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
pythonnative/layout.py ADDED
@@ -0,0 +1,328 @@
1
+ """Yoga 3.2.1 layout for headless tests and the Python preview host.
2
+
3
+ Mobile hosts run this same pinned core beside their native widgets. This
4
+ module contains style translation and ownership, not a second flex algorithm.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import ctypes as C
10
+ import math
11
+ import weakref
12
+ from typing import Any, Callable
13
+
14
+ LAYOUT_STYLE_KEYS = frozenset(
15
+ {
16
+ "width",
17
+ "height",
18
+ "min_width",
19
+ "max_width",
20
+ "min_height",
21
+ "max_height",
22
+ "flex",
23
+ "flex_grow",
24
+ "flex_shrink",
25
+ "flex_basis",
26
+ "flex_wrap",
27
+ "align_self",
28
+ "align_content",
29
+ "position",
30
+ "top",
31
+ "right",
32
+ "bottom",
33
+ "left",
34
+ "start",
35
+ "end",
36
+ "margin",
37
+ "margin_top",
38
+ "margin_bottom",
39
+ "margin_left",
40
+ "margin_right",
41
+ "margin_start",
42
+ "margin_end",
43
+ "margin_horizontal",
44
+ "margin_vertical",
45
+ "padding",
46
+ "padding_top",
47
+ "padding_bottom",
48
+ "padding_left",
49
+ "padding_right",
50
+ "padding_start",
51
+ "padding_end",
52
+ "padding_horizontal",
53
+ "padding_vertical",
54
+ "border_width",
55
+ "border_top_width",
56
+ "border_right_width",
57
+ "border_bottom_width",
58
+ "border_left_width",
59
+ "flex_direction",
60
+ "justify_content",
61
+ "align_items",
62
+ "spacing",
63
+ "gap",
64
+ "row_gap",
65
+ "column_gap",
66
+ "aspect_ratio",
67
+ "direction",
68
+ "display",
69
+ }
70
+ )
71
+ """Style keys that affect layout (and are consumed by the layout engine)."""
72
+
73
+
74
+ _lib: Any = None
75
+ _nodes: weakref.WeakValueDictionary[int, LayoutNode] = weakref.WeakValueDictionary()
76
+ _Measure = C.CFUNCTYPE(
77
+ None, C.c_void_p, C.c_float, C.c_int, C.c_float, C.c_int, C.POINTER(C.c_float), C.POINTER(C.c_float)
78
+ )
79
+
80
+
81
+ @_Measure
82
+ def _measure(ptr: int, width: float, wm: int, height: float, hm: int, outw: Any, outh: Any) -> None:
83
+ node = _nodes.get(ptr)
84
+ try:
85
+ w, h = node.measure(width if wm else math.inf, height if hm else math.inf)
86
+ outw[0], outh[0] = max(0, w), max(0, h)
87
+ except BaseException as exc:
88
+ if node is not None:
89
+ node._error = exc
90
+ outw[0] = outh[0] = 0
91
+
92
+
93
+ def _api() -> Any:
94
+ global _lib
95
+ if _lib is not None:
96
+ return _lib
97
+ from . import _yoga
98
+
99
+ lib = C.CDLL(_yoga.__file__)
100
+ signatures: dict[str, Any] = {
101
+ "YGNodeNew": (C.c_void_p, []),
102
+ "YGNodeFree": (None, [C.c_void_p]),
103
+ "YGNodeRemoveAllChildren": (None, [C.c_void_p]),
104
+ "YGNodeInsertChild": (None, [C.c_void_p, C.c_void_p, C.c_size_t]),
105
+ "YGNodeCopyStyle": (None, [C.c_void_p, C.c_void_p]),
106
+ "YGNodeMarkDirty": (None, [C.c_void_p]),
107
+ "YGNodeCalculateLayout": (None, [C.c_void_p, C.c_float, C.c_float, C.c_int]),
108
+ "pn_yoga_callback": (None, [_Measure]),
109
+ "pn_yoga_measure": (None, [C.c_void_p, C.c_int]),
110
+ }
111
+ for axis in ("Left", "Top", "Width", "Height"):
112
+ signatures["YGNodeLayoutGet" + axis] = (C.c_float, [C.c_void_p])
113
+ for name, (result, args) in signatures.items():
114
+ fn = getattr(lib, name)
115
+ fn.restype, fn.argtypes = result, args
116
+ lib.pn_yoga_callback(_measure)
117
+ _lib = lib
118
+ return lib
119
+
120
+
121
+ # Enum order follows Yoga's public C ABI in the pinned vendored headers.
122
+ ENUMS = {
123
+ "direction": ("Direction", ["inherit", "ltr", "rtl"]),
124
+ "flex_direction": ("FlexDirection", ["column", "column_reverse", "row", "row_reverse"]),
125
+ "justify_content": (
126
+ "JustifyContent",
127
+ ["flex_start", "center", "flex_end", "space_between", "space_around", "space_evenly"],
128
+ ),
129
+ "align_items": (
130
+ "AlignItems",
131
+ [
132
+ "auto",
133
+ "flex_start",
134
+ "center",
135
+ "flex_end",
136
+ "stretch",
137
+ "baseline",
138
+ "space_between",
139
+ "space_around",
140
+ "space_evenly",
141
+ ],
142
+ ),
143
+ "align_self": (
144
+ "AlignSelf",
145
+ [
146
+ "auto",
147
+ "flex_start",
148
+ "center",
149
+ "flex_end",
150
+ "stretch",
151
+ "baseline",
152
+ "space_between",
153
+ "space_around",
154
+ "space_evenly",
155
+ ],
156
+ ),
157
+ "align_content": (
158
+ "AlignContent",
159
+ [
160
+ "auto",
161
+ "flex_start",
162
+ "center",
163
+ "flex_end",
164
+ "stretch",
165
+ "baseline",
166
+ "space_between",
167
+ "space_around",
168
+ "space_evenly",
169
+ ],
170
+ ),
171
+ "position": ("PositionType", ["static", "relative", "absolute"]),
172
+ "flex_wrap": ("FlexWrap", ["nowrap", "wrap", "wrap_reverse"]),
173
+ "display": ("Display", ["flex", "none", "contents"]),
174
+ }
175
+ EDGES = {
176
+ name: i
177
+ for i, name in enumerate(["left", "top", "right", "bottom", "start", "end", "horizontal", "vertical", "all"])
178
+ }
179
+ ALIASES = {
180
+ "start": "flex_start",
181
+ "leading": "flex_start",
182
+ "top": "flex_start",
183
+ "end": "flex_end",
184
+ "trailing": "flex_end",
185
+ "bottom": "flex_end",
186
+ "fill": "stretch",
187
+ }
188
+
189
+
190
+ def _set(ptr: int, name: str, value: Any, edge: int | None = None, *, enum: bool = False) -> None:
191
+ if value is None or isinstance(value, bool):
192
+ return
193
+ suffix = ""
194
+ args: list[Any] = [ptr]
195
+ types: list[Any] = [C.c_void_p]
196
+ if edge is not None:
197
+ args.append(edge)
198
+ types.append(C.c_int)
199
+ if value == "auto":
200
+ suffix = "Auto"
201
+ else:
202
+ if isinstance(value, str) and value.endswith("%"):
203
+ suffix, value = "Percent", float(value[:-1])
204
+ args.append(int(value) if enum else float(value))
205
+ types.append(C.c_int if enum else C.c_float)
206
+ fn = getattr(_api(), "YGNodeStyleSet" + name + suffix)
207
+ fn.restype, fn.argtypes = None, types
208
+ fn(*args)
209
+
210
+
211
+ def apply_style(ptr: int, style: dict[str, Any]) -> None:
212
+ """Translate Pythonic style keys to Yoga's native style API."""
213
+ for key, value in style.items():
214
+ if value is None:
215
+ continue
216
+ if key in ENUMS:
217
+ name, values = ENUMS[key]
218
+ value = ALIASES.get(value, value) if key.startswith(("align_", "justify_")) else value
219
+ if value not in values:
220
+ raise ValueError(f"Invalid {key}: {value!r}")
221
+ _set(ptr, name, values.index(value), enum=True)
222
+ elif key in {
223
+ "width",
224
+ "height",
225
+ "min_width",
226
+ "min_height",
227
+ "max_width",
228
+ "max_height",
229
+ "flex",
230
+ "flex_grow",
231
+ "flex_shrink",
232
+ "flex_basis",
233
+ "aspect_ratio",
234
+ }:
235
+ _set(ptr, "".join(part.title() for part in key.split("_")), value)
236
+ elif key in {"spacing", "gap", "row_gap", "column_gap"}:
237
+ _set(ptr, "Gap", value, {"column_gap": 0, "row_gap": 1}.get(key, 2))
238
+ elif key in EDGES and key not in {"all", "horizontal", "vertical"}:
239
+ _set(ptr, "Position", value, EDGES[key])
240
+ elif key.startswith(("padding", "margin")):
241
+ group, _, edge = key.partition("_")
242
+ if isinstance(value, dict):
243
+ for side, amount in value.items():
244
+ _set(ptr, group.title(), amount, EDGES[side])
245
+ else:
246
+ _set(ptr, group.title(), value, EDGES[edge or "all"])
247
+ elif key.startswith("border_") and key.endswith("width"):
248
+ _set(ptr, "Border", value, EDGES[key[7:-6] or "all"])
249
+
250
+
251
+ class LayoutNode:
252
+ """An owned Yoga node, with Python measurement for headless backends."""
253
+
254
+ def __init__(
255
+ self,
256
+ style: dict[str, Any] | None = None,
257
+ children: list[LayoutNode] | None = None,
258
+ measure: Callable[[float, float], tuple[float, float]] | None = None,
259
+ user_data: Any = None,
260
+ ) -> None:
261
+ self.style = dict(style or {})
262
+ self.children = list(children or [])
263
+ self.measure = measure
264
+ self.user_data = user_data
265
+ self.x = self.y = self.width = self.height = 0.0
266
+ self.dirty = True
267
+ self._pn_scroll_axis: str | None = None
268
+ self._ptr: int | None = None
269
+ self._last_style: Any = None
270
+ self._last_children: tuple[int, ...] = ()
271
+ self._error: BaseException | None = None
272
+
273
+ def _sync(self) -> int:
274
+ lib = _api()
275
+ if self._ptr is None:
276
+ self._ptr = lib.YGNodeNew()
277
+ _nodes[self._ptr] = self
278
+ weakref.finalize(self, lib.YGNodeFree, self._ptr)
279
+ ptr = self._ptr
280
+ style = dict(self.style)
281
+ if self._pn_scroll_axis:
282
+ style.setdefault("flex_shrink", 1)
283
+ if style != self._last_style:
284
+ fresh = lib.YGNodeNew()
285
+ apply_style(fresh, style)
286
+ if self._pn_scroll_axis:
287
+ _set(fresh, "Overflow", 1, enum=True)
288
+ lib.YGNodeCopyStyle(ptr, fresh)
289
+ lib.YGNodeFree(fresh)
290
+ self._last_style = style
291
+ measured = self.measure is not None and not self.children
292
+ lib.pn_yoga_measure(ptr, measured)
293
+ if measured and self.dirty:
294
+ lib.YGNodeMarkDirty(ptr)
295
+ children = tuple(child._sync() for child in self.children)
296
+ if children != self._last_children:
297
+ lib.YGNodeRemoveAllChildren(ptr)
298
+ for i, child in enumerate(children):
299
+ lib.YGNodeInsertChild(ptr, child, i)
300
+ self._last_children = children
301
+ return ptr
302
+
303
+ def _read(self) -> None:
304
+ lib = _api()
305
+ self.x = lib.YGNodeLayoutGetLeft(self._ptr)
306
+ self.y = lib.YGNodeLayoutGetTop(self._ptr)
307
+ self.width = lib.YGNodeLayoutGetWidth(self._ptr)
308
+ self.height = lib.YGNodeLayoutGetHeight(self._ptr)
309
+ self.dirty = False
310
+ if self._error is not None:
311
+ error, self._error = self._error, None
312
+ raise error
313
+ for child in self.children:
314
+ child._read()
315
+
316
+
317
+ def calculate_layout(node: LayoutNode, width: float, height: float) -> None:
318
+ """Calculate a tree's layout with the pinned Yoga core."""
319
+ ptr = node._sync()
320
+ _api().YGNodeCalculateLayout(
321
+ ptr, width if math.isfinite(width) else math.nan, height if math.isfinite(height) else math.nan, 1
322
+ )
323
+ node._read()
324
+
325
+
326
+ def extract_layout_style(props: dict[str, Any]) -> dict[str, Any]:
327
+ """Select properties owned by layout."""
328
+ return {key: value for key, value in props.items() if key in LAYOUT_STYLE_KEYS}
@@ -0,0 +1,142 @@
1
+ """Batched mutation protocol between the reconciler and native backends.
2
+
3
+ The reconciler no longer talks to the native layer one call at a time.
4
+ Instead, every commit pass produces an ordered list of small mutation
5
+ ops referencing integer **tags** (stable per-view identifiers), and the
6
+ whole list is applied in a single
7
+ [`apply_mutations`][pythonnative.native_views.NativeViewRegistry.apply_mutations]
8
+ call. This mirrors React Native's Fabric mounting layer: the diff phase
9
+ is pure, and the native side sees one coherent transaction per commit.
10
+
11
+ Why tags instead of view objects?
12
+
13
+ - The diff phase runs *before* any native view exists, so ops cannot
14
+ reference views directly.
15
+ - Tags give the native side a stable identity to key its own view
16
+ registry, event routing, and animation bookkeeping on.
17
+ - A flat list of `(op, tag, payload)` tuples is trivially serializable,
18
+ which keeps the door open for applying mutations from a background
19
+ thread or through a single JNI/ObjC crossing in the future.
20
+
21
+ Op ordering rules (the reconciler guarantees these):
22
+
23
+ 1. A `CreateOp` for a tag precedes any other op referencing that tag.
24
+ 2. `InsertOp` ops appear after both the parent and child exist.
25
+ 3. `DestroyOp` ops are emitted children-first; handlers detach the view
26
+ from its parent as part of destruction.
27
+ 4. `SetFrameOp` ops are only emitted for frames that actually changed
28
+ since the last layout pass (frame diffing).
29
+ """
30
+
31
+ from dataclasses import dataclass, field
32
+ from typing import Any, Dict, Tuple, Union
33
+
34
+ __all__ = [
35
+ "CreateOp",
36
+ "UpdateOp",
37
+ "InsertOp",
38
+ "DestroyOp",
39
+ "SetFrameOp",
40
+ "Mutation",
41
+ ]
42
+
43
+
44
+ @dataclass(frozen=True)
45
+ class CreateOp:
46
+ """Create a native view for ``tag`` of element type ``type_name``.
47
+
48
+ Attributes:
49
+ tag: Unique integer identity assigned by the reconciler.
50
+ type_name: Element type name (e.g. ``"Text"``).
51
+ props: Initial *clean* props; callables have already been
52
+ routed to the [`EventRegistry`][pythonnative.events.EventRegistry]
53
+ and replaced by the ``_pn_events`` name set.
54
+ """
55
+
56
+ tag: int
57
+ type_name: str
58
+ props: Dict[str, Any] = field(default_factory=dict)
59
+
60
+
61
+ @dataclass(frozen=True)
62
+ class UpdateOp:
63
+ """Apply ``changed_props`` to the view registered under ``tag``.
64
+
65
+ Removed props are signaled with a value of ``None``, matching the
66
+ pre-existing handler contract.
67
+
68
+ Attributes:
69
+ tag: Unique integer identity of the target view.
70
+ changed_props: Mapping of modified prop names to their new values.
71
+ Removed props appear with a value of ``None``.
72
+ """
73
+
74
+ tag: int
75
+ changed_props: Dict[str, Any] = field(default_factory=dict)
76
+
77
+
78
+ @dataclass(frozen=True)
79
+ class InsertOp:
80
+ """Ensure the child view sits at ``index`` inside the parent view.
81
+
82
+ Handlers must treat this as *move-aware*: if the child is already
83
+ attached to the parent at a different position, it is moved rather
84
+ than duplicated. ``index`` is clamped by handlers to the current
85
+ child count.
86
+
87
+ Attributes:
88
+ parent_tag: Integer tag of the container view.
89
+ child_tag: Integer tag of the child view to insert or move.
90
+ index: Zero-based insertion index, clamped by handlers to the
91
+ current child count.
92
+ """
93
+
94
+ parent_tag: int
95
+ child_tag: int
96
+ index: int
97
+
98
+
99
+ @dataclass(frozen=True)
100
+ class DestroyOp:
101
+ """Release the native view registered under ``tag``.
102
+
103
+ The registry drops its tag record and calls the handler's
104
+ ``destroy`` hook so platform resources (listeners, timers, image
105
+ loads) can be released eagerly instead of waiting for GC.
106
+
107
+ Attributes:
108
+ tag: Unique integer identity of the view to destroy.
109
+ """
110
+
111
+ tag: int
112
+
113
+
114
+ @dataclass(frozen=True)
115
+ class SetFrameOp:
116
+ """Position and size the view registered under ``tag``.
117
+
118
+ Coordinates are points relative to the parent's content origin,
119
+ exactly as computed by the layout engine.
120
+
121
+ Attributes:
122
+ tag: Unique integer identity of the target view.
123
+ x: Horizontal origin offset in points relative to the parent.
124
+ y: Vertical origin offset in points relative to the parent.
125
+ width: View width in points.
126
+ height: View height in points.
127
+ """
128
+
129
+ tag: int
130
+ x: float
131
+ y: float
132
+ width: float
133
+ height: float
134
+
135
+ @property
136
+ def frame(self) -> Tuple[float, float, float, float]:
137
+ """Return ``(x, y, width, height)`` as a tuple."""
138
+ return (self.x, self.y, self.width, self.height)
139
+
140
+
141
+ Mutation = Union[CreateOp, UpdateOp, InsertOp, DestroyOp, SetFrameOp]
142
+ """Union of every op type carried by a commit transaction."""
@@ -0,0 +1,52 @@
1
+ plugins {
2
+ id 'com.android.library'
3
+ id 'org.jetbrains.kotlin.android'
4
+ }
5
+
6
+ android {
7
+ namespace 'com.pythonnative.runtime'
8
+ compileSdk 34
9
+
10
+ defaultConfig {
11
+ minSdk 24
12
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
13
+ }
14
+
15
+ externalNativeBuild {
16
+ cmake { path "src/main/cpp/CMakeLists.txt"; version "3.22.1" }
17
+ }
18
+
19
+ buildFeatures {
20
+ buildConfig false
21
+ }
22
+
23
+ compileOptions {
24
+ sourceCompatibility JavaVersion.VERSION_1_8
25
+ targetCompatibility JavaVersion.VERSION_1_8
26
+ }
27
+ kotlinOptions {
28
+ jvmTarget = '1.8'
29
+ }
30
+
31
+ testOptions {
32
+ unitTests.returnDefaultValues = true
33
+ }
34
+ }
35
+
36
+ dependencies {
37
+ api 'androidx.core:core-ktx:1.8.0'
38
+ api 'androidx.appcompat:appcompat:1.4.1'
39
+ api 'com.google.android.material:material:1.5.0'
40
+ api 'androidx.recyclerview:recyclerview:1.3.2'
41
+ api 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
42
+ api 'androidx.security:security-crypto:1.1.0'
43
+ api 'androidx.biometric:biometric:1.1.0'
44
+ api 'androidx.dynamicanimation:dynamicanimation:1.0.0'
45
+ // Screen navigation (PNScreenFragment inside the app's NavHostFragment).
46
+ api 'androidx.navigation:navigation-fragment-ktx:2.7.7'
47
+ api 'androidx.navigation:navigation-ui-ktx:2.7.7'
48
+
49
+ testImplementation 'junit:junit:4.13.2'
50
+ // Real org.json for host-side unit tests (the android.jar stubs are empty).
51
+ testImplementation 'org.json:json:20231013'
52
+ }
@@ -0,0 +1,3 @@
1
+ android.useAndroidX=true
2
+ android.nonTransitiveRClass=true
3
+ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
@@ -0,0 +1,12 @@
1
+ pluginManagement {
2
+ repositories { google(); mavenCentral(); gradlePluginPortal() }
3
+ plugins {
4
+ id 'com.android.library' version '8.7.3'
5
+ id 'org.jetbrains.kotlin.android' version '2.0.21'
6
+ }
7
+ }
8
+ dependencyResolutionManagement {
9
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
10
+ repositories { google(); mavenCentral() }
11
+ }
12
+ rootProject.name = 'PythonNativeRuntime'
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
+
4
+ <!-- Runtime-gated on Android 13+ (API 33); requested by the
5
+ Notifications module before posting. -->
6
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
7
+ <uses-permission android:name="android.permission.VIBRATE" />
8
+ <uses-permission android:name="android.permission.INTERNET" />
9
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
10
+
11
+ </manifest>
@@ -0,0 +1,9 @@
1
+ cmake_minimum_required(VERSION 3.22)
2
+ project(pn_yoga LANGUAGES CXX)
3
+ set(CMAKE_CXX_STANDARD 20)
4
+ set(PN_YOGA_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../../../yoga)
5
+ file(GLOB_RECURSE YOGA_SOURCES ${PN_YOGA_ROOT}/yoga/*.cpp)
6
+ add_library(pn_yoga SHARED ${YOGA_SOURCES} ${PN_YOGA_ROOT}/style.cpp yoga_jni.cpp)
7
+ target_include_directories(pn_yoga PRIVATE ${PN_YOGA_ROOT})
8
+ target_link_libraries(pn_yoga log)
9
+ target_link_options(pn_yoga PRIVATE "-Wl,-z,max-page-size=16384")
@@ -0,0 +1,52 @@
1
+ #include <jni.h>
2
+ #include <yoga/Yoga.h>
3
+ #include <include/PNStyle.h>
4
+ #include <cmath>
5
+ static JavaVM* vm;
6
+ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* value, void*) { vm = value; return JNI_VERSION_1_6; }
7
+ static JNIEnv* env() { JNIEnv* result; vm->GetEnv(reinterpret_cast<void**>(&result), JNI_VERSION_1_6); return result; }
8
+ static YGNodeRef node(jlong ptr) { return reinterpret_cast<YGNodeRef>(ptr); }
9
+ static YGSize measure(YGNodeConstRef n, float w, YGMeasureMode wm, float h, YGMeasureMode hm) {
10
+ auto e = env(); auto object = static_cast<jobject>(YGNodeGetContext(n));
11
+ auto cls = e->GetObjectClass(object);
12
+ auto method = e->GetMethodID(cls, "measure", "(FF)[F");
13
+ auto result = static_cast<jfloatArray>(e->CallObjectMethod(object, method, wm == YGMeasureModeUndefined ? 1e6f : w, hm == YGMeasureModeUndefined ? 1e6f : h));
14
+ float size[2] = {0, 0};
15
+ if (result) { e->GetFloatArrayRegion(result, 0, 2, size); e->DeleteLocalRef(result); }
16
+ e->DeleteLocalRef(cls);
17
+ return {size[0], size[1]};
18
+ }
19
+ static float baseline(YGNodeConstRef n, float, float h) {
20
+ auto e = env(); auto object = static_cast<jobject>(YGNodeGetContext(n));
21
+ auto cls = e->GetObjectClass(object);
22
+ auto method = e->GetMethodID(cls, "baseline", "(F)F");
23
+ float result = e->CallFloatMethod(object, method, h); e->DeleteLocalRef(cls); return result;
24
+ }
25
+ #define JNI(name) extern "C" JNIEXPORT name
26
+ JNI(jlong) Java_com_pythonnative_runtime_layout_YogaNode_create(JNIEnv* e, jobject self) {
27
+ auto n = YGNodeNew(); YGNodeSetContext(n, e->NewGlobalRef(self)); return reinterpret_cast<jlong>(n);
28
+ }
29
+ JNI(void) Java_com_pythonnative_runtime_layout_YogaNode_free(JNIEnv* e, jobject, jlong ptr) {
30
+ auto n = node(ptr); e->DeleteGlobalRef(static_cast<jobject>(YGNodeGetContext(n))); YGNodeFree(n);
31
+ }
32
+ JNI(void) Java_com_pythonnative_runtime_layout_YogaNode_style(JNIEnv* e, jobject, jlong ptr, jstring key, jstring value) {
33
+ auto k = e->GetStringUTFChars(key, nullptr); auto v = e->GetStringUTFChars(value, nullptr);
34
+ PNYogaSetStyle(node(ptr), k, v); e->ReleaseStringUTFChars(key, k); e->ReleaseStringUTFChars(value, v);
35
+ }
36
+ JNI(void) Java_com_pythonnative_runtime_layout_YogaNode_resetStyle(JNIEnv*, jobject, jlong ptr) {
37
+ auto fresh = YGNodeNew(); YGNodeCopyStyle(node(ptr), fresh); YGNodeFree(fresh);
38
+ }
39
+ JNI(void) Java_com_pythonnative_runtime_layout_YogaNode_measureLeaf(JNIEnv*, jobject, jlong ptr, jboolean enabled) {
40
+ YGNodeSetMeasureFunc(node(ptr), enabled ? measure : nullptr);
41
+ YGNodeSetBaselineFunc(node(ptr), enabled ? baseline : nullptr);
42
+ if (enabled) YGNodeMarkDirty(node(ptr));
43
+ }
44
+ JNI(void) Java_com_pythonnative_runtime_layout_YogaNode_insert(JNIEnv*, jobject, jlong ptr, jlong child, jint index) {
45
+ auto n = node(ptr); YGNodeSetMeasureFunc(n, nullptr); YGNodeInsertChild(n, node(child), index);
46
+ }
47
+ JNI(void) Java_com_pythonnative_runtime_layout_YogaNode_remove(JNIEnv*, jobject, jlong ptr, jlong child) { YGNodeRemoveChild(node(ptr), node(child)); }
48
+ JNI(void) Java_com_pythonnative_runtime_layout_YogaNode_calculate(JNIEnv*, jobject, jlong ptr, jfloat w, jfloat h) { YGNodeCalculateLayout(node(ptr), w, h, YGDirectionLTR); }
49
+ JNI(jfloatArray) Java_com_pythonnative_runtime_layout_YogaNode_frame(JNIEnv* e, jobject, jlong ptr) {
50
+ auto n = node(ptr); float values[] = {YGNodeLayoutGetLeft(n), YGNodeLayoutGetTop(n), YGNodeLayoutGetWidth(n), YGNodeLayoutGetHeight(n)};
51
+ auto result = e->NewFloatArray(4); e->SetFloatArrayRegion(result, 0, 4, values); return result;
52
+ }
@@ -0,0 +1,5 @@
1
+ package com.pythonnative.generated
2
+
3
+ import org.json.JSONObject
4
+ import com.pythonnative.runtime.modules.NativeModule
5
+ import com.pythonnative.runtime.modules.Promise