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,266 @@
1
+ import AVFoundation
2
+ import Contacts
3
+ import CoreLocation
4
+ import LocalAuthentication
5
+ import Photos
6
+ import UIKit
7
+ import UserNotifications
8
+
9
+ /// `Permissions`: `check` (sync) and `request` (async).
10
+ ///
11
+ /// Permission names are the `[permissions]` keys from pythonnative.toml
12
+ /// (`camera`, `microphone`, `photo_library`, `location_when_in_use`,
13
+ /// `contacts`, `notifications`). The Python facade validates them before
14
+ /// the call reaches this module, so an unknown name here is a bug rather
15
+ /// than user input, and is rejected rather than answered.
16
+ public final class PermissionsModule: PNNativeModule {
17
+ public static let name = "Permissions"
18
+
19
+ /// Every accepted permission name, in the `[permissions]` vocabulary.
20
+ public static let names: Set<String> = [
21
+ "camera", "microphone", "photo_library", "location_when_in_use", "contacts", "notifications",
22
+ ]
23
+
24
+ private var locationRequester: PNLocationPermissionRequester?
25
+
26
+ public init() {}
27
+
28
+ public func call(_ method: String, args: [String: Any], promise: PNPromise) {
29
+ let permission = PNProps.string(args["permission"]) ?? ""
30
+ switch method {
31
+ case "check", "request":
32
+ guard PermissionsModule.names.contains(permission) else {
33
+ return promise.reject("unknown permission '\(permission)'", code: "bad_args")
34
+ }
35
+ if method == "check" {
36
+ check(permission) { promise.resolve($0) }
37
+ } else {
38
+ request(permission) { promise.resolve($0) }
39
+ }
40
+ default:
41
+ promise.reject("Permissions has no method '\(method)'", code: "unknown_method")
42
+ }
43
+ }
44
+
45
+ // MARK: - Check
46
+
47
+ private func check(_ permission: String, _ done: @escaping (String) -> Void) {
48
+ switch permission {
49
+ case "camera":
50
+ done(PermissionsModule.status(AVCaptureDevice.authorizationStatus(for: .video)))
51
+ case "microphone":
52
+ done(PermissionsModule.status(AVCaptureDevice.authorizationStatus(for: .audio)))
53
+ case "photo_library":
54
+ done(PermissionsModule.status(PHPhotoLibrary.pnReadWriteAuthorizationStatus()))
55
+ case "contacts":
56
+ done(PermissionsModule.status(CNContactStore.authorizationStatus(for: .contacts)))
57
+ case "location_when_in_use":
58
+ done(PermissionsModule.status(CLLocationManager().pnAuthorizationStatus))
59
+ case "notifications":
60
+ UNUserNotificationCenter.current().getNotificationSettings { settings in
61
+ let status: String
62
+ switch settings.authorizationStatus {
63
+ case .authorized, .provisional, .ephemeral: status = "granted"
64
+ case .denied: status = "blocked"
65
+ case .notDetermined: status = "undetermined"
66
+ @unknown default: status = "undetermined"
67
+ }
68
+ DispatchQueue.main.async { done(status) }
69
+ }
70
+ default:
71
+ done("undetermined")
72
+ }
73
+ }
74
+
75
+ // MARK: - Request
76
+
77
+ private func request(_ permission: String, _ done: @escaping (String) -> Void) {
78
+ let finish: (String) -> Void = { status in DispatchQueue.main.async { done(status) } }
79
+ switch permission {
80
+ case "camera":
81
+ AVCaptureDevice.requestAccess(for: .video) { finish($0 ? "granted" : "blocked") }
82
+ case "microphone":
83
+ AVCaptureDevice.requestAccess(for: .audio) { finish($0 ? "granted" : "blocked") }
84
+ case "photo_library":
85
+ PHPhotoLibrary.pnRequestReadWriteAuthorization { finish(PermissionsModule.status($0)) }
86
+ case "contacts":
87
+ CNContactStore().requestAccess(for: .contacts) { granted, _ in finish(granted ? "granted" : "blocked") }
88
+ case "notifications":
89
+ UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, _ in
90
+ finish(granted ? "granted" : "blocked")
91
+ }
92
+ case "location_when_in_use":
93
+ let requester = PNLocationPermissionRequester { [weak self] status in
94
+ self?.locationRequester = nil
95
+ finish(status)
96
+ }
97
+ locationRequester = requester
98
+ requester.start()
99
+ default:
100
+ done("undetermined")
101
+ }
102
+ }
103
+
104
+ // MARK: - Status mapping
105
+
106
+ static func status(_ s: AVAuthorizationStatus) -> String {
107
+ switch s {
108
+ case .authorized: return "granted"
109
+ case .denied: return "blocked"
110
+ case .restricted: return "blocked"
111
+ case .notDetermined: return "undetermined"
112
+ @unknown default: return "undetermined"
113
+ }
114
+ }
115
+
116
+ static func status(_ s: PHAuthorizationStatus) -> String {
117
+ switch s {
118
+ case .authorized, .limited: return "granted"
119
+ case .denied, .restricted: return "blocked"
120
+ case .notDetermined: return "undetermined"
121
+ @unknown default: return "undetermined"
122
+ }
123
+ }
124
+
125
+ static func status(_ s: CNAuthorizationStatus) -> String {
126
+ switch s {
127
+ case .authorized: return "granted"
128
+ case .denied, .restricted: return "blocked"
129
+ case .notDetermined: return "undetermined"
130
+ // `.limited` (iOS 18) and future cases still permit access.
131
+ default: return "granted"
132
+ }
133
+ }
134
+
135
+ static func status(_ s: CLAuthorizationStatus) -> String {
136
+ switch s {
137
+ case .authorizedAlways, .authorizedWhenInUse: return "granted"
138
+ case .denied, .restricted: return "blocked"
139
+ case .notDetermined: return "undetermined"
140
+ @unknown default: return "undetermined"
141
+ }
142
+ }
143
+ }
144
+
145
+ /// One-shot when-in-use authorization request.
146
+ final class PNLocationPermissionRequester: NSObject, CLLocationManagerDelegate {
147
+ private let manager = CLLocationManager()
148
+ private let done: (String) -> Void
149
+ private var finished = false
150
+
151
+ init(done: @escaping (String) -> Void) {
152
+ self.done = done
153
+ super.init()
154
+ manager.delegate = self
155
+ }
156
+
157
+ func start() {
158
+ let current = manager.pnAuthorizationStatus
159
+ if current != .notDetermined {
160
+ finish(PermissionsModule.status(current))
161
+ return
162
+ }
163
+ manager.requestWhenInUseAuthorization()
164
+ }
165
+
166
+ func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
167
+ let status = manager.pnAuthorizationStatus
168
+ if status != .notDetermined {
169
+ finish(PermissionsModule.status(status))
170
+ }
171
+ }
172
+
173
+ private func finish(_ status: String) {
174
+ if finished { return }
175
+ finished = true
176
+ done(status)
177
+ }
178
+ }
179
+
180
+ /// `Notifications`: local notifications plus APNs registration.
181
+ public final class NotificationsModule: PNNativeModule {
182
+ public static let name = "Notifications"
183
+
184
+ private static var tokenWaiters: [PNPromise] = []
185
+
186
+ public init() {}
187
+
188
+ public func call(_ method: String, args: [String: Any], promise: PNPromise) {
189
+ let center = UNUserNotificationCenter.current()
190
+ switch method {
191
+ case "request_permission":
192
+ center.requestAuthorization(options: [.alert, .badge, .sound]) { granted, _ in
193
+ DispatchQueue.main.async { promise.resolve(granted) }
194
+ }
195
+ case "schedule":
196
+ let content = UNMutableNotificationContent()
197
+ content.title = PNProps.string(args["title"]) ?? ""
198
+ content.body = PNProps.string(args["body"]) ?? ""
199
+ if PNProps.bool(args["sound"]) != false { content.sound = .default }
200
+ if let badge = PNProps.int(args["badge"]) { content.badge = NSNumber(value: badge) }
201
+ let delay = max(0.1, PNProps.double(args["delay_seconds"]) ?? 0)
202
+ let trigger = UNTimeIntervalNotificationTrigger(timeInterval: delay, repeats: false)
203
+ let identifier = PNProps.string(args["identifier"]) ?? "default"
204
+ center.add(UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)) { error in
205
+ DispatchQueue.main.async {
206
+ if let error = error {
207
+ PNLog.modules.error("schedule failed: \(error.localizedDescription)")
208
+ }
209
+ promise.resolve(error == nil)
210
+ }
211
+ }
212
+ case "cancel":
213
+ let identifier = PNProps.string(args["identifier"]) ?? "default"
214
+ center.removePendingNotificationRequests(withIdentifiers: [identifier])
215
+ center.removeDeliveredNotifications(withIdentifiers: [identifier])
216
+ promise.resolve(nil)
217
+ case "get_device_token":
218
+ NotificationsModule.tokenWaiters.append(promise)
219
+ UIApplication.shared.registerForRemoteNotifications()
220
+ default:
221
+ promise.reject("Notifications has no method '\(method)'", code: "unknown_method")
222
+ }
223
+ }
224
+
225
+ /// Called by the app delegate with the APNs token.
226
+ public static func deliverToken(_ token: Data) {
227
+ let hex = token.map { String(format: "%02x", $0) }.joined()
228
+ let waiters = tokenWaiters
229
+ tokenWaiters = []
230
+ for waiter in waiters { waiter.resolve(hex) }
231
+ }
232
+
233
+ /// Called by the app delegate when APNs registration fails.
234
+ public static func deliverError(_ error: Error) {
235
+ let waiters = tokenWaiters
236
+ tokenWaiters = []
237
+ for waiter in waiters { waiter.reject(String(describing: error), code: "apns") }
238
+ }
239
+ }
240
+
241
+ /// `Biometrics`: `LAContext` availability and authentication.
242
+ public final class BiometricsModule: PNNativeModule {
243
+ public static let name = "Biometrics"
244
+
245
+ public init() {}
246
+
247
+ public func call(_ method: String, args: [String: Any], promise: PNPromise) {
248
+ switch method {
249
+ case "is_available":
250
+ let context = LAContext()
251
+ var error: NSError?
252
+ promise.resolve(context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error))
253
+ case "authenticate":
254
+ let context = LAContext()
255
+ let reason = PNProps.string(args["reason"]) ?? "Authenticate"
256
+ var error: NSError?
257
+ let policy: LAPolicy = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
258
+ ? .deviceOwnerAuthenticationWithBiometrics : .deviceOwnerAuthentication
259
+ context.evaluatePolicy(policy, localizedReason: reason) { success, _ in
260
+ DispatchQueue.main.async { promise.resolve(success) }
261
+ }
262
+ default:
263
+ promise.reject("Biometrics has no method '\(method)'", code: "unknown_method")
264
+ }
265
+ }
266
+ }
@@ -0,0 +1,251 @@
1
+ import AudioToolbox
2
+ import Security
3
+ import UIKit
4
+
5
+ /// `Device`: static device and app-path information.
6
+ public final class DeviceModule: PNNativeModule {
7
+ public static let name = "Device"
8
+
9
+ public init() {}
10
+
11
+ public func call(_ method: String, args: [String: Any], promise: PNPromise) {
12
+ switch method {
13
+ case "info":
14
+ promise.resolve(DeviceModule.info())
15
+ default:
16
+ promise.reject("Device has no method '\(method)'", code: "unknown_method")
17
+ }
18
+ }
19
+
20
+ /// The `Device.info()` payload.
21
+ public static func info() -> [String: Any] {
22
+ let paths = FileManager.default
23
+ let documents = paths.urls(for: .documentDirectory, in: .userDomainMask).first?.path ?? NSHomeDirectory() + "/Documents"
24
+ let caches = paths.urls(for: .cachesDirectory, in: .userDomainMask).first?.path ?? NSTemporaryDirectory()
25
+ return [
26
+ "os": "ios",
27
+ "os_version": UIDevice.current.systemVersion,
28
+ "model": UIDevice.current.model,
29
+ "name": UIDevice.current.name,
30
+ "app_dir": documents,
31
+ "cache_dir": caches,
32
+ "locale": Locale.current.identifier,
33
+ "scale": Double(PNWindow.screenScale()),
34
+ "is_simulator": DeviceModule.isSimulator,
35
+ ]
36
+ }
37
+
38
+ static var isSimulator: Bool {
39
+ #if targetEnvironment(simulator)
40
+ return true
41
+ #else
42
+ return false
43
+ #endif
44
+ }
45
+ }
46
+
47
+ /// `Storage`: `AsyncStorage` over the `pn_async_storage` defaults suite.
48
+ public final class StorageModule: PNNativeModule {
49
+ public static let name = "Storage"
50
+ static let suiteName = "pn_async_storage"
51
+
52
+ private let defaults: UserDefaults
53
+
54
+ public init() {
55
+ defaults = UserDefaults(suiteName: StorageModule.suiteName) ?? .standard
56
+ }
57
+
58
+ public func call(_ method: String, args: [String: Any], promise: PNPromise) {
59
+ switch method {
60
+ case "get":
61
+ guard let key = PNProps.string(args["key"]) else { return promise.reject("missing key", code: "bad_args") }
62
+ promise.resolve(defaults.string(forKey: key))
63
+ case "set":
64
+ guard let key = PNProps.string(args["key"]) else { return promise.reject("missing key", code: "bad_args") }
65
+ defaults.set(PNProps.string(args["value"]) ?? "", forKey: key)
66
+ promise.resolve(nil)
67
+ case "delete":
68
+ guard let key = PNProps.string(args["key"]) else { return promise.reject("missing key", code: "bad_args") }
69
+ defaults.removeObject(forKey: key)
70
+ promise.resolve(nil)
71
+ case "all_keys":
72
+ let keys: [String] = defaults.persistentDomain(forName: StorageModule.suiteName)?.keys.map { $0 } ?? []
73
+ promise.resolve(keys.sorted())
74
+ case "clear":
75
+ defaults.removePersistentDomain(forName: StorageModule.suiteName)
76
+ promise.resolve(nil)
77
+ default:
78
+ promise.reject("Storage has no method '\(method)'", code: "unknown_method")
79
+ }
80
+ }
81
+ }
82
+
83
+ /// `SecureStore`: Keychain generic passwords under one service.
84
+ public final class SecureStoreModule: PNNativeModule {
85
+ public static let name = "SecureStore"
86
+ static let service = "com.pythonnative.securestore"
87
+
88
+ public init() {}
89
+
90
+ public func call(_ method: String, args: [String: Any], promise: PNPromise) {
91
+ guard let key = PNProps.string(args["key"]) else {
92
+ promise.reject("missing key", code: "bad_args")
93
+ return
94
+ }
95
+ switch method {
96
+ case "set_item":
97
+ promise.resolve(SecureStoreModule.set(key, PNProps.string(args["value"]) ?? ""))
98
+ case "get_item":
99
+ promise.resolve(SecureStoreModule.get(key))
100
+ case "delete_item":
101
+ promise.resolve(SecureStoreModule.delete(key))
102
+ default:
103
+ promise.reject("SecureStore has no method '\(method)'", code: "unknown_method")
104
+ }
105
+ }
106
+
107
+ private static func query(_ key: String) -> [String: Any] {
108
+ [
109
+ kSecClass as String: kSecClassGenericPassword,
110
+ kSecAttrService as String: service,
111
+ kSecAttrAccount as String: key,
112
+ ]
113
+ }
114
+
115
+ static func set(_ key: String, _ value: String) -> Bool {
116
+ let data = Data(value.utf8)
117
+ var q = query(key)
118
+ let status = SecItemCopyMatching(q as CFDictionary, nil)
119
+ if status == errSecSuccess {
120
+ return SecItemUpdate(q as CFDictionary, [kSecValueData as String: data] as CFDictionary) == errSecSuccess
121
+ }
122
+ q[kSecValueData as String] = data
123
+ q[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock
124
+ return SecItemAdd(q as CFDictionary, nil) == errSecSuccess
125
+ }
126
+
127
+ static func get(_ key: String) -> String? {
128
+ var q = query(key)
129
+ q[kSecReturnData as String] = true
130
+ q[kSecMatchLimit as String] = kSecMatchLimitOne
131
+ var result: CFTypeRef?
132
+ guard SecItemCopyMatching(q as CFDictionary, &result) == errSecSuccess, let data = result as? Data else { return nil }
133
+ return String(data: data, encoding: .utf8)
134
+ }
135
+
136
+ static func delete(_ key: String) -> Bool {
137
+ SecItemDelete(query(key) as CFDictionary) == errSecSuccess
138
+ }
139
+ }
140
+
141
+ /// `Clipboard`: the general pasteboard.
142
+ public final class ClipboardModule: PNNativeModule {
143
+ public static let name = "Clipboard"
144
+
145
+ public init() {}
146
+
147
+ public func call(_ method: String, args: [String: Any], promise: PNPromise) {
148
+ switch method {
149
+ case "set_string":
150
+ UIPasteboard.general.string = PNProps.string(args["text"]) ?? ""
151
+ promise.resolve(nil)
152
+ case "get_string":
153
+ promise.resolve(UIPasteboard.general.string ?? "")
154
+ default:
155
+ promise.reject("Clipboard has no method '\(method)'", code: "unknown_method")
156
+ }
157
+ }
158
+ }
159
+
160
+ /// `Share`: `UIActivityViewController`, resolving whether a share completed.
161
+ public final class ShareModule: PNNativeModule {
162
+ public static let name = "Share"
163
+
164
+ public init() {}
165
+
166
+ public func call(_ method: String, args: [String: Any], promise: PNPromise) {
167
+ guard method == "share" else {
168
+ promise.reject("Share has no method '\(method)'", code: "unknown_method")
169
+ return
170
+ }
171
+ var items: [Any] = []
172
+ if let message = PNProps.string(args["message"]), !message.isEmpty { items.append(message) }
173
+ if let url = PNProps.string(args["url"]).flatMap({ URL(string: $0) }) { items.append(url) }
174
+ guard !items.isEmpty, let top = PNWindow.topViewController() else {
175
+ promise.resolve(false)
176
+ return
177
+ }
178
+ let controller = UIActivityViewController(activityItems: items, applicationActivities: nil)
179
+ if let title = PNProps.string(args["title"]) {
180
+ controller.setValue(title, forKey: "subject")
181
+ }
182
+ controller.completionWithItemsHandler = { _, completed, _, _ in
183
+ promise.resolve(completed)
184
+ }
185
+ if let popover = controller.popoverPresentationController {
186
+ popover.sourceView = top.view
187
+ popover.sourceRect = CGRect(x: top.view.bounds.midX, y: top.view.bounds.midY, width: 1, height: 1)
188
+ popover.permittedArrowDirections = []
189
+ }
190
+ top.present(controller, animated: true)
191
+ }
192
+ }
193
+
194
+ /// `Haptics`: feedback generators plus the legacy vibration sound.
195
+ public final class HapticsModule: PNNativeModule {
196
+ public static let name = "Haptics"
197
+
198
+ public init() {}
199
+
200
+ public func call(_ method: String, args: [String: Any], promise: PNPromise) {
201
+ switch method {
202
+ case "impact":
203
+ let generator = UIImpactFeedbackGenerator(style: HapticsModule.impactStyle(PNProps.string(args["style"])))
204
+ generator.prepare()
205
+ generator.impactOccurred()
206
+ promise.resolve(nil)
207
+ case "notification":
208
+ let generator = UINotificationFeedbackGenerator()
209
+ generator.prepare()
210
+ generator.notificationOccurred(HapticsModule.notificationType(PNProps.string(args["type"])))
211
+ promise.resolve(nil)
212
+ case "selection":
213
+ let generator = UISelectionFeedbackGenerator()
214
+ generator.prepare()
215
+ generator.selectionChanged()
216
+ promise.resolve(nil)
217
+ case "vibrate":
218
+ let duration = PNProps.int(args["duration_ms"]) ?? 400
219
+ if duration <= 100 {
220
+ let generator = UIImpactFeedbackGenerator(style: .heavy)
221
+ generator.prepare()
222
+ generator.impactOccurred()
223
+ } else {
224
+ AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
225
+ }
226
+ promise.resolve(nil)
227
+ case "cancel":
228
+ promise.resolve(nil)
229
+ default:
230
+ promise.reject("Haptics has no method '\(method)'", code: "unknown_method")
231
+ }
232
+ }
233
+
234
+ static func impactStyle(_ name: String?) -> UIImpactFeedbackGenerator.FeedbackStyle {
235
+ switch name {
236
+ case "light": return .light
237
+ case "heavy": return .heavy
238
+ case "soft": return .soft
239
+ case "rigid": return .rigid
240
+ default: return .medium
241
+ }
242
+ }
243
+
244
+ static func notificationType(_ name: String?) -> UINotificationFeedbackGenerator.FeedbackType {
245
+ switch name {
246
+ case "warning": return .warning
247
+ case "error": return .error
248
+ default: return .success
249
+ }
250
+ }
251
+ }
@@ -0,0 +1,8 @@
1
+ // Generated by `pn build`. Do not edit: the PythonNative build tool
2
+ // overwrites this file with one `register(into:)` call per bundled plugin.
3
+
4
+ /// Registration hook for plugins copied into `Sources/Plugins` by `pn build`.
5
+ public enum PNGeneratedPlugins {
6
+ /// Register every generated plugin into `registry`.
7
+ public static func registerAll(into registry: PNRegistry) {}
8
+ }
@@ -0,0 +1,46 @@
1
+ import UIKit
2
+
3
+ /// Screen id <-> `PNViewController` table.
4
+ ///
5
+ /// Python addresses screens by the integer id assigned here; the
6
+ /// controller is held weakly so a popped screen is reclaimed normally.
7
+ public final class PNScreenRegistry {
8
+ public static let shared = PNScreenRegistry()
9
+
10
+ private final class WeakBox {
11
+ weak var controller: PNViewController?
12
+ init(_ controller: PNViewController) { self.controller = controller }
13
+ }
14
+
15
+ private var screens: [Int64: WeakBox] = [:]
16
+ private var nextId: Int64 = 1
17
+
18
+ private init() {}
19
+
20
+ /// Assign a fresh id to `controller`.
21
+ func register(_ controller: PNViewController) -> Int64 {
22
+ let id = nextId
23
+ nextId += 1
24
+ screens[id] = WeakBox(controller)
25
+ return id
26
+ }
27
+
28
+ /// Forget `id` (called from the controller's deinit).
29
+ func unregister(_ id: Int64) {
30
+ screens.removeValue(forKey: id)
31
+ }
32
+
33
+ /// The controller for `id`, if it's still alive.
34
+ public func controller(for id: Int64) -> PNViewController? {
35
+ guard let box = screens[id] else { return nil }
36
+ if box.controller == nil {
37
+ screens.removeValue(forKey: id)
38
+ }
39
+ return box.controller
40
+ }
41
+
42
+ /// Ids of every live screen.
43
+ public var screenIds: [Int64] {
44
+ screens.compactMap { $0.value.controller == nil ? nil : $0.key }.sorted()
45
+ }
46
+ }