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
pythonnative/layout.py
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
"""Yoga 3.2.1 layout for headless tests and the Python preview host.
|
|
2
|
+
|
|
3
|
+
Mobile hosts run this same pinned core beside their native widgets. This
|
|
4
|
+
module contains style translation and ownership, not a second flex algorithm.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import ctypes as C
|
|
10
|
+
import math
|
|
11
|
+
import weakref
|
|
12
|
+
from typing import Any, Callable
|
|
13
|
+
|
|
14
|
+
LAYOUT_STYLE_KEYS = frozenset(
|
|
15
|
+
{
|
|
16
|
+
"width",
|
|
17
|
+
"height",
|
|
18
|
+
"min_width",
|
|
19
|
+
"max_width",
|
|
20
|
+
"min_height",
|
|
21
|
+
"max_height",
|
|
22
|
+
"flex",
|
|
23
|
+
"flex_grow",
|
|
24
|
+
"flex_shrink",
|
|
25
|
+
"flex_basis",
|
|
26
|
+
"flex_wrap",
|
|
27
|
+
"align_self",
|
|
28
|
+
"align_content",
|
|
29
|
+
"position",
|
|
30
|
+
"top",
|
|
31
|
+
"right",
|
|
32
|
+
"bottom",
|
|
33
|
+
"left",
|
|
34
|
+
"start",
|
|
35
|
+
"end",
|
|
36
|
+
"margin",
|
|
37
|
+
"margin_top",
|
|
38
|
+
"margin_bottom",
|
|
39
|
+
"margin_left",
|
|
40
|
+
"margin_right",
|
|
41
|
+
"margin_start",
|
|
42
|
+
"margin_end",
|
|
43
|
+
"margin_horizontal",
|
|
44
|
+
"margin_vertical",
|
|
45
|
+
"padding",
|
|
46
|
+
"padding_top",
|
|
47
|
+
"padding_bottom",
|
|
48
|
+
"padding_left",
|
|
49
|
+
"padding_right",
|
|
50
|
+
"padding_start",
|
|
51
|
+
"padding_end",
|
|
52
|
+
"padding_horizontal",
|
|
53
|
+
"padding_vertical",
|
|
54
|
+
"border_width",
|
|
55
|
+
"border_top_width",
|
|
56
|
+
"border_right_width",
|
|
57
|
+
"border_bottom_width",
|
|
58
|
+
"border_left_width",
|
|
59
|
+
"flex_direction",
|
|
60
|
+
"justify_content",
|
|
61
|
+
"align_items",
|
|
62
|
+
"spacing",
|
|
63
|
+
"gap",
|
|
64
|
+
"row_gap",
|
|
65
|
+
"column_gap",
|
|
66
|
+
"aspect_ratio",
|
|
67
|
+
"direction",
|
|
68
|
+
"display",
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
"""Style keys that affect layout (and are consumed by the layout engine)."""
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
_lib: Any = None
|
|
75
|
+
_nodes: weakref.WeakValueDictionary[int, LayoutNode] = weakref.WeakValueDictionary()
|
|
76
|
+
_Measure = C.CFUNCTYPE(
|
|
77
|
+
None, C.c_void_p, C.c_float, C.c_int, C.c_float, C.c_int, C.POINTER(C.c_float), C.POINTER(C.c_float)
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@_Measure
|
|
82
|
+
def _measure(ptr: int, width: float, wm: int, height: float, hm: int, outw: Any, outh: Any) -> None:
|
|
83
|
+
node = _nodes.get(ptr)
|
|
84
|
+
try:
|
|
85
|
+
w, h = node.measure(width if wm else math.inf, height if hm else math.inf)
|
|
86
|
+
outw[0], outh[0] = max(0, w), max(0, h)
|
|
87
|
+
except BaseException as exc:
|
|
88
|
+
if node is not None:
|
|
89
|
+
node._error = exc
|
|
90
|
+
outw[0] = outh[0] = 0
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _api() -> Any:
|
|
94
|
+
global _lib
|
|
95
|
+
if _lib is not None:
|
|
96
|
+
return _lib
|
|
97
|
+
from . import _yoga
|
|
98
|
+
|
|
99
|
+
lib = C.CDLL(_yoga.__file__)
|
|
100
|
+
signatures: dict[str, Any] = {
|
|
101
|
+
"YGNodeNew": (C.c_void_p, []),
|
|
102
|
+
"YGNodeFree": (None, [C.c_void_p]),
|
|
103
|
+
"YGNodeRemoveAllChildren": (None, [C.c_void_p]),
|
|
104
|
+
"YGNodeInsertChild": (None, [C.c_void_p, C.c_void_p, C.c_size_t]),
|
|
105
|
+
"YGNodeCopyStyle": (None, [C.c_void_p, C.c_void_p]),
|
|
106
|
+
"YGNodeMarkDirty": (None, [C.c_void_p]),
|
|
107
|
+
"YGNodeCalculateLayout": (None, [C.c_void_p, C.c_float, C.c_float, C.c_int]),
|
|
108
|
+
"pn_yoga_callback": (None, [_Measure]),
|
|
109
|
+
"pn_yoga_measure": (None, [C.c_void_p, C.c_int]),
|
|
110
|
+
}
|
|
111
|
+
for axis in ("Left", "Top", "Width", "Height"):
|
|
112
|
+
signatures["YGNodeLayoutGet" + axis] = (C.c_float, [C.c_void_p])
|
|
113
|
+
for name, (result, args) in signatures.items():
|
|
114
|
+
fn = getattr(lib, name)
|
|
115
|
+
fn.restype, fn.argtypes = result, args
|
|
116
|
+
lib.pn_yoga_callback(_measure)
|
|
117
|
+
_lib = lib
|
|
118
|
+
return lib
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# Enum order follows Yoga's public C ABI in the pinned vendored headers.
|
|
122
|
+
ENUMS = {
|
|
123
|
+
"direction": ("Direction", ["inherit", "ltr", "rtl"]),
|
|
124
|
+
"flex_direction": ("FlexDirection", ["column", "column_reverse", "row", "row_reverse"]),
|
|
125
|
+
"justify_content": (
|
|
126
|
+
"JustifyContent",
|
|
127
|
+
["flex_start", "center", "flex_end", "space_between", "space_around", "space_evenly"],
|
|
128
|
+
),
|
|
129
|
+
"align_items": (
|
|
130
|
+
"AlignItems",
|
|
131
|
+
[
|
|
132
|
+
"auto",
|
|
133
|
+
"flex_start",
|
|
134
|
+
"center",
|
|
135
|
+
"flex_end",
|
|
136
|
+
"stretch",
|
|
137
|
+
"baseline",
|
|
138
|
+
"space_between",
|
|
139
|
+
"space_around",
|
|
140
|
+
"space_evenly",
|
|
141
|
+
],
|
|
142
|
+
),
|
|
143
|
+
"align_self": (
|
|
144
|
+
"AlignSelf",
|
|
145
|
+
[
|
|
146
|
+
"auto",
|
|
147
|
+
"flex_start",
|
|
148
|
+
"center",
|
|
149
|
+
"flex_end",
|
|
150
|
+
"stretch",
|
|
151
|
+
"baseline",
|
|
152
|
+
"space_between",
|
|
153
|
+
"space_around",
|
|
154
|
+
"space_evenly",
|
|
155
|
+
],
|
|
156
|
+
),
|
|
157
|
+
"align_content": (
|
|
158
|
+
"AlignContent",
|
|
159
|
+
[
|
|
160
|
+
"auto",
|
|
161
|
+
"flex_start",
|
|
162
|
+
"center",
|
|
163
|
+
"flex_end",
|
|
164
|
+
"stretch",
|
|
165
|
+
"baseline",
|
|
166
|
+
"space_between",
|
|
167
|
+
"space_around",
|
|
168
|
+
"space_evenly",
|
|
169
|
+
],
|
|
170
|
+
),
|
|
171
|
+
"position": ("PositionType", ["static", "relative", "absolute"]),
|
|
172
|
+
"flex_wrap": ("FlexWrap", ["nowrap", "wrap", "wrap_reverse"]),
|
|
173
|
+
"display": ("Display", ["flex", "none", "contents"]),
|
|
174
|
+
}
|
|
175
|
+
EDGES = {
|
|
176
|
+
name: i
|
|
177
|
+
for i, name in enumerate(["left", "top", "right", "bottom", "start", "end", "horizontal", "vertical", "all"])
|
|
178
|
+
}
|
|
179
|
+
ALIASES = {
|
|
180
|
+
"start": "flex_start",
|
|
181
|
+
"leading": "flex_start",
|
|
182
|
+
"top": "flex_start",
|
|
183
|
+
"end": "flex_end",
|
|
184
|
+
"trailing": "flex_end",
|
|
185
|
+
"bottom": "flex_end",
|
|
186
|
+
"fill": "stretch",
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _set(ptr: int, name: str, value: Any, edge: int | None = None, *, enum: bool = False) -> None:
|
|
191
|
+
if value is None or isinstance(value, bool):
|
|
192
|
+
return
|
|
193
|
+
suffix = ""
|
|
194
|
+
args: list[Any] = [ptr]
|
|
195
|
+
types: list[Any] = [C.c_void_p]
|
|
196
|
+
if edge is not None:
|
|
197
|
+
args.append(edge)
|
|
198
|
+
types.append(C.c_int)
|
|
199
|
+
if value == "auto":
|
|
200
|
+
suffix = "Auto"
|
|
201
|
+
else:
|
|
202
|
+
if isinstance(value, str) and value.endswith("%"):
|
|
203
|
+
suffix, value = "Percent", float(value[:-1])
|
|
204
|
+
args.append(int(value) if enum else float(value))
|
|
205
|
+
types.append(C.c_int if enum else C.c_float)
|
|
206
|
+
fn = getattr(_api(), "YGNodeStyleSet" + name + suffix)
|
|
207
|
+
fn.restype, fn.argtypes = None, types
|
|
208
|
+
fn(*args)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def apply_style(ptr: int, style: dict[str, Any]) -> None:
|
|
212
|
+
"""Translate Pythonic style keys to Yoga's native style API."""
|
|
213
|
+
for key, value in style.items():
|
|
214
|
+
if value is None:
|
|
215
|
+
continue
|
|
216
|
+
if key in ENUMS:
|
|
217
|
+
name, values = ENUMS[key]
|
|
218
|
+
value = ALIASES.get(value, value) if key.startswith(("align_", "justify_")) else value
|
|
219
|
+
if value not in values:
|
|
220
|
+
raise ValueError(f"Invalid {key}: {value!r}")
|
|
221
|
+
_set(ptr, name, values.index(value), enum=True)
|
|
222
|
+
elif key in {
|
|
223
|
+
"width",
|
|
224
|
+
"height",
|
|
225
|
+
"min_width",
|
|
226
|
+
"min_height",
|
|
227
|
+
"max_width",
|
|
228
|
+
"max_height",
|
|
229
|
+
"flex",
|
|
230
|
+
"flex_grow",
|
|
231
|
+
"flex_shrink",
|
|
232
|
+
"flex_basis",
|
|
233
|
+
"aspect_ratio",
|
|
234
|
+
}:
|
|
235
|
+
_set(ptr, "".join(part.title() for part in key.split("_")), value)
|
|
236
|
+
elif key in {"spacing", "gap", "row_gap", "column_gap"}:
|
|
237
|
+
_set(ptr, "Gap", value, {"column_gap": 0, "row_gap": 1}.get(key, 2))
|
|
238
|
+
elif key in EDGES and key not in {"all", "horizontal", "vertical"}:
|
|
239
|
+
_set(ptr, "Position", value, EDGES[key])
|
|
240
|
+
elif key.startswith(("padding", "margin")):
|
|
241
|
+
group, _, edge = key.partition("_")
|
|
242
|
+
if isinstance(value, dict):
|
|
243
|
+
for side, amount in value.items():
|
|
244
|
+
_set(ptr, group.title(), amount, EDGES[side])
|
|
245
|
+
else:
|
|
246
|
+
_set(ptr, group.title(), value, EDGES[edge or "all"])
|
|
247
|
+
elif key.startswith("border_") and key.endswith("width"):
|
|
248
|
+
_set(ptr, "Border", value, EDGES[key[7:-6] or "all"])
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class LayoutNode:
|
|
252
|
+
"""An owned Yoga node, with Python measurement for headless backends."""
|
|
253
|
+
|
|
254
|
+
def __init__(
|
|
255
|
+
self,
|
|
256
|
+
style: dict[str, Any] | None = None,
|
|
257
|
+
children: list[LayoutNode] | None = None,
|
|
258
|
+
measure: Callable[[float, float], tuple[float, float]] | None = None,
|
|
259
|
+
user_data: Any = None,
|
|
260
|
+
) -> None:
|
|
261
|
+
self.style = dict(style or {})
|
|
262
|
+
self.children = list(children or [])
|
|
263
|
+
self.measure = measure
|
|
264
|
+
self.user_data = user_data
|
|
265
|
+
self.x = self.y = self.width = self.height = 0.0
|
|
266
|
+
self.dirty = True
|
|
267
|
+
self._pn_scroll_axis: str | None = None
|
|
268
|
+
self._ptr: int | None = None
|
|
269
|
+
self._last_style: Any = None
|
|
270
|
+
self._last_children: tuple[int, ...] = ()
|
|
271
|
+
self._error: BaseException | None = None
|
|
272
|
+
|
|
273
|
+
def _sync(self) -> int:
|
|
274
|
+
lib = _api()
|
|
275
|
+
if self._ptr is None:
|
|
276
|
+
self._ptr = lib.YGNodeNew()
|
|
277
|
+
_nodes[self._ptr] = self
|
|
278
|
+
weakref.finalize(self, lib.YGNodeFree, self._ptr)
|
|
279
|
+
ptr = self._ptr
|
|
280
|
+
style = dict(self.style)
|
|
281
|
+
if self._pn_scroll_axis:
|
|
282
|
+
style.setdefault("flex_shrink", 1)
|
|
283
|
+
if style != self._last_style:
|
|
284
|
+
fresh = lib.YGNodeNew()
|
|
285
|
+
apply_style(fresh, style)
|
|
286
|
+
if self._pn_scroll_axis:
|
|
287
|
+
_set(fresh, "Overflow", 1, enum=True)
|
|
288
|
+
lib.YGNodeCopyStyle(ptr, fresh)
|
|
289
|
+
lib.YGNodeFree(fresh)
|
|
290
|
+
self._last_style = style
|
|
291
|
+
measured = self.measure is not None and not self.children
|
|
292
|
+
lib.pn_yoga_measure(ptr, measured)
|
|
293
|
+
if measured and self.dirty:
|
|
294
|
+
lib.YGNodeMarkDirty(ptr)
|
|
295
|
+
children = tuple(child._sync() for child in self.children)
|
|
296
|
+
if children != self._last_children:
|
|
297
|
+
lib.YGNodeRemoveAllChildren(ptr)
|
|
298
|
+
for i, child in enumerate(children):
|
|
299
|
+
lib.YGNodeInsertChild(ptr, child, i)
|
|
300
|
+
self._last_children = children
|
|
301
|
+
return ptr
|
|
302
|
+
|
|
303
|
+
def _read(self) -> None:
|
|
304
|
+
lib = _api()
|
|
305
|
+
self.x = lib.YGNodeLayoutGetLeft(self._ptr)
|
|
306
|
+
self.y = lib.YGNodeLayoutGetTop(self._ptr)
|
|
307
|
+
self.width = lib.YGNodeLayoutGetWidth(self._ptr)
|
|
308
|
+
self.height = lib.YGNodeLayoutGetHeight(self._ptr)
|
|
309
|
+
self.dirty = False
|
|
310
|
+
if self._error is not None:
|
|
311
|
+
error, self._error = self._error, None
|
|
312
|
+
raise error
|
|
313
|
+
for child in self.children:
|
|
314
|
+
child._read()
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def calculate_layout(node: LayoutNode, width: float, height: float) -> None:
|
|
318
|
+
"""Calculate a tree's layout with the pinned Yoga core."""
|
|
319
|
+
ptr = node._sync()
|
|
320
|
+
_api().YGNodeCalculateLayout(
|
|
321
|
+
ptr, width if math.isfinite(width) else math.nan, height if math.isfinite(height) else math.nan, 1
|
|
322
|
+
)
|
|
323
|
+
node._read()
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def extract_layout_style(props: dict[str, Any]) -> dict[str, Any]:
|
|
327
|
+
"""Select properties owned by layout."""
|
|
328
|
+
return {key: value for key, value in props.items() if key in LAYOUT_STYLE_KEYS}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""Batched mutation protocol between the reconciler and native backends.
|
|
2
|
+
|
|
3
|
+
The reconciler no longer talks to the native layer one call at a time.
|
|
4
|
+
Instead, every commit pass produces an ordered list of small mutation
|
|
5
|
+
ops referencing integer **tags** (stable per-view identifiers), and the
|
|
6
|
+
whole list is applied in a single
|
|
7
|
+
[`apply_mutations`][pythonnative.native_views.NativeViewRegistry.apply_mutations]
|
|
8
|
+
call. This mirrors React Native's Fabric mounting layer: the diff phase
|
|
9
|
+
is pure, and the native side sees one coherent transaction per commit.
|
|
10
|
+
|
|
11
|
+
Why tags instead of view objects?
|
|
12
|
+
|
|
13
|
+
- The diff phase runs *before* any native view exists, so ops cannot
|
|
14
|
+
reference views directly.
|
|
15
|
+
- Tags give the native side a stable identity to key its own view
|
|
16
|
+
registry, event routing, and animation bookkeeping on.
|
|
17
|
+
- A flat list of `(op, tag, payload)` tuples is trivially serializable,
|
|
18
|
+
which keeps the door open for applying mutations from a background
|
|
19
|
+
thread or through a single JNI/ObjC crossing in the future.
|
|
20
|
+
|
|
21
|
+
Op ordering rules (the reconciler guarantees these):
|
|
22
|
+
|
|
23
|
+
1. A `CreateOp` for a tag precedes any other op referencing that tag.
|
|
24
|
+
2. `InsertOp` ops appear after both the parent and child exist.
|
|
25
|
+
3. `DestroyOp` ops are emitted children-first; handlers detach the view
|
|
26
|
+
from its parent as part of destruction.
|
|
27
|
+
4. `SetFrameOp` ops are only emitted for frames that actually changed
|
|
28
|
+
since the last layout pass (frame diffing).
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from dataclasses import dataclass, field
|
|
32
|
+
from typing import Any, Dict, Tuple, Union
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
"CreateOp",
|
|
36
|
+
"UpdateOp",
|
|
37
|
+
"InsertOp",
|
|
38
|
+
"DestroyOp",
|
|
39
|
+
"SetFrameOp",
|
|
40
|
+
"Mutation",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass(frozen=True)
|
|
45
|
+
class CreateOp:
|
|
46
|
+
"""Create a native view for ``tag`` of element type ``type_name``.
|
|
47
|
+
|
|
48
|
+
Attributes:
|
|
49
|
+
tag: Unique integer identity assigned by the reconciler.
|
|
50
|
+
type_name: Element type name (e.g. ``"Text"``).
|
|
51
|
+
props: Initial *clean* props; callables have already been
|
|
52
|
+
routed to the [`EventRegistry`][pythonnative.events.EventRegistry]
|
|
53
|
+
and replaced by the ``_pn_events`` name set.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
tag: int
|
|
57
|
+
type_name: str
|
|
58
|
+
props: Dict[str, Any] = field(default_factory=dict)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass(frozen=True)
|
|
62
|
+
class UpdateOp:
|
|
63
|
+
"""Apply ``changed_props`` to the view registered under ``tag``.
|
|
64
|
+
|
|
65
|
+
Removed props are signaled with a value of ``None``, matching the
|
|
66
|
+
pre-existing handler contract.
|
|
67
|
+
|
|
68
|
+
Attributes:
|
|
69
|
+
tag: Unique integer identity of the target view.
|
|
70
|
+
changed_props: Mapping of modified prop names to their new values.
|
|
71
|
+
Removed props appear with a value of ``None``.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
tag: int
|
|
75
|
+
changed_props: Dict[str, Any] = field(default_factory=dict)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@dataclass(frozen=True)
|
|
79
|
+
class InsertOp:
|
|
80
|
+
"""Ensure the child view sits at ``index`` inside the parent view.
|
|
81
|
+
|
|
82
|
+
Handlers must treat this as *move-aware*: if the child is already
|
|
83
|
+
attached to the parent at a different position, it is moved rather
|
|
84
|
+
than duplicated. ``index`` is clamped by handlers to the current
|
|
85
|
+
child count.
|
|
86
|
+
|
|
87
|
+
Attributes:
|
|
88
|
+
parent_tag: Integer tag of the container view.
|
|
89
|
+
child_tag: Integer tag of the child view to insert or move.
|
|
90
|
+
index: Zero-based insertion index, clamped by handlers to the
|
|
91
|
+
current child count.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
parent_tag: int
|
|
95
|
+
child_tag: int
|
|
96
|
+
index: int
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@dataclass(frozen=True)
|
|
100
|
+
class DestroyOp:
|
|
101
|
+
"""Release the native view registered under ``tag``.
|
|
102
|
+
|
|
103
|
+
The registry drops its tag record and calls the handler's
|
|
104
|
+
``destroy`` hook so platform resources (listeners, timers, image
|
|
105
|
+
loads) can be released eagerly instead of waiting for GC.
|
|
106
|
+
|
|
107
|
+
Attributes:
|
|
108
|
+
tag: Unique integer identity of the view to destroy.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
tag: int
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@dataclass(frozen=True)
|
|
115
|
+
class SetFrameOp:
|
|
116
|
+
"""Position and size the view registered under ``tag``.
|
|
117
|
+
|
|
118
|
+
Coordinates are points relative to the parent's content origin,
|
|
119
|
+
exactly as computed by the layout engine.
|
|
120
|
+
|
|
121
|
+
Attributes:
|
|
122
|
+
tag: Unique integer identity of the target view.
|
|
123
|
+
x: Horizontal origin offset in points relative to the parent.
|
|
124
|
+
y: Vertical origin offset in points relative to the parent.
|
|
125
|
+
width: View width in points.
|
|
126
|
+
height: View height in points.
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
tag: int
|
|
130
|
+
x: float
|
|
131
|
+
y: float
|
|
132
|
+
width: float
|
|
133
|
+
height: float
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def frame(self) -> Tuple[float, float, float, float]:
|
|
137
|
+
"""Return ``(x, y, width, height)`` as a tuple."""
|
|
138
|
+
return (self.x, self.y, self.width, self.height)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
Mutation = Union[CreateOp, UpdateOp, InsertOp, DestroyOp, SetFrameOp]
|
|
142
|
+
"""Union of every op type carried by a commit transaction."""
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
plugins {
|
|
2
|
+
id 'com.android.library'
|
|
3
|
+
id 'org.jetbrains.kotlin.android'
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
android {
|
|
7
|
+
namespace 'com.pythonnative.runtime'
|
|
8
|
+
compileSdk 34
|
|
9
|
+
|
|
10
|
+
defaultConfig {
|
|
11
|
+
minSdk 24
|
|
12
|
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
externalNativeBuild {
|
|
16
|
+
cmake { path "src/main/cpp/CMakeLists.txt"; version "3.22.1" }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
buildFeatures {
|
|
20
|
+
buildConfig false
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
compileOptions {
|
|
24
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
25
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
26
|
+
}
|
|
27
|
+
kotlinOptions {
|
|
28
|
+
jvmTarget = '1.8'
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
testOptions {
|
|
32
|
+
unitTests.returnDefaultValues = true
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
dependencies {
|
|
37
|
+
api 'androidx.core:core-ktx:1.8.0'
|
|
38
|
+
api 'androidx.appcompat:appcompat:1.4.1'
|
|
39
|
+
api 'com.google.android.material:material:1.5.0'
|
|
40
|
+
api 'androidx.recyclerview:recyclerview:1.3.2'
|
|
41
|
+
api 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
|
42
|
+
api 'androidx.security:security-crypto:1.1.0'
|
|
43
|
+
api 'androidx.biometric:biometric:1.1.0'
|
|
44
|
+
api 'androidx.dynamicanimation:dynamicanimation:1.0.0'
|
|
45
|
+
// Screen navigation (PNScreenFragment inside the app's NavHostFragment).
|
|
46
|
+
api 'androidx.navigation:navigation-fragment-ktx:2.7.7'
|
|
47
|
+
api 'androidx.navigation:navigation-ui-ktx:2.7.7'
|
|
48
|
+
|
|
49
|
+
testImplementation 'junit:junit:4.13.2'
|
|
50
|
+
// Real org.json for host-side unit tests (the android.jar stubs are empty).
|
|
51
|
+
testImplementation 'org.json:json:20231013'
|
|
52
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
pluginManagement {
|
|
2
|
+
repositories { google(); mavenCentral(); gradlePluginPortal() }
|
|
3
|
+
plugins {
|
|
4
|
+
id 'com.android.library' version '8.7.3'
|
|
5
|
+
id 'org.jetbrains.kotlin.android' version '2.0.21'
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
dependencyResolutionManagement {
|
|
9
|
+
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
|
10
|
+
repositories { google(); mavenCentral() }
|
|
11
|
+
}
|
|
12
|
+
rootProject.name = 'PythonNativeRuntime'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
3
|
+
|
|
4
|
+
<!-- Runtime-gated on Android 13+ (API 33); requested by the
|
|
5
|
+
Notifications module before posting. -->
|
|
6
|
+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
7
|
+
<uses-permission android:name="android.permission.VIBRATE" />
|
|
8
|
+
<uses-permission android:name="android.permission.INTERNET" />
|
|
9
|
+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
10
|
+
|
|
11
|
+
</manifest>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.22)
|
|
2
|
+
project(pn_yoga LANGUAGES CXX)
|
|
3
|
+
set(CMAKE_CXX_STANDARD 20)
|
|
4
|
+
set(PN_YOGA_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../../../yoga)
|
|
5
|
+
file(GLOB_RECURSE YOGA_SOURCES ${PN_YOGA_ROOT}/yoga/*.cpp)
|
|
6
|
+
add_library(pn_yoga SHARED ${YOGA_SOURCES} ${PN_YOGA_ROOT}/style.cpp yoga_jni.cpp)
|
|
7
|
+
target_include_directories(pn_yoga PRIVATE ${PN_YOGA_ROOT})
|
|
8
|
+
target_link_libraries(pn_yoga log)
|
|
9
|
+
target_link_options(pn_yoga PRIVATE "-Wl,-z,max-page-size=16384")
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#include <jni.h>
|
|
2
|
+
#include <yoga/Yoga.h>
|
|
3
|
+
#include <include/PNStyle.h>
|
|
4
|
+
#include <cmath>
|
|
5
|
+
static JavaVM* vm;
|
|
6
|
+
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* value, void*) { vm = value; return JNI_VERSION_1_6; }
|
|
7
|
+
static JNIEnv* env() { JNIEnv* result; vm->GetEnv(reinterpret_cast<void**>(&result), JNI_VERSION_1_6); return result; }
|
|
8
|
+
static YGNodeRef node(jlong ptr) { return reinterpret_cast<YGNodeRef>(ptr); }
|
|
9
|
+
static YGSize measure(YGNodeConstRef n, float w, YGMeasureMode wm, float h, YGMeasureMode hm) {
|
|
10
|
+
auto e = env(); auto object = static_cast<jobject>(YGNodeGetContext(n));
|
|
11
|
+
auto cls = e->GetObjectClass(object);
|
|
12
|
+
auto method = e->GetMethodID(cls, "measure", "(FF)[F");
|
|
13
|
+
auto result = static_cast<jfloatArray>(e->CallObjectMethod(object, method, wm == YGMeasureModeUndefined ? 1e6f : w, hm == YGMeasureModeUndefined ? 1e6f : h));
|
|
14
|
+
float size[2] = {0, 0};
|
|
15
|
+
if (result) { e->GetFloatArrayRegion(result, 0, 2, size); e->DeleteLocalRef(result); }
|
|
16
|
+
e->DeleteLocalRef(cls);
|
|
17
|
+
return {size[0], size[1]};
|
|
18
|
+
}
|
|
19
|
+
static float baseline(YGNodeConstRef n, float, float h) {
|
|
20
|
+
auto e = env(); auto object = static_cast<jobject>(YGNodeGetContext(n));
|
|
21
|
+
auto cls = e->GetObjectClass(object);
|
|
22
|
+
auto method = e->GetMethodID(cls, "baseline", "(F)F");
|
|
23
|
+
float result = e->CallFloatMethod(object, method, h); e->DeleteLocalRef(cls); return result;
|
|
24
|
+
}
|
|
25
|
+
#define JNI(name) extern "C" JNIEXPORT name
|
|
26
|
+
JNI(jlong) Java_com_pythonnative_runtime_layout_YogaNode_create(JNIEnv* e, jobject self) {
|
|
27
|
+
auto n = YGNodeNew(); YGNodeSetContext(n, e->NewGlobalRef(self)); return reinterpret_cast<jlong>(n);
|
|
28
|
+
}
|
|
29
|
+
JNI(void) Java_com_pythonnative_runtime_layout_YogaNode_free(JNIEnv* e, jobject, jlong ptr) {
|
|
30
|
+
auto n = node(ptr); e->DeleteGlobalRef(static_cast<jobject>(YGNodeGetContext(n))); YGNodeFree(n);
|
|
31
|
+
}
|
|
32
|
+
JNI(void) Java_com_pythonnative_runtime_layout_YogaNode_style(JNIEnv* e, jobject, jlong ptr, jstring key, jstring value) {
|
|
33
|
+
auto k = e->GetStringUTFChars(key, nullptr); auto v = e->GetStringUTFChars(value, nullptr);
|
|
34
|
+
PNYogaSetStyle(node(ptr), k, v); e->ReleaseStringUTFChars(key, k); e->ReleaseStringUTFChars(value, v);
|
|
35
|
+
}
|
|
36
|
+
JNI(void) Java_com_pythonnative_runtime_layout_YogaNode_resetStyle(JNIEnv*, jobject, jlong ptr) {
|
|
37
|
+
auto fresh = YGNodeNew(); YGNodeCopyStyle(node(ptr), fresh); YGNodeFree(fresh);
|
|
38
|
+
}
|
|
39
|
+
JNI(void) Java_com_pythonnative_runtime_layout_YogaNode_measureLeaf(JNIEnv*, jobject, jlong ptr, jboolean enabled) {
|
|
40
|
+
YGNodeSetMeasureFunc(node(ptr), enabled ? measure : nullptr);
|
|
41
|
+
YGNodeSetBaselineFunc(node(ptr), enabled ? baseline : nullptr);
|
|
42
|
+
if (enabled) YGNodeMarkDirty(node(ptr));
|
|
43
|
+
}
|
|
44
|
+
JNI(void) Java_com_pythonnative_runtime_layout_YogaNode_insert(JNIEnv*, jobject, jlong ptr, jlong child, jint index) {
|
|
45
|
+
auto n = node(ptr); YGNodeSetMeasureFunc(n, nullptr); YGNodeInsertChild(n, node(child), index);
|
|
46
|
+
}
|
|
47
|
+
JNI(void) Java_com_pythonnative_runtime_layout_YogaNode_remove(JNIEnv*, jobject, jlong ptr, jlong child) { YGNodeRemoveChild(node(ptr), node(child)); }
|
|
48
|
+
JNI(void) Java_com_pythonnative_runtime_layout_YogaNode_calculate(JNIEnv*, jobject, jlong ptr, jfloat w, jfloat h) { YGNodeCalculateLayout(node(ptr), w, h, YGDirectionLTR); }
|
|
49
|
+
JNI(jfloatArray) Java_com_pythonnative_runtime_layout_YogaNode_frame(JNIEnv* e, jobject, jlong ptr) {
|
|
50
|
+
auto n = node(ptr); float values[] = {YGNodeLayoutGetLeft(n), YGNodeLayoutGetTop(n), YGNodeLayoutGetWidth(n), YGNodeLayoutGetHeight(n)};
|
|
51
|
+
auto result = e->NewFloatArray(4); e->SetFloatArrayRegion(result, 0, 4, values); return result;
|
|
52
|
+
}
|