pythonnative 0.23.0__tar.gz → 0.25.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pythonnative-0.23.0/src/pythonnative.egg-info → pythonnative-0.25.0}/PKG-INFO +6 -4
- {pythonnative-0.23.0 → pythonnative-0.25.0}/README.md +5 -3
- {pythonnative-0.23.0 → pythonnative-0.25.0}/pyproject.toml +1 -1
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/__init__.py +44 -53
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/animated.py +3 -3
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/cli/pn.py +3 -3
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/components.py +309 -513
- pythonnative-0.25.0/src/pythonnative/diagnostics.py +214 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/element.py +5 -2
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/events.py +13 -8
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/hooks.py +761 -114
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/hot_reload.py +9 -1
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/notifications.py +36 -4
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/permissions.py +24 -1
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_views/android.py +85 -3
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_views/desktop.py +38 -1
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_views/ios.py +252 -7
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/navigation.py +41 -17
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/preview.py +43 -7
- pythonnative-0.25.0/src/pythonnative/reconciler.py +2270 -0
- pythonnative-0.25.0/src/pythonnative/runtime.py +704 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/screen.py +377 -34
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/storage.py +5 -5
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/style.py +83 -0
- pythonnative-0.25.0/src/pythonnative/suspense.py +417 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/ScreenFragment.kt +22 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0/src/pythonnative.egg-info}/PKG-INFO +6 -4
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative.egg-info/SOURCES.txt +5 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_async_hooks.py +110 -83
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_components.py +5 -4
- pythonnative-0.25.0/tests/test_core_semantics.py +827 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_desktop_backend.py +6 -5
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_hooks.py +12 -13
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_native_lists.py +44 -7
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_navigation.py +4 -4
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_new_components.py +5 -5
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_reconciler.py +10 -10
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_ref.py +41 -27
- pythonnative-0.25.0/tests/test_runtime.py +252 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_screen.py +67 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_storage.py +15 -23
- pythonnative-0.25.0/tests/test_suspense.py +547 -0
- pythonnative-0.25.0/tests/test_transitions.py +178 -0
- pythonnative-0.23.0/src/pythonnative/reconciler.py +0 -1367
- pythonnative-0.23.0/src/pythonnative/runtime.py +0 -512
- pythonnative-0.23.0/tests/test_runtime.py +0 -146
- {pythonnative-0.23.0 → pythonnative-0.25.0}/LICENSE +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/setup.cfg +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/_ios_log.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/alerts.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/appearance.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/cli/__init__.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/gestures.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/images.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/layout.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/mutations.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/__init__.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/app_state.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/battery.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/biometrics.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/camera.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/clipboard.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/file_system.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/haptics.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/linking.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/location.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/net_info.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/secure_store.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/share.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_views/__init__.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/native_views/base.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/net.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/platform.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/platform_metrics.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/project/__init__.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/project/android.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/project/builder.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/project/config.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/project/doctor.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/project/icons.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/project/ios.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/project/permissions.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/project/runtime_assets.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/sdk/__init__.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/sdk/_components.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/build.gradle +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/proguard-rules.pro +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/androidTest/java/com/pythonnative/android_template/ExampleInstrumentedTest.kt +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/Navigator.kt +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNAccessibilityDelegate.kt +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNBorderDrawable.kt +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNVirtualListView.java +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/drawable/ic_launcher_background.xml +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/layout/activity_main.xml +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/navigation/nav_graph.xml +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/values/colors.xml +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/values/strings.xml +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/values/themes.xml +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/values-night/themes.xml +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/xml/backup_rules.xml +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/xml/data_extraction_rules.xml +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/test/java/com/pythonnative/android_template/ExampleUnitTest.kt +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/build.gradle +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.jar +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.properties +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/gradle.properties +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/gradlew +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/gradlew.bat +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/settings.gradle +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/AppDelegate.swift +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/AccentColor.colorset/Contents.json +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/Contents.json +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/Base.lproj/LaunchScreen.storyboard +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/Base.lproj/Main.storyboard +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/Info.plist +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/ViewController.swift +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/utils.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative/virtual_rows.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative.egg-info/dependency_links.txt +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative.egg-info/entry_points.txt +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative.egg-info/requires.txt +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/src/pythonnative.egg-info/top_level.txt +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_alert.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_animated.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_appearance.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_cli.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_element.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_events.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_extended_components.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_gestures.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_hot_reload.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_images.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_incremental_render.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_ios_log.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_layout.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_metric_hooks.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_mutations.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_native_modules.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_native_views.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_net.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_platform.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_platform_metrics.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_sdk.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_smoke.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_style.py +0 -0
- {pythonnative-0.23.0 → pythonnative-0.25.0}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythonnative
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.25.0
|
|
4
4
|
Summary: Cross-platform native UI toolkit for Android and iOS
|
|
5
5
|
Author: Owen Carey
|
|
6
6
|
License: MIT License
|
|
@@ -104,7 +104,9 @@ PythonNative is a cross-platform toolkit for building native Android and iOS app
|
|
|
104
104
|
- **Declarative UI:** Describe *what* your UI should look like with element functions (`Text`, `Button`, `Column`, `Row`, etc.). PythonNative creates and updates native views automatically.
|
|
105
105
|
- **Rich component library:** 25+ built-in components backed by real native widgets: `TextInput`, `Image` / `ImageBackground`, `ScrollView`, `FlatList` / `SectionList`, `Modal`, `Pressable` / `TouchableOpacity`, `Switch` / `Checkbox`, `Slider`, `SegmentedControl`, `Picker`, `DatePicker`, `ProgressBar` / `ActivityIndicator`, `WebView`, and more.
|
|
106
106
|
- **Device APIs:** Cross-platform modules for `Camera`, `Location`, `FileSystem`, `Notifications`, `Clipboard`, `Share`, `Linking`, `Permissions`, `AppState`, `NetInfo`, `SecureStore`, `Battery`, `Haptics` / `Vibration`, and `Biometrics`, plus reactive `use_app_state` and `use_net_info` hooks.
|
|
107
|
-
- **Hooks and function components:** Manage state with `use_state`, side effects with `use_effect`, and navigation with `use_navigation`, all through one consistent pattern.
|
|
107
|
+
- **Hooks and function components:** Manage state with `use_state`, side effects with `use_effect` / `use_layout_effect`, refs and imperative handles with `use_ref` / `use_imperative_handle`, and navigation with `use_navigation`, all through one consistent pattern. Components can return a single element, a list of siblings, or `None`, and `Fragment`, `Portal`, and reactive `Provider` context work the way they do in React.
|
|
108
|
+
- **Async-first rendering:** One `asyncio` event loop runs the whole framework on the platform's main thread. Components can be `async def` and `await` data directly in the body; `Suspense` boundaries show declarative loading states while they wait. `use_resource` fetches during render, `use_effect` accepts coroutine callbacks (cancelled automatically on unmount), `lazy` code-splits components, and `use_transition` / `use_deferred_value` keep the UI responsive during expensive updates.
|
|
109
|
+
- **Developer feedback that finds your bugs:** In dev mode (`pn preview`, hot reload, or `PN_DEV=1`), uncaught errors from renders, effects, and event handlers show a full-screen RedBox with the traceback; unknown style keys and duplicate list keys print "did you mean" warnings; and conditional hooks raise a `HookOrderError` at the source instead of silently cross-wiring state.
|
|
108
110
|
- **Typed `style` prop:** Pass all visual and layout properties through a single `style` dict, fully described by the `pn.Style` `TypedDict` and the ergonomic `pn.style(...)` helper for IDE autocomplete and static checking. Compose reusable styles with `StyleSheet`.
|
|
109
111
|
- **Cross-platform flexbox engine:** A pure-Python, Yoga-style layout engine computes frames once and applies them to native views, so `flex`, `padding`, `aspect_ratio`, and `position: "absolute"` produce the same geometry on Android and iOS.
|
|
110
112
|
- **Virtual view tree + reconciler:** Element trees are diffed and patched with minimal native mutations, similar to React's reconciliation. Each commit lands as **one batched transaction** of mutation ops, and event callbacks are routed through a tag-based registry so re-renders that only change closures cost zero native calls. State updates re-render **locally**: only the component whose state changed (and its subtree) re-runs, and unchanged leaves reuse cached intrinsic measurements, so deep UIs stay responsive instead of re-rendering the whole app from the root on every tap.
|
|
@@ -115,7 +117,7 @@ PythonNative is a cross-platform toolkit for building native Android and iOS app
|
|
|
115
117
|
- **Custom-component SDK:** Wrap any platform widget as a first-class element with type-checked props via `pythonnative.sdk` (`Props`, `@native_component`, `element_factory`). Plugins distributed on PyPI auto-register through the `pythonnative.handlers` entry-point group.
|
|
116
118
|
- **CLI scaffolding:** `pn init` creates a ready-to-run project; `pn run android` and `pn run ios` build and launch your app.
|
|
117
119
|
- **Instant desktop preview:** `pn preview` renders your app in a native desktop window via Tkinter with Fast Refresh on every save: iterate on layout, state, and navigation in milliseconds without booting a simulator or device. The reconciler, hooks, layout engine, and navigation are the same code that ships to the phone.
|
|
118
|
-
- **Native-backed navigation:** Declarative `Stack`, `Tab`, and `Drawer` navigators inspired by React Navigation. The root stack drives the platform's native navigation controller (`UINavigationController` on iOS, AndroidX Navigation Component on Android), so transitions, back gestures, and the hardware back button match what users expect.
|
|
120
|
+
- **Native-backed navigation:** Declarative `Stack`, `Tab`, and `Drawer` navigators inspired by React Navigation. The root stack drives the platform's native navigation controller (`UINavigationController` on iOS, AndroidX Navigation Component on Android), so transitions, back gestures, and the hardware back button match what users expect; `use_back_handler` intercepts the back action when a screen needs to.
|
|
119
121
|
- **Fast Refresh hot reload:** `pn run --hot-reload` watches `app/` and patches edits into the running app on save, preserving component state across most changes.
|
|
120
122
|
- **Bundled templates:** Android Gradle and iOS Xcode templates are included, so scaffolding requires no network access.
|
|
121
123
|
|
|
@@ -140,7 +142,7 @@ def App():
|
|
|
140
142
|
pn.Text(f"Count: {count}", style=pn.style(font_size=24, bold=True)),
|
|
141
143
|
pn.Button(
|
|
142
144
|
"Tap me",
|
|
143
|
-
|
|
145
|
+
on_press=lambda: set_count(count + 1),
|
|
144
146
|
),
|
|
145
147
|
style=pn.style(spacing=12, padding=16),
|
|
146
148
|
)
|
|
@@ -33,7 +33,9 @@ PythonNative is a cross-platform toolkit for building native Android and iOS app
|
|
|
33
33
|
- **Declarative UI:** Describe *what* your UI should look like with element functions (`Text`, `Button`, `Column`, `Row`, etc.). PythonNative creates and updates native views automatically.
|
|
34
34
|
- **Rich component library:** 25+ built-in components backed by real native widgets: `TextInput`, `Image` / `ImageBackground`, `ScrollView`, `FlatList` / `SectionList`, `Modal`, `Pressable` / `TouchableOpacity`, `Switch` / `Checkbox`, `Slider`, `SegmentedControl`, `Picker`, `DatePicker`, `ProgressBar` / `ActivityIndicator`, `WebView`, and more.
|
|
35
35
|
- **Device APIs:** Cross-platform modules for `Camera`, `Location`, `FileSystem`, `Notifications`, `Clipboard`, `Share`, `Linking`, `Permissions`, `AppState`, `NetInfo`, `SecureStore`, `Battery`, `Haptics` / `Vibration`, and `Biometrics`, plus reactive `use_app_state` and `use_net_info` hooks.
|
|
36
|
-
- **Hooks and function components:** Manage state with `use_state`, side effects with `use_effect`, and navigation with `use_navigation`, all through one consistent pattern.
|
|
36
|
+
- **Hooks and function components:** Manage state with `use_state`, side effects with `use_effect` / `use_layout_effect`, refs and imperative handles with `use_ref` / `use_imperative_handle`, and navigation with `use_navigation`, all through one consistent pattern. Components can return a single element, a list of siblings, or `None`, and `Fragment`, `Portal`, and reactive `Provider` context work the way they do in React.
|
|
37
|
+
- **Async-first rendering:** One `asyncio` event loop runs the whole framework on the platform's main thread. Components can be `async def` and `await` data directly in the body; `Suspense` boundaries show declarative loading states while they wait. `use_resource` fetches during render, `use_effect` accepts coroutine callbacks (cancelled automatically on unmount), `lazy` code-splits components, and `use_transition` / `use_deferred_value` keep the UI responsive during expensive updates.
|
|
38
|
+
- **Developer feedback that finds your bugs:** In dev mode (`pn preview`, hot reload, or `PN_DEV=1`), uncaught errors from renders, effects, and event handlers show a full-screen RedBox with the traceback; unknown style keys and duplicate list keys print "did you mean" warnings; and conditional hooks raise a `HookOrderError` at the source instead of silently cross-wiring state.
|
|
37
39
|
- **Typed `style` prop:** Pass all visual and layout properties through a single `style` dict, fully described by the `pn.Style` `TypedDict` and the ergonomic `pn.style(...)` helper for IDE autocomplete and static checking. Compose reusable styles with `StyleSheet`.
|
|
38
40
|
- **Cross-platform flexbox engine:** A pure-Python, Yoga-style layout engine computes frames once and applies them to native views, so `flex`, `padding`, `aspect_ratio`, and `position: "absolute"` produce the same geometry on Android and iOS.
|
|
39
41
|
- **Virtual view tree + reconciler:** Element trees are diffed and patched with minimal native mutations, similar to React's reconciliation. Each commit lands as **one batched transaction** of mutation ops, and event callbacks are routed through a tag-based registry so re-renders that only change closures cost zero native calls. State updates re-render **locally**: only the component whose state changed (and its subtree) re-runs, and unchanged leaves reuse cached intrinsic measurements, so deep UIs stay responsive instead of re-rendering the whole app from the root on every tap.
|
|
@@ -44,7 +46,7 @@ PythonNative is a cross-platform toolkit for building native Android and iOS app
|
|
|
44
46
|
- **Custom-component SDK:** Wrap any platform widget as a first-class element with type-checked props via `pythonnative.sdk` (`Props`, `@native_component`, `element_factory`). Plugins distributed on PyPI auto-register through the `pythonnative.handlers` entry-point group.
|
|
45
47
|
- **CLI scaffolding:** `pn init` creates a ready-to-run project; `pn run android` and `pn run ios` build and launch your app.
|
|
46
48
|
- **Instant desktop preview:** `pn preview` renders your app in a native desktop window via Tkinter with Fast Refresh on every save: iterate on layout, state, and navigation in milliseconds without booting a simulator or device. The reconciler, hooks, layout engine, and navigation are the same code that ships to the phone.
|
|
47
|
-
- **Native-backed navigation:** Declarative `Stack`, `Tab`, and `Drawer` navigators inspired by React Navigation. The root stack drives the platform's native navigation controller (`UINavigationController` on iOS, AndroidX Navigation Component on Android), so transitions, back gestures, and the hardware back button match what users expect.
|
|
49
|
+
- **Native-backed navigation:** Declarative `Stack`, `Tab`, and `Drawer` navigators inspired by React Navigation. The root stack drives the platform's native navigation controller (`UINavigationController` on iOS, AndroidX Navigation Component on Android), so transitions, back gestures, and the hardware back button match what users expect; `use_back_handler` intercepts the back action when a screen needs to.
|
|
48
50
|
- **Fast Refresh hot reload:** `pn run --hot-reload` watches `app/` and patches edits into the running app on save, preserving component state across most changes.
|
|
49
51
|
- **Bundled templates:** Android Gradle and iOS Xcode templates are included, so scaffolding requires no network access.
|
|
50
52
|
|
|
@@ -69,7 +71,7 @@ def App():
|
|
|
69
71
|
pn.Text(f"Count: {count}", style=pn.style(font_size=24, bold=True)),
|
|
70
72
|
pn.Button(
|
|
71
73
|
"Tap me",
|
|
72
|
-
|
|
74
|
+
on_press=lambda: set_count(count + 1),
|
|
73
75
|
),
|
|
74
76
|
style=pn.style(spacing=12, padding=16),
|
|
75
77
|
)
|
|
@@ -54,96 +54,83 @@ Example:
|
|
|
54
54
|
count, set_count = pn.use_state(0)
|
|
55
55
|
return pn.Column(
|
|
56
56
|
pn.Text(f"Count: {count}", style=pn.style(font_size=24)),
|
|
57
|
-
pn.Button("+",
|
|
57
|
+
pn.Button("+", on_press=lambda: set_count(count + 1)),
|
|
58
58
|
style=pn.style(spacing=12),
|
|
59
59
|
)
|
|
60
60
|
```
|
|
61
61
|
"""
|
|
62
62
|
|
|
63
|
-
__version__ = "0.
|
|
63
|
+
__version__ = "0.25.0"
|
|
64
64
|
|
|
65
|
-
from . import appearance, gestures, images, runtime, sdk
|
|
65
|
+
from . import appearance, diagnostics, gestures, images, runtime, sdk
|
|
66
66
|
from .alerts import Alert
|
|
67
67
|
from .animated import Animated, AnimatedValue, use_animated_value
|
|
68
68
|
from .components import (
|
|
69
69
|
ActivityIndicator,
|
|
70
|
-
ActivityIndicatorProps,
|
|
71
70
|
Button,
|
|
72
|
-
ButtonProps,
|
|
73
71
|
Checkbox,
|
|
74
|
-
CheckboxProps,
|
|
75
72
|
Column,
|
|
76
73
|
DatePicker,
|
|
77
|
-
DatePickerProps,
|
|
78
74
|
ErrorBoundary,
|
|
79
75
|
FlatList,
|
|
80
76
|
Fragment,
|
|
81
77
|
Image,
|
|
82
78
|
ImageBackground,
|
|
83
|
-
ImageBackgroundProps,
|
|
84
|
-
ImageProps,
|
|
85
79
|
KeyboardAvoidingView,
|
|
86
|
-
|
|
80
|
+
ListController,
|
|
87
81
|
Modal,
|
|
88
|
-
ModalProps,
|
|
89
82
|
Picker,
|
|
90
|
-
|
|
83
|
+
Portal,
|
|
91
84
|
Pressable,
|
|
92
|
-
PressableProps,
|
|
93
85
|
ProgressBar,
|
|
94
|
-
ProgressBarProps,
|
|
95
86
|
RefreshControl,
|
|
96
87
|
Row,
|
|
97
88
|
SafeAreaView,
|
|
98
|
-
SafeAreaViewProps,
|
|
99
89
|
ScrollView,
|
|
100
|
-
ScrollViewProps,
|
|
101
90
|
SectionList,
|
|
102
91
|
SegmentedControl,
|
|
103
|
-
SegmentedControlProps,
|
|
104
92
|
Slider,
|
|
105
|
-
SliderProps,
|
|
106
93
|
Spacer,
|
|
107
|
-
SpacerProps,
|
|
108
94
|
StatusBar,
|
|
109
|
-
|
|
95
|
+
Suspense,
|
|
110
96
|
Switch,
|
|
111
|
-
SwitchProps,
|
|
112
97
|
Text,
|
|
113
98
|
TextInput,
|
|
114
|
-
TextInputProps,
|
|
115
|
-
TextProps,
|
|
116
99
|
TouchableOpacity,
|
|
117
|
-
TouchableOpacityProps,
|
|
118
100
|
View,
|
|
119
|
-
ViewProps,
|
|
120
101
|
WebView,
|
|
121
|
-
WebViewProps,
|
|
122
102
|
)
|
|
103
|
+
from .diagnostics import HookOrderError
|
|
123
104
|
from .element import Element
|
|
124
105
|
from .hooks import (
|
|
125
106
|
MutationCall,
|
|
126
107
|
MutationState,
|
|
127
108
|
Provider,
|
|
128
109
|
QueryResult,
|
|
110
|
+
Ref,
|
|
129
111
|
batch_updates,
|
|
130
112
|
component,
|
|
131
113
|
create_context,
|
|
132
114
|
memo,
|
|
133
|
-
|
|
115
|
+
use_back_handler,
|
|
134
116
|
use_callback,
|
|
135
117
|
use_color_scheme,
|
|
136
118
|
use_context,
|
|
119
|
+
use_deferred_value,
|
|
137
120
|
use_effect,
|
|
121
|
+
use_imperative_handle,
|
|
138
122
|
use_keyboard_height,
|
|
123
|
+
use_layout_effect,
|
|
139
124
|
use_memo,
|
|
140
125
|
use_mutation,
|
|
141
126
|
use_navigation,
|
|
142
127
|
use_query,
|
|
143
128
|
use_reducer,
|
|
144
129
|
use_ref,
|
|
130
|
+
use_resource,
|
|
145
131
|
use_safe_area_insets,
|
|
146
132
|
use_state,
|
|
133
|
+
use_transition,
|
|
147
134
|
use_window_dimensions,
|
|
148
135
|
)
|
|
149
136
|
from .native_modules import (
|
|
@@ -167,6 +154,7 @@ from .native_modules import (
|
|
|
167
154
|
)
|
|
168
155
|
from .navigation import (
|
|
169
156
|
NavigationContainer,
|
|
157
|
+
ScreenOptions,
|
|
170
158
|
create_drawer_navigator,
|
|
171
159
|
create_stack_navigator,
|
|
172
160
|
create_tab_navigator,
|
|
@@ -175,7 +163,7 @@ from .navigation import (
|
|
|
175
163
|
)
|
|
176
164
|
from .net import HTTPError, Response, fetch
|
|
177
165
|
from .platform import Platform
|
|
178
|
-
from .runtime import run_async
|
|
166
|
+
from .runtime import run_async, run_blocking
|
|
179
167
|
from .screen import create_screen
|
|
180
168
|
from .sdk import (
|
|
181
169
|
Props,
|
|
@@ -188,6 +176,8 @@ from .storage import AsyncStorage, use_persisted_state
|
|
|
188
176
|
from .style import (
|
|
189
177
|
DEFAULT_DARK_THEME,
|
|
190
178
|
DEFAULT_LIGHT_THEME,
|
|
179
|
+
AccessibilityState,
|
|
180
|
+
AlignContent,
|
|
191
181
|
AlignItems,
|
|
192
182
|
AlignSelf,
|
|
193
183
|
AutoCapitalize,
|
|
@@ -195,9 +185,11 @@ from .style import (
|
|
|
195
185
|
Dimension,
|
|
196
186
|
EdgeInsets,
|
|
197
187
|
FlexDirection,
|
|
188
|
+
FlexWrap,
|
|
198
189
|
FontWeight,
|
|
199
190
|
JustifyContent,
|
|
200
191
|
KeyboardType,
|
|
192
|
+
LayoutDirection,
|
|
201
193
|
Overflow,
|
|
202
194
|
Position,
|
|
203
195
|
ReturnKeyType,
|
|
@@ -215,6 +207,7 @@ from .style import (
|
|
|
215
207
|
style,
|
|
216
208
|
use_theme,
|
|
217
209
|
)
|
|
210
|
+
from .suspense import Resource, lazy, start_resource
|
|
218
211
|
|
|
219
212
|
__all__ = [
|
|
220
213
|
# Components
|
|
@@ -229,8 +222,10 @@ __all__ = [
|
|
|
229
222
|
"Image",
|
|
230
223
|
"ImageBackground",
|
|
231
224
|
"KeyboardAvoidingView",
|
|
225
|
+
"ListController",
|
|
232
226
|
"Modal",
|
|
233
227
|
"Picker",
|
|
228
|
+
"Portal",
|
|
234
229
|
"Pressable",
|
|
235
230
|
"ProgressBar",
|
|
236
231
|
"RefreshControl",
|
|
@@ -242,36 +237,13 @@ __all__ = [
|
|
|
242
237
|
"Slider",
|
|
243
238
|
"Spacer",
|
|
244
239
|
"StatusBar",
|
|
240
|
+
"Suspense",
|
|
245
241
|
"Switch",
|
|
246
242
|
"Text",
|
|
247
243
|
"TextInput",
|
|
248
244
|
"TouchableOpacity",
|
|
249
245
|
"View",
|
|
250
246
|
"WebView",
|
|
251
|
-
# Built-in Props dataclasses
|
|
252
|
-
"ActivityIndicatorProps",
|
|
253
|
-
"ButtonProps",
|
|
254
|
-
"CheckboxProps",
|
|
255
|
-
"DatePickerProps",
|
|
256
|
-
"ImageBackgroundProps",
|
|
257
|
-
"ImageProps",
|
|
258
|
-
"KeyboardAvoidingViewProps",
|
|
259
|
-
"ModalProps",
|
|
260
|
-
"PickerProps",
|
|
261
|
-
"PressableProps",
|
|
262
|
-
"ProgressBarProps",
|
|
263
|
-
"SafeAreaViewProps",
|
|
264
|
-
"ScrollViewProps",
|
|
265
|
-
"SegmentedControlProps",
|
|
266
|
-
"SliderProps",
|
|
267
|
-
"SpacerProps",
|
|
268
|
-
"StatusBarProps",
|
|
269
|
-
"SwitchProps",
|
|
270
|
-
"TextInputProps",
|
|
271
|
-
"TextProps",
|
|
272
|
-
"TouchableOpacityProps",
|
|
273
|
-
"ViewProps",
|
|
274
|
-
"WebViewProps",
|
|
275
247
|
# Core
|
|
276
248
|
"Element",
|
|
277
249
|
"create_screen",
|
|
@@ -283,13 +255,17 @@ __all__ = [
|
|
|
283
255
|
"MutationCall",
|
|
284
256
|
"MutationState",
|
|
285
257
|
"QueryResult",
|
|
286
|
-
"
|
|
258
|
+
"Ref",
|
|
259
|
+
"use_back_handler",
|
|
287
260
|
"use_callback",
|
|
288
261
|
"use_color_scheme",
|
|
289
262
|
"use_context",
|
|
263
|
+
"use_deferred_value",
|
|
290
264
|
"use_effect",
|
|
291
265
|
"use_focus_effect",
|
|
266
|
+
"use_imperative_handle",
|
|
292
267
|
"use_keyboard_height",
|
|
268
|
+
"use_layout_effect",
|
|
293
269
|
"use_memo",
|
|
294
270
|
"use_mutation",
|
|
295
271
|
"use_navigation",
|
|
@@ -297,17 +273,26 @@ __all__ = [
|
|
|
297
273
|
"use_query",
|
|
298
274
|
"use_reducer",
|
|
299
275
|
"use_ref",
|
|
276
|
+
"use_resource",
|
|
300
277
|
"use_route",
|
|
301
278
|
"use_safe_area_insets",
|
|
302
279
|
"use_state",
|
|
280
|
+
"use_transition",
|
|
303
281
|
"use_window_dimensions",
|
|
304
282
|
"Provider",
|
|
283
|
+
# Suspense and async rendering
|
|
284
|
+
"Resource",
|
|
285
|
+
"lazy",
|
|
286
|
+
"start_resource",
|
|
305
287
|
# Navigation
|
|
306
288
|
"NavigationContainer",
|
|
289
|
+
"ScreenOptions",
|
|
307
290
|
"create_drawer_navigator",
|
|
308
291
|
"create_stack_navigator",
|
|
309
292
|
"create_tab_navigator",
|
|
310
293
|
# Styling - typed primitives
|
|
294
|
+
"AccessibilityState",
|
|
295
|
+
"AlignContent",
|
|
311
296
|
"AlignItems",
|
|
312
297
|
"AlignSelf",
|
|
313
298
|
"AutoCapitalize",
|
|
@@ -317,9 +302,11 @@ __all__ = [
|
|
|
317
302
|
"Dimension",
|
|
318
303
|
"EdgeInsets",
|
|
319
304
|
"FlexDirection",
|
|
305
|
+
"FlexWrap",
|
|
320
306
|
"FontWeight",
|
|
321
307
|
"JustifyContent",
|
|
322
308
|
"KeyboardType",
|
|
309
|
+
"LayoutDirection",
|
|
323
310
|
"Overflow",
|
|
324
311
|
"Position",
|
|
325
312
|
"ReturnKeyType",
|
|
@@ -373,7 +360,11 @@ __all__ = [
|
|
|
373
360
|
"Response",
|
|
374
361
|
# Runtime
|
|
375
362
|
"run_async",
|
|
363
|
+
"run_blocking",
|
|
376
364
|
"runtime",
|
|
365
|
+
# Diagnostics
|
|
366
|
+
"HookOrderError",
|
|
367
|
+
"diagnostics",
|
|
377
368
|
# Platform
|
|
378
369
|
"Platform",
|
|
379
370
|
# Custom-component SDK
|
|
@@ -47,7 +47,7 @@ Example:
|
|
|
47
47
|
await pn.Animated.timing(opacity, to=1.0, duration=400)
|
|
48
48
|
await pn.Animated.timing(opacity, to=0.5, duration=200)
|
|
49
49
|
|
|
50
|
-
pn.
|
|
50
|
+
pn.use_effect(fade_in, [])
|
|
51
51
|
|
|
52
52
|
return pn.Animated.View(
|
|
53
53
|
pn.Text("Hello!"),
|
|
@@ -834,7 +834,7 @@ def _make_animated_factory(
|
|
|
834
834
|
ref = use_ref(None)
|
|
835
835
|
|
|
836
836
|
def _attach_bindings() -> Callable[[], None]:
|
|
837
|
-
tag = ref.
|
|
837
|
+
tag = ref._pn_tag
|
|
838
838
|
if tag is None:
|
|
839
839
|
return lambda: None
|
|
840
840
|
detachers = [value.attach(tag, _animated_prop_name(prop)) for prop, value in bindings.items()]
|
|
@@ -1014,7 +1014,7 @@ def use_animated_value(initial: float = 0.0) -> AnimatedValue:
|
|
|
1014
1014
|
async def fade_in():
|
|
1015
1015
|
await pn.Animated.timing(opacity, to=1.0, duration=300)
|
|
1016
1016
|
|
|
1017
|
-
pn.
|
|
1017
|
+
pn.use_effect(fade_in, [])
|
|
1018
1018
|
return pn.Animated.View(
|
|
1019
1019
|
pn.Text("Hello"),
|
|
1020
1020
|
style=pn.style(opacity=opacity),
|
|
@@ -59,8 +59,8 @@ def HomeScreen():
|
|
|
59
59
|
pn.Column(
|
|
60
60
|
pn.Text("Hello from PythonNative!", style={"font_size": 24, "bold": True}),
|
|
61
61
|
pn.Text(f"Tapped {count} times"),
|
|
62
|
-
pn.Button("Tap me",
|
|
63
|
-
pn.Button("Open detail",
|
|
62
|
+
pn.Button("Tap me", on_press=lambda: set_count(count + 1)),
|
|
63
|
+
pn.Button("Open detail", on_press=lambda: nav.navigate("Detail", {"count": count})),
|
|
64
64
|
style={"spacing": 12, "padding": 16, "align_items": "stretch"},
|
|
65
65
|
)
|
|
66
66
|
)
|
|
@@ -72,7 +72,7 @@ def DetailScreen():
|
|
|
72
72
|
params = pn.use_route()
|
|
73
73
|
return pn.Column(
|
|
74
74
|
pn.Text(f"Detail: count was {params.get('count', 0)}", style={"font_size": 20}),
|
|
75
|
-
pn.Button("Back",
|
|
75
|
+
pn.Button("Back", on_press=nav.go_back),
|
|
76
76
|
style={"spacing": 12, "padding": 16},
|
|
77
77
|
)
|
|
78
78
|
|