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,427 @@
1
+ """Custom native-component registration.
2
+
3
+ Implements the [`@native_component`][pythonnative.sdk.native_component]
4
+ decorator and supporting helpers that let third-party packages contribute
5
+ new element types to the reconciler.
6
+
7
+ On device a custom component is rendered by a Swift
8
+ ``PNComponentManager`` and a Kotlin ``ComponentManager`` registered
9
+ under the same type name by the package's native plugin (see
10
+ ``docs/guides/custom-components.md``). The Python side only needs to
11
+ know the element name and, optionally, its typed props and a
12
+ [`ViewHandler`][pythonnative.sdk.ViewHandler] that renders a stand-in
13
+ in unit tests (the browser preview draws unknown types as labeled
14
+ placeholders). Registration is therefore a three-part agreement:
15
+
16
+ 1. A typed, immutable [`Props`][pythonnative.sdk.Props] dataclass
17
+ declaring the component's public surface.
18
+ 2. An element factory built with
19
+ [`element_factory`][pythonnative.sdk.element_factory].
20
+ 3. Optionally, a test [`ViewHandler`][pythonnative.sdk.ViewHandler]
21
+ so the component also renders under the Python test backend.
22
+
23
+ The registry is process-wide. The view backend calls
24
+ [`install_into_registry`][pythonnative.sdk.install_into_registry] on
25
+ first use; that helper performs entry-point discovery (importing any
26
+ modules registered under
27
+ [`ENTRY_POINT_GROUP`][pythonnative.sdk.ENTRY_POINT_GROUP]) and copies
28
+ every test handler into the registry.
29
+
30
+ Example:
31
+ ```python
32
+ from dataclasses import dataclass
33
+ import pythonnative as pn
34
+ from pythonnative.sdk import Props, ViewHandler, element_factory, native_component
35
+
36
+
37
+ @dataclass(frozen=True)
38
+ class BadgeProps(Props):
39
+ text: str = ""
40
+ color: str = "#FF3B30"
41
+ style: pn.StyleProp = None
42
+
43
+
44
+ @native_component("Badge", props=BadgeProps)
45
+ class BadgePreviewHandler(ViewHandler):
46
+ def create(self, tag, props):
47
+ ... # stand-in used by the Python test backend
48
+
49
+ def update(self, view, changed):
50
+ ...
51
+
52
+
53
+ Badge = element_factory("Badge")
54
+ ```
55
+ """
56
+
57
+ from dataclasses import dataclass, fields, is_dataclass
58
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Type, TypeVar
59
+
60
+ from ..element import Element
61
+ from ..native_views.base import ViewHandler
62
+
63
+ ENTRY_POINT_GROUP = "pythonnative.handlers"
64
+ """Entry-point group used by PyPI packages to register native handlers.
65
+
66
+ Packages declare entries like:
67
+
68
+ ```toml
69
+ [project.entry-points."pythonnative.handlers"]
70
+ my_blur = "my_pkg.blur:register"
71
+ ```
72
+
73
+ PythonNative imports the referenced module the first time the
74
+ [`NativeViewRegistry`][pythonnative.native_views.NativeViewRegistry] is
75
+ materialized; the decorators inside that module populate the registry
76
+ during import.
77
+ """
78
+
79
+
80
+ @dataclass(frozen=True)
81
+ class Props:
82
+ """Optional base class for typed prop dataclasses.
83
+
84
+ Subclassing is not strictly required (any
85
+ ``@dataclass(frozen=True)`` works), but inheriting from
86
+ ``Props`` gives third-party components a clear, searchable marker
87
+ in their public API and a stable place to add framework-wide
88
+ behavior in the future.
89
+
90
+ Example:
91
+ ```python
92
+ from dataclasses import dataclass
93
+ from pythonnative.sdk import Props
94
+
95
+ @dataclass(frozen=True)
96
+ class BadgeProps(Props):
97
+ text: str = ""
98
+ color: str = "#FF3B30"
99
+ ```
100
+ """
101
+
102
+
103
+ # ---------------------------------------------------------------------- #
104
+ # Internal registry
105
+ # ---------------------------------------------------------------------- #
106
+
107
+ # name -> (props_type or None, test handler or None)
108
+ _REGISTRY: Dict[str, Tuple[Optional[type], Optional[ViewHandler]]] = {}
109
+
110
+ # Caches `_install_into_registry` runs to avoid repeated entry-point
111
+ # discovery once the registry has been populated for a given platform.
112
+ _DISCOVERED: bool = False
113
+
114
+
115
+ H = TypeVar("H", bound=ViewHandler)
116
+
117
+
118
+ def native_component(
119
+ name: str,
120
+ *,
121
+ props: Optional[type] = None,
122
+ ) -> Callable[[Type[H]], Type[H]]:
123
+ """Decorator that registers a test [`ViewHandler`][pythonnative.sdk.ViewHandler] under ``name``.
124
+
125
+ The handler class is instantiated immediately and stored in the
126
+ process-wide registry as the component's off-device renderer. The
127
+ on-device renderers are the Swift and Kotlin component managers the
128
+ package's native plugin registers under the same ``name``.
129
+
130
+ Args:
131
+ name: Element type name (e.g., ``"Badge"``). Used by the
132
+ reconciler and by native component managers at lookup time.
133
+ props: Optional dataclass type describing the component's
134
+ typed props. When supplied, the
135
+ [`element_factory`][pythonnative.sdk.element_factory] helper
136
+ uses this type to validate kwargs and produce frozen prop
137
+ instances.
138
+
139
+ Returns:
140
+ A decorator that, when applied to a
141
+ [`ViewHandler`][pythonnative.sdk.ViewHandler] subclass, registers
142
+ it and returns the class unchanged.
143
+
144
+ Raises:
145
+ TypeError: If the decorated object is not a class subclassing
146
+ ``ViewHandler``.
147
+ """
148
+
149
+ def decorator(handler_cls: Type[H]) -> Type[H]:
150
+ if not isinstance(handler_cls, type) or not issubclass(handler_cls, ViewHandler):
151
+ raise TypeError(f"@native_component({name!r}) must decorate a ViewHandler subclass; got {handler_cls!r}")
152
+ register_component(name=name, props=props, handler=handler_cls())
153
+ return handler_cls
154
+
155
+ return decorator
156
+
157
+
158
+ def register_component(
159
+ *,
160
+ name: str,
161
+ props: Optional[type] = None,
162
+ handler: Optional[ViewHandler] = None,
163
+ ) -> None:
164
+ """Register a custom native component imperatively.
165
+
166
+ Declares ``name`` as an element type so
167
+ [`element_factory`][pythonnative.sdk.element_factory] can build it.
168
+ ``handler`` is the optional test renderer; native
169
+ rendering always comes from the platform component managers.
170
+ Subsequent calls for the same ``name`` merge: a later ``props`` or
171
+ ``handler`` replaces the earlier one, ``None`` leaves it alone.
172
+
173
+ Args:
174
+ name: Element type name.
175
+ props: Optional dataclass type describing the typed props.
176
+ handler: Optional [`ViewHandler`][pythonnative.sdk.ViewHandler]
177
+ instance used off device.
178
+
179
+ Raises:
180
+ TypeError: If ``handler`` is not a ``ViewHandler`` instance, or
181
+ if ``props`` is not a dataclass type.
182
+ """
183
+ if props is not None and not (isinstance(props, type) and is_dataclass(props)):
184
+ raise TypeError(f"register_component({name!r}): props must be a @dataclass type, got {props!r}")
185
+ if handler is not None and not isinstance(handler, ViewHandler):
186
+ raise TypeError(f"register_component({name!r}): handler must be a ViewHandler instance")
187
+
188
+ if props is not None:
189
+ from .schema import ComponentSchema, register_schema
190
+
191
+ register_schema(ComponentSchema.from_dataclass(name, props))
192
+ existing = _REGISTRY.get(name)
193
+ if existing is None:
194
+ _REGISTRY[name] = (props, handler)
195
+ return
196
+ existing_props, existing_handler = existing
197
+ _REGISTRY[name] = (
198
+ props if props is not None else existing_props,
199
+ handler if handler is not None else existing_handler,
200
+ )
201
+
202
+
203
+ def unregister_component(name: str) -> None:
204
+ """Remove a previously-registered component (primarily for tests).
205
+
206
+ Args:
207
+ name: The element type name to unregister.
208
+ """
209
+ _REGISTRY.pop(name, None)
210
+ from .schema import COMPONENTS
211
+
212
+ COMPONENTS.pop(name, None)
213
+
214
+
215
+ def list_components() -> List[str]:
216
+ """Return the names of every registered custom component.
217
+
218
+ Useful for diagnostics and tests.
219
+
220
+ Returns:
221
+ Sorted list of names registered via
222
+ [`@native_component`][pythonnative.sdk.native_component] or
223
+ [`register_component`][pythonnative.sdk.register_component].
224
+ """
225
+ return sorted(_REGISTRY)
226
+
227
+
228
+ def get_props_type(name: str) -> Optional[type]:
229
+ """Return the registered props dataclass for ``name`` (or ``None``)."""
230
+ entry = _REGISTRY.get(name)
231
+ return entry[0] if entry is not None else None
232
+
233
+
234
+ def get_test_handler(name: str) -> Optional[ViewHandler]:
235
+ """Return the registered off-device handler for ``name`` (or ``None``)."""
236
+ entry = _REGISTRY.get(name)
237
+ return entry[1] if entry is not None else None
238
+
239
+
240
+ def install_into_registry(registry: Any) -> None:
241
+ """Copy registered test handlers into a view registry.
242
+
243
+ Called once by the registry on first use. Triggers entry-point
244
+ discovery on the first call so PyPI-installed components register
245
+ themselves before the registry snapshot is taken.
246
+
247
+ Args:
248
+ registry: A
249
+ [`NativeViewRegistry`][pythonnative.native_views.NativeViewRegistry]
250
+ (or duck-compatible object) with a ``register(name, handler)``
251
+ method.
252
+ """
253
+ _discover_entry_points()
254
+ for name, (_props_type, handler) in _REGISTRY.items():
255
+ if handler is not None:
256
+ registry.register(name, handler)
257
+
258
+
259
+ def _discover_entry_points() -> None:
260
+ """Import every module registered under ``ENTRY_POINT_GROUP``.
261
+
262
+ Idempotent and safe to call repeatedly; the actual discovery only
263
+ runs once per process. Exceptions raised by individual entry points
264
+ are swallowed (with the offending name printed to stderr) so a
265
+ single broken plugin never prevents the rest of the process from
266
+ rendering.
267
+ """
268
+ global _DISCOVERED
269
+ if _DISCOVERED:
270
+ return
271
+ _DISCOVERED = True
272
+
273
+ try:
274
+ from importlib.metadata import entry_points
275
+ except ImportError:
276
+ return
277
+
278
+ try:
279
+ eps = entry_points()
280
+ except Exception:
281
+ return
282
+
283
+ # importlib.metadata's API changed across Python versions; both
284
+ # ``select`` and direct ``.get`` are normalized here.
285
+ selected: List[Any] = []
286
+ if hasattr(eps, "select"):
287
+ try:
288
+ selected = list(eps.select(group=ENTRY_POINT_GROUP))
289
+ except Exception:
290
+ selected = []
291
+ if not selected:
292
+ try:
293
+ getter = getattr(eps, "get", None)
294
+ if getter is not None:
295
+ selected = list(getter(ENTRY_POINT_GROUP, []))
296
+ except Exception:
297
+ selected = []
298
+
299
+ for ep in selected:
300
+ name = getattr(ep, "name", "?")
301
+ try:
302
+ ep.load()
303
+ except Exception as exc: # pragma: no cover - defensive
304
+ import sys
305
+
306
+ print(
307
+ f"[pythonnative.sdk] Failed to load handler entry point {name!r}: {exc!r}",
308
+ file=sys.stderr,
309
+ flush=True,
310
+ )
311
+
312
+
313
+ def _reset_discovery_state_for_tests() -> None:
314
+ """Reset the entry-point discovery flag (for tests only)."""
315
+ global _DISCOVERED
316
+ _DISCOVERED = False
317
+
318
+
319
+ # ---------------------------------------------------------------------- #
320
+ # Element factories
321
+ # ---------------------------------------------------------------------- #
322
+
323
+
324
+ def _props_to_dict(value: Any) -> Dict[str, Any]:
325
+ """Convert a typed props dataclass to a flat dict of non-None fields."""
326
+ if isinstance(value, dict):
327
+ return {k: v for k, v in value.items() if v is not None}
328
+ if is_dataclass(value):
329
+ out: Dict[str, Any] = {}
330
+ for f in fields(value):
331
+ field_value = getattr(value, f.name)
332
+ if field_value is not None:
333
+ out[f.name] = field_value
334
+ return out
335
+ raise TypeError(f"Expected a dataclass instance or dict, got {type(value).__name__!r}")
336
+
337
+
338
+ def element_factory(name: str) -> Callable[..., Element]:
339
+ """Return a callable that builds [`Element`][pythonnative.Element] instances of type ``name``.
340
+
341
+ The returned factory accepts:
342
+
343
+ - Children as positional arguments (any number).
344
+ - ``key=`` (optional, keyword-only) for keyed reconciliation.
345
+ - Either ``props=`` (a dataclass instance) or per-field keyword
346
+ arguments matching the registered props dataclass.
347
+
348
+ If no ``props`` dataclass was registered for ``name``, kwargs flow
349
+ through unmodified, useful when iterating before locking down a
350
+ prop schema.
351
+
352
+ Args:
353
+ name: An element type name previously registered via
354
+ [`@native_component`][pythonnative.sdk.native_component] or
355
+ [`register_component`][pythonnative.sdk.register_component].
356
+
357
+ Returns:
358
+ A callable producing fresh
359
+ [`Element`][pythonnative.Element] instances of type ``name``.
360
+
361
+ Raises:
362
+ KeyError: If ``name`` is not registered.
363
+
364
+ Example:
365
+ ```python
366
+ Badge = element_factory("Badge")
367
+ Badge(text="3", color="#0A84FF")
368
+ Badge(props=BadgeProps(text="3"))
369
+ ```
370
+ """
371
+ if name not in _REGISTRY:
372
+ raise KeyError(
373
+ f"No component registered under name {name!r}. Use @native_component or register_component first."
374
+ )
375
+
376
+ def factory(*children: Element, key: Optional[str] = None, props: Any = None, **kwargs: Any) -> Element:
377
+ props_type = get_props_type(name)
378
+ if props is not None:
379
+ if kwargs:
380
+ raise TypeError("Pass either props=... or keyword props, not both")
381
+ props_dict = _props_to_dict(props)
382
+ elif props_type is not None:
383
+ try:
384
+ instance = props_type(**kwargs)
385
+ except TypeError as exc:
386
+ raise TypeError(f"Invalid props for {name!r}: {exc}") from exc
387
+ props_dict = _props_to_dict(instance)
388
+ else:
389
+ props_dict = dict(kwargs)
390
+ if props_type is not None:
391
+ from .schema import ComponentSchema
392
+
393
+ ComponentSchema.from_dataclass(name, props_type).validate(props_dict)
394
+ # Style props pass through resolve_style at the boundary so list
395
+ # forms / None get flattened identically to built-in factories.
396
+ from ..style import resolve_style as _resolve
397
+
398
+ style_value = props_dict.pop("style", None)
399
+ style_dict = _resolve(style_value)
400
+ merged: Dict[str, Any] = {**style_dict, **props_dict}
401
+ return Element(name, merged, list(children), key=key)
402
+
403
+ import inspect
404
+
405
+ props_type = get_props_type(name)
406
+ if props_type is not None:
407
+ factory.__signature__ = inspect.signature(props_type)
408
+ from .schema import ComponentSchema, register_schema
409
+
410
+ register_schema(ComponentSchema.from_dataclass(name, props_type))
411
+ factory.__name__ = name
412
+ factory.__doc__ = f"Construct an Element of type {name!r}."
413
+ return factory
414
+
415
+
416
+ __all__ = [
417
+ "ENTRY_POINT_GROUP",
418
+ "Props",
419
+ "element_factory",
420
+ "get_test_handler",
421
+ "get_props_type",
422
+ "install_into_registry",
423
+ "list_components",
424
+ "native_component",
425
+ "register_component",
426
+ "unregister_component",
427
+ ]
@@ -0,0 +1,91 @@
1
+ """Native contracts derived from the annotated built-in Python factories."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import dataclasses
6
+ import inspect
7
+ import typing
8
+ from typing import Any, Callable
9
+
10
+ from ..style import Style
11
+ from .schema import COMPONENTS, ComponentSchema, NativeField, register_schema, type_schema
12
+
13
+ # These types own native child layout or physical child presentation.
14
+ CONTAINERS = frozenset(
15
+ {"View", "Column", "Row", "ScrollView", "Screen", "ScreenStack", "Modal", "Portal", "VirtualList"}
16
+ )
17
+
18
+
19
+ def install(factories: dict[str, Any]) -> None:
20
+ """Compile ordinary Python annotations into the shared native contract."""
21
+ style_fields = {name: type_schema(annotation) for name, annotation in typing.get_type_hints(Style).items()}
22
+ for name, factory in factories.items():
23
+ if not inspect.isfunction(factory) or not name[:1].isupper() or name.startswith("_"):
24
+ continue
25
+ signature = inspect.signature(factory)
26
+ hints = typing.get_type_hints(factory)
27
+ fields: list[Any] = []
28
+ for key, parameter in signature.parameters.items():
29
+ if key in {"style", "ref", "key"} or parameter.kind in {parameter.VAR_POSITIONAL, parameter.VAR_KEYWORD}:
30
+ continue
31
+ annotation = hints.get(key, Any)
32
+ default = parameter.default
33
+ fields.append(
34
+ (key, annotation)
35
+ if default is inspect.Parameter.empty
36
+ else (key, annotation, dataclasses.field(default=default))
37
+ )
38
+ props_type = dataclasses.make_dataclass(f"{name}Props", fields, frozen=True, kw_only=True)
39
+ schema = ComponentSchema.from_dataclass(
40
+ name, props_type, measurement="container" if name in CONTAINERS else "intrinsic"
41
+ )
42
+ wire = dict(style_fields) | schema.props
43
+ wire.update(ref={}, on_layout=type_schema(Callable[..., Any]))
44
+ for key in wire:
45
+ wire[key] = dict(wire[key])
46
+ wire[key]["native"] = dataclasses.asdict(
47
+ NativeField(
48
+ invalidates_layout=key in style_fields or key in {"text", "value", "title", "source", "spans"},
49
+ recreate=key in {"multiline"},
50
+ animated=key
51
+ in {
52
+ "opacity",
53
+ "background_color",
54
+ "color",
55
+ "rotate",
56
+ "translate_x",
57
+ "translate_y",
58
+ "scale",
59
+ "scale_x",
60
+ "scale_y",
61
+ },
62
+ )
63
+ )
64
+ if name == "Text":
65
+ wire.update(text={"type": "string"}, spans={"type": "array"})
66
+ register_schema(dataclasses.replace(schema, props=wire, required=()))
67
+ base = COMPONENTS["View"]
68
+ for name, extra in {
69
+ "Screen": {"route_key": {"type": "string"}, "title": {"type": "string"}, "active": {"type": "boolean"}},
70
+ "ScreenStack": {"on_native_back": {"type": "event"}},
71
+ "VirtualList": {
72
+ "keys": {"type": "array"},
73
+ "revision": {"type": "integer"},
74
+ "count": {"type": "integer"},
75
+ "estimated_item_size": {"type": "number"},
76
+ "on_bind_row": {"type": "event"},
77
+ },
78
+ }.items():
79
+ register_schema(ComponentSchema(name, base.props | extra, measurement="container"))
80
+
81
+
82
+ def validate_props(name: str, props: dict[str, Any]) -> None:
83
+ """Check known built-in arguments while preserving composed internal props."""
84
+ schema = COMPONENTS.get(name)
85
+ if schema is None:
86
+ return
87
+ for key, value in props.items():
88
+ if value is not None and key in schema.props:
89
+ from .schema import validate
90
+
91
+ validate(value, schema.props[key], f"{name}.{key}")
@@ -0,0 +1,149 @@
1
+ """Generate component props decoders and portable native metadata."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ from ..bridge.codec import to_jsonable
10
+ from .schema import COMPONENTS, fingerprint, manifest
11
+
12
+
13
+ def generate(destination: str | Path) -> list[Path]:
14
+ """Write deterministic Swift, Kotlin, Python, and browser schema artifacts."""
15
+ destination = Path(destination)
16
+ destination.mkdir(parents=True, exist_ok=True)
17
+ spec = manifest()
18
+ encoded = json.dumps(spec, indent=2, sort_keys=True, default=str) + "\n"
19
+ swift = ["import Foundation", "", "// Generated from Python schemas. Regenerate instead of editing."]
20
+ kotlin = [
21
+ "package com.pythonnative.generated",
22
+ "",
23
+ "import org.json.JSONObject",
24
+ "",
25
+ "// Generated from Python schemas.",
26
+ ]
27
+ python = [
28
+ '"""Generated native component factories."""',
29
+ "from typing import Any",
30
+ "from pythonnative.element import Element",
31
+ "from pythonnative.sdk.schema import COMPONENTS",
32
+ "",
33
+ ]
34
+ docs = ["# Native contracts", "", f"Runtime fingerprint: `{fingerprint()}`.", ""]
35
+ names = {
36
+ "string": ("String", "String", "str"),
37
+ "boolean": ("Bool", "Boolean", "bool"),
38
+ "integer": ("Int", "Int", "int"),
39
+ "number": ("Double", "Double", "float"),
40
+ }
41
+ for name, component in sorted(COMPONENTS.items()):
42
+ if not name.isidentifier():
43
+ raise ValueError(f"Invalid native component name {name!r}")
44
+ swift.extend(
45
+ [
46
+ f"public struct {name}Props {{",
47
+ " public let values: [String: Any]",
48
+ " public init(_ values: [String: Any]) throws {",
49
+ " self.values = values",
50
+ ]
51
+ )
52
+ kotlin.extend([f"data class {name}Props(val values: JSONObject) {{", " init {"])
53
+ parameters = []
54
+ values = []
55
+ for key, field in component.props.items():
56
+ if not key.isidentifier():
57
+ raise ValueError(f"Invalid property name {key!r}")
58
+ kind = field.get("type")
59
+ swift_type, kotlin_type, python_type = names.get(kind, ("Any", "Any", "Any"))
60
+ if key in component.required:
61
+ swift.append(
62
+ f' guard values["{key}"] is {swift_type} else {{ '
63
+ f'throw NativeDecodeError.invalid("{name}.{key}") }}'
64
+ )
65
+ kotlin.append(
66
+ f' require(values.has("{key}") && !values.isNull("{key}")) {{ "Missing {name}.{key}" }}'
67
+ )
68
+ default = component.defaults.get(key)
69
+ if hasattr(default, "value"):
70
+ default = default.value
71
+ if default is None and python_type != "Any":
72
+ python_type += " | None"
73
+ parameters.append(f"{key}: {python_type}" + (f" = {default!r}" if key not in component.required else ""))
74
+ values.append(f'"{key}": {key}')
75
+ swift.append(" }")
76
+ kotlin.append(" }")
77
+ for key, field in component.props.items():
78
+ kind = field.get("type")
79
+ st, kt, _ = names.get(kind, ("Any", "Any", "Any"))
80
+ expression = f'values["{key}"]' + (f" as? {st}" if st != "Any" else "")
81
+ swift.append(f" public var {key}: {st}? {{ {expression} }}")
82
+ accessor = {"string": "getString", "boolean": "getBoolean", "integer": "getInt", "number": "getDouble"}.get(
83
+ kind, "get"
84
+ )
85
+ kotlin.append(
86
+ f' val {key}: {kt}? get() = if (values.isNull("{key}")) null else values.{accessor}("{key}")'
87
+ )
88
+ swift.extend(["}", ""])
89
+ kotlin.extend(["}", ""])
90
+ python.extend(
91
+ [
92
+ f"def {name}(*children: Element, "
93
+ + ", ".join(parameters + ["key: str | None = None"])
94
+ + ") -> Element:",
95
+ f' """Create a validated {name} native element."""',
96
+ " props = {" + ", ".join(values) + "}",
97
+ f' COMPONENTS["{name}"].validate(props)',
98
+ f' return Element("{name}", props, list(children), key=key)',
99
+ "",
100
+ ]
101
+ )
102
+ docs.extend(
103
+ [
104
+ f"## {name}",
105
+ "",
106
+ f"Measurement: {component.measurement}.",
107
+ "",
108
+ "| Property | Type | Required |",
109
+ "| --- | --- | --- |",
110
+ ]
111
+ )
112
+ docs.extend(
113
+ f"| `{key}` | `{field.get('type', 'union')}` | {key in component.required} |"
114
+ for key, field in component.props.items()
115
+ )
116
+ docs.append("")
117
+ swift.extend(["public enum NativeDecodeError: Error { case invalid(String) }", ""])
118
+ outputs: dict[str, Any] = {
119
+ "schema.json": encoded,
120
+ "schema.js": "export default " + encoded.strip() + ";\n",
121
+ "NativeProps.swift": "\n".join(swift),
122
+ "NativeProps.kt": "\n".join(kotlin),
123
+ "components.py": "\n".join(python),
124
+ "README.md": "\n".join(docs),
125
+ }
126
+ compact = json.dumps(to_jsonable(spec), separators=(",", ":"), sort_keys=True)
127
+ templates = Path(__file__).with_name("templates")
128
+ for extension in ("swift", "kt"):
129
+ template = (templates / f"contracts.{extension}").read_text(encoding="utf-8")
130
+ # Escaped Swift strings and Kotlin raw strings have different interpolation rules.
131
+ data = (
132
+ compact.replace("\\", "\\\\")
133
+ if extension == "swift"
134
+ else ",\n".join(
135
+ '"""' + compact[i : i + 8000].replace("$", "${'$'}") + '"""' for i in range(0, len(compact), 8000)
136
+ )
137
+ )
138
+ outputs[f"PNContracts.{extension}"] = template.replace("{{fingerprint}}", fingerprint()).replace(
139
+ "{{specification}}", data
140
+ )
141
+ from .module_codegen import generate_modules
142
+
143
+ outputs.update(generate_modules())
144
+ paths = []
145
+ for name, contents in outputs.items():
146
+ path = destination / name
147
+ path.write_text(contents, encoding="utf-8")
148
+ paths.append(path)
149
+ return paths