Skip to content

Commit 4e77288

Browse files
FeodorFitsnerFedericoraoInesaFitsner
authored
Lift app packaging into serious_python + SPM-by-default darwin builds (#6608)
* Update CONTRIBUTING.md hello.py example to use modern `ft.run()` and `ft.Page`/`ft.Text` instead of deprecated `flet.app (#6582) * Fix issue #6579 * docs: use fvm for Flutter commands * feat: add flet-spinkit extension package wrapping flutter_spinkit ^5.2.2 (#6596) * feat(flet-spinkit): add flet-spinkit extension package wrapping flutter_spinkit ^5.2.2 Adds 31 separate spinner animation controls (SpinKitRotatingCircle, SpinKitWave, SpinKitRipple, etc.) following the same structure as flet-color-pickers. Includes a spinkit_showcase example. * fix(flet-spinkit): use local path source for flet-spinkit in example * fix(flet-spinkit): use ft.Alignment.CENTER instead of ft.alignment.center * fix(flet-spinkit): use ft.Border.all instead of ft.border.all * refactor(flet-spinkit): simplify example to a single SpinKitRotatingCircle * feat(flet-spinkit): register flet_spinkit extension in client runner * fix(flet-spinkit): remove SpinKitPumpCurve/RingCurve (Curve helpers, not widgets), add SpinKitWaveSpinner * refactor(flet-spinkit): strip SpinKit prefix from all Python class names Python API is now fsk.RotatingCircle, fsk.Wave, fsk.WaveType etc. Flutter control type strings (@ft.control decorator values) are unchanged. * feat(flet-spinkit): expand example to a full 30-spinner grid showcase * feat(flet-spinkit): add spinkit_props example; use system theme in both examples * docs(flet-spinkit): add single-page SpinKit docs and sidebar entry * docs(flet-spinkit): register flet_spinkit in crocodocs; remove image refs from docs * ci(flet-spinkit): add flet-spinkit to build and publish pipeline; remove local path source overrides from examples * test(flet-spinkit): add unit tests; fix stale showcase description * refactor(flet-spinkit): rename import alias from fsk to spins in examples and tests * feat(flet-spinkit): complete integration and cleanup - Register flet-spinkit in sdk/python/pyproject.toml (dependencies + uv.sources) - Register flet-spinkit in sdk/python/packages/flet/pyproject.toml (extensions group) - Register flet-spinkit in flet_build_test/pyproject.toml (dependencies, uv.sources, dev_packages) - Replace custom _parseWaveType() helper with parseEnum() in spinkit.dart - Update implement-flet-extension SKILL.md with lessons learned from this implementation * docs(flet-spinkit): split into per-control pages, add WaveType page Replace single-page spinkit docs with individual pages per control, consistent with flet-color-pickers and other extensions. Add WaveType enum page to fix unresolved reST cross-reference on the Wave page. * test(flet-spinkit): rewrite as proper integration tests using ftt.FletTestApp Replace pure Python unit tests with integration tests that render each control in a real Flutter app. Use tester.pump() instead of pump_and_settle() to advance animation clock without waiting for continuous animations to settle. Assert finder.count == 1 to verify each control is mounted in the Flutter widget tree. * docs(flet-spinkit): reformat README to match other extension packages * Lift app packaging into serious_python: unpacked bundle + reworked storage dirs App Python sources now ship unpacked inside the app bundle (next to stdlib/site-packages) on macOS/iOS/Windows/Linux instead of being extracted from app.zip on first launch; Android ships a stored app.zip asset unpacked once. The app dir is read-only, so the process cwd moves to a writable, app-private data dir. - build_base.py: stage the app via SERIOUS_PYTHON_APP for native platforms; gate the app.zip existence check to Emscripten/web. - templates main.dart / native_runtime.dart: ask serious_python for the app dir (prepareApp/getAppDir) instead of extracting app.zip; set cwd + FLET_APP_STORAGE_DATA to <support>/data, add FLET_APP_STORAGE_CACHE, repoint FLET_APP_STORAGE_TEMP to the OS temp dir; pubspec pins serious_python 4.0.0 and makes app.zip a web-only asset. - run.py: dev-mode storage under a hidden, self-gitignored <project>/.flet/; cwd = .flet/storage/data, redirect TMPDIR, set the three FLET_APP_STORAGE_* vars; hide .flet/ on Windows; write a README explaining the dirs. - docs: new breaking-change guide + updated environment-variables, read-and-write-files, storagepaths, sidebars. * Bump pasteboard to ^0.5.0 (and refresh transitive deps in client lockfile) * flet build: Swift Package Manager by default for iOS/macOS (#6607) * flet build: use Swift Package Manager for iOS/macOS by default Drives the new serious_python_darwin SPM build path. SPM is Flet's default darwin integration (CocoaPods remains the fallback); Flet auto-enables it only on its own managed Flutter, never a Flutter found on PATH. - flutter_base.py: install_flutter() now enables Swift Package Manager on the Flet-managed Flutter (`flutter config --enable-swift-package-manager`) and sets flutter_installed_by_flet. - build_base.py: _darwin_spm_active() reports whether the darwin build uses SPM (true on Flet's managed Flutter; otherwise honors the user's flutter config via `flutter config --machine`). When active, the package step gets SERIOUS_PYTHON_DARWIN_SPM (so serious_python does the host-side SPM staging the podspec prepare_command can't) + SERIOUS_PYTHON_SPM_KEY_FILE, and the flutter build env gets SP_NATIVE_SET read back from that key file so SwiftPM re-resolves when the staged native set changes. Requires serious_python >= the SPM-capable release. * flet build: SPM-by-default plumbing + client plugin migration + stale flutter-packages fix - build_base.py: set SERIOUS_PYTHON_DARWIN_SPM explicitly (true/false) and pass SP_NATIVE_SET key file through to serious_python's package step; --swift-package-manager / pyproject opt-out with flet-video auto-fallback. - build_base.py: register_flutter_extensions now always clears the permanent flutter-packages dir before staging this build's set, so an extension removed since the previous build (e.g. dropping flet-video) no longer lingers in the built app. - flutter_base.py: drop the global 'flutter config' SPM toggle (flet must not mutate Flutter's machine-wide config). - client: migrate off non-SPM plugins for the default desktop client — window_to_front -> windowManager.show(); pin screen_retriever 0.2.1 (SPM); regenerate plugin registrants + Runner SPM project wiring. - typos: exclude generated *.pbxproj (pre-commit hook + _typos.toml). - templates/build pubspec + CHANGELOG. * flet build: always stage serious_python for SPM (drop flet-video CocoaPods fallback) The flet-video auto-fallback assumed that an app with a non-SPM plugin builds entirely with CocoaPods, so serious_python was staged for CocoaPods. That's wrong for Flutter 3.44+ (SPM on by default): Flutter builds hybrid — plugins with a Package.swift (incl. serious_python_darwin) use SPM while non-SPM plugins (media_kit/flet-video, torch_light) use CocoaPods in the same build. Staging serious_python for CocoaPods while Flutter linked it via its Package.swift left dart_bridge unlinked -> 'Undefined symbol: _DartBridge_*/_serious_python_run' on macOS and iOS. Always stage for SPM (Flutter's default); other non-SPM plugins ride CocoaPods via Flutter's hybrid mode independently. Keep --no-swift-package-manager / swift_package_manager=false only for when SPM is disabled in Flutter itself. Removes _references_non_spm_plugins/_NON_SPM_PLUGINS/_app_uses_non_spm_plugin (and the now-unused canonicalize_name/contextlib imports). * Add example deps and modernize typing imports Add flet-code-editor and flet-color-pickers to the flet_build_test example (pyproject and example imports) and register flet_spinkit import in main.py. Modernize typing usage across packages: add conditional typing-extensions dependency for flet-webview, use typing.Self on Python >=3.11 with a fallback to typing_extensions.Self, and simplify/remove try/except fallbacks by importing Protocol, TypeVar and ParamSpec directly from typing. These changes simplify type annotations and ensure compatibility with older Python via typing-extensions. * Pin serious_python to 4.0.0 Commented out the Shizuku Android provider entries in sdk/python/examples/apps/flet_build_test/pyproject.toml to disable that provider by default. Replaced the git-based serious_python dependency in sdk/python/templates/build/{{cookiecutter.out_dir}}/pubspec.yaml with a pinned version (4.0.0) to stop tracking the main branch and use the published package. --------- Co-authored-by: Federico Rao <157750791+Federicorao@users.noreply.github.com> Co-authored-by: InesaFitsner <inesa@appveyor.com>
1 parent a9e17d7 commit 4e77288

90 files changed

Lines changed: 6861 additions & 176 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/implement-flet-extension/SKILL.md

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Implement a Flet extension around an external Flutter package using existing `fl
4444

4545
## Flutter-side Rules
4646

47-
- Use `parseEnum()` for enums.
47+
- Use `parseEnum()` for enums — it's exported from `package:flet/flet.dart`. Call it as `parseEnum(MyEnum.values, widget.control.getString("attr"), MyEnum.defaultVal)!`. Do NOT write a custom `_parseXxx()` switch helper.
4848
- For control attributes, prefer `widget.control.getBool()/getDouble()/...` accessors.
4949
- For non-control parsing, use shared `parseSomething()` helpers.
5050
- Do not add one-off private parser utilities when standard helpers exist.
@@ -65,22 +65,33 @@ Without matching defaults, Dart receives `null` and either crashes or silently u
6565

6666
## Integration Checklist
6767

68-
- Add dependency and registration to Flet client app.
69-
- Add extension package to `sdk/python/pyproject.toml`.
70-
- Add extension to `sdk/python/packages/flet/pyproject.toml`.
71-
- Add extension to `sdk/python/examples/apps/flet_build_test/pyproject.toml`.
68+
- Register in the Flet client app — two files:
69+
1. `client/pubspec.yaml`: add `flet_<ext>: path: ../sdk/python/packages/flet-<ext>/src/flutter/flet_<ext>` under `dependencies`.
70+
2. `client/lib/main.dart`: add `import 'package:flet_<ext>/flet_<ext>.dart' as flet_<ext>;` and `flet_<ext>.Extension()` to the `extensions` list.
71+
- Add extension package to `sdk/python/pyproject.toml` in **two places**: the `dependencies` list and `[tool.uv.sources]` as `{ workspace = true }`.
72+
- Add extension to `sdk/python/packages/flet/pyproject.toml` in the `[dependency-groups] extensions` list.
73+
- Add extension to `sdk/python/examples/apps/flet_build_test/pyproject.toml` in **three places**: `[project] dependencies`, `[tool.uv.sources]` as `{ path = "...", editable = true }`, and `[tool.flet.dev_packages]` as a relative path string.
74+
- Add extension to `tools/crocodocs/pyproject.toml` under `[tool.crocodocs.packages]` as `<pkg_name> = "../../sdk/python/packages/<pkg-dir>/src"`. This fixes "Missing API entry" errors in the docs. Note: `api-data.json` is gitignored (generated at build time); only the `pyproject.toml` change needs committing.
7275
- Add extension to `.github/workflows/ci.yml` in both places:
7376
- `build_flet_extensions` -> `PACKAGES` list.
7477
- `py_publish` -> `for pkg in ...` publish loop.
7578
- Add `.gitignore` to Flutter extension project if missing.
79+
- Remove `[tool.uv.sources]` local path overrides from example `pyproject.toml` files before opening a PR (they are development-only conveniences).
7680

7781
## Docs, Examples, Tests
7882

7983
- Add control/service docs under `website/docs/controls/<name>` for controls and `website/docs/services/<name>` for services.
84+
- Always create one doc page per control, even for extensions with many similar controls. Use `index.md` for the overview (install instructions, examples, list of links) and individual `<controlname>.md` files for each control — consistent with `flet-color-pickers` and other extensions.
85+
- Use `<ClassSummary name="pkg.ClassName" />` and `<ClassMembers name="pkg.ClassName" />` JSX from `@site/src/components/crocodocs` to render API docs. Do NOT add `image=`, `imageCaption=`, or `imageWidth=` props to `<ClassSummary>` when no screenshots exist yet.
86+
- In the `## Examples` section, do NOT add `###` subtitles above `<CodeExample>` blocks — titles are injected automatically from the example file itself.
8087
- Add all custom enums/types docs and update `website/sidebars.yml` navigation.
8188
- Use markdown filenames without underscores (`codeeditor.md`, not `code_editor.md`).
82-
- Add examples under `sdk/python/examples` in the appropriate category for control vs service.
83-
- Add integration tests under `packages/flet/integration_tests` in the appropriate category for control vs service.
89+
- Add examples under `sdk/python/examples/extensions/<name>/` for extension controls.
90+
- Use `import flet_<ext> as <short_alias>` in examples (e.g., `import flet_spinkit as spins`). Keep alias short but readable.
91+
- Use `ft.Colors.SURFACE_CONTAINER_HIGHEST` for card/cell backgrounds in showcase examples — it adapts to light and dark system themes automatically.
92+
- Do NOT set an explicit dark theme in examples; let the app use system theme (no `page.theme_mode`).
93+
- Add integration tests under `packages/flet/integration_tests/extensions/<name>/`**not** inside the extension package's own directory (no `tests/` folder in the package itself, matching the pattern of `flet-code-editor`, `flet-color-pickers`, etc.).
94+
- For controls with continuously-running animations, do NOT use `assert_control_screenshot` or `pump_and_settle` — they will timeout waiting for animations to settle. Instead use `await flet_app.tester.pump(duration=ft.Duration(milliseconds=500))` which advances the clock by a fixed amount. This still runs real Flutter rendering and catches crashes, without screenshot comparison.
8495
- Ensure generated screenshots are suitable for docs usage when visual examples are added.
8596

8697
## Upgrade and Compatibility Guardrails

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,7 @@ jobs:
672672
flet-permission-handler
673673
flet-rive
674674
flet-secure-storage
675+
flet-spinkit
675676
flet-video
676677
flet-webview
677678
)
@@ -836,6 +837,7 @@ jobs:
836837
flet_permission_handler \
837838
flet_rive \
838839
flet_secure_storage \
840+
flet_spinkit \
839841
flet_video \
840842
flet_webview; do
841843
uv publish dist/**/${pkg}-*

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22

33
### New features
44

5-
* Multi-version bundled CPython support in `flet build` and `flet publish`. Pick the runtime your app ships with via the new `--python-version` flag (3.12 / 3.13 / 3.14), or let it be derived from `[project].requires-python` in your `pyproject.toml`; defaults to the latest supported stable (currently 3.14). The matching CPython-standalone build, Pyodide release (0.27.7 / 0.29.4 / 314.0.0), and Emscripten wheel platform tag are all resolved from `flet-dev/python-build`'s date-keyed manifest. Adding a future pre-release CPython line (e.g. 3.15 beta) is a one-row append with `prerelease=True` — opt-in only via an explicit `--python-version 3.15` or `requires-python = "==3.15.*"`, never the auto-resolved default. Requires `serious_python` >= 3.0.0, now pinned in the `flet build` template. See the new [Choosing a Python version](https://flet.dev/docs/publish#choosing-a-python-version) docs section ([#6577](https://github.com/flet-dev/flet/pull/6577)) by @FeodorFitsner.
5+
* Multi-version bundled CPython support in `flet build` and `flet publish`. Pick the runtime your app ships with via the new `--python-version` flag (3.12 / 3.13 / 3.14), or let it be derived from `[project].requires-python` in your `pyproject.toml`; defaults to the latest supported stable (currently 3.14). The matching CPython-standalone build, Pyodide release (0.27.7 / 0.29.4 / 314.0.0), and Emscripten wheel platform tag are all resolved from `flet-dev/python-build`'s date-keyed manifest. Adding a future pre-release CPython line (e.g. 3.15 beta) is a one-row append with `prerelease=True` — opt-in only via an explicit `--python-version 3.15` or `requires-python = "==3.15.*"`, never the auto-resolved default. Requires `serious_python` >= 4.0.0, now pinned in the `flet build` template. See the new [Choosing a Python version](https://flet.dev/docs/publish#choosing-a-python-version) docs section ([#6577](https://github.com/flet-dev/flet/pull/6577)) by @FeodorFitsner.
66
* Add `ft.DataChannel`: dedicated byte channels for widgets that move bulk binary data (image frames, audio buffers, ML tensors) between Dart and Python, bypassing the MsgPack control protocol. The Dart side opens a channel via `FletBackend.of(context).openDataChannel()` and announces it to Python by firing a `data_channel_open` control event with `{channel_name, channel_id}`; the Python side declares `on_data_channel_open: Optional[ft.EventHandler[ft.DataChannelOpenEvent]]` and captures the channel via `self.get_data_channel(e.channel_id)`. Backed by a dedicated `PythonBridge` per channel in embedded native mode (4–7 GiB/s on M2 Pro) and by the default `ProtocolMuxedDataChannelFactory` in dev / web modes (raw-byte frames muxed over the active Flet protocol transport with a 1-byte type discriminator). Pyodide gets zero-copy outbound sends via `postMessage` Transferable ArrayBuffer. First consumer: `flet-charts` `MatplotlibChartCanvas`, migrated from `_invoke_method` PNG dispatch to a 1-byte-opcode data channel by @FeodorFitsner.
77
* **In-process Python transport (`dart_bridge` FFI).** `package:flet` gains a third protocol transport alongside the UDS / TCP socket servers: it can run Flet's MsgPack protocol over an in-process `dart_bridge` byte channel via a `FletApp(channelBuilder: …)` seam (the `flet` package stays Python-independent — it doesn't depend on `serious_python` or know about `PythonBridge`; the embedder wires the channel). `serious_python` >= 3.0.0 uses this seam to embed the Python interpreter **in-process** instead of talking to it over a localhost socket, and the `flet build` template migrates from sockets to the FFI transport. On Android, where the OS may keep the process alive across a back-button quit and restart only the Dart VM, the transport rebinds to the new VM's `dart_bridge` ports on a session-restart signal (`libdart_bridge` >= 1.3.0) — the Python process and its in-memory state are preserved and the Flet session is rebuilt from `REGISTER_CLIENT` by @FeodorFitsner.
88
* Add `flet clean` command that deletes the `build` directory of a Flet app — the Flutter bootstrap project, cached artifacts, and generated output — in a single step ([#6233](https://github.com/flet-dev/flet/issues/6233)) by @ndonkoHenri.
99
* Add `compression_quality` to `FilePicker.pick_files()` for selecting the image compression quality used by supported platforms ([#6573](https://github.com/flet-dev/flet/pull/6573)) by @ndonkoHenri.
1010

1111
### Improvements
1212

13+
* **Swift Package Manager for iOS/macOS builds (on by default).** `flet build` / `flet debug` now integrate the embedded Python runtime via SPM instead of CocoaPods (CocoaPods goes read-only in December 2026). Flet **auto-falls back to CocoaPods** when the app depends on a package that isn't SPM-ready — currently `flet-video` (media_kit) — since Flutter then builds the whole app with CocoaPods. Force CocoaPods for other non-SPM packages with `--no-swift-package-manager` (or `swift_package_manager = false` under `[tool.flet]`). Flet does **not** change Flutter's global SPM configuration; the setting only selects how `serious_python` stages the runtime to match. When SPM is used (it has no `pod install` hook), `flet build` sets `SERIOUS_PYTHON_DARWIN_SPM` so `serious_python`'s `package` step stages the runtime (Python/dart_bridge xcframeworks, the iOS native extensions, and the stdlib/site-packages/app resources) into the plugin's `Package.swift` layout on the host before `flutter build`, and exports the `SP_NATIVE_SET` cache-bust key into the build. Requires the SPM-capable `serious_python` release.
1314
* **Smaller Android apps with no native-packaging config.** `flet build apk`/`aab` consume serious_python's new Android packaging: Python extension modules load **memory-mapped directly from the APK** (no extraction to disk), and pure Python ships in stored asset zips read via `zipimport`, so the standard library is no longer duplicated per ABI. Apps no longer need `useLegacyPackaging` / `keepDebugSymbols` — the `flet build` Android template drops them; just use `minSdk 23+`. New `--android-extract-packages` flag and `[tool.flet.android].extract_packages` ship "path-hungry" packages — those that read bundled data via `__file__` / `pkg_resources` instead of `importlib.resources` — extracted to disk instead of inside the zip (most packages, including `certifi`, are zip-safe and need no entry). Requires `serious_python` with the native-mmap packaging (dart_bridge 1.4.0).
1415
* Pyodide is no longer pre-baked into the `flet build` template. Each `flet build web` / `flet publish` run downloads the matching `pyodide-core-<version>.tar.bz2` (plus the runtime `micropip` and `packaging` wheels) into a per-version cache at `~/.flet/pyodide/<version>/` and copies the files into the build output. Subsequent builds reuse the cache; the older `0.27.5` bundle previously shipped in the cookiecutter template is gone ([#6577](https://github.com/flet-dev/flet/pull/6577)) by @FeodorFitsner.
1516
* The supported Python / Pyodide / dart_bridge versions are loaded on demand from `flet-dev/python-build`'s date-keyed `manifest.json` (fetched once and cached under `~/.flet/cache`), the single source of truth shared with `serious_python` — replacing flet's hand-mirrored version table. `flet build` forwards only `SERIOUS_PYTHON_VERSION` and lets `serious_python` derive the full version / build date / dart_bridge version from its own committed snapshot. The module exposes `get_supported_python_versions()` / `get_default_python_version()` (the previous `SUPPORTED_PYTHON_VERSIONS` / `DEFAULT_PYTHON_VERSION` constants are removed) ([#6577](https://github.com/flet-dev/flet/pull/6577)) by @FeodorFitsner.
@@ -22,6 +23,7 @@
2223

2324
### Breaking changes
2425

26+
* **App files now ship unpacked in a read-only bundle, and the storage directories were reworked** (requires `serious_python` >= 4.0.0, now pinned in the `flet build` template). Your Python sources ship **unpacked inside the app bundle** next to the stdlib/site-packages (no first-launch `app.zip` extraction) on macOS/iOS/Windows/Linux; on Android they ship as a *stored* `app.zip` asset unpacked once on first launch; web is unchanged. The app directory is now **read-only**, so the Python program's **working directory** moved to a writable, app-private data dir. `FLET_APP_STORAGE_DATA` now maps to the OS *application support* dir (a `data` subdir) instead of the user's Documents folder and is the cwd; `FLET_APP_STORAGE_TEMP` now points to the OS temp dir (was the cache dir) and a new `FLET_APP_STORAGE_CACHE` exposes the cache dir. `flet run` sets the dev cwd to a hidden, git-ignored `<project>/.flet/storage/data`. Relative **reads** of bundled files (`open("seed.json")`) must move to `__file__`/`importlib.resources` or `assets/`. See the [app files unpacked / storage dirs](/docs/updates/breaking-changes/v0-86-0-app-files-unpacked-read-only-bundle) guide by @FeodorFitsner.
2527
* `flet build` and `flet publish` now bundle CPython 3.14 by default (previously 3.12, implicit via the old single-version `serious_python`). Existing apps that depend on native wheels without 3.14 binaries should pin explicitly with `--python-version 3.12` (CLI), `requires-python = ">=3.12,<3.13"` (pyproject), or `SERIOUS_PYTHON_VERSION=3.12` in the build environment ([#6577](https://github.com/flet-dev/flet/pull/6577)) by @FeodorFitsner.
2628
* Android builds now include only the ABIs the bundled Python supports: for Python 3.13+, `armeabi-v7a` is no longer supported nor packaged by default. An explicit `--arch armeabi-v7a` fails with a clear error unless combined with `--python-version 3.12`, which is the only Python version supporting it. The per-version ABI set is sourced from python-build's manifest (`pythons.<short>.android_abis`), not hardcoded in flet ([#6578](https://github.com/flet-dev/flet/pull/6578)) by @ndonkoHenri.
2729
* `flet build` / `flet publish` now **compile your app and packages to `.pyc` by default** (previously off). This removes per-launch bytecode recompilation — a significant cold-start win, especially on mobile where pure Python is imported from a stored zip (`zipimport`) and can't cache bytecode back to disk, so every module would otherwise recompile from source on each launch. The CLI flags gain `--no-compile-app` / `--no-compile-packages` (via `argparse.BooleanOptionalAction`; the existing `--compile-app` / `--compile-packages` still work), and `[tool.flet.compile].app` / `.packages` now default to `true`. Pass `--no-compile-*` or set them to `false` to restore the old behavior (faster iterative builds, or keeping `.py` source in the bundle). Compiled web builds were verified to load in Pyodide (bundled CPython and Pyodide share the same minor version). See the [compile-on-by-default](/docs/updates/breaking-changes/v0-86-0-compile-on-by-default) guide ([#6598](https://github.com/flet-dev/flet/pull/6598)) by @FeodorFitsner.

0 commit comments

Comments
 (0)