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.
Files changed (418) hide show
  1. pythonnative/__init__.py +411 -0
  2. pythonnative/_ios_log.py +92 -0
  3. pythonnative/_yoga.cp313-win_amd64.pyd +0 -0
  4. pythonnative/alerts.py +236 -0
  5. pythonnative/animated.py +1687 -0
  6. pythonnative/animation_graph.py +78 -0
  7. pythonnative/appearance.py +124 -0
  8. pythonnative/bootstrap.py +100 -0
  9. pythonnative/bridge/__init__.py +302 -0
  10. pythonnative/bridge/android.py +78 -0
  11. pythonnative/bridge/codec.py +170 -0
  12. pythonnative/bridge/commits.py +114 -0
  13. pythonnative/bridge/fake.py +243 -0
  14. pythonnative/bridge/ios.py +138 -0
  15. pythonnative/bridge/web.py +489 -0
  16. pythonnative/cli/__init__.py +7 -0
  17. pythonnative/cli/pn.py +1214 -0
  18. pythonnative/component.py +271 -0
  19. pythonnative/components/__init__.py +111 -0
  20. pythonnative/components/_base.py +166 -0
  21. pythonnative/components/controls.py +521 -0
  22. pythonnative/components/layout.py +518 -0
  23. pythonnative/components/lists.py +785 -0
  24. pythonnative/components/media.py +204 -0
  25. pythonnative/components/overlays.py +107 -0
  26. pythonnative/components/pressable.py +252 -0
  27. pythonnative/components/structural.py +167 -0
  28. pythonnative/components/text.py +291 -0
  29. pythonnative/devclient.py +824 -0
  30. pythonnative/devserver/__init__.py +34 -0
  31. pythonnative/devserver/server.py +718 -0
  32. pythonnative/devserver/static/animation_graph.js +82 -0
  33. pythonnative/devserver/static/bridge.js +147 -0
  34. pythonnative/devserver/static/colors.js +70 -0
  35. pythonnative/devserver/static/host.js +552 -0
  36. pythonnative/devserver/static/index.html +60 -0
  37. pythonnative/devserver/static/layout.js +85 -0
  38. pythonnative/devserver/static/preview.css +415 -0
  39. pythonnative/devserver/static/renderer.js +1994 -0
  40. pythonnative/devserver/static/shell.js +345 -0
  41. pythonnative/devserver/static/yoga/LICENSE +21 -0
  42. pythonnative/devserver/static/yoga/binaries/yoga-wasm-base64-esm.js +75 -0
  43. pythonnative/devserver/static/yoga/src/generated/YGEnums.d.ts +189 -0
  44. pythonnative/devserver/static/yoga/src/generated/YGEnums.js +211 -0
  45. pythonnative/devserver/static/yoga/src/generated/YGEnums.js.map +1 -0
  46. pythonnative/devserver/static/yoga/src/index.d.ts +12 -0
  47. pythonnative/devserver/static/yoga/src/index.js +16 -0
  48. pythonnative/devserver/static/yoga/src/index.js.map +1 -0
  49. pythonnative/devserver/static/yoga/src/load.d.ts +11 -0
  50. pythonnative/devserver/static/yoga/src/load.js +17 -0
  51. pythonnative/devserver/static/yoga/src/load.js.map +1 -0
  52. pythonnative/devserver/static/yoga/src/wrapAssembly.d.ts +155 -0
  53. pythonnative/devserver/static/yoga/src/wrapAssembly.js +125 -0
  54. pythonnative/devserver/static/yoga/src/wrapAssembly.js.map +1 -0
  55. pythonnative/devserver/watcher.py +267 -0
  56. pythonnative/devserver/ws.py +421 -0
  57. pythonnative/diagnostics.py +241 -0
  58. pythonnative/element.py +159 -0
  59. pythonnative/equality.py +19 -0
  60. pythonnative/events.py +231 -0
  61. pythonnative/gestures.py +1333 -0
  62. pythonnative/hooks.py +1621 -0
  63. pythonnative/hosts/__init__.py +63 -0
  64. pythonnative/hosts/base.py +596 -0
  65. pythonnative/hosts/native.py +302 -0
  66. pythonnative/hot_reload.py +585 -0
  67. pythonnative/layout.py +328 -0
  68. pythonnative/mutations.py +142 -0
  69. pythonnative/native/android/build.gradle +52 -0
  70. pythonnative/native/android/gradle.properties +3 -0
  71. pythonnative/native/android/settings.gradle +12 -0
  72. pythonnative/native/android/src/main/AndroidManifest.xml +11 -0
  73. pythonnative/native/android/src/main/cpp/CMakeLists.txt +9 -0
  74. pythonnative/native/android/src/main/cpp/yoga_jni.cpp +52 -0
  75. pythonnative/native/android/src/main/java/com/pythonnative/generated/NativeModules.kt +5 -0
  76. pythonnative/native/android/src/main/java/com/pythonnative/generated/NativeProps.kt +3705 -0
  77. pythonnative/native/android/src/main/java/com/pythonnative/generated/PNContracts.kt +129 -0
  78. pythonnative/native/android/src/main/java/com/pythonnative/runtime/PNBridge.kt +261 -0
  79. pythonnative/native/android/src/main/java/com/pythonnative/runtime/PythonHost.kt +20 -0
  80. pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/AnimationGraph.kt +108 -0
  81. pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/AnimationSpecs.kt +141 -0
  82. pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/PNAnimator.kt +257 -0
  83. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/CommitState.kt +106 -0
  84. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/JsonUtil.kt +175 -0
  85. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/MainThread.kt +40 -0
  86. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNLog.kt +33 -0
  87. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNRegistry.kt +82 -0
  88. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNTransaction.kt +80 -0
  89. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/TransactionApplier.kt +117 -0
  90. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/ViewRegistry.kt +74 -0
  91. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/BuiltinComponents.kt +37 -0
  92. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ButtonManager.kt +32 -0
  93. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ComponentManager.kt +213 -0
  94. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ContainerManagers.kt +69 -0
  95. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ControlManagers.kt +186 -0
  96. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/DatePickerManager.kt +123 -0
  97. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ImageLoader.kt +141 -0
  98. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ImageManager.kt +162 -0
  99. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ModalManager.kt +134 -0
  100. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PNColor.kt +201 -0
  101. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PickerManager.kt +86 -0
  102. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PortalManager.kt +55 -0
  103. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PressableManager.kt +122 -0
  104. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ScreenStackManager.kt +110 -0
  105. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ScrollViewManager.kt +214 -0
  106. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/SegmentedControlManager.kt +113 -0
  107. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/StatusBarManager.kt +52 -0
  108. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TabBarManager.kt +131 -0
  109. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TextInputManager.kt +250 -0
  110. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TextManager.kt +233 -0
  111. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ViewStyler.kt +355 -0
  112. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/VirtualListManager.kt +159 -0
  113. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/WebViewManager.kt +149 -0
  114. pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureArbiter.kt +233 -0
  115. pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureCoordinator.kt +127 -0
  116. pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureRecognizers.kt +527 -0
  117. pythonnative/native/android/src/main/java/com/pythonnative/runtime/layout/NativeLayout.kt +145 -0
  118. pythonnative/native/android/src/main/java/com/pythonnative/runtime/layout/YogaNode.kt +29 -0
  119. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/BuiltinModules.kt +73 -0
  120. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/DeviceModules.kt +316 -0
  121. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/HostModule.kt +61 -0
  122. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/MediaModules.kt +200 -0
  123. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/NativeModule.kt +158 -0
  124. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/NotificationsModule.kt +100 -0
  125. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/PermissionsModule.kt +99 -0
  126. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/StorageModules.kt +89 -0
  127. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/SystemModules.kt +178 -0
  128. pythonnative/native/android/src/main/java/com/pythonnative/runtime/plugins/GeneratedPlugins.kt +16 -0
  129. pythonnative/native/android/src/main/java/com/pythonnative/runtime/screens/PNScreenFragment.kt +188 -0
  130. pythonnative/native/android/src/main/java/com/pythonnative/runtime/screens/ScreenRegistry.kt +80 -0
  131. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNAccessibilityDelegate.kt +48 -0
  132. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNBorderDrawable.kt +76 -0
  133. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNEditText.kt +18 -0
  134. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNFrameLayout.kt +49 -0
  135. pythonnative/native/android/src/test/java/com/pythonnative/runtime/AnimationSpecsTest.kt +75 -0
  136. pythonnative/native/android/src/test/java/com/pythonnative/runtime/GestureArbiterTest.kt +197 -0
  137. pythonnative/native/android/src/test/java/com/pythonnative/runtime/PNColorTest.kt +47 -0
  138. pythonnative/native/android/src/test/java/com/pythonnative/runtime/PNTransactionTest.kt +78 -0
  139. pythonnative/native/android/src/test/java/com/pythonnative/runtime/PromiseTest.kt +89 -0
  140. pythonnative/native/ios/Package.swift +23 -0
  141. pythonnative/native/ios/Sources/PythonNativeKit/Animation/PNAnimationGraph.swift +199 -0
  142. pythonnative/native/ios/Sources/PythonNativeKit/Animation/PNAnimator.swift +312 -0
  143. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNBridge.swift +255 -0
  144. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNCommit.swift +104 -0
  145. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNRegistry.swift +142 -0
  146. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNTransaction.swift +166 -0
  147. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNViewRegistry.swift +53 -0
  148. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNButtonManagers.swift +207 -0
  149. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNColor.swift +173 -0
  150. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNComponentManager.swift +183 -0
  151. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNContainerView.swift +56 -0
  152. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNControlManagers.swift +281 -0
  153. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNImageManager.swift +222 -0
  154. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNOverlayManagers.swift +243 -0
  155. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNPressableManager.swift +114 -0
  156. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNScreenStackManager.swift +107 -0
  157. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNScrollViewManager.swift +197 -0
  158. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTabBarManager.swift +106 -0
  159. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTextInputManager.swift +297 -0
  160. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTextManager.swift +230 -0
  161. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTransform.swift +82 -0
  162. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewManager.swift +86 -0
  163. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewState.swift +87 -0
  164. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewStyler.swift +340 -0
  165. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNVirtualListManager.swift +155 -0
  166. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNWebViewManager.swift +124 -0
  167. pythonnative/native/ios/Sources/PythonNativeKit/Generated/NativeModules.swift +1 -0
  168. pythonnative/native/ios/Sources/PythonNativeKit/Generated/NativeProps.swift +3775 -0
  169. pythonnative/native/ios/Sources/PythonNativeKit/Generated/PNContracts.swift +46 -0
  170. pythonnative/native/ios/Sources/PythonNativeKit/Gestures/PNGestureCoordinator.swift +260 -0
  171. pythonnative/native/ios/Sources/PythonNativeKit/Layout/PNLayout.swift +173 -0
  172. pythonnative/native/ios/Sources/PythonNativeKit/Modules/AlertModule.swift +92 -0
  173. pythonnative/native/ios/Sources/PythonNativeKit/Modules/HostModule.swift +80 -0
  174. pythonnative/native/ios/Sources/PythonNativeKit/Modules/LifecycleModules.swift +174 -0
  175. pythonnative/native/ios/Sources/PythonNativeKit/Modules/MediaModules.swift +177 -0
  176. pythonnative/native/ios/Sources/PythonNativeKit/Modules/PNNativeModule.swift +168 -0
  177. pythonnative/native/ios/Sources/PythonNativeKit/Modules/PermissionModules.swift +266 -0
  178. pythonnative/native/ios/Sources/PythonNativeKit/Modules/SystemModules.swift +251 -0
  179. pythonnative/native/ios/Sources/PythonNativeKit/Plugins/PNPluginRegistration.swift +8 -0
  180. pythonnative/native/ios/Sources/PythonNativeKit/Screens/PNScreenRegistry.swift +46 -0
  181. pythonnative/native/ios/Sources/PythonNativeKit/Screens/PNViewController.swift +237 -0
  182. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNCompat.swift +46 -0
  183. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNJSON.swift +173 -0
  184. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNLog.swift +47 -0
  185. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNWindow.swift +51 -0
  186. pythonnative/native/ios/Tests/PythonNativeKitTests/PNAnimationGraphTests.swift +26 -0
  187. pythonnative/native/ios/Tests/PythonNativeKitTests/PNColorTests.swift +50 -0
  188. pythonnative/native/ios/Tests/PythonNativeKitTests/PNCommitTests.swift +86 -0
  189. pythonnative/native/ios/Tests/PythonNativeKitTests/PNGestureTests.swift +101 -0
  190. pythonnative/native/ios/Tests/PythonNativeKitTests/PNManagerTests.swift +126 -0
  191. pythonnative/native/ios/Tests/PythonNativeKitTests/PNModuleTests.swift +111 -0
  192. pythonnative/native/ios/Tests/PythonNativeKitTests/PNTransactionTests.swift +91 -0
  193. pythonnative/native/yoga/LICENSE +21 -0
  194. pythonnative/native/yoga/Package.swift +9 -0
  195. pythonnative/native/yoga/VENDORED.md +2 -0
  196. pythonnative/native/yoga/include/PNStyle.h +10 -0
  197. pythonnative/native/yoga/include/module.modulemap +5 -0
  198. pythonnative/native/yoga/include/yoga/YGConfig.h +158 -0
  199. pythonnative/native/yoga/include/yoga/YGEnums.h +142 -0
  200. pythonnative/native/yoga/include/yoga/YGMacros.h +99 -0
  201. pythonnative/native/yoga/include/yoga/YGNode.h +304 -0
  202. pythonnative/native/yoga/include/yoga/YGNodeLayout.h +35 -0
  203. pythonnative/native/yoga/include/yoga/YGNodeStyle.h +130 -0
  204. pythonnative/native/yoga/include/yoga/YGPixelGrid.h +29 -0
  205. pythonnative/native/yoga/include/yoga/YGValue.h +84 -0
  206. pythonnative/native/yoga/include/yoga/Yoga.h +21 -0
  207. pythonnative/native/yoga/python.cpp +16 -0
  208. pythonnative/native/yoga/style.cpp +272 -0
  209. pythonnative/native/yoga/yoga/CMakeLists.txt +41 -0
  210. pythonnative/native/yoga/yoga/YGConfig.cpp +92 -0
  211. pythonnative/native/yoga/yoga/YGConfig.h +158 -0
  212. pythonnative/native/yoga/yoga/YGEnums.cpp +262 -0
  213. pythonnative/native/yoga/yoga/YGEnums.h +142 -0
  214. pythonnative/native/yoga/yoga/YGMacros.h +99 -0
  215. pythonnative/native/yoga/yoga/YGNode.cpp +366 -0
  216. pythonnative/native/yoga/yoga/YGNode.h +304 -0
  217. pythonnative/native/yoga/yoga/YGNodeLayout.cpp +92 -0
  218. pythonnative/native/yoga/yoga/YGNodeLayout.h +35 -0
  219. pythonnative/native/yoga/yoga/YGNodeStyle.cpp +405 -0
  220. pythonnative/native/yoga/yoga/YGNodeStyle.h +130 -0
  221. pythonnative/native/yoga/yoga/YGPixelGrid.cpp +22 -0
  222. pythonnative/native/yoga/yoga/YGPixelGrid.h +29 -0
  223. pythonnative/native/yoga/yoga/YGValue.cpp +20 -0
  224. pythonnative/native/yoga/yoga/YGValue.h +84 -0
  225. pythonnative/native/yoga/yoga/Yoga.h +21 -0
  226. pythonnative/native/yoga/yoga/algorithm/AbsoluteLayout.cpp +563 -0
  227. pythonnative/native/yoga/yoga/algorithm/AbsoluteLayout.h +41 -0
  228. pythonnative/native/yoga/yoga/algorithm/Align.h +72 -0
  229. pythonnative/native/yoga/yoga/algorithm/Baseline.cpp +78 -0
  230. pythonnative/native/yoga/yoga/algorithm/Baseline.h +21 -0
  231. pythonnative/native/yoga/yoga/algorithm/BoundAxis.h +79 -0
  232. pythonnative/native/yoga/yoga/algorithm/Cache.cpp +121 -0
  233. pythonnative/native/yoga/yoga/algorithm/Cache.h +30 -0
  234. pythonnative/native/yoga/yoga/algorithm/CalculateLayout.cpp +2428 -0
  235. pythonnative/native/yoga/yoga/algorithm/CalculateLayout.h +38 -0
  236. pythonnative/native/yoga/yoga/algorithm/FlexDirection.h +120 -0
  237. pythonnative/native/yoga/yoga/algorithm/FlexLine.cpp +124 -0
  238. pythonnative/native/yoga/yoga/algorithm/FlexLine.h +75 -0
  239. pythonnative/native/yoga/yoga/algorithm/PixelGrid.cpp +132 -0
  240. pythonnative/native/yoga/yoga/algorithm/PixelGrid.h +29 -0
  241. pythonnative/native/yoga/yoga/algorithm/SizingMode.h +73 -0
  242. pythonnative/native/yoga/yoga/algorithm/TrailingPosition.h +44 -0
  243. pythonnative/native/yoga/yoga/config/Config.cpp +135 -0
  244. pythonnative/native/yoga/yoga/config/Config.h +92 -0
  245. pythonnative/native/yoga/yoga/debug/AssertFatal.cpp +53 -0
  246. pythonnative/native/yoga/yoga/debug/AssertFatal.h +29 -0
  247. pythonnative/native/yoga/yoga/debug/Log.cpp +107 -0
  248. pythonnative/native/yoga/yoga/debug/Log.h +34 -0
  249. pythonnative/native/yoga/yoga/enums/Align.h +47 -0
  250. pythonnative/native/yoga/yoga/enums/BoxSizing.h +40 -0
  251. pythonnative/native/yoga/yoga/enums/Dimension.h +40 -0
  252. pythonnative/native/yoga/yoga/enums/Direction.h +41 -0
  253. pythonnative/native/yoga/yoga/enums/Display.h +41 -0
  254. pythonnative/native/yoga/yoga/enums/Edge.h +47 -0
  255. pythonnative/native/yoga/yoga/enums/Errata.h +41 -0
  256. pythonnative/native/yoga/yoga/enums/ExperimentalFeature.h +39 -0
  257. pythonnative/native/yoga/yoga/enums/FlexDirection.h +42 -0
  258. pythonnative/native/yoga/yoga/enums/Gutter.h +41 -0
  259. pythonnative/native/yoga/yoga/enums/Justify.h +44 -0
  260. pythonnative/native/yoga/yoga/enums/LogLevel.h +44 -0
  261. pythonnative/native/yoga/yoga/enums/MeasureMode.h +41 -0
  262. pythonnative/native/yoga/yoga/enums/NodeType.h +40 -0
  263. pythonnative/native/yoga/yoga/enums/Overflow.h +41 -0
  264. pythonnative/native/yoga/yoga/enums/PhysicalEdge.h +21 -0
  265. pythonnative/native/yoga/yoga/enums/PositionType.h +41 -0
  266. pythonnative/native/yoga/yoga/enums/Unit.h +42 -0
  267. pythonnative/native/yoga/yoga/enums/Wrap.h +41 -0
  268. pythonnative/native/yoga/yoga/enums/YogaEnums.h +85 -0
  269. pythonnative/native/yoga/yoga/event/event.cpp +87 -0
  270. pythonnative/native/yoga/yoga/event/event.h +130 -0
  271. pythonnative/native/yoga/yoga/module.modulemap +21 -0
  272. pythonnative/native/yoga/yoga/node/CachedMeasurement.h +53 -0
  273. pythonnative/native/yoga/yoga/node/LayoutResults.cpp +48 -0
  274. pythonnative/native/yoga/yoga/node/LayoutResults.h +122 -0
  275. pythonnative/native/yoga/yoga/node/LayoutableChildren.h +148 -0
  276. pythonnative/native/yoga/yoga/node/Node.cpp +443 -0
  277. pythonnative/native/yoga/yoga/node/Node.h +337 -0
  278. pythonnative/native/yoga/yoga/numeric/Comparison.h +81 -0
  279. pythonnative/native/yoga/yoga/numeric/FloatOptional.h +93 -0
  280. pythonnative/native/yoga/yoga/style/SmallValueBuffer.h +133 -0
  281. pythonnative/native/yoga/yoga/style/Style.h +757 -0
  282. pythonnative/native/yoga/yoga/style/StyleLength.h +107 -0
  283. pythonnative/native/yoga/yoga/style/StyleValueHandle.h +98 -0
  284. pythonnative/native/yoga/yoga/style/StyleValuePool.h +127 -0
  285. pythonnative/native_modules/__init__.py +124 -0
  286. pythonnative/native_modules/app_state.py +99 -0
  287. pythonnative/native_modules/battery.py +75 -0
  288. pythonnative/native_modules/biometrics.py +42 -0
  289. pythonnative/native_modules/camera.py +65 -0
  290. pythonnative/native_modules/clipboard.py +46 -0
  291. pythonnative/native_modules/fallback.py +324 -0
  292. pythonnative/native_modules/file_system.py +145 -0
  293. pythonnative/native_modules/haptics.py +75 -0
  294. pythonnative/native_modules/linking.py +123 -0
  295. pythonnative/native_modules/location.py +75 -0
  296. pythonnative/native_modules/net_info.py +112 -0
  297. pythonnative/native_modules/notifications.py +129 -0
  298. pythonnative/native_modules/permissions.py +108 -0
  299. pythonnative/native_modules/registry.py +526 -0
  300. pythonnative/native_modules/secure_store.py +52 -0
  301. pythonnative/native_modules/share.py +51 -0
  302. pythonnative/native_views/__init__.py +375 -0
  303. pythonnative/native_views/base.py +316 -0
  304. pythonnative/native_views/bridge_backend.py +277 -0
  305. pythonnative/navigation/__init__.py +103 -0
  306. pythonnative/navigation/container.py +154 -0
  307. pythonnative/navigation/handle.py +540 -0
  308. pythonnative/navigation/hooks.py +133 -0
  309. pythonnative/navigation/host.py +58 -0
  310. pythonnative/navigation/linking.py +200 -0
  311. pythonnative/navigation/navigators.py +659 -0
  312. pythonnative/navigation/screen.py +149 -0
  313. pythonnative/navigation/state.py +269 -0
  314. pythonnative/net.py +248 -0
  315. pythonnative/platform.py +166 -0
  316. pythonnative/platform_metrics.py +252 -0
  317. pythonnative/preview.py +287 -0
  318. pythonnative/profiling.py +101 -0
  319. pythonnative/project/__init__.py +68 -0
  320. pythonnative/project/android.py +557 -0
  321. pythonnative/project/builder.py +817 -0
  322. pythonnative/project/config.py +773 -0
  323. pythonnative/project/deps.py +719 -0
  324. pythonnative/project/devices.py +304 -0
  325. pythonnative/project/doctor.py +283 -0
  326. pythonnative/project/fingerprint.py +171 -0
  327. pythonnative/project/icons.py +247 -0
  328. pythonnative/project/ios.py +325 -0
  329. pythonnative/project/lockfile.py +100 -0
  330. pythonnative/project/permissions.py +361 -0
  331. pythonnative/project/plugins.py +519 -0
  332. pythonnative/project/runtime_assets.py +183 -0
  333. pythonnative/py.typed +0 -0
  334. pythonnative/query.py +153 -0
  335. pythonnative/reconciler/__init__.py +29 -0
  336. pythonnative/reconciler/boundaries.py +375 -0
  337. pythonnative/reconciler/children.py +88 -0
  338. pythonnative/reconciler/core.py +1165 -0
  339. pythonnative/reconciler/layout_pass.py +393 -0
  340. pythonnative/reconciler/vnode.py +266 -0
  341. pythonnative/refresh.py +55 -0
  342. pythonnative/runtime.py +306 -0
  343. pythonnative/scheduler.py +159 -0
  344. pythonnative/sdk/__init__.py +153 -0
  345. pythonnative/sdk/_components.py +427 -0
  346. pythonnative/sdk/builtins.py +91 -0
  347. pythonnative/sdk/codegen.py +149 -0
  348. pythonnative/sdk/module_codegen.py +184 -0
  349. pythonnative/sdk/schema.py +224 -0
  350. pythonnative/sdk/templates/contracts.kt +46 -0
  351. pythonnative/sdk/templates/contracts.swift +46 -0
  352. pythonnative/storage.py +184 -0
  353. pythonnative/style.py +841 -0
  354. pythonnative/suspense.py +183 -0
  355. pythonnative/templates/android_template/app/build.gradle +75 -0
  356. pythonnative/templates/android_template/app/proguard-rules.pro +21 -0
  357. pythonnative/templates/android_template/app/src/androidTest/java/com/pythonnative/android_template/ExampleInstrumentedTest.kt +24 -0
  358. pythonnative/templates/android_template/app/src/debug/AndroidManifest.xml +7 -0
  359. pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +32 -0
  360. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +130 -0
  361. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/ScreenFragment.kt +13 -0
  362. pythonnative/templates/android_template/app/src/main/res/drawable/ic_launcher_background.xml +170 -0
  363. pythonnative/templates/android_template/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +30 -0
  364. pythonnative/templates/android_template/app/src/main/res/layout/activity_main.xml +10 -0
  365. pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +6 -0
  366. pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +6 -0
  367. pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
  368. pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp +0 -0
  369. pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
  370. pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp +0 -0
  371. pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
  372. pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp +0 -0
  373. pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
  374. pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp +0 -0
  375. pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
  376. pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp +0 -0
  377. pythonnative/templates/android_template/app/src/main/res/navigation/nav_graph.xml +22 -0
  378. pythonnative/templates/android_template/app/src/main/res/values/colors.xml +5 -0
  379. pythonnative/templates/android_template/app/src/main/res/values/strings.xml +5 -0
  380. pythonnative/templates/android_template/app/src/main/res/values/themes.xml +9 -0
  381. pythonnative/templates/android_template/app/src/main/res/values-night/themes.xml +7 -0
  382. pythonnative/templates/android_template/app/src/main/res/xml/backup_rules.xml +13 -0
  383. pythonnative/templates/android_template/app/src/main/res/xml/data_extraction_rules.xml +19 -0
  384. pythonnative/templates/android_template/app/src/test/java/com/pythonnative/android_template/ExampleUnitTest.kt +17 -0
  385. pythonnative/templates/android_template/build.gradle +10 -0
  386. pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.jar +0 -0
  387. pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.properties +6 -0
  388. pythonnative/templates/android_template/gradle.properties +23 -0
  389. pythonnative/templates/android_template/gradlew +185 -0
  390. pythonnative/templates/android_template/gradlew.bat +89 -0
  391. pythonnative/templates/android_template/settings.gradle +17 -0
  392. pythonnative/templates/ios_template/ios_template/AppDelegate.swift +51 -0
  393. pythonnative/templates/ios_template/ios_template/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
  394. pythonnative/templates/ios_template/ios_template/Assets.xcassets/AppIcon.appiconset/Contents.json +13 -0
  395. pythonnative/templates/ios_template/ios_template/Assets.xcassets/Contents.json +6 -0
  396. pythonnative/templates/ios_template/ios_template/Base.lproj/LaunchScreen.storyboard +25 -0
  397. pythonnative/templates/ios_template/ios_template/BridgingHeader.h +14 -0
  398. pythonnative/templates/ios_template/ios_template/Info.plist +28 -0
  399. pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +390 -0
  400. pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +61 -0
  401. pythonnative/templates/ios_template/ios_template/ViewController.swift +23 -0
  402. pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +745 -0
  403. pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  404. pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift +36 -0
  405. pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift +41 -0
  406. pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift +32 -0
  407. pythonnative/testing/__init__.py +53 -0
  408. pythonnative/testing/backend.py +276 -0
  409. pythonnative/testing/harness.py +369 -0
  410. pythonnative/utils.py +145 -0
  411. pythonnative-0.40.0.dist-info/DELVEWHEEL +2 -0
  412. pythonnative-0.40.0.dist-info/METADATA +150 -0
  413. pythonnative-0.40.0.dist-info/RECORD +418 -0
  414. pythonnative-0.40.0.dist-info/WHEEL +5 -0
  415. pythonnative-0.40.0.dist-info/entry_points.txt +2 -0
  416. pythonnative-0.40.0.dist-info/licenses/LICENSE +21 -0
  417. pythonnative-0.40.0.dist-info/top_level.txt +1 -0
  418. pythonnative.libs/msvcp140-a4c2229bdc2a2a630acdc095b4d86008.dll +0 -0
@@ -0,0 +1,325 @@
1
+ """Config-driven iOS project configurator.
2
+
3
+ Adapts the bundled ``ios_template`` Xcode project to a specific
4
+ [`AppConfig`][pythonnative.project.config.AppConfig]. Unlike Android, the
5
+ iOS bundle identifier, version, team, and deployment target are *not*
6
+ baked into files; they're passed to ``xcodebuild`` as build-setting
7
+ overrides (see [`build_settings`][pythonnative.project.ios.build_settings]),
8
+ which avoids fragile ``project.pbxproj`` edits. This module owns the
9
+ parts that must live on disk:
10
+
11
+ - **Info.plist.** Display name, supported orientations, permission usage
12
+ descriptions (from ``[permissions]``), background modes, URL schemes
13
+ (from ``[app].url_schemes``), and any ``[ios].extra_info_plist`` keys.
14
+ - **Entitlements.** A ``.entitlements`` file generated when a declared
15
+ capability needs one (e.g., ``remote_notifications``).
16
+ - **Branding.** The ``AppIcon`` asset and an optional ``Splash`` image
17
+ set plus a generated ``LaunchScreen`` storyboard.
18
+ - **Export options.** A plist for ``xcodebuild -exportArchive`` derived
19
+ from ``[ios.signing]``.
20
+
21
+ The embedded CPython runtime is *not* handled here: the bundled Xcode
22
+ template links ``Python.xcframework`` directly and installs the standard
23
+ library, app sources, and packages during the Xcode build (see the
24
+ "Install Python runtime" build phase). The
25
+ [`builder`][pythonnative.project.builder] stages the framework and the
26
+ Python sources into the project before invoking ``xcodebuild``.
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ import plistlib
32
+ from dataclasses import dataclass
33
+ from pathlib import Path
34
+ from typing import Callable, Dict, List, Optional
35
+
36
+ from . import icons
37
+ from .config import AppConfig
38
+
39
+ PROJECT_NAME = "ios_template"
40
+ """The fixed Xcode project/scheme/target name (kept stable on purpose)."""
41
+
42
+ PROJECT_FILE = "ios_template.xcodeproj"
43
+ """The ``.xcodeproj`` directory name within the staged template."""
44
+
45
+ APP_BUNDLE_NAME = "ios_template.app"
46
+ """The built ``.app`` bundle name (product name is left as the target name)."""
47
+
48
+ ENTITLEMENTS_FILE = "ios_template/ios_template.entitlements"
49
+ """Project-relative path of the generated entitlements file (when needed)."""
50
+
51
+ _ORIENTATIONS: Dict[str, List[str]] = {
52
+ "portrait": ["UIInterfaceOrientationPortrait"],
53
+ "landscape": [
54
+ "UIInterfaceOrientationLandscapeLeft",
55
+ "UIInterfaceOrientationLandscapeRight",
56
+ ],
57
+ "all": [
58
+ "UIInterfaceOrientationPortrait",
59
+ "UIInterfaceOrientationLandscapeLeft",
60
+ "UIInterfaceOrientationLandscapeRight",
61
+ ],
62
+ }
63
+
64
+ _EXPORT_METHODS = {
65
+ "development": "development",
66
+ "ad-hoc": "ad-hoc",
67
+ "app-store": "app-store",
68
+ "enterprise": "enterprise",
69
+ }
70
+
71
+ Logger = Callable[[str], None]
72
+
73
+
74
+ @dataclass
75
+ class IOSLayout:
76
+ """Resolved paths within a configured iOS project.
77
+
78
+ Attributes:
79
+ project_dir: The staged ``ios_template`` directory.
80
+ info_plist: Path to the app ``Info.plist``.
81
+ bundle_id: The resolved iOS bundle identifier.
82
+ """
83
+
84
+ project_dir: Path
85
+ info_plist: Path
86
+ bundle_id: str
87
+
88
+
89
+ def configure(project_dir: Path, config: AppConfig, *, log: Optional[Logger] = None) -> IOSLayout:
90
+ """Configure a staged iOS template for ``config``.
91
+
92
+ Args:
93
+ project_dir: The staged ``ios_template`` directory.
94
+ config: The validated app configuration.
95
+ log: Optional progress logger.
96
+
97
+ Returns:
98
+ An [`IOSLayout`][pythonnative.project.ios.IOSLayout].
99
+ """
100
+ emit: Logger = log or (lambda _message: None)
101
+ project_dir = Path(project_dir)
102
+ info_plist = project_dir / "ios_template" / "Info.plist"
103
+
104
+ configure_info_plist(info_plist, config)
105
+ write_entitlements(project_dir, config)
106
+ _apply_branding(project_dir, config, emit)
107
+
108
+ emit(f"Configured iOS project ({config.bundle_id}).")
109
+ return IOSLayout(project_dir=project_dir, info_plist=info_plist, bundle_id=config.bundle_id)
110
+
111
+
112
+ # ======================================================================
113
+ # Info.plist
114
+ # ======================================================================
115
+
116
+
117
+ def configure_info_plist(info_plist: Path, config: AppConfig) -> None:
118
+ """Write display name, orientation, permissions, and extras to the plist.
119
+
120
+ Args:
121
+ info_plist: Path to the app ``Info.plist``.
122
+ config: The validated app configuration.
123
+ """
124
+ with open(info_plist, "rb") as handle:
125
+ plist = plistlib.load(handle)
126
+
127
+ plist["CFBundleDisplayName"] = config.display_name
128
+ plist["CFBundleName"] = config.name
129
+ plist["PNEntryModule"] = config.entry_module
130
+
131
+ orientations = _ORIENTATIONS.get(config.orientation, _ORIENTATIONS["portrait"])
132
+ plist["UISupportedInterfaceOrientations"] = list(orientations)
133
+ plist["UISupportedInterfaceOrientations~ipad"] = list(orientations)
134
+
135
+ resolved = config.resolved_permissions()
136
+ for key, reason in resolved.ios_usage_descriptions.items():
137
+ plist[key] = reason
138
+ # Debug builds connect to `pn start` over the LAN, which iOS gates
139
+ # behind the local-network prompt; the prompt needs this string.
140
+ plist.setdefault(
141
+ "NSLocalNetworkUsageDescription",
142
+ "Development builds connect to the PythonNative dev server on your computer.",
143
+ )
144
+ if resolved.ios_background_modes:
145
+ plist["UIBackgroundModes"] = list(resolved.ios_background_modes)
146
+
147
+ if config.url_schemes:
148
+ plist["CFBundleURLTypes"] = [
149
+ {
150
+ "CFBundleURLName": config.bundle_id,
151
+ "CFBundleURLSchemes": list(config.url_schemes),
152
+ }
153
+ ]
154
+
155
+ if config.splash:
156
+ plist["UILaunchStoryboardName"] = "LaunchScreen"
157
+
158
+ for key, value in config.ios.extra_info_plist.items():
159
+ plist[key] = value
160
+
161
+ with open(info_plist, "wb") as handle:
162
+ plistlib.dump(plist, handle)
163
+
164
+
165
+ def write_entitlements(project_dir: Path, config: AppConfig) -> Optional[Path]:
166
+ """Generate the app entitlements file when a capability needs one.
167
+
168
+ Args:
169
+ project_dir: The staged ``ios_template`` directory.
170
+ config: The validated app configuration.
171
+
172
+ Returns:
173
+ The written entitlements path, or ``None`` when no declared
174
+ capability requires entitlements.
175
+ """
176
+ entitlements = config.resolved_permissions().ios_entitlements
177
+ if not entitlements:
178
+ return None
179
+ dest = project_dir / ENTITLEMENTS_FILE
180
+ dest.parent.mkdir(parents=True, exist_ok=True)
181
+ with open(dest, "wb") as handle:
182
+ plistlib.dump(dict(entitlements), handle)
183
+ return dest
184
+
185
+
186
+ # ======================================================================
187
+ # Build settings / export options
188
+ # ======================================================================
189
+
190
+
191
+ def build_settings(config: AppConfig, *, for_archive: bool = False) -> List[str]:
192
+ """Return ``KEY=VALUE`` ``xcodebuild`` overrides for this config.
193
+
194
+ Args:
195
+ config: The validated app configuration.
196
+ for_archive: When ``True``, include signing settings appropriate
197
+ for a device archive.
198
+
199
+ Returns:
200
+ A list of ``"SETTING=value"`` strings to append to an
201
+ ``xcodebuild`` invocation.
202
+ """
203
+ orientations = _ORIENTATIONS.get(config.orientation, _ORIENTATIONS["portrait"])
204
+ orientation_value = " ".join(orientations)
205
+ settings = [
206
+ f"PRODUCT_BUNDLE_IDENTIFIER={config.bundle_id}",
207
+ f"MARKETING_VERSION={config.version}",
208
+ f"CURRENT_PROJECT_VERSION={config.build}",
209
+ f"IPHONEOS_DEPLOYMENT_TARGET={config.ios.deployment_target}",
210
+ f"INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone={orientation_value}",
211
+ f"INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad={orientation_value}",
212
+ ]
213
+ if config.ios.development_team:
214
+ settings.append(f"DEVELOPMENT_TEAM={config.ios.development_team}")
215
+ if config.resolved_permissions().ios_entitlements:
216
+ settings.append(f"CODE_SIGN_ENTITLEMENTS={ENTITLEMENTS_FILE}")
217
+ if for_archive and not config.ios.signing.provisioning_profile:
218
+ settings.append("CODE_SIGN_STYLE=Automatic")
219
+ return settings
220
+
221
+
222
+ def write_export_options(config: AppConfig, dest: Path, *, upload: bool = False) -> Path:
223
+ """Write an ``exportOptions.plist`` for ``xcodebuild -exportArchive``.
224
+
225
+ Args:
226
+ config: The validated app configuration.
227
+ dest: Destination plist path.
228
+ upload: When ``True``, ask ``xcodebuild`` to upload the build to
229
+ App Store Connect instead of exporting a local ``.ipa``
230
+ (requires ``export_method = "app-store"``).
231
+
232
+ Returns:
233
+ ``dest``.
234
+ """
235
+ signing = config.ios.signing
236
+ options: Dict[str, object] = {
237
+ "method": _EXPORT_METHODS.get(signing.export_method, "development"),
238
+ "compileBitcode": False,
239
+ "stripSwiftSymbols": True,
240
+ }
241
+ if upload:
242
+ options["destination"] = "upload"
243
+ if config.ios.development_team:
244
+ options["teamID"] = config.ios.development_team
245
+ if signing.provisioning_profile:
246
+ options["signingStyle"] = "manual"
247
+ options["provisioningProfiles"] = {config.bundle_id: signing.provisioning_profile}
248
+ else:
249
+ options["signingStyle"] = "automatic"
250
+
251
+ dest.parent.mkdir(parents=True, exist_ok=True)
252
+ with open(dest, "wb") as handle:
253
+ plistlib.dump(options, handle)
254
+ return dest
255
+
256
+
257
+ # ======================================================================
258
+ # Branding
259
+ # ======================================================================
260
+
261
+
262
+ def _apply_branding(project_dir: Path, config: AppConfig, emit: Logger) -> None:
263
+ assets_dir = project_dir / "ios_template" / "Assets.xcassets"
264
+ icon_path = config.resolve_path(config.icon) if config.icon else None
265
+ splash_path = config.resolve_path(config.splash) if config.splash else None
266
+
267
+ if icon_path and icons.has_source(icon_path):
268
+ if icons.generate_ios_icons(icon_path, assets_dir / "AppIcon.appiconset"):
269
+ emit("Generated iOS app icon.")
270
+ else:
271
+ emit("Skipping iOS icon: Pillow not installed (pip install 'pythonnative[build]').")
272
+
273
+ if splash_path and icons.has_source(splash_path):
274
+ if icons.generate_ios_splash(splash_path, assets_dir / "Splash.imageset"):
275
+ _write_launch_storyboard(project_dir)
276
+ emit("Configured iOS splash screen.")
277
+ else:
278
+ emit("Skipping iOS splash: Pillow not installed (pip install 'pythonnative[build]').")
279
+
280
+
281
+ def _write_launch_storyboard(project_dir: Path) -> None:
282
+ """Overwrite ``LaunchScreen.storyboard`` with a centered splash image."""
283
+ storyboard = project_dir / "ios_template" / "Base.lproj" / "LaunchScreen.storyboard"
284
+ storyboard.write_text(_LAUNCH_STORYBOARD, encoding="utf-8")
285
+
286
+
287
+ # An edge-pinned image view (aspect-fit) over a white background. The
288
+ # image references the generated "Splash" asset set.
289
+ _LAUNCH_STORYBOARD = """<?xml version="1.0" encoding="UTF-8"?>
290
+ <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22155" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
291
+ <dependencies>
292
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22131"/>
293
+ <capability name="Safe area layout guides" minToolsVersion="9.0"/>
294
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
295
+ </dependencies>
296
+ <scenes>
297
+ <scene sceneID="EHf-IW-A2E">
298
+ <objects>
299
+ <viewController id="01J-lp-oVM" sceneMemberID="viewController">
300
+ <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
301
+ <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
302
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
303
+ <subviews>
304
+ <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="Splash" translatesAutoresizingMaskIntoConstraints="NO" id="Spl-aS-h00"/>
305
+ </subviews>
306
+ <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
307
+ <color key="backgroundColor" systemColor="systemBackgroundColor"/>
308
+ <constraints>
309
+ <constraint firstItem="Spl-aS-h00" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="lea-Sp-001"/>
310
+ <constraint firstItem="Spl-aS-h00" firstAttribute="trailing" secondItem="Ze5-6b-2t3" secondAttribute="trailing" id="tra-Sp-002"/>
311
+ <constraint firstItem="Spl-aS-h00" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="top-Sp-003"/>
312
+ <constraint firstItem="Spl-aS-h00" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="bot-Sp-004"/>
313
+ </constraints>
314
+ </view>
315
+ </viewController>
316
+ <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
317
+ </objects>
318
+ <point key="canvasLocation" x="53" y="375"/>
319
+ </scene>
320
+ </scenes>
321
+ <resources>
322
+ <image name="Splash" width="393" height="393"/>
323
+ </resources>
324
+ </document>
325
+ """
@@ -0,0 +1,100 @@
1
+ """Deterministic, hash-verified wheel locks for embedded Python targets."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import dataclasses
6
+ import json
7
+ import re
8
+ from pathlib import Path
9
+ from typing import Any, Sequence
10
+
11
+ from .config import AppConfig
12
+ from .deps import DependencyError, Resolution, Target
13
+
14
+ NAME = "pn.lock"
15
+
16
+
17
+ def target_key(target: Target) -> str:
18
+ """Identify every platform constraint that changes compatible wheels."""
19
+ return ":".join((target.platform, target.python_version, target.arch, target.sdk, target.os_version))
20
+
21
+
22
+ def write(config: AppConfig, resolutions: Sequence[Resolution]) -> Path:
23
+ """Record every selected wheel and its SHA-256 digest atomically."""
24
+ targets: dict[str, Any] = {}
25
+ for resolution in resolutions:
26
+ if not resolution.ok:
27
+ raise DependencyError(f"Cannot lock unsuccessful target: {resolution.target.label}")
28
+ packages = []
29
+ for package in resolution.packages:
30
+ if not re.fullmatch(r"[0-9a-f]{64}", package.sha256):
31
+ raise DependencyError(f"The index did not supply a SHA-256 digest for {package.filename}")
32
+ packages.append(
33
+ {
34
+ "name": package.name,
35
+ "version": package.version,
36
+ "filename": package.filename,
37
+ "url": package.url,
38
+ "sha256": package.sha256,
39
+ }
40
+ )
41
+ targets[target_key(resolution.target)] = {"target": dataclasses.asdict(resolution.target), "packages": packages}
42
+ path = config.project_root / NAME
43
+ try:
44
+ previous = read(config)
45
+ except DependencyError:
46
+ previous = None
47
+ if previous:
48
+ targets = previous["targets"] | targets
49
+ document = {
50
+ "version": 1,
51
+ "python": config.python_version,
52
+ "requirements": list(config.requirements),
53
+ "indexes": list(config.extra_index_urls),
54
+ "targets": targets,
55
+ }
56
+ temporary = path.with_suffix(".lock.tmp")
57
+ temporary.write_text(json.dumps(document, sort_keys=True, indent=2) + "\n", encoding="utf-8")
58
+ temporary.replace(path)
59
+ return path
60
+
61
+
62
+ def read(config: AppConfig) -> dict[str, Any] | None:
63
+ """Read a lock and reject stale requirements instead of silently resolving."""
64
+ path = config.project_root / NAME
65
+ if not path.exists():
66
+ return None
67
+ value = json.loads(path.read_text(encoding="utf-8"))
68
+ if (
69
+ value.get("version") != 1
70
+ or value.get("python") != config.python_version
71
+ or value.get("requirements") != list(config.requirements)
72
+ or value.get("indexes") != list(config.extra_index_urls)
73
+ ):
74
+ raise DependencyError("pn.lock doesn't match this app. Run 'pn deps --lock' to update it.")
75
+ return value
76
+
77
+
78
+ def requirements(config: AppConfig, targets: Sequence[Target], *, direct: bool = False) -> str | None:
79
+ """Build pip input containing exact versions and every allowed wheel hash."""
80
+ document = read(config)
81
+ if document is None:
82
+ return None
83
+ packages: dict[str, dict[str, Any]] = {}
84
+ for target in targets:
85
+ selected = document["targets"].get(target_key(target))
86
+ if selected is None:
87
+ raise DependencyError(f"pn.lock has no {target.label}. Run 'pn deps {target.platform} --lock'.")
88
+ for package in selected["packages"]:
89
+ key = re.sub(r"[-_.]+", "-", package["name"]).lower()
90
+ old = packages.setdefault(key, package | {"hashes": set()})
91
+ if old["version"] != package["version"]:
92
+ raise DependencyError(
93
+ f"{key} resolves to different versions across architectures; pin one compatible version."
94
+ )
95
+ old["hashes"].add(package["sha256"])
96
+ lines = ["--require-hashes"]
97
+ for name, package in sorted(packages.items()):
98
+ requirement = f"{name} @ {package['url']}" if direct else f"{name}=={package['version']}"
99
+ lines.append(requirement + " " + " ".join(f"--hash=sha256:{digest}" for digest in sorted(package["hashes"])))
100
+ return "\n".join(lines) + "\n"