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,14 @@
|
|
|
1
|
+
//
|
|
2
|
+
// BridgingHeader.h
|
|
3
|
+
// ios_template
|
|
4
|
+
//
|
|
5
|
+
// Exposes the embedded CPython C API to Swift. The header resolves
|
|
6
|
+
// through the linked Python.xcframework's framework search path.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#ifndef ios_template_BridgingHeader_h
|
|
10
|
+
#define ios_template_BridgingHeader_h
|
|
11
|
+
|
|
12
|
+
#include <Python/Python.h>
|
|
13
|
+
|
|
14
|
+
#endif /* ios_template_BridgingHeader_h */
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<!-- PythonNative's StatusBar element is applied through PNViewController's
|
|
6
|
+
preferredStatusBarStyle / prefersStatusBarHidden overrides, so the
|
|
7
|
+
modern view-controller-based appearance must stay enabled. -->
|
|
8
|
+
<key>UIViewControllerBasedStatusBarAppearance</key>
|
|
9
|
+
<true/>
|
|
10
|
+
<key>UIApplicationSceneManifest</key>
|
|
11
|
+
<dict>
|
|
12
|
+
<key>UIApplicationSupportsMultipleScenes</key>
|
|
13
|
+
<false/>
|
|
14
|
+
<key>UISceneConfigurations</key>
|
|
15
|
+
<dict>
|
|
16
|
+
<key>UIWindowSceneSessionRoleApplication</key>
|
|
17
|
+
<array>
|
|
18
|
+
<dict>
|
|
19
|
+
<key>UISceneConfigurationName</key>
|
|
20
|
+
<string>Default Configuration</string>
|
|
21
|
+
<key>UISceneDelegateClassName</key>
|
|
22
|
+
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
|
23
|
+
</dict>
|
|
24
|
+
</array>
|
|
25
|
+
</dict>
|
|
26
|
+
</dict>
|
|
27
|
+
</dict>
|
|
28
|
+
</plist>
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
//
|
|
2
|
+
// PythonRuntime.swift
|
|
3
|
+
// ios_template
|
|
4
|
+
//
|
|
5
|
+
// Embeds CPython directly through the C API (no PythonKit). The
|
|
6
|
+
// Python.xcframework is linked at build time, so a missing runtime is
|
|
7
|
+
// a build error, never a silent runtime fallback.
|
|
8
|
+
//
|
|
9
|
+
// After the interpreter starts, `pythonnative.bootstrap.start()` binds
|
|
10
|
+
// the PythonNativeKit C exports, registers the Python callback, and
|
|
11
|
+
// verifies the protocol version. Everything else (screens, modules,
|
|
12
|
+
// deep links) flows over that bridge; nothing else here calls Python
|
|
13
|
+
// functions by name.
|
|
14
|
+
//
|
|
15
|
+
|
|
16
|
+
import Foundation
|
|
17
|
+
import PythonNativeKit
|
|
18
|
+
|
|
19
|
+
enum PythonRuntimeError: Error, CustomStringConvertible {
|
|
20
|
+
case startup(String)
|
|
21
|
+
case call(String)
|
|
22
|
+
|
|
23
|
+
var description: String {
|
|
24
|
+
switch self {
|
|
25
|
+
case .startup(let message): return message
|
|
26
|
+
case .call(let message): return message
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// An owned reference to a Python object. Reference counting is handled
|
|
32
|
+
/// automatically; the wrapped pointer is released on deinit.
|
|
33
|
+
final class PyRef {
|
|
34
|
+
fileprivate let pointer: UnsafeMutablePointer<PyObject>
|
|
35
|
+
|
|
36
|
+
fileprivate init(owned pointer: UnsafeMutablePointer<PyObject>) {
|
|
37
|
+
self.pointer = pointer
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
deinit {
|
|
41
|
+
let gil = PyGILState_Ensure()
|
|
42
|
+
Py_DecRef(pointer)
|
|
43
|
+
PyGILState_Release(gil)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/// Call a method on this object with string/number/bool arguments.
|
|
47
|
+
@discardableResult
|
|
48
|
+
func call(_ method: String, _ args: Any...) throws -> PyRef {
|
|
49
|
+
let gil = PyGILState_Ensure()
|
|
50
|
+
defer { PyGILState_Release(gil) }
|
|
51
|
+
guard let bound = PyObject_GetAttrString(pointer, method) else {
|
|
52
|
+
throw PythonRuntimeError.call("Python object has no method '\(method)': \(PythonRuntime.consumeError())")
|
|
53
|
+
}
|
|
54
|
+
defer { Py_DecRef(bound) }
|
|
55
|
+
return try PythonRuntime.invoke(bound, args: args, context: method)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// Truthiness of the wrapped object (`PyObject_IsTrue`).
|
|
59
|
+
var isTruthy: Bool {
|
|
60
|
+
let gil = PyGILState_Ensure()
|
|
61
|
+
defer { PyGILState_Release(gil) }
|
|
62
|
+
return PyObject_IsTrue(pointer) == 1
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/// Owns the embedded CPython interpreter for the whole process.
|
|
67
|
+
final class PythonRuntime {
|
|
68
|
+
static let shared = PythonRuntime()
|
|
69
|
+
|
|
70
|
+
private(set) var started = false
|
|
71
|
+
private(set) var startupError: String? = nil
|
|
72
|
+
|
|
73
|
+
private init() {}
|
|
74
|
+
|
|
75
|
+
// MARK: - Startup
|
|
76
|
+
|
|
77
|
+
/// Initialize the embedded interpreter once and complete the bridge
|
|
78
|
+
/// handshake. Throws with a full description when the bundle is not
|
|
79
|
+
/// packaged correctly or the protocol versions disagree; there is
|
|
80
|
+
/// deliberately no fallback mode.
|
|
81
|
+
func ensureStarted() throws {
|
|
82
|
+
if let error = startupError { throw PythonRuntimeError.startup(error) }
|
|
83
|
+
if started { return }
|
|
84
|
+
do {
|
|
85
|
+
try start()
|
|
86
|
+
// The interpreter is live from here on; a failed handshake is
|
|
87
|
+
// recorded as a startup error but Python is never re-initialized.
|
|
88
|
+
started = true
|
|
89
|
+
try connectBridge()
|
|
90
|
+
} catch let error as PythonRuntimeError {
|
|
91
|
+
startupError = error.description
|
|
92
|
+
throw error
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/// Run `pythonnative.bootstrap.start(dev, strict=True)`: it binds the
|
|
97
|
+
/// `pn_bridge_*` symbols, registers the native -> Python callback,
|
|
98
|
+
/// verifies the protocol version against `pn_bridge_protocol_version()`,
|
|
99
|
+
/// routes `print()` to the console, and warms the asyncio runtime.
|
|
100
|
+
private func connectBridge() throws {
|
|
101
|
+
#if DEBUG
|
|
102
|
+
let dev = true
|
|
103
|
+
#else
|
|
104
|
+
let dev = false
|
|
105
|
+
#endif
|
|
106
|
+
do {
|
|
107
|
+
try callList(module: "pythonnative.bootstrap", function: "start", [dev, true])
|
|
108
|
+
} catch let error as PythonRuntimeError {
|
|
109
|
+
throw PythonRuntimeError.startup(
|
|
110
|
+
"Bridge bootstrap failed (native protocol v\(pn_bridge_protocol_version())):\n\(error.description)"
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
guard PNBridge.shared.hasCallback else {
|
|
114
|
+
throw PythonRuntimeError.startup(
|
|
115
|
+
"pythonnative.bridge.handshake() returned without registering the native callback."
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private func start() throws {
|
|
121
|
+
guard let resourcePath = Bundle.main.resourcePath else {
|
|
122
|
+
throw PythonRuntimeError.startup("The app bundle has no resource path; the build is corrupt.")
|
|
123
|
+
}
|
|
124
|
+
let pythonHome = "\(resourcePath)/python"
|
|
125
|
+
let appPath = "\(resourcePath)/app"
|
|
126
|
+
let packagesPath = "\(resourcePath)/app_packages"
|
|
127
|
+
for (path, hint) in [
|
|
128
|
+
(pythonHome, "the embedded Python runtime"),
|
|
129
|
+
(appPath, "the app's Python sources"),
|
|
130
|
+
(packagesPath, "the bundled Python packages"),
|
|
131
|
+
] where !FileManager.default.fileExists(atPath: path) {
|
|
132
|
+
throw PythonRuntimeError.startup(
|
|
133
|
+
"Missing \(hint) at \(path). Build the app with 'pn run ios' or 'pn build ios' "
|
|
134
|
+
+ "so the PythonNative CLI stages the Python runtime; the raw Xcode template "
|
|
135
|
+
+ "cannot run on its own."
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// The embedded CPython (3.13+) reports sys.platform == "ios" on its
|
|
140
|
+
// own; this explicit override is belt-and-braces for
|
|
141
|
+
// pythonnative.utils.IS_IOS and costs nothing.
|
|
142
|
+
setenv("PN_PLATFORM", "ios", 1)
|
|
143
|
+
|
|
144
|
+
var preconfig = PyPreConfig()
|
|
145
|
+
PyPreConfig_InitIsolatedConfig(&preconfig)
|
|
146
|
+
preconfig.utf8_mode = 1
|
|
147
|
+
var status = Py_PreInitialize(&preconfig)
|
|
148
|
+
if PyStatus_Exception(status) != 0 {
|
|
149
|
+
throw PythonRuntimeError.startup("Unable to pre-initialize Python: \(Self.statusMessage(status))")
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
var config = PyConfig()
|
|
153
|
+
PyConfig_InitIsolatedConfig(&config)
|
|
154
|
+
defer { PyConfig_Clear(&config) }
|
|
155
|
+
// Unbuffered stdio so print() reaches the device log immediately.
|
|
156
|
+
config.buffered_stdio = 0
|
|
157
|
+
// The signed bundle is immutable; never try to write bytecode.
|
|
158
|
+
config.write_bytecode = 0
|
|
159
|
+
|
|
160
|
+
guard let homeW = Py_DecodeLocale(pythonHome, nil) else {
|
|
161
|
+
throw PythonRuntimeError.startup("Could not decode the Python home path.")
|
|
162
|
+
}
|
|
163
|
+
status = withUnsafeMutablePointer(to: &config) { cfg in
|
|
164
|
+
PyConfig_SetString(cfg, &cfg.pointee.home, homeW)
|
|
165
|
+
}
|
|
166
|
+
PyMem_RawFree(homeW)
|
|
167
|
+
if PyStatus_Exception(status) != 0 {
|
|
168
|
+
throw PythonRuntimeError.startup("Unable to set the Python home: \(Self.statusMessage(status))")
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
status = PyConfig_Read(&config)
|
|
172
|
+
if PyStatus_Exception(status) != 0 {
|
|
173
|
+
throw PythonRuntimeError.startup("Unable to read the Python config: \(Self.statusMessage(status))")
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
status = Py_InitializeFromConfig(&config)
|
|
177
|
+
if PyStatus_Exception(status) != 0 {
|
|
178
|
+
throw PythonRuntimeError.startup("Unable to initialize Python: \(Self.statusMessage(status))")
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// The interpreter is live and this thread holds the GIL. Finish
|
|
182
|
+
// path setup, then release the GIL; every later entry point
|
|
183
|
+
// re-acquires it via PyGILState_Ensure.
|
|
184
|
+
do {
|
|
185
|
+
try bootstrapPaths(appPath: appPath, packagesPath: packagesPath)
|
|
186
|
+
} catch {
|
|
187
|
+
PyEval_SaveThread()
|
|
188
|
+
throw error
|
|
189
|
+
}
|
|
190
|
+
PyEval_SaveThread()
|
|
191
|
+
NSLog("[PN] Embedded Python initialized (home: \(pythonHome))")
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
private func bootstrapPaths(appPath: String, packagesPath: String) throws {
|
|
195
|
+
// site.addsitedir(app_packages): adds to sys.path and honors .pth files.
|
|
196
|
+
guard let site = PyImport_ImportModule("site"),
|
|
197
|
+
let addsitedir = PyObject_GetAttrString(site, "addsitedir")
|
|
198
|
+
else {
|
|
199
|
+
throw PythonRuntimeError.startup("Could not import the site module: \(Self.consumeError())")
|
|
200
|
+
}
|
|
201
|
+
defer { Py_DecRef(site) }
|
|
202
|
+
defer { Py_DecRef(addsitedir) }
|
|
203
|
+
guard let packagesObj = PyUnicode_FromString(packagesPath),
|
|
204
|
+
let argsTuple = PyTuple_New(1)
|
|
205
|
+
else {
|
|
206
|
+
throw PythonRuntimeError.startup("Could not build site.addsitedir arguments.")
|
|
207
|
+
}
|
|
208
|
+
PyTuple_SetItem(argsTuple, 0, packagesObj) // steals packagesObj
|
|
209
|
+
defer { Py_DecRef(argsTuple) }
|
|
210
|
+
guard let addResult = PyObject_CallObject(addsitedir, argsTuple) else {
|
|
211
|
+
throw PythonRuntimeError.startup("site.addsitedir failed: \(Self.consumeError())")
|
|
212
|
+
}
|
|
213
|
+
Py_DecRef(addResult)
|
|
214
|
+
|
|
215
|
+
// sys.path.insert(0, app) so `import app.main` resolves.
|
|
216
|
+
guard let sys = PyImport_ImportModule("sys"),
|
|
217
|
+
let sysPath = PyObject_GetAttrString(sys, "path"),
|
|
218
|
+
let appObj = PyUnicode_FromString(appPath)
|
|
219
|
+
else {
|
|
220
|
+
throw PythonRuntimeError.startup("Could not access sys.path: \(Self.consumeError())")
|
|
221
|
+
}
|
|
222
|
+
defer { Py_DecRef(sys) }
|
|
223
|
+
defer { Py_DecRef(sysPath) }
|
|
224
|
+
defer { Py_DecRef(appObj) }
|
|
225
|
+
// The bundle root itself is also importable ("app" package form).
|
|
226
|
+
if let resourceObj = PyUnicode_FromString(Bundle.main.resourcePath ?? appPath) {
|
|
227
|
+
PyList_Insert(sysPath, 0, resourceObj)
|
|
228
|
+
Py_DecRef(resourceObj)
|
|
229
|
+
}
|
|
230
|
+
if PyList_Insert(sysPath, 0, appObj) != 0 {
|
|
231
|
+
throw PythonRuntimeError.startup("Could not add the app directory to sys.path.")
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
#if DEBUG
|
|
235
|
+
// Dev-only: prioritize the writable hot-reload overlay. Release
|
|
236
|
+
// builds never look outside the signed bundle.
|
|
237
|
+
let documents = NSHomeDirectory() + "/Documents"
|
|
238
|
+
guard let hotReload = PyImport_ImportModule("pythonnative.hot_reload"),
|
|
239
|
+
let configure = PyObject_GetAttrString(hotReload, "configure_dev_environment"),
|
|
240
|
+
let docsObj = PyUnicode_FromString(documents),
|
|
241
|
+
let devArgs = PyTuple_New(1)
|
|
242
|
+
else {
|
|
243
|
+
throw PythonRuntimeError.startup(
|
|
244
|
+
"Could not import pythonnative: \(Self.consumeError())\n"
|
|
245
|
+
+ "The pythonnative package must be staged into app_packages by the pn CLI."
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
defer { Py_DecRef(hotReload) }
|
|
249
|
+
defer { Py_DecRef(configure) }
|
|
250
|
+
PyTuple_SetItem(devArgs, 0, docsObj) // steals docsObj
|
|
251
|
+
defer { Py_DecRef(devArgs) }
|
|
252
|
+
if let devResult = PyObject_CallObject(configure, devArgs) {
|
|
253
|
+
Py_DecRef(devResult)
|
|
254
|
+
} else {
|
|
255
|
+
throw PythonRuntimeError.startup("Hot-reload setup failed: \(Self.consumeError())")
|
|
256
|
+
}
|
|
257
|
+
#endif
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// MARK: - Calling into Python
|
|
261
|
+
|
|
262
|
+
/// Import `module` and call its `function` with the given arguments.
|
|
263
|
+
/// Supported argument types: String, Int, UInt, Bool, Double.
|
|
264
|
+
@discardableResult
|
|
265
|
+
func call(module: String, function: String, _ args: Any...) throws -> PyRef {
|
|
266
|
+
try callList(module: module, function: function, args)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
@discardableResult
|
|
270
|
+
func callList(module: String, function: String, _ args: [Any]) throws -> PyRef {
|
|
271
|
+
guard started else {
|
|
272
|
+
throw PythonRuntimeError.call("Python is not running (startup failed or never happened).")
|
|
273
|
+
}
|
|
274
|
+
let gil = PyGILState_Ensure()
|
|
275
|
+
defer { PyGILState_Release(gil) }
|
|
276
|
+
guard let moduleObj = PyImport_ImportModule(module) else {
|
|
277
|
+
throw PythonRuntimeError.call("Could not import \(module): \(Self.consumeError())")
|
|
278
|
+
}
|
|
279
|
+
defer { Py_DecRef(moduleObj) }
|
|
280
|
+
guard let fnObj = PyObject_GetAttrString(moduleObj, function) else {
|
|
281
|
+
throw PythonRuntimeError.call("\(module) has no attribute '\(function)': \(Self.consumeError())")
|
|
282
|
+
}
|
|
283
|
+
defer { Py_DecRef(fnObj) }
|
|
284
|
+
return try Self.invoke(fnObj, args: args, context: "\(module).\(function)")
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/// Shared invocation helper. The caller must hold the GIL.
|
|
288
|
+
fileprivate static func invoke(
|
|
289
|
+
_ callable: UnsafeMutablePointer<PyObject>,
|
|
290
|
+
args: [Any],
|
|
291
|
+
context: String
|
|
292
|
+
) throws -> PyRef {
|
|
293
|
+
guard let tuple = PyTuple_New(args.count) else {
|
|
294
|
+
throw PythonRuntimeError.call("Could not allocate arguments for \(context).")
|
|
295
|
+
}
|
|
296
|
+
for (index, arg) in args.enumerated() {
|
|
297
|
+
guard let converted = convert(arg) else {
|
|
298
|
+
Py_DecRef(tuple)
|
|
299
|
+
throw PythonRuntimeError.call("Unsupported argument type \(type(of: arg)) for \(context).")
|
|
300
|
+
}
|
|
301
|
+
PyTuple_SetItem(tuple, index, converted) // steals converted
|
|
302
|
+
}
|
|
303
|
+
defer { Py_DecRef(tuple) }
|
|
304
|
+
guard let result = PyObject_CallObject(callable, tuple) else {
|
|
305
|
+
throw PythonRuntimeError.call("\(context) raised: \(consumeError())")
|
|
306
|
+
}
|
|
307
|
+
return PyRef(owned: result)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private static func convert(_ value: Any) -> UnsafeMutablePointer<PyObject>? {
|
|
311
|
+
switch value {
|
|
312
|
+
case let string as String:
|
|
313
|
+
return PyUnicode_FromString(string)
|
|
314
|
+
case let flag as Bool:
|
|
315
|
+
return PyBool_FromLong(flag ? 1 : 0)
|
|
316
|
+
case let unsigned as UInt:
|
|
317
|
+
return PyLong_FromUnsignedLongLong(UInt64(unsigned))
|
|
318
|
+
case let integer as Int:
|
|
319
|
+
return PyLong_FromLongLong(Int64(integer))
|
|
320
|
+
case let double as Double:
|
|
321
|
+
return PyFloat_FromDouble(double)
|
|
322
|
+
default:
|
|
323
|
+
return nil
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// MARK: - Error formatting
|
|
328
|
+
|
|
329
|
+
/// Format and clear the pending Python exception (caller holds the GIL).
|
|
330
|
+
fileprivate static func consumeError() -> String {
|
|
331
|
+
var ptype: UnsafeMutablePointer<PyObject>? = nil
|
|
332
|
+
var pvalue: UnsafeMutablePointer<PyObject>? = nil
|
|
333
|
+
var ptrace: UnsafeMutablePointer<PyObject>? = nil
|
|
334
|
+
PyErr_Fetch(&ptype, &pvalue, &ptrace)
|
|
335
|
+
PyErr_NormalizeException(&ptype, &pvalue, &ptrace)
|
|
336
|
+
defer {
|
|
337
|
+
Py_DecRef(ptype)
|
|
338
|
+
Py_DecRef(pvalue)
|
|
339
|
+
Py_DecRef(ptrace)
|
|
340
|
+
}
|
|
341
|
+
guard ptype != nil else { return "unknown Python error" }
|
|
342
|
+
|
|
343
|
+
if let traceback = PyImport_ImportModule("traceback") {
|
|
344
|
+
defer { Py_DecRef(traceback) }
|
|
345
|
+
let fnName = ptrace != nil ? "format_exception" : "format_exception_only"
|
|
346
|
+
if let formatFn = PyObject_GetAttrString(traceback, fnName) {
|
|
347
|
+
defer { Py_DecRef(formatFn) }
|
|
348
|
+
let count = ptrace != nil ? 3 : 2
|
|
349
|
+
if let tuple = PyTuple_New(count) {
|
|
350
|
+
Py_IncRef(ptype)
|
|
351
|
+
PyTuple_SetItem(tuple, 0, ptype)
|
|
352
|
+
Py_IncRef(pvalue)
|
|
353
|
+
PyTuple_SetItem(tuple, 1, pvalue)
|
|
354
|
+
if count == 3 {
|
|
355
|
+
Py_IncRef(ptrace)
|
|
356
|
+
PyTuple_SetItem(tuple, 2, ptrace)
|
|
357
|
+
}
|
|
358
|
+
defer { Py_DecRef(tuple) }
|
|
359
|
+
if let lines = PyObject_CallObject(formatFn, tuple) {
|
|
360
|
+
defer { Py_DecRef(lines) }
|
|
361
|
+
if let empty = PyUnicode_FromString(""),
|
|
362
|
+
let joined = PyUnicode_Join(empty, lines)
|
|
363
|
+
{
|
|
364
|
+
Py_DecRef(empty)
|
|
365
|
+
defer { Py_DecRef(joined) }
|
|
366
|
+
if let utf8 = PyUnicode_AsUTF8(joined) {
|
|
367
|
+
return String(cString: utf8)
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
// Fallback: str(value).
|
|
375
|
+
if let value = pvalue, let str = PyObject_Str(value) {
|
|
376
|
+
defer { Py_DecRef(str) }
|
|
377
|
+
if let utf8 = PyUnicode_AsUTF8(str) {
|
|
378
|
+
return String(cString: utf8)
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return "unknown Python error"
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
private static func statusMessage(_ status: PyStatus) -> String {
|
|
385
|
+
if let errMsg = status.err_msg {
|
|
386
|
+
return String(cString: errMsg)
|
|
387
|
+
}
|
|
388
|
+
return "unknown error"
|
|
389
|
+
}
|
|
390
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
//
|
|
2
|
+
// SceneDelegate.swift
|
|
3
|
+
// ios_template
|
|
4
|
+
//
|
|
5
|
+
// Creates the window programmatically and forwards scene-level events
|
|
6
|
+
// (deep links, foreground/background transitions) to the Swift native
|
|
7
|
+
// modules, which relay them to Python over the bridge.
|
|
8
|
+
//
|
|
9
|
+
|
|
10
|
+
import PythonNativeKit
|
|
11
|
+
import UIKit
|
|
12
|
+
|
|
13
|
+
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|
14
|
+
var window: UIWindow?
|
|
15
|
+
|
|
16
|
+
func scene(
|
|
17
|
+
_ scene: UIScene,
|
|
18
|
+
willConnectTo session: UISceneSession,
|
|
19
|
+
options connectionOptions: UIScene.ConnectionOptions
|
|
20
|
+
) {
|
|
21
|
+
guard let windowScene = (scene as? UIWindowScene) else { return }
|
|
22
|
+
// A cold start from a deep link delivers the URL here, before
|
|
23
|
+
// Python is running; LinkingModule buffers it until the bridge
|
|
24
|
+
// callback is registered so Linking.get_initial_url() sees it.
|
|
25
|
+
for context in connectionOptions.urlContexts {
|
|
26
|
+
LinkingModule.deliver(url: context.url.absoluteString)
|
|
27
|
+
}
|
|
28
|
+
let window = UIWindow(windowScene: windowScene)
|
|
29
|
+
let root = ViewController()
|
|
30
|
+
let nav = UINavigationController(rootViewController: root)
|
|
31
|
+
window.rootViewController = nav
|
|
32
|
+
self.window = window
|
|
33
|
+
window.makeKeyAndVisible()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
|
|
37
|
+
for context in URLContexts {
|
|
38
|
+
LinkingModule.deliver(url: context.url.absoluteString)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// MARK: - AppState forwarding
|
|
43
|
+
|
|
44
|
+
func sceneDidBecomeActive(_ scene: UIScene) {
|
|
45
|
+
AppStateModule.dispatch("active")
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
func sceneWillResignActive(_ scene: UIScene) {
|
|
49
|
+
AppStateModule.dispatch("inactive")
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
func sceneWillEnterForeground(_ scene: UIScene) {
|
|
53
|
+
AppStateModule.dispatch("inactive")
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
func sceneDidEnterBackground(_ scene: UIScene) {
|
|
57
|
+
AppStateModule.dispatch("background")
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
func sceneDidDisconnect(_ scene: UIScene) {}
|
|
61
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ViewController.swift
|
|
3
|
+
// ios_template
|
|
4
|
+
//
|
|
5
|
+
// Hosts one PythonNative screen. All screen plumbing lives in
|
|
6
|
+
// PythonNativeKit's PNViewController; this subclass only starts the
|
|
7
|
+
// embedded interpreter (showing a bootstrap error on failure).
|
|
8
|
+
//
|
|
9
|
+
|
|
10
|
+
import PythonNativeKit
|
|
11
|
+
import UIKit
|
|
12
|
+
|
|
13
|
+
final class ViewController: PNViewController {
|
|
14
|
+
override func prepareRuntime() -> Bool {
|
|
15
|
+
do {
|
|
16
|
+
try PythonRuntime.shared.ensureStarted()
|
|
17
|
+
} catch {
|
|
18
|
+
showBootstrapError("Python failed to start.\n\n\(error)")
|
|
19
|
+
return false
|
|
20
|
+
}
|
|
21
|
+
return true
|
|
22
|
+
}
|
|
23
|
+
}
|