Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/serious_python/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 4.4.2

* **iOS:** new `SERIOUS_PYTHON_BUNDLE_ID` env var namespaces the generated frameworks' bundle identifiers under your app (`com.example.myapp.-ssl`) instead of a shared `org.python.*` default identical in every app built with serious_python. `flet build` sets it for you; set it yourself for a manual two-step build, in both places you set `SERIOUS_PYTHON_SITE_PACKAGES`.
* **iOS:** the bundled Python frameworks (`_ssl`, `_hashlib` and every other native extension) now carry the build-provenance keys Xcode stamps into a real framework's `Info.plist`, instead of a minimal hand-written one.
* Both are hypotheses under test for the `ITMS-91065: Missing signature` App Store rejection in flet-dev/flet#6724 — neither is a confirmed fix. Only new App Store submissions are affected by that rejection; existing published apps are not. See `serious_python_darwin` 4.4.2.
* Bundled python-build snapshot re-pinned to **20260727**. No versions moved — Python (**3.12.13 / 3.13.14 / 3.14.6**), Pyodide, and `dart_bridge` **1.6.1** are unchanged from 20260726.

## 4.4.1

* **iOS:** the bundled `_ssl` and `_hashlib` frameworks now ship OpenSSL's official privacy manifest instead of an incomplete stub, correcting what they declare under Apple's third-party SDK requirements. This is a correctness fix and is *not* expected to resolve the `ITMS-91065: Missing signature` App Store rejection reported in flet-dev/flet#6724, which remains under investigation. See `serious_python_darwin` 4.4.1.
Expand Down
17 changes: 17 additions & 0 deletions src/serious_python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,23 @@ dart run serious_python:main package app/src -p iOS -r -r -r app/src/requirement

For the **web** (`Emscripten`) target there is no `SERIOUS_PYTHON_APP`; the app and its `__pypackages__` are zipped into the `app/app.zip` asset instead — make sure it's added to `pubspec.yaml`.

On **iOS**, also set `SERIOUS_PYTHON_BUNDLE_ID` to your app's bundle identifier:

```
export SERIOUS_PYTHON_BUNDLE_ID=com.example.myapp
```

Each Python C-extension ships as its own embedded framework, and this namespaces
their `CFBundleIdentifier`s under your app (`com.example.myapp.-ssl`) instead of a
shared `org.python.*` default that would be identical in every app built with
serious_python — matching what CPython's own iOS support does. A framework's bundle
identifier also becomes its code signing identifier, which Apple's App Store scan
appears to key on for the third-party SDK requirements. Set it in **both** places
`SERIOUS_PYTHON_SITE_PACKAGES` is set (the `package` command and the later `flutter
build`), since the CocoaPods `prepare_command` re-runs the darwin sync. If unset —
or if the value isn't a valid bundle identifier — the `org.python.*` defaults are
kept and a warning is printed. `flet build` sets this for you.

## Python app structure

By default, embedded Python program is run in a separate thread, to avoid UI blocking. Your Flutter app is not supposed to directly call Python functions or modules, but instead it should communicate via some API provided by a Python app, such as: REST API, sockets, SQLite database, files, etc.
Expand Down
9 changes: 9 additions & 0 deletions src/serious_python/example/bridge_example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,14 @@ dev_dependencies:
sdk: flutter
flutter_lints: ^2.0.0

# jni arrives transitively (path_provider -> path_provider_android ->
# jni_flutter -> jni). 1.0.1 added global_jni_env.c, which passes a `va_list`
# where a `void *` is expected: fine on x86_64, where va_list is an array type
# that decays to a pointer, but a hard error on aarch64, where it's a struct.
# That breaks `flutter build linux` on ARM64 hosts. Tracked upstream at
# dart-lang/native#3498 — drop this override once a fixed jni is released.
dependency_overrides:
jni: 1.0.0

flutter:
uses-material-design: true
14 changes: 7 additions & 7 deletions src/serious_python/example/flask_example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ packages:
source: hosted
version: "4.1.2"
jni:
dependency: transitive
dependency: "direct overridden"
description:
name: jni
sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f
Expand Down Expand Up @@ -361,42 +361,42 @@ packages:
path: "../.."
relative: true
source: path
version: "4.0.0"
version: "4.4.1"
serious_python_android:
dependency: transitive
description:
path: "../../../serious_python_android"
relative: true
source: path
version: "4.0.0"
version: "4.4.1"
serious_python_darwin:
dependency: transitive
description:
path: "../../../serious_python_darwin"
relative: true
source: path
version: "4.0.0"
version: "4.4.1"
serious_python_linux:
dependency: transitive
description:
path: "../../../serious_python_linux"
relative: true
source: path
version: "4.0.0"
version: "4.4.1"
serious_python_platform_interface:
dependency: transitive
description:
path: "../../../serious_python_platform_interface"
relative: true
source: path
version: "4.0.0"
version: "4.4.1"
serious_python_windows:
dependency: transitive
description:
path: "../../../serious_python_windows"
relative: true
source: path
version: "4.0.0"
version: "4.4.1"
shelf:
dependency: transitive
description:
Expand Down
9 changes: 9 additions & 0 deletions src/serious_python/example/flask_example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ dev_dependencies:
# following page: https://dart.dev/tools/pub/pubspec

# The following section is specific to Flutter packages.
# jni arrives transitively (path_provider -> path_provider_android ->
# jni_flutter -> jni). 1.0.1 added global_jni_env.c, which passes a `va_list`
# where a `void *` is expected: fine on x86_64, where va_list is an array type
# that decays to a pointer, but a hard error on aarch64, where it's a struct.
# That breaks `flutter build linux` on ARM64 hosts. Tracked upstream at
# dart-lang/native#3498 — drop this override once a fixed jni is released.
dependency_overrides:
jni: 1.0.0

flutter:

# The following line ensures that the Material Icons font is
Expand Down
14 changes: 7 additions & 7 deletions src/serious_python/example/run_example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ packages:
source: sdk
version: "0.0.0"
jni:
dependency: transitive
dependency: "direct overridden"
description:
name: jni
sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f
Expand Down Expand Up @@ -384,42 +384,42 @@ packages:
path: "../.."
relative: true
source: path
version: "4.0.0"
version: "4.4.1"
serious_python_android:
dependency: transitive
description:
path: "../../../serious_python_android"
relative: true
source: path
version: "4.0.0"
version: "4.4.1"
serious_python_darwin:
dependency: transitive
description:
path: "../../../serious_python_darwin"
relative: true
source: path
version: "4.0.0"
version: "4.4.1"
serious_python_linux:
dependency: transitive
description:
path: "../../../serious_python_linux"
relative: true
source: path
version: "4.0.0"
version: "4.4.1"
serious_python_platform_interface:
dependency: transitive
description:
path: "../../../serious_python_platform_interface"
relative: true
source: path
version: "4.0.0"
version: "4.4.1"
serious_python_windows:
dependency: transitive
description:
path: "../../../serious_python_windows"
relative: true
source: path
version: "4.0.0"
version: "4.4.1"
shelf:
dependency: transitive
description:
Expand Down
9 changes: 9 additions & 0 deletions src/serious_python/example/run_example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ dev_dependencies:
# following page: https://dart.dev/tools/pub/pubspec

# The following section is specific to Flutter packages.
# jni arrives transitively (path_provider -> path_provider_android ->
# jni_flutter -> jni). 1.0.1 added global_jni_env.c, which passes a `va_list`
# where a `void *` is expected: fine on x86_64, where va_list is an array type
# that decays to a pointer, but a hard error on aarch64, where it's a struct.
# That breaks `flutter build linux` on ARM64 hosts. Tracked upstream at
# dart-lang/native#3498 — drop this override once a fixed jni is released.
dependency_overrides:
jni: 1.0.0

flutter:

# The following line ensures that the Material Icons font is
Expand Down
4 changes: 2 additions & 2 deletions src/serious_python/lib/src/python_versions.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// GENERATED by `dart run serious_python:gen_version_tables` from python-build's
// manifest.json (release 20260726). Do not edit by hand — edit python-build's
// manifest.json (release 20260727). Do not edit by hand — edit python-build's
// manifest.json, cut a release, bump `pythonReleaseDate`, and regenerate.

const pythonVersionEnvironmentVariable = "SERIOUS_PYTHON_VERSION";
Expand All @@ -10,7 +10,7 @@ const pyodideVersionEnvironmentVariable = "SERIOUS_PYTHON_PYODIDE_VERSION";
const dartBridgeVersionEnvironmentVariable = "DART_BRIDGE_VERSION";

/// python-build release the bundled runtimes come from (YYYYMMDD).
const pythonReleaseDate = "20260726";
const pythonReleaseDate = "20260727";
const dartBridgeVersion = "1.6.1";
const defaultPythonVersion = "3.14";

Expand Down
2 changes: 1 addition & 1 deletion src/serious_python/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: serious_python
description: A cross-platform plugin for adding embedded Python runtime to your Flutter apps.
homepage: https://flet.dev
repository: https://github.com/flet-dev/serious-python
version: 4.4.1
version: 4.4.2

platforms:
ios:
Expand Down
4 changes: 4 additions & 0 deletions src/serious_python_android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 4.4.2

* Re-pins the bundled python-build snapshot to **20260727**. Its only functional change is to the iOS frameworks' `Info.plist` (see `serious_python_darwin` 4.4.2); no versions moved and the Android runtime is unchanged from 20260726.

## 4.4.1

* Re-pins the bundled python-build snapshot to **20260726**. Its only functional change is an iOS privacy-manifest fix (see `serious_python_darwin` 4.4.1); no versions moved and the Android runtime is unchanged from 20260725.
Expand Down
2 changes: 1 addition & 1 deletion src/serious_python_android/android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ buildscript {
}

group = "com.flet.serious_python_android"
version = "4.4.1"
version = "4.4.2"

rootProject.allprojects {
repositories {
Expand Down
4 changes: 2 additions & 2 deletions src/serious_python_android/android/python_versions.properties
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# GENERATED by `dart run serious_python:gen_version_tables` from
# python-build manifest.json (release 20260726). Do not edit by hand.
# python-build manifest.json (release 20260727). Do not edit by hand.
default_python_version=3.14
dart_bridge_version=1.6.1
python_build_release_date=20260726
python_build_release_date=20260727
3.12.full_version=3.12.13
3.12.android_abis=arm64-v8a,x86_64,armeabi-v7a
3.13.full_version=3.13.14
Expand Down
2 changes: 1 addition & 1 deletion src/serious_python_android/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: serious_python_android
description: Android implementation of the serious_python plugin
homepage: https://flet.dev
repository: https://github.com/flet-dev/serious-python
version: 4.4.1
version: 4.4.2

environment:
sdk: ">=3.0.0 <4.0.0"
Expand Down
7 changes: 7 additions & 0 deletions src/serious_python_darwin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 4.4.2

* **iOS: framework bundle identifiers are now namespaced under the host app.** Every Python C-extension ships as its own embedded framework, and each carried a fixed `org.python.<module>` `CFBundleIdentifier` — `org.python.ssl`, `org.python.hashlib`, … — byte-identical in every app ever built with serious_python. Set `SERIOUS_PYTHON_BUNDLE_ID` to the app's bundle identifier and they become `com.example.myapp.-ssl` instead, matching what CPython's own iOS support does when it converts a `.so` into a framework. This matters because a framework's bundle identifier also becomes its **code signing identifier**, which is the one field that survives the `codesign -f` Xcode applies at embed and again at `exportArchive`. `Python.framework` is covered too — it was `org.python.python` in every app; nothing resolves it by identifier (the string appears in no shipped binary and there are no `CFBundleGetBundleWithIdentifier` lookups), so the rename is inert at runtime. `dart_bridge.framework` is deliberately left at `dev.flet.dartbridge`, which is already a vendor-owned identifier rather than a shared placeholder. Unset, or set to something that isn't a valid bundle identifier, leaves the old defaults in place and prints a warning. `flet build` supplies it from your app's configured bundle id (flet-dev/flet#6731).
* **iOS: generated frameworks now carry Xcode's build-provenance keys in their `Info.plist`.** Every framework built from a `lib-dynload` `.so` — `_ssl`, `_hashlib`, and the rest — previously shipped ten hand-written keys and not a single `DT*` key, so to Apple's static analysis the bundle didn't look like anything Xcode had produced. They now carry the same key set Xcode stamps into a real framework (`BuildMachineOSBuild`, `DTCompiler`, `DTPlatformBuild`, `DTPlatformName`, `DTPlatformVersion`, `DTSDKBuild`, `DTSDKName`, `DTXcode`, `DTXcodeBuild`, `UIDeviceFamily`, and `UIRequiredDeviceCapabilities` on the device slice), resolved from the SDK the release was built with. The simulator slice is also labelled correctly now — it previously claimed `CFBundleSupportedPlatforms=iPhoneOS`. See flet-dev/python-build#36.
* Both changes above are hypotheses under test for the `ITMS-91065: Missing signature` App Store rejection in flet-dev/flet#6724, **neither is a confirmed fix**. The shared bundle identifier is the stronger of the two: it accounts for every outcome we could find (BeeWare namespaces under the app and has no reports; a third-party OpenSSL xcframework with its own vendor identifier is reported to pass; our `org.python.*` and one other project's independent identifier both draw the rejection). Two further candidates were ruled out experimentally: a signature applied at the source can't matter (re-signing the way `exportArchive` does destroys the certificate chain, team identifier and timestamp, leaving only the identifier string, which is derived from `CFBundleIdentifier` for an unsigned framework anyway), and the privacy manifest can't be the differentiator (a third-party OpenSSL xcframework the App Store accepts ships an empty stub, and our frameworks already carry a manifest — Apple emits no `ITMS-91061` alongside the rejection). The check only fires for new apps, or updates that newly add a listed SDK, so existing published apps are unaffected either way.
* Re-pins the bundled python-build snapshot to **20260727**. No versions moved: Python (**3.12.13 / 3.13.14 / 3.14.6**), Pyodide, and `dart_bridge` **1.6.1** are unchanged from 20260726, and the `Info.plist` change above is the only functional difference on any platform.

## 4.4.1

* **iOS: `_ssl.framework` and `_hashlib.framework` now carry OpenSSL's official privacy manifest.** Both extensions statically link OpenSSL, so Apple's App Store scan identifies them as containing BoringSSL / openssl_grpc — a listed third-party SDK that must declare a privacy manifest. The bundled `PrivacyInfo.xcprivacy` was a stub: `NSPrivacyAccessedAPITypes` was an empty array, and it carried an `NSPrivacyUsesNonStandardAPIs` key that isn't part of Apple's schema. It is now byte-identical to the manifest OpenSSL publishes for its Apple builds, declaring the file-timestamp API access the library actually performs (`NSPrivacyAccessedAPICategoryFileTimestamp`, reason `C617.1`). See flet-dev/python-build#35.
Expand Down
4 changes: 2 additions & 2 deletions src/serious_python_darwin/darwin/python_versions.properties
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# GENERATED by `dart run serious_python:gen_version_tables` from
# python-build manifest.json (release 20260726). Do not edit by hand.
# python-build manifest.json (release 20260727). Do not edit by hand.
default_python_version=3.14
dart_bridge_version=1.6.1
python_build_release_date=20260726
python_build_release_date=20260727
3.12.full_version=3.12.13
3.12.android_abis=arm64-v8a,x86_64,armeabi-v7a
3.13.full_version=3.13.14
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
Pod::Spec.new do |s|
s.name = 'serious_python_darwin'
s.version = '4.4.1'
s.version = '4.4.2'
s.summary = 'A cross-platform plugin for adding embedded Python runtime to your Flutter apps.'
s.description = <<-DESC
A cross-platform plugin for adding embedded Python runtime to your Flutter apps.
Expand Down
18 changes: 18 additions & 0 deletions src/serious_python_darwin/darwin/sync_site_packages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,24 @@ if [[ -n "$SERIOUS_PYTHON_SITE_PACKAGES" && -d "$SERIOUS_PYTHON_SITE_PACKAGES" ]
done
done

# Namespace the frameworks' CFBundleIdentifiers under the host app's
# bundle id (see xcframework_utils.sh). Runs before the reconcile pass
# below, whose ad-hoc re-sign reseals the modified Info.plists. Skipped
# when the caller doesn't supply a bundle id, leaving the org.python.*
# defaults in place.
if [[ -n "${SERIOUS_PYTHON_BUNDLE_ID:-}" ]]; then
echo "Namespacing framework bundle identifiers under $SERIOUS_PYTHON_BUNDLE_ID"
rewrite_framework_bundle_ids "$dist/site-xcframeworks" "$SERIOUS_PYTHON_BUNDLE_ID" || exit 1
# Python.xcframework is staged straight out of dist/xcframeworks by
# stage_spm.sh (and referenced there by the podspec), so it never
# passes through site-xcframeworks above and kept a shared
# `org.python.python`. Nothing resolves it by identifier -- the string
# appears in no binary and there are no CFBundleGetBundleWithIdentifier
# lookups -- so renaming it is inert at runtime. dart_bridge is left
# alone: `dev.flet.dartbridge` is already a vendor-owned identifier.
rewrite_framework_bundle_ids "$dist/xcframeworks" "$SERIOUS_PYTHON_BUNDLE_ID" "dart_bridge" || exit 1
fi

# After every .so/.dylib is framework-ized, reconcile the Mach-O
# install names so the interdependent @rpath refs point at the new
# framework paths (serious-python #223). Without this, dyld cannot
Expand Down
Loading
Loading