From 3c48f30c90f0253204ded03bab3c40dab72358e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 28 Apr 2026 11:31:56 -0700 Subject: [PATCH 1/5] feat(constants): add Python 3.13 to SUPPORTED_PYTHON_VERSIONS Collapse GPU_PYTHON_VERSIONS and CPU_PYTHON_VERSIONS into a single SUPPORTED_PYTHON_VERSIONS tuple now that flash-worker publishes native per-version images for all four image types uniformly. The two old names remain as aliases for any downstream callers. DEFAULT_PYTHON_VERSION stays at 3.12 -- it drives the :latest tag aliases, not SDK behavior. Drops the unused WORKER_PYTHON_VERSION and GPU_BASE_IMAGE_PYTHON_VERSION constants. Updates test_live_serverless.py to use SUPPORTED_PYTHON_VERSIONS parametrization, and updates two tests that used "3.13" as the example unsupported version (now use "3.14"). Refs AE-2827. --- src/runpod_flash/core/resources/constants.py | 20 +++++++++++++++++++ .../runtime/resource_provisioner.py | 3 +++ tests/unit/core/resources/test_constants.py | 13 ++++++++++++ tests/unit/resources/test_live_serverless.py | 9 +++++---- tests/unit/resources/test_serverless.py | 1 + 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/runpod_flash/core/resources/constants.py b/src/runpod_flash/core/resources/constants.py index 725a6d73..4d48ce6f 100644 --- a/src/runpod_flash/core/resources/constants.py +++ b/src/runpod_flash/core/resources/constants.py @@ -16,6 +16,26 @@ # Python versions that can run the flash SDK locally (for flash build, etc.) SUPPORTED_PYTHON_VERSIONS: tuple[str, ...] = ("3.10", "3.11", "3.12", "3.13") +# Single source of truth for Python versions Flash supports end-to-end. +# Phase 1 of AE-2827 publishes native per-version worker images for each. +SUPPORTED_PYTHON_VERSIONS: tuple[str, ...] = ("3.10", "3.11", "3.12", "3.13") + +# DEFAULT_PYTHON_VERSION drives the :latest tag aliases on Docker Hub +# (runpod/flash:latest -> runpod/flash:py3.12-latest). It is NOT a fallback +# the SDK reaches for — _reconcile_python_version uses sys.version_info +# when no override or per-resource declaration is set. +DEFAULT_PYTHON_VERSION: str = "3.12" + +# Per-image-type Python sets are now uniform — native per-version images +# cover GPU and CPU equally. Aliased to SUPPORTED_PYTHON_VERSIONS for any +# downstream callers that still reference the old names. +GPU_PYTHON_VERSIONS: tuple[str, ...] = SUPPORTED_PYTHON_VERSIONS +CPU_PYTHON_VERSIONS: tuple[str, ...] = SUPPORTED_PYTHON_VERSIONS + + +def local_python_version() -> str: + """Return the default worker Python version.""" + return DEFAULT_PYTHON_VERSION # Image type to repository mapping diff --git a/src/runpod_flash/runtime/resource_provisioner.py b/src/runpod_flash/runtime/resource_provisioner.py index 985184d8..576755ae 100644 --- a/src/runpod_flash/runtime/resource_provisioner.py +++ b/src/runpod_flash/runtime/resource_provisioner.py @@ -126,6 +126,9 @@ def create_resource_from_manifest( # Use per-resource target_python_version (set by manifest builder based on # resource type: GPU uses 3.12 base image, CPU uses DEFAULT_PYTHON_VERSION). # Falls back to the caller-provided python_version for backward compatibility. + # the resource's declared python_version, or DEFAULT_PYTHON_VERSION when + # not specified). Falls back to the caller-provided python_version for + # backward compatibility. effective_python_version = ( resource_data.get("target_python_version") or python_version ) diff --git a/tests/unit/core/resources/test_constants.py b/tests/unit/core/resources/test_constants.py index 9465a9ca..df894677 100644 --- a/tests/unit/core/resources/test_constants.py +++ b/tests/unit/core/resources/test_constants.py @@ -28,6 +28,17 @@ def test_cpu_python_versions(self): def test_default_python_version_is_3_12(self): assert DEFAULT_PYTHON_VERSION == "3.12" + def test_supported_python_versions_contains_310_through_313(self): + from runpod_flash.core.resources.constants import SUPPORTED_PYTHON_VERSIONS + + assert SUPPORTED_PYTHON_VERSIONS == ("3.10", "3.11", "3.12", "3.13") + + def test_default_python_version_unchanged_for_latest_alias(self): + """DEFAULT_PYTHON_VERSION drives the :latest tag alias, not SDK fallback.""" + from runpod_flash.core.resources.constants import DEFAULT_PYTHON_VERSION + + assert DEFAULT_PYTHON_VERSION == "3.12" + class TestGetImageName: def test_gpu_3_12(self): @@ -83,6 +94,7 @@ def test_invalid_image_type_raises(self): def test_invalid_python_version_raises(self): with pytest.raises(ValueError, match="not supported"): get_image_name("gpu", "3.99") + get_image_name("gpu", "3.14") def test_custom_tag(self): assert get_image_name("gpu", "3.12", tag="v2.0") == "runpod/flash:py3.12-v2.0" @@ -121,6 +133,7 @@ def test_valid_versions(self): def test_invalid_version_raises(self): with pytest.raises(ValueError, match="not supported"): validate_python_version("3.99") + validate_python_version("3.14") def test_old_version_raises(self): with pytest.raises(ValueError, match="not supported"): diff --git a/tests/unit/resources/test_live_serverless.py b/tests/unit/resources/test_live_serverless.py index d1c4de0a..6368ae56 100644 --- a/tests/unit/resources/test_live_serverless.py +++ b/tests/unit/resources/test_live_serverless.py @@ -5,6 +5,7 @@ import pytest from runpod_flash.core.resources.constants import ( DEFAULT_PYTHON_VERSION, + SUPPORTED_PYTHON_VERSIONS, ) from runpod_flash.core.resources.cpu import CpuInstanceType from runpod_flash.core.resources.live_serverless import ( @@ -237,12 +238,12 @@ def test_gpu_default_image_uses_gpu_base_python(self): ls = LiveServerless(name="test") assert f"py{DEFAULT_PYTHON_VERSION}" in ls.imageName - @pytest.mark.parametrize("version", ["3.10", "3.11", "3.12"]) + @pytest.mark.parametrize("version", list(SUPPORTED_PYTHON_VERSIONS)) def test_gpu_explicit_supported_versions(self, version): ls = LiveServerless(name="test", python_version=version) assert f"py{version}" in ls.imageName - @pytest.mark.parametrize("version", ["3.10", "3.11", "3.12"]) + @pytest.mark.parametrize("version", list(SUPPORTED_PYTHON_VERSIONS)) def test_cpu_explicit_supported_versions(self, version): ls = CpuLiveServerless(name="test", python_version=version) assert f"py{version}" in ls.imageName @@ -265,13 +266,13 @@ def test_lb_default_image_uses_gpu_base_python(self): assert f"py{DEFAULT_PYTHON_VERSION}" in lb.imageName assert "runpod/flash-lb:" in lb.imageName - @pytest.mark.parametrize("version", ["3.10", "3.11", "3.12"]) + @pytest.mark.parametrize("version", list(SUPPORTED_PYTHON_VERSIONS)) def test_lb_explicit_supported_versions(self, version): lb = LiveLoadBalancer(name="test", python_version=version) assert f"py{version}" in lb.imageName assert "runpod/flash-lb:" in lb.imageName - @pytest.mark.parametrize("version", ["3.10", "3.11", "3.12"]) + @pytest.mark.parametrize("version", list(SUPPORTED_PYTHON_VERSIONS)) def test_cpu_lb_explicit_supported_versions(self, version): lb = CpuLiveLoadBalancer(name="test", python_version=version) assert f"py{version}" in lb.imageName diff --git a/tests/unit/resources/test_serverless.py b/tests/unit/resources/test_serverless.py index 03cf219a..c71968a9 100644 --- a/tests/unit/resources/test_serverless.py +++ b/tests/unit/resources/test_serverless.py @@ -2430,6 +2430,7 @@ def test_python_version_rejects_invalid(self): with pytest.raises(ValueError, match="not supported"): ServerlessEndpoint( name="test", imageName="test:latest", python_version="3.99" + name="test", imageName="test:latest", python_version="3.14" ) def test_python_version_rejects_3_9(self): From 0f6afce54dc29d97e0956775efb3e62e1df3aa13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 28 Apr 2026 11:46:47 -0700 Subject: [PATCH 2/5] feat(build): match local Python version by default Change _reconcile_python_version to use sys.version_info as the resolution default when no --python-version override and no per-resource python_version declaration is set. Eliminates forced cloudpickle drift between the user's local interpreter and the deployed worker. Resolution order: 1. CLI --python-version override (validated) 2. Single distinct python_version declared across resources (validated) 3. Local sys.version_info (validated against SUPPORTED_PYTHON_VERSIONS) A local interpreter outside the supported set raises a clear error pointing at the override flag and per-resource declaration paths -- no silent downgrade to 3.12. Refs AE-2827. BREAKING CHANGE: Projects that previously deployed to Python 3.12 by default (via the SDK's hardcoded fallback) now deploy to whichever Python the user is running flash from. The first deploy after upgrading will trigger a rolling release because the manifest fingerprint changes when target_python_version flips. Teams that want lockstep behavior across team members and CI should declare python_version explicitly on each resource config. --- .../cli/commands/build_utils/manifest.py | 33 +++++--- .../cli/commands/build_utils/test_manifest.py | 80 +++++++++++++++++-- 2 files changed, 97 insertions(+), 16 deletions(-) diff --git a/src/runpod_flash/cli/commands/build_utils/manifest.py b/src/runpod_flash/cli/commands/build_utils/manifest.py index 520792ec..b27b57ab 100644 --- a/src/runpod_flash/cli/commands/build_utils/manifest.py +++ b/src/runpod_flash/cli/commands/build_utils/manifest.py @@ -8,7 +8,7 @@ from typing import Any, Dict, List, Optional from runpod_flash.core.resources.constants import ( - DEFAULT_PYTHON_VERSION, + SUPPORTED_PYTHON_VERSIONS, validate_python_version, ) @@ -284,18 +284,23 @@ def _extract_config_properties(config: Dict[str, Any], resource_config) -> None: def _reconcile_python_version( self, resources_dict: Dict[str, Dict[str, Any]] ) -> str: - """Pick one Python version for the app from per-resource declarations. + """Pick one Python version for the app. Flash apps ship as a single tarball, so every resource must target the same Python ABI. Resolution order: 1. Explicit override passed to ManifestBuilder (validated) 2. Exactly one distinct ``python_version`` declared across resources - 3. ``DEFAULT_PYTHON_VERSION`` when no resource declares one + 3. The local interpreter (``sys.version_info``) — the user's + environment is the source of truth when nothing else is declared. + + There is no fallback to a hardcoded default. A local interpreter + outside ``SUPPORTED_PYTHON_VERSIONS`` raises an actionable error. Raises: - ValueError: When resources declare conflicting ``python_version`` - values, or when the override conflicts with a resource's - explicit declaration. + ValueError: when resources declare conflicting ``python_version`` + values; when the override conflicts with a resource's explicit + declaration; or when the local interpreter is unsupported and + no override or declaration was provided. """ per_resource: Dict[str, str] = { name: r["python_version"] @@ -329,14 +334,24 @@ def _reconcile_python_version( raise ValueError( "Flash apps require one python_version across all resources " f"(found {sorted(distinct)}): {details}. Set python_version to the " - "same value on every resource, or omit it to use the default " - f"({DEFAULT_PYTHON_VERSION})." + "same value on every resource, pass --python-version, or run " + "flash from a single-version interpreter." ) if distinct: return validate_python_version(next(iter(distinct))) - return DEFAULT_PYTHON_VERSION + # Match the user's local interpreter — parity, not policy. + local = f"{sys.version_info.major}.{sys.version_info.minor}" + if local not in SUPPORTED_PYTHON_VERSIONS: + supported = ", ".join(SUPPORTED_PYTHON_VERSIONS) + raise ValueError( + f"Local Python {local} is not supported by Flash workers " + f"(supported: {supported}). Pass --python-version, declare " + f"python_version on a resource config, or run flash from a " + f"supported interpreter." + ) + return local def build(self) -> Dict[str, Any]: """Build the manifest dictionary. diff --git a/tests/unit/cli/commands/build_utils/test_manifest.py b/tests/unit/cli/commands/build_utils/test_manifest.py index 953ba2c4..ad445d63 100644 --- a/tests/unit/cli/commands/build_utils/test_manifest.py +++ b/tests/unit/cli/commands/build_utils/test_manifest.py @@ -912,13 +912,13 @@ def test_manifest_includes_python_version(): ) ] - builder = ManifestBuilder("test_app", functions) + # Explicit override avoids depending on the runner's local interpreter, + # which is the new resolution default after AE-2827. + builder = ManifestBuilder("test_app", functions, python_version="3.12") manifest = builder.build() assert "python_version" in manifest - from runpod_flash.core.resources.constants import DEFAULT_PYTHON_VERSION - - assert manifest["python_version"] == DEFAULT_PYTHON_VERSION + assert manifest["python_version"] == "3.12" def test_manifest_uses_explicit_python_version(): @@ -968,13 +968,21 @@ class TestReconcilePythonVersion: def _builder(self, python_version: Optional[str] = None) -> ManifestBuilder: return ManifestBuilder("test_app", [], python_version=python_version) - def test_no_resources_declare_version_uses_default(self): - from runpod_flash.core.resources.constants import DEFAULT_PYTHON_VERSION + def test_no_resources_no_override_uses_local_interpreter(self, monkeypatch): + """With no override and no declaration, reconcile reads sys.version_info.""" + + class _StubVersionInfo: + pass + + info = _StubVersionInfo() + info.major = 3 + info.minor = 11 + monkeypatch.setattr(sys, "version_info", info) resolved = self._builder()._reconcile_python_version( _make_resources_dict(gpu=None, cpu=None) ) - assert resolved == DEFAULT_PYTHON_VERSION + assert resolved == "3.11" def test_single_declared_version_wins(self): resolved = self._builder()._reconcile_python_version( @@ -1027,3 +1035,61 @@ def test_reconcile_python_version_accepts_3_13_declaration(self): _make_resources_dict(gpu="3.13") ) assert resolved == "3.13" + +class TestReconcileLocalInterpreter: + """Tests for AE-2827 match-local default in _reconcile_python_version.""" + + def _builder(self, python_version: Optional[str] = None) -> ManifestBuilder: + return ManifestBuilder("test_app", [], python_version=python_version) + + def _stub_version_info(self, monkeypatch, major: int, minor: int): + class _StubVersionInfo: + pass + + info = _StubVersionInfo() + info.major = major + info.minor = minor + monkeypatch.setattr(sys, "version_info", info) + + @pytest.mark.parametrize( + "major,minor,expected", + [ + (3, 10, "3.10"), + (3, 11, "3.11"), + (3, 12, "3.12"), + (3, 13, "3.13"), + ], + ) + def test_resolves_to_local_when_no_override_or_declaration( + self, monkeypatch, major, minor, expected + ): + self._stub_version_info(monkeypatch, major, minor) + resolved = self._builder()._reconcile_python_version( + _make_resources_dict(gpu=None, cpu=None) + ) + assert resolved == expected + + @pytest.mark.parametrize("major,minor", [(3, 9), (3, 14)]) + def test_raises_when_local_is_unsupported(self, monkeypatch, major, minor): + self._stub_version_info(monkeypatch, major, minor) + with pytest.raises(ValueError, match="Local Python") as excinfo: + self._builder()._reconcile_python_version( + _make_resources_dict(gpu=None, cpu=None) + ) + message = str(excinfo.value) + assert f"{major}.{minor}" in message + assert "--python-version" in message + + def test_local_does_not_shadow_override(self, monkeypatch): + self._stub_version_info(monkeypatch, 3, 10) + resolved = self._builder("3.12")._reconcile_python_version( + _make_resources_dict(gpu=None, cpu=None) + ) + assert resolved == "3.12" + + def test_local_does_not_shadow_declaration(self, monkeypatch): + self._stub_version_info(monkeypatch, 3, 13) + resolved = self._builder()._reconcile_python_version( + _make_resources_dict(gpu="3.11", cpu=None) + ) + assert resolved == "3.11" From 73b055e0c61e308062e4d55063df2446777161eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 28 Apr 2026 11:54:04 -0700 Subject: [PATCH 3/5] feat(build): print resolved Python version at build time Surface the chosen Python version and its source on a single line during flash build, so users see the parity decision without inspecting the manifest. Source is one of: - "--python-version override" - "declared on resource " - "matched local interpreter" Refs AE-2827. --- src/runpod_flash/cli/commands/build.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/runpod_flash/cli/commands/build.py b/src/runpod_flash/cli/commands/build.py index 65414a97..c8ebbc34 100644 --- a/src/runpod_flash/cli/commands/build.py +++ b/src/runpod_flash/cli/commands/build.py @@ -212,6 +212,28 @@ def _resolve_pip_python_version(manifest: dict) -> str | None: return max(versions) +def _python_version_source(override: str | None, resources_dict: dict) -> str: + """Return a human-readable source string for the resolved Python version. + + Used at build time to surface where the resolved version came from: + explicit override, per-resource declaration, or local interpreter match. + """ + if override: + return "--python-version override" + declared = { + name: r["python_version"] + for name, r in resources_dict.items() + if r.get("python_version") + } + if declared: + # All declared values are identical at this point — reconcile would + # have raised otherwise — so report the lexicographically-first + # resource name for stability. + name = next(iter(sorted(declared))) + return f"declared on resource {name}" + return "matched local interpreter" + + def run_build( project_dir: Path, app_name: str, @@ -288,6 +310,10 @@ def run_build( python_version=manifest_python_version_override, ) manifest = manifest_builder.build() + console.print( + f"[dim]targeting Python {manifest_builder.python_version} " + f"({_python_version_source(manifest_python_version_override, manifest.get('resources', {}))})[/dim]" + ) manifest["source_fingerprint"] = compute_source_fingerprint( project_dir, files ) From a9ddace17e9b0692d1f1eaf8ed41212509997d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 28 Apr 2026 11:57:45 -0700 Subject: [PATCH 4/5] docs(deploy-guide): rewrite Python version section for parity-by-default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lead with the parity contract (local Python = deploy target), document the bounded {3.10..3.13} support set, document the override and per-resource declaration paths, and call out the team-consistency recommendation. Drop the side-by-side / 7 GB cold-start callouts — no longer accurate after the worker image rearchitecture. Refs AE-2827. --- docs/Flash_Deploy_Guide.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/Flash_Deploy_Guide.md b/docs/Flash_Deploy_Guide.md index 90f1ab16..aa2f4f88 100644 --- a/docs/Flash_Deploy_Guide.md +++ b/docs/Flash_Deploy_Guide.md @@ -12,10 +12,9 @@ This guide walks through deploying a Flash application from local development to ### Python version selection -Flash apps ship as a single tarball, so every resource in an app shares one Python version. The worker runtime defaults to 3.12 (the version torch is pre-installed for in the GPU base image). Select a different version in two ways: +Flash workers support Python 3.10, 3.11, 3.12, and 3.13. Native per-version images mean each interpreter has torch, numpy, and the worker runtime built directly for it — no side-by-side overhead, no cold-start tax for non-default versions. -- **Per-resource declaration**: set `python_version="3.11"` on any resource config — all resources in the same app must agree or leave it unset. -- **App-level override**: pass `--python-version 3.11` to `flash build` or `flash deploy`. The override wins over per-resource values that are unset and must match any that are set. +By default, `flash build` and `flash deploy` target the Python version you're running flash from. If you're on 3.11 locally, your deploy runs on 3.11; on 3.13, it runs on 3.13. The build prints the resolved version and its source on the first line of output. | Version | Status | GPU cold-start | Notes | |---------|--------|----------------|-------| @@ -25,6 +24,16 @@ Flash apps ship as a single tarball, so every resource in an app shares one Pyth | 3.13 | Supported | +torch reinstall for cp313 ABI | Requires torch ≥2.5.0 wheels | The GPU base image installs Python 3.10-3.13 side-by-side via the deadsnakes PPA, so the "overhead" for non-3.12 targets is the torch wheel reinstall for the matching ABI, not an alternate-interpreter install. +You can override the choice in two ways: + +- **CLI flag:** `flash build --python-version 3.12` or `flash deploy --python-version 3.12`. Validated against the supported set. +- **Per-resource declaration:** set `python_version="3.12"` on any `LiveServerless`, `CpuLiveServerless`, `LiveLoadBalancer`, or `CpuLiveLoadBalancer` config. The build reconciles to the declared value (or raises if resources disagree). + +For projects shared across a team, declare `python_version` explicitly on each resource config. That makes the deploy result identical regardless of who runs `flash build` and what Python they happen to have installed locally — useful when team members and CI run different interpreters. + +Flash will refuse to build if your local Python is outside the supported set (e.g. 3.9 or 3.14). The error message tells you to pass `--python-version`, declare on a resource, or upgrade your interpreter. + +The `runpod/flash:latest`, `runpod/flash-lb:latest`, `runpod/flash-cpu:latest`, and `runpod/flash-lb-cpu:latest` aliases all point at the 3.12 image variant — Dockerfiles or compose files that pin `:latest` will keep getting 3.12. Use the `:py3.X-{tag}` form for explicit version pinning. ## Quick Start From bdef1e0579ea1ef65acf5f336039de975b5ca70a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 28 Apr 2026 12:01:44 -0700 Subject: [PATCH 5/5] docs(cli): document parity-by-default and 3.13 in --python-version help Phase 3 of AE-2827. Updates the Options bullet for --python-version on both flash build and flash deploy docs to reflect the new behavior: local interpreter is the default; 3.13 is now in the supported set. Refs AE-2827. --- src/runpod_flash/cli/docs/flash-build.md | 8 ++++---- src/runpod_flash/cli/docs/flash-deploy.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/runpod_flash/cli/docs/flash-build.md b/src/runpod_flash/cli/docs/flash-build.md index 0798e0de..baaddc64 100644 --- a/src/runpod_flash/cli/docs/flash-build.md +++ b/src/runpod_flash/cli/docs/flash-build.md @@ -28,7 +28,7 @@ flash build [OPTIONS] - `--no-deps`: Skip transitive dependencies during pip install (default: false) - `--output, -o`: Custom archive name (default: artifact.tar.gz) - `--exclude`: Comma-separated packages to exclude (e.g., 'torch,torchvision') -- `--python-version`: Target Python version for worker images (`3.10`, `3.11`, or `3.12`). Overrides per-resource `python_version`. Default: value declared on resource configs, or 3.12 if none set. +- `--python-version`: Target Python version for worker images (`3.10`, `3.11`, `3.12`, or `3.13`). Overrides per-resource `python_version` declarations and the local-interpreter default. By default, `flash build` targets the Python version you're running flash from. To launch a local preview environment, use `flash deploy --preview` instead. @@ -68,7 +68,7 @@ After `flash build` completes: Flash automatically handles cross-platform builds, ensuring compatibility with Runpod's Linux x86_64 serverless infrastructure: - **Automatic Platform Targeting**: Dependencies are always installed for Linux x86_64, regardless of your build platform (macOS, Windows, or Linux) -- **Python Version**: Targets Python 3.12 for wheel ABI selection regardless of local interpreter +- **Python Version**: Targets the resolved Python version (your local interpreter by default, or whatever `--python-version` / per-resource `python_version` selects) for wheel ABI selection - **Binary Wheel Enforcement**: Only pre-built binary wheels are used, preventing platform-specific compilation issues This means you can safely build on macOS ARM64, Windows, or any platform, and the deployment will work correctly on Runpod. @@ -181,8 +181,8 @@ ls .flash/.build/my-project/ If a package doesn't have pre-built Linux x86_64 wheels: 1. **Install standard pip**: `python -m ensurepip --upgrade` -- standard pip has better manylinux compatibility than uv pip -2. **Check package availability**: Visit PyPI and verify the package has Linux wheels for Python 3.12 -3. **Python 3.12**: All flash workers run Python 3.12. Ensure packages are available for this version. +2. **Check package availability**: Visit PyPI and verify the package has Linux wheels for your target Python version (`3.10`, `3.11`, `3.12`, or `3.13`) +3. **Match interpreter**: Flash builds default to your local Python version. If a wheel is missing for that version, either pick a different `--python-version` or upgrade/downgrade the package. 4. **Pure-Python packages**: These work regardless, as they don't require platform-specific builds ## Managing Deployment Size diff --git a/src/runpod_flash/cli/docs/flash-deploy.md b/src/runpod_flash/cli/docs/flash-deploy.md index ef2c288a..24bcafde 100644 --- a/src/runpod_flash/cli/docs/flash-deploy.md +++ b/src/runpod_flash/cli/docs/flash-deploy.md @@ -88,7 +88,7 @@ flash deploy [OPTIONS] - `--exclude`: Comma-separated packages to exclude (e.g., 'torch,torchvision') - `--output, -o`: Custom archive name (default: artifact.tar.gz) - `--preview`: Build and launch local preview environment instead of deploying -- `--python-version`: Target Python version for worker images (`3.10`, `3.11`, or `3.12`). Overrides per-resource `python_version`. +- `--python-version`: Target Python version for worker images (`3.10`, `3.11`, `3.12`, or `3.13`). Overrides per-resource `python_version` declarations and the local-interpreter default. By default, `flash deploy` targets the Python version you're running flash from. ## Examples