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,63 @@
1
+ """Screen hosts: the bridge between a native screen and the reconciler.
2
+
3
+ On every bridge platform (iOS, Android, and the browser preview) the
4
+ native runtime creates screens through the bridge
5
+ (``callback("host", screen_id, "create", {...})``), which lands in
6
+ [`NativeScreenHost`][pythonnative.hosts.native.NativeScreenHost]. Unit
7
+ tests use the headless base [`ScreenHost`][pythonnative.hosts.ScreenHost]
8
+ with a fake backend, created through
9
+ [`create_screen`][pythonnative.hosts.create_screen].
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from typing import Any, Optional, Sequence, Type
15
+
16
+ from ..utils import IS_NATIVE
17
+ from .base import ScreenHost, import_component
18
+
19
+ __all__ = ["ScreenHost", "create_screen", "host_class", "import_component", "live_hosts"]
20
+
21
+
22
+ def host_class() -> Type[ScreenHost]:
23
+ """The host class for the current runtime."""
24
+ if IS_NATIVE:
25
+ from .native import NativeScreenHost
26
+
27
+ return NativeScreenHost
28
+ return ScreenHost
29
+
30
+
31
+ def create_screen(component_path: str, native_instance: Any = None, args_json: Optional[str] = None) -> ScreenHost:
32
+ """Create the screen host for a root component.
33
+
34
+ Args:
35
+ component_path: ``"app.main"`` (the module's ``App`` is used) or a
36
+ dotted path like ``"app.main.RootScreen"``. Imported lazily
37
+ so the dev server can reload it.
38
+ native_instance: The platform object owning the screen (the
39
+ integer screen id on the bridge platforms).
40
+ args_json: Optional JSON launch arguments (pushed screens
41
+ receive their navigation history here).
42
+
43
+ Returns:
44
+ A host ready for ``on_create`` and the other lifecycle calls.
45
+ """
46
+ component = import_component(component_path)
47
+ host = host_class()(native_instance, component_path, component)
48
+ if args_json:
49
+ host.set_args(args_json)
50
+ return host
51
+
52
+
53
+ def live_hosts() -> Sequence[ScreenHost]:
54
+ """Every screen host currently mounted by the native runtime.
55
+
56
+ Returns an empty sequence off the bridge platforms; tests hold their
57
+ own host references.
58
+ """
59
+ if not IS_NATIVE:
60
+ return []
61
+ from .native import live_hosts as native_live_hosts
62
+
63
+ return list(native_live_hosts())
@@ -0,0 +1,596 @@
1
+ """Platform-independent application surface host.
2
+
3
+ A host mounts one logical application tree, publishes native lifecycle and
4
+ viewport changes, schedules Python work on the application thread, and caches
5
+ navigation restoration state. Logical screen containers present the tree's
6
+ screen roots through native navigation controllers and fragments.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import importlib
12
+ import json
13
+ import os
14
+ import sys
15
+ import traceback
16
+ from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple
17
+
18
+ from .. import diagnostics
19
+ from ..element import Element
20
+
21
+ __all__ = ["ScreenHost", "import_component", "log_pn", "debug_enabled"]
22
+
23
+ MAX_RENDER_PASSES = 25
24
+ _DEBUG_ENV = "PYTHONNATIVE_DEBUG"
25
+
26
+
27
+ def debug_enabled() -> bool:
28
+ """Return whether the ``PYTHONNATIVE_DEBUG`` environment variable turns on host diagnostics."""
29
+ return os.environ.get(_DEBUG_ENV, "").lower() in {"1", "true", "yes", "on"}
30
+
31
+
32
+ def log_pn(msg: str) -> None:
33
+ """Emit optional diagnostics when ``PYTHONNATIVE_DEBUG`` is enabled."""
34
+ if not debug_enabled():
35
+ return
36
+ try:
37
+ print(f"[PN] {msg}", flush=True)
38
+ except Exception:
39
+ pass
40
+
41
+
42
+ # ======================================================================
43
+ # Component resolution
44
+ # ======================================================================
45
+
46
+
47
+ def _missing_module_is_target(exc: ModuleNotFoundError, dotted: str) -> bool:
48
+ """Whether ``exc`` means ``dotted`` itself is absent (vs. one of its imports)."""
49
+ missing = exc.name or ""
50
+ return missing == dotted or dotted.startswith(missing + ".")
51
+
52
+
53
+ def import_component(component_path: str) -> Any:
54
+ """Import a root component by module path or dotted attribute path.
55
+
56
+ ``"app.main"`` imports the module and returns its ``App`` attribute;
57
+ ``"app.main.RootScreen"`` returns the named attribute. Errors raised
58
+ *inside* a resolvable module (a missing third-party dependency, a
59
+ syntax error) propagate unchanged so the real cause stays visible.
60
+
61
+ Raises:
62
+ ImportError: When neither form resolves.
63
+ """
64
+ try:
65
+ module = importlib.import_module(component_path)
66
+ except ModuleNotFoundError as exc:
67
+ if not _missing_module_is_target(exc, component_path):
68
+ raise
69
+ module = None
70
+ if module is not None:
71
+ component = getattr(module, "App", None)
72
+ if component is not None:
73
+ return component
74
+
75
+ if "." in component_path:
76
+ module_path, attr = component_path.rsplit(".", 1)
77
+ try:
78
+ parent = importlib.import_module(module_path)
79
+ except ModuleNotFoundError as exc:
80
+ if not _missing_module_is_target(exc, module_path):
81
+ raise
82
+ parent = None
83
+ if parent is not None:
84
+ component = getattr(parent, attr, None)
85
+ if component is not None:
86
+ return component
87
+
88
+ raise ImportError(
89
+ f"Could not resolve component {component_path!r}. Define a top-level `App` function in the "
90
+ "module (e.g. `app/main.py`) or pass an explicit dotted path like `app.main.RootScreen`."
91
+ )
92
+
93
+
94
+ # ======================================================================
95
+ # Host
96
+ # ======================================================================
97
+
98
+
99
+ class ScreenHost:
100
+ """Base screen host; see the module docstring.
101
+
102
+ Attributes:
103
+ native_instance: The platform object owning this screen
104
+ (an integer screen id on the bridge platforms).
105
+ component_path: Import path of the root component.
106
+ args: Launch arguments (``set_args``), including the serialized
107
+ navigation state under ``"pn_nav"`` for pushed screens.
108
+ reconciler: The mounted reconciler, or ``None`` before
109
+ ``on_create`` / after ``on_destroy``.
110
+ is_focused: Whether the screen is presented (``on_resume`` /
111
+ ``on_pause``).
112
+ """
113
+
114
+ def __init__(self, native_instance: Any, component_path: str, component: Any) -> None:
115
+ self.native_instance = native_instance
116
+ self.component_path = component_path
117
+ self.component = component
118
+ self.args: Dict[str, Any] = {}
119
+ self.reconciler: Any = None
120
+ self.root_native_view: Any = None
121
+ self.is_focused = True
122
+ self._focus_listeners: List[Callable[[bool], None]] = []
123
+ self._is_rendering = False
124
+ self._render_queued = False
125
+ self._render_scheduled = False
126
+ self._redbox_reconciler: Any = None
127
+ self._redbox_root: Any = None
128
+
129
+ # ------------------------------------------------------------------
130
+ # Platform primitives (override)
131
+ # ------------------------------------------------------------------
132
+
133
+ def _attach_root(self, native_view: Any) -> None:
134
+ """Place ``native_view`` into the platform container."""
135
+
136
+ def _detach_root(self, native_view: Any) -> None:
137
+ """Remove ``native_view`` from the platform container."""
138
+
139
+ def _initial_viewport_size(self) -> Optional[Tuple[float, float]]:
140
+ """A plausible viewport size before the first layout (see ``_seed_viewport``)."""
141
+ return None
142
+
143
+ def _schedule_render_async(self) -> bool:
144
+ """Defer a render to the platform's next UI turn; ``False`` renders inline."""
145
+ return False
146
+
147
+ def _native_set_options(self, options: Dict[str, Any]) -> None:
148
+ """Apply header options (``title`` at minimum) to the native chrome."""
149
+
150
+ # ------------------------------------------------------------------
151
+ # HostNavigator protocol
152
+ # ------------------------------------------------------------------
153
+
154
+ def initial_navigation_state(self) -> Optional[Dict[str, Any]]:
155
+ """Return the serialized navigation state from ``args["pn_nav"]``, or ``None`` for the first screen."""
156
+ from ..navigation.host import initial_state_from_args
157
+
158
+ return initial_state_from_args(self.args)
159
+
160
+ def cache_navigation_state(self, state: Dict[str, Any]) -> None:
161
+ """Publish a restorable immutable navigation snapshot to the native host."""
162
+ from ..navigation.host import NAV_STATE_ARG
163
+
164
+ self.args = dict(self.args or {}) | {NAV_STATE_ARG: state}
165
+
166
+ def set_screen_options(self, options: Dict[str, Any]) -> None:
167
+ """Apply header ``options`` (``title`` and friends) to the native chrome."""
168
+ self._native_set_options(dict(options))
169
+
170
+ def add_focus_listener(self, callback: Callable[[bool], None]) -> Callable[[], None]:
171
+ """Subscribe to focus changes (``on_resume`` / ``on_pause``); returns an unsubscribe callable."""
172
+ self._focus_listeners.append(callback)
173
+
174
+ def remove() -> None:
175
+ try:
176
+ self._focus_listeners.remove(callback)
177
+ except ValueError:
178
+ pass
179
+
180
+ return remove
181
+
182
+ # ------------------------------------------------------------------
183
+ # Lifecycle (called by the platform)
184
+ # ------------------------------------------------------------------
185
+
186
+ def on_create(self) -> None:
187
+ """Mount the root component (idempotent across native view recreation).
188
+
189
+ Android destroys and recreates a fragment's view when the user
190
+ pops back to it and calls ``on_create`` again; the Python host
191
+ persists, so an already-mounted tree is simply re-attached.
192
+ """
193
+ self._register_redbox_reporter()
194
+ if self.reconciler is not None and self.root_native_view is not None:
195
+ self._attach_root(self.root_native_view)
196
+ return
197
+
198
+ self.reconciler = self._new_reconciler()
199
+ self._seed_viewport()
200
+ try:
201
+ self._is_rendering = True
202
+ try:
203
+ self.root_native_view = self.reconciler.mount(self._root_element())
204
+ self._attach_root(self.root_native_view)
205
+ self._drain_renders()
206
+ finally:
207
+ self._is_rendering = False
208
+ except Exception as exc:
209
+ if not diagnostics.is_dev():
210
+ raise
211
+ self.show_redbox(exc, phase="mount")
212
+
213
+ def on_start(self) -> None:
214
+ """Handle the platform's start event (no-op by default)."""
215
+ pass
216
+
217
+ def on_resume(self) -> None:
218
+ """Mark the screen focused and notify focus listeners."""
219
+ self.set_focused(True)
220
+
221
+ def on_layout(self) -> None:
222
+ """Handle a native layout pass (no-op by default; platforms sync the viewport here)."""
223
+ pass
224
+
225
+ def on_pause(self) -> None:
226
+ """Mark the screen unfocused and notify focus listeners."""
227
+ self.set_focused(False)
228
+
229
+ def on_stop(self) -> None:
230
+ """Handle the platform's stop event (no-op by default)."""
231
+ pass
232
+
233
+ def on_restart(self) -> None:
234
+ """Handle the platform's restart event (no-op by default)."""
235
+ pass
236
+
237
+ def on_save_instance_state(self) -> None:
238
+ """Handle the platform's save-state request (no-op by default)."""
239
+ pass
240
+
241
+ def on_restore_instance_state(self) -> None:
242
+ """Handle the platform's restore-state event (no-op by default)."""
243
+ pass
244
+
245
+ def on_destroy(self) -> None:
246
+ """Tear down: unmount (running effect cleanups), release native views."""
247
+ self.clear_redbox(reattach=False)
248
+ diagnostics.set_error_reporter(self, None)
249
+ reconciler, self.reconciler = self.reconciler, None
250
+ if reconciler is not None:
251
+ try:
252
+ reconciler.unmount()
253
+ except Exception:
254
+ log_pn("on_destroy: reconciler.unmount() failed")
255
+ root, self.root_native_view = self.root_native_view, None
256
+ if root is not None:
257
+ try:
258
+ self._detach_root(root)
259
+ except Exception:
260
+ pass
261
+ self._focus_listeners = []
262
+
263
+ def on_back_pressed(self) -> bool:
264
+ """Offer the system back action to ``use_back_handler`` subscribers.
265
+
266
+ Returns ``True`` when a handler consumed the event, in which
267
+ case the platform must not pop the screen.
268
+ """
269
+ if self.reconciler is None:
270
+ return False
271
+ try:
272
+ return bool(self.reconciler.dispatch_back_press())
273
+ except Exception as exc:
274
+ if not diagnostics.report_error(exc, phase="back handler"):
275
+ traceback.print_exc()
276
+ return False
277
+
278
+ def set_args(self, args: Any) -> None:
279
+ """Record launch arguments (a dict or a JSON string)."""
280
+ if isinstance(args, str):
281
+ try:
282
+ parsed = json.loads(args) or {}
283
+ except Exception:
284
+ parsed = {}
285
+ self.args = parsed if isinstance(parsed, dict) else {}
286
+ return
287
+ self.args = args if isinstance(args, dict) else {}
288
+
289
+ def set_focused(self, focused: bool) -> None:
290
+ """Update ``is_focused`` and notify focus listeners when the value changes."""
291
+ if self.is_focused == focused:
292
+ return
293
+ self.is_focused = focused
294
+ for callback in list(self._focus_listeners):
295
+ try:
296
+ callback(focused)
297
+ except Exception:
298
+ pass
299
+
300
+ def set_viewport_size(self, width: float, height: float) -> None:
301
+ """Forward a viewport-size change (in points) to the reconciler."""
302
+ if self.reconciler is None or width <= 0 or height <= 0:
303
+ return
304
+ self.reconciler.set_viewport_size(float(width), float(height))
305
+ if self._redbox_reconciler is not None:
306
+ self._redbox_reconciler.set_viewport_size(float(width), float(height))
307
+ try:
308
+ from .. import platform_metrics
309
+
310
+ platform_metrics.set_window_dimensions(float(width), float(height))
311
+ except Exception:
312
+ pass
313
+
314
+ # ------------------------------------------------------------------
315
+ # Rendering
316
+ # ------------------------------------------------------------------
317
+
318
+ def _root_element(self) -> Element:
319
+ from ..navigation.host import HostRoot
320
+
321
+ self.component = import_component(self.component_path)
322
+ return HostRoot(self.component(), host=self)
323
+
324
+ def _new_reconciler(self) -> Any:
325
+ from ..native_views import get_registry
326
+ from ..reconciler import Reconciler
327
+
328
+ reconciler = Reconciler(get_registry())
329
+ reconciler.on_render_requested = self.request_render
330
+ return reconciler
331
+
332
+ def _seed_viewport(self) -> None:
333
+ """Give the reconciler a plausible viewport before the first mount.
334
+
335
+ The authoritative size arrives right after attach, but the mount
336
+ commit has already run by then; without a viewport its layout
337
+ pass is skipped and mount-time ``use_layout_effect`` callbacks
338
+ would observe no frames.
339
+ """
340
+ try:
341
+ size = self._initial_viewport_size()
342
+ except Exception:
343
+ return
344
+ if size and size[0] > 0 and size[1] > 0:
345
+ self.reconciler.set_viewport_size(float(size[0]), float(size[1]))
346
+
347
+ def request_render(self) -> None:
348
+ """Request a render pass (queued if one is in progress)."""
349
+ if self.reconciler is None:
350
+ return
351
+ if self._is_rendering:
352
+ self._render_queued = True
353
+ return
354
+ if self._schedule_render_async():
355
+ return
356
+ self._re_render()
357
+
358
+ def flush_scheduled_render(self) -> None:
359
+ """Run a render deferred by ``_schedule_render_async`` (platform UI turn)."""
360
+ self._render_scheduled = False
361
+ if self.reconciler is None:
362
+ return
363
+ if self._is_rendering:
364
+ self._render_queued = True
365
+ self._schedule_render_async()
366
+ return
367
+ self._re_render()
368
+
369
+ def _re_render(self) -> None:
370
+ log_pn("_re_render: starting local render pass")
371
+ try:
372
+ self._is_rendering = True
373
+ try:
374
+ self._render_queued = False
375
+ self._commit_dirty()
376
+ self._drain_renders()
377
+ finally:
378
+ self._is_rendering = False
379
+ except Exception as exc:
380
+ if not diagnostics.is_dev():
381
+ raise
382
+ self.show_redbox(exc, phase="render")
383
+ log_pn("_re_render: done")
384
+
385
+ def _commit_dirty(self) -> None:
386
+ new_root = self.reconciler.flush_dirty()
387
+ if new_root is not self.root_native_view:
388
+ log_pn("_commit_dirty: root view changed; reattaching")
389
+ self._detach_root(self.root_native_view)
390
+ self.root_native_view = new_root
391
+ self._attach_root(new_root)
392
+
393
+ def _drain_renders(self) -> None:
394
+ """Flush renders queued by effects; capped to break runaway loops."""
395
+ for i in range(MAX_RENDER_PASSES):
396
+ if not self._render_queued:
397
+ break
398
+ log_pn(f"_drain_renders: pass #{i + 1}")
399
+ self._render_queued = False
400
+ self._commit_dirty()
401
+
402
+ # ------------------------------------------------------------------
403
+ # RedBox (dev-mode error overlay)
404
+ # ------------------------------------------------------------------
405
+
406
+ def _register_redbox_reporter(self) -> None:
407
+ if diagnostics.is_dev():
408
+ diagnostics.set_error_reporter(self, lambda exc, phase: self.show_redbox(exc, phase))
409
+
410
+ def show_redbox(self, exc: BaseException, phase: str = "render") -> None:
411
+ """Mount the dev error overlay over this screen (from any thread)."""
412
+ log_pn(f"show_redbox: {type(exc).__name__} during {phase}")
413
+ try:
414
+ print(f"[PN] {phase} error:", file=sys.stderr)
415
+ traceback.print_exception(type(exc), exc, exc.__traceback__)
416
+ except Exception:
417
+ pass
418
+
419
+ def mount() -> None:
420
+ try:
421
+ self.clear_redbox(reattach=False)
422
+ from ..native_views import get_registry
423
+ from ..reconciler import Reconciler
424
+
425
+ redbox = Reconciler(get_registry())
426
+ element = _redbox_element(exc, phase, lambda: self.clear_redbox())
427
+ root = redbox.mount(element)
428
+ width, height = self.reconciler.viewport_size if self.reconciler is not None else (0.0, 0.0)
429
+ if width <= 0 or height <= 0:
430
+ from .. import platform_metrics
431
+
432
+ dims = platform_metrics.get_window_dimensions()
433
+ width, height = dims.width, dims.height
434
+ if width > 0 and height > 0:
435
+ redbox.set_viewport_size(width, height)
436
+ self._redbox_reconciler = redbox
437
+ self._redbox_root = root
438
+ if self.root_native_view is not None:
439
+ self._detach_root(self.root_native_view)
440
+ self._attach_root(root)
441
+ except Exception:
442
+ print("[PN] RedBox failed to mount:", file=sys.stderr)
443
+ traceback.print_exc()
444
+
445
+ from ..runtime import call_on_application_thread
446
+
447
+ call_on_application_thread(mount)
448
+
449
+ def clear_redbox(self, reattach: bool = True) -> None:
450
+ """Dismiss the dev error overlay, reattaching the app's root view unless ``reattach`` is ``False``."""
451
+ redbox, self._redbox_reconciler = self._redbox_reconciler, None
452
+ self._redbox_root = None
453
+ if redbox is None:
454
+ return
455
+ try:
456
+ redbox.unmount()
457
+ except Exception:
458
+ pass
459
+ if reattach and self.root_native_view is not None:
460
+ try:
461
+ self._attach_root(self.root_native_view)
462
+ except Exception:
463
+ pass
464
+
465
+ # ------------------------------------------------------------------
466
+ # Hot reload
467
+ # ------------------------------------------------------------------
468
+
469
+ def reload(self, changed_modules: Optional[Sequence[str]] = None) -> str:
470
+ """Reload ``changed_modules`` (and their dependents) and refresh this tree.
471
+
472
+ A convenience for a single host (tests, scripts). The dev client
473
+ reloads modules once per process and then calls
474
+ [`refresh`][pythonnative.hosts.ScreenHost.refresh] on every live
475
+ host; see ``pythonnative.hot_reload.apply_reload``.
476
+
477
+ Returns:
478
+ ``"fast_refresh"``, ``"remount"``, ``"error"``, or ``"none"``
479
+ (nothing was reloaded).
480
+ """
481
+ from ..hot_reload import ModuleReloader
482
+
483
+ requested = list(changed_modules or [])
484
+ targets = ModuleReloader.expand_reload_targets(requested, self.component_path)
485
+ reloaded = ModuleReloader.reload_modules(targets)
486
+ if not reloaded:
487
+ log_pn(f"reload: no modules could be reloaded from {targets!r}")
488
+ return "none"
489
+ return self.refresh(reloaded)
490
+
491
+ def refresh(self, reloaded_modules: Sequence[str], *, force_remount: bool = False) -> str:
492
+ """Refresh the mounted tree against already-reloaded modules.
493
+
494
+ Tries Fast Refresh first (swap component functions in place so
495
+ hook state survives) and falls back to a full remount.
496
+
497
+ Returns:
498
+ ``"fast_refresh"``, ``"remount"``, or ``"error"`` (the error
499
+ is shown in the RedBox in dev mode, re-raised otherwise).
500
+ """
501
+ reloaded = list(reloaded_modules)
502
+ try:
503
+ self.component = import_component(self.component_path)
504
+ except Exception as exc:
505
+ if not diagnostics.is_dev():
506
+ raise
507
+ self.show_redbox(exc, phase="hot reload import")
508
+ return "error"
509
+ if self.reconciler is None:
510
+ return "none"
511
+ self.clear_redbox()
512
+ if not force_remount and self._try_fast_refresh(reloaded):
513
+ return "fast_refresh"
514
+ try:
515
+ self._full_remount(reloaded)
516
+ except Exception as exc:
517
+ if not diagnostics.is_dev():
518
+ raise
519
+ self.show_redbox(exc, phase="hot reload")
520
+ return "error"
521
+ return "remount"
522
+
523
+ def _try_fast_refresh(self, reloaded_modules: Sequence[str]) -> bool:
524
+ from ..hot_reload import ModuleReloader
525
+
526
+ reconciler = self.reconciler
527
+ if reconciler is None or reconciler.root is None:
528
+ return False
529
+ if not ModuleReloader.refresh_in_place(reconciler, reloaded_modules):
530
+ return False
531
+ self._is_rendering = True
532
+ try:
533
+ new_root = reconciler.reconcile(self._root_element())
534
+ if new_root is not self.root_native_view:
535
+ self._detach_root(self.root_native_view)
536
+ self.root_native_view = new_root
537
+ self._attach_root(new_root)
538
+ except Exception as exc:
539
+ log_pn(f"fast refresh: render failed after swap: {exc!r}; falling back to remount")
540
+ return False
541
+ finally:
542
+ self._is_rendering = False
543
+ self._drain_renders()
544
+ return True
545
+
546
+ def _full_remount(self, reloaded_modules: Sequence[str]) -> None:
547
+ old_reconciler, old_root = self.reconciler, self.root_native_view
548
+ new_reconciler = self._new_reconciler()
549
+ self.reconciler = new_reconciler
550
+ self._is_rendering = True
551
+ try:
552
+ new_root = new_reconciler.mount(self._root_element())
553
+ except Exception:
554
+ self.reconciler = old_reconciler
555
+ raise
556
+ finally:
557
+ self._is_rendering = False
558
+ if old_reconciler is not None:
559
+ old_reconciler.unmount()
560
+ if old_root is not None:
561
+ self._detach_root(old_root)
562
+ self.root_native_view = new_root
563
+ self._attach_root(new_root)
564
+ self._drain_renders()
565
+
566
+
567
+ def _redbox_element(exc: BaseException, phase: str, on_dismiss: Callable[[], None]) -> Element:
568
+ from ..components import Button, Column, ScrollView, Text
569
+
570
+ trace = "".join(traceback.format_exception(type(exc), exc, exc.__traceback__))
571
+ message = str(exc) or "(no message)"
572
+ return Column(
573
+ Column(
574
+ Text(f"{type(exc).__name__} in {phase}", style={"color": "#FFD3DA", "font_size": 13, "bold": True}),
575
+ Text(message, style={"color": "#FFFFFF", "font_size": 17, "bold": True}),
576
+ style={"background_color": "#C4283C", "padding": 16, "padding_top": 56, "spacing": 6},
577
+ ),
578
+ ScrollView(
579
+ Text(trace, style={"color": "#FF9AA8", "font_size": 12}),
580
+ style={"flex": 1, "padding": 12},
581
+ ),
582
+ Column(
583
+ Button("Dismiss", on_press=on_dismiss, style={"color": "#FFFFFF"}),
584
+ Text(
585
+ "Fix the error and save to reload.", style={"color": "#8E8E93", "font_size": 12, "text_align": "center"}
586
+ ),
587
+ style={"padding": 12, "padding_bottom": 32, "spacing": 4},
588
+ ),
589
+ style={"flex": 1, "background_color": "#1C1C1E"},
590
+ )
591
+
592
+
593
+ def flush_hosts(hosts: Sequence[ScreenHost]) -> None:
594
+ """Run deferred renders for ``hosts`` (platform UI-thread drains call this)."""
595
+ for host in hosts:
596
+ host.flush_scheduled_render()