pythonnative 0.8.0__tar.gz → 0.10.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 (107) hide show
  1. {pythonnative-0.8.0/src/pythonnative.egg-info → pythonnative-0.10.0}/PKG-INFO +3 -1
  2. {pythonnative-0.8.0 → pythonnative-0.10.0}/pyproject.toml +29 -3
  3. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/__init__.py +28 -3
  4. pythonnative-0.10.0/src/pythonnative/_ios_log.py +92 -0
  5. pythonnative-0.10.0/src/pythonnative/cli/__init__.py +7 -0
  6. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/cli/pn.py +397 -47
  7. pythonnative-0.10.0/src/pythonnative/components.py +649 -0
  8. pythonnative-0.10.0/src/pythonnative/element.py +77 -0
  9. pythonnative-0.10.0/src/pythonnative/hooks.py +706 -0
  10. pythonnative-0.10.0/src/pythonnative/hot_reload.py +329 -0
  11. pythonnative-0.10.0/src/pythonnative/native_modules/__init__.py +25 -0
  12. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/native_modules/camera.py +32 -16
  13. pythonnative-0.10.0/src/pythonnative/native_modules/file_system.py +241 -0
  14. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/native_modules/location.py +32 -9
  15. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/native_modules/notifications.py +51 -18
  16. pythonnative-0.10.0/src/pythonnative/native_views/__init__.py +172 -0
  17. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/native_views/android.py +14 -7
  18. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/native_views/base.py +68 -11
  19. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/native_views/ios.py +13 -6
  20. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/navigation.py +288 -63
  21. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/page.py +248 -48
  22. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/reconciler.py +59 -25
  23. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/style.py +79 -18
  24. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +4 -0
  25. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PageFragment.kt +23 -0
  26. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/ios_template/ios_template/ViewController.swift +52 -25
  27. pythonnative-0.10.0/src/pythonnative/utils.py +184 -0
  28. {pythonnative-0.8.0 → pythonnative-0.10.0/src/pythonnative.egg-info}/PKG-INFO +3 -1
  29. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative.egg-info/SOURCES.txt +6 -1
  30. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative.egg-info/requires.txt +2 -0
  31. pythonnative-0.10.0/tests/test_cli.py +182 -0
  32. pythonnative-0.10.0/tests/test_hot_reload.py +97 -0
  33. pythonnative-0.10.0/tests/test_ios_log.py +147 -0
  34. pythonnative-0.10.0/tests/test_page.py +68 -0
  35. pythonnative-0.10.0/tests/test_utils.py +70 -0
  36. pythonnative-0.8.0/src/pythonnative/cli/__init__.py +0 -0
  37. pythonnative-0.8.0/src/pythonnative/components.py +0 -408
  38. pythonnative-0.8.0/src/pythonnative/element.py +0 -53
  39. pythonnative-0.8.0/src/pythonnative/hooks.py +0 -440
  40. pythonnative-0.8.0/src/pythonnative/hot_reload.py +0 -143
  41. pythonnative-0.8.0/src/pythonnative/native_modules/__init__.py +0 -19
  42. pythonnative-0.8.0/src/pythonnative/native_modules/file_system.py +0 -131
  43. pythonnative-0.8.0/src/pythonnative/native_views/__init__.py +0 -87
  44. pythonnative-0.8.0/src/pythonnative/utils.py +0 -83
  45. pythonnative-0.8.0/tests/test_cli.py +0 -85
  46. {pythonnative-0.8.0 → pythonnative-0.10.0}/LICENSE +0 -0
  47. {pythonnative-0.8.0 → pythonnative-0.10.0}/README.md +0 -0
  48. {pythonnative-0.8.0 → pythonnative-0.10.0}/setup.cfg +0 -0
  49. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/build.gradle +0 -0
  50. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/proguard-rules.pro +0 -0
  51. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/androidTest/java/com/pythonnative/android_template/ExampleInstrumentedTest.kt +0 -0
  52. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +0 -0
  53. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/Navigator.kt +0 -0
  54. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/drawable/ic_launcher_background.xml +0 -0
  55. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +0 -0
  56. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/layout/activity_main.xml +0 -0
  57. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +0 -0
  58. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +0 -0
  59. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
  60. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp +0 -0
  61. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
  62. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp +0 -0
  63. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
  64. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp +0 -0
  65. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
  66. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp +0 -0
  67. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
  68. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp +0 -0
  69. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/navigation/nav_graph.xml +0 -0
  70. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/values/colors.xml +0 -0
  71. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/values/strings.xml +0 -0
  72. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/values/themes.xml +0 -0
  73. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/values-night/themes.xml +0 -0
  74. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/xml/backup_rules.xml +0 -0
  75. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/main/res/xml/data_extraction_rules.xml +0 -0
  76. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/app/src/test/java/com/pythonnative/android_template/ExampleUnitTest.kt +0 -0
  77. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/build.gradle +0 -0
  78. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.jar +0 -0
  79. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.properties +0 -0
  80. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/gradle.properties +0 -0
  81. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/gradlew +0 -0
  82. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/gradlew.bat +0 -0
  83. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/android_template/settings.gradle +0 -0
  84. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/ios_template/ios_template/AppDelegate.swift +0 -0
  85. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/AccentColor.colorset/Contents.json +0 -0
  86. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
  87. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/ios_template/ios_template/Assets.xcassets/Contents.json +0 -0
  88. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/ios_template/ios_template/Base.lproj/LaunchScreen.storyboard +0 -0
  89. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/ios_template/ios_template/Base.lproj/Main.storyboard +0 -0
  90. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/ios_template/ios_template/Info.plist +0 -0
  91. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +0 -0
  92. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +0 -0
  93. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -0
  94. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift +0 -0
  95. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift +0 -0
  96. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift +0 -0
  97. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative.egg-info/dependency_links.txt +0 -0
  98. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative.egg-info/entry_points.txt +0 -0
  99. {pythonnative-0.8.0 → pythonnative-0.10.0}/src/pythonnative.egg-info/top_level.txt +0 -0
  100. {pythonnative-0.8.0 → pythonnative-0.10.0}/tests/test_components.py +0 -0
  101. {pythonnative-0.8.0 → pythonnative-0.10.0}/tests/test_element.py +0 -0
  102. {pythonnative-0.8.0 → pythonnative-0.10.0}/tests/test_hooks.py +0 -0
  103. {pythonnative-0.8.0 → pythonnative-0.10.0}/tests/test_native_views.py +0 -0
  104. {pythonnative-0.8.0 → pythonnative-0.10.0}/tests/test_navigation.py +0 -0
  105. {pythonnative-0.8.0 → pythonnative-0.10.0}/tests/test_reconciler.py +0 -0
  106. {pythonnative-0.8.0 → pythonnative-0.10.0}/tests/test_smoke.py +0 -0
  107. {pythonnative-0.8.0 → pythonnative-0.10.0}/tests/test_style.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythonnative
3
- Version: 0.8.0
3
+ Version: 0.10.0
4
4
  Summary: Cross-platform native UI toolkit for Android and iOS
5
5
  Author: Owen Carey
6
6
  License: MIT License
@@ -48,6 +48,8 @@ Provides-Extra: docs
48
48
  Requires-Dist: mkdocs>=1.5; extra == "docs"
49
49
  Requires-Dist: mkdocs-material[imaging]>=9.5; extra == "docs"
50
50
  Requires-Dist: mkdocstrings[python]>=0.24; extra == "docs"
51
+ Requires-Dist: mkdocs-autorefs>=1.0; extra == "docs"
52
+ Requires-Dist: pymdown-extensions>=10.7; extra == "docs"
51
53
  Provides-Extra: dev
52
54
  Requires-Dist: black>=24.0; extra == "dev"
53
55
  Requires-Dist: ruff>=0.5; extra == "dev"
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pythonnative"
7
- version = "0.8.0"
7
+ version = "0.10.0"
8
8
  description = "Cross-platform native UI toolkit for Android and iOS"
9
9
  authors = [
10
10
  { name = "Owen Carey" }
@@ -35,6 +35,8 @@ docs = [
35
35
  "mkdocs>=1.5",
36
36
  "mkdocs-material[imaging]>=9.5",
37
37
  "mkdocstrings[python]>=0.24",
38
+ "mkdocs-autorefs>=1.0",
39
+ "pymdown-extensions>=10.7",
38
40
  ]
39
41
  dev = [
40
42
  "black>=24.0",
@@ -81,8 +83,32 @@ extend-exclude = [
81
83
  ]
82
84
 
83
85
  [tool.ruff.lint]
84
- select = ["E", "F", "I"]
85
- ignore = []
86
+ # Docstring (D) rules use the Google convention; see [tool.ruff.lint.pydocstyle].
87
+ # Selectively enabled so tests/examples/templates aren't penalized.
88
+ select = ["E", "F", "I", "D"]
89
+ # D107 (missing __init__ docstring): mkdocstrings is configured to merge
90
+ # __init__ into the class docstring, so the class docstring is the source of truth.
91
+ # D105 (magic method docstring): most are self-explanatory (__repr__, __eq__, etc.).
92
+ # D203/D213: conflict with Google convention defaults; ruff auto-suppresses
93
+ # these via `convention = "google"`, but we list them defensively.
94
+ ignore = ["D107", "D105", "D203", "D213"]
95
+
96
+ [tool.ruff.lint.per-file-ignores]
97
+ "tests/**/*.py" = ["D"]
98
+ "examples/**/*.py" = ["D"]
99
+ "src/pythonnative/templates/**/*.py" = ["D"]
100
+ "setup.py" = ["D"]
101
+ "conftest.py" = ["D"]
102
+ # Platform handler subclasses implement the ViewHandler ABC defined in
103
+ # native_views/base.py, which carries the canonical docstrings for the
104
+ # protocol. The concrete classes are internal (registered by name in
105
+ # NativeViewRegistry, never imported by users), so requiring per-method
106
+ # docstrings would only add boilerplate that repeats the ABC.
107
+ "src/pythonnative/native_views/android.py" = ["D101", "D102"]
108
+ "src/pythonnative/native_views/ios.py" = ["D101", "D102"]
109
+
110
+ [tool.ruff.lint.pydocstyle]
111
+ convention = "google"
86
112
 
87
113
  [tool.black]
88
114
  line-length = 120
@@ -1,7 +1,31 @@
1
- """PythonNative declarative native UI for Android and iOS.
1
+ """PythonNative: declarative native UI for Android and iOS.
2
2
 
3
- Public API::
3
+ PythonNative is a cross-platform toolkit that turns Python ``@component``
4
+ functions into real, native Android and iOS views. The component model
5
+ is React-like (function components plus hooks), but rendering happens
6
+ through direct platform bindings: Chaquopy on Android (Java) and
7
+ rubicon-objc on iOS (Objective-C). There is no JavaScript bridge.
4
8
 
9
+ Key building blocks:
10
+
11
+ - **Element factories** ([`Text`][pythonnative.Text],
12
+ [`Button`][pythonnative.Button], [`Column`][pythonnative.Column], etc.)
13
+ return immutable [`Element`][pythonnative.Element] descriptors.
14
+ - **Hooks** ([`use_state`][pythonnative.use_state],
15
+ [`use_effect`][pythonnative.use_effect],
16
+ [`use_reducer`][pythonnative.use_reducer], etc.) manage state, side
17
+ effects, and context inside `@component` functions.
18
+ - **Navigation** is built from
19
+ [`NavigationContainer`][pythonnative.NavigationContainer] plus one of
20
+ the [`create_stack_navigator`][pythonnative.create_stack_navigator],
21
+ [`create_tab_navigator`][pythonnative.create_tab_navigator], or
22
+ [`create_drawer_navigator`][pythonnative.create_drawer_navigator]
23
+ factories.
24
+ - **Styling** uses a single ``style`` dict per element (or a list of
25
+ dicts), composable via [`StyleSheet`][pythonnative.StyleSheet].
26
+
27
+ Example:
28
+ ```python
5
29
  import pythonnative as pn
6
30
 
7
31
  @pn.component
@@ -12,9 +36,10 @@ Public API::
12
36
  pn.Button("+", on_click=lambda: set_count(count + 1)),
13
37
  style={"spacing": 12},
14
38
  )
39
+ ```
15
40
  """
16
41
 
17
- __version__ = "0.8.0"
42
+ __version__ = "0.10.0"
18
43
 
19
44
  from .components import (
20
45
  ActivityIndicator,
@@ -0,0 +1,92 @@
1
+ """Route Python `sys.stdout`/`sys.stderr` through fd 2 on iOS.
2
+
3
+ When an app is launched via `xcrun simctl launch --console-pty`
4
+ (what `pn run ios` does), the simulator attaches the caller's
5
+ terminal to the app's stderr, which is the same channel `NSLog` and
6
+ `os_log` write to. Python `print()` calls, however, go to
7
+ `sys.stdout` (fd 1), and for reasons specific to how CPython's
8
+ embedded framework is started on the iOS Simulator that descriptor
9
+ does not reach the attached console. As a result, users see
10
+ Swift-side `NSLog` output but never their own `print()` output.
11
+
12
+ Redirecting `sys.stdout` and `sys.stderr` at a Python level to write
13
+ straight to fd 2 is a small, reliable fix: fd 2 *is* visible to
14
+ `simctl` (that is exactly how `NSLog` reaches the terminal), so
15
+ Python output lands next to the Swift logs with correct ordering.
16
+
17
+ This module is intentionally self-contained (no rubicon-objc or
18
+ platform-specific C bindings required), so it is safe to import
19
+ early during `pythonnative` package initialization.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import os
25
+ import sys
26
+ from typing import Iterable
27
+
28
+ _STDERR_FD = 2
29
+
30
+
31
+ class _StderrStream:
32
+ """Minimal text-mode file-like that writes UTF-8 bytes to fd 2.
33
+
34
+ Write-through (no buffering), so a `print()` call appears in the
35
+ terminal immediately. That matches user expectations for an
36
+ interactive "run on simulator" log stream.
37
+ """
38
+
39
+ encoding = "utf-8"
40
+ errors = "replace"
41
+ mode = "w"
42
+ name = "<stderr>"
43
+
44
+ def write(self, s: str) -> int:
45
+ if not s:
46
+ return 0
47
+ data = s.encode(self.encoding, self.errors)
48
+ try:
49
+ return os.write(_STDERR_FD, data)
50
+ except OSError:
51
+ return 0
52
+
53
+ def writelines(self, lines: Iterable[str]) -> None:
54
+ for line in lines:
55
+ self.write(line)
56
+
57
+ def flush(self) -> None:
58
+ # os.write is unbuffered; nothing to flush.
59
+ return None
60
+
61
+ def isatty(self) -> bool:
62
+ try:
63
+ return os.isatty(_STDERR_FD)
64
+ except OSError:
65
+ return False
66
+
67
+ def fileno(self) -> int:
68
+ return _STDERR_FD
69
+
70
+ def close(self) -> None:
71
+ # Don't actually close fd 2.
72
+ return None
73
+
74
+ @property
75
+ def closed(self) -> bool:
76
+ return False
77
+
78
+
79
+ _installed = False
80
+
81
+
82
+ def install() -> None:
83
+ """Swap `sys.stdout` and `sys.stderr` for fd-2 writers.
84
+
85
+ Idempotent: only the first call has effect.
86
+ """
87
+ global _installed
88
+ if _installed:
89
+ return
90
+ sys.stdout = _StderrStream()
91
+ sys.stderr = _StderrStream()
92
+ _installed = True
@@ -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
+ """