diff --git a/.gitignore b/.gitignore index 6d098c3..6aabcf1 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,8 @@ dist/ *.egg-info/ *.egg *.whl +!src/wheels/ +!src/wheels/**/*.whl # IDE and Editor files .vscode/ @@ -77,4 +79,4 @@ marketing/*.psd *.temp *.bak *.swp -*~.nib \ No newline at end of file +*~.nib diff --git a/README.md b/README.md index 012b928..8fa61f5 100644 --- a/README.md +++ b/README.md @@ -225,13 +225,10 @@ The addon features intelligent font detection and validation: ## Dependencies -The addon automatically installs required dependencies: +The addon bundles and automatically installs its dependencies when needed: -- **Pillow** (>=10.0.0): For image generation and text rendering - -Optional dependency for vector overlays: - -- **CairoSVG** (>=2.7.0): Required to rasterize SVG overlays. Install it inside Blender's Python environment with `pip install cairosvg`. +- **Pillow** (>=10.0.0): Image generation and text rendering. +- **CairoSVG** (>=2.7.0): Rasterizes SVG overlays using the bundled wheel set for macOS and Linux (installs on first SVG use). ## Troubleshooting diff --git a/USER_GUIDE.md b/USER_GUIDE.md index c7d6ba7..bfa802d 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -15,7 +15,7 @@ This guide keeps things short so you can start creating textures right away. ## Requirements - Blender 4.0 or newer (Windows, macOS, Linux). -- Pillow installs automatically with the addon. _(SVG overlays need CairoSVG – only install if you plan to use SVGs.)_ +- Pillow and CairoSVG install automatically with the addon _(SVG overlays work out of the box)._ --- @@ -66,5 +66,5 @@ This guide keeps things short so you can start creating textures right away. - Need multiple styles fast? Duplicate the blend file or save presets before you start experimenting. - Keep the preview size smaller while fine-tuning; switch to full resolution for final renders. -- SVG logos? Add them as overlay components—the addon will rasterize them when CairoSVG is installed. +- SVG logos? Add them as overlay components—the addon bundles CairoSVG and rasterizes them automatically. - For team projects, export presets (`Add-on Panel > Presets > Export`) so everyone can share the same look. diff --git a/build/__pycache__/sync_version.cpython-311.pyc b/build/__pycache__/sync_version.cpython-311.pyc index 7bea139..df352e2 100644 Binary files a/build/__pycache__/sync_version.cpython-311.pyc and b/build/__pycache__/sync_version.cpython-311.pyc differ diff --git a/dist/text_texture_generator_v1.0.0.zip b/dist/text_texture_generator_v1.0.0.zip index d15fc49..cce051e 100644 Binary files a/dist/text_texture_generator_v1.0.0.zip and b/dist/text_texture_generator_v1.0.0.zip differ diff --git a/dist/text_texture_generator_v1.0.0_free.zip b/dist/text_texture_generator_v1.0.0_free.zip index 5c894ef..9bfbe3b 100644 Binary files a/dist/text_texture_generator_v1.0.0_free.zip and b/dist/text_texture_generator_v1.0.0_free.zip differ diff --git a/marketing/GUMROAD_LISTING.md b/marketing/GUMROAD_LISTING.md index d7e9a05..07c55c8 100644 --- a/marketing/GUMROAD_LISTING.md +++ b/marketing/GUMROAD_LISTING.md @@ -28,6 +28,6 @@ Create polished text textures without leaving Blender. This addon drops a dedica ## Requirements - Blender 4.0 or newer (Windows, macOS, or Linux). -- Pillow installs automatically; CairoSVG is only needed for SVG overlays. +- Pillow and CairoSVG install automatically—SVG overlays are ready out of the box. Questions or feature requests? Message us on Gumroad or email `marc@mintel.me`—we’re happy to help. diff --git a/marketing/SUPERHIVE_LISTING.md b/marketing/SUPERHIVE_LISTING.md index fd2b5c6..0a06c02 100644 --- a/marketing/SUPERHIVE_LISTING.md +++ b/marketing/SUPERHIVE_LISTING.md @@ -29,7 +29,7 @@ Bring typography directly into your Blender workflow. The Text Texture Generator ## Requirements & Setup - Blender 4.0 or newer on Windows, macOS, or Linux. -- Pillow installs automatically; install CairoSVG only if you plan to use SVG overlays. +- Pillow and CairoSVG install automatically, so SVG overlays work immediately. - Installation follows the standard “Install Add-on from File…” flow and includes demo `.blend` scenes to explore the toolset immediately. Need a production license, classroom seats, or have a technical question? Send a DM on Superhive or drop an email to `marc@mintel.me`—we usually reply within one business day. diff --git a/scripts/build_addon.py b/scripts/build_addon.py index 2392943..723a6c9 100755 --- a/scripts/build_addon.py +++ b/scripts/build_addon.py @@ -201,7 +201,48 @@ def should_exclude_file(file_path: Path, source_dir: Path, exclude_patterns: Lis return False -def copy_source_files(source_dir: Path, dest_dir: Path, exclude_patterns: List[str], exclude_files: List[str] = None, minify: bool = True): +def _format_version_tuple(version_tuple: tuple) -> str: + """Format version tuple for insertion into bl_info.""" + return "(" + ", ".join(str(part) for part in version_tuple) + ")" + + +def _edition_version_tuple(version: str, version_type: str) -> tuple: + """Return edition-specific version tuple.""" + try: + major_str, minor_str, patch_str = version.split(".", 2) + major, minor, patch = int(major_str), int(minor_str), int(patch_str) + except ValueError: + # Fallback if version string unexpected + return (1, 0, 0) if version_type == "free" else (1, 0, 1) + + if version_type == "full": + return (major, minor, patch + 1) + return (major, minor, patch) + + +def _apply_edition_overrides(rel_path: Path, source_code: str, version_type: str, version: str) -> str: + """Inject edition-specific metadata into copied source files.""" + if rel_path.as_posix() == "__init__.py": + edition_name = "Text Texture Generator (Pro)" if version_type == "full" else "Text Texture Generator (Free)" + target_version_tuple = _edition_version_tuple(version, version_type) + + source_code = re.sub( + r'"name":\s*"Text Texture Generator\s*\([^"]*\)"', + f'"name": "{edition_name}"', + source_code, + count=1 + ) + + source_code = re.sub( + r'"version":\s*\([^\)]+\)', + f'"version": {_format_version_tuple(target_version_tuple)}', + source_code, + count=1 + ) + return source_code + + +def copy_source_files(source_dir: Path, dest_dir: Path, exclude_patterns: List[str], exclude_files: List[str] = None, minify: bool = True, version_type: str = "free", version: str = "1.0.0"): """Copy source files to destination, excluding specified patterns and files.""" if exclude_files is None: exclude_files = [] @@ -232,17 +273,25 @@ def copy_source_files(source_dir: Path, dest_dir: Path, exclude_patterns: List[s # Read, minify, and write Python files try: source_code = item.read_text(encoding='utf-8') + source_code = _apply_edition_overrides(rel_path, source_code, version_type, version) minified_code = minify_python_code(source_code) dest_file.write_text(minified_code, encoding='utf-8') print(f" Copied (minified): {rel_path}") except Exception as e: # If minification fails, fall back to regular copy print(f" Warning: Could not minify {rel_path}, copying as-is: {e}") - shutil.copy2(item, dest_file) + source_code = item.read_text(encoding='utf-8') + source_code = _apply_edition_overrides(rel_path, source_code, version_type, version) + dest_file.write_text(source_code, encoding='utf-8') print(f" Copied: {rel_path}") else: # Copy non-Python files or when minification is disabled - shutil.copy2(item, dest_file) + if item.suffix == '.py': + source_code = item.read_text(encoding='utf-8') + source_code = _apply_edition_overrides(rel_path, source_code, version_type, version) + dest_file.write_text(source_code, encoding='utf-8') + else: + shutil.copy2(item, dest_file) print(f" Copied: {rel_path}") copied_count += 1 @@ -360,7 +409,7 @@ def build_addon(version_type: str, version: Optional[str] = None, output_dir: Op # Copy source files to temp directory with version-specific exclusions build_temp_dir = temp_dir / f"{config['project']['id']}_{version_type}" - copy_source_files(source_dir, build_temp_dir, exclude_patterns, exclude_files, minify) + copy_source_files(source_dir, build_temp_dir, exclude_patterns, exclude_files, minify, version_type=version_type, version=version) # Create output filename version_suffix = f"_{version_type}" if version_type == "free" else "" diff --git a/src/__pycache__/__init__.cpython-311.pyc b/src/__pycache__/__init__.cpython-311.pyc index 8a42469..85cd663 100644 Binary files a/src/__pycache__/__init__.cpython-311.pyc and b/src/__pycache__/__init__.cpython-311.pyc differ diff --git a/src/core/__pycache__/generation_engine.cpython-311.pyc b/src/core/__pycache__/generation_engine.cpython-311.pyc index b3baecc..5fe96b0 100644 Binary files a/src/core/__pycache__/generation_engine.cpython-311.pyc and b/src/core/__pycache__/generation_engine.cpython-311.pyc differ diff --git a/src/core/generation_engine.py b/src/core/generation_engine.py index c728a5d..8229f4a 100644 --- a/src/core/generation_engine.py +++ b/src/core/generation_engine.py @@ -6,6 +6,8 @@ Core functionality for generating texture images with text overlays. import math import bpy +from array import array + from ..utils.constants import has_text_fitting from ..utils.overlay_assets import ( SVGConversionError, @@ -662,13 +664,13 @@ def generate_texture_image(props, width, height): # Convert PIL image to Blender format (flip vertically to fix mirroring) pil_img = pil_img.transpose(Image.FLIP_TOP_BOTTOM) # Fix mirroring issue - pil_pixels = list(pil_img.getdata()) - blender_pixels = [] - for r, g, b, a in pil_pixels: - pass - blender_pixels.extend([r/255.0, g/255.0, b/255.0, a/255.0]) - - blender_img.pixels[:] = blender_pixels + raw_bytes = pil_img.tobytes() + normalized = array('f', (channel / 255.0 for channel in raw_bytes)) + pixels_attr = getattr(blender_img, "pixels", None) + if hasattr(pixels_attr, "foreach_set"): + pixels_attr.foreach_set(normalized) + else: + blender_img.pixels[:] = normalized.tolist() return blender_img, None except ImportError as e: pass diff --git a/src/operators/__init__.py b/src/operators/__init__.py index 5844c26..592ea90 100644 --- a/src/operators/__init__.py +++ b/src/operators/__init__.py @@ -46,22 +46,34 @@ except ImportError: # preset_ops module not available (free version) PRESET_OPERATORS = [] -if is_full_version(): - try: - pass - from .text_editor_ops import * - from .text_editor_ops import ( - TEXT_TEXTURE_OT_edit_text, - ) - TEXT_EDITOR_OPERATORS = [ - 'TEXT_TEXTURE_OT_edit_text', - ] - except ImportError as e: - import sys - print(f"WARNING: text_editor_ops import failed in operators/__init__.py: {e}", file=sys.stderr) - TEXT_EDITOR_OPERATORS = [] -else: - TEXT_EDITOR_OPERATORS = [] +try: + pass + from .text_editor_ops import * + from .text_editor_ops import ( + TEXT_TEXTURE_OT_edit_text, + ) + TEXT_EDITOR_OPERATORS = [ + 'TEXT_TEXTURE_OT_edit_text', + ] +except ImportError as e: + import sys + print(f"WARNING: text_editor_ops import failed in operators/__init__.py: {e}", file=sys.stderr) + + class TEXT_TEXTURE_OT_edit_text: + """Fallback stub when text editor operator is unavailable.""" + bl_idname = "text_texture.edit_text" + bl_label = "Edit Text (Unavailable)" + bl_description = "Text editor feature unavailable in this build" + bl_options = {'REGISTER'} + + @classmethod + def poll(cls, context): + return False + + def execute(self, context): + raise RuntimeError("Text editor feature is unavailable in this build.") + + TEXT_EDITOR_OPERATORS = ['TEXT_TEXTURE_OT_edit_text'] try: pass diff --git a/src/operators/__pycache__/__init__.cpython-311.pyc b/src/operators/__pycache__/__init__.cpython-311.pyc index 2120dd6..b97a959 100644 Binary files a/src/operators/__pycache__/__init__.cpython-311.pyc and b/src/operators/__pycache__/__init__.cpython-311.pyc differ diff --git a/src/operators/__pycache__/generation_ops.cpython-311.pyc b/src/operators/__pycache__/generation_ops.cpython-311.pyc index f6c56d5..34889b6 100644 Binary files a/src/operators/__pycache__/generation_ops.cpython-311.pyc and b/src/operators/__pycache__/generation_ops.cpython-311.pyc differ diff --git a/src/operators/generation_ops.py b/src/operators/generation_ops.py index 65fd5ee..81173da 100644 --- a/src/operators/generation_ops.py +++ b/src/operators/generation_ops.py @@ -162,8 +162,8 @@ class TEXT_TEXTURE_OT_preview(Operator): # Get properties and generate preview with correct parameters props = context.scene.text_texture_props preview_size = props.preview_size if hasattr(props, 'preview_size') else 512 - preview_width = getattr(props, 'texture_width', preview_size) or preview_size - preview_height = getattr(props, 'texture_height', preview_size) or preview_size + preview_width = preview_size + preview_height = preview_size result = generate_preview(props, preview_width, preview_height) if result: diff --git a/src/properties/__pycache__/property_groups.cpython-311.pyc b/src/properties/__pycache__/property_groups.cpython-311.pyc index 3c09a2b..e0f7ddc 100644 Binary files a/src/properties/__pycache__/property_groups.cpython-311.pyc and b/src/properties/__pycache__/property_groups.cpython-311.pyc differ diff --git a/src/ui/__pycache__/panels.cpython-311.pyc b/src/ui/__pycache__/panels.cpython-311.pyc index 5a30685..8670c85 100644 Binary files a/src/ui/__pycache__/panels.cpython-311.pyc and b/src/ui/__pycache__/panels.cpython-311.pyc differ diff --git a/src/utils/__init__.py b/src/utils/__init__.py index 4967617..8518c48 100644 --- a/src/utils/__init__.py +++ b/src/utils/__init__.py @@ -18,11 +18,18 @@ from .constants import ( is_free_version, is_full_version ) -from .system import install_pillow, get_system_fonts, get_font_enum_items, find_default_truetype_font +from .system import ( + install_pillow, + install_cairosvg_from_bundle, + get_system_fonts, + get_font_enum_items, + find_default_truetype_font +) __all__ = [ 'bl_info', 'install_pillow', + 'install_cairosvg_from_bundle', 'get_system_fonts', 'get_font_enum_items', 'find_default_truetype_font', diff --git a/src/utils/__pycache__/__init__.cpython-311.pyc b/src/utils/__pycache__/__init__.cpython-311.pyc index b567240..af4d213 100644 Binary files a/src/utils/__pycache__/__init__.cpython-311.pyc and b/src/utils/__pycache__/__init__.cpython-311.pyc differ diff --git a/src/utils/__pycache__/constants.cpython-311.pyc b/src/utils/__pycache__/constants.cpython-311.pyc index b095e97..4ce1361 100644 Binary files a/src/utils/__pycache__/constants.cpython-311.pyc and b/src/utils/__pycache__/constants.cpython-311.pyc differ diff --git a/src/utils/__pycache__/system.cpython-311.pyc b/src/utils/__pycache__/system.cpython-311.pyc index b4a9e7d..2941032 100644 Binary files a/src/utils/__pycache__/system.cpython-311.pyc and b/src/utils/__pycache__/system.cpython-311.pyc differ diff --git a/src/utils/overlay_assets.py b/src/utils/overlay_assets.py index e5c4692..2b4b394 100644 --- a/src/utils/overlay_assets.py +++ b/src/utils/overlay_assets.py @@ -87,11 +87,16 @@ def ensure_svg_raster(image_path: str, scale: float) -> RasterizationResult: try: import cairosvg # type: ignore - except ImportError as import_error: - raise SVGConversionError( - "SVG overlay support requires the 'cairosvg' package. " - "Install it via pip (pip install cairosvg) inside Blender's Python environment." - ) from import_error + except ImportError: + try: + from .system import install_cairosvg_from_bundle + install_cairosvg_from_bundle() + import cairosvg # type: ignore # noqa: F401 + except Exception as install_error: + raise SVGConversionError( + "SVG overlay support requires CairoSVG, but the bundled installation failed. " + "Please reinstall the addon or install CairoSVG manually inside Blender's Python environment." + ) from install_error # Guard against invalid scales (NaN, infinity, zero, negative) if not isinstance(scale, (int, float)) or not math.isfinite(scale): diff --git a/src/utils/system.py b/src/utils/system.py index 6d981d5..301ffbd 100644 --- a/src/utils/system.py +++ b/src/utils/system.py @@ -6,9 +6,76 @@ import subprocess import sys import platform import os +from pathlib import Path +from typing import Iterable + +_SUPPORTED_PYTHON_TAG = "cp311" +_BUNDLED_WHEEL_DIRS = { + "darwin": "cp311-macosx_10_9_universal2", + "linux": "cp311-manylinux_2_28_x86_64", +} +_BUNDLED_CAIROSVG_PACKAGES = ( + "cairosvg==2.7.1", + "cairocffi==1.7.1", + "cssselect2==0.7.0", + "tinycss2==1.2.1", + "defusedxml==0.7.1", + "cffi==1.17.1", + "pycparser==2.21", +) _DEFAULT_FONT_CACHE = None + +def _pip_install_from_bundle(packages: Iterable[str], bundle_dir: Path) -> None: + """Install packages from a bundled wheel directory using pip.""" + pass + command = [ + sys.executable, + "-m", + "pip", + "install", + "--no-index", + "--no-cache-dir", + "--find-links", + str(bundle_dir), + *packages, + ] + subprocess.check_call(command) + + +def _get_wheel_bundle_dir() -> Path: + """Return the platform-specific wheel bundle directory for the current environment.""" + pass + python_tag = f"cp{sys.version_info.major}{sys.version_info.minor}" + if python_tag != _SUPPORTED_PYTHON_TAG: + pass + raise RuntimeError( + f"Bundled dependencies target Python {_SUPPORTED_PYTHON_TAG}, " + f"but current interpreter reports {python_tag}." + ) + + platform_key = platform.system().lower() + bundle_name = _BUNDLED_WHEEL_DIRS.get(platform_key) + if not bundle_name: + pass + raise RuntimeError(f"No bundled wheel directory configured for platform '{platform_key}'.") + + wheels_root = Path(__file__).resolve().parent.parent / "wheels" + bundle_dir = wheels_root / bundle_name + if not bundle_dir.exists(): + pass + raise FileNotFoundError(f"Bundled wheel directory not found: {bundle_dir}") + + return bundle_dir + + +def install_cairosvg_from_bundle() -> None: + """Install CairoSVG and its dependencies using the bundled wheels.""" + pass + bundle_dir = _get_wheel_bundle_dir() + _pip_install_from_bundle(_BUNDLED_CAIROSVG_PACKAGES, bundle_dir) + def install_pillow(): pass """Install Pillow if not available""" diff --git a/src/wheels/cp311-macosx_10_9_universal2/CairoSVG-2.7.1-py3-none-any.whl b/src/wheels/cp311-macosx_10_9_universal2/CairoSVG-2.7.1-py3-none-any.whl new file mode 100644 index 0000000..cf43f34 Binary files /dev/null and b/src/wheels/cp311-macosx_10_9_universal2/CairoSVG-2.7.1-py3-none-any.whl differ diff --git a/src/wheels/cp311-macosx_10_9_universal2/cairocffi-1.7.1-py3-none-any.whl b/src/wheels/cp311-macosx_10_9_universal2/cairocffi-1.7.1-py3-none-any.whl new file mode 100644 index 0000000..418ab7e Binary files /dev/null and b/src/wheels/cp311-macosx_10_9_universal2/cairocffi-1.7.1-py3-none-any.whl differ diff --git a/src/wheels/cp311-macosx_10_9_universal2/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl b/src/wheels/cp311-macosx_10_9_universal2/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl new file mode 100644 index 0000000..9833e64 Binary files /dev/null and b/src/wheels/cp311-macosx_10_9_universal2/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl differ diff --git a/src/wheels/cp311-macosx_10_9_universal2/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl b/src/wheels/cp311-macosx_10_9_universal2/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl new file mode 100644 index 0000000..f5632d4 Binary files /dev/null and b/src/wheels/cp311-macosx_10_9_universal2/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl differ diff --git a/src/wheels/cp311-macosx_10_9_universal2/cssselect2-0.7.0-py3-none-any.whl b/src/wheels/cp311-macosx_10_9_universal2/cssselect2-0.7.0-py3-none-any.whl new file mode 100644 index 0000000..b2cd8ba Binary files /dev/null and b/src/wheels/cp311-macosx_10_9_universal2/cssselect2-0.7.0-py3-none-any.whl differ diff --git a/src/wheels/cp311-macosx_10_9_universal2/defusedxml-0.7.1-py2.py3-none-any.whl b/src/wheels/cp311-macosx_10_9_universal2/defusedxml-0.7.1-py2.py3-none-any.whl new file mode 100644 index 0000000..8e678bf Binary files /dev/null and b/src/wheels/cp311-macosx_10_9_universal2/defusedxml-0.7.1-py2.py3-none-any.whl differ diff --git a/src/wheels/cp311-macosx_10_9_universal2/pycparser-2.21-py2.py3-none-any.whl b/src/wheels/cp311-macosx_10_9_universal2/pycparser-2.21-py2.py3-none-any.whl new file mode 100644 index 0000000..fef6735 Binary files /dev/null and b/src/wheels/cp311-macosx_10_9_universal2/pycparser-2.21-py2.py3-none-any.whl differ diff --git a/src/wheels/cp311-macosx_10_9_universal2/tinycss2-1.2.1-py3-none-any.whl b/src/wheels/cp311-macosx_10_9_universal2/tinycss2-1.2.1-py3-none-any.whl new file mode 100644 index 0000000..3e41dd4 Binary files /dev/null and b/src/wheels/cp311-macosx_10_9_universal2/tinycss2-1.2.1-py3-none-any.whl differ diff --git a/src/wheels/cp311-manylinux_2_28_x86_64/CairoSVG-2.7.1-py3-none-any.whl b/src/wheels/cp311-manylinux_2_28_x86_64/CairoSVG-2.7.1-py3-none-any.whl new file mode 100644 index 0000000..cf43f34 Binary files /dev/null and b/src/wheels/cp311-manylinux_2_28_x86_64/CairoSVG-2.7.1-py3-none-any.whl differ diff --git a/src/wheels/cp311-manylinux_2_28_x86_64/cairocffi-1.7.1-py3-none-any.whl b/src/wheels/cp311-manylinux_2_28_x86_64/cairocffi-1.7.1-py3-none-any.whl new file mode 100644 index 0000000..418ab7e Binary files /dev/null and b/src/wheels/cp311-manylinux_2_28_x86_64/cairocffi-1.7.1-py3-none-any.whl differ diff --git a/src/wheels/cp311-manylinux_2_28_x86_64/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl b/src/wheels/cp311-manylinux_2_28_x86_64/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl new file mode 100644 index 0000000..de6ffd6 Binary files /dev/null and b/src/wheels/cp311-manylinux_2_28_x86_64/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl differ diff --git a/src/wheels/cp311-manylinux_2_28_x86_64/cssselect2-0.7.0-py3-none-any.whl b/src/wheels/cp311-manylinux_2_28_x86_64/cssselect2-0.7.0-py3-none-any.whl new file mode 100644 index 0000000..b2cd8ba Binary files /dev/null and b/src/wheels/cp311-manylinux_2_28_x86_64/cssselect2-0.7.0-py3-none-any.whl differ diff --git a/src/wheels/cp311-manylinux_2_28_x86_64/defusedxml-0.7.1-py2.py3-none-any.whl b/src/wheels/cp311-manylinux_2_28_x86_64/defusedxml-0.7.1-py2.py3-none-any.whl new file mode 100644 index 0000000..8e678bf Binary files /dev/null and b/src/wheels/cp311-manylinux_2_28_x86_64/defusedxml-0.7.1-py2.py3-none-any.whl differ diff --git a/src/wheels/cp311-manylinux_2_28_x86_64/pycparser-2.21-py2.py3-none-any.whl b/src/wheels/cp311-manylinux_2_28_x86_64/pycparser-2.21-py2.py3-none-any.whl new file mode 100644 index 0000000..fef6735 Binary files /dev/null and b/src/wheels/cp311-manylinux_2_28_x86_64/pycparser-2.21-py2.py3-none-any.whl differ diff --git a/src/wheels/cp311-manylinux_2_28_x86_64/tinycss2-1.2.1-py3-none-any.whl b/src/wheels/cp311-manylinux_2_28_x86_64/tinycss2-1.2.1-py3-none-any.whl new file mode 100644 index 0000000..3e41dd4 Binary files /dev/null and b/src/wheels/cp311-manylinux_2_28_x86_64/tinycss2-1.2.1-py3-none-any.whl differ diff --git a/tests/e2e/__pycache__/conftest.cpython-311-pytest-8.3.5.pyc b/tests/e2e/__pycache__/conftest.cpython-311-pytest-8.3.5.pyc index b85084b..feb2a2f 100644 Binary files a/tests/e2e/__pycache__/conftest.cpython-311-pytest-8.3.5.pyc and b/tests/e2e/__pycache__/conftest.cpython-311-pytest-8.3.5.pyc differ diff --git a/tests/integration/__pycache__/test_text_generation_pipeline.cpython-311-pytest-8.3.5.pyc b/tests/integration/__pycache__/test_text_generation_pipeline.cpython-311-pytest-8.3.5.pyc index 94c91df..31cbe6b 100644 Binary files a/tests/integration/__pycache__/test_text_generation_pipeline.cpython-311-pytest-8.3.5.pyc and b/tests/integration/__pycache__/test_text_generation_pipeline.cpython-311-pytest-8.3.5.pyc differ diff --git a/tests/unit/__pycache__/test_version_differentiation.cpython-311-pytest-8.3.5.pyc b/tests/unit/__pycache__/test_version_differentiation.cpython-311-pytest-8.3.5.pyc index 8c12a76..ac8ac7f 100644 Binary files a/tests/unit/__pycache__/test_version_differentiation.cpython-311-pytest-8.3.5.pyc and b/tests/unit/__pycache__/test_version_differentiation.cpython-311-pytest-8.3.5.pyc differ diff --git a/tests/unit/core/__pycache__/test_generation_engine.cpython-311-pytest-8.3.5.pyc b/tests/unit/core/__pycache__/test_generation_engine.cpython-311-pytest-8.3.5.pyc index ecd294a..98d8f9e 100644 Binary files a/tests/unit/core/__pycache__/test_generation_engine.cpython-311-pytest-8.3.5.pyc and b/tests/unit/core/__pycache__/test_generation_engine.cpython-311-pytest-8.3.5.pyc differ