pythonnative 0.40.0__cp313-cp313-win_amd64.whl
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/__init__.py +411 -0
- pythonnative/_ios_log.py +92 -0
- pythonnative/_yoga.cp313-win_amd64.pyd +0 -0
- pythonnative/alerts.py +236 -0
- pythonnative/animated.py +1687 -0
- pythonnative/animation_graph.py +78 -0
- pythonnative/appearance.py +124 -0
- pythonnative/bootstrap.py +100 -0
- pythonnative/bridge/__init__.py +302 -0
- pythonnative/bridge/android.py +78 -0
- pythonnative/bridge/codec.py +170 -0
- pythonnative/bridge/commits.py +114 -0
- pythonnative/bridge/fake.py +243 -0
- pythonnative/bridge/ios.py +138 -0
- pythonnative/bridge/web.py +489 -0
- pythonnative/cli/__init__.py +7 -0
- pythonnative/cli/pn.py +1214 -0
- pythonnative/component.py +271 -0
- pythonnative/components/__init__.py +111 -0
- pythonnative/components/_base.py +166 -0
- pythonnative/components/controls.py +521 -0
- pythonnative/components/layout.py +518 -0
- pythonnative/components/lists.py +785 -0
- pythonnative/components/media.py +204 -0
- pythonnative/components/overlays.py +107 -0
- pythonnative/components/pressable.py +252 -0
- pythonnative/components/structural.py +167 -0
- pythonnative/components/text.py +291 -0
- pythonnative/devclient.py +824 -0
- pythonnative/devserver/__init__.py +34 -0
- pythonnative/devserver/server.py +718 -0
- pythonnative/devserver/static/animation_graph.js +82 -0
- pythonnative/devserver/static/bridge.js +147 -0
- pythonnative/devserver/static/colors.js +70 -0
- pythonnative/devserver/static/host.js +552 -0
- pythonnative/devserver/static/index.html +60 -0
- pythonnative/devserver/static/layout.js +85 -0
- pythonnative/devserver/static/preview.css +415 -0
- pythonnative/devserver/static/renderer.js +1994 -0
- pythonnative/devserver/static/shell.js +345 -0
- pythonnative/devserver/static/yoga/LICENSE +21 -0
- pythonnative/devserver/static/yoga/binaries/yoga-wasm-base64-esm.js +75 -0
- pythonnative/devserver/static/yoga/src/generated/YGEnums.d.ts +189 -0
- pythonnative/devserver/static/yoga/src/generated/YGEnums.js +211 -0
- pythonnative/devserver/static/yoga/src/generated/YGEnums.js.map +1 -0
- pythonnative/devserver/static/yoga/src/index.d.ts +12 -0
- pythonnative/devserver/static/yoga/src/index.js +16 -0
- pythonnative/devserver/static/yoga/src/index.js.map +1 -0
- pythonnative/devserver/static/yoga/src/load.d.ts +11 -0
- pythonnative/devserver/static/yoga/src/load.js +17 -0
- pythonnative/devserver/static/yoga/src/load.js.map +1 -0
- pythonnative/devserver/static/yoga/src/wrapAssembly.d.ts +155 -0
- pythonnative/devserver/static/yoga/src/wrapAssembly.js +125 -0
- pythonnative/devserver/static/yoga/src/wrapAssembly.js.map +1 -0
- pythonnative/devserver/watcher.py +267 -0
- pythonnative/devserver/ws.py +421 -0
- pythonnative/diagnostics.py +241 -0
- pythonnative/element.py +159 -0
- pythonnative/equality.py +19 -0
- pythonnative/events.py +231 -0
- pythonnative/gestures.py +1333 -0
- pythonnative/hooks.py +1621 -0
- pythonnative/hosts/__init__.py +63 -0
- pythonnative/hosts/base.py +596 -0
- pythonnative/hosts/native.py +302 -0
- pythonnative/hot_reload.py +585 -0
- pythonnative/layout.py +328 -0
- pythonnative/mutations.py +142 -0
- pythonnative/native/android/build.gradle +52 -0
- pythonnative/native/android/gradle.properties +3 -0
- pythonnative/native/android/settings.gradle +12 -0
- pythonnative/native/android/src/main/AndroidManifest.xml +11 -0
- pythonnative/native/android/src/main/cpp/CMakeLists.txt +9 -0
- pythonnative/native/android/src/main/cpp/yoga_jni.cpp +52 -0
- pythonnative/native/android/src/main/java/com/pythonnative/generated/NativeModules.kt +5 -0
- pythonnative/native/android/src/main/java/com/pythonnative/generated/NativeProps.kt +3705 -0
- pythonnative/native/android/src/main/java/com/pythonnative/generated/PNContracts.kt +129 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/PNBridge.kt +261 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/PythonHost.kt +20 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/AnimationGraph.kt +108 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/AnimationSpecs.kt +141 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/PNAnimator.kt +257 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/CommitState.kt +106 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/JsonUtil.kt +175 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/MainThread.kt +40 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNLog.kt +33 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNRegistry.kt +82 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNTransaction.kt +80 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/TransactionApplier.kt +117 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/ViewRegistry.kt +74 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/BuiltinComponents.kt +37 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ButtonManager.kt +32 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ComponentManager.kt +213 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ContainerManagers.kt +69 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ControlManagers.kt +186 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/DatePickerManager.kt +123 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ImageLoader.kt +141 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ImageManager.kt +162 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ModalManager.kt +134 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PNColor.kt +201 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PickerManager.kt +86 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PortalManager.kt +55 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PressableManager.kt +122 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ScreenStackManager.kt +110 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ScrollViewManager.kt +214 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/SegmentedControlManager.kt +113 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/StatusBarManager.kt +52 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TabBarManager.kt +131 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TextInputManager.kt +250 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TextManager.kt +233 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ViewStyler.kt +355 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/VirtualListManager.kt +159 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/WebViewManager.kt +149 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureArbiter.kt +233 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureCoordinator.kt +127 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureRecognizers.kt +527 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/layout/NativeLayout.kt +145 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/layout/YogaNode.kt +29 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/BuiltinModules.kt +73 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/DeviceModules.kt +316 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/HostModule.kt +61 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/MediaModules.kt +200 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/NativeModule.kt +158 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/NotificationsModule.kt +100 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/PermissionsModule.kt +99 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/StorageModules.kt +89 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/SystemModules.kt +178 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/plugins/GeneratedPlugins.kt +16 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/screens/PNScreenFragment.kt +188 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/screens/ScreenRegistry.kt +80 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNAccessibilityDelegate.kt +48 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNBorderDrawable.kt +76 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNEditText.kt +18 -0
- pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNFrameLayout.kt +49 -0
- pythonnative/native/android/src/test/java/com/pythonnative/runtime/AnimationSpecsTest.kt +75 -0
- pythonnative/native/android/src/test/java/com/pythonnative/runtime/GestureArbiterTest.kt +197 -0
- pythonnative/native/android/src/test/java/com/pythonnative/runtime/PNColorTest.kt +47 -0
- pythonnative/native/android/src/test/java/com/pythonnative/runtime/PNTransactionTest.kt +78 -0
- pythonnative/native/android/src/test/java/com/pythonnative/runtime/PromiseTest.kt +89 -0
- pythonnative/native/ios/Package.swift +23 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Animation/PNAnimationGraph.swift +199 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Animation/PNAnimator.swift +312 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNBridge.swift +255 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNCommit.swift +104 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNRegistry.swift +142 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNTransaction.swift +166 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNViewRegistry.swift +53 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNButtonManagers.swift +207 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNColor.swift +173 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNComponentManager.swift +183 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNContainerView.swift +56 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNControlManagers.swift +281 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNImageManager.swift +222 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNOverlayManagers.swift +243 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNPressableManager.swift +114 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNScreenStackManager.swift +107 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNScrollViewManager.swift +197 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTabBarManager.swift +106 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTextInputManager.swift +297 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTextManager.swift +230 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTransform.swift +82 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewManager.swift +86 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewState.swift +87 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewStyler.swift +340 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNVirtualListManager.swift +155 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Components/PNWebViewManager.swift +124 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Generated/NativeModules.swift +1 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Generated/NativeProps.swift +3775 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Generated/PNContracts.swift +46 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Gestures/PNGestureCoordinator.swift +260 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Layout/PNLayout.swift +173 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Modules/AlertModule.swift +92 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Modules/HostModule.swift +80 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Modules/LifecycleModules.swift +174 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Modules/MediaModules.swift +177 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Modules/PNNativeModule.swift +168 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Modules/PermissionModules.swift +266 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Modules/SystemModules.swift +251 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Plugins/PNPluginRegistration.swift +8 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Screens/PNScreenRegistry.swift +46 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Screens/PNViewController.swift +237 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Support/PNCompat.swift +46 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Support/PNJSON.swift +173 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Support/PNLog.swift +47 -0
- pythonnative/native/ios/Sources/PythonNativeKit/Support/PNWindow.swift +51 -0
- pythonnative/native/ios/Tests/PythonNativeKitTests/PNAnimationGraphTests.swift +26 -0
- pythonnative/native/ios/Tests/PythonNativeKitTests/PNColorTests.swift +50 -0
- pythonnative/native/ios/Tests/PythonNativeKitTests/PNCommitTests.swift +86 -0
- pythonnative/native/ios/Tests/PythonNativeKitTests/PNGestureTests.swift +101 -0
- pythonnative/native/ios/Tests/PythonNativeKitTests/PNManagerTests.swift +126 -0
- pythonnative/native/ios/Tests/PythonNativeKitTests/PNModuleTests.swift +111 -0
- pythonnative/native/ios/Tests/PythonNativeKitTests/PNTransactionTests.swift +91 -0
- pythonnative/native/yoga/LICENSE +21 -0
- pythonnative/native/yoga/Package.swift +9 -0
- pythonnative/native/yoga/VENDORED.md +2 -0
- pythonnative/native/yoga/include/PNStyle.h +10 -0
- pythonnative/native/yoga/include/module.modulemap +5 -0
- pythonnative/native/yoga/include/yoga/YGConfig.h +158 -0
- pythonnative/native/yoga/include/yoga/YGEnums.h +142 -0
- pythonnative/native/yoga/include/yoga/YGMacros.h +99 -0
- pythonnative/native/yoga/include/yoga/YGNode.h +304 -0
- pythonnative/native/yoga/include/yoga/YGNodeLayout.h +35 -0
- pythonnative/native/yoga/include/yoga/YGNodeStyle.h +130 -0
- pythonnative/native/yoga/include/yoga/YGPixelGrid.h +29 -0
- pythonnative/native/yoga/include/yoga/YGValue.h +84 -0
- pythonnative/native/yoga/include/yoga/Yoga.h +21 -0
- pythonnative/native/yoga/python.cpp +16 -0
- pythonnative/native/yoga/style.cpp +272 -0
- pythonnative/native/yoga/yoga/CMakeLists.txt +41 -0
- pythonnative/native/yoga/yoga/YGConfig.cpp +92 -0
- pythonnative/native/yoga/yoga/YGConfig.h +158 -0
- pythonnative/native/yoga/yoga/YGEnums.cpp +262 -0
- pythonnative/native/yoga/yoga/YGEnums.h +142 -0
- pythonnative/native/yoga/yoga/YGMacros.h +99 -0
- pythonnative/native/yoga/yoga/YGNode.cpp +366 -0
- pythonnative/native/yoga/yoga/YGNode.h +304 -0
- pythonnative/native/yoga/yoga/YGNodeLayout.cpp +92 -0
- pythonnative/native/yoga/yoga/YGNodeLayout.h +35 -0
- pythonnative/native/yoga/yoga/YGNodeStyle.cpp +405 -0
- pythonnative/native/yoga/yoga/YGNodeStyle.h +130 -0
- pythonnative/native/yoga/yoga/YGPixelGrid.cpp +22 -0
- pythonnative/native/yoga/yoga/YGPixelGrid.h +29 -0
- pythonnative/native/yoga/yoga/YGValue.cpp +20 -0
- pythonnative/native/yoga/yoga/YGValue.h +84 -0
- pythonnative/native/yoga/yoga/Yoga.h +21 -0
- pythonnative/native/yoga/yoga/algorithm/AbsoluteLayout.cpp +563 -0
- pythonnative/native/yoga/yoga/algorithm/AbsoluteLayout.h +41 -0
- pythonnative/native/yoga/yoga/algorithm/Align.h +72 -0
- pythonnative/native/yoga/yoga/algorithm/Baseline.cpp +78 -0
- pythonnative/native/yoga/yoga/algorithm/Baseline.h +21 -0
- pythonnative/native/yoga/yoga/algorithm/BoundAxis.h +79 -0
- pythonnative/native/yoga/yoga/algorithm/Cache.cpp +121 -0
- pythonnative/native/yoga/yoga/algorithm/Cache.h +30 -0
- pythonnative/native/yoga/yoga/algorithm/CalculateLayout.cpp +2428 -0
- pythonnative/native/yoga/yoga/algorithm/CalculateLayout.h +38 -0
- pythonnative/native/yoga/yoga/algorithm/FlexDirection.h +120 -0
- pythonnative/native/yoga/yoga/algorithm/FlexLine.cpp +124 -0
- pythonnative/native/yoga/yoga/algorithm/FlexLine.h +75 -0
- pythonnative/native/yoga/yoga/algorithm/PixelGrid.cpp +132 -0
- pythonnative/native/yoga/yoga/algorithm/PixelGrid.h +29 -0
- pythonnative/native/yoga/yoga/algorithm/SizingMode.h +73 -0
- pythonnative/native/yoga/yoga/algorithm/TrailingPosition.h +44 -0
- pythonnative/native/yoga/yoga/config/Config.cpp +135 -0
- pythonnative/native/yoga/yoga/config/Config.h +92 -0
- pythonnative/native/yoga/yoga/debug/AssertFatal.cpp +53 -0
- pythonnative/native/yoga/yoga/debug/AssertFatal.h +29 -0
- pythonnative/native/yoga/yoga/debug/Log.cpp +107 -0
- pythonnative/native/yoga/yoga/debug/Log.h +34 -0
- pythonnative/native/yoga/yoga/enums/Align.h +47 -0
- pythonnative/native/yoga/yoga/enums/BoxSizing.h +40 -0
- pythonnative/native/yoga/yoga/enums/Dimension.h +40 -0
- pythonnative/native/yoga/yoga/enums/Direction.h +41 -0
- pythonnative/native/yoga/yoga/enums/Display.h +41 -0
- pythonnative/native/yoga/yoga/enums/Edge.h +47 -0
- pythonnative/native/yoga/yoga/enums/Errata.h +41 -0
- pythonnative/native/yoga/yoga/enums/ExperimentalFeature.h +39 -0
- pythonnative/native/yoga/yoga/enums/FlexDirection.h +42 -0
- pythonnative/native/yoga/yoga/enums/Gutter.h +41 -0
- pythonnative/native/yoga/yoga/enums/Justify.h +44 -0
- pythonnative/native/yoga/yoga/enums/LogLevel.h +44 -0
- pythonnative/native/yoga/yoga/enums/MeasureMode.h +41 -0
- pythonnative/native/yoga/yoga/enums/NodeType.h +40 -0
- pythonnative/native/yoga/yoga/enums/Overflow.h +41 -0
- pythonnative/native/yoga/yoga/enums/PhysicalEdge.h +21 -0
- pythonnative/native/yoga/yoga/enums/PositionType.h +41 -0
- pythonnative/native/yoga/yoga/enums/Unit.h +42 -0
- pythonnative/native/yoga/yoga/enums/Wrap.h +41 -0
- pythonnative/native/yoga/yoga/enums/YogaEnums.h +85 -0
- pythonnative/native/yoga/yoga/event/event.cpp +87 -0
- pythonnative/native/yoga/yoga/event/event.h +130 -0
- pythonnative/native/yoga/yoga/module.modulemap +21 -0
- pythonnative/native/yoga/yoga/node/CachedMeasurement.h +53 -0
- pythonnative/native/yoga/yoga/node/LayoutResults.cpp +48 -0
- pythonnative/native/yoga/yoga/node/LayoutResults.h +122 -0
- pythonnative/native/yoga/yoga/node/LayoutableChildren.h +148 -0
- pythonnative/native/yoga/yoga/node/Node.cpp +443 -0
- pythonnative/native/yoga/yoga/node/Node.h +337 -0
- pythonnative/native/yoga/yoga/numeric/Comparison.h +81 -0
- pythonnative/native/yoga/yoga/numeric/FloatOptional.h +93 -0
- pythonnative/native/yoga/yoga/style/SmallValueBuffer.h +133 -0
- pythonnative/native/yoga/yoga/style/Style.h +757 -0
- pythonnative/native/yoga/yoga/style/StyleLength.h +107 -0
- pythonnative/native/yoga/yoga/style/StyleValueHandle.h +98 -0
- pythonnative/native/yoga/yoga/style/StyleValuePool.h +127 -0
- pythonnative/native_modules/__init__.py +124 -0
- pythonnative/native_modules/app_state.py +99 -0
- pythonnative/native_modules/battery.py +75 -0
- pythonnative/native_modules/biometrics.py +42 -0
- pythonnative/native_modules/camera.py +65 -0
- pythonnative/native_modules/clipboard.py +46 -0
- pythonnative/native_modules/fallback.py +324 -0
- pythonnative/native_modules/file_system.py +145 -0
- pythonnative/native_modules/haptics.py +75 -0
- pythonnative/native_modules/linking.py +123 -0
- pythonnative/native_modules/location.py +75 -0
- pythonnative/native_modules/net_info.py +112 -0
- pythonnative/native_modules/notifications.py +129 -0
- pythonnative/native_modules/permissions.py +108 -0
- pythonnative/native_modules/registry.py +526 -0
- pythonnative/native_modules/secure_store.py +52 -0
- pythonnative/native_modules/share.py +51 -0
- pythonnative/native_views/__init__.py +375 -0
- pythonnative/native_views/base.py +316 -0
- pythonnative/native_views/bridge_backend.py +277 -0
- pythonnative/navigation/__init__.py +103 -0
- pythonnative/navigation/container.py +154 -0
- pythonnative/navigation/handle.py +540 -0
- pythonnative/navigation/hooks.py +133 -0
- pythonnative/navigation/host.py +58 -0
- pythonnative/navigation/linking.py +200 -0
- pythonnative/navigation/navigators.py +659 -0
- pythonnative/navigation/screen.py +149 -0
- pythonnative/navigation/state.py +269 -0
- pythonnative/net.py +248 -0
- pythonnative/platform.py +166 -0
- pythonnative/platform_metrics.py +252 -0
- pythonnative/preview.py +287 -0
- pythonnative/profiling.py +101 -0
- pythonnative/project/__init__.py +68 -0
- pythonnative/project/android.py +557 -0
- pythonnative/project/builder.py +817 -0
- pythonnative/project/config.py +773 -0
- pythonnative/project/deps.py +719 -0
- pythonnative/project/devices.py +304 -0
- pythonnative/project/doctor.py +283 -0
- pythonnative/project/fingerprint.py +171 -0
- pythonnative/project/icons.py +247 -0
- pythonnative/project/ios.py +325 -0
- pythonnative/project/lockfile.py +100 -0
- pythonnative/project/permissions.py +361 -0
- pythonnative/project/plugins.py +519 -0
- pythonnative/project/runtime_assets.py +183 -0
- pythonnative/py.typed +0 -0
- pythonnative/query.py +153 -0
- pythonnative/reconciler/__init__.py +29 -0
- pythonnative/reconciler/boundaries.py +375 -0
- pythonnative/reconciler/children.py +88 -0
- pythonnative/reconciler/core.py +1165 -0
- pythonnative/reconciler/layout_pass.py +393 -0
- pythonnative/reconciler/vnode.py +266 -0
- pythonnative/refresh.py +55 -0
- pythonnative/runtime.py +306 -0
- pythonnative/scheduler.py +159 -0
- pythonnative/sdk/__init__.py +153 -0
- pythonnative/sdk/_components.py +427 -0
- pythonnative/sdk/builtins.py +91 -0
- pythonnative/sdk/codegen.py +149 -0
- pythonnative/sdk/module_codegen.py +184 -0
- pythonnative/sdk/schema.py +224 -0
- pythonnative/sdk/templates/contracts.kt +46 -0
- pythonnative/sdk/templates/contracts.swift +46 -0
- pythonnative/storage.py +184 -0
- pythonnative/style.py +841 -0
- pythonnative/suspense.py +183 -0
- pythonnative/templates/android_template/app/build.gradle +75 -0
- pythonnative/templates/android_template/app/proguard-rules.pro +21 -0
- pythonnative/templates/android_template/app/src/androidTest/java/com/pythonnative/android_template/ExampleInstrumentedTest.kt +24 -0
- pythonnative/templates/android_template/app/src/debug/AndroidManifest.xml +7 -0
- pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +32 -0
- pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +130 -0
- pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/ScreenFragment.kt +13 -0
- pythonnative/templates/android_template/app/src/main/res/drawable/ic_launcher_background.xml +170 -0
- pythonnative/templates/android_template/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +30 -0
- pythonnative/templates/android_template/app/src/main/res/layout/activity_main.xml +10 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +6 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +6 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp +0 -0
- pythonnative/templates/android_template/app/src/main/res/navigation/nav_graph.xml +22 -0
- pythonnative/templates/android_template/app/src/main/res/values/colors.xml +5 -0
- pythonnative/templates/android_template/app/src/main/res/values/strings.xml +5 -0
- pythonnative/templates/android_template/app/src/main/res/values/themes.xml +9 -0
- pythonnative/templates/android_template/app/src/main/res/values-night/themes.xml +7 -0
- pythonnative/templates/android_template/app/src/main/res/xml/backup_rules.xml +13 -0
- pythonnative/templates/android_template/app/src/main/res/xml/data_extraction_rules.xml +19 -0
- pythonnative/templates/android_template/app/src/test/java/com/pythonnative/android_template/ExampleUnitTest.kt +17 -0
- pythonnative/templates/android_template/build.gradle +10 -0
- pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.jar +0 -0
- pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.properties +6 -0
- pythonnative/templates/android_template/gradle.properties +23 -0
- pythonnative/templates/android_template/gradlew +185 -0
- pythonnative/templates/android_template/gradlew.bat +89 -0
- pythonnative/templates/android_template/settings.gradle +17 -0
- pythonnative/templates/ios_template/ios_template/AppDelegate.swift +51 -0
- pythonnative/templates/ios_template/ios_template/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
- pythonnative/templates/ios_template/ios_template/Assets.xcassets/AppIcon.appiconset/Contents.json +13 -0
- pythonnative/templates/ios_template/ios_template/Assets.xcassets/Contents.json +6 -0
- pythonnative/templates/ios_template/ios_template/Base.lproj/LaunchScreen.storyboard +25 -0
- pythonnative/templates/ios_template/ios_template/BridgingHeader.h +14 -0
- pythonnative/templates/ios_template/ios_template/Info.plist +28 -0
- pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +390 -0
- pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +61 -0
- pythonnative/templates/ios_template/ios_template/ViewController.swift +23 -0
- pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +745 -0
- pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift +36 -0
- pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift +41 -0
- pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift +32 -0
- pythonnative/testing/__init__.py +53 -0
- pythonnative/testing/backend.py +276 -0
- pythonnative/testing/harness.py +369 -0
- pythonnative/utils.py +145 -0
- pythonnative-0.40.0.dist-info/DELVEWHEEL +2 -0
- pythonnative-0.40.0.dist-info/METADATA +150 -0
- pythonnative-0.40.0.dist-info/RECORD +418 -0
- pythonnative-0.40.0.dist-info/WHEEL +5 -0
- pythonnative-0.40.0.dist-info/entry_points.txt +2 -0
- pythonnative-0.40.0.dist-info/licenses/LICENSE +21 -0
- pythonnative-0.40.0.dist-info/top_level.txt +1 -0
- pythonnative.libs/msvcp140-a4c2229bdc2a2a630acdc095b4d86008.dll +0 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"""Revisioned native view backend.
|
|
2
|
+
|
|
3
|
+
Each commit is validated, sent as a protocol-2 envelope, and acknowledged before
|
|
4
|
+
Python updates its native tag index. Rejected commits poison the surface until
|
|
5
|
+
it is remounted. Native events carry application, revision, sequence, and text
|
|
6
|
+
edit identities. NativeViewRef holds a live native tag rather than a UI object.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import math
|
|
12
|
+
import uuid
|
|
13
|
+
from typing import Any, Dict, List, Optional, Sequence, Tuple
|
|
14
|
+
|
|
15
|
+
from ..bridge import codec, get_transport
|
|
16
|
+
from ..bridge.commits import PROTOCOL_VERSION, CommitError, CommitState
|
|
17
|
+
from ..mutations import CreateOp, DestroyOp, Mutation, UpdateOp
|
|
18
|
+
|
|
19
|
+
__all__ = ["BridgeBackend", "NativeViewRef"]
|
|
20
|
+
|
|
21
|
+
_MEASURE_UNBOUNDED = 1e6
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class NativeViewRef:
|
|
25
|
+
"""Opaque handle to a native view living on the other side of the bridge.
|
|
26
|
+
|
|
27
|
+
Attributes:
|
|
28
|
+
tag: The reconciler-assigned tag; pass it to
|
|
29
|
+
``Reconciler.dispatch_command`` or ``get_registry().command``.
|
|
30
|
+
type_name: The element type (``"Text"``, ``"ScrollView"``, ...).
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
__slots__ = ("tag", "type_name")
|
|
34
|
+
|
|
35
|
+
def __init__(self, tag: int, type_name: str) -> None:
|
|
36
|
+
self.tag = tag
|
|
37
|
+
self.type_name = type_name
|
|
38
|
+
|
|
39
|
+
def __repr__(self) -> str:
|
|
40
|
+
return f"<NativeViewRef {self.type_name} tag={self.tag}>"
|
|
41
|
+
|
|
42
|
+
def __int__(self) -> int:
|
|
43
|
+
return self.tag
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class BridgeBackend:
|
|
47
|
+
"""Registry protocol implementation that forwards to the native runtime."""
|
|
48
|
+
|
|
49
|
+
def __init__(self, transport: Any = None) -> None:
|
|
50
|
+
self._transport = transport
|
|
51
|
+
self._commit = CommitState(str(uuid.uuid4()), 1)
|
|
52
|
+
self._births: dict[int, int] = {}
|
|
53
|
+
self._event_sequences: dict[tuple[int, str], int] = {}
|
|
54
|
+
self._edit_revisions: dict[int, int] = {}
|
|
55
|
+
self._failed = False
|
|
56
|
+
self.on_layout: Any = None
|
|
57
|
+
self._types: Dict[int, str] = {}
|
|
58
|
+
self._refs: Dict[int, NativeViewRef] = {}
|
|
59
|
+
self._python_props: Dict[int, Dict[str, Any]] = {}
|
|
60
|
+
self._handlers: Dict[str, Any] = {}
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def transport(self) -> Any:
|
|
64
|
+
"""The transport in use (resolved lazily on first access)."""
|
|
65
|
+
if self._transport is None:
|
|
66
|
+
self._transport = get_transport()
|
|
67
|
+
return self._transport
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def native_layout(self) -> bool:
|
|
71
|
+
"""Whether layout runs beside the renderer's native widgets."""
|
|
72
|
+
return self.transport.name in {"ios", "android", "web"}
|
|
73
|
+
|
|
74
|
+
def compute_layout(self, roots: list[int], width: float, height: float) -> None:
|
|
75
|
+
"""Compute native Yoga layout in one request, returning changed frames."""
|
|
76
|
+
raw = self.transport.call(
|
|
77
|
+
"Layout", "compute", codec.dumps({"call_id": 0, "args": {"roots": roots, "width": width, "height": height}})
|
|
78
|
+
)
|
|
79
|
+
result = codec.loads(raw)
|
|
80
|
+
if not isinstance(result, dict) or not result.get("ok"):
|
|
81
|
+
raise CommitError(f"Native layout failed: {result!r}")
|
|
82
|
+
if self.on_layout is not None:
|
|
83
|
+
self.on_layout(result.get("value", []))
|
|
84
|
+
|
|
85
|
+
# ------------------------------------------------------------------
|
|
86
|
+
# Registration (kept for protocol parity with NativeViewRegistry)
|
|
87
|
+
# ------------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
def register(self, type_name: str, handler: Any) -> None:
|
|
90
|
+
"""Record a Python handler for diagnostics only.
|
|
91
|
+
|
|
92
|
+
On device, rendering is native; a Python ``ViewHandler`` can't
|
|
93
|
+
create platform views. The registration is kept so
|
|
94
|
+
``handler_for`` can answer introspection questions and so the
|
|
95
|
+
SDK's install step doesn't fail, but it is never invoked.
|
|
96
|
+
"""
|
|
97
|
+
self._handlers[type_name] = handler
|
|
98
|
+
|
|
99
|
+
def handler_for(self, type_name: str) -> Any:
|
|
100
|
+
"""Return the diagnostic Python handler registered for ``type_name``."""
|
|
101
|
+
return self._handlers.get(type_name)
|
|
102
|
+
|
|
103
|
+
# ------------------------------------------------------------------
|
|
104
|
+
# Tag table
|
|
105
|
+
# ------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
def resolve_view(self, tag: int) -> Optional[NativeViewRef]:
|
|
108
|
+
"""Return the handle for ``tag`` (``None`` if the view is gone)."""
|
|
109
|
+
return self._refs.get(tag)
|
|
110
|
+
|
|
111
|
+
def type_of(self, tag: int) -> Optional[str]:
|
|
112
|
+
"""Return the element type registered for ``tag``."""
|
|
113
|
+
return self._types.get(tag)
|
|
114
|
+
|
|
115
|
+
def live_view_count(self) -> int:
|
|
116
|
+
"""Number of views currently alive on the native side."""
|
|
117
|
+
return len(self._types)
|
|
118
|
+
|
|
119
|
+
def python_props(self, tag: int) -> Dict[str, Any]:
|
|
120
|
+
"""Props held Python-side for ``tag`` (callables never sent to native)."""
|
|
121
|
+
return self._python_props.get(tag, {})
|
|
122
|
+
|
|
123
|
+
# ------------------------------------------------------------------
|
|
124
|
+
# Commit channel
|
|
125
|
+
# ------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
def apply_mutations(self, ops: Sequence[Mutation]) -> None:
|
|
128
|
+
"""Serialize ``ops`` and apply them natively in one crossing."""
|
|
129
|
+
if not ops:
|
|
130
|
+
return
|
|
131
|
+
if self._failed:
|
|
132
|
+
raise CommitError("Native surface failed; remount the application with a new backend")
|
|
133
|
+
payload, sidecar = codec.encode_transaction(ops)
|
|
134
|
+
wire_ops = codec.loads(payload)
|
|
135
|
+
for op in wire_ops:
|
|
136
|
+
if op[0] == "u" and self._types.get(op[1]) == "TextInput" and "value" in op[2]:
|
|
137
|
+
op[2]["_pn_edit_revision"] = self._edit_revisions.get(op[1], 0)
|
|
138
|
+
envelope = {
|
|
139
|
+
"version": PROTOCOL_VERSION,
|
|
140
|
+
"application": self._commit.application,
|
|
141
|
+
"surface": self._commit.surface,
|
|
142
|
+
"revision": self._commit.revision + 1,
|
|
143
|
+
"ops": wire_ops,
|
|
144
|
+
}
|
|
145
|
+
from ..profiling import count
|
|
146
|
+
|
|
147
|
+
count("bridge.commits")
|
|
148
|
+
count("bridge.operations", len(ops))
|
|
149
|
+
count("bridge.bytes", len(payload.encode("utf-8")))
|
|
150
|
+
candidate = self._commit.prepare(envelope)
|
|
151
|
+
try:
|
|
152
|
+
ack = codec.loads(self.transport.apply(codec.dumps(envelope)))
|
|
153
|
+
if ack != candidate.acknowledgement():
|
|
154
|
+
raise CommitError(f"Native commit {candidate.revision} rejected: {ack!r}")
|
|
155
|
+
except Exception:
|
|
156
|
+
self._failed = True
|
|
157
|
+
raise
|
|
158
|
+
self._commit = candidate
|
|
159
|
+
destroyed: List[int] = []
|
|
160
|
+
for op in ops:
|
|
161
|
+
if isinstance(op, CreateOp):
|
|
162
|
+
self._types[op.tag] = op.type_name
|
|
163
|
+
self._births[op.tag] = candidate.revision
|
|
164
|
+
self._refs[op.tag] = NativeViewRef(op.tag, op.type_name)
|
|
165
|
+
elif isinstance(op, DestroyOp):
|
|
166
|
+
destroyed.append(op.tag)
|
|
167
|
+
for tag, props in sidecar:
|
|
168
|
+
self._python_props.setdefault(tag, {}).update(props)
|
|
169
|
+
for op in ops:
|
|
170
|
+
if isinstance(op, UpdateOp):
|
|
171
|
+
# A prop that changed from a callable to None arrives
|
|
172
|
+
# as None in the wire dict; drop the stale sidecar copy.
|
|
173
|
+
bucket = self._python_props.get(op.tag)
|
|
174
|
+
if bucket:
|
|
175
|
+
for key, value in op.changed_props.items():
|
|
176
|
+
if value is None:
|
|
177
|
+
bucket.pop(key, None)
|
|
178
|
+
if not bucket:
|
|
179
|
+
self._python_props.pop(op.tag, None)
|
|
180
|
+
for tag in destroyed:
|
|
181
|
+
self._forget(tag)
|
|
182
|
+
|
|
183
|
+
def accept_event(self, tag: int, name: str, envelope: Any) -> bool:
|
|
184
|
+
"""Reject events from destroyed views, earlier applications, and replayed input."""
|
|
185
|
+
if self._failed or not isinstance(envelope, dict):
|
|
186
|
+
return False
|
|
187
|
+
if envelope.get("application") != self._commit.application or envelope.get("surface") != self._commit.surface:
|
|
188
|
+
return False
|
|
189
|
+
revision, sequence = envelope.get("revision"), envelope.get("sequence")
|
|
190
|
+
if type(revision) is not int or type(sequence) is not int or tag not in self._births:
|
|
191
|
+
return False
|
|
192
|
+
key = (tag, name)
|
|
193
|
+
if not self._births[tag] <= revision <= self._commit.revision or sequence <= self._event_sequences.get(key, 0):
|
|
194
|
+
return False
|
|
195
|
+
self._event_sequences[key] = sequence
|
|
196
|
+
if name == "on_change" and self._types.get(tag) == "TextInput":
|
|
197
|
+
edit = envelope.get("edit_revision")
|
|
198
|
+
if type(edit) is int:
|
|
199
|
+
self._edit_revisions[tag] = max(edit, self._edit_revisions.get(tag, 0))
|
|
200
|
+
return isinstance(envelope.get("args"), list)
|
|
201
|
+
|
|
202
|
+
def _forget(self, tag: int) -> None:
|
|
203
|
+
self._types.pop(tag, None)
|
|
204
|
+
self._births.pop(tag, None)
|
|
205
|
+
self._edit_revisions.pop(tag, None)
|
|
206
|
+
for key in tuple(self._event_sequences):
|
|
207
|
+
if key[0] == tag:
|
|
208
|
+
del self._event_sequences[key]
|
|
209
|
+
self._refs.pop(tag, None)
|
|
210
|
+
self._python_props.pop(tag, None)
|
|
211
|
+
|
|
212
|
+
# ------------------------------------------------------------------
|
|
213
|
+
# Imperative escape hatches
|
|
214
|
+
# ------------------------------------------------------------------
|
|
215
|
+
|
|
216
|
+
def measure_intrinsic(self, tag: int, max_width: float, max_height: float) -> Tuple[float, float]:
|
|
217
|
+
"""Ask native for the natural size of ``tag`` under the constraints."""
|
|
218
|
+
if tag not in self._types:
|
|
219
|
+
return (0.0, 0.0)
|
|
220
|
+
w, h = self.transport.measure(tag, _bound(max_width), _bound(max_height))
|
|
221
|
+
return (max(0.0, float(w)), max(0.0, float(h)))
|
|
222
|
+
|
|
223
|
+
def command(self, tag: int, name: str, args: Optional[Dict[str, Any]] = None) -> Any:
|
|
224
|
+
"""Run an imperative command on one view; returns its JSON result or ``None``."""
|
|
225
|
+
if tag not in self._types:
|
|
226
|
+
raise CommitError(f"Command {name!r} addressed stale view {tag}")
|
|
227
|
+
result = self.transport.command(tag, name, codec.dumps(codec.to_jsonable(args or {})))
|
|
228
|
+
return codec.loads(result)
|
|
229
|
+
|
|
230
|
+
def set_animated_property(self, tag: int, prop_name: str, value: Any) -> None:
|
|
231
|
+
"""Write one animated property value without animating (a Python-driven frame)."""
|
|
232
|
+
if tag not in self._types:
|
|
233
|
+
return
|
|
234
|
+
self.transport.animate(tag, codec.dumps({"op": "set", "prop": prop_name, "value": codec.to_jsonable(value)}))
|
|
235
|
+
|
|
236
|
+
def install_animation_graph(self, tag: int, graph: dict[str, Any]) -> None:
|
|
237
|
+
"""Install native expression nodes and view bindings in one crossing."""
|
|
238
|
+
if tag in self._types:
|
|
239
|
+
self.transport.animate(tag, codec.dumps({"op": "graph", "graph": graph}))
|
|
240
|
+
|
|
241
|
+
def start_animation(self, tag: int, anim_id: int, prop_name: str, spec: Dict[str, Any]) -> bool:
|
|
242
|
+
"""Start a native-driven animation; returns whether native accepted it."""
|
|
243
|
+
if tag not in self._types:
|
|
244
|
+
return False
|
|
245
|
+
request = {"op": "start", "id": int(anim_id), "prop": prop_name, "spec": codec.to_jsonable(spec)}
|
|
246
|
+
result = codec.loads(self.transport.animate(tag, codec.dumps(request)))
|
|
247
|
+
return bool(isinstance(result, dict) and result.get("ok"))
|
|
248
|
+
|
|
249
|
+
def cancel_animation(self, tag: int, anim_id: int) -> Any:
|
|
250
|
+
"""Cancel a native animation and return its presentation value, if known."""
|
|
251
|
+
if tag not in self._types:
|
|
252
|
+
return None
|
|
253
|
+
result = codec.loads(self.transport.animate(tag, codec.dumps({"op": "cancel", "id": int(anim_id)})))
|
|
254
|
+
if isinstance(result, dict):
|
|
255
|
+
return result.get("value")
|
|
256
|
+
return None
|
|
257
|
+
|
|
258
|
+
def reset(self) -> None:
|
|
259
|
+
"""Forget a disconnected surface before the host remounts its tree."""
|
|
260
|
+
self._types.clear()
|
|
261
|
+
self._refs.clear()
|
|
262
|
+
self._python_props.clear()
|
|
263
|
+
self._commit = CommitState(str(uuid.uuid4()), 1)
|
|
264
|
+
self._births: dict[int, int] = {}
|
|
265
|
+
self._event_sequences: dict[tuple[int, str], int] = {}
|
|
266
|
+
self._failed = False
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _bound(value: float) -> float:
|
|
270
|
+
"""Clamp ``math.inf`` to the wire's "unconstrained" sentinel."""
|
|
271
|
+
try:
|
|
272
|
+
f = float(value)
|
|
273
|
+
except (TypeError, ValueError):
|
|
274
|
+
return _MEASURE_UNBOUNDED
|
|
275
|
+
if not math.isfinite(f) or f > _MEASURE_UNBOUNDED:
|
|
276
|
+
return _MEASURE_UNBOUNDED
|
|
277
|
+
return max(0.0, f)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Navigation: stack, tab, and drawer navigators with a React Navigation-style API.
|
|
2
|
+
|
|
3
|
+
```python
|
|
4
|
+
import pythonnative as pn
|
|
5
|
+
|
|
6
|
+
Stack = pn.create_stack_navigator()
|
|
7
|
+
|
|
8
|
+
@pn.component
|
|
9
|
+
def HomeScreen():
|
|
10
|
+
nav = pn.use_navigation()
|
|
11
|
+
return pn.Button("Open 42", on_press=lambda: nav.navigate("Detail", id=42))
|
|
12
|
+
|
|
13
|
+
@pn.component
|
|
14
|
+
def DetailScreen():
|
|
15
|
+
route = pn.use_route()
|
|
16
|
+
return pn.Text(f"Item {route.params['id']}")
|
|
17
|
+
|
|
18
|
+
@pn.component
|
|
19
|
+
def App():
|
|
20
|
+
return pn.NavigationContainer(
|
|
21
|
+
Stack.Navigator(
|
|
22
|
+
Stack.Screen("Home", HomeScreen, title="Home"),
|
|
23
|
+
Stack.Screen("Detail", DetailScreen, options=lambda route: {"title": f"Item {route.params['id']}"}),
|
|
24
|
+
)
|
|
25
|
+
)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Public surface (all re-exported from ``pythonnative``):
|
|
29
|
+
|
|
30
|
+
- Factories: [`create_stack_navigator`][pythonnative.create_stack_navigator],
|
|
31
|
+
[`create_tab_navigator`][pythonnative.create_tab_navigator],
|
|
32
|
+
[`create_drawer_navigator`][pythonnative.create_drawer_navigator],
|
|
33
|
+
[`NavigationContainer`][pythonnative.NavigationContainer].
|
|
34
|
+
- Hooks: [`use_navigation`][pythonnative.use_navigation],
|
|
35
|
+
[`use_route`][pythonnative.use_route],
|
|
36
|
+
[`use_is_focused`][pythonnative.use_is_focused],
|
|
37
|
+
[`use_focus_effect`][pythonnative.use_focus_effect].
|
|
38
|
+
- Types: [`Navigation`][pythonnative.Navigation],
|
|
39
|
+
[`Route`][pythonnative.navigation.Route],
|
|
40
|
+
[`NavigationState`][pythonnative.navigation.NavigationState],
|
|
41
|
+
[`ScreenOptions`][pythonnative.ScreenOptions],
|
|
42
|
+
[`LinkingConfig`][pythonnative.LinkingConfig].
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
from .container import ContainerContext, NavigationContainer
|
|
46
|
+
from .handle import (
|
|
47
|
+
DrawerNavigation,
|
|
48
|
+
EventName,
|
|
49
|
+
FocusContext,
|
|
50
|
+
HostNavigator,
|
|
51
|
+
Navigation,
|
|
52
|
+
NavigationContext,
|
|
53
|
+
NavigationEvent,
|
|
54
|
+
NavigatorCore,
|
|
55
|
+
TabNavigation,
|
|
56
|
+
)
|
|
57
|
+
from .hooks import use_focus_effect, use_is_focused, use_navigation, use_route
|
|
58
|
+
from .host import NAV_STATE_ARG, HostContext, HostRoot
|
|
59
|
+
from .linking import LinkingConfig
|
|
60
|
+
from .navigators import (
|
|
61
|
+
DrawerNavigator,
|
|
62
|
+
StackNavigator,
|
|
63
|
+
TabNavigator,
|
|
64
|
+
create_drawer_navigator,
|
|
65
|
+
create_stack_navigator,
|
|
66
|
+
create_tab_navigator,
|
|
67
|
+
)
|
|
68
|
+
from .screen import HeaderSlot, ScreenDef, ScreenOptions
|
|
69
|
+
from .state import NavigationState, Route, RouteParams
|
|
70
|
+
|
|
71
|
+
__all__ = [
|
|
72
|
+
"NAV_STATE_ARG",
|
|
73
|
+
"ContainerContext",
|
|
74
|
+
"DrawerNavigation",
|
|
75
|
+
"DrawerNavigator",
|
|
76
|
+
"EventName",
|
|
77
|
+
"FocusContext",
|
|
78
|
+
"HeaderSlot",
|
|
79
|
+
"HostContext",
|
|
80
|
+
"HostNavigator",
|
|
81
|
+
"HostRoot",
|
|
82
|
+
"LinkingConfig",
|
|
83
|
+
"Navigation",
|
|
84
|
+
"NavigationContainer",
|
|
85
|
+
"NavigationContext",
|
|
86
|
+
"NavigationEvent",
|
|
87
|
+
"NavigationState",
|
|
88
|
+
"NavigatorCore",
|
|
89
|
+
"Route",
|
|
90
|
+
"RouteParams",
|
|
91
|
+
"ScreenDef",
|
|
92
|
+
"ScreenOptions",
|
|
93
|
+
"StackNavigator",
|
|
94
|
+
"TabNavigation",
|
|
95
|
+
"TabNavigator",
|
|
96
|
+
"create_drawer_navigator",
|
|
97
|
+
"create_stack_navigator",
|
|
98
|
+
"create_tab_navigator",
|
|
99
|
+
"use_focus_effect",
|
|
100
|
+
"use_is_focused",
|
|
101
|
+
"use_navigation",
|
|
102
|
+
"use_route",
|
|
103
|
+
]
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""``NavigationContainer``: the root of a navigator tree.
|
|
2
|
+
|
|
3
|
+
The container wires the root navigator to the outside world: deep links
|
|
4
|
+
(via [`LinkingConfig`][pythonnative.LinkingConfig]), a caller-supplied
|
|
5
|
+
initial state, and ``on_state_change`` / ``on_ready`` callbacks. Every
|
|
6
|
+
app with navigation renders exactly one container at the top.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Any, Callable, Mapping, Optional, Union
|
|
12
|
+
|
|
13
|
+
from ..component import component
|
|
14
|
+
from ..element import Element, Node
|
|
15
|
+
from ..hooks import Context, create_context, use_effect, use_memo, use_ref
|
|
16
|
+
from .linking import LinkingConfig
|
|
17
|
+
from .state import NavigationState
|
|
18
|
+
|
|
19
|
+
__all__ = ["ContainerContext", "NavigationContainer"]
|
|
20
|
+
|
|
21
|
+
StateLike = Union[NavigationState, Mapping[str, Any]]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ContainerConfig:
|
|
25
|
+
"""What a root navigator reads from its enclosing container."""
|
|
26
|
+
|
|
27
|
+
__slots__ = ("initial_state", "on_state_change", "on_ready", "_root", "_ready")
|
|
28
|
+
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
initial_state: Optional[NavigationState],
|
|
32
|
+
on_state_change: Optional[Callable[[NavigationState], None]],
|
|
33
|
+
on_ready: Optional[Callable[[], None]],
|
|
34
|
+
) -> None:
|
|
35
|
+
self.initial_state = initial_state
|
|
36
|
+
self.on_state_change = on_state_change
|
|
37
|
+
self.on_ready = on_ready
|
|
38
|
+
self._root: Any = None
|
|
39
|
+
self._ready = False
|
|
40
|
+
|
|
41
|
+
def attach_root(self, core: Any) -> Callable[[], None]:
|
|
42
|
+
"""Register the root navigator core; returns a detach callable."""
|
|
43
|
+
self._root = core
|
|
44
|
+
if not self._ready:
|
|
45
|
+
self._ready = True
|
|
46
|
+
if self.on_ready is not None:
|
|
47
|
+
self.on_ready()
|
|
48
|
+
|
|
49
|
+
def detach() -> None:
|
|
50
|
+
if self._root is core:
|
|
51
|
+
self._root = None
|
|
52
|
+
|
|
53
|
+
return detach
|
|
54
|
+
|
|
55
|
+
def dispatch_seed(self, seed: NavigationState) -> bool:
|
|
56
|
+
"""Route a deep-link state to the root navigator (``False`` if none is mounted)."""
|
|
57
|
+
if self._root is None:
|
|
58
|
+
return False
|
|
59
|
+
target = seed.current
|
|
60
|
+
self._root.navigate(target.name, target.params, target.state)
|
|
61
|
+
return True
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
ContainerContext: Context[Optional[ContainerConfig]] = create_context(None, name="NavigationContainer")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _coerce_state(value: Optional[StateLike]) -> Optional[NavigationState]:
|
|
68
|
+
if value is None or isinstance(value, NavigationState):
|
|
69
|
+
return value
|
|
70
|
+
try:
|
|
71
|
+
return NavigationState.from_dict(value)
|
|
72
|
+
except Exception:
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@component
|
|
77
|
+
def NavigationContainer(
|
|
78
|
+
*children: Node,
|
|
79
|
+
linking: Optional[LinkingConfig] = None,
|
|
80
|
+
initial_state: Optional[StateLike] = None,
|
|
81
|
+
on_state_change: Optional[Callable[[NavigationState], None]] = None,
|
|
82
|
+
on_ready: Optional[Callable[[], None]] = None,
|
|
83
|
+
) -> Element:
|
|
84
|
+
"""Root of a navigator tree.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
*children: The root navigator (a ``Stack.Navigator``, ``Tab.Navigator``,
|
|
88
|
+
or ``Drawer.Navigator``) and anything rendered alongside it.
|
|
89
|
+
linking: Deep-link configuration. The URL the app was launched
|
|
90
|
+
with seeds the initial state; URLs that arrive later are
|
|
91
|
+
dispatched as ``navigate`` calls.
|
|
92
|
+
initial_state: Explicit initial state for the root navigator
|
|
93
|
+
(a ``NavigationState`` or its ``to_dict()`` form). Takes
|
|
94
|
+
precedence over the launch URL. State restored by a native
|
|
95
|
+
host (a pushed native screen re-entering Python) takes
|
|
96
|
+
precedence over both.
|
|
97
|
+
on_state_change: Called with the root navigator's state after
|
|
98
|
+
every change. Persist ``state.to_dict()`` to restore later.
|
|
99
|
+
on_ready: Called once the root navigator has mounted.
|
|
100
|
+
|
|
101
|
+
Example:
|
|
102
|
+
```python
|
|
103
|
+
Stack = pn.create_stack_navigator()
|
|
104
|
+
|
|
105
|
+
@pn.component
|
|
106
|
+
def App():
|
|
107
|
+
return pn.NavigationContainer(
|
|
108
|
+
Stack.Navigator(
|
|
109
|
+
Stack.Screen("Home", HomeScreen),
|
|
110
|
+
Stack.Screen("Detail", DetailScreen, options={"title": "Detail"}),
|
|
111
|
+
),
|
|
112
|
+
linking=linking,
|
|
113
|
+
)
|
|
114
|
+
```
|
|
115
|
+
"""
|
|
116
|
+
coerced = _coerce_state(initial_state)
|
|
117
|
+
|
|
118
|
+
def build() -> ContainerConfig:
|
|
119
|
+
seed = coerced
|
|
120
|
+
if seed is None and linking is not None:
|
|
121
|
+
from ..native_modules.linking import Linking
|
|
122
|
+
|
|
123
|
+
url = Linking.get_initial_url()
|
|
124
|
+
if url:
|
|
125
|
+
seed = linking.state_from_url(url)
|
|
126
|
+
return ContainerConfig(seed, on_state_change, on_ready)
|
|
127
|
+
|
|
128
|
+
config = use_memo(build, [])
|
|
129
|
+
config.on_state_change = on_state_change
|
|
130
|
+
config.on_ready = on_ready
|
|
131
|
+
|
|
132
|
+
initial_url: Any = use_ref(None)
|
|
133
|
+
|
|
134
|
+
def subscribe() -> Optional[Callable[[], None]]:
|
|
135
|
+
if linking is None:
|
|
136
|
+
return None
|
|
137
|
+
from ..native_modules.linking import Linking
|
|
138
|
+
|
|
139
|
+
initial_url.current = Linking.get_initial_url()
|
|
140
|
+
|
|
141
|
+
def on_url(url: str) -> None:
|
|
142
|
+
# The initial URL already seeded the state; don't navigate twice.
|
|
143
|
+
if url == initial_url.current:
|
|
144
|
+
initial_url.current = None
|
|
145
|
+
return
|
|
146
|
+
seed = linking.state_from_url(url)
|
|
147
|
+
if seed is not None:
|
|
148
|
+
config.dispatch_seed(seed)
|
|
149
|
+
|
|
150
|
+
return Linking.add_listener(on_url)
|
|
151
|
+
|
|
152
|
+
use_effect(subscribe, [linking])
|
|
153
|
+
|
|
154
|
+
return ContainerContext.Provider(config, *children)
|