diff --git a/CHANGELOG.md b/CHANGELOG.md index f5099208ec..60e3d038d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Bug fixes * Fix `flet-geolocator.Geolocator` reliability on web and desktop: `get_last_known_position()` no longer crashes with `TypeError: argument after ** must be a mapping, not NoneType` and now returns `Optional[GeolocatorPosition]`; `get_current_position()` no longer hangs forever on web (Dart-side workaround for the upstream [`geolocator_web` 4.1.3](https://pub.dev/packages/geolocator_web) `inMicroseconds`/`inMilliseconds` timeout typo) and uses sensible web defaults (`time_limit: 30s`, `maximum_age: 5m`); the previously-dropped `configuration` argument now actually reaches `getCurrentPosition` on the Dart side; the position stream is gated behind a registered `on_position_change`/`on_error` handler (with cancel-on-update to prevent leaks); and platform exceptions (`LocationServiceDisabledException`, `PermissionDeniedException`, `PermissionDefinitionsNotFoundException`, `PermissionRequestInProgressException`, `PositionUpdateException`, `TimeoutException`) are now translated into actionable error messages and surfaced to Python as `RuntimeError` without the default `Exception:` prefix ([#6487](https://github.com/flet-dev/flet/pull/6487)) by @FeodorFitsner. +* Fix PEP 508 markers on `flet`'s `oauthlib`/`httpx` deps not actually excluding those packages under Pyodide: the `flet build web` package platform has been renamed from `Pyodide` to `Emscripten` to match `platform.system()` inside the Pyodide runtime, and the markers now use `platform_system != 'Emscripten'`, so the exclusion works both via `flet build` and a direct `micropip.install("flet")` in a Pyodide REPL. Requires `serious_python` `>= 1.0.0`, which is now pinned in the `flet build` template ([#6492](https://github.com/flet-dev/flet/pull/6492)) by @FeodorFitsner. ## 0.85.0 diff --git a/client/web/python-worker.js b/client/web/python-worker.js index 8df242310b..40c6083afc 100644 --- a/client/web/python-worker.js +++ b/client/web/python-worker.js @@ -149,23 +149,27 @@ self.initPyodide = async function () { micropip = await ensure_micropip() await micropip.install(py_args["dependencies"], pre=micropip_include_pre) - # Install the python_output bridge using msgpack from the - # already-loaded user deps (typically pulled in via flet). If - # msgpack isn't around — apps that don't depend on flet — skip - # silently; stdout/stderr just stays in the dev console. + # Install the python_output bridge. msgpack normally rides in + # with the user's flet dependency, but apps without a flet dep + # (or without a pyproject.toml at all) would otherwise leave the + # bridge unregistered and their prints stranded in the dev + # console. Pyodide ships msgpack as a prebuilt package, so we + # load it explicitly when it isn't already importable. try: import msgpack as _msgpack + except ImportError: + import pyodide_js + await pyodide_js.loadPackage("msgpack") + import msgpack as _msgpack - def _send_python_output(text, is_stderr): - flet_js.receive_callback( - _msgpack.packb( - [7, {"text": text, "is_stderr": bool(is_stderr)}] - ) + def _send_python_output(text, is_stderr): + flet_js.receive_callback( + _msgpack.packb( + [7, {"text": text, "is_stderr": bool(is_stderr)}] ) + ) - flet_js.send_python_output = _send_python_output - except ImportError: - pass + flet_js.send_python_output = _send_python_output # Flip the worker into "user code" mode so stdout/stderr starts # flowing to the host page's Console pane instead of dev console. diff --git a/sdk/python/examples/apps/declarative/use_dialog_basic/main.py b/sdk/python/examples/apps/declarative/use_dialog_basic/main.py index 7755320678..59df7b72ea 100644 --- a/sdk/python/examples/apps/declarative/use_dialog_basic/main.py +++ b/sdk/python/examples/apps/declarative/use_dialog_basic/main.py @@ -53,5 +53,9 @@ async def handle_delete(): ) +def main(page: ft.Page): + page.render(App) + + if __name__ == "__main__": - ft.run(lambda page: page.render(App)) + ft.run(main) diff --git a/sdk/python/examples/apps/declarative/use_dialog_chained/main.py b/sdk/python/examples/apps/declarative/use_dialog_chained/main.py index 553e57465b..c16b2aa30e 100644 --- a/sdk/python/examples/apps/declarative/use_dialog_chained/main.py +++ b/sdk/python/examples/apps/declarative/use_dialog_chained/main.py @@ -78,5 +78,9 @@ def on_confirm_dismiss(): ) +def main(page: ft.Page): + page.render(App) + + if __name__ == "__main__": - ft.run(lambda page: page.render(App)) + ft.run(main) diff --git a/sdk/python/examples/apps/declarative/use_dialog_multiple/main.py b/sdk/python/examples/apps/declarative/use_dialog_multiple/main.py index 39d845975a..a6ff382560 100644 --- a/sdk/python/examples/apps/declarative/use_dialog_multiple/main.py +++ b/sdk/python/examples/apps/declarative/use_dialog_multiple/main.py @@ -145,5 +145,9 @@ def handler(): ) +def main(page: ft.Page): + page.render(App) + + if __name__ == "__main__": - ft.run(lambda page: page.render(App)) + ft.run(main) diff --git a/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py b/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py index 29bff9fd2c..29faa3ab1f 100644 --- a/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py +++ b/sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py @@ -95,7 +95,7 @@ def __init__(self, parser: argparse.ArgumentParser) -> None: "can_be_run_on": ["Linux"], }, "web": { - "package_platform": "Pyodide", + "package_platform": "Emscripten", "config_platform": "web", "flutter_build_command": "web", "status_text": "web app", @@ -1833,7 +1833,7 @@ def package_python_app(self): package_args.extend(["-r", f"flet=={flet.version.flet_version}"]) # site-packages variable - if self.package_platform != "Pyodide": + if self.package_platform != "Emscripten": package_env["SERIOUS_PYTHON_SITE_PACKAGES"] = str( self.build_dir / "site-packages" ) @@ -2043,12 +2043,12 @@ def _run_flutter_command(self): build_env = {} # site-packages variable - if self.package_platform != "Pyodide": + if self.package_platform != "Emscripten": build_env["SERIOUS_PYTHON_SITE_PACKAGES"] = str( self.build_dir / "site-packages" ) - if self.package_platform == "Pyodide" and not self.template_data["no_wasm"]: + if self.package_platform == "Emscripten" and not self.template_data["no_wasm"]: build_args.append("--wasm") android_signing_key_store = ( diff --git a/sdk/python/packages/flet/pyproject.toml b/sdk/python/packages/flet/pyproject.toml index a54bf04509..c6a20b80f2 100644 --- a/sdk/python/packages/flet/pyproject.toml +++ b/sdk/python/packages/flet/pyproject.toml @@ -9,8 +9,8 @@ requires-python = ">=3.10" dependencies = [ "flet-cli; extra == 'cli'", "flet-web; extra == 'web'", - "oauthlib >=3.2.2; platform_system != 'Pyodide'", - "httpx >=0.28.1; platform_system != 'Pyodide'", + "oauthlib >=3.2.2; platform_system != 'Emscripten'", + "httpx >=0.28.1; platform_system != 'Emscripten'", "repath >=0.9.0", "msgpack >=1.1.0", "typing-extensions; python_version < '3.11'" diff --git a/sdk/python/templates/build/{{cookiecutter.out_dir}}/pubspec.yaml b/sdk/python/templates/build/{{cookiecutter.out_dir}}/pubspec.yaml index e3439b98d0..8046108d96 100644 --- a/sdk/python/templates/build/{{cookiecutter.out_dir}}/pubspec.yaml +++ b/sdk/python/templates/build/{{cookiecutter.out_dir}}/pubspec.yaml @@ -17,7 +17,7 @@ dependencies: flet: path: ../../../../../packages/flet - serious_python: 0.9.12 + serious_python: 1.0.0 package_info_plus: ^9.0.0 path_provider: ^2.1.4 diff --git a/sdk/python/templates/build/{{cookiecutter.out_dir}}/web/python-worker.js b/sdk/python/templates/build/{{cookiecutter.out_dir}}/web/python-worker.js index 8df242310b..40c6083afc 100644 --- a/sdk/python/templates/build/{{cookiecutter.out_dir}}/web/python-worker.js +++ b/sdk/python/templates/build/{{cookiecutter.out_dir}}/web/python-worker.js @@ -149,23 +149,27 @@ self.initPyodide = async function () { micropip = await ensure_micropip() await micropip.install(py_args["dependencies"], pre=micropip_include_pre) - # Install the python_output bridge using msgpack from the - # already-loaded user deps (typically pulled in via flet). If - # msgpack isn't around — apps that don't depend on flet — skip - # silently; stdout/stderr just stays in the dev console. + # Install the python_output bridge. msgpack normally rides in + # with the user's flet dependency, but apps without a flet dep + # (or without a pyproject.toml at all) would otherwise leave the + # bridge unregistered and their prints stranded in the dev + # console. Pyodide ships msgpack as a prebuilt package, so we + # load it explicitly when it isn't already importable. try: import msgpack as _msgpack + except ImportError: + import pyodide_js + await pyodide_js.loadPackage("msgpack") + import msgpack as _msgpack - def _send_python_output(text, is_stderr): - flet_js.receive_callback( - _msgpack.packb( - [7, {"text": text, "is_stderr": bool(is_stderr)}] - ) + def _send_python_output(text, is_stderr): + flet_js.receive_callback( + _msgpack.packb( + [7, {"text": text, "is_stderr": bool(is_stderr)}] ) + ) - flet_js.send_python_output = _send_python_output - except ImportError: - pass + flet_js.send_python_output = _send_python_output # Flip the worker into "user code" mode so stdout/stderr starts # flowing to the host page's Console pane instead of dev console.