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,123 @@
|
|
|
1
|
+
"""Open URLs, deep links, and the system settings page.
|
|
2
|
+
|
|
3
|
+
[`Linking`][pythonnative.Linking] wraps ``UIApplication.openURL`` /
|
|
4
|
+
``Intent(ACTION_VIEW)`` (in the native ``Linking`` module) so a Python
|
|
5
|
+
app can hand a URL (``https:``, ``mailto:``, ``tel:``, a custom
|
|
6
|
+
scheme, ...) to the OS.
|
|
7
|
+
|
|
8
|
+
Outbound methods hand the URL to the OS and return at once, so they
|
|
9
|
+
are synchronous; the ``bool`` says whether the platform accepted the
|
|
10
|
+
request. Off device they return ``False``.
|
|
11
|
+
|
|
12
|
+
Inbound deep links flow the other way: declare your schemes in
|
|
13
|
+
``pythonnative.toml`` (``app.url_schemes``) and the native module
|
|
14
|
+
pushes a ``url`` event for every URL that opens the app, which lands in
|
|
15
|
+
[`dispatch_url`][pythonnative.native_modules.linking.dispatch_url]. The
|
|
16
|
+
URL that cold-started the app is kept and returned by
|
|
17
|
+
``get_initial_url``; later URLs reach subscribers added with
|
|
18
|
+
``add_listener``.
|
|
19
|
+
|
|
20
|
+
Example:
|
|
21
|
+
```python
|
|
22
|
+
import pythonnative as pn
|
|
23
|
+
|
|
24
|
+
if url := pn.Linking.get_initial_url():
|
|
25
|
+
navigate_to(url)
|
|
26
|
+
|
|
27
|
+
unsubscribe = pn.Linking.add_listener(navigate_to)
|
|
28
|
+
```
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
from typing import Any, Callable, List, Optional
|
|
34
|
+
|
|
35
|
+
from .registry import native_module, on_event
|
|
36
|
+
|
|
37
|
+
_initial_url: Optional[str] = None
|
|
38
|
+
_url_listeners: List[Callable[[str], None]] = []
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _call_bool(method: str, **args: Any) -> bool:
|
|
42
|
+
return bool(native_module("Linking").call(method, **args))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class Linking:
|
|
46
|
+
"""System URL / deep-link interface (synchronous).
|
|
47
|
+
|
|
48
|
+
Raises:
|
|
49
|
+
NativeModuleError: If the native module fails.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def open_url(url: str) -> bool:
|
|
54
|
+
"""Hand ``url`` to the OS. Returns ``True`` if it was accepted."""
|
|
55
|
+
return _call_bool("open_url", url=url)
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def can_open_url(url: str) -> bool:
|
|
59
|
+
"""Return ``True`` when some installed app can handle ``url``."""
|
|
60
|
+
return _call_bool("can_open_url", url=url)
|
|
61
|
+
|
|
62
|
+
@staticmethod
|
|
63
|
+
def open_settings() -> bool:
|
|
64
|
+
"""Open this app's entry in the system Settings app."""
|
|
65
|
+
return _call_bool("open_settings")
|
|
66
|
+
|
|
67
|
+
@staticmethod
|
|
68
|
+
def get_initial_url() -> Optional[str]:
|
|
69
|
+
"""Return the URL that launched the app, if any."""
|
|
70
|
+
return _initial_url
|
|
71
|
+
|
|
72
|
+
@staticmethod
|
|
73
|
+
def add_listener(callback: Callable[[str], None]) -> Callable[[], None]:
|
|
74
|
+
"""Subscribe to deep links that arrive while the app is running.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
callback: Called with the full URL string for every inbound
|
|
78
|
+
deep link (including the initial one, which is
|
|
79
|
+
dispatched right after startup).
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
A zero-arg function that unsubscribes when called.
|
|
83
|
+
"""
|
|
84
|
+
_url_listeners.append(callback)
|
|
85
|
+
|
|
86
|
+
def _unsubscribe() -> None:
|
|
87
|
+
try:
|
|
88
|
+
_url_listeners.remove(callback)
|
|
89
|
+
except ValueError:
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
return _unsubscribe
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def set_initial_url(url: Optional[str]) -> None:
|
|
96
|
+
"""Record the launch URL (or clear it with ``None``)."""
|
|
97
|
+
global _initial_url
|
|
98
|
+
_initial_url = url
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def dispatch_url(url: str) -> None:
|
|
102
|
+
"""Deliver an inbound deep link.
|
|
103
|
+
|
|
104
|
+
The first URL ever dispatched is also recorded as the initial URL
|
|
105
|
+
(a cold start from a deep link reaches Python only after the
|
|
106
|
+
interpreter boots, so native can't report it earlier than this).
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
url: The full URL string that opened the app.
|
|
110
|
+
"""
|
|
111
|
+
global _initial_url
|
|
112
|
+
if _initial_url is None:
|
|
113
|
+
_initial_url = url
|
|
114
|
+
for listener in list(_url_listeners):
|
|
115
|
+
try:
|
|
116
|
+
listener(url)
|
|
117
|
+
except Exception as exc:
|
|
118
|
+
from .. import diagnostics
|
|
119
|
+
|
|
120
|
+
diagnostics.warn(f"Linking listener raised while handling {url!r}: {exc!r}")
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
on_event("Linking", "url", lambda payload: dispatch_url(str(payload)))
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Cross-platform location / GPS access.
|
|
2
|
+
|
|
3
|
+
[`Location.get_current`][pythonnative.native_modules.location.Location.get_current]
|
|
4
|
+
is a coroutine that resolves to a ``(latitude, longitude)`` tuple, or
|
|
5
|
+
``None`` if no fix is available (the user denied permission, location
|
|
6
|
+
services are off, or the request timed out).
|
|
7
|
+
The native ``Location`` module owns the ``CLLocationManager`` /
|
|
8
|
+
``LocationManager`` session and resolves the call with
|
|
9
|
+
``{"latitude", "longitude", "accuracy", "altitude", "timestamp"}``.
|
|
10
|
+
|
|
11
|
+
Permission prompts are triggered the first time a location-using API
|
|
12
|
+
is called; ensure the appropriate manifest entries
|
|
13
|
+
(``android.permission.ACCESS_FINE_LOCATION``) and Info.plist keys
|
|
14
|
+
(``NSLocationWhenInUseUsageDescription``) are present.
|
|
15
|
+
|
|
16
|
+
Example:
|
|
17
|
+
```python
|
|
18
|
+
import pythonnative as pn
|
|
19
|
+
|
|
20
|
+
async def show_position():
|
|
21
|
+
coords = await pn.Location.get_current()
|
|
22
|
+
if coords is None:
|
|
23
|
+
return
|
|
24
|
+
lat, lon = coords
|
|
25
|
+
print(f"You are at {lat:.5f}, {lon:.5f}")
|
|
26
|
+
```
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
from typing import Any, Dict, Optional, Tuple
|
|
32
|
+
|
|
33
|
+
from .registry import NativeModuleError, native_module
|
|
34
|
+
|
|
35
|
+
Coords = Tuple[float, float]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class Location:
|
|
39
|
+
"""GPS / location-services interface."""
|
|
40
|
+
|
|
41
|
+
@staticmethod
|
|
42
|
+
async def get_current(**options: Any) -> Optional[Coords]:
|
|
43
|
+
"""Request the device's current location.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
**options: Forwarded to the native module (``accuracy``,
|
|
47
|
+
``timeout``). Unknown keys are ignored.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
``(latitude, longitude)`` if a fix was obtained, otherwise
|
|
51
|
+
``None``.
|
|
52
|
+
|
|
53
|
+
Raises:
|
|
54
|
+
NativeModuleError: If the native module fails.
|
|
55
|
+
"""
|
|
56
|
+
fix = await Location.get_current_fix(**options)
|
|
57
|
+
if fix is None:
|
|
58
|
+
return None
|
|
59
|
+
return (fix["latitude"], fix["longitude"])
|
|
60
|
+
|
|
61
|
+
@staticmethod
|
|
62
|
+
async def get_current_fix(**options: Any) -> Optional[Dict[str, float]]:
|
|
63
|
+
"""Like ``get_current`` but returns the full fix dict.
|
|
64
|
+
|
|
65
|
+
Keys: ``latitude``, ``longitude``, and when the platform reports
|
|
66
|
+
them ``accuracy`` (meters), ``altitude`` (meters), ``speed``
|
|
67
|
+
(m/s), ``heading`` (degrees), ``timestamp`` (Unix seconds).
|
|
68
|
+
"""
|
|
69
|
+
result = await native_module("Location").call_async("get_current", **options)
|
|
70
|
+
if not isinstance(result, dict):
|
|
71
|
+
return None
|
|
72
|
+
fix: Dict[str, float] = {k: float(v) for k, v in result.items() if v is not None}
|
|
73
|
+
if "latitude" not in fix or "longitude" not in fix:
|
|
74
|
+
raise NativeModuleError("Location", "get_current", f"fix is missing coordinates: {sorted(result)}")
|
|
75
|
+
return fix
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""Network connectivity state.
|
|
2
|
+
|
|
3
|
+
[`NetInfo`][pythonnative.NetInfo] reports whether the device is online
|
|
4
|
+
and over what kind of connection. ``fetch`` returns a snapshot dict;
|
|
5
|
+
``add_listener`` (and the [`use_net_info`][pythonnative.use_net_info]
|
|
6
|
+
hook) deliver live updates pushed by the native ``NetInfo`` module
|
|
7
|
+
(``NWPathMonitor`` on iOS, ``ConnectivityManager.NetworkCallback`` on
|
|
8
|
+
Android) as ``change`` events. Off device, tests push snapshots through
|
|
9
|
+
[`dispatch_net_info`][pythonnative.native_modules.net_info.dispatch_net_info].
|
|
10
|
+
|
|
11
|
+
A snapshot looks like::
|
|
12
|
+
|
|
13
|
+
{"is_connected": True, "type": "wifi", "is_internet_reachable": True}
|
|
14
|
+
|
|
15
|
+
``type`` is one of ``"wifi"``, ``"cellular"``, ``"ethernet"``,
|
|
16
|
+
``"none"``, or ``"unknown"``.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from typing import Any, Callable, Dict, List
|
|
22
|
+
|
|
23
|
+
from .. import diagnostics
|
|
24
|
+
from ..hooks import use_effect, use_state
|
|
25
|
+
from .registry import native_module, on_event
|
|
26
|
+
|
|
27
|
+
NetInfoState = Dict[str, object]
|
|
28
|
+
|
|
29
|
+
_listeners: List[Callable[[NetInfoState], None]] = []
|
|
30
|
+
_last_state: NetInfoState = {
|
|
31
|
+
"is_connected": True,
|
|
32
|
+
"type": "unknown",
|
|
33
|
+
"is_internet_reachable": True,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class NetInfo:
|
|
38
|
+
"""Network connectivity interface."""
|
|
39
|
+
|
|
40
|
+
@staticmethod
|
|
41
|
+
def fetch() -> NetInfoState:
|
|
42
|
+
"""Return a fresh snapshot of connectivity state."""
|
|
43
|
+
global _last_state
|
|
44
|
+
snapshot = native_module("NetInfo").call("fetch")
|
|
45
|
+
if isinstance(snapshot, dict):
|
|
46
|
+
_last_state = _normalize(snapshot)
|
|
47
|
+
return dict(_last_state)
|
|
48
|
+
|
|
49
|
+
@staticmethod
|
|
50
|
+
def add_listener(callback: Callable[[NetInfoState], None]) -> Callable[[], None]:
|
|
51
|
+
"""Subscribe to connectivity changes; returns an unsubscribe fn."""
|
|
52
|
+
_listeners.append(callback)
|
|
53
|
+
|
|
54
|
+
def _unsubscribe() -> None:
|
|
55
|
+
try:
|
|
56
|
+
_listeners.remove(callback)
|
|
57
|
+
except ValueError:
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
return _unsubscribe
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _normalize(snapshot: Dict[str, Any]) -> NetInfoState:
|
|
64
|
+
return {
|
|
65
|
+
"is_connected": bool(snapshot.get("is_connected", False)),
|
|
66
|
+
"type": str(snapshot.get("type", "unknown")),
|
|
67
|
+
"is_internet_reachable": bool(snapshot.get("is_internet_reachable", False)),
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def dispatch_net_info(state: NetInfoState) -> None:
|
|
72
|
+
"""Push a new connectivity snapshot and notify listeners."""
|
|
73
|
+
global _last_state
|
|
74
|
+
_last_state = dict(state)
|
|
75
|
+
for listener in list(_listeners):
|
|
76
|
+
try:
|
|
77
|
+
listener(dict(state))
|
|
78
|
+
except Exception:
|
|
79
|
+
diagnostics.swallowed("net_info.dispatch_net_info")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _on_native_change(payload: Any) -> None:
|
|
83
|
+
if not isinstance(payload, dict):
|
|
84
|
+
return
|
|
85
|
+
state = _normalize(payload)
|
|
86
|
+
if state == _last_state:
|
|
87
|
+
return
|
|
88
|
+
dispatch_net_info(state)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
on_event("NetInfo", "change", _on_native_change)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def use_net_info() -> NetInfoState:
|
|
95
|
+
"""Subscribe a component to [`NetInfo`][pythonnative.NetInfo].
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
The latest connectivity snapshot dict; the component
|
|
99
|
+
re-renders whenever connectivity changes.
|
|
100
|
+
"""
|
|
101
|
+
state, set_state = use_state(NetInfo.fetch)
|
|
102
|
+
|
|
103
|
+
def _subscribe() -> Callable[[], None]:
|
|
104
|
+
set_state(NetInfo.fetch())
|
|
105
|
+
|
|
106
|
+
def on_change(snapshot: NetInfoState) -> None:
|
|
107
|
+
set_state(snapshot)
|
|
108
|
+
|
|
109
|
+
return NetInfo.add_listener(on_change)
|
|
110
|
+
|
|
111
|
+
use_effect(_subscribe, [])
|
|
112
|
+
return state
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""Local notifications and remote push registration.
|
|
2
|
+
|
|
3
|
+
Coroutines for requesting permission and scheduling / cancelling local
|
|
4
|
+
notifications, backed by the native ``Notifications`` module
|
|
5
|
+
(``UNUserNotificationCenter`` on iOS, ``NotificationManager`` on
|
|
6
|
+
Android).
|
|
7
|
+
|
|
8
|
+
On iOS you must ``await Notifications.request_permission()`` before
|
|
9
|
+
scheduling. On Android 13+ the ``POST_NOTIFICATIONS`` runtime
|
|
10
|
+
permission is requested automatically the first time you schedule a
|
|
11
|
+
notification (the template manifest declares it); earlier Android
|
|
12
|
+
versions don't prompt at all.
|
|
13
|
+
|
|
14
|
+
For remote (server-sent) pushes, enable the ``remote_notifications``
|
|
15
|
+
capability in ``pythonnative.toml`` and call
|
|
16
|
+
``Notifications.get_device_token()`` to register with APNs and receive
|
|
17
|
+
the device token your server needs. Android remote push requires
|
|
18
|
+
Firebase Cloud Messaging, which needs a per-app ``google-services.json``
|
|
19
|
+
and is not wired up by the built-in module; ``get_device_token`` returns
|
|
20
|
+
``None`` there.
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
```python
|
|
24
|
+
import pythonnative as pn
|
|
25
|
+
|
|
26
|
+
async def setup_reminders():
|
|
27
|
+
if not await pn.Notifications.request_permission():
|
|
28
|
+
return
|
|
29
|
+
await pn.Notifications.schedule(
|
|
30
|
+
title="Reminder",
|
|
31
|
+
body="Time for a walk!",
|
|
32
|
+
delay_seconds=60,
|
|
33
|
+
identifier="walk",
|
|
34
|
+
)
|
|
35
|
+
```
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
from __future__ import annotations
|
|
39
|
+
|
|
40
|
+
from typing import Any, Optional
|
|
41
|
+
|
|
42
|
+
from .registry import native_module
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class Notifications:
|
|
46
|
+
"""Local notification interface."""
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
async def request_permission() -> bool:
|
|
50
|
+
"""Request notification permission from the user.
|
|
51
|
+
|
|
52
|
+
On Android 12 and below the manifest declaration is sufficient
|
|
53
|
+
and this returns ``True`` without prompting. On Android 13+
|
|
54
|
+
(API 33) the ``POST_NOTIFICATIONS`` runtime permission prompt
|
|
55
|
+
is shown if the user hasn't decided yet.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
``True`` if granted (or no prompt is needed), ``False`` if
|
|
59
|
+
the user declined (always ``False`` off device).
|
|
60
|
+
|
|
61
|
+
Raises:
|
|
62
|
+
NativeModuleError: If the native module fails.
|
|
63
|
+
"""
|
|
64
|
+
return bool(await native_module("Notifications").call_async("request_permission"))
|
|
65
|
+
|
|
66
|
+
@staticmethod
|
|
67
|
+
async def schedule(
|
|
68
|
+
title: str,
|
|
69
|
+
body: str = "",
|
|
70
|
+
*,
|
|
71
|
+
delay_seconds: float = 0,
|
|
72
|
+
identifier: str = "default",
|
|
73
|
+
**options: Any,
|
|
74
|
+
) -> bool:
|
|
75
|
+
"""Schedule a local notification.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
title: Notification title.
|
|
79
|
+
body: Notification body text.
|
|
80
|
+
delay_seconds: Seconds from now until delivery. Use ``0``
|
|
81
|
+
for an effectively immediate notification.
|
|
82
|
+
identifier: Stable ID used by
|
|
83
|
+
[`cancel`][pythonnative.native_modules.notifications.Notifications.cancel]
|
|
84
|
+
to target this notification.
|
|
85
|
+
**options: Forwarded to the native module (``sound``,
|
|
86
|
+
``badge``, ...). Unknown keys are ignored.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
``True`` once scheduled, ``False`` if the user has denied
|
|
90
|
+
notification permission (so nothing was scheduled).
|
|
91
|
+
|
|
92
|
+
Raises:
|
|
93
|
+
NativeModuleError: If the native module fails.
|
|
94
|
+
"""
|
|
95
|
+
result = await native_module("Notifications").call_async(
|
|
96
|
+
"schedule",
|
|
97
|
+
title=title,
|
|
98
|
+
body=body,
|
|
99
|
+
delay_seconds=float(delay_seconds),
|
|
100
|
+
identifier=identifier,
|
|
101
|
+
**options,
|
|
102
|
+
)
|
|
103
|
+
return bool(result)
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
async def cancel(identifier: str = "default") -> None:
|
|
107
|
+
"""Cancel a pending notification by its identifier (a no-op when none is pending)."""
|
|
108
|
+
await native_module("Notifications").call_async("cancel", identifier=identifier)
|
|
109
|
+
|
|
110
|
+
@staticmethod
|
|
111
|
+
async def get_device_token() -> Optional[str]:
|
|
112
|
+
"""Register for remote notifications and return the device token.
|
|
113
|
+
|
|
114
|
+
On iOS this calls ``registerForRemoteNotifications`` and waits
|
|
115
|
+
for the APNs callback; the token is a lowercase hex string your
|
|
116
|
+
server passes to APNs. Requires the ``remote_notifications``
|
|
117
|
+
capability (which adds the ``aps-environment`` entitlement) and
|
|
118
|
+
a real device (the simulator has no APNs connection).
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
The APNs token, or ``None`` on platforms without built-in
|
|
122
|
+
remote push support (Android and off device).
|
|
123
|
+
|
|
124
|
+
Raises:
|
|
125
|
+
NativeModuleError: If APNs registration fails; ``code`` is
|
|
126
|
+
``"apns"`` and the message carries the system's error.
|
|
127
|
+
"""
|
|
128
|
+
token = await native_module("Notifications").call_async("get_device_token")
|
|
129
|
+
return str(token) if token else None
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Runtime permission checks and requests.
|
|
2
|
+
|
|
3
|
+
[`Permissions`][pythonnative.Permissions] normalizes the very different
|
|
4
|
+
iOS and Android permission models behind two calls, both served by the
|
|
5
|
+
native ``Permissions`` module:
|
|
6
|
+
|
|
7
|
+
- ``check(permission)``: synchronous, returns a status without
|
|
8
|
+
prompting.
|
|
9
|
+
- ``request(permission)``: a coroutine that shows the system prompt
|
|
10
|
+
(if needed) and resolves to the resulting status.
|
|
11
|
+
|
|
12
|
+
Statuses are ``"granted"``, ``"denied"``, ``"blocked"`` (denied with
|
|
13
|
+
"don't ask again" / Settings required), or ``"undetermined"``.
|
|
14
|
+
|
|
15
|
+
Permission names are the same words you declare in the
|
|
16
|
+
``[permissions]`` table of ``pythonnative.toml``, so the string that
|
|
17
|
+
puts ``NSCameraUsageDescription`` in your Info.plist is the string you
|
|
18
|
+
pass here: ``"camera"``, ``"microphone"``, ``"photo_library"``,
|
|
19
|
+
``"location_when_in_use"``, ``"contacts"``, ``"notifications"``. The
|
|
20
|
+
full list is [`RUNTIME_PERMISSIONS`][pythonnative.native_modules.permissions.RUNTIME_PERMISSIONS];
|
|
21
|
+
capabilities that have no runtime prompt (``vibration``,
|
|
22
|
+
``background_fetch``, ...) are declared in the config only. A name
|
|
23
|
+
outside the list raises ``ValueError`` before anything reaches native.
|
|
24
|
+
|
|
25
|
+
Example:
|
|
26
|
+
```python
|
|
27
|
+
import pythonnative as pn
|
|
28
|
+
|
|
29
|
+
async def scan():
|
|
30
|
+
if await pn.Permissions.request("camera") != "granted":
|
|
31
|
+
return
|
|
32
|
+
await pn.Camera.take_photo()
|
|
33
|
+
```
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
from __future__ import annotations
|
|
37
|
+
|
|
38
|
+
from typing import Literal
|
|
39
|
+
|
|
40
|
+
from .registry import native_module
|
|
41
|
+
|
|
42
|
+
PermissionStatus = Literal["granted", "denied", "blocked", "undetermined"]
|
|
43
|
+
"""Outcome of a check or request."""
|
|
44
|
+
|
|
45
|
+
PermissionName = Literal[
|
|
46
|
+
"camera",
|
|
47
|
+
"microphone",
|
|
48
|
+
"photo_library",
|
|
49
|
+
"location_when_in_use",
|
|
50
|
+
"contacts",
|
|
51
|
+
"notifications",
|
|
52
|
+
]
|
|
53
|
+
"""A capability that has a runtime prompt; the same names as ``[permissions]`` in ``pythonnative.toml``."""
|
|
54
|
+
|
|
55
|
+
GRANTED: PermissionStatus = "granted"
|
|
56
|
+
DENIED: PermissionStatus = "denied"
|
|
57
|
+
BLOCKED: PermissionStatus = "blocked"
|
|
58
|
+
UNDETERMINED: PermissionStatus = "undetermined"
|
|
59
|
+
|
|
60
|
+
_STATUSES = (GRANTED, DENIED, BLOCKED, UNDETERMINED)
|
|
61
|
+
|
|
62
|
+
RUNTIME_PERMISSIONS = (
|
|
63
|
+
"camera",
|
|
64
|
+
"microphone",
|
|
65
|
+
"photo_library",
|
|
66
|
+
"location_when_in_use",
|
|
67
|
+
"contacts",
|
|
68
|
+
"notifications",
|
|
69
|
+
)
|
|
70
|
+
"""Every permission name ``check`` / ``request`` accept, in the ``[permissions]`` vocabulary."""
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _coerce(value: object) -> PermissionStatus:
|
|
74
|
+
status = str(value) if value is not None else UNDETERMINED
|
|
75
|
+
return status if status in _STATUSES else UNDETERMINED
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _validate(permission: str) -> str:
|
|
79
|
+
if permission not in RUNTIME_PERMISSIONS:
|
|
80
|
+
raise ValueError(
|
|
81
|
+
f"Unknown permission {permission!r}. Use one of {', '.join(RUNTIME_PERMISSIONS)} "
|
|
82
|
+
"(the same names as [permissions] in pythonnative.toml)."
|
|
83
|
+
)
|
|
84
|
+
return permission
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class Permissions:
|
|
88
|
+
"""Runtime permission interface.
|
|
89
|
+
|
|
90
|
+
Raises:
|
|
91
|
+
ValueError: For a permission name outside
|
|
92
|
+
[`RUNTIME_PERMISSIONS`][pythonnative.native_modules.permissions.RUNTIME_PERMISSIONS].
|
|
93
|
+
NativeModuleError: If the native module fails.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
@staticmethod
|
|
97
|
+
def check(permission: PermissionName) -> PermissionStatus:
|
|
98
|
+
"""Return the current status of ``permission`` without prompting."""
|
|
99
|
+
return _coerce(native_module("Permissions").call("check", permission=_validate(permission)))
|
|
100
|
+
|
|
101
|
+
@staticmethod
|
|
102
|
+
async def request(permission: PermissionName) -> PermissionStatus:
|
|
103
|
+
"""Prompt for ``permission`` (if needed) and return the result.
|
|
104
|
+
|
|
105
|
+
Off device (``pn preview``, tests) the answer is always
|
|
106
|
+
``"undetermined"``: there is no prompt to show.
|
|
107
|
+
"""
|
|
108
|
+
return _coerce(await native_module("Permissions").call_async("request", permission=_validate(permission)))
|