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,489 @@
1
+ """WebSocket transport for the browser renderer.
2
+
3
+ Network I/O and request settlement execute independently of the application
4
+ asyncio loop. Python owns the component tree; the page owns DOM widgets and Yoga
5
+ layout. Revisioned commits receive explicit acknowledgements, and callbacks
6
+ are queued onto the Python application thread. No asyncio loop is pumped by
7
+ the browser transport.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import itertools
13
+ import json
14
+ import queue
15
+ import sys
16
+ import threading
17
+ import time
18
+ import traceback
19
+ from typing import Any, Callable, Dict, List, Optional, Tuple
20
+
21
+ from . import PROTOCOL_VERSION, codec
22
+
23
+ __all__ = ["BROWSER_MODULES", "WebTransport"]
24
+
25
+ BROWSER_MODULES = frozenset(
26
+ {"Host", "Layout", "Alert", "Clipboard", "Linking", "Share", "Haptics", "NetInfo", "AppState", "Device"}
27
+ )
28
+ """Native modules the preview page implements; the rest use Python fallbacks."""
29
+
30
+ REQUEST_TIMEOUT_S = 15.0
31
+ """How long a synchronous request waits for the page before giving up."""
32
+
33
+ Callback = Callable[[str, int, str, str], Optional[str]]
34
+
35
+
36
+ class _Waiter:
37
+ __slots__ = ("event", "result", "failed")
38
+
39
+ def __init__(self) -> None:
40
+ self.event = threading.Event()
41
+ self.result: Any = None
42
+ self.failed = False
43
+
44
+
45
+ class WebTransport:
46
+ """Bridge transport whose native side is a browser page.
47
+
48
+ Install it with ``pythonnative.bridge.set_transport`` and hand it to
49
+ ``DevServer.set_preview_channel``; the page does the rest.
50
+
51
+ Args:
52
+ log: Where diagnostics go (defaults to stderr).
53
+ """
54
+
55
+ name = "web"
56
+
57
+ def __init__(self, *, log: Optional[Callable[[str], None]] = None) -> None:
58
+ self._log = log or (lambda line: print(line, file=sys.stderr, flush=True))
59
+ self._callback: Optional[Callback] = None
60
+ self._peer: Any = None
61
+ self._peer_lock = threading.Lock()
62
+ self._ids = itertools.count(1)
63
+ self._waiters: Dict[int, _Waiter] = {}
64
+ self._waiters_lock = threading.Lock()
65
+ self._main: "queue.Queue[Callable[[], None]]" = queue.Queue()
66
+ self._main_thread: Optional[threading.Thread] = None
67
+ self._stop = threading.Event()
68
+ self._gestures: Dict[int, Tuple[str, Any]] = {}
69
+ self._gesture_timer: Optional[Any] = None
70
+ self._warned_no_peer = False
71
+ self._python_modules: Dict[str, Any] = {}
72
+ self.on_dev_message: Optional[Callable[[Dict[str, Any]], None]] = None
73
+ """Hook for ``["dev", {...}]`` messages from the page (runs on the main thread)."""
74
+ self.on_peer_changed: Optional[Callable[[bool], None]] = None
75
+ """Called on the main thread with ``True`` on connect and ``False`` on disconnect."""
76
+
77
+ # ------------------------------------------------------------------
78
+ # Transport protocol
79
+ # ------------------------------------------------------------------
80
+
81
+ def protocol_version(self) -> int:
82
+ """The page speaks whatever this package speaks; they ship together."""
83
+ return PROTOCOL_VERSION
84
+
85
+ def set_callback(self, callback: Callback) -> None:
86
+ """Install the native -> Python entry point (``bridge.native_callback``)."""
87
+ self._callback = callback
88
+
89
+ def apply(self, transaction_json: str) -> str:
90
+ """Wait for the page to acknowledge this exact commit revision."""
91
+ return codec.dumps(self._request(["apply", None, codec.loads(transaction_json)]))
92
+
93
+ def measure(self, tag: int, max_width: float, max_height: float) -> Tuple[float, float]:
94
+ """Ask the page for the intrinsic size of ``tag``."""
95
+ result = self._request(["measure", None, int(tag), _finite(max_width), _finite(max_height)])
96
+ if isinstance(result, (list, tuple)) and len(result) >= 2:
97
+ try:
98
+ return (float(result[0]), float(result[1]))
99
+ except (TypeError, ValueError):
100
+ return (0.0, 0.0)
101
+ return (0.0, 0.0)
102
+
103
+ def command(self, tag: int, name: str, args_json: str) -> Optional[str]:
104
+ """Run an imperative command on one view; returns its JSON result or ``None``."""
105
+ result = self._request(["command", None, int(tag), name, args_json])
106
+ return _as_json_text(result)
107
+
108
+ def animate(self, tag: int, request_json: str) -> Optional[str]:
109
+ """Handle an animation request (``set`` / ``start`` / ``cancel``) for one view."""
110
+ result = self._request(["animate", None, int(tag), request_json])
111
+ return _as_json_text(result)
112
+
113
+ def call(self, module: str, method: str, args_json: str) -> Optional[str]:
114
+ """Call a native module: ``Host.post`` locally, page modules over the wire, others in Python."""
115
+ if module in BROWSER_MODULES:
116
+ result = self._request(["call", None, module, method, args_json])
117
+ return _as_json_text(result)
118
+ return self._call_python_module(module, method, args_json)
119
+
120
+ # ------------------------------------------------------------------
121
+ # Main thread
122
+ # ------------------------------------------------------------------
123
+
124
+ def post_to_application(self, fn: Callable[[], None]) -> None:
125
+ """Queue ``fn`` for the main loop (never runs inline)."""
126
+ from ..runtime import get_loop
127
+
128
+ loop = get_loop()
129
+ if loop.is_running():
130
+ loop.call_soon_threadsafe(self._run_job, fn)
131
+ else:
132
+ self._main.put(fn)
133
+
134
+ def run_main_loop(self, *, until: Optional[Callable[[], bool]] = None) -> None:
135
+ """Drain main-thread work until ``stop`` is called (or ``until`` holds).
136
+
137
+ This is the preview's event loop: the browser's stand-in for the
138
+ platform main queue. Call it from the thread that should own the
139
+ framework (the process main thread under ``pn preview``).
140
+ """
141
+ self._main_thread = threading.current_thread()
142
+ self._stop.clear()
143
+ while not self._stop.is_set():
144
+ if until is not None and until():
145
+ return
146
+ try:
147
+ job = self._main.get(timeout=0.1)
148
+ except queue.Empty:
149
+ continue
150
+ self._run_job(job)
151
+
152
+ def drain_main(self, timeout: float = 0.0) -> int:
153
+ """Run queued main-thread work inline (tests); returns how many jobs ran."""
154
+ self._main_thread = threading.current_thread()
155
+ deadline = time.monotonic() + timeout
156
+ ran = 0
157
+ while True:
158
+ try:
159
+ job = self._main.get_nowait()
160
+ except queue.Empty:
161
+ if timeout <= 0 or time.monotonic() >= deadline:
162
+ return ran
163
+ time.sleep(0.002)
164
+ continue
165
+ self._run_job(job)
166
+ ran += 1
167
+
168
+ def stop(self) -> None:
169
+ """Make ``run_main_loop`` return."""
170
+ self._stop.set()
171
+
172
+ def _run_job(self, job: Callable[[], None]) -> None:
173
+ try:
174
+ job()
175
+ except Exception:
176
+ self._log("[pn preview] main-thread job raised:")
177
+ self._log(traceback.format_exc())
178
+
179
+ # ------------------------------------------------------------------
180
+ # PreviewChannel (called on the dev server thread)
181
+ # ------------------------------------------------------------------
182
+
183
+ def on_preview_connected(self, peer: Any, info: Dict[str, Any]) -> None:
184
+ """A page connected; it becomes the native side."""
185
+ del info
186
+ with self._peer_lock:
187
+ self._peer = peer
188
+ self._warned_no_peer = False
189
+ self.post_to_application(lambda: self._peer_changed(True))
190
+
191
+ def on_preview_disconnected(self, peer: Any) -> None:
192
+ """The page went away: fail waiting requests and tear down its screens."""
193
+ with self._peer_lock:
194
+ if self._peer is not peer:
195
+ return
196
+ self._peer = None
197
+ self._fail_all_waiters()
198
+ self.post_to_application(lambda: self._peer_changed(False))
199
+
200
+ def on_preview_message(self, peer: Any, text: str) -> None:
201
+ """Route one frame from the page."""
202
+ with self._peer_lock:
203
+ if peer is not self._peer:
204
+ return
205
+ try:
206
+ message = json.loads(text)
207
+ except ValueError:
208
+ self._log(f"[pn preview] dropped malformed message: {text[:120]!r}")
209
+ return
210
+ if not isinstance(message, list) or not message:
211
+ return
212
+ kind = message[0]
213
+ if kind == "res":
214
+ self._settle(message)
215
+ return
216
+ if kind == "cb":
217
+ self.post_to_application(lambda: self._deliver_fire_and_forget(message))
218
+ return
219
+ if kind == "req":
220
+ self.post_to_application(lambda: self._deliver_request(peer, message))
221
+ return
222
+ if kind == "gesture":
223
+ self.post_to_application(lambda: self._deliver_gesture(message))
224
+ return
225
+ if kind == "dev":
226
+ payload = message[1] if len(message) > 1 and isinstance(message[1], dict) else {}
227
+ self.post_to_application(lambda: self._deliver_dev(payload))
228
+ return
229
+ self._log(f"[pn preview] unknown message kind {kind!r}")
230
+
231
+ # ------------------------------------------------------------------
232
+ # Sending
233
+ # ------------------------------------------------------------------
234
+
235
+ @property
236
+ def connected(self) -> bool:
237
+ """Whether a page is attached."""
238
+ with self._peer_lock:
239
+ return self._peer is not None
240
+
241
+ def send_dev(self, payload: Dict[str, Any]) -> None:
242
+ """Send a ``["dev", {...}]`` message to the page (logs, reload status, ...)."""
243
+ self._send(codec.dumps(["dev", codec.to_jsonable(payload)]))
244
+
245
+ def _send(self, text: str) -> bool:
246
+ with self._peer_lock:
247
+ peer = self._peer
248
+ if peer is None:
249
+ return False
250
+ try:
251
+ peer.send(text)
252
+ except Exception as exc:
253
+ self._log(f"[pn preview] send failed: {exc!r}")
254
+ return False
255
+ return True
256
+
257
+ def _request(self, message: List[Any]) -> Any:
258
+ """Send ``message`` (slot 1 receives the id) and block for the ``res``."""
259
+ with self._peer_lock:
260
+ peer = self._peer
261
+ if peer is None:
262
+ if not self._warned_no_peer:
263
+ self._warned_no_peer = True
264
+ self._log("[pn preview] request made with no browser attached; answering with defaults")
265
+ return None
266
+ request_id = next(self._ids)
267
+ message[1] = request_id
268
+ waiter = _Waiter()
269
+ with self._waiters_lock:
270
+ self._waiters[request_id] = waiter
271
+ try:
272
+ peer.send(codec.dumps(message))
273
+ except Exception as exc:
274
+ with self._waiters_lock:
275
+ self._waiters.pop(request_id, None)
276
+ self._log(f"[pn preview] request send failed: {exc!r}")
277
+ return None
278
+ if not waiter.event.wait(REQUEST_TIMEOUT_S):
279
+ with self._waiters_lock:
280
+ self._waiters.pop(request_id, None)
281
+ self._log(f"[pn preview] {message[0]} request timed out after {REQUEST_TIMEOUT_S:g}s")
282
+ return None
283
+ if waiter.failed:
284
+ return None
285
+ return waiter.result
286
+
287
+ def _settle(self, message: List[Any]) -> None:
288
+ if len(message) < 2:
289
+ return
290
+ try:
291
+ request_id = int(message[1])
292
+ except (TypeError, ValueError):
293
+ return
294
+ with self._waiters_lock:
295
+ waiter = self._waiters.pop(request_id, None)
296
+ if waiter is None:
297
+ return
298
+ waiter.result = message[2] if len(message) > 2 else None
299
+ waiter.event.set()
300
+
301
+ def _fail_all_waiters(self) -> None:
302
+ with self._waiters_lock:
303
+ waiters = list(self._waiters.values())
304
+ self._waiters.clear()
305
+ for waiter in waiters:
306
+ waiter.failed = True
307
+ waiter.event.set()
308
+
309
+ # ------------------------------------------------------------------
310
+ # Inbound (main thread)
311
+ # ------------------------------------------------------------------
312
+
313
+ def _deliver_callback(self, message: List[Any]) -> Optional[str]:
314
+ callback = self._callback
315
+ if callback is None or len(message) < 5:
316
+ return None
317
+ _, kind, tag, name, payload = message[:5]
318
+ return callback(str(kind), int(tag or 0), str(name), _payload_text(payload))
319
+
320
+ def _deliver_fire_and_forget(self, message: List[Any]) -> None:
321
+ self._deliver_callback(message)
322
+
323
+ def _deliver_request(self, peer: Any, message: List[Any]) -> None:
324
+ if len(message) < 6:
325
+ return
326
+ request_id = message[1]
327
+ result = self._deliver_callback(["cb", *message[2:6]])
328
+ try:
329
+ peer.send(codec.dumps(["res", request_id, result]))
330
+ except Exception as exc:
331
+ self._log(f"[pn preview] reply failed: {exc!r}")
332
+
333
+ def _deliver_dev(self, payload: Dict[str, Any]) -> None:
334
+ hook = self.on_dev_message
335
+ if hook is not None:
336
+ hook(payload)
337
+
338
+ def _peer_changed(self, connected: bool) -> None:
339
+ if not connected:
340
+ self._gestures.clear()
341
+ hook = self.on_peer_changed
342
+ if hook is not None:
343
+ hook(connected)
344
+
345
+ # -- gestures --------------------------------------------------------
346
+
347
+ def _deliver_gesture(self, message: List[Any]) -> None:
348
+ """Feed a pointer event to the tag's arbiter (built from the specs the page sends)."""
349
+ if len(message) < 4:
350
+ return
351
+ _, tag, phase, info = message[:4]
352
+ if not isinstance(info, dict):
353
+ return
354
+ tag = int(tag)
355
+ arbiter = self._arbiter_for(tag, info.get("specs"))
356
+ if arbiter is None:
357
+ return
358
+ t = float(info.get("t", time.monotonic()))
359
+ pointer = int(info.get("id", 0))
360
+ x = float(info.get("x", 0.0))
361
+ y = float(info.get("y", 0.0))
362
+ if phase == "down":
363
+ arbiter.pointer_down(pointer, x, y, t)
364
+ elif phase == "move":
365
+ arbiter.pointer_move(pointer, x, y, t)
366
+ elif phase == "up":
367
+ arbiter.pointer_up(pointer, x, y, t)
368
+ elif phase == "cancel":
369
+ arbiter.cancel(t)
370
+ elif phase == "clear":
371
+ self._gestures.pop(tag, None)
372
+ return
373
+ self._schedule_gesture_poll()
374
+
375
+ def _arbiter_for(self, tag: int, specs: Any) -> Any:
376
+ if not isinstance(specs, list) or not specs:
377
+ self._gestures.pop(tag, None)
378
+ return None
379
+ key = json.dumps(specs, sort_keys=True)
380
+ existing = self._gestures.get(tag)
381
+ if existing is not None and existing[0] == key:
382
+ return existing[1]
383
+ from ..events import dispatch_event
384
+ from ..gestures import make_arbiter
385
+
386
+ def _emit(index: int, payload: Dict[str, Any]) -> None:
387
+ dispatch_event(tag, f"gesture:{index}", payload)
388
+
389
+ arbiter = make_arbiter([s for s in specs if isinstance(s, dict)], _emit)
390
+ self._gestures[tag] = (key, arbiter)
391
+ return arbiter
392
+
393
+ def _schedule_gesture_poll(self) -> None:
394
+ """Arm one timer for the earliest recognizer deadline (long press, multi-tap windows)."""
395
+ deadlines = [d for _, arb in self._gestures.values() if (d := arb.next_deadline()) is not None]
396
+ if not deadlines:
397
+ return
398
+ delay = max(0.0, min(deadlines) - time.monotonic())
399
+ from ..runtime import get_loop
400
+
401
+ loop = get_loop()
402
+ if self._gesture_timer is not None:
403
+ try:
404
+ self._gesture_timer.cancel()
405
+ except Exception:
406
+ pass
407
+ self._gesture_timer = loop.call_later(delay + 0.001, self._poll_gestures)
408
+
409
+ def _poll_gestures(self) -> None:
410
+ self._gesture_timer = None
411
+ now = time.monotonic()
412
+ for _, arbiter in list(self._gestures.values()):
413
+ arbiter.poll(now)
414
+ self._schedule_gesture_poll()
415
+
416
+ # -- Python module fallbacks ------------------------------------------
417
+
418
+ def _call_python_module(self, module: str, method: str, args_json: str) -> Optional[str]:
419
+ from ..native_modules.registry import NativeModuleError, PythonModule, dispatch_module_message
420
+
421
+ envelope = codec.loads(args_json) or {}
422
+ args = envelope.get("args") if isinstance(envelope, dict) else None
423
+ call_id = int(envelope.get("call_id", 0) or 0) if isinstance(envelope, dict) else 0
424
+ # One instance per module for the life of the transport, so stateful
425
+ # fallbacks (Storage, SecureStore, ...) remember between calls.
426
+ impl = self._python_modules.get(module)
427
+ if impl is None:
428
+ impl = self._python_modules[module] = PythonModule(module)
429
+ try:
430
+ fn = impl._method(method)
431
+ value = fn(**(args or {}))
432
+ except KeyError:
433
+ return codec.dumps({"ok": False, "error": f"no module named {module!r}", "code": "unknown_module"})
434
+ except NativeModuleError as exc:
435
+ return codec.dumps({"ok": False, "error": exc.message, "code": exc.code})
436
+ except Exception as exc:
437
+ return codec.dumps({"ok": False, "error": str(exc)})
438
+ if hasattr(value, "__await__"):
439
+ if call_id == 0:
440
+ return codec.dumps({"ok": False, "error": f"{module}.{method} is asynchronous; use call_async()"})
441
+ from ..runtime import run_async
442
+
443
+ async def _finish() -> None:
444
+ try:
445
+ result = await value
446
+ dispatch_module_message(
447
+ module, {"call_id": call_id, "ok": True, "value": codec.to_jsonable(result)}
448
+ )
449
+ except Exception as exc:
450
+ dispatch_module_message(module, {"call_id": call_id, "ok": False, "error": str(exc)})
451
+
452
+ run_async(_finish())
453
+ return codec.dumps({"pending": True})
454
+ try:
455
+ return codec.dumps({"ok": True, "value": codec.to_jsonable(value)})
456
+ except TypeError:
457
+ return codec.dumps({"ok": True, "value": None})
458
+
459
+
460
+ _UNBOUNDED = 1e6
461
+ """Wire sentinel for an unconstrained measure axis (matches the native runtimes)."""
462
+
463
+
464
+ def _finite(value: Any) -> float:
465
+ """JSON has no infinity: clamp unconstrained measure axes to the wire sentinel."""
466
+ try:
467
+ f = float(value)
468
+ except (TypeError, ValueError):
469
+ return _UNBOUNDED
470
+ if f != f or f > _UNBOUNDED or f == float("inf"):
471
+ return _UNBOUNDED
472
+ return max(0.0, f)
473
+
474
+
475
+ def _as_json_text(result: Any) -> Optional[str]:
476
+ """Normalize a page result to the JSON text the native protocol returns."""
477
+ if result is None:
478
+ return None
479
+ if isinstance(result, str):
480
+ return result
481
+ return codec.dumps(result)
482
+
483
+
484
+ def _payload_text(payload: Any) -> str:
485
+ if payload is None:
486
+ return ""
487
+ if isinstance(payload, str):
488
+ return payload
489
+ return codec.dumps(payload)
@@ -0,0 +1,7 @@
1
+ """Command-line interface package for the `pn` script.
2
+
3
+ The CLI entry point lives in
4
+ [`pythonnative.cli.pn`][pythonnative.cli.pn] and is exposed as the
5
+ `pn` console script (configured in `pyproject.toml`'s
6
+ `[project.scripts]`).
7
+ """