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,158 @@
1
+ package com.pythonnative.runtime.modules
2
+
3
+ import com.pythonnative.runtime.PNBridge
4
+ import com.pythonnative.runtime.bridge.JsonUtil
5
+ import com.pythonnative.runtime.bridge.MainThread
6
+ import org.json.JSONObject
7
+
8
+ /**
9
+ * A named native module exposing methods to Python through
10
+ * `PNBridge.call(module, method, argsJson)`.
11
+ *
12
+ * Implementations settle the [Promise] synchronously (the result is
13
+ * returned inline) or later from any thread (the result is delivered
14
+ * as a `module` callback on the main thread). Unknown methods should
15
+ * call [Promise.rejectUnknownMethod].
16
+ */
17
+ interface NativeModule {
18
+ /** The module name Python addresses, for example `"Clipboard"`. */
19
+ val name: String
20
+
21
+ /** Handle one call; must settle `promise` exactly once (now or later). */
22
+ fun call(method: String, args: JSONObject, promise: Promise)
23
+ }
24
+
25
+ /**
26
+ * Result envelopes for module calls and events, as JSON strings.
27
+ */
28
+ object ModuleEnvelope {
29
+ /** Decode `{"call_id": n, "args": {...}}` into `(callId, args)`. */
30
+ fun decodeCall(argsJson: String): Pair<Long, JSONObject> {
31
+ val obj = if (argsJson.isBlank()) JSONObject() else JSONObject(argsJson)
32
+ val callId = obj.optLong("call_id", 0L)
33
+ val args = obj.optJSONObject("args") ?: JSONObject()
34
+ return callId to args
35
+ }
36
+
37
+ /** `{"ok": true, "value": ...}` */
38
+ fun ok(value: Any?): String = JSONObject().put("ok", true).put("value", JsonUtil.wrap(value)).toString()
39
+
40
+ /** `{"ok": false, "error": message, "code": code}` */
41
+ fun error(message: String, code: String? = null): String {
42
+ val obj = JSONObject().put("ok", false).put("error", message)
43
+ if (code != null) obj.put("code", code)
44
+ return obj.toString()
45
+ }
46
+
47
+ /** `{"pending": true}` */
48
+ fun pending(): String = JSONObject().put("pending", true).toString()
49
+
50
+ /** `{"call_id": n, "ok": true, "value": ...}` for asynchronous settlement. */
51
+ fun settled(callId: Long, value: Any?): String =
52
+ JSONObject().put("call_id", callId).put("ok", true).put("value", JsonUtil.wrap(value)).toString()
53
+
54
+ /** `{"call_id": n, "ok": false, "error": message, "code": code}` for asynchronous rejection. */
55
+ fun settledError(callId: Long, message: String, code: String?): String {
56
+ val obj = JSONObject().put("call_id", callId).put("ok", false).put("error", message)
57
+ if (code != null) obj.put("code", code)
58
+ return obj.toString()
59
+ }
60
+
61
+ /** `{"event": name, "payload": {...}}` */
62
+ fun event(event: String, payload: Any?): String =
63
+ JSONObject().put("event", event).put("payload", JsonUtil.wrap(payload)).toString()
64
+ }
65
+
66
+ /**
67
+ * The settlement handle for one module call.
68
+ *
69
+ * If [resolve] or [reject] runs before the module's `call` returns,
70
+ * the result is returned inline to Python. Otherwise Python receives
71
+ * `{"pending": true}` and the eventual settlement is delivered on the
72
+ * main thread as a `module` callback carrying the `call_id`.
73
+ */
74
+ class Promise(val callId: Long, val module: String, private val dispatch: (Runnable) -> Unit = defaultDispatcher) {
75
+ private var returned = false
76
+ private var settledInline: String? = null
77
+ internal var onFinished: (() -> Unit)? = null
78
+ private var cancellation: (() -> Unit)? = null
79
+ var isCancelled = false
80
+ private set
81
+
82
+ /** Release native work when the Python awaiter is cancelled. */
83
+ @Synchronized fun onCancel(callback: () -> Unit) {
84
+ if (isCancelled) callback() else if (!isSettled) cancellation = callback
85
+ }
86
+
87
+ @Synchronized fun cancel() {
88
+ if (isSettled) return
89
+ isCancelled = true
90
+ isSettled = true
91
+ val callback = cancellation
92
+ cancellation = null
93
+ onFinished?.invoke()
94
+ runCatching { callback?.invoke() }
95
+ }
96
+
97
+ /** Whether the promise has been resolved or rejected. */
98
+ var isSettled = false
99
+ private set
100
+
101
+ /** Resolve with `value` (JSON-encodable: primitives, maps, lists, `JSONObject`). */
102
+ @Synchronized fun resolve(value: Any?) {
103
+ if (isSettled) return
104
+ isSettled = true
105
+ cancellation = null
106
+ onFinished?.invoke()
107
+ if (!returned) {
108
+ settledInline = ModuleEnvelope.ok(value)
109
+ } else {
110
+ deliver(ModuleEnvelope.settled(callId, value))
111
+ }
112
+ }
113
+
114
+ /** Reject with `message` and an optional machine-readable `code`. */
115
+ @Synchronized fun reject(message: String, code: String? = null) {
116
+ if (isSettled) return
117
+ isSettled = true
118
+ cancellation = null
119
+ onFinished?.invoke()
120
+ if (!returned) {
121
+ settledInline = ModuleEnvelope.error(message, code)
122
+ } else {
123
+ deliver(ModuleEnvelope.settledError(callId, message, code))
124
+ }
125
+ }
126
+
127
+ /** Reject because the module has no method named `method`. */
128
+ fun rejectUnknownMethod(method: String) = reject("$module has no method '$method'", "unknown_method")
129
+
130
+ /**
131
+ * Called by the bridge after `call` returns: yields the inline
132
+ * envelope when already settled, otherwise `{"pending": true}` and
133
+ * arms asynchronous delivery.
134
+ */
135
+ @Synchronized fun markReturned(): String {
136
+ returned = true
137
+ return settledInline ?: ModuleEnvelope.pending()
138
+ }
139
+
140
+ private fun deliver(payload: String) {
141
+ val moduleName = module
142
+ dispatch(Runnable { PNBridge.callPython("module", 0, moduleName, payload) })
143
+ }
144
+
145
+ companion object {
146
+ /** How asynchronous settlements reach the main thread (replaceable in tests). */
147
+ var defaultDispatcher: (Runnable) -> Unit = { MainThread.post(it) }
148
+ }
149
+ }
150
+
151
+ /** Unsolicited module events (`{"event": name, "payload": {...}}`). */
152
+ object ModuleEvents {
153
+ /** Emit `event` for `module` on the main thread (posting if needed). */
154
+ fun emit(module: String, event: String, payload: Any?) {
155
+ val json = ModuleEnvelope.event(event, payload)
156
+ MainThread.runOnMain { PNBridge.callPython("module", 0, module, json) }
157
+ }
158
+ }
@@ -0,0 +1,100 @@
1
+ package com.pythonnative.runtime.modules
2
+
3
+ import android.app.Notification
4
+ import android.app.NotificationChannel
5
+ import android.app.NotificationManager
6
+ import android.content.Context
7
+ import android.os.Build
8
+ import com.pythonnative.runtime.PNBridge
9
+ import com.pythonnative.runtime.bridge.JsonUtil
10
+ import com.pythonnative.runtime.bridge.MainThread
11
+ import com.pythonnative.runtime.bridge.PNLog
12
+ import com.pythonnative.runtime.bridge.str
13
+ import org.json.JSONObject
14
+ import kotlin.math.abs
15
+
16
+ /**
17
+ * `Notifications`: `request_permission()` (async; `POST_NOTIFICATIONS`
18
+ * on API 33+), `schedule({title, body, delay_seconds, identifier})`
19
+ * (a Handler-delayed local notification, in-process only),
20
+ * `cancel(identifier)`, and `get_device_token()` (`null`; no built-in
21
+ * push on Android).
22
+ */
23
+ class NotificationsModule : NativeModule {
24
+ override val name = "Notifications"
25
+ private val delayed = HashMap<String, Runnable>()
26
+
27
+ override fun call(method: String, args: JSONObject, promise: Promise) {
28
+ when (method) {
29
+ "request_permission" -> requestPermission(promise)
30
+ "schedule" -> promise.resolve(schedule(args))
31
+ "cancel" -> {
32
+ cancel(args.str("identifier") ?: "")
33
+ promise.resolve(null)
34
+ }
35
+ "get_device_token" -> promise.resolve(null)
36
+ else -> promise.rejectUnknownMethod(method)
37
+ }
38
+ }
39
+
40
+ private fun requestPermission(promise: Promise) {
41
+ if (Build.VERSION.SDK_INT < 33) return promise.resolve(true)
42
+ BuiltinModules.permissions.request("notifications") { status ->
43
+ promise.resolve(status == PermissionsModule.GRANTED)
44
+ }
45
+ }
46
+
47
+ private fun schedule(args: JSONObject): Boolean {
48
+ val title = args.str("title") ?: ""
49
+ val body = args.str("body") ?: ""
50
+ val identifier = args.str("identifier") ?: "pn_${System.currentTimeMillis()}"
51
+ val delaySeconds = JsonUtil.toDouble(args.opt("delay_seconds"), 0.0)
52
+ cancel(identifier)
53
+ if (delaySeconds <= 0.0) return post(title, body, identifier)
54
+ val runnable = Runnable {
55
+ delayed.remove(identifier)
56
+ post(title, body, identifier)
57
+ }
58
+ delayed[identifier] = runnable
59
+ MainThread.postDelayed(runnable, (delaySeconds * 1000).toLong())
60
+ return true
61
+ }
62
+
63
+ private fun cancel(identifier: String) {
64
+ delayed.remove(identifier)?.let { MainThread.remove(it) }
65
+ try {
66
+ manager()?.cancel(notificationId(identifier))
67
+ } catch (e: Exception) {
68
+ PNLog.swallowed("Notifications.cancel", e)
69
+ }
70
+ }
71
+
72
+ private fun manager(): NotificationManager? =
73
+ PNBridge.context().getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager
74
+
75
+ private fun post(title: String, body: String, identifier: String): Boolean {
76
+ return try {
77
+ val ctx = PNBridge.context()
78
+ val nm = manager() ?: return false
79
+ val builder = if (Build.VERSION.SDK_INT >= 26) {
80
+ nm.createNotificationChannel(NotificationChannel(CHANNEL_ID, "PythonNative", NotificationManager.IMPORTANCE_DEFAULT))
81
+ Notification.Builder(ctx, CHANNEL_ID)
82
+ } else {
83
+ @Suppress("DEPRECATION")
84
+ Notification.Builder(ctx)
85
+ }
86
+ builder.setContentTitle(title).setContentText(body).setSmallIcon(android.R.drawable.ic_dialog_info)
87
+ nm.notify(notificationId(identifier), builder.build())
88
+ true
89
+ } catch (e: Exception) {
90
+ PNLog.swallowed("Notifications.post", e)
91
+ false
92
+ }
93
+ }
94
+
95
+ private fun notificationId(identifier: String): Int = abs(identifier.hashCode()) % Int.MAX_VALUE
96
+
97
+ private companion object {
98
+ const val CHANNEL_ID = "pn_default"
99
+ }
100
+ }
@@ -0,0 +1,99 @@
1
+ package com.pythonnative.runtime.modules
2
+
3
+ import android.content.pm.PackageManager
4
+ import android.os.Build
5
+ import androidx.core.app.ActivityCompat
6
+ import androidx.core.content.ContextCompat
7
+ import com.pythonnative.runtime.PNBridge
8
+ import com.pythonnative.runtime.bridge.str
9
+ import org.json.JSONObject
10
+
11
+ /**
12
+ * `Permissions.check(permission)` (sync) and `request(permission)`
13
+ * (async, routed through `onRequestPermissionsResult`). Statuses are
14
+ * `granted`, `denied`, `blocked`, and `undetermined`.
15
+ *
16
+ * Permission names are the `[permissions]` keys from pythonnative.toml
17
+ * (`camera`, `microphone`, `photo_library`, `location_when_in_use`,
18
+ * `contacts`, `notifications`); the Python facade validates them before
19
+ * the call reaches this module, so an unknown name here is a bug rather
20
+ * than user input, and is rejected rather than answered.
21
+ */
22
+ class PermissionsModule : NativeModule {
23
+ override val name = "Permissions"
24
+ private val pending = HashMap<Int, Pair<String, (String) -> Unit>>()
25
+
26
+ override fun call(method: String, args: JSONObject, promise: Promise) {
27
+ val permission = args.str("permission") ?: ""
28
+ if (method == "check" || method == "request") {
29
+ if (!MANIFEST.containsKey(permission)) {
30
+ return promise.reject("unknown permission '$permission'", "bad_args")
31
+ }
32
+ }
33
+ when (method) {
34
+ "check" -> promise.resolve(check(permission))
35
+ "request" -> request(permission) { promise.resolve(it) }
36
+ else -> promise.rejectUnknownMethod(method)
37
+ }
38
+ }
39
+
40
+ /** Current status of `permission` without prompting. */
41
+ fun check(permission: String): String {
42
+ val manifest = MANIFEST[permission] ?: return UNDETERMINED
43
+ if (permission == "notifications" && Build.VERSION.SDK_INT < 33) return GRANTED
44
+ if (permission == "photo_library" && Build.VERSION.SDK_INT < 33) {
45
+ return statusOf("android.permission.READ_EXTERNAL_STORAGE")
46
+ }
47
+ return statusOf(manifest)
48
+ }
49
+
50
+ private fun statusOf(manifest: String): String {
51
+ val ctx = PNBridge.activity() ?: return UNDETERMINED
52
+ val granted = ContextCompat.checkSelfPermission(ctx, manifest) == PackageManager.PERMISSION_GRANTED
53
+ if (granted) return GRANTED
54
+ // "denied" with no rationale after a previous denial means "don't ask again".
55
+ val asked = ctx.getSharedPreferences("pn_permissions", 0).getBoolean(manifest, false)
56
+ return if (asked && !ActivityCompat.shouldShowRequestPermissionRationale(ctx, manifest)) BLOCKED else DENIED
57
+ }
58
+
59
+ /** Prompt for `permission` if needed and report the resulting status to `onDone`. */
60
+ fun request(permission: String, onDone: (String) -> Unit) {
61
+ val manifest = MANIFEST[permission] ?: return onDone(UNDETERMINED)
62
+ if (check(permission) == GRANTED) return onDone(GRANTED)
63
+ val activity = PNBridge.activity() ?: return onDone(check(permission))
64
+ val target = if (permission == "photo_library" && Build.VERSION.SDK_INT < 33) "android.permission.READ_EXTERNAL_STORAGE" else manifest
65
+ val code = RequestCodes.next()
66
+ pending[code] = target to onDone
67
+ try {
68
+ ActivityCompat.requestPermissions(activity, arrayOf(target), code)
69
+ } catch (e: Exception) {
70
+ pending.remove(code)
71
+ onDone(check(permission))
72
+ }
73
+ }
74
+
75
+ /** Route `Activity.onRequestPermissionsResult`; `true` when a pending request matched. */
76
+ fun onRequestPermissionsResult(requestCode: Int, grantResults: IntArray): Boolean {
77
+ val (manifest, onDone) = pending.remove(requestCode) ?: return false
78
+ PNBridge.activity()?.getSharedPreferences("pn_permissions", 0)?.edit()?.putBoolean(manifest, true)?.apply()
79
+ val granted = grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED
80
+ onDone(if (granted) GRANTED else statusOf(manifest))
81
+ return true
82
+ }
83
+
84
+ companion object {
85
+ const val GRANTED = "granted"
86
+ const val DENIED = "denied"
87
+ const val BLOCKED = "blocked"
88
+ const val UNDETERMINED = "undetermined"
89
+
90
+ val MANIFEST = mapOf(
91
+ "camera" to "android.permission.CAMERA",
92
+ "microphone" to "android.permission.RECORD_AUDIO",
93
+ "photo_library" to "android.permission.READ_MEDIA_IMAGES",
94
+ "location_when_in_use" to "android.permission.ACCESS_FINE_LOCATION",
95
+ "contacts" to "android.permission.READ_CONTACTS",
96
+ "notifications" to "android.permission.POST_NOTIFICATIONS",
97
+ )
98
+ }
99
+ }
@@ -0,0 +1,89 @@
1
+ package com.pythonnative.runtime.modules
2
+
3
+ import android.content.Context
4
+ import android.content.SharedPreferences
5
+ import com.pythonnative.runtime.PNBridge
6
+ import com.pythonnative.runtime.bridge.PNLog
7
+ import com.pythonnative.runtime.bridge.str
8
+ import org.json.JSONObject
9
+
10
+ /** `Storage`: `get/set/delete/all_keys/clear` over the `pn_async_storage` SharedPreferences file. */
11
+ class StorageModule : NativeModule {
12
+ override val name = "Storage"
13
+
14
+ private fun prefs(): SharedPreferences =
15
+ PNBridge.context().getSharedPreferences("pn_async_storage", Context.MODE_PRIVATE)
16
+
17
+ override fun call(method: String, args: JSONObject, promise: Promise) {
18
+ val key = args.str("key")
19
+ when (method) {
20
+ "get", "get_item" -> promise.resolve(prefs().getString(key ?: "", null))
21
+ "set", "set_item" -> {
22
+ prefs().edit().putString(key ?: "", args.str("value") ?: "").apply()
23
+ promise.resolve(null)
24
+ }
25
+ "delete", "remove", "remove_item" -> {
26
+ prefs().edit().remove(key ?: "").apply()
27
+ promise.resolve(null)
28
+ }
29
+ "all_keys", "get_all_keys" -> promise.resolve(prefs().all.keys.sorted())
30
+ "clear" -> {
31
+ prefs().edit().clear().apply()
32
+ promise.resolve(null)
33
+ }
34
+ else -> promise.rejectUnknownMethod(method)
35
+ }
36
+ }
37
+ }
38
+
39
+ /**
40
+ * `SecureStore`: `set_item/get_item/delete_item` over `EncryptedSharedPreferences`.
41
+ *
42
+ * security-crypto 1.1 deprecates the whole API in favour of hand-rolled Keystore code, but the
43
+ * file name and schemes must stay identical to what earlier PythonNative releases wrote so that
44
+ * existing secrets remain readable, hence the suppression.
45
+ */
46
+ @Suppress("DEPRECATION")
47
+ class SecureStoreModule : NativeModule {
48
+ override val name = "SecureStore"
49
+ private var prefs: SharedPreferences? = null
50
+
51
+ private fun prefs(): SharedPreferences? {
52
+ prefs?.let { return it }
53
+ return try {
54
+ val ctx = PNBridge.context()
55
+ val master = androidx.security.crypto.MasterKey.Builder(ctx)
56
+ .setKeyScheme(androidx.security.crypto.MasterKey.KeyScheme.AES256_GCM)
57
+ .build()
58
+ androidx.security.crypto.EncryptedSharedPreferences.create(
59
+ ctx,
60
+ "com.pythonnative.securestore",
61
+ master,
62
+ androidx.security.crypto.EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
63
+ androidx.security.crypto.EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
64
+ ).also { prefs = it }
65
+ } catch (e: Exception) {
66
+ PNLog.rateLimited("securestore", "EncryptedSharedPreferences unavailable", e)
67
+ null
68
+ }
69
+ }
70
+
71
+ override fun call(method: String, args: JSONObject, promise: Promise) {
72
+ val key = args.str("key") ?: ""
73
+ val store = prefs()
74
+ when (method) {
75
+ "set_item" -> {
76
+ if (store == null) return promise.resolve(false)
77
+ store.edit().putString(key, args.str("value") ?: "").apply()
78
+ promise.resolve(true)
79
+ }
80
+ "get_item" -> promise.resolve(store?.getString(key, null))
81
+ "delete_item" -> {
82
+ if (store == null) return promise.resolve(false)
83
+ store.edit().remove(key).apply()
84
+ promise.resolve(true)
85
+ }
86
+ else -> promise.rejectUnknownMethod(method)
87
+ }
88
+ }
89
+ }
@@ -0,0 +1,178 @@
1
+ package com.pythonnative.runtime.modules
2
+
3
+ import android.app.Activity
4
+ import android.content.BroadcastReceiver
5
+ import android.content.Context
6
+ import android.content.Intent
7
+ import android.content.IntentFilter
8
+ import android.net.ConnectivityManager
9
+ import android.net.Network
10
+ import android.net.NetworkCapabilities
11
+ import android.os.BatteryManager
12
+ import com.pythonnative.runtime.PNBridge
13
+ import com.pythonnative.runtime.bridge.MainThread
14
+ import com.pythonnative.runtime.bridge.PNLog
15
+ import org.json.JSONObject
16
+
17
+ /**
18
+ * `Battery`: `get_level()` (0..1 or -1) and `get_state()`
19
+ * (`unknown|unplugged|charging|full`), plus `change` events from the
20
+ * sticky `ACTION_BATTERY_CHANGED` broadcast.
21
+ */
22
+ class BatteryModule : NativeModule {
23
+ override val name = "Battery"
24
+ private var receiver: BroadcastReceiver? = null
25
+
26
+ override fun call(method: String, args: JSONObject, promise: Promise) {
27
+ when (method) {
28
+ "get_level" -> promise.resolve(level())
29
+ "get_state" -> promise.resolve(state())
30
+ else -> promise.rejectUnknownMethod(method)
31
+ }
32
+ }
33
+
34
+ private fun manager(): BatteryManager? =
35
+ PNBridge.context().getSystemService(Context.BATTERY_SERVICE) as? BatteryManager
36
+
37
+ private fun level(): Double {
38
+ val pct = manager()?.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) ?: return -1.0
39
+ return if (pct in 0..100) pct / 100.0 else -1.0
40
+ }
41
+
42
+ private fun state(): String = stateName(manager()?.getIntProperty(BatteryManager.BATTERY_PROPERTY_STATUS) ?: -1)
43
+
44
+ private fun stateName(status: Int): String = when (status) {
45
+ BatteryManager.BATTERY_STATUS_CHARGING -> "charging"
46
+ BatteryManager.BATTERY_STATUS_FULL -> "full"
47
+ BatteryManager.BATTERY_STATUS_DISCHARGING, BatteryManager.BATTERY_STATUS_NOT_CHARGING -> "unplugged"
48
+ else -> "unknown"
49
+ }
50
+
51
+ fun attach(activity: Activity) {
52
+ if (receiver != null) return
53
+ val r = object : BroadcastReceiver() {
54
+ override fun onReceive(context: Context?, intent: Intent?) {
55
+ if (intent == null) return
56
+ val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
57
+ val scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
58
+ val status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
59
+ val fraction = if (level >= 0 && scale > 0) level.toDouble() / scale.toDouble() else -1.0
60
+ ModuleEvents.emit(name, "change", JSONObject().put("level", fraction).put("state", stateName(status)))
61
+ }
62
+ }
63
+ try {
64
+ activity.registerReceiver(r, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
65
+ receiver = r
66
+ } catch (e: Exception) {
67
+ PNLog.swallowed("Battery.attach", e)
68
+ }
69
+ }
70
+
71
+ fun detach(activity: Activity) {
72
+ receiver?.let {
73
+ try {
74
+ activity.unregisterReceiver(it)
75
+ } catch (e: Exception) {
76
+ PNLog.swallowed("Battery.detach", e)
77
+ }
78
+ }
79
+ receiver = null
80
+ }
81
+ }
82
+
83
+ /**
84
+ * `NetInfo.fetch()` → `{is_connected, type, is_internet_reachable}`;
85
+ * a default `NetworkCallback` emits `change` events on the main thread.
86
+ */
87
+ class NetInfoModule : NativeModule {
88
+ override val name = "NetInfo"
89
+ private var callback: ConnectivityManager.NetworkCallback? = null
90
+ private var last: JSONObject? = null
91
+
92
+ override fun call(method: String, args: JSONObject, promise: Promise) {
93
+ when (method) {
94
+ "fetch" -> promise.resolve(snapshot())
95
+ else -> promise.rejectUnknownMethod(method)
96
+ }
97
+ }
98
+
99
+ private fun manager(): ConnectivityManager? =
100
+ PNBridge.context().getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
101
+
102
+ fun snapshot(): JSONObject {
103
+ val offline = JSONObject().put("is_connected", false).put("type", "none").put("is_internet_reachable", false)
104
+ return try {
105
+ val manager = manager() ?: return offline
106
+ val network = manager.activeNetwork ?: return offline
107
+ val caps = manager.getNetworkCapabilities(network) ?: return offline
108
+ val kind = when {
109
+ caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> "wifi"
110
+ caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> "cellular"
111
+ caps.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> "ethernet"
112
+ else -> "other"
113
+ }
114
+ JSONObject()
115
+ .put("is_connected", true)
116
+ .put("type", kind)
117
+ .put("is_internet_reachable", caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET))
118
+ } catch (e: Exception) {
119
+ offline
120
+ }
121
+ }
122
+
123
+ fun attach(activity: Activity) {
124
+ if (callback != null) return
125
+ try {
126
+ val manager = activity.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
127
+ val cb = object : ConnectivityManager.NetworkCallback() {
128
+ override fun onAvailable(network: Network) = changed()
129
+ override fun onLost(network: Network) = changed()
130
+ override fun onCapabilitiesChanged(network: Network, capabilities: NetworkCapabilities) = changed()
131
+ }
132
+ manager.registerDefaultNetworkCallback(cb)
133
+ callback = cb
134
+ } catch (e: Exception) {
135
+ PNLog.swallowed("NetInfo.attach", e)
136
+ }
137
+ }
138
+
139
+ private fun changed() {
140
+ // NetworkCallback fires on a binder thread; hop to main before reading state.
141
+ MainThread.post {
142
+ val current = snapshot()
143
+ if (last?.toString() == current.toString()) return@post
144
+ last = current
145
+ ModuleEvents.emit(name, "change", current)
146
+ }
147
+ }
148
+
149
+ fun detach(activity: Activity) {
150
+ callback?.let {
151
+ try {
152
+ (activity.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).unregisterNetworkCallback(it)
153
+ } catch (e: Exception) {
154
+ PNLog.swallowed("NetInfo.detach", e)
155
+ }
156
+ }
157
+ callback = null
158
+ }
159
+ }
160
+
161
+ /** `AppState.current_state()` plus `change` events (`active|inactive|background`). */
162
+ class AppStateModule : NativeModule {
163
+ override val name = "AppState"
164
+ private var state = "active"
165
+
166
+ override fun call(method: String, args: JSONObject, promise: Promise) {
167
+ when (method) {
168
+ "current_state" -> promise.resolve(state)
169
+ else -> promise.rejectUnknownMethod(method)
170
+ }
171
+ }
172
+
173
+ fun transition(next: String) {
174
+ if (state == next) return
175
+ state = next
176
+ ModuleEvents.emit(name, "change", JSONObject().put("state", next))
177
+ }
178
+ }
@@ -0,0 +1,16 @@
1
+ package com.pythonnative.runtime.plugins
2
+
3
+ import com.pythonnative.runtime.bridge.PNRegistry
4
+
5
+ /**
6
+ * Plugin registrations generated by `pn build`.
7
+ *
8
+ * The build tool overwrites this file with one `register` call per
9
+ * plugin entry declared in the project's `pythonnative.plugins` entry
10
+ * points. Nothing else may depend on its content beyond [registerAll].
11
+ */
12
+ object GeneratedPlugins {
13
+ /** Register every generated plugin with `registry`. */
14
+ @Suppress("UNUSED_PARAMETER")
15
+ fun registerAll(registry: PNRegistry) {}
16
+ }