Multi-version Python support (3.12 / 3.13 / 3.14)#6577
Merged
Conversation
Delete generated web/canvaskit build artifacts from sdk/python/templates/build/{{cookiecutter.out_dir}} (canvaskit.js, .symbols, .wasm and chromium/skwasm variants). These are built/WebAssembly output files and have been removed from the template to avoid committing generated binaries and reduce repository/template size.
Add a `python_versions` registry that maps each supported short Python
version to its CPython-standalone build, Pyodide release, and Emscripten
wheel platform tag. `flet build` and `flet publish` resolve the version
in this order: `--python-version X.Y` (new flag) -> `[project].requires-
python` (highest matching stable; pre-release rows are skipped unless an
explicit specifier like `==3.15.*` opts in) -> default `3.14`.
`build_base.py` threads the resolved version through to serious_python
(via `--python-version` and `SERIOUS_PYTHON_VERSION`) and the Flutter
build env, and exposes it to the cookiecutter template as
`cookiecutter.options.python_version` so the Android `abiFilters` can
drop `armeabi-v7a` for 3.13+ (PEP 738 dropped 32-bit Android in
python-build releases).
Pyodide is no longer pre-baked into the build template. On each web
build/publish, the matching pyodide-core tarball plus the micropip /
packaging wheels are downloaded into the build output and cached under
`~/.flet/pyodide/<version>/`. `client/web/python.js` and the templated
`python.js` drop the hardcoded `defaultPyodideUrl`; `patch_index.py`
injects `flet.pyodideUrl` at build time (CDN for normal builds, local
`pyodide/pyodide.js` when `--no-cdn`).
Other:
* Bump the `serious_python` pin in the build template to 2.0.0
(multi-version support landed there as a breaking release; pin must
follow once 2.0.0 is published to pub.dev).
* Add `python_version`-aware section to the publish docs ("Choosing a
Python version"), Pyodide pairing table on the static-website page,
and a `--pre` clarification on `flet publish`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…odide
With multi-version Python, Pyodide is selected per build from
`SUPPORTED_PYTHON_VERSIONS` (currently 0.27.7 / 0.29.4 / 314.0.0a2 for
Python 3.12 / 3.13 / 3.14). The old single-line `Pyodide: 0.27.7` field
on `flet.version` was both stale and misleading once it stopped tracking
what `flet build` actually bundles.
Replace it with a multi-line listing rendered from the registry:
Flet: 0.85.3
Flutter: 3.41.7
Supported Python versions:
3.12 (Pyodide 0.27.7)
3.13 (Pyodide 0.29.4)
3.14 (Pyodide 314.0.0a2, default)
Pre-release rows render with ", pre-release" appended. `PYODIDE_VERSION`
and the `pyodide_version` export on `flet.version` are removed (the only
external consumer was the CLI version output, now updated).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sort SUPPORTED_PYTHON_VERSIONS by `packaging.version.Version(r.short)` in reverse before rendering, so users see the default (newest stable) at the top instead of having to scan to the bottom of the list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`flet build` rewrites local-path dev dependencies as `<pkg> @
file://<path>` so pip installs them in place. On Windows the literal
f"file://{dev_path}" rendered `file://D:\a\...\flet`, which pip parsed
as a UNC path (`\\D:\a\...`) and failed with:
ERROR: Could not install packages due to an OSError: [Errno 2]
No such file or directory: '\\\\D:\\a\\flet\\flet\\sdk\\python\\packages\\flet'
`Path.as_uri()` produces the correct three-slash form
(`file:///D:/a/flet/...` on Windows, `file:///Users/...` on POSIX) and
URL-encodes any special characters, so it's safe on every platform.
Surfaces on flet's own apk-windows CI job
(flet-dev/flet#27111512526 job 80010220246).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Each of the 14 build targets (linux/macos/windows + Android aab+apk on
all three hosts + ipa + ios-simulator + web on all three hosts) now runs
against every supported bundled CPython, producing 42 jobs total.
Matrix gains a `python_version` scalar axis and promotes `name` from an
`include` row to a base axis so GH Actions takes the cartesian product;
the existing `include` entries are kept as-is and matched by `name` to
supply per-target runner / build_cmd / artifact_path. The build step now
passes `--python-version ${{ matrix.python_version }}` to `flet build`,
and the upload step disambiguates the artifact name with a `-pyX.Y`
suffix so the 42 uploads don't collide.
`fail-fast: false` is unchanged so a single failing combo doesn't kill
the rest of the grid.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Split the 14-target build matrix into a reusable workflow (`flet-build-test-matrix.yml`) that takes the bundled Python version as an input, and call it three times from the entrypoint — once per supported CPython release. The Actions UI now renders each call as its own collapsible "Matrix: build" card (`0/14 jobs completed`) instead of a single flat 42-row list. Adds a `python_version` choice input to `workflow_dispatch` (`all` | `3.12` | `3.13` | `3.14`) so manual runs can target a single version. push and pull_request triggers always fire all three. Each call is gated by `if: github.event_name != 'workflow_dispatch' || inputs.python_version == 'all' || inputs.python_version == 'X.Y'`. The pack job stays at the top level (its host-Python PyInstaller bundle is independent of the bundled CPython that `flet build` ships, so it doesn't need a per-Python axis). path-filter triggers now reference both workflow files. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bumps the Dart-side `flet` package to 0.86.0 and adds the user-facing 0.86.0 entry to the top-level changelog: new `--python-version` flag, per-version Pyodide download/cache, `flet --version` listing change, the default-3.14 breaking note, removal of `flet.version.pyodide_version`, and the Windows `file://` dev-package URL fix. The Dart `flet` package gets the usual italic release-coordination note since this branch doesn't touch the Dart side. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Match the same descending order applied to `flet --version` so users see the default (3.14) at the top of every supported-Python table instead of having to scan to the bottom of the list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ndonkoHenri
added a commit
that referenced
this pull request
Jun 11, 2026
The multi-version Python PR (#6577) removed flet.version.pyodide_version but the 'Get Pyodide version' step still read it, failing every 'Build Flet Client for Web' run. Resolve the version from the flet_cli.utils.python_versions registry instead (default release's Pyodide), and replace the hand-rolled tarball + wheel downloads with flet_cli.utils.pyodide.ensure_pyodide — the hardcoded micropip-0.8.0/packaging-24.2 filenames would have silently broken on the new Pyodide line (3.14's lock resolves micropip 0.11.1), since curl without -f writes 404 pages into the .whl files.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds multi-version bundled CPython support to
flet buildandflet publish. Users pick which interpreter ships with their app via a new--python-versionflag (3.12 / 3.13 / 3.14) or via[project].requires-pythonin theirpyproject.toml; the default is the latest supported stable (currently 3.14). Pyodide is no longer pre-baked into the build template — the matching release for each Python version is downloaded into the build output and cached under~/.flet/pyodide/<version>/per build.Companion to flet-dev/serious-python#207 (the 2.0.0 release where the platform plugins and packager learned to parameterize the bundled Python version). The build template here pins
serious_python: 2.0.0, so this branch should land after serious_python 2.0.0 publishes to pub.dev.Highlights
flet_cli/utils/python_versions.py— single source of truth for Python ↔ CPython-standalone ↔ Pyodide ↔ wheel-platform-tag.prerelease: Truerows are opt-in (skipped in open-endedrequires-pythonresolution; reachable via explicit--python-version 3.15/==3.15.*).build_base.pyplumbing: resolves once ininitialize_command, threads--python-version+SERIOUS_PYTHON_VERSIONinto both the serious_python package step and the laterflutter build, and exposes the resolved short version to the cookiecutter template ascookiecutter.options.python_versionso the AndroidabiFilterscan droparmeabi-v7afor 3.13+ (PEP 738).flet_cli/utils/pyodide.pyfetchespyodide-core-<version>.tar.bz2+micropip/packagingwheels into a per-version cache, idempotent.patch_index.py: injectsflet.pyodideUrlper build (CDN or localpyodide/pyodide.js); the hardcodeddefaultPyodideUrlconstant is removed from bothclient/web/python.jsand the build templatepython.js. Pre-baked pyodide bundle deleted from the build template.flet --version: lists supported Python versions (newest first) instead of a single static Pyodide line — the globalflet.version.pyodide_versionexport is removed.--prevs--python-versionclarification onflet publish.flet-build-testnow runs against the full 3.12 / 3.13 / 3.14 grid (14 build targets × 3 versions = 42 jobs), grouped via a reusable workflow so the Actions UI shows three cards instead of a flat 42-row list.workflow_dispatchgains apython_versionchoice input (all/3.12/3.13/3.14) for targeted manual runs.file://URLs on Windows now use `Path.as_uri()` so paths render asfile:///D:/...instead of being misparsed as UNC.Type of change
file://URLChecklist
website/sidebars.ymlfor breaking changes, removals, and deprecations, if applicable. (Not breaking from end-user perspective; existing builds keep working with--python-version 3.12if pinned.)Additional details
Release sequencing: this branch's build template pins
serious_python: 2.0.0. Don't merge until serious_python 2.0.0 is live on pub.dev (flet-dev/serious-python#207).🤖 Generated with Claude Code
Summary by Sourcery
Add configurable bundled Python version support to Flet builds and publishes, wiring version resolution through the CLI, web runtime, templates, and CI, and switch Pyodide to a per-version, cached download instead of a baked-in bundle.
New Features:
flet buildandflet publishto select the bundled Python interpreter via a new--python-versionflag orproject.requires-python, with 3.12, 3.13, and 3.14 supported.flet --version, including which version is the default and associated Pyodide releases.Bug Fixes:
file://URLs on Windows by usingPath.as_uri()so pip resolves drive-letter paths correctly instead of treating them as UNC paths.Enhancements:
Build:
flet-build-testworkflow into a reusable matrix workflow invoked once per supported Python version, and add aworkflow_dispatchinput to target specific Python versions while preserving full matrix coverage by default.CI:
Documentation:
--preand--python-versionin the publish docs.