From 96ce39af18ae05aecd10d29d495206931ee19441 Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Thu, 29 Oct 2026 00:57:53 +0100 Subject: [PATCH 1/4] Report Python startup errors in flet test When the app's Python program failed before connecting, such as an import error, the build template reported it only on the boot screen's status. `waitForAppLoaded` checked only `FletBackend.error`, so `flet test` waited out its two-minute timeout and failed with "The app did not load its first page", without the traceback. `waitForAppLoaded` now also checks the backend's boot status and fails right away with the error text, so the test output includes the Python traceback. --- CHANGELOG.md | 2 +- .../lib/src/app_startup.dart | 10 ++++++++++ .../test/app_startup_test.dart | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9cf707de8..c20cf17013 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,7 +66,7 @@ * Fix `FilePicker` dialogs failing with a timeout after being open for an hour ([#6999](https://github.com/flet-dev/flet/pull/6999)) by @ndonkoHenri. * Fix `flet build` failing on every rebuild after one with changed build options, in apps with Flutter extensions ([#7010](https://github.com/flet-dev/flet/issues/7010), [#7012](https://github.com/flet-dev/flet/pull/7012)) by @ndonkoHenri. * Fix `flet build` not reinstalling the app's packages after `requirements.txt` is edited or `build/site-packages` is deleted ([#6994](https://github.com/flet-dev/flet/issues/6994), [#6996](https://github.com/flet-dev/flet/pull/6996)) by @ndonkoHenri. -* Fix `flet test` failing when the app under test starts slowly, as on the first run after a build: the test now waits until the app finishes initializing its first page ([#6993](https://github.com/flet-dev/flet/issues/6993), [#6995](https://github.com/flet-dev/flet/pull/6995)) by @ndonkoHenri. +* Fix `flet test` failing when the app under test starts slowly, as on the first run after a build: the test now waits until the app finishes initializing its first page, and fails right away with the Python traceback when the app's Python program fails to start ([#6993](https://github.com/flet-dev/flet/issues/6993), [#6995](https://github.com/flet-dev/flet/pull/6995)) by @ndonkoHenri. * Fix `use_effect()` cleanups being skipped: a cleanup returned by the setup was lost once the component re-rendered, only one ran when `cleanup=` was passed too, and `async` cleanups never ran when a dependency change re-ran the effect. A pending `async` setup is also cancelled on unmount ([#6963](https://github.com/flet-dev/flet/issues/6963), [#6983](https://github.com/flet-dev/flet/pull/6983), [#7005](https://github.com/flet-dev/flet/pull/7005)) by @mangod12. * iOS apps built with `flet build ipa` no longer fail App Store Connect validation with ITMS-90683 (missing `NSPhotoLibraryUsageDescription` and `NSCameraUsageDescription` purpose strings): the `file_picker` plugin is updated to 13.x, which picks photos with the system photo picker and no longer links DKImagePickerController's camera and photo-library code. `device_info_plus`, `package_info_plus` and `share_plus` move to their next major versions with it (`win32` 6). `FilePicker.save_file()` on desktop now creates the chosen file (empty when no `src_bytes` are given) before returning its path by @FeodorFitsner. * Fix `Tester.find_by_key()` not finding `Tab` and `PopupMenuItem` controls by their keys ([#6965](https://github.com/flet-dev/flet/issues/6965), [#6976](https://github.com/flet-dev/flet/pull/6976)) by @RezaShamsipour. diff --git a/packages/flet_integration_test/lib/src/app_startup.dart b/packages/flet_integration_test/lib/src/app_startup.dart index 9b33b0b6ad..898a82f3da 100644 --- a/packages/flet_integration_test/lib/src/app_startup.dart +++ b/packages/flet_integration_test/lib/src/app_startup.dart @@ -9,12 +9,22 @@ import 'package:flutter_test/flutter_test.dart'; /// the first launch after a build, when antivirus software scans the bundle, /// so a fixed number of frames is not enough. Throws when the app reports a /// startup error or has not loaded within [timeout]. +/// +/// A startup error includes the embedded Python program failing before it +/// connects, such as an exception raised while importing the app's modules. +/// The app reports that on its boot screen rather than through the Flet +/// protocol, so the thrown exception carries the boot screen's error text, +/// including the Python traceback. Future waitForAppLoaded(WidgetTester tester, {Duration timeout = const Duration(minutes: 2)}) async { final deadline = tester.binding.clock.now().add(timeout); while (true) { await tester.pump(const Duration(milliseconds: 100)); final backend = _findFletBackend(tester); + final bootError = backend?.bootStatus.value.error; + if (bootError != null && bootError.isNotEmpty) { + throw Exception("The app failed to start:\n$bootError"); + } if (backend != null && !backend.isLoading) { if (backend.error.isNotEmpty) { throw Exception("The app failed to start: ${backend.error}"); diff --git a/packages/flet_integration_test/test/app_startup_test.dart b/packages/flet_integration_test/test/app_startup_test.dart index 7863624774..60b1359780 100644 --- a/packages/flet_integration_test/test/app_startup_test.dart +++ b/packages/flet_integration_test/test/app_startup_test.dart @@ -74,6 +74,22 @@ void main() { contains('Initialization failed')))); }); + testWidgets('a Python program that fails to start fails with its traceback', + (tester) async { + final backend = await _mountApp(tester); + // The embedded Python program exits before it connects, so the backend + // is still loading and only the boot screen shows the error. + Timer(const Duration(milliseconds: 300), () { + backend.bootStatus.value = const BootStatus(BootStage.startingUp, + error: "ModuleNotFoundError: No module named 'pydantic_core'"); + }); + + await expectLater( + () => waitForAppLoaded(tester), + throwsA(isA().having((e) => e.toString(), 'message', + contains("No module named 'pydantic_core'")))); + }); + testWidgets('a registered app that never initializes times out', (tester) async { final backend = await _mountApp(tester); From 21761e6b9eae60bdf618bdc552a92fcf14bec162 Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Thu, 29 Oct 2026 00:58:16 +0100 Subject: [PATCH 2/4] Bump Flutter to 3.47.8 --- .fvmrc | 2 +- CHANGELOG.md | 2 +- packages/flet/CHANGELOG.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.fvmrc b/.fvmrc index 6b3d30c248..4e46fba09b 100644 --- a/.fvmrc +++ b/.fvmrc @@ -1,3 +1,3 @@ { - "flutter": "3.47.7" + "flutter": "3.47.8" } diff --git a/CHANGELOG.md b/CHANGELOG.md index c20cf17013..935080ac5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,7 +45,7 @@ * Add `Theme.markdown_theme`: a default `MarkdownStyleSheet` for every `Markdown`, with a control's own `md_style_sheet` applied on top property by property by @FeodorFitsner. * Add `PopupMenuTheme.border_radius` to set the default hover/splash corner radius of every `PopupMenuButton` by @FeodorFitsner. -* Bump the bundled Flutter to [3.47.7](https://github.com/flutter/flutter/blob/stable/CHANGELOG.md#3477) (from 3.44.8). Android builds use Gradle 9.3.1, Android Gradle Plugin 8.13.2 and Kotlin 2.3.21 by @ndonkoHenri. +* Bump the bundled Flutter to [3.47.8](https://github.com/flutter/flutter/blob/stable/CHANGELOG.md#3478) (from 3.44.8). Android builds use Gradle 9.3.1, Android Gradle Plugin 8.13.2 and Kotlin 2.3.21 by @ndonkoHenri. **Compatibility:** Desktop apps and the desktop app that `flet run` opens now render with Impeller, Flutter 3.47's default desktop renderer, instead of Skia. Use `flet build --no-impeller` (or `impeller = false` under `[tool.flet]`), `flet run --no-impeller` or the `FLET_NO_IMPELLER` environment variable to render with Skia; see [Renderer](/docs/publish#renderer). Android plugins that still use `jcenter()` or other APIs removed in Gradle 9 no longer build. `flet build` downloads Flutter 3.47.7 on first use. diff --git a/packages/flet/CHANGELOG.md b/packages/flet/CHANGELOG.md index 058ca5d23f..c5881ba523 100644 --- a/packages/flet/CHANGELOG.md +++ b/packages/flet/CHANGELOG.md @@ -22,7 +22,7 @@ * An embedded page builds its `Navigator` with `requestFocus: false`, so pushing its routes doesn't move the focus out of the host app by @FeodorFitsner. * `PageControl` wraps an embedded page's app in a `CupertinoTheme` derived from the page's own Material theme (top-level pages are unchanged). Flutter's `Theme` reuses an ambient `CupertinoTheme` when one exists above it instead of deriving one from its `ThemeData`, so an embedded page's Cupertino widgets took the host app's colors by @FeodorFitsner. * `CupertinoButtonControl` falls back to the `ButtonStyle` in `internals["style"]` - what an adaptive Material `Button` sends - for background, foreground and padding when `bgcolor`/`color`/`padding` are absent by @FeodorFitsner. -* Flutter updated to [3.47.7](https://github.com/flutter/flutter/blob/stable/CHANGELOG.md#3477). +* Flutter updated to [3.47.8](https://github.com/flutter/flutter/blob/stable/CHANGELOG.md#3478). * **Breaking:** `parseTheme()` now builds themes from a seed with neutral surfaces by default (`#ffffff` / `#121212` and a neutral grey ramp for surface containers, `onSurface`, `outline` and inverse surfaces); the seed still drives accent colors. A theme's `surfaces: "tonal"` restores the seed-tinted Material 3 surfaces. Adds the `ThemeSurfaces` enum, `parseThemeSurfaces()` and `neutralizeSurfaces()` ([#6921](https://github.com/flet-dev/flet/issues/6921)) by @FeodorFitsner. * Import Material and Cupertino from the `material_ui` and `cupertino_ui` packages instead of `package:flutter/material.dart` and `package:flutter/cupertino.dart`. Helpers that take or return Material or Cupertino types, such as `parseColor()`, `parseTextStyle()` and `parseButtonStyle()`, now use those packages' types, and `flet.dart` no longer re-exports `Icons` and `CupertinoIcons`. Requires Flutter 3.47 or later. * Add `markdownStyleSheetFromTheme()`, which builds the default `MarkdownStyleSheet` from a `material_ui` theme. `MarkdownStyleSheet.fromTheme()` from `flutter_markdown_plus` only accepts the Flutter SDK's `ThemeData`. From 224e61beabd012ca586ce02de67623f974d2a193 Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Thu, 29 Oct 2026 00:59:04 +0100 Subject: [PATCH 3/4] Link the PR in the changelog --- CHANGELOG.md | 4 ++-- packages/flet/CHANGELOG.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 935080ac5b..3305589639 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,7 +45,7 @@ * Add `Theme.markdown_theme`: a default `MarkdownStyleSheet` for every `Markdown`, with a control's own `md_style_sheet` applied on top property by property by @FeodorFitsner. * Add `PopupMenuTheme.border_radius` to set the default hover/splash corner radius of every `PopupMenuButton` by @FeodorFitsner. -* Bump the bundled Flutter to [3.47.8](https://github.com/flutter/flutter/blob/stable/CHANGELOG.md#3478) (from 3.44.8). Android builds use Gradle 9.3.1, Android Gradle Plugin 8.13.2 and Kotlin 2.3.21 by @ndonkoHenri. +* Bump the bundled Flutter to [3.47.8](https://github.com/flutter/flutter/blob/stable/CHANGELOG.md#3478) (from 3.44.8). Android builds use Gradle 9.3.1, Android Gradle Plugin 8.13.2 and Kotlin 2.3.21 ([#6916](https://github.com/flet-dev/flet/pull/6916), [#7023](https://github.com/flet-dev/flet/pull/7023)) by @ndonkoHenri. **Compatibility:** Desktop apps and the desktop app that `flet run` opens now render with Impeller, Flutter 3.47's default desktop renderer, instead of Skia. Use `flet build --no-impeller` (or `impeller = false` under `[tool.flet]`), `flet run --no-impeller` or the `FLET_NO_IMPELLER` environment variable to render with Skia; see [Renderer](/docs/publish#renderer). Android plugins that still use `jcenter()` or other APIs removed in Gradle 9 no longer build. `flet build` downloads Flutter 3.47.7 on first use. @@ -66,7 +66,7 @@ * Fix `FilePicker` dialogs failing with a timeout after being open for an hour ([#6999](https://github.com/flet-dev/flet/pull/6999)) by @ndonkoHenri. * Fix `flet build` failing on every rebuild after one with changed build options, in apps with Flutter extensions ([#7010](https://github.com/flet-dev/flet/issues/7010), [#7012](https://github.com/flet-dev/flet/pull/7012)) by @ndonkoHenri. * Fix `flet build` not reinstalling the app's packages after `requirements.txt` is edited or `build/site-packages` is deleted ([#6994](https://github.com/flet-dev/flet/issues/6994), [#6996](https://github.com/flet-dev/flet/pull/6996)) by @ndonkoHenri. -* Fix `flet test` failing when the app under test starts slowly, as on the first run after a build: the test now waits until the app finishes initializing its first page, and fails right away with the Python traceback when the app's Python program fails to start ([#6993](https://github.com/flet-dev/flet/issues/6993), [#6995](https://github.com/flet-dev/flet/pull/6995)) by @ndonkoHenri. +* Fix `flet test` failing when the app under test starts slowly, as on the first run after a build: the test now waits until the app finishes initializing its first page, and fails right away with the Python traceback when the app's Python program fails to start ([#6993](https://github.com/flet-dev/flet/issues/6993), [#6995](https://github.com/flet-dev/flet/pull/6995), [#7023](https://github.com/flet-dev/flet/pull/7023)) by @ndonkoHenri. * Fix `use_effect()` cleanups being skipped: a cleanup returned by the setup was lost once the component re-rendered, only one ran when `cleanup=` was passed too, and `async` cleanups never ran when a dependency change re-ran the effect. A pending `async` setup is also cancelled on unmount ([#6963](https://github.com/flet-dev/flet/issues/6963), [#6983](https://github.com/flet-dev/flet/pull/6983), [#7005](https://github.com/flet-dev/flet/pull/7005)) by @mangod12. * iOS apps built with `flet build ipa` no longer fail App Store Connect validation with ITMS-90683 (missing `NSPhotoLibraryUsageDescription` and `NSCameraUsageDescription` purpose strings): the `file_picker` plugin is updated to 13.x, which picks photos with the system photo picker and no longer links DKImagePickerController's camera and photo-library code. `device_info_plus`, `package_info_plus` and `share_plus` move to their next major versions with it (`win32` 6). `FilePicker.save_file()` on desktop now creates the chosen file (empty when no `src_bytes` are given) before returning its path by @FeodorFitsner. * Fix `Tester.find_by_key()` not finding `Tab` and `PopupMenuItem` controls by their keys ([#6965](https://github.com/flet-dev/flet/issues/6965), [#6976](https://github.com/flet-dev/flet/pull/6976)) by @RezaShamsipour. diff --git a/packages/flet/CHANGELOG.md b/packages/flet/CHANGELOG.md index c5881ba523..0d1c677b9d 100644 --- a/packages/flet/CHANGELOG.md +++ b/packages/flet/CHANGELOG.md @@ -1,5 +1,6 @@ ## 1.1.0 +* Flutter updated to [3.47.8](https://github.com/flutter/flutter/blob/stable/CHANGELOG.md#3478). * Update `file_picker` to 13.x (federated; iOS picks media with `PHPickerViewController`, dropping DKImagePickerController, whose camera and photo-library references made App Store Connect demand purpose strings). `FilePickerService` uses `pickFile()`/`pickFiles()`, reads bytes and uploads through `PlatformFile.readAsBytes()`/`readAsByteStream()`, passes `lockParentWindow` through `WindowsOptions`/`LinuxOptions` and `cancel_upload_on_window_blur` through `file_picker_web`'s `FilePickerWebOptions` (imported only on web). `saveFile()` always writes the file, so desktop saves without `src_bytes` create it empty. Bump `device_info_plus` to ^13.3.0, `package_info_plus` to ^10.2.2 and `share_plus` to ^13.3.1 (`win32` 6, required by file_picker 13's Windows implementation) by @FeodorFitsner. * Apply `min_width`/`max_width`/`min_height`/`max_height` to every `LayoutControl` as a `ConstrainedBox` around the control (outside any fixed size). A control that implements one of these names itself lists it in `skip_properties` (`ListTile.min_height`, `NavigationRail.min_width`) by @FeodorFitsner. * Pass `material_tap_target_size` to `Switch` and `ThemeData` (`parseMaterialTapTargetSize()`) by @FeodorFitsner. @@ -22,7 +23,6 @@ * An embedded page builds its `Navigator` with `requestFocus: false`, so pushing its routes doesn't move the focus out of the host app by @FeodorFitsner. * `PageControl` wraps an embedded page's app in a `CupertinoTheme` derived from the page's own Material theme (top-level pages are unchanged). Flutter's `Theme` reuses an ambient `CupertinoTheme` when one exists above it instead of deriving one from its `ThemeData`, so an embedded page's Cupertino widgets took the host app's colors by @FeodorFitsner. * `CupertinoButtonControl` falls back to the `ButtonStyle` in `internals["style"]` - what an adaptive Material `Button` sends - for background, foreground and padding when `bgcolor`/`color`/`padding` are absent by @FeodorFitsner. -* Flutter updated to [3.47.8](https://github.com/flutter/flutter/blob/stable/CHANGELOG.md#3478). * **Breaking:** `parseTheme()` now builds themes from a seed with neutral surfaces by default (`#ffffff` / `#121212` and a neutral grey ramp for surface containers, `onSurface`, `outline` and inverse surfaces); the seed still drives accent colors. A theme's `surfaces: "tonal"` restores the seed-tinted Material 3 surfaces. Adds the `ThemeSurfaces` enum, `parseThemeSurfaces()` and `neutralizeSurfaces()` ([#6921](https://github.com/flet-dev/flet/issues/6921)) by @FeodorFitsner. * Import Material and Cupertino from the `material_ui` and `cupertino_ui` packages instead of `package:flutter/material.dart` and `package:flutter/cupertino.dart`. Helpers that take or return Material or Cupertino types, such as `parseColor()`, `parseTextStyle()` and `parseButtonStyle()`, now use those packages' types, and `flet.dart` no longer re-exports `Icons` and `CupertinoIcons`. Requires Flutter 3.47 or later. * Add `markdownStyleSheetFromTheme()`, which builds the default `MarkdownStyleSheet` from a `material_ui` theme. `MarkdownStyleSheet.fromTheme()` from `flutter_markdown_plus` only accepts the Flutter SDK's `ThemeData`. From 24fd5ec515277f7b1205948e88655a19bd5fd328 Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Thu, 29 Oct 2026 01:05:59 +0100 Subject: [PATCH 4/4] Type use_ref() with a function initializer `use_ref(initial_value: RefValueT | Callable[[], RefValueT] | None = None)` put the TypeVar on both sides of a union, as `use_state()` did before #7014: mypy rejected a function initializer and fell back to `Any`, and ty inferred the function-or-value union. Overloads now match a zero-argument function first, keep the original union as the fallback so value-or-function arguments passed through by custom hooks type as before, and give `use_ref()` / `use_ref(None)` a `MutableRef[Any]` that can be assigned later. --- CHANGELOG.md | 2 +- .../flet/src/flet/components/hooks/use_ref.py | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3305589639..345261e9d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ ### Bug fixes -* Fix `use_state()` type inference for callable initializers in mypy and ty ([#6960](https://github.com/flet-dev/flet/issues/6960), [#7014](https://github.com/flet-dev/flet/pull/7014)) by @mmporong. +* Fix `use_state()` and `use_ref()` type inference for callable initializers in mypy and ty ([#6960](https://github.com/flet-dev/flet/issues/6960), [#7014](https://github.com/flet-dev/flet/pull/7014), [#7023](https://github.com/flet-dev/flet/pull/7023)) by @mmporong. * Fix `flet build` apps showing a blank page when the system suspended them while Python was starting, such as when iOS launches an app in the background for a notification action ([#6999](https://github.com/flet-dev/flet/pull/6999)) by @ndonkoHenri. * Fix `flet build` naming a Linux app's icons `None.png` and leaving the iOS frameworks it builds from the app's packages under shared identifiers when no `bundle_id` is set ([#6999](https://github.com/flet-dev/flet/pull/6999)) by @ndonkoHenri. * Fix `flet build` writing numbers in `[tool.flet.macos.entitlement]`, `[tool.flet.ios.info]` and `[tool.flet.macos.info]` as strings, producing invalid plists when keys or values contain `&` or `<`, and failing when a `pyproject.toml` value contains `{{` ([#6999](https://github.com/flet-dev/flet/pull/6999)) by @ndonkoHenri. diff --git a/sdk/python/packages/flet/src/flet/components/hooks/use_ref.py b/sdk/python/packages/flet/src/flet/components/hooks/use_ref.py index 8f8bd469d7..d223502d9c 100644 --- a/sdk/python/packages/flet/src/flet/components/hooks/use_ref.py +++ b/sdk/python/packages/flet/src/flet/components/hooks/use_ref.py @@ -2,7 +2,7 @@ from collections.abc import Callable from dataclasses import dataclass -from typing import Generic, TypeVar +from typing import Any, Generic, TypeVar, overload from flet.components.hooks.hook import Hook from flet.components.utils import current_component @@ -35,6 +35,20 @@ class RefHook(Hook, Generic[RefValueT]): ref: MutableRef[RefValueT] +@overload +def use_ref(initial_value: None = None) -> MutableRef[Any]: ... + + +@overload +def use_ref(initial_value: Callable[[], RefValueT]) -> MutableRef[RefValueT]: ... + + +@overload +def use_ref( + initial_value: RefValueT | Callable[[], RefValueT], +) -> MutableRef[RefValueT]: ... + + def use_ref( initial_value: RefValueT | Callable[[], RefValueT] | None = None, ) -> MutableRef[RefValueT]: