pythonnative 0.32.0__py3-none-any.whl → 0.34.0__py3-none-any.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 (78) hide show
  1. pythonnative/__init__.py +27 -15
  2. pythonnative/animated.py +7 -13
  3. pythonnative/cli/pn.py +1 -2
  4. pythonnative/component.py +255 -0
  5. pythonnative/components/__init__.py +106 -0
  6. pythonnative/components/_base.py +132 -0
  7. pythonnative/components/controls.py +515 -0
  8. pythonnative/components/layout.py +459 -0
  9. pythonnative/components/lists.py +809 -0
  10. pythonnative/components/media.py +204 -0
  11. pythonnative/components/overlays.py +107 -0
  12. pythonnative/components/pressable.py +252 -0
  13. pythonnative/components/structural.py +167 -0
  14. pythonnative/components/text.py +291 -0
  15. pythonnative/diagnostics.py +1 -1
  16. pythonnative/element.py +108 -29
  17. pythonnative/gestures.py +1 -1
  18. pythonnative/hooks.py +366 -671
  19. pythonnative/hosts/__init__.py +85 -0
  20. pythonnative/hosts/android.py +269 -0
  21. pythonnative/hosts/base.py +665 -0
  22. pythonnative/hosts/desktop.py +107 -0
  23. pythonnative/hosts/ios.py +404 -0
  24. pythonnative/hot_reload.py +16 -24
  25. pythonnative/layout.py +372 -66
  26. pythonnative/native_modules/__init__.py +23 -0
  27. pythonnative/native_modules/net_info.py +5 -1
  28. pythonnative/native_views/__init__.py +1 -1
  29. pythonnative/native_views/android.py +50 -6
  30. pythonnative/native_views/base.py +64 -1
  31. pythonnative/native_views/desktop.py +11 -3
  32. pythonnative/native_views/ios.py +72 -12
  33. pythonnative/navigation/__init__.py +102 -0
  34. pythonnative/navigation/container.py +154 -0
  35. pythonnative/navigation/handle.py +573 -0
  36. pythonnative/navigation/hooks.py +94 -0
  37. pythonnative/navigation/host.py +58 -0
  38. pythonnative/navigation/linking.py +200 -0
  39. pythonnative/navigation/navigators.py +637 -0
  40. pythonnative/navigation/screen.py +149 -0
  41. pythonnative/navigation/state.py +248 -0
  42. pythonnative/net.py +4 -0
  43. pythonnative/platform_metrics.py +1 -1
  44. pythonnative/preview.py +21 -19
  45. pythonnative/project/android.py +7 -1
  46. pythonnative/project/doctor.py +1 -1
  47. pythonnative/project/ios.py +1 -0
  48. pythonnative/project/runtime_assets.py +1 -1
  49. pythonnative/reconciler/__init__.py +29 -0
  50. pythonnative/reconciler/boundaries.py +365 -0
  51. pythonnative/reconciler/children.py +88 -0
  52. pythonnative/reconciler/core.py +1153 -0
  53. pythonnative/reconciler/layout_pass.py +359 -0
  54. pythonnative/reconciler/vnode.py +266 -0
  55. pythonnative/scheduler.py +159 -0
  56. pythonnative/sdk/_components.py +2 -4
  57. pythonnative/style.py +95 -13
  58. pythonnative/suspense.py +8 -12
  59. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +85 -1
  60. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/ScreenFragment.kt +6 -7
  61. pythonnative/templates/android_template/app/src/main/res/navigation/nav_graph.xml +1 -1
  62. pythonnative/templates/android_template/app/src/main/res/values/strings.xml +3 -1
  63. pythonnative/templates/ios_template/ios_template/AppDelegate.swift +33 -0
  64. pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +1 -1
  65. pythonnative/templates/ios_template/ios_template/ViewController.swift +12 -10
  66. pythonnative/testing/__init__.py +53 -0
  67. pythonnative/testing/backend.py +276 -0
  68. pythonnative/testing/harness.py +391 -0
  69. {pythonnative-0.32.0.dist-info → pythonnative-0.34.0.dist-info}/METADATA +2 -21
  70. {pythonnative-0.32.0.dist-info → pythonnative-0.34.0.dist-info}/RECORD +74 -43
  71. pythonnative/components.py +0 -2856
  72. pythonnative/navigation.py +0 -1031
  73. pythonnative/reconciler.py +0 -2298
  74. pythonnative/screen.py +0 -2068
  75. {pythonnative-0.32.0.dist-info → pythonnative-0.34.0.dist-info}/WHEEL +0 -0
  76. {pythonnative-0.32.0.dist-info → pythonnative-0.34.0.dist-info}/entry_points.txt +0 -0
  77. {pythonnative-0.32.0.dist-info → pythonnative-0.34.0.dist-info}/licenses/LICENSE +0 -0
  78. {pythonnative-0.32.0.dist-info → pythonnative-0.34.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,154 @@
1
+ """``NavigationContainer``: the root of a navigator tree.
2
+
3
+ The container wires the root navigator to the outside world: deep links
4
+ (via [`LinkingConfig`][pythonnative.LinkingConfig]), a caller-supplied
5
+ initial state, and ``on_state_change`` / ``on_ready`` callbacks. Every
6
+ app with navigation renders exactly one container at the top.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from typing import Any, Callable, Mapping, Optional, Union
12
+
13
+ from ..component import component
14
+ from ..element import Element, Node
15
+ from ..hooks import Context, create_context, use_effect, use_memo, use_ref
16
+ from .linking import LinkingConfig
17
+ from .state import NavigationState
18
+
19
+ __all__ = ["ContainerContext", "NavigationContainer"]
20
+
21
+ StateLike = Union[NavigationState, Mapping[str, Any]]
22
+
23
+
24
+ class ContainerConfig:
25
+ """What a root navigator reads from its enclosing container."""
26
+
27
+ __slots__ = ("initial_state", "on_state_change", "on_ready", "_root", "_ready")
28
+
29
+ def __init__(
30
+ self,
31
+ initial_state: Optional[NavigationState],
32
+ on_state_change: Optional[Callable[[NavigationState], None]],
33
+ on_ready: Optional[Callable[[], None]],
34
+ ) -> None:
35
+ self.initial_state = initial_state
36
+ self.on_state_change = on_state_change
37
+ self.on_ready = on_ready
38
+ self._root: Any = None
39
+ self._ready = False
40
+
41
+ def attach_root(self, core: Any) -> Callable[[], None]:
42
+ """Register the root navigator core; returns a detach callable."""
43
+ self._root = core
44
+ if not self._ready:
45
+ self._ready = True
46
+ if self.on_ready is not None:
47
+ self.on_ready()
48
+
49
+ def detach() -> None:
50
+ if self._root is core:
51
+ self._root = None
52
+
53
+ return detach
54
+
55
+ def dispatch_seed(self, seed: NavigationState) -> bool:
56
+ """Route a deep-link state to the root navigator (``False`` if none is mounted)."""
57
+ if self._root is None:
58
+ return False
59
+ target = seed.current
60
+ self._root.navigate(target.name, target.params, target.state)
61
+ return True
62
+
63
+
64
+ ContainerContext: Context[Optional[ContainerConfig]] = create_context(None, name="NavigationContainer")
65
+
66
+
67
+ def _coerce_state(value: Optional[StateLike]) -> Optional[NavigationState]:
68
+ if value is None or isinstance(value, NavigationState):
69
+ return value
70
+ try:
71
+ return NavigationState.from_dict(value)
72
+ except Exception:
73
+ return None
74
+
75
+
76
+ @component
77
+ def NavigationContainer(
78
+ *children: Node,
79
+ linking: Optional[LinkingConfig] = None,
80
+ initial_state: Optional[StateLike] = None,
81
+ on_state_change: Optional[Callable[[NavigationState], None]] = None,
82
+ on_ready: Optional[Callable[[], None]] = None,
83
+ ) -> Element:
84
+ """Root of a navigator tree.
85
+
86
+ Args:
87
+ *children: The root navigator (a ``Stack.Navigator``, ``Tab.Navigator``,
88
+ or ``Drawer.Navigator``) and anything rendered alongside it.
89
+ linking: Deep-link configuration. The URL the app was launched
90
+ with seeds the initial state; URLs that arrive later are
91
+ dispatched as ``navigate`` calls.
92
+ initial_state: Explicit initial state for the root navigator
93
+ (a ``NavigationState`` or its ``to_dict()`` form). Takes
94
+ precedence over the launch URL. State restored by a native
95
+ host (a pushed native screen re-entering Python) takes
96
+ precedence over both.
97
+ on_state_change: Called with the root navigator's state after
98
+ every change. Persist ``state.to_dict()`` to restore later.
99
+ on_ready: Called once the root navigator has mounted.
100
+
101
+ Example:
102
+ ```python
103
+ Stack = pn.create_stack_navigator()
104
+
105
+ @pn.component
106
+ def App():
107
+ return pn.NavigationContainer(
108
+ Stack.Navigator(
109
+ Stack.Screen("Home", HomeScreen),
110
+ Stack.Screen("Detail", DetailScreen, options={"title": "Detail"}),
111
+ ),
112
+ linking=linking,
113
+ )
114
+ ```
115
+ """
116
+ coerced = _coerce_state(initial_state)
117
+
118
+ def build() -> ContainerConfig:
119
+ seed = coerced
120
+ if seed is None and linking is not None:
121
+ from ..native_modules.linking import Linking
122
+
123
+ url = Linking.get_initial_url()
124
+ if url:
125
+ seed = linking.state_from_url(url)
126
+ return ContainerConfig(seed, on_state_change, on_ready)
127
+
128
+ config = use_memo(build, [])
129
+ config.on_state_change = on_state_change
130
+ config.on_ready = on_ready
131
+
132
+ initial_url: Any = use_ref(None)
133
+
134
+ def subscribe() -> Optional[Callable[[], None]]:
135
+ if linking is None:
136
+ return None
137
+ from ..native_modules.linking import Linking
138
+
139
+ initial_url.current = Linking.get_initial_url()
140
+
141
+ def on_url(url: str) -> None:
142
+ # The initial URL already seeded the state; don't navigate twice.
143
+ if url == initial_url.current:
144
+ initial_url.current = None
145
+ return
146
+ seed = linking.state_from_url(url)
147
+ if seed is not None:
148
+ config.dispatch_seed(seed)
149
+
150
+ return Linking.add_listener(on_url)
151
+
152
+ use_effect(subscribe, [linking])
153
+
154
+ return ContainerContext.Provider(config, *children)