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
10 changes: 7 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ jobs:
build_system: ['cocoapods', 'spm']
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
BRIDGE_EXAMPLE_TEST_PYDANTIC: "1"
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
Expand Down Expand Up @@ -124,7 +125,7 @@ jobs:
if [ "${{ matrix.build_system }}" = "cocoapods" ]; then
export SERIOUS_PYTHON_DARWIN_SPM=false
fi
dart run serious_python:main package app/src --platform Darwin --python-version ${{ matrix.python_version }}
dart run serious_python:main package app/src --platform Darwin --python-version ${{ matrix.python_version }} --requirements "pydantic>=2,<3"
if [ "${{ matrix.build_system }}" = "spm" ]; then
export SP_NATIVE_SET="$(cat build/.serious_python_spm_key)"
fi
Expand Down Expand Up @@ -370,6 +371,7 @@ jobs:
python_version: ['3.12', '3.13', '3.14']
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
BRIDGE_EXAMPLE_TEST_PYDANTIC: "1"
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
Expand Down Expand Up @@ -397,7 +399,7 @@ jobs:
working-directory: "src/serious_python/example/bridge_example"
shell: bash
run: |
dart run serious_python:main package app/src --platform Windows --python-version ${{ matrix.python_version }}
dart run serious_python:main package app/src --platform Windows --python-version ${{ matrix.python_version }} --requirements "pydantic>=2,<3"
# bash + pipefail so the test step actually fails when flutter fails
# (default PowerShell shell on windows runners eats the failure when
# piping into tail).
Expand Down Expand Up @@ -446,6 +448,7 @@ jobs:
title: ARM64
env:
SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }}
BRIDGE_EXAMPLE_TEST_PYDANTIC: "1"
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
Expand Down Expand Up @@ -498,7 +501,8 @@ jobs:
flutter pub get
dart run serious_python:main package app/src \
--platform Linux \
--python-version ${{ matrix.python_version }}
--python-version ${{ matrix.python_version }} \
--requirements "pydantic>=2,<3"
set -o pipefail

# Three back-to-back `xvfb-run` invocations race for display
Expand Down
5 changes: 5 additions & 0 deletions src/serious_python/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 6.1.2

* Windows Debug builds (`flutter test`, `flutter run`) use the release CPython, so compiled packages such as `pydantic-core` or `numpy` import there ([#261](https://github.com/flet-dev/serious-python/pull/261), [flet-dev/flet#7020](https://github.com/flet-dev/flet/discussions/7020)).
* Fix native Python extension imports on Linux, including `pydantic-core`, which failed with unresolved CPython symbols such as `PyExc_RecursionError` ([#261](https://github.com/flet-dev/serious-python/pull/261)).

## 6.1.1

* Release Windows apps no longer ship Python's debug modules (`*_d.pyd`), about 10 MB each ([#260](https://github.com/flet-dev/serious-python/pull/260)).
Expand Down
19 changes: 19 additions & 0 deletions src/serious_python/example/bridge_example/app/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,25 @@ def _emit(event: dict) -> None:
dart_bridge.send_bytes(control_port, json.dumps(event).encode("utf-8"))


# Desktop CI packages Pydantic v2 to exercise its native pydantic-core wheel.
# Validate before registering handlers so a failure prevents test readiness.
if os.environ.get("BRIDGE_EXAMPLE_TEST_PYDANTIC") == "1":
try:
from pydantic import BaseModel

class DependencyProbe(BaseModel):
value: int

assert DependencyProbe.model_validate({"value": "42"}).value == 42
print("[bridge_example] Pydantic native extension validation passed", flush=True)
except Exception:
import traceback

# Native stderr is not forwarded by every integration-test runner.
_emit({"event": "startup_error", "message": traceback.format_exc()})
raise


def on_control(payload: bytes) -> None:
global counter
if not payload:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ Future<app.BridgeExampleHandle> bootAndAwaitReady(WidgetTester tester) async {
// readiness signal for the control channel.
final deadline = DateTime.now().add(const Duration(seconds: 30));
while (handle.pythonVersion.value == null) {
if (handle.startupError != null) {
throw StateError('Python startup failed:\n${handle.startupError}');
}
if (DateTime.now().isAfter(deadline)) {
throw TimeoutException(
'Python control handler never responded with version event');
Expand Down
23 changes: 14 additions & 9 deletions src/serious_python/example/bridge_example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ class BridgeExampleHandle {
/// event arrives.
final ValueNotifier<String?> pythonVersion = ValueNotifier<String?>(null);

/// Startup traceback sent over the bridge when a dependency check fails.
String? startupError;

/// Send a JSON control op (Dart → Python) on the control channel.
void sendControl(Map<String, dynamic> op) {
final bytes = Uint8List.fromList(utf8.encode(jsonEncode(op)));
Expand Down Expand Up @@ -72,15 +75,6 @@ void main() {
BridgeExampleHandle._instance =
BridgeExampleHandle._(control, echo);

// Fire-and-forget: Python's main.py blocks forever waiting for messages.
// Awaiting SeriousPython.run() would deadlock the UI.
unawaited(SeriousPython.run(
environmentVariables: {
_controlPortEnv: '${control.port}',
_echoPortEnv: '${echo.port}',
},
));

runApp(const BridgeExampleApp());
}

Expand All @@ -101,6 +95,15 @@ class _BridgeExampleAppState extends State<BridgeExampleApp> {
final handle = BridgeExampleHandle.instance;
_controlSub = handle.controlBridge.messages.listen(_onControl);

// Subscribe before starting Python so even an immediate startup failure
// reaches the test harness. main.py blocks forever, so don't await it.
unawaited(SeriousPython.run(
environmentVariables: {
_controlPortEnv: '${handle.controlBridge.port}',
_echoPortEnv: '${handle.echoBridge.port}',
},
));

// Request the Python version once Python has had a moment to register
// its handler. sendControl() retries internally if the handler isn't
// ready yet, so we can fire immediately.
Expand All @@ -123,6 +126,8 @@ class _BridgeExampleAppState extends State<BridgeExampleApp> {
handle.counter.value = msg['value'] as int;
} else if (event == 'version') {
handle.pythonVersion.value = msg['value'] as String;
} else if (event == 'startup_error') {
handle.startupError = msg['message'] as String;
}
// 'mem' events are consumed by the memory test directly via its own
// listener — no widget-visible state for them.
Expand Down
12 changes: 6 additions & 6 deletions src/serious_python/example/flask_example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -361,42 +361,42 @@ packages:
path: "../.."
relative: true
source: path
version: "6.1.1"
version: "6.1.2"
serious_python_android:
dependency: transitive
description:
path: "../../../serious_python_android"
relative: true
source: path
version: "6.1.1"
version: "6.1.2"
serious_python_darwin:
dependency: transitive
description:
path: "../../../serious_python_darwin"
relative: true
source: path
version: "6.1.1"
version: "6.1.2"
serious_python_linux:
dependency: transitive
description:
path: "../../../serious_python_linux"
relative: true
source: path
version: "6.1.1"
version: "6.1.2"
serious_python_platform_interface:
dependency: transitive
description:
path: "../../../serious_python_platform_interface"
relative: true
source: path
version: "6.1.1"
version: "6.1.2"
serious_python_windows:
dependency: transitive
description:
path: "../../../serious_python_windows"
relative: true
source: path
version: "6.1.1"
version: "6.1.2"
shelf:
dependency: transitive
description:
Expand Down
12 changes: 6 additions & 6 deletions src/serious_python/example/run_example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -384,42 +384,42 @@ packages:
path: "../.."
relative: true
source: path
version: "6.1.1"
version: "6.1.2"
serious_python_android:
dependency: transitive
description:
path: "../../../serious_python_android"
relative: true
source: path
version: "6.1.1"
version: "6.1.2"
serious_python_darwin:
dependency: transitive
description:
path: "../../../serious_python_darwin"
relative: true
source: path
version: "6.1.1"
version: "6.1.2"
serious_python_linux:
dependency: transitive
description:
path: "../../../serious_python_linux"
relative: true
source: path
version: "6.1.1"
version: "6.1.2"
serious_python_platform_interface:
dependency: transitive
description:
path: "../../../serious_python_platform_interface"
relative: true
source: path
version: "6.1.1"
version: "6.1.2"
serious_python_windows:
dependency: transitive
description:
path: "../../../serious_python_windows"
relative: true
source: path
version: "6.1.1"
version: "6.1.2"
shelf:
dependency: transitive
description:
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: 6.1.1
version: 6.1.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 @@
## 6.1.2

* Align with the serious_python **6.1.2** release ([#261](https://github.com/flet-dev/serious-python/pull/261)).

## 6.1.1

* Align with the serious_python **6.1.1** release ([#260](https://github.com/flet-dev/serious-python/pull/260)).
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 = "6.1.1"
version = "6.1.2"

rootProject.allprojects {
repositories {
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: 6.1.1
version: 6.1.2

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

* Align with the serious_python **6.1.2** release ([#261](https://github.com/flet-dev/serious-python/pull/261)).

## 6.1.1

* Align with the serious_python **6.1.1** release ([#260](https://github.com/flet-dev/serious-python/pull/260)).
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 = '6.1.1'
s.version = '6.1.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
2 changes: 1 addition & 1 deletion src/serious_python_darwin/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: serious_python_darwin
description: iOS and macOS implementations of the serious_python plugin
homepage: https://flet.dev
repository: https://github.com/flet-dev/serious-python
version: 6.1.1
version: 6.1.2

environment:
# The Swift Package Manager build path needs Flutter 3.44 / Dart 3.11 (the
Expand Down
4 changes: 4 additions & 0 deletions src/serious_python_linux/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 6.1.2

* Fix native Python extension imports, including `pydantic-core`, which failed with unresolved CPython symbols such as `PyExc_RecursionError` ([#261](https://github.com/flet-dev/serious-python/pull/261)).

## 6.1.1

* Align with the serious_python **6.1.1** release ([#260](https://github.com/flet-dev/serious-python/pull/260)).
Expand Down
2 changes: 1 addition & 1 deletion src/serious_python_linux/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: serious_python_linux
description: Linux implementations of the serious_python plugin
homepage: https://flet.dev
repository: https://github.com/flet-dev/serious-python
version: 6.1.1
version: 6.1.2

environment:
sdk: '>=3.1.3 <4.0.0'
Expand Down
5 changes: 5 additions & 0 deletions src/serious_python_platform_interface/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 6.1.2

* On Windows, open `dart_bridge.dll` in Debug builds too, instead of `dart_bridge_d.dll` ([#261](https://github.com/flet-dev/serious-python/pull/261), [flet-dev/flet#7020](https://github.com/flet-dev/flet/discussions/7020)).
* On Linux, load the bridge and its CPython dependencies with global symbol visibility so native Python extension wheels can resolve the CPython API ([#261](https://github.com/flet-dev/serious-python/pull/261)).

## 6.1.1

* Align with the serious_python **6.1.1** release ([#260](https://github.com/flet-dev/serious-python/pull/260)).
Expand Down
Loading
Loading