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,184 @@
1
+ """Typed module facades and native dispatch adapters from Python protocols."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from .schema import MODULES
8
+
9
+
10
+ def _types(schema: dict[str, Any]) -> tuple[str, str, str]:
11
+ if "anyOf" in schema:
12
+ variants = [item for item in schema["anyOf"] if item.get("type") != "null"]
13
+ if len(variants) == 1:
14
+ python, swift, kotlin = _types(variants[0])
15
+ return python + " | None", swift + "?", kotlin + "?"
16
+ return {
17
+ "string": ("str", "String", "String"),
18
+ "integer": ("int", "Int", "Int"),
19
+ "number": ("float", "Double", "Double"),
20
+ "boolean": ("bool", "Bool", "Boolean"),
21
+ "null": ("None", "Void", "Unit"),
22
+ }.get(schema.get("type", ""), ("Any", "Any", "Any"))
23
+
24
+
25
+ def generate_modules() -> dict[str, str]:
26
+ """Generate native interfaces, checked dispatch, and typed Python calls."""
27
+ python = [
28
+ '"""Generated native module facades."""',
29
+ "from typing import Any",
30
+ "from pythonnative.native_modules.registry import native_module",
31
+ "",
32
+ ]
33
+ swift = ["import Foundation", ""]
34
+ kotlin = [
35
+ "package com.pythonnative.generated",
36
+ "",
37
+ "import org.json.JSONObject",
38
+ "import com.pythonnative.runtime.modules.NativeModule",
39
+ "import com.pythonnative.runtime.modules.Promise",
40
+ "",
41
+ ]
42
+ for name, module in sorted(MODULES.items()):
43
+ if not name.isidentifier():
44
+ raise ValueError(f"Invalid module name: {name!r}")
45
+ python.append(f"class {name}:")
46
+ swift.extend([f"public protocol {name}Implementation {{", " init()"])
47
+ kotlin.append(f"interface {name}Implementation {{")
48
+ method_info = []
49
+ for method, contract in module.methods.items():
50
+ if not method.isidentifier():
51
+ raise ValueError(f"Invalid method name: {method!r}")
52
+ result_py, result_swift, result_kotlin = _types(contract["result"])
53
+ params_py, params_swift, params_kotlin, args = [], [], [], []
54
+ for key, schema in contract["arguments"].items():
55
+ if not key.isidentifier():
56
+ raise ValueError(f"Invalid argument name: {key!r}")
57
+ pt, st, kt = _types(schema)
58
+ params_py.append(f"{key}: {pt}")
59
+ params_swift.append(f"{key}: {st}")
60
+ params_kotlin.append(f"{key}: {kt}")
61
+ args.append(key)
62
+ asynchronous = contract["async"]
63
+ python.extend(
64
+ [
65
+ " @staticmethod",
66
+ f" {'async ' if asynchronous else ''}def {method}("
67
+ + ", ".join(params_py)
68
+ + f") -> {result_py}:",
69
+ f' return {"await " if asynchronous else ""}native_module("{name}").'
70
+ f'{"call_async" if asynchronous else "call"}("{method}"'
71
+ + "".join(f", {key}={key}" for key in args)
72
+ + ")",
73
+ "",
74
+ ]
75
+ )
76
+ if asynchronous:
77
+ swift.append(
78
+ f" func {method}("
79
+ + ", ".join(params_swift + [f"completion: @escaping (Result<{result_swift}, Error>) -> Void"])
80
+ + ")"
81
+ )
82
+ kotlin.append(
83
+ f" fun {method}("
84
+ + ", ".join(params_kotlin + [f"completion: (Result<{result_kotlin}>) -> Unit"])
85
+ + ")"
86
+ )
87
+ else:
88
+ swift.append(f" func {method}(" + ", ".join(params_swift) + f") throws -> {result_swift}")
89
+ kotlin.append(f" fun {method}(" + ", ".join(params_kotlin) + f"): {result_kotlin}")
90
+ method_info.append((method, contract, args))
91
+ if not method_info:
92
+ python.append(" pass")
93
+ python.append("")
94
+ swift.extend(
95
+ [
96
+ "}",
97
+ "",
98
+ f"public final class {name}Module<Implementation: {name}Implementation>: PNNativeModule {{",
99
+ f' public static var name: String {{ "{name}" }}',
100
+ " let implementation: Implementation",
101
+ " public init() { implementation = Implementation() }",
102
+ " public func call(_ method: String, args: [String: Any], promise: PNPromise) {",
103
+ " do {",
104
+ " switch method {",
105
+ ]
106
+ )
107
+ kotlin.extend(
108
+ [
109
+ "}",
110
+ "",
111
+ f"class {name}Module(private val implementation: {name}Implementation): NativeModule {{",
112
+ f' override val name = "{name}"',
113
+ " override fun call(method: String, args: JSONObject, promise: Promise) {",
114
+ " try {",
115
+ " when (method) {",
116
+ ]
117
+ )
118
+ for method, contract, args in method_info:
119
+ swift.append(f' case "{method}":')
120
+ kotlin.append(f' "{method}" -> {{')
121
+ for key in args:
122
+ _, st, kt = _types(contract["arguments"][key])
123
+ if st.endswith("?"):
124
+ swift.append(f' let {key} = args["{key}"] as? {st[:-1]}')
125
+ else:
126
+ swift.append(
127
+ f' guard let {key} = args["{key}"] as? {st} else {{ '
128
+ f'promise.reject("Invalid {key}"); return }}'
129
+ )
130
+ accessor = {"String": "getString", "Int": "getInt", "Double": "getDouble", "Boolean": "getBoolean"}.get(
131
+ kt.rstrip("?"), "get"
132
+ )
133
+ expression = f'args.{accessor}("{key}")'
134
+ if kt.endswith("?"):
135
+ expression = f'if (args.isNull("{key}")) null else {expression}'
136
+ kotlin.append(f" val {key} = {expression}")
137
+ sc = f"implementation.{method}(" + ", ".join(f"{key}: {key}" for key in args)
138
+ kc = f"implementation.{method}(" + ", ".join(args)
139
+ void = contract["result"].get("type") == "null"
140
+ if contract["async"]:
141
+ swift.append(f" {sc}) {{ result in")
142
+ swift.append(
143
+ " switch result { case .success(let value): promise.resolve("
144
+ + ("nil" if void else "value")
145
+ + "); case .failure(let error): promise.reject(error) }"
146
+ )
147
+ swift.append(" }")
148
+ kotlin.append(
149
+ f" {kc}) {{ result -> result.fold({{ value -> promise.resolve("
150
+ + ("null" if void else "value")
151
+ + ') }, { error -> promise.reject(error.message ?: "Native call failed") }) }'
152
+ )
153
+ elif void:
154
+ swift.append(f" try {sc}); promise.resolve(nil)")
155
+ kotlin.append(f" {kc}); promise.resolve(null)")
156
+ else:
157
+ swift.append(f" promise.resolve(try {sc}))")
158
+ kotlin.append(f" promise.resolve({kc}))")
159
+ kotlin.append(" }")
160
+ swift.extend(
161
+ [
162
+ ' default: promise.reject("Unknown method", code: "unknown_method")',
163
+ " }",
164
+ " } catch { promise.reject(error) }",
165
+ " }",
166
+ "}",
167
+ "",
168
+ ]
169
+ )
170
+ kotlin.extend(
171
+ [
172
+ " else -> promise.rejectUnknownMethod(method)",
173
+ " }",
174
+ ' } catch (error: Exception) { promise.reject(error.message ?: "Native call failed") }',
175
+ " }",
176
+ "}",
177
+ "",
178
+ ]
179
+ )
180
+ return {
181
+ "modules.py": "\n".join(python),
182
+ "NativeModules.swift": "\n".join(swift),
183
+ "NativeModules.kt": "\n".join(kotlin),
184
+ }
@@ -0,0 +1,224 @@
1
+ """Python definitions for native props, events, commands, and modules."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import collections.abc
6
+ import dataclasses
7
+ import enum
8
+ import hashlib
9
+ import inspect
10
+ import json
11
+ import types
12
+ import typing
13
+ from dataclasses import dataclass, field
14
+ from typing import Any, Mapping
15
+
16
+
17
+ @dataclass(frozen=True)
18
+ class NativeField:
19
+ """Native behavior attached to an annotated dataclass field.
20
+
21
+ Use ``Annotated[T, NativeField(...)]`` for native-specific metadata.
22
+ """
23
+
24
+ invalidates_layout: bool = False
25
+ recreate: bool = False
26
+ animated: bool = False
27
+ platforms: tuple[str, ...] = ("ios", "android", "web")
28
+ description: str = ""
29
+
30
+
31
+ def type_schema(annotation: Any) -> dict[str, Any]:
32
+ """Convert a Python annotation into a portable JSON type description."""
33
+ origin, args = typing.get_origin(annotation), typing.get_args(annotation)
34
+ if origin is typing.Annotated:
35
+ result = type_schema(args[0])
36
+ for metadata in args[1:]:
37
+ if isinstance(metadata, NativeField):
38
+ result["native"] = dataclasses.asdict(metadata)
39
+ return result
40
+ if origin in (typing.Union, types.UnionType):
41
+ return {"anyOf": [type_schema(arg) for arg in args]}
42
+ if origin is typing.Literal:
43
+ return {"enum": list(args)}
44
+ if annotation is type(None):
45
+ return {"type": "null"}
46
+ if annotation in (str, bool, int, float):
47
+ return {"type": {str: "string", bool: "boolean", int: "integer", float: "number"}[annotation]}
48
+ if origin in (list, tuple, set, collections.abc.Sequence):
49
+ return {"type": "array", "items": type_schema(args[0]) if args else {}}
50
+ if origin in (dict, collections.abc.Mapping) or annotation is dict:
51
+ return {"type": "object", "additionalProperties": type_schema(args[-1]) if args else {}}
52
+ if origin in (typing.Callable, collections.abc.Callable):
53
+ return {
54
+ "type": "event",
55
+ "arguments": [type_schema(arg) for arg in args[0]] if args and args[0] is not Ellipsis else [],
56
+ }
57
+ if inspect.isclass(annotation) and issubclass(annotation, enum.Enum):
58
+ return {"enum": [value.value for value in annotation]}
59
+ if dataclasses.is_dataclass(annotation):
60
+ hints = typing.get_type_hints(annotation, include_extras=True)
61
+ return {"type": "object", "properties": {name: type_schema(value) for name, value in hints.items()}}
62
+ return {}
63
+
64
+
65
+ def validate(value: Any, schema: Mapping[str, Any], path: str = "value") -> None:
66
+ """Validate wire values without coercion or ambiguous boolean comparisons."""
67
+ if "anyOf" in schema:
68
+ for alternative in schema["anyOf"]:
69
+ try:
70
+ validate(value, alternative, path)
71
+ return
72
+ except TypeError:
73
+ pass
74
+ raise TypeError(f"{path} does not match its annotation")
75
+ if "enum" in schema:
76
+ candidate = value.value if isinstance(value, enum.Enum) else value
77
+ if candidate not in schema["enum"]:
78
+ raise TypeError(f"{path} must be one of {schema['enum']!r}")
79
+ kind = schema.get("type")
80
+ checks = {
81
+ "null": lambda: value is None,
82
+ "string": lambda: isinstance(value, str),
83
+ "boolean": lambda: type(value) is bool,
84
+ "integer": lambda: type(value) is int,
85
+ "number": lambda: type(value) in (int, float),
86
+ "array": lambda: isinstance(value, (list, tuple, set)),
87
+ "object": lambda: isinstance(value, Mapping) or dataclasses.is_dataclass(value),
88
+ "event": lambda: callable(value),
89
+ }
90
+ if kind in checks and not checks[kind]():
91
+ raise TypeError(f"{path} must be {kind}, received {type(value).__name__}")
92
+ if kind == "array":
93
+ for index, item in enumerate(value):
94
+ validate(item, schema.get("items", {}), f"{path}[{index}]")
95
+ if kind == "object":
96
+ values = dataclasses.asdict(value) if dataclasses.is_dataclass(value) and not isinstance(value, type) else value
97
+ for name, item in values.items():
98
+ validate(
99
+ item, schema.get("properties", {}).get(name, schema.get("additionalProperties", {})), f"{path}.{name}"
100
+ )
101
+
102
+
103
+ @dataclass(frozen=True)
104
+ class ComponentSchema:
105
+ """The portable contract shared by every renderer and the component SDK."""
106
+
107
+ name: str
108
+ props: dict[str, dict[str, Any]]
109
+ required: tuple[str, ...] = ()
110
+ defaults: dict[str, Any] = field(default_factory=dict)
111
+ measurement: str = "intrinsic"
112
+ commands: dict[str, Any] = field(default_factory=dict)
113
+
114
+ @classmethod
115
+ def from_dataclass(cls, name: str, props: type, *, measurement: str = "intrinsic") -> ComponentSchema:
116
+ """Describe a native widget with a frozen Python props dataclass."""
117
+ if not dataclasses.is_dataclass(props):
118
+ raise TypeError("Native props must be a dataclass")
119
+ hints = typing.get_type_hints(props, include_extras=True)
120
+ required, defaults = [], {}
121
+ for item in dataclasses.fields(props):
122
+ if item.default is not dataclasses.MISSING:
123
+ defaults[item.name] = item.default
124
+ elif item.default_factory is not dataclasses.MISSING:
125
+ defaults[item.name] = item.default_factory()
126
+ else:
127
+ required.append(item.name)
128
+ return cls(
129
+ name, {key: type_schema(value) for key, value in hints.items()}, tuple(required), defaults, measurement
130
+ )
131
+
132
+ def validate(self, props: Mapping[str, Any], *, partial: bool = False) -> None:
133
+ """Validate a construction or a partial update against this contract."""
134
+ if not partial:
135
+ missing = set(self.required) - props.keys()
136
+ if missing:
137
+ raise TypeError(f"{self.name} requires {', '.join(sorted(missing))}")
138
+ for key, value in props.items():
139
+ if key not in self.props:
140
+ raise TypeError(f"Unknown {self.name} prop {key!r}")
141
+ validate(value, self.props[key], f"{self.name}.{key}")
142
+
143
+
144
+ @dataclass(frozen=True)
145
+ class ModuleSchema:
146
+ """Typed native module methods, arguments, results, and async behavior."""
147
+
148
+ name: str
149
+ methods: dict[str, dict[str, Any]]
150
+
151
+ @classmethod
152
+ def from_protocol(cls, name: str, protocol: type) -> ModuleSchema:
153
+ """Read annotated methods from a Python protocol or interface class."""
154
+ methods = {}
155
+ for method_name, method in inspect.getmembers(protocol, inspect.isfunction):
156
+ if method_name.startswith("_"):
157
+ continue
158
+ hints = typing.get_type_hints(method, include_extras=True)
159
+ signature = inspect.signature(method)
160
+ methods[method_name] = {
161
+ "arguments": {key: type_schema(hints.get(key, Any)) for key in signature.parameters if key != "self"},
162
+ "result": type_schema(hints.get("return", Any)),
163
+ "async": inspect.iscoroutinefunction(method),
164
+ }
165
+ return cls(name, methods)
166
+
167
+
168
+ COMPONENTS: dict[str, ComponentSchema] = {}
169
+ MODULES: dict[str, ModuleSchema] = {}
170
+
171
+
172
+ def register_schema(schema: ComponentSchema | ModuleSchema) -> None:
173
+ """Register the contract used to generate and validate a native extension."""
174
+ if isinstance(schema, ComponentSchema):
175
+ COMPONENTS[schema.name] = schema
176
+ else:
177
+ MODULES[schema.name] = schema
178
+
179
+
180
+ def manifest() -> dict[str, Any]:
181
+ """Return deterministic native metadata for code generation and tooling."""
182
+ return {
183
+ "protocol": 2,
184
+ "yoga": "3.2.1",
185
+ "components": {name: dataclasses.asdict(value) for name, value in sorted(COMPONENTS.items())},
186
+ "modules": {name: dataclasses.asdict(value) for name, value in sorted(MODULES.items())},
187
+ }
188
+
189
+
190
+ def fingerprint() -> str:
191
+ """Hash the native contract; incompatible dev clients require rebuilding."""
192
+ return hashlib.sha256(json.dumps(manifest(), sort_keys=True, default=str).encode()).hexdigest()
193
+
194
+
195
+ def load_manifest(document: Mapping[str, Any]) -> None:
196
+ """Load declarative extension contracts without importing target binaries."""
197
+ if document.get("protocol") != 2 or document.get("yoga") != "3.2.1":
198
+ raise ValueError("Native contracts require protocol 2 and Yoga 3.2.1")
199
+ pending = []
200
+ for group, constructor, registered in (
201
+ ("components", ComponentSchema, COMPONENTS),
202
+ ("modules", ModuleSchema, MODULES),
203
+ ):
204
+ for name, value in document.get(group, {}).items():
205
+ if not name.isidentifier() or value.get("name") != name:
206
+ raise ValueError(f"Invalid native contract name: {name!r}")
207
+ schema = constructor(**value)
208
+ old = registered.get(name)
209
+ if old is not None and json.dumps(dataclasses.asdict(old), sort_keys=True, default=str) != json.dumps(
210
+ dataclasses.asdict(schema), sort_keys=True, default=str
211
+ ):
212
+ raise ValueError(f"Conflicting native contract: {name}")
213
+ pending.append(schema)
214
+ for schema in pending:
215
+ register_schema(schema)
216
+
217
+
218
+ def load_bundled_contracts() -> None:
219
+ """Install the exact contracts compiled into this embedded application."""
220
+ from importlib.resources import files
221
+
222
+ path = files("pythonnative").joinpath("_native_contracts.json")
223
+ if path.is_file():
224
+ load_manifest(json.loads(path.read_text(encoding="utf-8")))
@@ -0,0 +1,46 @@
1
+ package com.pythonnative.generated
2
+
3
+ import org.json.JSONArray
4
+ import org.json.JSONObject
5
+
6
+ /** Generated contract metadata shared by built-ins and extension managers. */
7
+ object PNContracts {
8
+ const val fingerprint = "{{fingerprint}}"
9
+ private val components = JSONObject(listOf({{specification}}).joinToString("")).getJSONObject("components")
10
+
11
+ fun validate(name: String, props: JSONObject, partial: Boolean = false): Boolean {
12
+ val schema = components.optJSONObject(name) ?: return true
13
+ val fields = schema.getJSONObject("props")
14
+ val required = schema.optJSONArray("required") ?: JSONArray()
15
+ if (!partial) for (i in 0 until required.length()) if (!props.has(required.getString(i))) return false
16
+ for (key in props.keys()) {
17
+ if (partial && props.isNull(key)) continue
18
+ val field = fields.optJSONObject(key) ?: continue
19
+ if (!matches(props.get(key), field)) return false
20
+ }
21
+ return true
22
+ }
23
+
24
+ fun invalidatesLayout(name: String, changed: JSONObject): Boolean {
25
+ val fields = components.optJSONObject(name)?.optJSONObject("props") ?: return true
26
+ return changed.keys().asSequence().any { fields.optJSONObject(it)?.optJSONObject("native")?.optBoolean("invalidates_layout", true) ?: true }
27
+ }
28
+
29
+ private fun matches(value: Any, schema: JSONObject): Boolean {
30
+ schema.optJSONArray("anyOf")?.let { alternatives ->
31
+ return (0 until alternatives.length()).any { matches(value, alternatives.getJSONObject(it)) }
32
+ }
33
+ schema.optJSONArray("enum")?.let { values -> return (0 until values.length()).any { values.get(it).toString() == value.toString() } }
34
+ return when (schema.optString("type")) {
35
+ "null" -> value == JSONObject.NULL
36
+ "string" -> value is String
37
+ "boolean" -> value is Boolean
38
+ "integer" -> value is Number && value.toDouble() == value.toLong().toDouble()
39
+ "number" -> value is Number && value.toDouble().isFinite()
40
+ "array" -> value is JSONArray && (0 until value.length()).all { matches(value.get(it), schema.optJSONObject("items") ?: JSONObject()) }
41
+ "object" -> value is JSONObject
42
+ "event" -> value is Boolean || value == JSONObject.NULL
43
+ else -> true
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,46 @@
1
+ import Foundation
2
+ import CoreFoundation
3
+
4
+ /// Generated contract metadata; validation is shared by built-ins and plugins.
5
+ public enum PNContracts {
6
+ public static let fingerprint = "{{fingerprint}}"
7
+ private static let specification = """
8
+ {{specification}}
9
+ """
10
+ private static let components = (try! JSONSerialization.jsonObject(with: Data(specification.utf8)) as! [String: Any])["components"] as! [String: [String: Any]]
11
+
12
+ public static func validate(_ name: String, _ props: [String: Any], partial: Bool = false) -> Bool {
13
+ guard let schema = components[name], let fields = schema["props"] as? [String: [String: Any]] else { return true }
14
+ if !partial {
15
+ for key in schema["required"] as? [String] ?? [] where props[key] == nil { return false }
16
+ }
17
+ for (key, value) in props {
18
+ if value is NSNull && partial { continue }
19
+ if let field = fields[key], !matches(value, field) { return false }
20
+ }
21
+ return true
22
+ }
23
+
24
+ public static func invalidatesLayout(_ name: String, _ changed: [String: Any]) -> Bool {
25
+ guard let fields = components[name]?["props"] as? [String: [String: Any]] else { return true }
26
+ return changed.keys.contains { ((fields[$0]?["native"] as? [String: Any])?["invalidates_layout"] as? Bool) ?? true }
27
+ }
28
+
29
+ private static func matches(_ value: Any, _ schema: [String: Any]) -> Bool {
30
+ if let alternatives = schema["anyOf"] as? [[String: Any]] { return alternatives.contains { matches(value, $0) } }
31
+ if let values = schema["enum"] as? [Any] { return values.contains { String(describing: $0) == String(describing: value) } }
32
+ switch schema["type"] as? String {
33
+ case "null": return value is NSNull
34
+ case "string": return value is String
35
+ case "boolean": return (value as? NSNumber).map { CFGetTypeID($0) == CFBooleanGetTypeID() } ?? false
36
+ case "integer": return (value as? NSNumber).map { CFGetTypeID($0) != CFBooleanGetTypeID() && $0.doubleValue.rounded() == $0.doubleValue } ?? false
37
+ case "number": return (value as? NSNumber).map { CFGetTypeID($0) != CFBooleanGetTypeID() && $0.doubleValue.isFinite } ?? false
38
+ case "array":
39
+ guard let array = value as? [Any] else { return false }
40
+ return array.allSatisfy { matches($0, schema["items"] as? [String: Any] ?? [:]) }
41
+ case "object": return value is [String: Any]
42
+ case "event": return value is Bool || value is NSNull
43
+ default: return true
44
+ }
45
+ }
46
+ }