Skip to content

Lift app packaging into serious_python + SPM-by-default darwin builds#6608

Merged
FeodorFitsner merged 10 commits into
flet-0.86from
app-package
Jun 22, 2026
Merged

Lift app packaging into serious_python + SPM-by-default darwin builds#6608
FeodorFitsner merged 10 commits into
flet-0.86from
app-package

Conversation

@FeodorFitsner

@FeodorFitsner FeodorFitsner commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Brings the 4.0.0 app-packaging line and Swift Package Manager by default into the flet-0.86 release branch.

Highlights

Lift app packaging into serious_python

  • App bundling moves into serious_python's package step: unpacked bundle layout + reworked storage dirs.

Swift Package Manager by default for iOS/macOS (#6607)

  • flet build uses SPM by default for darwin; auto-falls back to CocoaPods when the app uses a non-SPM plugin (flet-video). Opt-out via --swift-package-manager/--no-swift-package-manager or pyproject swift_package_manager.
  • Sets SERIOUS_PYTHON_DARWIN_SPM explicitly and threads the SP_NATIVE_SET cache-bust key through to serious_python; no global flutter config mutation.
  • Stale flutter-packages fix: register_flutter_extensions() clears the permanent dir each build, so a removed extension (e.g. dropping flet-video) no longer lingers in the built app.
  • Default desktop client migrated off non-SPM plugins: window_to_frontwindowManager.show(), screen_retriever 0.2.1; regenerated registrants + Runner SPM wiring.

Misc

  • Bump pasteboard to ^0.5.0 (+ refresh client lockfile).
  • Exclude generated *.pbxproj from the typos hook.

Test plan

  • pre-commit (ruff + typos) clean
  • flet build macos / ipa (SPM default + CocoaPods fallback for flet-video)
  • rebuild after dropping flet-video → confirms it's gone (stale-extension fix)

Summary by Sourcery

Adopt serious_python 4.0.0 app packaging and make Swift Package Manager the default integration path for the embedded Python runtime on iOS/macOS, alongside reworked app storage directories and corresponding docs updates.

New Features:

  • Add a Swift Package Manager toggle for iOS/macOS builds, defaulting to SPM with automatic CocoaPods fallback when non-SPM plugins are used.
  • Introduce structured dev-mode storage under a hidden, git-ignored .flet/storage directory that mirrors packaged app storage layout, including cache support via FLET_APP_STORAGE_CACHE.

Bug Fixes:

  • Ensure stale Flutter extensions are cleared between builds so removed plugins like flet-video do not linger in packaged apps.

Enhancements:

  • Lift Python app bundling into serious_python’s package step so native builds consume an unpacked app directory instead of app.zip, with platform-specific staging validation.
  • Wire flet build/flet debug to drive serious_python’s SPM vs CocoaPods staging via environment variables and a cache-busting key for Darwin builds without mutating global Flutter config.
  • Clarify and improve runtime handling of app storage directories and working directory semantics across platforms, including aligning FLET_APP_STORAGE_* usage and documenting their behavior.
  • Replace the window_to_front plugin with window_manager.show() for desktop window focusing, and update screen_retriever to an SPM-compatible version in templates and client config.
  • Exclude generated Xcode .pbxproj files from typo checking in pre-commit and typos config to avoid false positives.

Build:

  • Pin the build template to serious_python 4.0.0 from its main branch and adjust Flutter assets to only include app.zip for web builds that still use it.
  • Update client dependency constraints and lockfile entries, including bumping pasteboard to ^0.5.0 and aligning plugin versions for SPM-based Darwin builds.

Documentation:

  • Document the new unpacked, read-only app bundle layout and reworked storage directories as a breaking change for 0.86.0, including migration guidance for file access.
  • Expand environment variable and cookbook documentation to cover the three-tier storage model (data, cache, temp) and its interaction with StoragePaths and dev-mode behavior.

Federicorao and others added 5 commits June 18, 2026 07:17
…`ft.Page`/`ft.Text` instead of deprecated `flet.app (#6582)

* Fix issue #6579

* docs: use fvm for Flutter commands
…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
…orage 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.
* 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.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've reviewed this pull request using the Sourcery rules engine

Comment on lines 429 to 435
self.p = subprocess.Popen(
self.args, env=p_env, stdout=subprocess.PIPE, encoding="utf-8"
self.args,
env=p_env,
cwd=self.flet_app_data_dir,
stdout=subprocess.PIPE,
encoding="utf-8",
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (python.lang.security.audit.dangerous-subprocess-use-audit): Detected subprocess function 'Popen' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'.

Source: opengrep

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 21, 2026

Copy link
Copy Markdown

Deploying flet-website-v2 with  Cloudflare Pages  Cloudflare Pages

Latest commit: ab3640b
Status: ✅  Deploy successful!
Preview URL: https://9d22a934.flet-website-v2.pages.dev
Branch Preview URL: https://app-package.flet-website-v2.pages.dev

View logs

…aPods 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 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.
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.
@FeodorFitsner FeodorFitsner merged commit 4e77288 into flet-0.86 Jun 22, 2026
82 of 155 checks passed
@FeodorFitsner FeodorFitsner deleted the app-package branch June 22, 2026 22:11
FeodorFitsner added a commit that referenced this pull request Jun 25, 2026
Bring the `flet test` (on-device integration testing) branch up to date with the
current flet-0.86 line for a clean cross-platform CI experiment.

Conflict resolution:
- dart-bridge build template (lib/main.dart, native_runtime*.dart, python.dart,
  pubspec.yaml) and app.py / __init__.py / python_versions.py: take flet-0.86 —
  its #6601/#6608 dart-bridge + serious_python 4.x packaging supersedes the
  earlier prototype that this branch built on. The flet-test feature rides on top
  (separate tester socket channel, build_base test_mode injection, the
  integration_test/ entry + flet_integration_test package — all preserved).
- flet_backend.dart: keep flet-0.86's bootStatus wiring + this branch's
  `"test": ... FLET_TEST` page prop.
- cli.py: keep both `flet test` and the new `flet clean` registrations.
- _typos.toml: union (UDID/udid + certifi).
- CHANGELOG.md / breaking-changes index: take flet-0.86 (superset).
- website/sidebars.js: accept flet-0.86's deletion (now generated from sidebars.yml).
FeodorFitsner added a commit that referenced this pull request Jul 2, 2026
…ntal builds (#6634)

register_flutter_extensions() unconditionally wiped the permanent
build/flutter-packages directory before repopulating it only when the
temp dir exists. On incremental builds the package hash is unchanged, so
serious_python is invoked with --skip-site-packages and does not copy
Flutter packages to the temp dir. The absent temp dir then meant the
wiped extensions were never restored, breaking 'flutter build web'
(unresolved web plugins such as audioplayers_web, camera_web, etc.).

Track when the package step ran with --skip-site-packages and skip the
wipe/move in that case, keeping the previous build's extension copy. A
removed extension changes the package requirements, flips the hash, and
takes the full (non-skip) path that still clears stale extensions.

Regression from #6608.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants