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,369 @@
1
+ """Render components into a fake backend and query the result.
2
+
3
+ ```python
4
+ import pythonnative as pn
5
+ from pythonnative.testing import render
6
+
7
+ def test_counter():
8
+ result = render(Counter())
9
+ assert result.get_by_text("Count: 0")
10
+ result.press(result.get_by_text("+"))
11
+ assert result.get_by_text("Count: 1")
12
+ ```
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import re
18
+ from typing import Any, Callable, Dict, Generic, List, Optional, Pattern, Tuple, TypeVar, Union
19
+
20
+ from ..element import Element, Node
21
+ from ..events import dispatch_event, get_event_registry
22
+ from .backend import FakeBackend, FakeView
23
+
24
+ __all__ = ["FakeHost", "HookResult", "RenderResult", "render", "render_hook", "settle"]
25
+
26
+ T = TypeVar("T")
27
+ Matcher = Union[str, Pattern[str], Callable[[Optional[str]], bool]]
28
+ Target = Union[FakeView, int]
29
+
30
+ DEFAULT_VIEWPORT: Tuple[float, float] = (390.0, 844.0)
31
+
32
+
33
+ def _matches(value: Optional[str], matcher: Matcher, *, exact: bool) -> bool:
34
+ if callable(matcher) and not isinstance(matcher, (str, re.Pattern)):
35
+ return bool(matcher(value))
36
+ if value is None:
37
+ return False
38
+ if isinstance(matcher, re.Pattern):
39
+ return matcher.search(value) is not None
40
+ return value == matcher if exact else matcher in value
41
+
42
+
43
+ def settle(reconciler: Any = None, timeout: float = 1.0) -> None:
44
+ """Pump the framework loop and flush pending renders until everything is idle.
45
+
46
+ Use after triggering async work (``use_resource``, ``use_query``,
47
+ transitions, coroutines started by handlers) so assertions see the
48
+ settled tree.
49
+ """
50
+ from .. import runtime
51
+
52
+ for _ in range(50):
53
+ idle = runtime.drain(timeout)
54
+ if reconciler is not None:
55
+ reconciler.flush_dirty()
56
+ if reconciler.transitions.pending:
57
+ reconciler.transitions.flush()
58
+ continue
59
+ if idle and (reconciler is None or not reconciler._has_dirty_work()):
60
+ return
61
+
62
+
63
+ class FakeHost:
64
+ """Application lifecycle and restoration host for navigation tests.
65
+
66
+ Pass as ``render(..., host=FakeHost())`` to provide restoration state.
67
+ Screens remain in the logical tree. ``set_focused`` simulates the
68
+ application entering or leaving the foreground.
69
+ """
70
+
71
+ def __init__(self, initial_state: Optional[Dict[str, Any]] = None) -> None:
72
+ self.is_focused = True
73
+ self.initial_state = initial_state
74
+ self.options: List[Dict[str, Any]] = []
75
+ self._focus_listeners: List[Callable[[bool], None]] = []
76
+
77
+ def initial_navigation_state(self) -> Optional[Dict[str, Any]]:
78
+ """Return the ``initial_state`` the host was constructed with (``None`` for a fresh root)."""
79
+ return self.initial_state
80
+
81
+ def set_screen_options(self, options: Dict[str, Any]) -> None:
82
+ """Append a copy of ``options`` to ``options`` (see the ``title`` property)."""
83
+ self.options.append(dict(options))
84
+
85
+ def add_focus_listener(self, callback: Callable[[bool], None]) -> Callable[[], None]:
86
+ """Register a focus callback fired by ``set_focused``; returns an unsubscribe callable."""
87
+ self._focus_listeners.append(callback)
88
+ return lambda: self._focus_listeners.remove(callback)
89
+
90
+ def set_focused(self, focused: bool) -> None:
91
+ """Simulate the platform covering (``False``) or revealing (``True``) the screen."""
92
+ self.is_focused = focused
93
+ for cb in list(self._focus_listeners):
94
+ cb(focused)
95
+
96
+ @property
97
+ def title(self) -> Optional[str]:
98
+ """The most recent ``title`` passed to ``set_screen_options``."""
99
+ for options in reversed(self.options):
100
+ if "title" in options:
101
+ return options["title"]
102
+ return None
103
+
104
+
105
+ class RenderResult:
106
+ """Handle to a mounted tree: queries, events, re-render, unmount.
107
+
108
+ Query methods come in three flavors, mirroring Testing Library:
109
+ ``get_by_*`` returns exactly one match or raises ``LookupError``
110
+ (with the tree dumped in the message), ``query_by_*`` returns the
111
+ match or ``None``, ``get_all_by_*`` returns every match. Matchers
112
+ are exact strings, compiled regexes, or predicates. Views inside a
113
+ ``display: "none"`` subtree (inactive tabs, covered stack screens)
114
+ are skipped unless ``hidden=True`` is passed.
115
+ """
116
+
117
+ def __init__(self, reconciler: Any, backend: FakeBackend, wrap: Callable[[Node], Element]) -> None:
118
+ self.reconciler = reconciler
119
+ self.backend = backend
120
+ self._wrap = wrap
121
+
122
+ # -- tree -----------------------------------------------------------
123
+
124
+ @property
125
+ def root(self) -> Optional[FakeView]:
126
+ """The root native view (``None`` after unmount)."""
127
+ return self.reconciler.root_view()
128
+
129
+ def views(self, *, hidden: bool = False) -> List[FakeView]:
130
+ """Every live view, root first (includes detached ``Portal`` overlays)."""
131
+ root = self.root
132
+ out = list(root.walk(include_hidden=hidden)) if root is not None else []
133
+ seen = {id(v) for v in out}
134
+ for view in self.backend.views.values():
135
+ if view.parent is None and view is not root and id(view) not in seen:
136
+ out.extend(view.walk(include_hidden=hidden))
137
+ return out
138
+
139
+ def dump(self) -> str:
140
+ """Indented text rendering of the live tree."""
141
+ root = self.root
142
+ return root.dump() if root is not None else "<unmounted>"
143
+
144
+ def text(self, *, hidden: bool = False) -> List[str]:
145
+ """Visible strings in document order."""
146
+ return [v.text for v in self.views(hidden=hidden) if v.text is not None]
147
+
148
+ # -- queries --------------------------------------------------------
149
+
150
+ def _all(self, predicate: Callable[[FakeView], bool], hidden: bool = False) -> List[FakeView]:
151
+ return [v for v in self.views(hidden=hidden) if predicate(v)]
152
+
153
+ def _one(self, kind: str, matcher: Any, found: List[FakeView]) -> FakeView:
154
+ if len(found) == 1:
155
+ return found[0]
156
+ detail = "no matches" if not found else f"{len(found)} matches: {found}"
157
+ raise LookupError(f"get_by_{kind}({matcher!r}): {detail}\n\n{self.dump()}")
158
+
159
+ def get_all_by_text(self, matcher: Matcher, *, exact: bool = True, hidden: bool = False) -> List[FakeView]:
160
+ """Return every view whose visible text matches ``matcher`` (``exact=False`` matches substrings)."""
161
+ return self._all(lambda v: _matches(v.text, matcher, exact=exact), hidden)
162
+
163
+ def get_by_text(self, matcher: Matcher, *, exact: bool = True, hidden: bool = False) -> FakeView:
164
+ """Return the single view whose visible text matches ``matcher``; raise ``LookupError`` otherwise."""
165
+ return self._one("text", matcher, self.get_all_by_text(matcher, exact=exact, hidden=hidden))
166
+
167
+ def query_by_text(self, matcher: Matcher, *, exact: bool = True, hidden: bool = False) -> Optional[FakeView]:
168
+ """Return the first view whose visible text matches ``matcher``, or ``None``."""
169
+ found = self.get_all_by_text(matcher, exact=exact, hidden=hidden)
170
+ return found[0] if found else None
171
+
172
+ def get_all_by_test_id(self, matcher: Matcher, *, hidden: bool = False) -> List[FakeView]:
173
+ """Return every view whose ``test_id`` prop matches ``matcher``."""
174
+ return self._all(lambda v: _matches(v.test_id, matcher, exact=True), hidden)
175
+
176
+ def get_by_test_id(self, matcher: Matcher, *, hidden: bool = False) -> FakeView:
177
+ """Return the single view whose ``test_id`` prop matches ``matcher``; raise ``LookupError`` otherwise."""
178
+ return self._one("test_id", matcher, self.get_all_by_test_id(matcher, hidden=hidden))
179
+
180
+ def query_by_test_id(self, matcher: Matcher, *, hidden: bool = False) -> Optional[FakeView]:
181
+ """Return the first view whose ``test_id`` prop matches ``matcher``, or ``None``."""
182
+ found = self.get_all_by_test_id(matcher, hidden=hidden)
183
+ return found[0] if found else None
184
+
185
+ def get_all_by_label(self, matcher: Matcher, *, hidden: bool = False) -> List[FakeView]:
186
+ """Return every view whose ``accessibility_label`` prop matches ``matcher``."""
187
+ return self._all(lambda v: _matches(v.label, matcher, exact=True), hidden)
188
+
189
+ def get_by_label(self, matcher: Matcher, *, hidden: bool = False) -> FakeView:
190
+ """Return the single view whose ``accessibility_label`` matches ``matcher``; raise ``LookupError`` if not."""
191
+ return self._one("label", matcher, self.get_all_by_label(matcher, hidden=hidden))
192
+
193
+ def query_by_label(self, matcher: Matcher, *, hidden: bool = False) -> Optional[FakeView]:
194
+ """Return the first view whose ``accessibility_label`` prop matches ``matcher``, or ``None``."""
195
+ found = self.get_all_by_label(matcher, hidden=hidden)
196
+ return found[0] if found else None
197
+
198
+ def get_all_by_type(self, type_name: str, *, hidden: bool = False) -> List[FakeView]:
199
+ """Return every view of native type ``type_name`` (for example ``"Text"``)."""
200
+ return self._all(lambda v: v.type_name == type_name, hidden)
201
+
202
+ def get_by_type(self, type_name: str, *, hidden: bool = False) -> FakeView:
203
+ """Return the single view of native type ``type_name``; raise ``LookupError`` otherwise."""
204
+ return self._one("type", type_name, self.get_all_by_type(type_name, hidden=hidden))
205
+
206
+ def query_by_type(self, type_name: str, *, hidden: bool = False) -> Optional[FakeView]:
207
+ """Return the first view of native type ``type_name``, or ``None``."""
208
+ found = self.get_all_by_type(type_name, hidden=hidden)
209
+ return found[0] if found else None
210
+
211
+ # -- events ---------------------------------------------------------
212
+
213
+ def fire(self, target: Target, event: str, *args: Any) -> None:
214
+ """Dispatch ``event`` (an ``on_*`` prop name) to ``target`` and settle.
215
+
216
+ Raises:
217
+ LookupError: If no handler is registered for the event.
218
+ """
219
+ tag = target.tag if isinstance(target, FakeView) else int(target)
220
+ if not get_event_registry().has(tag, event):
221
+ raise LookupError(f"fire({target!r}, {event!r}): no handler registered\n\n{self.dump()}")
222
+ dispatch_event(tag, event, *args)
223
+ self.settle()
224
+
225
+ def press(self, target: Target) -> None:
226
+ """Fire ``on_press`` on ``target``."""
227
+ self.fire(target, "on_press")
228
+
229
+ def change_text(self, target: Target, value: str) -> None:
230
+ """Fire ``on_change`` on a ``TextInput``."""
231
+ self.fire(target, "on_change", value)
232
+
233
+ def back(self) -> bool:
234
+ """Simulate the system back action; returns whether a handler consumed it."""
235
+ consumed = bool(self.reconciler.dispatch_back_press())
236
+ self.settle()
237
+ return consumed
238
+
239
+ # -- lifecycle ------------------------------------------------------
240
+
241
+ def settle(self, timeout: float = 1.0) -> None:
242
+ """Flush pending renders and async work (see [`settle`][pythonnative.testing.settle])."""
243
+ settle(self.reconciler, timeout)
244
+
245
+ def rerender(self, element: Node) -> None:
246
+ """Reconcile a new root element (new props from outside the tree)."""
247
+ self.reconciler.reconcile(self._wrap(element))
248
+ self.settle()
249
+
250
+ def unmount(self) -> None:
251
+ """Unmount the tree, running effect cleanups and destroying every view."""
252
+ self.reconciler.unmount()
253
+
254
+ def __enter__(self) -> "RenderResult":
255
+ return self
256
+
257
+ def __exit__(self, *exc: Any) -> None:
258
+ self.unmount()
259
+
260
+
261
+ def render(
262
+ element: Node,
263
+ *,
264
+ viewport: Optional[Tuple[float, float]] = DEFAULT_VIEWPORT,
265
+ backend: Optional[FakeBackend] = None,
266
+ host: Optional[FakeHost] = None,
267
+ settle_first: bool = True,
268
+ ) -> RenderResult:
269
+ """Mount ``element`` into a [`FakeBackend`][pythonnative.testing.FakeBackend].
270
+
271
+ Args:
272
+ element: The element (or component call) to render.
273
+ viewport: Size for the layout pass; ``None`` skips layout.
274
+ backend: Reuse an existing backend (defaults to a fresh one).
275
+ host: Render under a [`HostRoot`][pythonnative.navigation.host.HostRoot]
276
+ with this fake host for focus and restoration state.
277
+ settle_first: Drain async work and effects before returning.
278
+ """
279
+ from ..reconciler import Reconciler
280
+
281
+ backend = backend if backend is not None else FakeBackend()
282
+ reconciler = Reconciler(backend)
283
+ if viewport is not None:
284
+ reconciler.set_viewport_size(float(viewport[0]), float(viewport[1]))
285
+
286
+ def wrap(node: Node) -> Element:
287
+ if host is not None:
288
+ from ..navigation.host import HostRoot
289
+
290
+ return HostRoot(node, host=host)
291
+ if isinstance(node, Element):
292
+ return node
293
+ from ..components import Fragment
294
+
295
+ return Fragment(*(node if isinstance(node, (list, tuple)) else [node]))
296
+
297
+ reconciler.mount(wrap(element))
298
+ result = RenderResult(reconciler, backend, wrap)
299
+ if settle_first:
300
+ result.settle()
301
+ return result
302
+
303
+
304
+ class HookResult(Generic[T]):
305
+ """Handle returned by [`render_hook`][pythonnative.testing.render_hook].
306
+
307
+ Attributes:
308
+ current: The hook's most recent return value.
309
+ """
310
+
311
+ def __init__(self, result: RenderResult, box: Dict[str, Any], rerender: Callable[..., None]) -> None:
312
+ self._result = result
313
+ self._box = box
314
+ self._rerender = rerender
315
+
316
+ @property
317
+ def current(self) -> T:
318
+ """The value the hook returned on its most recent render."""
319
+ return self._box["value"]
320
+
321
+ @property
322
+ def render_count(self) -> int:
323
+ """How many times the hook has run since ``render_hook`` was called."""
324
+ return self._box["renders"]
325
+
326
+ def act(self, fn: Callable[[], Any]) -> None:
327
+ """Run ``fn`` (typically a state setter) and settle."""
328
+ fn()
329
+ self._result.settle()
330
+
331
+ def rerender(self, *args: Any, **kwargs: Any) -> None:
332
+ """Re-run the hook with new arguments."""
333
+ self._rerender(*args, **kwargs)
334
+
335
+ def settle(self) -> None:
336
+ """Flush pending renders and async work started by the hook."""
337
+ self._result.settle()
338
+
339
+ def unmount(self) -> None:
340
+ """Unmount the harness component, running the hook's effect cleanups."""
341
+ self._result.unmount()
342
+
343
+
344
+ def render_hook(hook: Callable[..., T], *args: Any, host: Optional[FakeHost] = None, **kwargs: Any) -> HookResult[T]:
345
+ """Run ``hook(*args, **kwargs)`` inside a throwaway component.
346
+
347
+ ```python
348
+ result = render_hook(lambda: pn.use_state(0))
349
+ value, set_value = result.current
350
+ result.act(lambda: set_value(5))
351
+ assert result.current[0] == 5
352
+ ```
353
+ """
354
+ from ..component import component
355
+
356
+ box: Dict[str, Any] = {"value": None, "renders": 0}
357
+
358
+ @component
359
+ def Harness(*, args: Tuple[Any, ...], kwargs: Dict[str, Any]) -> None:
360
+ box["value"] = hook(*args, **kwargs)
361
+ box["renders"] += 1
362
+ return None
363
+
364
+ result = render(Harness(args=tuple(args), kwargs=dict(kwargs)), host=host)
365
+
366
+ def rerender(*new_args: Any, **new_kwargs: Any) -> None:
367
+ result.rerender(Harness(args=tuple(new_args) or tuple(args), kwargs={**kwargs, **new_kwargs}))
368
+
369
+ return HookResult(result, box, rerender)
pythonnative/utils.py ADDED
@@ -0,0 +1,145 @@
1
+ """Platform detection and shared helpers.
2
+
3
+ This module is imported early by most other modules, so it avoids
4
+ importing platform-specific packages at module level. The detection
5
+ results are cached the first time
6
+ [`IS_ANDROID`][pythonnative.utils.IS_ANDROID],
7
+ [`IS_IOS`][pythonnative.utils.IS_IOS], and
8
+ [`IS_WEB`][pythonnative.utils.IS_WEB] are read.
9
+
10
+ Attributes:
11
+ IS_ANDROID: `True` when running inside an Android process
12
+ (`sys.platform == "android"` on the embedded CPython 3.13+, or
13
+ Chaquopy's `java` module imports successfully).
14
+ IS_IOS: `True` when running inside an iOS app bundle
15
+ (`sys.platform == "ios"` on the embedded CPython 3.13+, or the
16
+ explicit `PN_PLATFORM=ios` override).
17
+ IS_WEB: `True` when running the browser preview (signaled by
18
+ `PN_PLATFORM=web`, set by ``pn preview`` / ``pn start``). The
19
+ reconciler then commits through the bridge to a browser page
20
+ instead of to Swift or Kotlin.
21
+ """
22
+
23
+ import os
24
+ import sys
25
+ from typing import Optional
26
+
27
+ # ======================================================================
28
+ # Platform detection
29
+ # ======================================================================
30
+
31
+ _is_android: Optional[bool] = None
32
+ _is_ios: Optional[bool] = None
33
+ _is_web: Optional[bool] = None
34
+
35
+
36
+ def _detect_android() -> bool:
37
+ """Return whether we're running inside an Android process.
38
+
39
+ CPython 3.13+ reports ``sys.platform == "android"`` (PEP 738); the
40
+ Chaquopy ``java`` module import is kept as a secondary signal.
41
+ """
42
+ if sys.platform == "android":
43
+ return True
44
+ try:
45
+ from java import jclass # noqa: F401
46
+
47
+ return True
48
+ except Exception:
49
+ pass
50
+ return False
51
+
52
+
53
+ def _detect_ios() -> bool:
54
+ """Detect whether we're running inside an iOS app bundle.
55
+
56
+ Signals, in priority order:
57
+
58
+ - `sys.platform == "ios"`: CPython 3.13+ reports this on both
59
+ devices and the Simulator (PEP 730), so it is the canonical
60
+ signal for the embedded runtime.
61
+ - Explicit `PN_PLATFORM=ios` env var: set by the iOS template before
62
+ Python starts as a belt-and-braces override, and by tests.
63
+
64
+ Running on macOS is never enough on its own: the browser preview
65
+ and unit tests run there and must not be mistaken for iOS.
66
+ """
67
+ if sys.platform == "ios":
68
+ return True
69
+ return os.environ.get("PN_PLATFORM") == "ios"
70
+
71
+
72
+ def _detect_web() -> bool:
73
+ """Detect whether we're running the browser preview.
74
+
75
+ The only signal is the explicit ``PN_PLATFORM=web`` env var, set by
76
+ ``pn preview`` / ``pn start`` before importing PythonNative. Web is
77
+ a *development* target: the app renders in a browser tab through
78
+ the bridge protocol so the inner dev loop doesn't require a device
79
+ build. Off-device unit tests deliberately leave this flag ``False``
80
+ so they keep using an injected fake backend and
81
+ ``Platform.OS == "test"``.
82
+ """
83
+ return os.environ.get("PN_PLATFORM") == "web"
84
+
85
+
86
+ def _ensure_platform_detection() -> None:
87
+ """Populate `_is_android` / `_is_ios` / `_is_web` once, then reuse."""
88
+ global _is_android, _is_ios, _is_web
89
+ if _is_android is None:
90
+ _is_android = _detect_android()
91
+ if _is_ios is None:
92
+ _is_ios = (not _is_android) and _detect_ios()
93
+ if _is_web is None:
94
+ _is_web = (not _is_android) and (not _is_ios) and _detect_web()
95
+
96
+
97
+ def _get_is_android() -> bool:
98
+ """Return the cached Android-detection result."""
99
+ _ensure_platform_detection()
100
+ assert _is_android is not None
101
+ return _is_android
102
+
103
+
104
+ def _get_is_ios() -> bool:
105
+ """Return the cached iOS-detection result."""
106
+ _ensure_platform_detection()
107
+ assert _is_ios is not None
108
+ return _is_ios
109
+
110
+
111
+ def _get_is_web() -> bool:
112
+ """Return the cached web-detection result."""
113
+ _ensure_platform_detection()
114
+ assert _is_web is not None
115
+ return _is_web
116
+
117
+
118
+ IS_ANDROID: bool = _get_is_android()
119
+ """``True`` when running inside an Android process.
120
+
121
+ The flag is computed once at import time, from ``sys.platform ==
122
+ "android"`` or a successful import of Chaquopy's `java` module.
123
+ """
124
+
125
+ IS_IOS: bool = _get_is_ios()
126
+ """``True`` when running inside an iOS app bundle.
127
+
128
+ The flag is computed once at import time, from ``sys.platform ==
129
+ "ios"`` or the explicit `PN_PLATFORM=ios` override.
130
+ """
131
+
132
+ IS_WEB: bool = _get_is_web()
133
+ """``True`` when running the browser preview.
134
+
135
+ Set by ``pn preview`` / ``pn start`` via ``PN_PLATFORM=web``. Mutually
136
+ exclusive with `IS_ANDROID` / `IS_IOS`. Off-device unit tests leave
137
+ this ``False`` and inject a fake backend instead.
138
+ """
139
+
140
+ IS_NATIVE: bool = IS_ANDROID or IS_IOS or IS_WEB
141
+ """``True`` whenever the reconciler commits through the bridge.
142
+
143
+ All three of iOS, Android, and the browser preview render through a
144
+ bridge transport; only headless tests have no native side at all.
145
+ """
@@ -0,0 +1,2 @@
1
+ Version: 1.13.1
2
+ Arguments: ['C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-7660rwxu\\cp313-win_amd64\\build\\venv\\Scripts\\delvewheel', 'repair', '-w', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-7660rwxu\\cp313-win_amd64\\repaired_wheel', '-v', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-7660rwxu\\cp313-win_amd64\\built_wheel\\pythonnative-0.40.0-cp313-cp313-win_amd64.whl']
@@ -0,0 +1,150 @@
1
+ Metadata-Version: 2.4
2
+ Name: pythonnative
3
+ Version: 0.40.0
4
+ Summary: Cross-platform native UI toolkit for Android and iOS
5
+ Author: Owen Carey
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Owen Carey
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in
18
+ all copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26
+ THE SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/pythonnative/pythonnative
29
+ Project-URL: Repository, https://github.com/pythonnative/pythonnative
30
+ Project-URL: Issues, https://github.com/pythonnative/pythonnative/issues
31
+ Project-URL: Documentation, https://pythonnative.com/
32
+ Classifier: Development Status :: 2 - Pre-Alpha
33
+ Classifier: Intended Audience :: Developers
34
+ Classifier: License :: OSI Approved :: MIT License
35
+ Classifier: Programming Language :: Python :: 3
36
+ Classifier: Programming Language :: Python :: 3 :: Only
37
+ Classifier: Programming Language :: Python :: 3.13
38
+ Classifier: Programming Language :: Python :: 3.14
39
+ Classifier: Topic :: Software Development :: User Interfaces
40
+ Requires-Python: >=3.13
41
+ Description-Content-Type: text/markdown
42
+ License-File: LICENSE
43
+ Requires-Dist: requests>=2.31.0
44
+ Provides-Extra: build
45
+ Requires-Dist: Pillow>=10.0; extra == "build"
46
+ Dynamic: license-file
47
+
48
+ <p align="center">
49
+ <img src="docs/assets/banner.jpg" alt="PythonNative" width="800" />
50
+ </p>
51
+
52
+ <p align="center">
53
+ <em>Build native Android and iOS apps in Python.</em>
54
+ </p>
55
+
56
+ <p align="center">
57
+ <a href="https://github.com/pythonnative/pythonnative/actions/workflows/ci.yml"><img src="https://github.com/pythonnative/pythonnative/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
58
+ <a href="https://github.com/pythonnative/pythonnative/actions/workflows/release.yml"><img src="https://github.com/pythonnative/pythonnative/actions/workflows/release.yml/badge.svg" alt="Release" /></a>
59
+ <a href="https://pypi.org/project/pythonnative/"><img src="https://img.shields.io/pypi/v/pythonnative" alt="PyPI Version" /></a>
60
+ <a href="https://pypi.org/project/pythonnative/"><img src="https://img.shields.io/pypi/pyversions/pythonnative" alt="Python Versions" /></a>
61
+ <a href="LICENSE"><img src="https://img.shields.io/pypi/l/pythonnative" alt="License: MIT" /></a>
62
+ <a href="https://pythonnative.com/"><img src="https://img.shields.io/website?url=https%3A%2F%2Fpythonnative.com&label=docs" alt="Docs" /></a>
63
+ </p>
64
+
65
+ <p align="center">
66
+ <a href="https://pythonnative.com/">Documentation</a> ·
67
+ <a href="https://pythonnative.com/getting-started/">Getting Started</a> ·
68
+ <a href="https://pythonnative.com/examples/">Examples</a> ·
69
+ <a href="CONTRIBUTING.md">Contributing</a>
70
+ </p>
71
+
72
+ ---
73
+
74
+ ## Overview
75
+
76
+ PythonNative is a cross-platform toolkit for building native Android and iOS apps in Python. It provides a **declarative, React-like component model** with hooks and automatic reconciliation on top of a **native rendering core** written in Swift and Kotlin. Write function components with `use_state`, `use_effect`, and friends, just like React, and let PythonNative handle creating and updating native views.
77
+
78
+ ## Features
79
+
80
+ - **Declarative UI:** Describe *what* your UI should look like with element functions (`Text`, `Button`, `Column`, `Row`, etc.). PythonNative creates and updates native views automatically.
81
+ - **Rich component library:** 25+ built-in components backed by real native widgets: `TextInput`, `Image` / `ImageBackground`, `ScrollView`, `FlatList` / `SectionList`, `Modal`, `Pressable` / `TouchableOpacity`, `Switch` / `Checkbox`, `Slider`, `SegmentedControl`, `Picker`, `DatePicker`, `ProgressBar` / `ActivityIndicator`, `WebView`, and more.
82
+ - **Device APIs:** Cross-platform modules for `Camera`, `Location`, `FileSystem`, `Notifications`, `Clipboard`, `Share`, `Linking`, `Permissions`, `AppState`, `NetInfo`, `SecureStore`, `Battery`, `Haptics` / `Vibration`, and `Biometrics`, plus reactive `use_app_state` and `use_net_info` hooks.
83
+ - **Hooks and function components:** Manage state with `use_state`, side effects with `use_effect` / `use_layout_effect`, refs and imperative handles with `use_ref` / `use_imperative_handle`, and navigation with `use_navigation`, all through one consistent pattern. Components can return a single element, a list of siblings, or `None`, and `Fragment`, `Portal`, and reactive `Provider` context work the way they do in React.
84
+ - **Async-first rendering:** One `asyncio` event loop runs the whole framework on the platform's main thread. Components can be `async def` and `await` data directly in the body; `Suspense` boundaries show declarative loading states while they wait. `use_resource` fetches during render, `use_effect` accepts coroutine callbacks (cancelled automatically on unmount), `lazy` code-splits components, and `use_transition` / `use_deferred_value` keep the UI responsive during expensive updates.
85
+ - **Developer feedback that finds your bugs:** In dev mode (`pn start`, `pn preview`, debug builds from `pn run`, or `PN_DEV=1`), uncaught errors from renders, effects, and event handlers show a full-screen RedBox with the traceback; unknown style keys and duplicate list keys print "did you mean" warnings; and conditional hooks raise a `HookOrderError` at the source instead of silently cross-wiring state.
86
+ - **Typed `style` prop and theme:** Pass all visual and layout properties through a single `style` dict, fully described by the `pn.Style` `TypedDict` and the ergonomic `pn.style(...)` helper for IDE autocomplete and static checking. Compose reusable styles with `StyleSheet`, and read design tokens from a typed, immutable `pn.Theme` via `use_theme()` that follows light and dark mode by default.
87
+ - **Cross-platform flexbox engine:** A pure-Python, Yoga-style layout engine computes frames once and applies them to native views, so `flex`, `padding`, `aspect_ratio`, and `position: "absolute"` produce the same geometry on Android and iOS.
88
+ - **Virtual view tree + reconciler:** Element trees are diffed and patched with minimal native mutations, similar to React's reconciliation. Each commit lands as **one batched transaction** of mutation ops, and event callbacks are routed through a tag-based registry so re-renders that only change closures cost zero native calls. State updates re-render **locally**: only the component whose state changed (and its subtree) re-runs, and unchanged leaves reuse cached intrinsic measurements, so deep UIs stay responsive instead of re-rendering the whole app from the root on every tap.
89
+ - **Native-driven animations:** The `Animated` API (timing / spring / decay / loop / stagger, awaitable or fire-and-forget) hands animations to Core Animation and `ViewPropertyAnimator` whenever possible, so no Python code runs per frame; a pure-Python ticker covers the rest. `interpolate`, arithmetic operators on animated nodes, `Animated.event` scroll binding, and `diff_clamp` cover the scroll-driven patterns (collapsing headers, parallax) that define native feel.
90
+ - **Native gesture system:** Attach `Tap`, `LongPress`, `Pan`, `Swipe`, `Fling`, `Pinch`, and `Rotation` recognizers to any view via the `gestures=` prop, backed by `UIGestureRecognizer` on iOS and a unit-testable pure-Python arbiter on Android and in the browser preview. Compose them with `Race`, `Exclusive`, and `Simultaneous` for cross-gesture arbitration (single vs. double tap, drag vs. long press).
91
+ - **Virtualized lists:** `FlatList` / `SectionList` window their rows in Python over the platform scroll view: uniform, exact, or measured variable heights, grids, headers/footers, infinite scroll, and an imperative scroll controller, identical on every platform.
92
+ - **Native rendering core:** each commit is one serialized transaction applied by Swift and Kotlin component managers, the same shape as React Native's Fabric. Device APIs are native modules registered by name (TurboModules-style), callable from thin Python facades.
93
+ - **Custom-component SDK:** Wrap any platform widget as a first-class element with type-checked props via `pythonnative.sdk` (`Props`, `@native_component`, `element_factory`). Plugins distributed on PyPI auto-register through the `pythonnative.handlers` entry-point group.
94
+ - **Metro-style dev loop:** `pn start` runs one dev server that serves the browser preview and every connected debug build. Save a file and each client Fast Refreshes in place, keeping component state; their `print` output and tracebacks stream back into the same terminal. `pn run android` / `pn run ios` bakes the server URL into a debug build and rebuilds the native project only when a native input actually changed, so relaunching after a Python edit takes seconds, not minutes.
95
+ - **PyPI packages, binary wheels included:** List requirements in `pythonnative.toml` and the CLI resolves them for the *device* (iOS wheels via PEP 730 and BeeWare's index, Android wheels via PEP 738 and Chaquopy), bundling numpy, Pillow, cryptography, and friends alongside pure-Python packages. `pn deps` reports what each target resolves to before you build, and a weekly-checked compatibility matrix keeps the docs honest.
96
+ - **Browser preview:** `pn preview` renders your app in a browser tab inside a phone frame (pick a device, rotate, toggle dark mode) with Fast Refresh on every save. The page is a bridge peer exactly like the Swift and Kotlin runtimes, so the reconciler, hooks, layout engine, navigation, and screen host are the same code that ships to the phone; only the leaf widgets are DOM elements.
97
+ - **Native-backed navigation:** Declarative `Stack`, `Tab`, and `Drawer` navigators inspired by React Navigation. The root stack drives the platform's native navigation controller (`UINavigationController` on iOS, AndroidX Navigation Component on Android), so transitions, back gestures, and the hardware back button match what users expect; `use_back_handler` intercepts the back action when a screen needs to.
98
+ - **Dev client:** Build a shell app once with `pn run ios --dev-client` and point it at any project's dev server from a connect screen, the way Expo Go does; physical phones on the same Wi-Fi get the same Fast Refresh as simulators.
99
+ - **Bundled templates:** Android Gradle and iOS Xcode templates are included, so scaffolding requires no network access.
100
+
101
+ ## Quick Start
102
+
103
+ ### Installation
104
+
105
+ Requires Python 3.13 or newer.
106
+
107
+ ```bash
108
+ pip install pythonnative
109
+ ```
110
+
111
+ ### Usage
112
+
113
+ ```python
114
+ import pythonnative as pn
115
+
116
+
117
+ @pn.component
118
+ def App():
119
+ count, set_count = pn.use_state(0)
120
+ return pn.Column(
121
+ pn.Text(f"Count: {count}", style=pn.style(font_size=24, bold=True)),
122
+ pn.Button(
123
+ "Tap me",
124
+ on_press=lambda: set_count(count + 1),
125
+ ),
126
+ style=pn.style(spacing=12, padding=16),
127
+ )
128
+ ```
129
+
130
+ ### Develop
131
+
132
+ ```bash
133
+ pn init my-app && cd my-app
134
+ pn preview # dev server + browser preview with Fast Refresh
135
+ pn run ios # in another terminal: debug build that connects to the same server
136
+ pn run android
137
+ pn build ios # standalone release artifacts
138
+ ```
139
+
140
+ ## Documentation
141
+
142
+ Visit [pythonnative.com](https://pythonnative.com/) for the full documentation, including getting started guides, platform-specific instructions for Android and iOS, API reference, and working examples.
143
+
144
+ ## Contributing
145
+
146
+ Contributions are welcome. Please see [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions, coding standards, and guidelines for submitting pull requests.
147
+
148
+ ## License
149
+
150
+ [MIT](LICENSE)