Skip to content
Merged
6 changes: 5 additions & 1 deletion docs/dedicated-data-channels.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,11 @@ def _pump(self):
Real parallelism comes from C extensions that **release the GIL during
their work** — NumPy, PyTorch, Pillow, cryptography. Pure-Python CPU work
serialises on the GIL; for that, use `multiprocessing` or
PEP 684 subinterpreters.
PEP 684 subinterpreters. Caveat: `multiprocessing` works in the embedded
runtime only on **desktop** hosts whose binary services the spawn re-exec
protocol via `serious_python_main` (dart_bridge >= 1.5.0, flet >= 0.86 build
template); it is not available on iOS/Android, where the OS forbids spawning
child processes.

### Dart side — Isolate scope

Expand Down
3 changes: 3 additions & 0 deletions src/serious_python/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## 4.3.0

* **Desktop multiprocessing support** ([flet-dev/flet#4283](https://github.com/flet-dev/flet/issues/4283)). `dart_bridge` **1.5.0** adds `serious_python_is_mp_invocation` / `serious_python_main` (+ `_w` wide-char variants on Windows): host apps call them first thing in `main` to detect CPython child command lines (`--multiprocessing-fork`, `-c "from multiprocessing..."` — spawn workers, the resource tracker, and the forkserver) and service them as a plain headless interpreter (`Py_Main`/`Py_BytesMain`, stable ABI) instead of re-launching the GUI. The exports rely on the `PYTHONHOME`/`PYTHONPATH` the parent already stamped process-wide.
* `PYTHONINSPECT=1` is no longer set by any platform implementation. It had no effect on the embedded interpreter, but it leaked into the process environment where any *real* interpreter child (e.g. a serviced multiprocessing worker) would inherit it and hang in interactive mode after its command completed.
* Bump the bundled python-build snapshot to `20260708`, which delivers `dart_bridge` **1.5.0**; Pyodide for 3.14 bumped **314.0.1 → 314.0.2**. Bundled Python versions are unchanged from 4.2.1 (**3.12.13 / 3.13.14 / 3.14.6**).
* **Windows:** fix `flet build windows` failing with `file INSTALL cannot find "C:/WINDOWS/System32/vcruntime140_1.dll"` for users who build with VS Build Tools rather than full Visual Studio (a WOW64 file-system-redirection issue with the bundled 32-bit cmake). See `serious_python_windows` 4.3.0.

## 4.2.1
Expand Down
8 changes: 4 additions & 4 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 20260701). Do not edit by hand — edit python-build's
// manifest.json (release 20260708). 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,8 +10,8 @@ const pyodideVersionEnvironmentVariable = "SERIOUS_PYTHON_PYODIDE_VERSION";
const dartBridgeVersionEnvironmentVariable = "DART_BRIDGE_VERSION";

/// python-build release the bundled runtimes come from (YYYYMMDD).
const pythonReleaseDate = "20260701";
const dartBridgeVersion = "1.4.1";
const pythonReleaseDate = "20260708";
const dartBridgeVersion = "1.5.0";
const defaultPythonVersion = "3.14";

class PythonRelease {
Expand Down Expand Up @@ -56,7 +56,7 @@ const pythonReleases = <String, PythonRelease>{
"3.14": PythonRelease(
standaloneVersion: "3.14.6",
standaloneReleaseDate: "20260623",
pyodideVersion: "314.0.1",
pyodideVersion: "314.0.2",
pyodidePlatformTag: "pyemscripten-2026.0-wasm32",
androidAbis: ["arm64-v8a", "x86_64", "armeabi-v7a"],
prerelease: false,
Expand Down
3 changes: 2 additions & 1 deletion src/serious_python_android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## 4.3.0

* Version bump aligning with the `serious_python_*` 4.3.0 release.
* `PYTHONINSPECT=1` is no longer set by any platform implementation. It had no effect on the embedded interpreter, but it leaked into the process environment where any *real* interpreter child (e.g. a serviced multiprocessing worker) would inherit it and hang in interactive mode after its command completed. No functional change on Android, which doesn't support process spawning.
* Bump the bundled python-build snapshot to `20260708` (`dart_bridge` **1.5.0**). The new multiprocessing child-interception exports are present in the runtime but not wired up on Android, which doesn't support process spawning.

## 4.2.1

Expand Down
6 changes: 3 additions & 3 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 20260701). Do not edit by hand.
# python-build manifest.json (release 20260708). Do not edit by hand.
default_python_version=3.14
dart_bridge_version=1.4.1
python_build_release_date=20260701
dart_bridge_version=1.5.0
python_build_release_date=20260708
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
1 change: 0 additions & 1 deletion src/serious_python_android/lib/serious_python_android.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ class SeriousPythonAndroid extends SeriousPythonPlatform {
}

final env = <String, String>{
'PYTHONINSPECT': '1',
'PYTHONDONTWRITEBYTECODE': '1',
'PYTHONNOUSERSITE': '1',
'PYTHONUNBUFFERED': '1',
Expand Down
4 changes: 3 additions & 1 deletion src/serious_python_darwin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## 4.3.0

* Version bump aligning with the `serious_python_*` 4.3.0 release.
* Bump `dart_bridge` to **1.5.0** (python-build snapshot `20260708`): multiprocessing child-interception exports (`serious_python_is_mp_invocation` / `serious_python_main`), kept alive against the host link's `-dead_strip` both by `__attribute__((used))` in the archive and by keep-alive references in `SeriousPythonPlugin.swift`. See the `serious_python` 4.3.0 notes.
* `prepare_macos.sh` / `prepare_ios.sh`: the extracted `dart_bridge.xcframework` in `dist_*` is now keyed to the dart_bridge version (`.dart_bridge_version` marker) — previously a version bump kept staging the stale extraction from the earlier version.
* `PYTHONINSPECT=1` is no longer set by any platform implementation. It had no effect on the embedded interpreter, but it leaked into the process environment where any *real* interpreter child (e.g. a serviced multiprocessing worker) would inherit it and hang in interactive mode after its command completed.

## 4.2.1

Expand Down
14 changes: 9 additions & 5 deletions src/serious_python_darwin/darwin/prepare_ios.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ cache_root="${FLET_CACHE_DIR:-$HOME/.flet/cache}"
# date — e.g. a rebuild that only re-signs binaries) downloads fresh instead of
# being served stale from the previous release's cache. dart-bridge stays
# version-keyed (its re-releases bump the version).
pb_cache="$cache_root/python-build/v$python_full_version-$python_build_date"
pb_id="$python_full_version-$python_build_date"
pb_cache="$cache_root/python-build/v$pb_id"
db_cache="$cache_root/dart-bridge/v$dart_bridge_version"
mkdir -p "$pb_cache" "$db_cache"

Expand All @@ -34,14 +35,13 @@ fi
# 3.14 site-packages, which trips C-extension ABI errors ("unknown slot ID") at
# import. The marker keys the extracted dist to the version + release date, so a
# same-version re-release (new build date) also re-extracts.
build_id="$python_full_version-$python_build_date"
marker="$dist/.python_build_id"
if [ ! -d "$dist" ] || [ "$(cat "$marker" 2>/dev/null)" != "$build_id" ]; then
if [ ! -d "$dist" ] || [ "$(cat "$marker" 2>/dev/null)" != "$pb_id" ]; then
rm -rf "$dist"
mkdir -p "$dist"
tar -xzf "$python_ios_dist_path" -C "$dist"
mv "$dist/python-stdlib" "$dist/stdlib"
echo "$build_id" > "$marker"
echo "$pb_id" > "$marker"
fi

# ---- flet-dev/dart-bridge (xcframework) -----------------------------------
Expand All @@ -55,7 +55,11 @@ if [ ! -f "$dart_bridge_path" ]; then
mv "$dart_bridge_path.tmp" "$dart_bridge_path"
fi

if [ ! -d "$dist/xcframeworks/dart_bridge.xcframework" ]; then
# Cache dart_bridge.xcframework by version; extract it if missing or if the version marker differs.
db_marker="$dist/xcframeworks/.dart_bridge_version"
if [ ! -d "$dist/xcframeworks/dart_bridge.xcframework" ] || [ "$(cat "$db_marker" 2>/dev/null)" != "$dart_bridge_version" ]; then
rm -rf "$dist/xcframeworks/dart_bridge.xcframework"
mkdir -p "$dist/xcframeworks"
unzip -q "$dart_bridge_path" -d "$dist/xcframeworks/"
echo "$dart_bridge_version" > "$db_marker"
fi
14 changes: 9 additions & 5 deletions src/serious_python_darwin/darwin/prepare_macos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ cache_root="${FLET_CACHE_DIR:-$HOME/.flet/cache}"
# date — e.g. a rebuild that only re-signs binaries) downloads fresh instead of
# being served stale from the previous release's cache. dart-bridge stays
# version-keyed (its re-releases bump the version).
pb_cache="$cache_root/python-build/v$python_full_version-$python_build_date"
pb_id="$python_full_version-$python_build_date"
pb_cache="$cache_root/python-build/v$pb_id"
db_cache="$cache_root/dart-bridge/v$dart_bridge_version"
mkdir -p "$pb_cache" "$db_cache"

Expand All @@ -36,9 +37,8 @@ fi
# 3.14 site-packages, which trips C-extension ABI errors ("unknown slot ID") at
# import. The marker keys the extracted dist to the version + release date, so a
# same-version re-release (new build date) also re-extracts.
build_id="$python_full_version-$python_build_date"
marker="$dist/.python_build_id"
if [ ! -d "$dist" ] || [ "$(cat "$marker" 2>/dev/null)" != "$build_id" ]; then
if [ ! -d "$dist" ] || [ "$(cat "$marker" 2>/dev/null)" != "$pb_id" ]; then
rm -rf "$dist"
mkdir -p "$dist"
tar -xzf "$python_macos_dist_path" -C "$dist"
Expand All @@ -54,7 +54,7 @@ if [ ! -d "$dist" ] || [ "$(cat "$marker" 2>/dev/null)" != "$build_id" ]; then
# unexpectedly" crash dialog. We don't need this launcher for embedded
# use; libdart_bridge dlopens Python.framework's main binary directly.
find "$dist/xcframeworks" -type d -name 'Python.app' -prune -exec rm -rf {} +
echo "$build_id" > "$marker"
echo "$pb_id" > "$marker"
fi

# ---- flet-dev/dart-bridge (xcframework, same archive for macOS + iOS) -----
Expand All @@ -68,7 +68,11 @@ if [ ! -f "$dart_bridge_path" ]; then
mv "$dart_bridge_path.tmp" "$dart_bridge_path"
fi

if [ ! -d "$dist/xcframeworks/dart_bridge.xcframework" ]; then
# Cache dart_bridge.xcframework by version; extract it if missing or if the version marker differs.
db_marker="$dist/xcframeworks/.dart_bridge_version"
if [ ! -d "$dist/xcframeworks/dart_bridge.xcframework" ] || [ "$(cat "$db_marker" 2>/dev/null)" != "$dart_bridge_version" ]; then
rm -rf "$dist/xcframeworks/dart_bridge.xcframework"
mkdir -p "$dist/xcframeworks"
unzip -q "$dart_bridge_path" -d "$dist/xcframeworks/"
echo "$dart_bridge_version" > "$db_marker"
fi
6 changes: 3 additions & 3 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 20260701). Do not edit by hand.
# python-build manifest.json (release 20260708). Do not edit by hand.
default_python_version=3.14
dart_bridge_version=1.4.1
python_build_release_date=20260701
dart_bridge_version=1.5.0
python_build_release_date=20260708
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 @@ -16,6 +16,17 @@ private func _sp_init_keepalive(_ data: UnsafeMutableRawPointer?) -> Int
@_silgen_name("DartBridge_EnqueueMessage")
private func _sp_enqueue_keepalive(_ data: UnsafePointer<CChar>?, _ len: Int)

// multiprocessing child-interception entry points,
// dlsym'd by the host app's main.swift before NSApplicationMain.
@_silgen_name("serious_python_is_mp_invocation")
private func _sp_is_mp_keepalive(
_ argc: Int32, _ argv: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>?
) -> Int32
@_silgen_name("serious_python_main")
private func _sp_main_keepalive(
_ argc: Int32, _ argv: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>?
) -> Int32

/// Thin Flutter plugin: surfaces the python.bundle resource path to Dart.
/// All Python lifecycle now lives in `serious_python_run`
/// (dart_bridge.xcframework), invoked from Dart.
Expand All @@ -39,6 +50,8 @@ public class SeriousPythonPlugin: NSObject, FlutterPlugin {
_ = _sp_run_keepalive(nil)
_ = _sp_init_keepalive(nil)
_sp_enqueue_keepalive(nil, 0)
_ = _sp_is_mp_keepalive(0, nil)
_ = _sp_main_keepalive(0, nil)
}
}

Expand Down
1 change: 0 additions & 1 deletion src/serious_python_darwin/lib/serious_python_darwin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ class SeriousPythonDarwin extends SeriousPythonPlatform {
];

final env = <String, String>{
'PYTHONINSPECT': '1',
'PYTHONDONTWRITEBYTECODE': '1',
'PYTHONNOUSERSITE': '1',
'PYTHONUNBUFFERED': '1',
Expand Down
3 changes: 2 additions & 1 deletion src/serious_python_linux/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## 4.3.0

* Version bump aligning with the `serious_python_*` 4.3.0 release.
* Bump `dart_bridge` to **1.5.0** (python-build snapshot `20260708`): multiprocessing child-interception exports (`serious_python_is_mp_invocation` / `serious_python_main`), consumed by the flet build template's `main.cc` via `dlopen("libdart_bridge.so")`. Relevant on Linux since Python 3.14 made `forkserver` (which execs `sys.executable`) the default start method. See the `serious_python` 4.3.0 notes.
* `PYTHONINSPECT=1` is no longer set by any platform implementation. It had no effect on the embedded interpreter, but it leaked into the process environment where any *real* interpreter child (e.g. a serviced multiprocessing worker) would inherit it and hang in interactive mode after its command completed.

## 4.2.1

Expand Down
1 change: 0 additions & 1 deletion src/serious_python_linux/lib/serious_python_linux.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ class SeriousPythonLinux extends SeriousPythonPlatform {
];

final env = <String, String>{
'PYTHONINSPECT': '1',
'PYTHONDONTWRITEBYTECODE': '1',
'PYTHONNOUSERSITE': '1',
'PYTHONUNBUFFERED': '1',
Expand Down
6 changes: 3 additions & 3 deletions src/serious_python_linux/linux/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 20260701). Do not edit by hand.
# python-build manifest.json (release 20260708). Do not edit by hand.
default_python_version=3.14
dart_bridge_version=1.4.1
python_build_release_date=20260701
dart_bridge_version=1.5.0
python_build_release_date=20260708
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: 2 additions & 0 deletions src/serious_python_windows/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## 4.3.0

* Bump `dart_bridge` to **1.5.0** (python-build snapshot `20260708`): multiprocessing child-interception exports, including the Windows wide-char variants `serious_python_is_mp_invocation_w` / `serious_python_main_w` (→ `Py_Main`) consumed by the flet build template's `wWinMain`. See the `serious_python` 4.3.0 notes.
* `PYTHONINSPECT=1` is no longer set by any platform implementation. It had no effect on the embedded interpreter, but it leaked into the process environment where any *real* interpreter child (e.g. a serviced multiprocessing worker) would inherit it and hang in interactive mode after its command completed.
* **Fix `flet build windows` failing with `file INSTALL cannot find "C:/WINDOWS/System32/vcruntime140_1.dll"`** for users who have VS Build Tools installed rather than full Visual Studio. The plugin harvests the CRT runtime DLLs (`msvcp140.dll` / `vcruntime140.dll` / `vcruntime140_1.dll`) from `%WINDIR%\System32`, but Flutter drives the CMake install step with the **32-bit** `cmake.exe` bundled in VS Build Tools. Under WOW64 file-system redirection that process sees `System32` transparently rewritten to `SysWOW64`, which holds the x86 CRT and doesn't contain `vcruntime140_1.dll` at all — so the x64 build copied wrong-arch DLLs and then failed. The CRT directory is now resolved via the `Sysnative` pseudo-folder (visible only to 32-bit processes, mapping back to the real 64-bit `System32`) when present, falling back to `System32` for native 64-bit cmake. See flet-dev/flet#6436.

## 4.2.1
Expand Down
1 change: 0 additions & 1 deletion src/serious_python_windows/lib/serious_python_windows.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ class SeriousPythonWindows extends SeriousPythonPlatform {
];

final env = <String, String>{
'PYTHONINSPECT': '1',
'PYTHONDONTWRITEBYTECODE': '1',
'PYTHONNOUSERSITE': '1',
'PYTHONUNBUFFERED': '1',
Expand Down
6 changes: 3 additions & 3 deletions src/serious_python_windows/windows/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 20260701). Do not edit by hand.
# python-build manifest.json (release 20260708). Do not edit by hand.
default_python_version=3.14
dart_bridge_version=1.4.1
python_build_release_date=20260701
dart_bridge_version=1.5.0
python_build_release_date=20260708
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
Loading