pythonnative 0.24.0__tar.gz → 0.25.0__tar.gz

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 (167) hide show
  1. {pythonnative-0.24.0/src/pythonnative.egg-info → pythonnative-0.25.0}/PKG-INFO +2 -1
  2. {pythonnative-0.24.0 → pythonnative-0.25.0}/README.md +1 -0
  3. {pythonnative-0.24.0 → pythonnative-0.25.0}/pyproject.toml +1 -1
  4. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/__init__.py +16 -4
  5. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/animated.py +2 -2
  6. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/components.py +59 -0
  7. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/hooks.py +364 -81
  8. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/notifications.py +36 -4
  9. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/permissions.py +24 -1
  10. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_views/android.py +7 -2
  11. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_views/ios.py +12 -1
  12. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/reconciler.py +518 -37
  13. pythonnative-0.25.0/src/pythonnative/runtime.py +704 -0
  14. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/screen.py +53 -7
  15. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/storage.py +2 -2
  16. pythonnative-0.25.0/src/pythonnative/suspense.py +417 -0
  17. {pythonnative-0.24.0 → pythonnative-0.25.0/src/pythonnative.egg-info}/PKG-INFO +2 -1
  18. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative.egg-info/SOURCES.txt +3 -0
  19. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_async_hooks.py +110 -83
  20. pythonnative-0.25.0/tests/test_runtime.py +252 -0
  21. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_storage.py +15 -23
  22. pythonnative-0.25.0/tests/test_suspense.py +547 -0
  23. pythonnative-0.25.0/tests/test_transitions.py +178 -0
  24. pythonnative-0.24.0/src/pythonnative/runtime.py +0 -512
  25. pythonnative-0.24.0/tests/test_runtime.py +0 -146
  26. {pythonnative-0.24.0 → pythonnative-0.25.0}/LICENSE +0 -0
  27. {pythonnative-0.24.0 → pythonnative-0.25.0}/setup.cfg +0 -0
  28. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/_ios_log.py +0 -0
  29. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/alerts.py +0 -0
  30. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/appearance.py +0 -0
  31. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/cli/__init__.py +0 -0
  32. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/cli/pn.py +0 -0
  33. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/diagnostics.py +0 -0
  34. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/element.py +0 -0
  35. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/events.py +0 -0
  36. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/gestures.py +0 -0
  37. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/hot_reload.py +0 -0
  38. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/images.py +0 -0
  39. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/layout.py +0 -0
  40. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/mutations.py +0 -0
  41. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/__init__.py +0 -0
  42. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/app_state.py +0 -0
  43. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/battery.py +0 -0
  44. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/biometrics.py +0 -0
  45. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/camera.py +0 -0
  46. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/clipboard.py +0 -0
  47. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/file_system.py +0 -0
  48. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/haptics.py +0 -0
  49. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/linking.py +0 -0
  50. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/location.py +0 -0
  51. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/net_info.py +0 -0
  52. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/secure_store.py +0 -0
  53. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_modules/share.py +0 -0
  54. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_views/__init__.py +0 -0
  55. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_views/base.py +0 -0
  56. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/native_views/desktop.py +0 -0
  57. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/navigation.py +0 -0
  58. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/net.py +0 -0
  59. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/platform.py +0 -0
  60. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/platform_metrics.py +0 -0
  61. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/preview.py +0 -0
  62. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/project/__init__.py +0 -0
  63. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/project/android.py +0 -0
  64. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/project/builder.py +0 -0
  65. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/project/config.py +0 -0
  66. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/project/doctor.py +0 -0
  67. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/project/icons.py +0 -0
  68. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/project/ios.py +0 -0
  69. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/project/permissions.py +0 -0
  70. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/project/runtime_assets.py +0 -0
  71. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/sdk/__init__.py +0 -0
  72. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/sdk/_components.py +0 -0
  73. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/style.py +0 -0
  74. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/build.gradle +0 -0
  75. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/proguard-rules.pro +0 -0
  76. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/androidTest/java/com/pythonnative/android_template/ExampleInstrumentedTest.kt +0 -0
  77. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +0 -0
  78. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +0 -0
  79. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/Navigator.kt +0 -0
  80. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNAccessibilityDelegate.kt +0 -0
  81. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNBorderDrawable.kt +0 -0
  82. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNVirtualListView.java +0 -0
  83. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/ScreenFragment.kt +0 -0
  84. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/drawable/ic_launcher_background.xml +0 -0
  85. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +0 -0
  86. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/layout/activity_main.xml +0 -0
  87. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +0 -0
  88. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +0 -0
  89. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
  90. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp +0 -0
  91. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
  92. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp +0 -0
  93. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
  94. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp +0 -0
  95. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
  96. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp +0 -0
  97. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
  98. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp +0 -0
  99. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/navigation/nav_graph.xml +0 -0
  100. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/values/colors.xml +0 -0
  101. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/values/strings.xml +0 -0
  102. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/values/themes.xml +0 -0
  103. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/values-night/themes.xml +0 -0
  104. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/xml/backup_rules.xml +0 -0
  105. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/main/res/xml/data_extraction_rules.xml +0 -0
  106. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/app/src/test/java/com/pythonnative/android_template/ExampleUnitTest.kt +0 -0
  107. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/build.gradle +0 -0
  108. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.jar +0 -0
  109. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.properties +0 -0
  110. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/gradle.properties +0 -0
  111. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/gradlew +0 -0
  112. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/gradlew.bat +0 -0
  113. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/android_template/settings.gradle +0 -0
  114. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/AppDelegate.swift +0 -0
  115. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/AccentColor.colorset/Contents.json +0 -0
  116. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
  117. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/Contents.json +0 -0
  118. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/Base.lproj/LaunchScreen.storyboard +0 -0
  119. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/Base.lproj/Main.storyboard +0 -0
  120. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/Info.plist +0 -0
  121. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +0 -0
  122. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template/ViewController.swift +0 -0
  123. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +0 -0
  124. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -0
  125. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift +0 -0
  126. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift +0 -0
  127. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift +0 -0
  128. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/utils.py +0 -0
  129. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative/virtual_rows.py +0 -0
  130. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative.egg-info/dependency_links.txt +0 -0
  131. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative.egg-info/entry_points.txt +0 -0
  132. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative.egg-info/requires.txt +0 -0
  133. {pythonnative-0.24.0 → pythonnative-0.25.0}/src/pythonnative.egg-info/top_level.txt +0 -0
  134. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_alert.py +0 -0
  135. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_animated.py +0 -0
  136. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_appearance.py +0 -0
  137. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_cli.py +0 -0
  138. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_components.py +0 -0
  139. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_core_semantics.py +0 -0
  140. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_desktop_backend.py +0 -0
  141. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_element.py +0 -0
  142. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_events.py +0 -0
  143. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_extended_components.py +0 -0
  144. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_gestures.py +0 -0
  145. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_hooks.py +0 -0
  146. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_hot_reload.py +0 -0
  147. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_images.py +0 -0
  148. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_incremental_render.py +0 -0
  149. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_ios_log.py +0 -0
  150. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_layout.py +0 -0
  151. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_metric_hooks.py +0 -0
  152. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_mutations.py +0 -0
  153. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_native_lists.py +0 -0
  154. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_native_modules.py +0 -0
  155. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_native_views.py +0 -0
  156. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_navigation.py +0 -0
  157. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_net.py +0 -0
  158. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_new_components.py +0 -0
  159. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_platform.py +0 -0
  160. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_platform_metrics.py +0 -0
  161. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_reconciler.py +0 -0
  162. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_ref.py +0 -0
  163. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_screen.py +0 -0
  164. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_sdk.py +0 -0
  165. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_smoke.py +0 -0
  166. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_style.py +0 -0
  167. {pythonnative-0.24.0 → pythonnative-0.25.0}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythonnative
3
- Version: 0.24.0
3
+ Version: 0.25.0
4
4
  Summary: Cross-platform native UI toolkit for Android and iOS
5
5
  Author: Owen Carey
6
6
  License: MIT License
@@ -105,6 +105,7 @@ PythonNative is a cross-platform toolkit for building native Android and iOS app
105
105
  - **Rich component library:** 25+ built-in components backed by real native widgets: `TextInput`, `Image` / `ImageBackground`, `ScrollView`, `FlatList` / `SectionList`, `Modal`, `Pressable` / `TouchableOpacity`, `Switch` / `Checkbox`, `Slider`, `SegmentedControl`, `Picker`, `DatePicker`, `ProgressBar` / `ActivityIndicator`, `WebView`, and more.
106
106
  - **Device APIs:** Cross-platform modules for `Camera`, `Location`, `FileSystem`, `Notifications`, `Clipboard`, `Share`, `Linking`, `Permissions`, `AppState`, `NetInfo`, `SecureStore`, `Battery`, `Haptics` / `Vibration`, and `Biometrics`, plus reactive `use_app_state` and `use_net_info` hooks.
107
107
  - **Hooks and function components:** Manage state with `use_state`, side effects with `use_effect` / `use_layout_effect`, refs and imperative handles with `use_ref` / `use_imperative_handle`, and navigation with `use_navigation`, all through one consistent pattern. Components can return a single element, a list of siblings, or `None`, and `Fragment`, `Portal`, and reactive `Provider` context work the way they do in React.
108
+ - **Async-first rendering:** One `asyncio` event loop runs the whole framework on the platform's main thread. Components can be `async def` and `await` data directly in the body; `Suspense` boundaries show declarative loading states while they wait. `use_resource` fetches during render, `use_effect` accepts coroutine callbacks (cancelled automatically on unmount), `lazy` code-splits components, and `use_transition` / `use_deferred_value` keep the UI responsive during expensive updates.
108
109
  - **Developer feedback that finds your bugs:** In dev mode (`pn preview`, hot reload, or `PN_DEV=1`), uncaught errors from renders, effects, and event handlers show a full-screen RedBox with the traceback; unknown style keys and duplicate list keys print "did you mean" warnings; and conditional hooks raise a `HookOrderError` at the source instead of silently cross-wiring state.
109
110
  - **Typed `style` prop:** Pass all visual and layout properties through a single `style` dict, fully described by the `pn.Style` `TypedDict` and the ergonomic `pn.style(...)` helper for IDE autocomplete and static checking. Compose reusable styles with `StyleSheet`.
110
111
  - **Cross-platform flexbox engine:** A pure-Python, Yoga-style layout engine computes frames once and applies them to native views, so `flex`, `padding`, `aspect_ratio`, and `position: "absolute"` produce the same geometry on Android and iOS.
@@ -34,6 +34,7 @@ PythonNative is a cross-platform toolkit for building native Android and iOS app
34
34
  - **Rich component library:** 25+ built-in components backed by real native widgets: `TextInput`, `Image` / `ImageBackground`, `ScrollView`, `FlatList` / `SectionList`, `Modal`, `Pressable` / `TouchableOpacity`, `Switch` / `Checkbox`, `Slider`, `SegmentedControl`, `Picker`, `DatePicker`, `ProgressBar` / `ActivityIndicator`, `WebView`, and more.
35
35
  - **Device APIs:** Cross-platform modules for `Camera`, `Location`, `FileSystem`, `Notifications`, `Clipboard`, `Share`, `Linking`, `Permissions`, `AppState`, `NetInfo`, `SecureStore`, `Battery`, `Haptics` / `Vibration`, and `Biometrics`, plus reactive `use_app_state` and `use_net_info` hooks.
36
36
  - **Hooks and function components:** Manage state with `use_state`, side effects with `use_effect` / `use_layout_effect`, refs and imperative handles with `use_ref` / `use_imperative_handle`, and navigation with `use_navigation`, all through one consistent pattern. Components can return a single element, a list of siblings, or `None`, and `Fragment`, `Portal`, and reactive `Provider` context work the way they do in React.
37
+ - **Async-first rendering:** One `asyncio` event loop runs the whole framework on the platform's main thread. Components can be `async def` and `await` data directly in the body; `Suspense` boundaries show declarative loading states while they wait. `use_resource` fetches during render, `use_effect` accepts coroutine callbacks (cancelled automatically on unmount), `lazy` code-splits components, and `use_transition` / `use_deferred_value` keep the UI responsive during expensive updates.
37
38
  - **Developer feedback that finds your bugs:** In dev mode (`pn preview`, hot reload, or `PN_DEV=1`), uncaught errors from renders, effects, and event handlers show a full-screen RedBox with the traceback; unknown style keys and duplicate list keys print "did you mean" warnings; and conditional hooks raise a `HookOrderError` at the source instead of silently cross-wiring state.
38
39
  - **Typed `style` prop:** Pass all visual and layout properties through a single `style` dict, fully described by the `pn.Style` `TypedDict` and the ergonomic `pn.style(...)` helper for IDE autocomplete and static checking. Compose reusable styles with `StyleSheet`.
39
40
  - **Cross-platform flexbox engine:** A pure-Python, Yoga-style layout engine computes frames once and applies them to native views, so `flex`, `padding`, `aspect_ratio`, and `position: "absolute"` produce the same geometry on Android and iOS.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pythonnative"
7
- version = "0.24.0"
7
+ version = "0.25.0"
8
8
  description = "Cross-platform native UI toolkit for Android and iOS"
9
9
  authors = [
10
10
  { name = "Owen Carey" }
@@ -60,7 +60,7 @@ Example:
60
60
  ```
61
61
  """
62
62
 
63
- __version__ = "0.24.0"
63
+ __version__ = "0.25.0"
64
64
 
65
65
  from . import appearance, diagnostics, gestures, images, runtime, sdk
66
66
  from .alerts import Alert
@@ -92,6 +92,7 @@ from .components import (
92
92
  Slider,
93
93
  Spacer,
94
94
  StatusBar,
95
+ Suspense,
95
96
  Switch,
96
97
  Text,
97
98
  TextInput,
@@ -111,11 +112,11 @@ from .hooks import (
111
112
  component,
112
113
  create_context,
113
114
  memo,
114
- use_async_effect,
115
115
  use_back_handler,
116
116
  use_callback,
117
117
  use_color_scheme,
118
118
  use_context,
119
+ use_deferred_value,
119
120
  use_effect,
120
121
  use_imperative_handle,
121
122
  use_keyboard_height,
@@ -126,8 +127,10 @@ from .hooks import (
126
127
  use_query,
127
128
  use_reducer,
128
129
  use_ref,
130
+ use_resource,
129
131
  use_safe_area_insets,
130
132
  use_state,
133
+ use_transition,
131
134
  use_window_dimensions,
132
135
  )
133
136
  from .native_modules import (
@@ -160,7 +163,7 @@ from .navigation import (
160
163
  )
161
164
  from .net import HTTPError, Response, fetch
162
165
  from .platform import Platform
163
- from .runtime import run_async
166
+ from .runtime import run_async, run_blocking
164
167
  from .screen import create_screen
165
168
  from .sdk import (
166
169
  Props,
@@ -204,6 +207,7 @@ from .style import (
204
207
  style,
205
208
  use_theme,
206
209
  )
210
+ from .suspense import Resource, lazy, start_resource
207
211
 
208
212
  __all__ = [
209
213
  # Components
@@ -233,6 +237,7 @@ __all__ = [
233
237
  "Slider",
234
238
  "Spacer",
235
239
  "StatusBar",
240
+ "Suspense",
236
241
  "Switch",
237
242
  "Text",
238
243
  "TextInput",
@@ -251,11 +256,11 @@ __all__ = [
251
256
  "MutationState",
252
257
  "QueryResult",
253
258
  "Ref",
254
- "use_async_effect",
255
259
  "use_back_handler",
256
260
  "use_callback",
257
261
  "use_color_scheme",
258
262
  "use_context",
263
+ "use_deferred_value",
259
264
  "use_effect",
260
265
  "use_focus_effect",
261
266
  "use_imperative_handle",
@@ -268,11 +273,17 @@ __all__ = [
268
273
  "use_query",
269
274
  "use_reducer",
270
275
  "use_ref",
276
+ "use_resource",
271
277
  "use_route",
272
278
  "use_safe_area_insets",
273
279
  "use_state",
280
+ "use_transition",
274
281
  "use_window_dimensions",
275
282
  "Provider",
283
+ # Suspense and async rendering
284
+ "Resource",
285
+ "lazy",
286
+ "start_resource",
276
287
  # Navigation
277
288
  "NavigationContainer",
278
289
  "ScreenOptions",
@@ -349,6 +360,7 @@ __all__ = [
349
360
  "Response",
350
361
  # Runtime
351
362
  "run_async",
363
+ "run_blocking",
352
364
  "runtime",
353
365
  # Diagnostics
354
366
  "HookOrderError",
@@ -47,7 +47,7 @@ Example:
47
47
  await pn.Animated.timing(opacity, to=1.0, duration=400)
48
48
  await pn.Animated.timing(opacity, to=0.5, duration=200)
49
49
 
50
- pn.use_async_effect(fade_in, [])
50
+ pn.use_effect(fade_in, [])
51
51
 
52
52
  return pn.Animated.View(
53
53
  pn.Text("Hello!"),
@@ -1014,7 +1014,7 @@ def use_animated_value(initial: float = 0.0) -> AnimatedValue:
1014
1014
  async def fade_in():
1015
1015
  await pn.Animated.timing(opacity, to=1.0, duration=300)
1016
1016
 
1017
- pn.use_async_effect(fade_in, [])
1017
+ pn.use_effect(fade_in, [])
1018
1018
  return pn.Animated.View(
1019
1019
  pn.Text("Hello"),
1020
1020
  style=pn.style(opacity=opacity),
@@ -1732,6 +1732,65 @@ def ErrorBoundary(
1732
1732
  return Element("__ErrorBoundary__", props, list(children), key=key)
1733
1733
 
1734
1734
 
1735
+ def Suspense(
1736
+ *children: Element,
1737
+ fallback: Optional[Any] = None,
1738
+ key: Optional[str] = None,
1739
+ ) -> Element:
1740
+ """Show ``fallback`` while descendants wait on async work, then swap in the content.
1741
+
1742
+ A Suspense boundary catches **suspensions** from the subtree it
1743
+ wraps: an ``async def`` component body blocking on a pending
1744
+ await, or a regular component calling
1745
+ [`Resource.read`][pythonnative.suspense.Resource.read] on data that hasn't
1746
+ arrived (see [`use_resource`][pythonnative.use_resource] and
1747
+ [`lazy`][pythonnative.lazy]). While anything is pending the
1748
+ boundary renders ``fallback``; when the awaited work completes it
1749
+ retries the content and swaps it in. Suspended components keep
1750
+ their hook state across retries, so cached resources aren't
1751
+ refetched.
1752
+
1753
+ Two timing behaviors, matching React:
1754
+
1755
+ - **Initial mount**: the fallback shows until the content is ready.
1756
+ - **Updates**: a component that's already on screen and suspends
1757
+ again (its dependencies changed) keeps its previous content
1758
+ visible and re-renders when ready; there's no fallback flash.
1759
+
1760
+ Args:
1761
+ *children: Subtree to wrap (the async content).
1762
+ fallback: Content shown while suspended: an
1763
+ [`Element`][pythonnative.Element] or a zero-arg callable
1764
+ returning one. Without it, suspensions propagate to the
1765
+ next Suspense boundary up.
1766
+ key: Stable identity for keyed reconciliation.
1767
+
1768
+ Returns:
1769
+ An [`Element`][pythonnative.Element] of type ``"__Suspense__"``.
1770
+
1771
+ Example:
1772
+ ```python
1773
+ import pythonnative as pn
1774
+
1775
+ @pn.component
1776
+ async def Profile(user_id: str):
1777
+ user = await api.fetch_user(user_id)
1778
+ return pn.Text(user.name)
1779
+
1780
+ @pn.component
1781
+ def Screen():
1782
+ return pn.Suspense(
1783
+ Profile(user_id="42"),
1784
+ fallback=pn.ActivityIndicator(),
1785
+ )
1786
+ ```
1787
+ """
1788
+ props: Dict[str, Any] = {}
1789
+ if fallback is not None:
1790
+ props["__fallback__"] = fallback
1791
+ return Element("__Suspense__", props, list(children), key=key)
1792
+
1793
+
1735
1794
  # ======================================================================
1736
1795
  # Lists (native virtualization with a Python-windowed fallback)
1737
1796
  # ======================================================================