pythonnative 0.32.0__tar.gz → 0.34.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.32.0/src/pythonnative.egg-info → pythonnative-0.34.0}/PKG-INFO +2 -21
- {pythonnative-0.32.0 → pythonnative-0.34.0}/pyproject.toml +25 -15
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/__init__.py +27 -15
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/animated.py +7 -13
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/cli/pn.py +1 -2
- pythonnative-0.34.0/src/pythonnative/component.py +255 -0
- pythonnative-0.34.0/src/pythonnative/components/__init__.py +106 -0
- pythonnative-0.34.0/src/pythonnative/components/_base.py +132 -0
- pythonnative-0.34.0/src/pythonnative/components/controls.py +515 -0
- pythonnative-0.34.0/src/pythonnative/components/layout.py +459 -0
- pythonnative-0.34.0/src/pythonnative/components/lists.py +809 -0
- pythonnative-0.34.0/src/pythonnative/components/media.py +204 -0
- pythonnative-0.34.0/src/pythonnative/components/overlays.py +107 -0
- pythonnative-0.34.0/src/pythonnative/components/pressable.py +252 -0
- pythonnative-0.34.0/src/pythonnative/components/structural.py +167 -0
- pythonnative-0.34.0/src/pythonnative/components/text.py +291 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/diagnostics.py +1 -1
- pythonnative-0.34.0/src/pythonnative/element.py +159 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/gestures.py +1 -1
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/hooks.py +366 -671
- pythonnative-0.34.0/src/pythonnative/hosts/__init__.py +85 -0
- pythonnative-0.34.0/src/pythonnative/hosts/android.py +269 -0
- pythonnative-0.34.0/src/pythonnative/hosts/base.py +665 -0
- pythonnative-0.34.0/src/pythonnative/hosts/desktop.py +107 -0
- pythonnative-0.34.0/src/pythonnative/hosts/ios.py +404 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/hot_reload.py +16 -24
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/layout.py +372 -66
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/__init__.py +23 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/net_info.py +5 -1
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_views/__init__.py +1 -1
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_views/android.py +50 -6
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_views/base.py +64 -1
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_views/desktop.py +11 -3
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_views/ios.py +72 -12
- pythonnative-0.34.0/src/pythonnative/navigation/__init__.py +102 -0
- pythonnative-0.34.0/src/pythonnative/navigation/container.py +154 -0
- pythonnative-0.34.0/src/pythonnative/navigation/handle.py +573 -0
- pythonnative-0.34.0/src/pythonnative/navigation/hooks.py +94 -0
- pythonnative-0.34.0/src/pythonnative/navigation/host.py +58 -0
- pythonnative-0.34.0/src/pythonnative/navigation/linking.py +200 -0
- pythonnative-0.34.0/src/pythonnative/navigation/navigators.py +637 -0
- pythonnative-0.34.0/src/pythonnative/navigation/screen.py +149 -0
- pythonnative-0.34.0/src/pythonnative/navigation/state.py +248 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/net.py +4 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/platform_metrics.py +1 -1
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/preview.py +21 -19
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/project/android.py +7 -1
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/project/doctor.py +1 -1
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/project/ios.py +1 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/project/runtime_assets.py +1 -1
- pythonnative-0.34.0/src/pythonnative/reconciler/__init__.py +29 -0
- pythonnative-0.34.0/src/pythonnative/reconciler/boundaries.py +365 -0
- pythonnative-0.34.0/src/pythonnative/reconciler/children.py +88 -0
- pythonnative-0.34.0/src/pythonnative/reconciler/core.py +1153 -0
- pythonnative-0.34.0/src/pythonnative/reconciler/layout_pass.py +359 -0
- pythonnative-0.34.0/src/pythonnative/reconciler/vnode.py +266 -0
- pythonnative-0.34.0/src/pythonnative/scheduler.py +159 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/sdk/_components.py +2 -4
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/style.py +95 -13
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/suspense.py +8 -12
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +85 -1
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/ScreenFragment.kt +6 -7
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/navigation/nav_graph.xml +1 -1
- pythonnative-0.34.0/src/pythonnative/templates/android_template/app/src/main/res/values/strings.xml +5 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_template/AppDelegate.swift +33 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +1 -1
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_template/ViewController.swift +12 -10
- pythonnative-0.34.0/src/pythonnative/testing/__init__.py +53 -0
- pythonnative-0.34.0/src/pythonnative/testing/backend.py +276 -0
- pythonnative-0.34.0/src/pythonnative/testing/harness.py +391 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0/src/pythonnative.egg-info}/PKG-INFO +2 -21
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative.egg-info/SOURCES.txt +36 -5
- pythonnative-0.34.0/src/pythonnative.egg-info/requires.txt +11 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_animated.py +2 -2
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_animated_graph.py +1 -1
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_appearance.py +7 -6
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_async_hooks.py +2 -2
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_components.py +11 -11
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_core_semantics.py +7 -9
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_desktop_backend.py +4 -3
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_events.py +6 -7
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_extended_components.py +3 -4
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_gestures.py +3 -4
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_hooks.py +228 -268
- pythonnative-0.34.0/tests/test_hosts.py +431 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_hot_reload.py +10 -9
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_incremental_render.py +12 -12
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_interaction_props.py +2 -3
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_layout.py +300 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_metric_hooks.py +6 -6
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_mutations.py +9 -9
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_native_lists.py +8 -7
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_native_modules.py +4 -4
- pythonnative-0.34.0/tests/test_navigation.py +1182 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_net.py +11 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_new_components.py +4 -5
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_reconciler.py +34 -34
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_ref.py +4 -4
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_smoke.py +0 -1
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_storage.py +2 -2
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_style.py +103 -1
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_suspense.py +3 -2
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_transitions.py +3 -3
- pythonnative-0.32.0/src/pythonnative/components.py +0 -2856
- pythonnative-0.32.0/src/pythonnative/element.py +0 -80
- pythonnative-0.32.0/src/pythonnative/navigation.py +0 -1031
- pythonnative-0.32.0/src/pythonnative/reconciler.py +0 -2298
- pythonnative-0.32.0/src/pythonnative/screen.py +0 -2068
- pythonnative-0.32.0/src/pythonnative/templates/android_template/app/src/main/res/values/strings.xml +0 -3
- pythonnative-0.32.0/src/pythonnative.egg-info/requires.txt +0 -33
- pythonnative-0.32.0/tests/test_navigation.py +0 -1198
- pythonnative-0.32.0/tests/test_screen.py +0 -299
- {pythonnative-0.32.0 → pythonnative-0.34.0}/LICENSE +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/README.md +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/setup.cfg +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/_ios_log.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/alerts.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/appearance.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/cli/__init__.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/events.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/images.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/mutations.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/app_state.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/battery.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/biometrics.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/camera.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/clipboard.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/file_system.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/haptics.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/linking.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/location.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/notifications.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/permissions.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/secure_store.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/native_modules/share.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/platform.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/project/__init__.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/project/builder.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/project/config.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/project/devices.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/project/icons.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/project/permissions.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/runtime.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/sdk/__init__.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/storage.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/build.gradle +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/proguard-rules.pro +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/androidTest/java/com/pythonnative/android_template/ExampleInstrumentedTest.kt +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/Navigator.kt +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNAccessibilityDelegate.kt +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNBorderDrawable.kt +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNFrameLayout.kt +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNVirtualListView.java +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/drawable/ic_launcher_background.xml +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/layout/activity_main.xml +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/values/colors.xml +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/values/themes.xml +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/values-night/themes.xml +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/xml/backup_rules.xml +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/main/res/xml/data_extraction_rules.xml +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/app/src/test/java/com/pythonnative/android_template/ExampleUnitTest.kt +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/build.gradle +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.jar +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.properties +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/gradle.properties +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/gradlew +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/gradlew.bat +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/android_template/settings.gradle +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/AccentColor.colorset/Contents.json +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/Contents.json +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_template/Base.lproj/LaunchScreen.storyboard +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_template/BridgingHeader.h +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_template/Info.plist +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/utils.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative/virtual_rows.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative.egg-info/dependency_links.txt +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative.egg-info/entry_points.txt +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/src/pythonnative.egg-info/top_level.txt +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_alert.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_cli.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_element.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_gesture_composition.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_images.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_ios_log.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_native_views.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_platform.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_platform_metrics.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_runtime.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.0}/tests/test_sdk.py +0 -0
- {pythonnative-0.32.0 → pythonnative-0.34.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.34.0
|
|
4
4
|
Summary: Cross-platform native UI toolkit for Android and iOS
|
|
5
5
|
Author: Owen Carey
|
|
6
6
|
License: MIT License
|
|
@@ -43,30 +43,11 @@ Description-Content-Type: text/markdown
|
|
|
43
43
|
License-File: LICENSE
|
|
44
44
|
Requires-Dist: requests>=2.31.0
|
|
45
45
|
Requires-Dist: tomli>=2.0; python_version < "3.11"
|
|
46
|
+
Requires-Dist: typing_extensions>=4.4; python_version < "3.11"
|
|
46
47
|
Provides-Extra: ios
|
|
47
48
|
Requires-Dist: rubicon-objc<0.5.0,>=0.4.6; extra == "ios"
|
|
48
49
|
Provides-Extra: build
|
|
49
50
|
Requires-Dist: Pillow>=10.0; extra == "build"
|
|
50
|
-
Provides-Extra: docs
|
|
51
|
-
Requires-Dist: mkdocs>=1.5; extra == "docs"
|
|
52
|
-
Requires-Dist: mkdocs-material[imaging]>=9.5; extra == "docs"
|
|
53
|
-
Requires-Dist: mkdocstrings[python]>=0.24; extra == "docs"
|
|
54
|
-
Requires-Dist: mkdocs-autorefs>=1.0; extra == "docs"
|
|
55
|
-
Requires-Dist: pymdown-extensions>=10.7; extra == "docs"
|
|
56
|
-
Provides-Extra: dev
|
|
57
|
-
Requires-Dist: black>=24.0; extra == "dev"
|
|
58
|
-
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
59
|
-
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
60
|
-
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
61
|
-
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
62
|
-
Requires-Dist: Pillow>=10.0; extra == "dev"
|
|
63
|
-
Provides-Extra: ci
|
|
64
|
-
Requires-Dist: black>=24.0; extra == "ci"
|
|
65
|
-
Requires-Dist: ruff>=0.5; extra == "ci"
|
|
66
|
-
Requires-Dist: mypy>=1.10; extra == "ci"
|
|
67
|
-
Requires-Dist: pytest>=8.0; extra == "ci"
|
|
68
|
-
Requires-Dist: pytest-asyncio>=0.23; extra == "ci"
|
|
69
|
-
Requires-Dist: Pillow>=10.0; extra == "ci"
|
|
70
51
|
Dynamic: license-file
|
|
71
52
|
|
|
72
53
|
<p align="center">
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pythonnative"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.34.0"
|
|
8
8
|
description = "Cross-platform native UI toolkit for Android and iOS"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Owen Carey" }
|
|
@@ -26,6 +26,7 @@ classifiers = [
|
|
|
26
26
|
dependencies = [
|
|
27
27
|
"requests>=2.31.0",
|
|
28
28
|
"tomli>=2.0; python_version < '3.11'",
|
|
29
|
+
"typing_extensions>=4.4; python_version < '3.11'",
|
|
29
30
|
]
|
|
30
31
|
|
|
31
32
|
[project.optional-dependencies]
|
|
@@ -35,13 +36,10 @@ ios = [
|
|
|
35
36
|
build = [
|
|
36
37
|
"Pillow>=10.0",
|
|
37
38
|
]
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"mkdocs-autorefs>=1.0",
|
|
43
|
-
"pymdown-extensions>=10.7",
|
|
44
|
-
]
|
|
39
|
+
|
|
40
|
+
# Contributor tooling, not published as package extras (PEP 735). Install
|
|
41
|
+
# with `uv sync --group dev` or `--group docs`; `uv sync` alone gets `dev`.
|
|
42
|
+
[dependency-groups]
|
|
45
43
|
dev = [
|
|
46
44
|
"black>=24.0",
|
|
47
45
|
"ruff>=0.5",
|
|
@@ -49,14 +47,17 @@ dev = [
|
|
|
49
47
|
"pytest>=8.0",
|
|
50
48
|
"pytest-asyncio>=0.23",
|
|
51
49
|
"Pillow>=10.0",
|
|
50
|
+
# `pn run ios` shells out to `sys.executable -m pip` to vendor
|
|
51
|
+
# rubicon-objc (project/builder.py), and the test suite exercises that
|
|
52
|
+
# path. `uv sync` does not seed pip the way `uv venv --seed` did.
|
|
53
|
+
"pip>=24.0",
|
|
52
54
|
]
|
|
53
|
-
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"Pillow>=10.0",
|
|
55
|
+
docs = [
|
|
56
|
+
"mkdocs>=1.5",
|
|
57
|
+
"mkdocs-material[imaging]>=9.5",
|
|
58
|
+
"mkdocstrings[python]>=0.24",
|
|
59
|
+
"mkdocs-autorefs>=1.0",
|
|
60
|
+
"pymdown-extensions>=10.7",
|
|
60
61
|
]
|
|
61
62
|
|
|
62
63
|
[project.scripts]
|
|
@@ -144,6 +145,15 @@ asyncio_mode = "auto"
|
|
|
144
145
|
# ── Semantic Release ────────────────────────────────────────────────
|
|
145
146
|
|
|
146
147
|
[tool.semantic_release]
|
|
148
|
+
# PSR stamps the new version into pyproject.toml before running this, so
|
|
149
|
+
# `--upgrade-package` re-syncs only this project's own version in the lock
|
|
150
|
+
# (never dependency upgrades), and the staged uv.lock lands in the release
|
|
151
|
+
# commit. This also replaces the workflow's separate `python -m build`.
|
|
152
|
+
build_command = """
|
|
153
|
+
uv lock --upgrade-package pythonnative
|
|
154
|
+
git add uv.lock
|
|
155
|
+
uv build
|
|
156
|
+
"""
|
|
147
157
|
version_toml = ["pyproject.toml:project.version"]
|
|
148
158
|
version_variables = ["src/pythonnative/__init__.py:__version__"]
|
|
149
159
|
commit_message = "chore(release): v{version}"
|
|
@@ -60,11 +60,12 @@ Example:
|
|
|
60
60
|
```
|
|
61
61
|
"""
|
|
62
62
|
|
|
63
|
-
__version__ = "0.
|
|
63
|
+
__version__ = "0.34.0"
|
|
64
64
|
|
|
65
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
|
+
from .component import Component, component, memo
|
|
68
69
|
from .components import (
|
|
69
70
|
ActivityIndicator,
|
|
70
71
|
Button,
|
|
@@ -103,15 +104,12 @@ from .components import (
|
|
|
103
104
|
from .diagnostics import HookOrderError
|
|
104
105
|
from .element import Element
|
|
105
106
|
from .hooks import (
|
|
107
|
+
Context,
|
|
106
108
|
MutationCall,
|
|
107
109
|
MutationState,
|
|
108
|
-
Provider,
|
|
109
110
|
QueryResult,
|
|
110
111
|
Ref,
|
|
111
|
-
batch_updates,
|
|
112
|
-
component,
|
|
113
112
|
create_context,
|
|
114
|
-
memo,
|
|
115
113
|
use_back_handler,
|
|
116
114
|
use_callback,
|
|
117
115
|
use_color_scheme,
|
|
@@ -123,16 +121,17 @@ from .hooks import (
|
|
|
123
121
|
use_layout_effect,
|
|
124
122
|
use_memo,
|
|
125
123
|
use_mutation,
|
|
126
|
-
use_navigation,
|
|
127
124
|
use_query,
|
|
128
125
|
use_reducer,
|
|
129
126
|
use_ref,
|
|
130
127
|
use_resource,
|
|
131
128
|
use_safe_area_insets,
|
|
132
129
|
use_state,
|
|
130
|
+
use_subscription,
|
|
133
131
|
use_transition,
|
|
134
132
|
use_window_dimensions,
|
|
135
133
|
)
|
|
134
|
+
from .hosts import create_screen
|
|
136
135
|
from .native_modules import (
|
|
137
136
|
AppState,
|
|
138
137
|
Battery,
|
|
@@ -153,18 +152,24 @@ from .native_modules import (
|
|
|
153
152
|
use_net_info,
|
|
154
153
|
)
|
|
155
154
|
from .navigation import (
|
|
155
|
+
LinkingConfig,
|
|
156
|
+
Navigation,
|
|
156
157
|
NavigationContainer,
|
|
158
|
+
NavigationState,
|
|
159
|
+
Route,
|
|
157
160
|
ScreenOptions,
|
|
158
161
|
create_drawer_navigator,
|
|
159
162
|
create_stack_navigator,
|
|
160
163
|
create_tab_navigator,
|
|
161
164
|
use_focus_effect,
|
|
165
|
+
use_is_focused,
|
|
166
|
+
use_navigation,
|
|
162
167
|
use_route,
|
|
163
168
|
)
|
|
164
169
|
from .net import HTTPError, Response, fetch
|
|
165
170
|
from .platform import Platform
|
|
166
171
|
from .runtime import run_async, run_blocking
|
|
167
|
-
from .
|
|
172
|
+
from .scheduler import batch_updates
|
|
168
173
|
from .sdk import (
|
|
169
174
|
Props,
|
|
170
175
|
ViewHandler,
|
|
@@ -245,51 +250,58 @@ __all__ = [
|
|
|
245
250
|
"View",
|
|
246
251
|
"WebView",
|
|
247
252
|
# Core
|
|
253
|
+
"Component",
|
|
248
254
|
"Element",
|
|
249
|
-
"create_screen",
|
|
250
|
-
# Hooks
|
|
251
|
-
"batch_updates",
|
|
252
255
|
"component",
|
|
253
|
-
"
|
|
256
|
+
"create_screen",
|
|
254
257
|
"memo",
|
|
258
|
+
# Hooks
|
|
259
|
+
"Context",
|
|
255
260
|
"MutationCall",
|
|
256
261
|
"MutationState",
|
|
257
262
|
"QueryResult",
|
|
258
263
|
"Ref",
|
|
264
|
+
"batch_updates",
|
|
265
|
+
"create_context",
|
|
259
266
|
"use_back_handler",
|
|
260
267
|
"use_callback",
|
|
261
268
|
"use_color_scheme",
|
|
262
269
|
"use_context",
|
|
263
270
|
"use_deferred_value",
|
|
264
271
|
"use_effect",
|
|
265
|
-
"use_focus_effect",
|
|
266
272
|
"use_imperative_handle",
|
|
267
273
|
"use_keyboard_height",
|
|
268
274
|
"use_layout_effect",
|
|
269
275
|
"use_memo",
|
|
270
276
|
"use_mutation",
|
|
271
|
-
"use_navigation",
|
|
272
277
|
"use_persisted_state",
|
|
273
278
|
"use_query",
|
|
274
279
|
"use_reducer",
|
|
275
280
|
"use_ref",
|
|
276
281
|
"use_resource",
|
|
277
|
-
"use_route",
|
|
278
282
|
"use_safe_area_insets",
|
|
279
283
|
"use_state",
|
|
284
|
+
"use_subscription",
|
|
280
285
|
"use_transition",
|
|
281
286
|
"use_window_dimensions",
|
|
282
|
-
"Provider",
|
|
283
287
|
# Suspense and async rendering
|
|
284
288
|
"Resource",
|
|
285
289
|
"lazy",
|
|
286
290
|
"start_resource",
|
|
287
291
|
# Navigation
|
|
292
|
+
"LinkingConfig",
|
|
293
|
+
"Navigation",
|
|
288
294
|
"NavigationContainer",
|
|
295
|
+
"NavigationState",
|
|
296
|
+
"Route",
|
|
289
297
|
"ScreenOptions",
|
|
290
298
|
"create_drawer_navigator",
|
|
291
299
|
"create_stack_navigator",
|
|
292
300
|
"create_tab_navigator",
|
|
301
|
+
"use_focus_effect",
|
|
302
|
+
"use_is_focused",
|
|
303
|
+
"use_navigation",
|
|
304
|
+
"use_route",
|
|
293
305
|
# Styling - typed primitives
|
|
294
306
|
"AccessibilityState",
|
|
295
307
|
"AlignContent",
|
|
@@ -1356,20 +1356,14 @@ def _make_animated_factory(
|
|
|
1356
1356
|
accept_children: bool,
|
|
1357
1357
|
) -> Callable[..., Element]:
|
|
1358
1358
|
"""Build an animated wrapper for ``element_type``."""
|
|
1359
|
-
from .
|
|
1359
|
+
from .component import Component
|
|
1360
1360
|
|
|
1361
|
-
|
|
1362
|
-
def _animated(*args: Any, **kwargs: Any) -> Element:
|
|
1361
|
+
def _animated(*children: Any, **kwargs: Any) -> Element:
|
|
1363
1362
|
from .components import Image as _Image
|
|
1364
1363
|
from .components import Text as _Text
|
|
1365
1364
|
from .components import View as _View
|
|
1366
1365
|
|
|
1367
|
-
|
|
1368
|
-
# prop (this function declares ``*args``), and the reconciler
|
|
1369
|
-
# re-invokes it with keyword props only, so at render time the
|
|
1370
|
-
# payload arrives in ``kwargs``, never in ``args``.
|
|
1371
|
-
children = list(args) or list(kwargs.pop("children", ()) or ())
|
|
1372
|
-
|
|
1366
|
+
kids: List[Any] = list(children)
|
|
1373
1367
|
style = kwargs.pop("style", None)
|
|
1374
1368
|
plain_style, bindings = _resolve_style_with_values(style)
|
|
1375
1369
|
|
|
@@ -1397,13 +1391,13 @@ def _make_animated_factory(
|
|
|
1397
1391
|
text = children[0] if children else kwargs.pop("text", "")
|
|
1398
1392
|
return _Text(text, style=plain_style, ref=ref, **kwargs)
|
|
1399
1393
|
if element_type == "Image":
|
|
1400
|
-
source =
|
|
1394
|
+
source = kids[0] if kids else kwargs.pop("source", "")
|
|
1401
1395
|
return _Image(source, style=plain_style, ref=ref, **kwargs)
|
|
1402
1396
|
if not accept_children:
|
|
1403
|
-
|
|
1404
|
-
return _View(*
|
|
1397
|
+
kids = []
|
|
1398
|
+
return _View(*kids, style=plain_style, ref=ref, **kwargs)
|
|
1405
1399
|
|
|
1406
|
-
return _animated
|
|
1400
|
+
return Component(_animated, display_name=f"Animated.{element_type}")
|
|
1407
1401
|
|
|
1408
1402
|
|
|
1409
1403
|
def _animated_prop_name(prop: str) -> str:
|
|
@@ -196,8 +196,7 @@ def init_project(args: argparse.Namespace) -> None:
|
|
|
196
196
|
# ``is_symlink()`` so the whole class is closed, not one spelling of it.
|
|
197
197
|
if name and (target.is_symlink() or target.resolve().parent != cwd.resolve()):
|
|
198
198
|
print(
|
|
199
|
-
f"Refusing to scaffold through a link or outside the current directory: {name}. "
|
|
200
|
-
"Use a plain directory name."
|
|
199
|
+
f"Refusing to scaffold through a link or outside the current directory: {name}. Use a plain directory name."
|
|
201
200
|
)
|
|
202
201
|
sys.exit(1)
|
|
203
202
|
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"""The ``@component`` decorator and the [`Component`][pythonnative.Component] type.
|
|
2
|
+
|
|
3
|
+
A component is a plain Python function that takes props and returns a
|
|
4
|
+
[`Node`][pythonnative.element.Node]: an [`Element`][pythonnative.Element],
|
|
5
|
+
a list of elements, or ``None``. Decorating it with
|
|
6
|
+
[`@component`][pythonnative.component.component] turns it into a
|
|
7
|
+
[`Component`][pythonnative.Component]: a callable that *describes* a
|
|
8
|
+
render (it returns an ``Element`` whose ``type`` is the component)
|
|
9
|
+
instead of performing one. The reconciler invokes the function body
|
|
10
|
+
later, with hook state installed.
|
|
11
|
+
|
|
12
|
+
The decorator preserves the function's signature for type checkers via
|
|
13
|
+
:class:`typing.ParamSpec`, so ``Greeting(nme="x")`` is a static error
|
|
14
|
+
and editors autocomplete props from the function definition.
|
|
15
|
+
|
|
16
|
+
Children
|
|
17
|
+
--------
|
|
18
|
+
|
|
19
|
+
Children are positional. A component that accepts children declares a
|
|
20
|
+
``*children`` parameter, exactly like the built-in containers:
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
@pn.component
|
|
24
|
+
def Card(*children: pn.Element, title: str = "") -> pn.Element:
|
|
25
|
+
return pn.Column(pn.Text(title, style=pn.style(bold=True)), *children)
|
|
26
|
+
|
|
27
|
+
Card(pn.Text("body"), title="Hello")
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Positional arguments to a component *without* ``*children`` bind to its
|
|
31
|
+
positional parameters, so ``Greeting("World")`` works for
|
|
32
|
+
``def Greeting(name: str)``.
|
|
33
|
+
|
|
34
|
+
Keys
|
|
35
|
+
----
|
|
36
|
+
|
|
37
|
+
Every component accepts ``key=`` at the call site for keyed
|
|
38
|
+
reconciliation. ``key`` is consumed by the framework and is not passed
|
|
39
|
+
to the function unless the function declares a ``key`` parameter
|
|
40
|
+
itself. Declaring it (``key: str | None = None``) is the way to keep
|
|
41
|
+
strict type checkers happy when a component is rendered in a list;
|
|
42
|
+
otherwise use [`Element.with_key`][pythonnative.element.Element.with_key].
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
from __future__ import annotations
|
|
46
|
+
|
|
47
|
+
import functools
|
|
48
|
+
import inspect
|
|
49
|
+
from typing import Any, Awaitable, Callable, Dict, Generic, List, Optional, ParamSpec, Tuple, Union
|
|
50
|
+
|
|
51
|
+
from .element import Element, Node
|
|
52
|
+
|
|
53
|
+
__all__ = ["Component", "RenderFn", "component", "memo", "is_component"]
|
|
54
|
+
|
|
55
|
+
P = ParamSpec("P")
|
|
56
|
+
|
|
57
|
+
RenderFn = Callable[P, Union[Node, Awaitable[Node]]]
|
|
58
|
+
"""A component body: returns a [`Node`][pythonnative.element.Node], or awaits one when ``async def``."""
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class Component(Generic[P]):
|
|
62
|
+
"""A render-function wrapped by [`@component`][pythonnative.component.component].
|
|
63
|
+
|
|
64
|
+
Calling a ``Component`` does not run the function; it returns an
|
|
65
|
+
[`Element`][pythonnative.Element] describing the call so the
|
|
66
|
+
reconciler can mount it, preserve its hook state across renders,
|
|
67
|
+
and re-run it when its state or props change.
|
|
68
|
+
|
|
69
|
+
Attributes:
|
|
70
|
+
fn: The original render function.
|
|
71
|
+
display_name: Name shown in diagnostics and dev tooling
|
|
72
|
+
(defaults to ``fn.__name__``).
|
|
73
|
+
memoized: Whether [`memo`][pythonnative.memo] was applied, in
|
|
74
|
+
which case the reconciler skips re-rendering this component
|
|
75
|
+
when its props are shallowly equal to the previous render.
|
|
76
|
+
accepts_children: Whether ``fn`` declares ``*children``.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
__slots__ = (
|
|
80
|
+
"fn",
|
|
81
|
+
"display_name",
|
|
82
|
+
"memoized",
|
|
83
|
+
"props_equal",
|
|
84
|
+
"accepts_children",
|
|
85
|
+
"_positional",
|
|
86
|
+
"_declares_key",
|
|
87
|
+
"_is_async",
|
|
88
|
+
"__wrapped__",
|
|
89
|
+
"__dict__",
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def __init__(self, fn: RenderFn[P], *, display_name: Optional[str] = None) -> None:
|
|
93
|
+
if isinstance(fn, Component):
|
|
94
|
+
raise TypeError(f"{fn!r} is already a component; remove the duplicate @component")
|
|
95
|
+
sig = inspect.signature(fn)
|
|
96
|
+
positional: List[str] = []
|
|
97
|
+
accepts_children = False
|
|
98
|
+
declares_key = False
|
|
99
|
+
for name, param in sig.parameters.items():
|
|
100
|
+
if param.kind in (inspect.Parameter.POSITIONAL_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD):
|
|
101
|
+
positional.append(name)
|
|
102
|
+
elif param.kind is inspect.Parameter.VAR_POSITIONAL:
|
|
103
|
+
accepts_children = True
|
|
104
|
+
if name == "key":
|
|
105
|
+
declares_key = True
|
|
106
|
+
self.fn = fn
|
|
107
|
+
self.display_name = display_name or getattr(fn, "__name__", "Component")
|
|
108
|
+
self.memoized = False
|
|
109
|
+
self.props_equal: Optional[Callable[[Dict[str, Any], Dict[str, Any]], bool]] = None
|
|
110
|
+
self.accepts_children = accepts_children
|
|
111
|
+
self._positional: Tuple[str, ...] = tuple(positional)
|
|
112
|
+
self._declares_key = declares_key
|
|
113
|
+
self._is_async = inspect.iscoroutinefunction(fn)
|
|
114
|
+
self.__wrapped__ = fn
|
|
115
|
+
functools.update_wrapper(self, fn, updated=())
|
|
116
|
+
|
|
117
|
+
# ------------------------------------------------------------------
|
|
118
|
+
# Element construction
|
|
119
|
+
# ------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> Element:
|
|
122
|
+
"""Describe a render of this component with the given props."""
|
|
123
|
+
props: Dict[str, Any] = dict(kwargs)
|
|
124
|
+
key = props.pop("key", None) if not self._declares_key else props.get("key")
|
|
125
|
+
children: List[Any] = []
|
|
126
|
+
if args:
|
|
127
|
+
if self.accepts_children:
|
|
128
|
+
children = list(args)
|
|
129
|
+
else:
|
|
130
|
+
names = self._positional
|
|
131
|
+
if len(args) > len(names):
|
|
132
|
+
raise TypeError(
|
|
133
|
+
f"{self.display_name}() takes {len(names)} positional argument(s) but "
|
|
134
|
+
f"{len(args)} were given. Declare *children to accept child elements."
|
|
135
|
+
)
|
|
136
|
+
for name, value in zip(names, args):
|
|
137
|
+
if name in props:
|
|
138
|
+
raise TypeError(f"{self.display_name}() got multiple values for argument {name!r}")
|
|
139
|
+
props[name] = value
|
|
140
|
+
return Element(self, props, children, key=key if isinstance(key, str) or key is None else str(key))
|
|
141
|
+
|
|
142
|
+
# ------------------------------------------------------------------
|
|
143
|
+
# Rendering (used by the reconciler)
|
|
144
|
+
# ------------------------------------------------------------------
|
|
145
|
+
|
|
146
|
+
def render(self, element: Element) -> Any:
|
|
147
|
+
"""Invoke the render function for ``element``.
|
|
148
|
+
|
|
149
|
+
Children stored on the element are passed positionally; props
|
|
150
|
+
are passed by keyword. Returns whatever the function returned
|
|
151
|
+
(an element, a list, ``None``, or a coroutine for ``async def``
|
|
152
|
+
bodies).
|
|
153
|
+
"""
|
|
154
|
+
if self.accepts_children:
|
|
155
|
+
return self.fn(*element.children, **element.props)
|
|
156
|
+
return self.fn(**element.props) # type: ignore[call-arg]
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def is_async(self) -> bool:
|
|
160
|
+
"""Whether the render function is an ``async def``."""
|
|
161
|
+
return self._is_async
|
|
162
|
+
|
|
163
|
+
def __repr__(self) -> str:
|
|
164
|
+
flags = " memo" if self.memoized else ""
|
|
165
|
+
return f"<Component {self.display_name}{flags}>"
|
|
166
|
+
|
|
167
|
+
def __get__(self, instance: Any, owner: Any = None) -> "Component[P]":
|
|
168
|
+
# Components stored on classes (rare) should not bind ``self``.
|
|
169
|
+
return self
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def component(fn: RenderFn[P]) -> Component[P]:
|
|
173
|
+
"""Turn a render function into a [`Component`][pythonnative.Component].
|
|
174
|
+
|
|
175
|
+
The decorated function may use hooks (``use_state``, ``use_effect``,
|
|
176
|
+
etc.) and returns an [`Element`][pythonnative.Element] tree, a list
|
|
177
|
+
of elements, or ``None``. Each call site creates an independent
|
|
178
|
+
component instance with its own hook state.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
fn: The render function. May be ``async def``; the body is then
|
|
182
|
+
driven by the reconciler and suspends on pending awaits (see
|
|
183
|
+
[`Suspense`][pythonnative.Suspense]).
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
A ``Component`` whose call signature mirrors ``fn`` (plus the
|
|
187
|
+
framework ``key=`` keyword).
|
|
188
|
+
|
|
189
|
+
Example:
|
|
190
|
+
```python
|
|
191
|
+
import pythonnative as pn
|
|
192
|
+
|
|
193
|
+
@pn.component
|
|
194
|
+
def Greeting(name: str = "World"):
|
|
195
|
+
return pn.Text(f"Hello, {name}!")
|
|
196
|
+
```
|
|
197
|
+
"""
|
|
198
|
+
return Component(fn)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def memo(
|
|
202
|
+
target: Optional[Component[P]] = None,
|
|
203
|
+
*,
|
|
204
|
+
equal: Optional[Callable[[Dict[str, Any], Dict[str, Any]], bool]] = None,
|
|
205
|
+
) -> Any:
|
|
206
|
+
"""Skip a component's render when its props haven't changed.
|
|
207
|
+
|
|
208
|
+
Apply on top of ``@component``. When the reconciler re-renders the
|
|
209
|
+
parent tree, a memoized child is skipped (its previously-rendered
|
|
210
|
+
subtree is reused) iff its props and children are equal to the
|
|
211
|
+
previous render and none of its own state setters fired. Props are
|
|
212
|
+
compared shallowly by default: callables by identity, everything
|
|
213
|
+
else by ``==``.
|
|
214
|
+
|
|
215
|
+
Pair with [`use_callback`][pythonnative.use_callback] when passing
|
|
216
|
+
callbacks as props, otherwise a fresh closure defeats the memo.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
target: A [`Component`][pythonnative.Component].
|
|
220
|
+
equal: Optional custom comparator ``(old_props, new_props) ->
|
|
221
|
+
bool`` replacing the shallow comparison.
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
The same component, marked for memoization (or a decorator when
|
|
225
|
+
called with keyword arguments only).
|
|
226
|
+
|
|
227
|
+
Example:
|
|
228
|
+
```python
|
|
229
|
+
@pn.memo
|
|
230
|
+
@pn.component
|
|
231
|
+
def ExpensiveRow(label: str):
|
|
232
|
+
...
|
|
233
|
+
|
|
234
|
+
@pn.memo(equal=lambda a, b: a["id"] == b["id"])
|
|
235
|
+
@pn.component
|
|
236
|
+
def Row(id: int, extra: dict):
|
|
237
|
+
...
|
|
238
|
+
```
|
|
239
|
+
"""
|
|
240
|
+
|
|
241
|
+
def apply(comp: Component[P]) -> Component[P]:
|
|
242
|
+
if not isinstance(comp, Component):
|
|
243
|
+
raise TypeError("@memo must wrap a @component; write @memo above @component")
|
|
244
|
+
comp.memoized = True
|
|
245
|
+
comp.props_equal = equal
|
|
246
|
+
return comp
|
|
247
|
+
|
|
248
|
+
if target is None:
|
|
249
|
+
return apply
|
|
250
|
+
return apply(target)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def is_component(obj: Any) -> bool:
|
|
254
|
+
"""Return whether ``obj`` is a [`Component`][pythonnative.Component]."""
|
|
255
|
+
return isinstance(obj, Component)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Built-in element factories.
|
|
2
|
+
|
|
3
|
+
Each factory function (``Text``, ``Button``, …) is a fully-typed thin
|
|
4
|
+
wrapper that builds an [`Element`][pythonnative.Element] through the
|
|
5
|
+
shared ``_make_element`` helper, so style resolution, ``ref``
|
|
6
|
+
attachment, ``None``-default dropping, and forced overrides (e.g.
|
|
7
|
+
``Column``'s fixed ``flex_direction``) live in exactly one place. The
|
|
8
|
+
factory signatures themselves are the canonical prop schemas: editors
|
|
9
|
+
and type checkers validate calls directly against them.
|
|
10
|
+
|
|
11
|
+
The factories are grouped by concern into submodules (``text``,
|
|
12
|
+
``media``, ``controls``, ``layout``, ``pressable``, ``overlays``,
|
|
13
|
+
``structural``, ``lists``); everything public is re-exported here, so
|
|
14
|
+
``from pythonnative.components import Text`` keeps working.
|
|
15
|
+
|
|
16
|
+
Example:
|
|
17
|
+
```python
|
|
18
|
+
import pythonnative as pn
|
|
19
|
+
|
|
20
|
+
pn.Column(
|
|
21
|
+
pn.Text("Hello", style=pn.style(font_size=18)),
|
|
22
|
+
pn.Button("Tap", on_press=lambda: print("tapped")),
|
|
23
|
+
style=pn.style(spacing=12, padding=16),
|
|
24
|
+
)
|
|
25
|
+
```
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from ._base import _SPAN_STYLE_KEYS, _flatten_text_spans, _make_element # noqa: F401
|
|
29
|
+
from .controls import (
|
|
30
|
+
ActivityIndicator,
|
|
31
|
+
Checkbox,
|
|
32
|
+
DatePicker,
|
|
33
|
+
Picker,
|
|
34
|
+
ProgressBar,
|
|
35
|
+
RefreshControl,
|
|
36
|
+
SegmentedControl,
|
|
37
|
+
Slider,
|
|
38
|
+
StatusBar,
|
|
39
|
+
Switch,
|
|
40
|
+
)
|
|
41
|
+
from .layout import ( # noqa: F401
|
|
42
|
+
_SAFE_AREA_EDGES,
|
|
43
|
+
Column,
|
|
44
|
+
KeyboardAvoidingView,
|
|
45
|
+
Row,
|
|
46
|
+
SafeAreaView,
|
|
47
|
+
ScrollView,
|
|
48
|
+
Spacer,
|
|
49
|
+
View,
|
|
50
|
+
_KeyboardAvoidingContainer,
|
|
51
|
+
_numeric_edge_padding,
|
|
52
|
+
_SafeAreaContainer,
|
|
53
|
+
)
|
|
54
|
+
from .lists import ( # noqa: F401
|
|
55
|
+
_DEFAULT_ROW_EXTENT,
|
|
56
|
+
FlatList,
|
|
57
|
+
ListController,
|
|
58
|
+
SectionList,
|
|
59
|
+
_all_extents_known,
|
|
60
|
+
_dispatch_scroll_command,
|
|
61
|
+
_native_lists_supported,
|
|
62
|
+
_NativeList,
|
|
63
|
+
_RowSpec,
|
|
64
|
+
_VirtualizedList,
|
|
65
|
+
)
|
|
66
|
+
from .media import Image, ImageBackground, WebView
|
|
67
|
+
from .overlays import Modal, Portal
|
|
68
|
+
from .pressable import Pressable, TouchableOpacity, _StatefulPressable # noqa: F401
|
|
69
|
+
from .structural import ErrorBoundary, Fragment, Suspense
|
|
70
|
+
from .text import Button, Text, TextInput
|
|
71
|
+
|
|
72
|
+
__all__ = [
|
|
73
|
+
"ActivityIndicator",
|
|
74
|
+
"Button",
|
|
75
|
+
"Checkbox",
|
|
76
|
+
"Column",
|
|
77
|
+
"DatePicker",
|
|
78
|
+
"ErrorBoundary",
|
|
79
|
+
"FlatList",
|
|
80
|
+
"Fragment",
|
|
81
|
+
"Image",
|
|
82
|
+
"ImageBackground",
|
|
83
|
+
"KeyboardAvoidingView",
|
|
84
|
+
"ListController",
|
|
85
|
+
"Modal",
|
|
86
|
+
"Picker",
|
|
87
|
+
"Portal",
|
|
88
|
+
"Pressable",
|
|
89
|
+
"ProgressBar",
|
|
90
|
+
"RefreshControl",
|
|
91
|
+
"Row",
|
|
92
|
+
"SafeAreaView",
|
|
93
|
+
"ScrollView",
|
|
94
|
+
"SectionList",
|
|
95
|
+
"SegmentedControl",
|
|
96
|
+
"Slider",
|
|
97
|
+
"Spacer",
|
|
98
|
+
"StatusBar",
|
|
99
|
+
"Suspense",
|
|
100
|
+
"Switch",
|
|
101
|
+
"Text",
|
|
102
|
+
"TextInput",
|
|
103
|
+
"TouchableOpacity",
|
|
104
|
+
"View",
|
|
105
|
+
"WebView",
|
|
106
|
+
]
|