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,78 @@
1
+ """Portable animation expressions evaluated by the native UI thread."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+
8
+ def serialize(root: Any) -> dict[str, Any]:
9
+ """Serialize one connected animation graph in dependency order."""
10
+ from .animated import AnimatedInterpolation, AnimatedNode, AnimatedValue, _AnimatedDiffClamp, _AnimatedOperation
11
+
12
+ connected: dict[int, Any] = {}
13
+
14
+ def discover(node: Any) -> None:
15
+ if not isinstance(node, AnimatedNode) or id(node) in connected:
16
+ return
17
+ connected[id(node)] = node
18
+ for child in list(node._children):
19
+ discover(child)
20
+ for parent in getattr(node, "_parents", [getattr(node, "_parent", None)]):
21
+ discover(parent)
22
+
23
+ discover(root)
24
+ encoded: dict[int, dict[str, Any]] = {}
25
+
26
+ def encode(node: Any) -> Any:
27
+ if not isinstance(node, AnimatedNode):
28
+ return {"constant": float(node)}
29
+ identity = id(node)
30
+ if identity not in encoded:
31
+ definition: dict[str, Any] = {"id": identity}
32
+ if isinstance(node, AnimatedValue):
33
+ definition.update(kind="value", value=node.value)
34
+ elif isinstance(node, AnimatedInterpolation):
35
+ definition.update(
36
+ kind="interpolate",
37
+ inputs=[encode(node._parent)],
38
+ ranges=node._inputs,
39
+ outputs=node._outputs,
40
+ color=node._kind == "color",
41
+ left=node._left,
42
+ right=node._right,
43
+ )
44
+ elif isinstance(node, _AnimatedOperation):
45
+ definition.update(kind=node._op, inputs=[encode(parent) for parent in node._parents])
46
+ elif isinstance(node, _AnimatedDiffClamp):
47
+ definition.update(
48
+ kind="diff_clamp",
49
+ inputs=[encode(node._parent)],
50
+ minimum=node._min,
51
+ maximum=node._max,
52
+ previous=node._last_input,
53
+ value=node.value,
54
+ )
55
+ else:
56
+ raise TypeError(f"Unsupported animated node {type(node).__name__}")
57
+ encoded[identity] = definition
58
+ return {"node": identity}
59
+
60
+ for node in connected.values():
61
+ encode(node)
62
+ bindings = [[tag, prop, id(node)] for node in connected.values() for tag, prop in node.attachments()]
63
+ return {"id": min(connected), "nodes": list(encoded.values()), "bindings": bindings}
64
+
65
+
66
+ def install(node: Any, *, detached_tag: int | None = None) -> dict[str, Any] | None:
67
+ """Synchronize native graph ownership when a binding is attached or removed."""
68
+ from .animated import _backend
69
+
70
+ backend = _backend()
71
+ handler = getattr(backend, "install_animation_graph", None)
72
+ if handler is None:
73
+ return None
74
+ graph = serialize(node)
75
+ tag = graph["bindings"][0][0] if graph["bindings"] else detached_tag
76
+ if tag is not None:
77
+ handler(tag, graph)
78
+ return graph
@@ -0,0 +1,124 @@
1
+ """System color-scheme (light / dark mode) tracking.
2
+
3
+ The platform screen host publishes the operating system's current
4
+ appearance here (Android: ``Configuration.uiMode``; iOS:
5
+ ``UITraitCollection.userInterfaceStyle``), and components read it back
6
+ through [`use_color_scheme`][pythonnative.use_color_scheme] or
7
+ [`use_theme`][pythonnative.use_theme], both of which re-render when
8
+ the scheme changes.
9
+
10
+ Apps can also *override* the scheme (e.g. an in-app appearance
11
+ setting) with [`set_color_scheme`][pythonnative.appearance.set_color_scheme];
12
+ the override wins over the system value until cleared with ``None``.
13
+
14
+ Example:
15
+ >>> from pythonnative import appearance
16
+ >>> appearance.get_color_scheme()
17
+ 'light'
18
+ >>> appearance.set_color_scheme("dark") # app-level override
19
+ >>> appearance.get_color_scheme()
20
+ 'dark'
21
+ >>> appearance.set_color_scheme(None) # follow the system again
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import threading
27
+ from typing import Callable, List, Literal, Optional
28
+
29
+ ColorScheme = Literal["light", "dark"]
30
+ """The two supported appearance values."""
31
+
32
+ _system_scheme: str = "light"
33
+ _override_scheme: Optional[str] = None
34
+
35
+ _subscribers: List[Callable[[], None]] = []
36
+ _subscribers_lock = threading.Lock()
37
+
38
+
39
+ def _notify_subscribers() -> None:
40
+ """Invoke every registered subscriber, swallowing exceptions."""
41
+ with _subscribers_lock:
42
+ callbacks = list(_subscribers)
43
+ for cb in callbacks:
44
+ try:
45
+ cb()
46
+ except Exception:
47
+ pass
48
+
49
+
50
+ def subscribe(callback: Callable[[], None]) -> Callable[[], None]:
51
+ """Register ``callback`` to fire whenever the effective scheme changes.
52
+
53
+ Returns an unsubscribe function. Threadsafe.
54
+ """
55
+ with _subscribers_lock:
56
+ _subscribers.append(callback)
57
+
58
+ def _unsub() -> None:
59
+ with _subscribers_lock:
60
+ try:
61
+ _subscribers.remove(callback)
62
+ except ValueError:
63
+ pass
64
+
65
+ return _unsub
66
+
67
+
68
+ def _coerce(scheme: object) -> Optional[str]:
69
+ if scheme in ("light", "dark"):
70
+ return str(scheme)
71
+ return None
72
+
73
+
74
+ def set_system_color_scheme(scheme: str) -> None:
75
+ """Publish the operating system's current scheme.
76
+
77
+ Called by the platform screen host on create/resume and whenever
78
+ the system reports an appearance change. Invalid values are
79
+ ignored. Subscribers are only notified when the *effective* scheme
80
+ (after any app override) actually changes.
81
+ """
82
+ global _system_scheme
83
+ coerced = _coerce(scheme)
84
+ if coerced is None or coerced == _system_scheme:
85
+ return
86
+ effective_before = get_color_scheme()
87
+ _system_scheme = coerced
88
+ if get_color_scheme() != effective_before:
89
+ _notify_subscribers()
90
+
91
+
92
+ def set_color_scheme(scheme: Optional[str]) -> None:
93
+ """Set (or clear) the app-level scheme override.
94
+
95
+ Args:
96
+ scheme: ``"light"`` or ``"dark"`` to force that appearance
97
+ regardless of the system setting, or ``None`` to follow
98
+ the system again.
99
+ """
100
+ global _override_scheme
101
+ coerced = _coerce(scheme) if scheme is not None else None
102
+ if scheme is not None and coerced is None:
103
+ return
104
+ effective_before = get_color_scheme()
105
+ _override_scheme = coerced
106
+ if get_color_scheme() != effective_before:
107
+ _notify_subscribers()
108
+
109
+
110
+ def get_color_scheme() -> str:
111
+ """Return the effective scheme: the app override if set, else the system value."""
112
+ return _override_scheme if _override_scheme is not None else _system_scheme
113
+
114
+
115
+ def get_system_color_scheme() -> str:
116
+ """Return the system-reported scheme, ignoring any app override."""
117
+ return _system_scheme
118
+
119
+
120
+ def reset_color_scheme() -> None:
121
+ """Reset to system ``"light"`` with no override. Intended for tests."""
122
+ global _system_scheme, _override_scheme
123
+ _system_scheme = "light"
124
+ _override_scheme = None
@@ -0,0 +1,100 @@
1
+ """Entry point the native app templates run right after Python starts.
2
+
3
+ Both templates execute one line of Python once the interpreter is up:
4
+
5
+ ```python
6
+ import pythonnative.bootstrap; pythonnative.bootstrap.start()
7
+ ```
8
+
9
+ [`start`][pythonnative.bootstrap.start] connects the two halves of the
10
+ bridge (installing the native -> Python callback on iOS), verifies the
11
+ protocol version, routes ``print()`` to the console on iOS, warms the
12
+ asyncio runtime, and, in debug builds, starts the dev client that syncs
13
+ sources from ``pn start``. From then on the native runtime drives
14
+ everything through ``callback("host", ...)``; see ``docs/concepts/bridge.md``.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import os
20
+ import sys
21
+ import traceback
22
+ from typing import Any, Dict
23
+
24
+ __all__ = ["start", "status"]
25
+
26
+ _started: Dict[str, Any] = {}
27
+
28
+
29
+ def start(dev: bool = False, strict: bool = False) -> Dict[str, Any]:
30
+ """Connect the bridge and prepare the runtime.
31
+
32
+ Args:
33
+ dev: Enable dev mode (RedBox, validation warnings, the dev
34
+ client). Debug templates pass ``True``.
35
+ strict: Re-raise the failure after recording it. The templates
36
+ pass ``True`` so a broken bridge surfaces as a bootstrap
37
+ error screen with the full traceback.
38
+
39
+ Returns:
40
+ A status dict (``{"protocol": 2, "platform": "ios"}``) that the
41
+ template logs. Unless ``strict`` is set this never raises:
42
+ failures are printed and reported in the dict under
43
+ ``"error"``.
44
+ """
45
+ global _started
46
+ if _started and "error" not in _started:
47
+ return dict(_started)
48
+ status_: Dict[str, Any] = {"platform": None, "protocol": None}
49
+ try:
50
+ from .utils import IS_ANDROID, IS_IOS
51
+
52
+ status_["platform"] = "ios" if IS_IOS else "android" if IS_ANDROID else "off-device"
53
+ if IS_IOS:
54
+ try:
55
+ from . import _ios_log
56
+
57
+ _ios_log.install()
58
+ except Exception:
59
+ pass
60
+ from .runtime import start as start_runtime
61
+
62
+ start_runtime()
63
+ from .sdk.schema import load_bundled_contracts
64
+
65
+ load_bundled_contracts()
66
+ from . import bridge
67
+
68
+ status_["protocol"] = bridge.handshake()
69
+ dev_mode = bool(dev or os.environ.get("PN_DEV") in ("1", "true"))
70
+ if dev_mode:
71
+ from . import diagnostics
72
+
73
+ diagnostics.set_dev_mode(True)
74
+ # Import the view backend eagerly: on a slow device the first
75
+ # commit shouldn't also pay for importing the reconciler.
76
+ from .native_views import get_registry
77
+
78
+ get_registry()
79
+ if dev_mode:
80
+ # Debug builds are dev clients: connect to `pn start` when
81
+ # the build (or a remembered connection) names a server.
82
+ from . import devclient
83
+
84
+ client = devclient.start_if_configured()
85
+ status_["dev_server"] = client.url if client is not None else None
86
+ except Exception as exc:
87
+ status_["error"] = f"{type(exc).__name__}: {exc}"
88
+ print(f"[pn.bootstrap] start failed: {exc!r}", file=sys.stderr)
89
+ traceback.print_exc()
90
+ _started = status_
91
+ if strict:
92
+ raise
93
+ return dict(status_)
94
+ _started = status_
95
+ return dict(status_)
96
+
97
+
98
+ def status() -> Dict[str, Any]:
99
+ """Return the result of the last [`start`][pythonnative.bootstrap.start] (empty before it ran)."""
100
+ return dict(_started)
@@ -0,0 +1,302 @@
1
+ """The native bridge: one channel between Python and Swift / Kotlin.
2
+
3
+ Everything that crosses into native code goes through a
4
+ [`Transport`][pythonnative.bridge.Transport] (``apply`` a transaction,
5
+ ``measure`` a view, run a ``command``, drive an ``animate`` request, or
6
+ ``call`` a native module), and everything native sends back arrives at
7
+ [`native_callback`][pythonnative.bridge.native_callback]. The protocol
8
+ is documented in ``docs/concepts/bridge.md``.
9
+
10
+ Under ``pn preview`` the native side is a browser page, reached through
11
+ [`WebTransport`][pythonnative.bridge.web.WebTransport]; the preview
12
+ installs it with [`set_transport`][pythonnative.bridge.set_transport]
13
+ before any screen mounts. In headless tests there is no transport at
14
+ all: native modules fall back to their Python implementations, and
15
+ tests that want to exercise the bridge itself install a
16
+ [`FakeTransport`][pythonnative.bridge.fake.FakeTransport].
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import threading
22
+ from typing import Callable, Optional, Protocol, Tuple
23
+
24
+ from . import codec
25
+
26
+ __all__ = [
27
+ "PROTOCOL_VERSION",
28
+ "Transport",
29
+ "get_transport",
30
+ "has_transport",
31
+ "handshake",
32
+ "native_callback",
33
+ "set_transport",
34
+ ]
35
+
36
+ from .commits import PROTOCOL_VERSION
37
+
38
+ """Bridge protocol version this Python package speaks."""
39
+
40
+
41
+ class Transport(Protocol):
42
+ """The Python -> native half of the bridge."""
43
+
44
+ name: str
45
+
46
+ def protocol_version(self) -> int:
47
+ """Return the protocol version compiled into the native library."""
48
+
49
+ def apply(self, transaction_json: str) -> str:
50
+ """Apply one serialized transaction (a JSON array of ops)."""
51
+
52
+ def measure(self, tag: int, max_width: float, max_height: float) -> Tuple[float, float]:
53
+ """Return the intrinsic ``(width, height)`` of the view ``tag`` under the constraints."""
54
+
55
+ def command(self, tag: int, name: str, args_json: str) -> Optional[str]:
56
+ """Run an imperative command on one view; returns its JSON result or ``None``."""
57
+
58
+ def animate(self, tag: int, request_json: str) -> Optional[str]:
59
+ """Handle an animation request (``set`` / ``start`` / ``cancel``) for one view."""
60
+
61
+ def call(self, module: str, method: str, args_json: str) -> Optional[str]:
62
+ """Call a native module method with a ``{"call_id", "args"}`` envelope."""
63
+
64
+ def set_callback(self, callback: Callable[[str, int, str, str], Optional[str]]) -> None:
65
+ """Install ``callback`` as the native -> Python entry point."""
66
+
67
+
68
+ # ======================================================================
69
+ # Transport selection
70
+ # ======================================================================
71
+
72
+ _transport: Optional[Transport] = None
73
+ _transport_lock = threading.Lock()
74
+ _explicit = False
75
+
76
+
77
+ def _create_platform_transport() -> Optional[Transport]:
78
+ from ..utils import IS_ANDROID, IS_IOS, IS_WEB
79
+
80
+ if IS_IOS:
81
+ from .ios import IOSTransport
82
+
83
+ transport: Transport = IOSTransport()
84
+ transport.set_callback(native_callback)
85
+ return transport
86
+ if IS_ANDROID:
87
+ from .android import AndroidTransport
88
+
89
+ return AndroidTransport()
90
+ if IS_WEB:
91
+ raise RuntimeError(
92
+ "PN_PLATFORM=web is set but no browser preview transport is installed. "
93
+ "Start the app with `pn preview` (or `pn start`), which installs the WebTransport."
94
+ )
95
+ return None
96
+
97
+
98
+ def get_transport() -> Transport:
99
+ """Return the active transport, creating the platform one on first use.
100
+
101
+ Raises:
102
+ RuntimeError: Off-device, where no native runtime exists.
103
+ """
104
+ global _transport
105
+ if _transport is not None:
106
+ return _transport
107
+ with _transport_lock:
108
+ if _transport is None:
109
+ created = _create_platform_transport()
110
+ if created is None:
111
+ raise RuntimeError(
112
+ "No native bridge is available on this platform (running off-device). "
113
+ "Use `pn preview` for the browser renderer or install a FakeTransport in tests."
114
+ )
115
+ _transport = created
116
+ return _transport
117
+
118
+
119
+ def has_transport() -> bool:
120
+ """Whether a transport exists or can be created without raising."""
121
+ if _transport is not None:
122
+ return True
123
+ if _explicit:
124
+ return False
125
+ from ..utils import IS_ANDROID, IS_IOS, IS_WEB
126
+
127
+ return bool(IS_IOS or IS_ANDROID or IS_WEB)
128
+
129
+
130
+ def set_transport(transport: Optional[Transport]) -> None:
131
+ """Install a transport explicitly (tests) or reset with ``None``."""
132
+ global _transport, _explicit
133
+ with _transport_lock:
134
+ _transport = transport
135
+ _explicit = transport is not None
136
+ if transport is not None:
137
+ transport.set_callback(native_callback)
138
+
139
+
140
+ def handshake() -> int:
141
+ """Verify the native library speaks our protocol version.
142
+
143
+ Called by the native templates right after Python starts. Returns
144
+ the negotiated version.
145
+
146
+ Raises:
147
+ RuntimeError: On a version mismatch, with a hint to rebuild.
148
+ """
149
+ version = get_transport().protocol_version()
150
+ if version != PROTOCOL_VERSION:
151
+ raise RuntimeError(
152
+ f"Bridge protocol mismatch: the native runtime speaks v{version} but pythonnative "
153
+ f"expects v{PROTOCOL_VERSION}. Re-run 'pn build' so the staged template matches the "
154
+ "installed pythonnative package."
155
+ )
156
+ if getattr(get_transport(), "name", "") in {"ios", "android"}:
157
+ from ..sdk.schema import fingerprint
158
+
159
+ reply = codec.loads(get_transport().call("Runtime", "capabilities", codec.dumps({"id": 0, "args": {}})))
160
+ capabilities = reply.get("value", {}) if isinstance(reply, dict) else {}
161
+ if capabilities.get("schema") != fingerprint() or capabilities.get("yoga") != "3.2.1":
162
+ raise RuntimeError("Native component contracts changed. Rebuild the app with 'pn run'.")
163
+ return version
164
+
165
+
166
+ # ======================================================================
167
+ # native -> Python
168
+ # ======================================================================
169
+
170
+
171
+ # Callback threads coalesce continuous input before the application loop drains.
172
+ _continuous: dict[tuple[int, str], list[str]] = {}
173
+
174
+
175
+ def _deliver_continuous(tag: int, name: str, slot: list[str]) -> None:
176
+ if _continuous.get((tag, name)) is slot:
177
+ _continuous.pop((tag, name), None)
178
+ native_callback("event", tag, name, slot[0])
179
+
180
+
181
+ def native_callback(kind: str, tag: int, name: str, payload: str) -> Optional[str]:
182
+ """Single entry point for every native -> Python message.
183
+
184
+ Args:
185
+ kind: ``"event"``, ``"module"``, ``"host"``, ``"animation"``,
186
+ or ``"pump"``.
187
+ tag: View tag (events), screen id (host), otherwise ``0``.
188
+ name: Event name, module name, or host event.
189
+ payload: JSON text whose shape depends on ``kind``.
190
+
191
+ Returns:
192
+ A JSON string for request-style messages (a handler's return
193
+ value, ``"true"`` / ``"false"`` for ``back_pressed``), else
194
+ ``None``. Never raises: failures are reported through
195
+ ``diagnostics`` so nothing propagates into UIKit or the
196
+ Android looper.
197
+ """
198
+ from ..runtime import _on_loop_thread, get_loop
199
+
200
+ loop = get_loop()
201
+ if loop.is_running() and not _on_loop_thread(loop):
202
+ if kind == "event" and name in {"on_scroll", "on_selection_change", "on_gesture_update"}:
203
+ key = (tag, name)
204
+ slot = _continuous.get(key)
205
+ if slot is None:
206
+ slot = [payload]
207
+ _continuous[key] = slot
208
+ loop.call_soon_threadsafe(_deliver_continuous, tag, name, slot)
209
+ else:
210
+ slot[0] = payload
211
+ else:
212
+ _continuous.clear()
213
+ loop.call_soon_threadsafe(native_callback, kind, tag, name, payload)
214
+ return None
215
+ try:
216
+ if kind == "layout":
217
+ from ..native_views import get_registry
218
+
219
+ backend = get_registry()
220
+ if backend.on_layout is not None:
221
+ backend.on_layout(codec.loads(payload))
222
+ return None
223
+ if kind == "event":
224
+ return _on_event(int(tag), name, payload)
225
+ if kind == "module":
226
+ from ..native_modules.registry import dispatch_module_message
227
+
228
+ dispatch_module_message(name, codec.loads(payload) or {})
229
+ return None
230
+ if kind == "host":
231
+ from ..hosts.native import dispatch_host_event
232
+
233
+ return dispatch_host_event(int(tag), name, codec.loads(payload))
234
+ if kind == "animation":
235
+ from ..animated import native_animation_completed
236
+
237
+ data = codec.loads(payload) or {}
238
+ native_animation_completed(int(data.get("id", 0)), bool(data.get("finished", True)))
239
+ return None
240
+ print(f"[pn.bridge] unknown callback kind {kind!r}")
241
+ except Exception as exc:
242
+ from .. import diagnostics
243
+
244
+ if not diagnostics.report_error(exc, phase=f"bridge {kind}:{name}"):
245
+ import traceback
246
+
247
+ traceback.print_exc()
248
+ return None
249
+
250
+
251
+ def _on_event(tag: int, name: str, payload: str) -> Optional[str]:
252
+ from ..events import get_event_registry
253
+
254
+ args = codec.loads(payload)
255
+ from ..native_views import get_registry
256
+
257
+ backend = get_registry()
258
+ accept = getattr(backend, "accept_event", None)
259
+ if accept is not None:
260
+ if not accept(tag, name, args):
261
+ return None
262
+ args = args["args"]
263
+ if args is None:
264
+ args = []
265
+ elif not isinstance(args, list):
266
+ args = [args]
267
+ callback = get_event_registry().get(tag, name)
268
+ if callback is None:
269
+ from ..native_views import get_registry
270
+
271
+ backend = get_registry()
272
+ internal = getattr(backend, "handle_internal_event", None)
273
+ if internal is not None:
274
+ result = internal(tag, name, args)
275
+ return None if result is None else codec.dumps(codec.to_jsonable(result))
276
+ return None
277
+ try:
278
+ result = get_event_registry().invoke(tag, name, *args)
279
+ except Exception as exc:
280
+ from .. import diagnostics
281
+
282
+ if not diagnostics.report_error(exc, phase=f"event {name!r}"):
283
+ import traceback
284
+
285
+ traceback.print_exc()
286
+ return None
287
+ import inspect
288
+
289
+ if result is None or inspect.isawaitable(result):
290
+ return None
291
+ try:
292
+ return codec.dumps(codec.to_jsonable(result))
293
+ except (TypeError, ValueError):
294
+ return None
295
+
296
+
297
+ def _reset_for_tests() -> None:
298
+ """Drop the transport for test isolation."""
299
+ global _transport, _explicit
300
+ with _transport_lock:
301
+ _transport = None
302
+ _explicit = False
@@ -0,0 +1,78 @@
1
+ """Android transport: the ``com.pythonnative.runtime.PNBridge`` class via Chaquopy.
2
+
3
+ ``PNBridge`` is the only Java class Python touches. Its static methods
4
+ mirror the C entry points used on iOS (see ``docs/concepts/bridge.md``).
5
+ The reverse direction (native -> Python) is installed by the template's
6
+ ``MainActivity``, which implements ``PythonHost`` by calling
7
+ [`pythonnative.bridge.native_callback`][pythonnative.bridge.native_callback]
8
+ through Chaquopy; this transport therefore has nothing to register.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from typing import Any, Callable, Optional, Tuple
14
+
15
+ __all__ = ["AndroidTransport"]
16
+
17
+ BRIDGE_CLASS = "com.pythonnative.runtime.PNBridge"
18
+
19
+
20
+ class AndroidTransport:
21
+ """Thin wrapper over the static ``PNBridge`` methods."""
22
+
23
+ name = "android"
24
+
25
+ def __init__(self, bridge_class: Any = None) -> None:
26
+ if bridge_class is None:
27
+ from java import jclass
28
+
29
+ try:
30
+ bridge_class = jclass(BRIDGE_CLASS)
31
+ except Exception as exc:
32
+ raise RuntimeError(
33
+ f"{BRIDGE_CLASS} is not on the classpath. Rebuild the app with 'pn run android' or "
34
+ "'pn build android' so the pythonnative Gradle module is included."
35
+ ) from exc
36
+ self._bridge = bridge_class
37
+
38
+ def protocol_version(self) -> int:
39
+ """Return the protocol version compiled into the native library."""
40
+ return int(self._bridge.protocolVersion())
41
+
42
+ def apply(self, transaction_json: str) -> str:
43
+ """Apply one serialized transaction (a JSON array of ops)."""
44
+ return str(self._bridge.apply(transaction_json))
45
+
46
+ def measure(self, tag: int, max_width: float, max_height: float) -> Tuple[float, float]:
47
+ """Return the intrinsic ``(width, height)`` of the view ``tag`` under the constraints."""
48
+ packed = self._bridge.measure(int(tag), float(max_width), float(max_height))
49
+ if not packed:
50
+ return (0.0, 0.0)
51
+ text = str(packed)
52
+ w, _, h = text.partition(",")
53
+ try:
54
+ return (float(w), float(h))
55
+ except ValueError:
56
+ return (0.0, 0.0)
57
+
58
+ def command(self, tag: int, name: str, args_json: str) -> Optional[str]:
59
+ """Run an imperative command on one view; returns its JSON result or ``None``."""
60
+ return _opt_str(self._bridge.command(int(tag), name, args_json))
61
+
62
+ def animate(self, tag: int, request_json: str) -> Optional[str]:
63
+ """Handle an animation request (``set`` / ``start`` / ``cancel``) for one view."""
64
+ return _opt_str(self._bridge.animate(int(tag), request_json))
65
+
66
+ def call(self, module: str, method: str, args_json: str) -> Optional[str]:
67
+ """Call a native module method with a ``{"call_id", "args"}`` envelope."""
68
+ return _opt_str(self._bridge.call(module, method, args_json))
69
+
70
+ def set_callback(self, callback: Callable[[str, int, str, str], Optional[str]]) -> None:
71
+ """No-op: the Android template installs the host through ``PNBridge.setHost``."""
72
+ del callback
73
+
74
+
75
+ def _opt_str(value: Any) -> Optional[str]:
76
+ if value is None:
77
+ return None
78
+ return str(value)