pythonnative 0.22.1__py3-none-any.whl → 0.23.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.
- pythonnative/__init__.py +16 -2
- pythonnative/appearance.py +124 -0
- pythonnative/components.py +708 -38
- pythonnative/hooks.py +41 -0
- pythonnative/images.py +196 -0
- pythonnative/mutations.py +3 -12
- pythonnative/native_views/__init__.py +1 -7
- pythonnative/native_views/android.py +573 -45
- pythonnative/native_views/desktop.py +78 -19
- pythonnative/native_views/ios.py +739 -51
- pythonnative/preview.py +31 -0
- pythonnative/project/config.py +1 -9
- pythonnative/screen.py +85 -0
- pythonnative/style.py +65 -6
- pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +2 -1
- pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNAccessibilityDelegate.kt +47 -0
- pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNBorderDrawable.kt +67 -0
- pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNVirtualListView.java +172 -0
- pythonnative/virtual_rows.py +137 -0
- {pythonnative-0.22.1.dist-info → pythonnative-0.23.0.dist-info}/METADATA +1 -1
- {pythonnative-0.22.1.dist-info → pythonnative-0.23.0.dist-info}/RECORD +25 -19
- {pythonnative-0.22.1.dist-info → pythonnative-0.23.0.dist-info}/WHEEL +1 -1
- {pythonnative-0.22.1.dist-info → pythonnative-0.23.0.dist-info}/entry_points.txt +0 -0
- {pythonnative-0.22.1.dist-info → pythonnative-0.23.0.dist-info}/licenses/LICENSE +0 -0
- {pythonnative-0.22.1.dist-info → pythonnative-0.23.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""Row subtrees for natively virtualized lists.
|
|
2
|
+
|
|
3
|
+
Native virtualized lists (Android ``RecyclerView`` via
|
|
4
|
+
``PNVirtualListView``, iOS ``UITableView``) own row lifecycle on the
|
|
5
|
+
platform side: the platform decides when a row enters the viewport,
|
|
6
|
+
hands PythonNative an empty native container, and recycles that
|
|
7
|
+
container when the row scrolls away.
|
|
8
|
+
|
|
9
|
+
Each visible row hosts a full PythonNative subtree driven by its own
|
|
10
|
+
nested [`Reconciler`][pythonnative.reconciler.Reconciler]. The
|
|
11
|
+
[`RowSubtree`][pythonnative.virtual_rows.RowSubtree] class wraps that
|
|
12
|
+
per-row reconciler: it mounts the row element into fresh native views,
|
|
13
|
+
re-reconciles in place when the platform rebinds the same container to
|
|
14
|
+
a different row index (recycling), and tears everything down when the
|
|
15
|
+
list is destroyed.
|
|
16
|
+
|
|
17
|
+
State inside rows works: hooks like ``use_state`` mark the row's own
|
|
18
|
+
reconciler dirty and a guarded flush re-renders just that row.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from typing import Any, Callable, Dict
|
|
22
|
+
|
|
23
|
+
from .element import Element
|
|
24
|
+
|
|
25
|
+
__all__ = ["RowSubtree", "RowHostPool"]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class RowSubtree:
|
|
29
|
+
"""One list row's mounted PythonNative subtree.
|
|
30
|
+
|
|
31
|
+
Owns a nested reconciler whose viewport is the row's cell size.
|
|
32
|
+
The native root view produced by
|
|
33
|
+
[`mount`][pythonnative.virtual_rows.RowSubtree.mount] is what the
|
|
34
|
+
platform handler attaches to the recycled cell container.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(self) -> None:
|
|
38
|
+
from .native_views import get_registry
|
|
39
|
+
from .reconciler import Reconciler
|
|
40
|
+
|
|
41
|
+
self._reconciler = Reconciler(get_registry())
|
|
42
|
+
# Guarded synchronous flush so ``use_state`` inside a row
|
|
43
|
+
# re-renders the row. Re-entrant requests (a setter firing
|
|
44
|
+
# during the flush itself) are queued and drained after.
|
|
45
|
+
self._flushing = False
|
|
46
|
+
self._flush_queued = False
|
|
47
|
+
self._reconciler._screen_re_render = self._request_flush
|
|
48
|
+
self.native_root: Any = None
|
|
49
|
+
|
|
50
|
+
def _request_flush(self) -> None:
|
|
51
|
+
if self._flushing:
|
|
52
|
+
self._flush_queued = True
|
|
53
|
+
return
|
|
54
|
+
self._flushing = True
|
|
55
|
+
try:
|
|
56
|
+
for _ in range(8):
|
|
57
|
+
self._flush_queued = False
|
|
58
|
+
self.native_root = self._reconciler.flush_dirty()
|
|
59
|
+
if not self._flush_queued:
|
|
60
|
+
break
|
|
61
|
+
finally:
|
|
62
|
+
self._flushing = False
|
|
63
|
+
|
|
64
|
+
def mount(self, element: Element, width: float, height: float) -> Any:
|
|
65
|
+
"""Mount ``element`` at the given cell size; returns the native root."""
|
|
66
|
+
self.native_root = self._reconciler.mount(element)
|
|
67
|
+
self._reconciler.set_viewport_size(float(width), float(height))
|
|
68
|
+
return self.native_root
|
|
69
|
+
|
|
70
|
+
def rebind(self, element: Element, width: float, height: float) -> Any:
|
|
71
|
+
"""Reconcile the subtree to ``element`` (cell recycled to a new row).
|
|
72
|
+
|
|
73
|
+
Cheaper than unmount + mount when consecutive rows share a
|
|
74
|
+
shape, which is the overwhelmingly common case in lists.
|
|
75
|
+
Returns the (possibly replaced) native root.
|
|
76
|
+
"""
|
|
77
|
+
self._reconciler.set_viewport_size(float(width), float(height))
|
|
78
|
+
self.native_root = self._reconciler.reconcile(element)
|
|
79
|
+
return self.native_root
|
|
80
|
+
|
|
81
|
+
def unmount(self) -> None:
|
|
82
|
+
"""Destroy the subtree and release its native views."""
|
|
83
|
+
try:
|
|
84
|
+
self._reconciler.unmount()
|
|
85
|
+
except Exception:
|
|
86
|
+
pass
|
|
87
|
+
self.native_root = None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class RowHostPool:
|
|
91
|
+
"""Per-list bookkeeping of row subtrees keyed by native container.
|
|
92
|
+
|
|
93
|
+
Platform handlers create one pool per virtualized list view. Keys
|
|
94
|
+
are platform-stable container identities (Java identity hash on
|
|
95
|
+
Android, ``contentView`` pointer on iOS).
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
def __init__(self) -> None:
|
|
99
|
+
self._subtrees: Dict[int, RowSubtree] = {}
|
|
100
|
+
|
|
101
|
+
def bind(
|
|
102
|
+
self,
|
|
103
|
+
container_key: int,
|
|
104
|
+
make_element: Callable[[], Element],
|
|
105
|
+
width: float,
|
|
106
|
+
height: float,
|
|
107
|
+
) -> Any:
|
|
108
|
+
"""Mount or rebind the subtree for ``container_key``.
|
|
109
|
+
|
|
110
|
+
Returns the subtree's native root. The caller must (re)attach
|
|
111
|
+
it to the container: platforms strip a recycled cell's
|
|
112
|
+
children before rebinding, so even an unchanged root needs
|
|
113
|
+
re-attachment.
|
|
114
|
+
"""
|
|
115
|
+
element = make_element()
|
|
116
|
+
subtree = self._subtrees.get(container_key)
|
|
117
|
+
if subtree is None:
|
|
118
|
+
subtree = RowSubtree()
|
|
119
|
+
self._subtrees[container_key] = subtree
|
|
120
|
+
return subtree.mount(element, width, height)
|
|
121
|
+
return subtree.rebind(element, width, height)
|
|
122
|
+
|
|
123
|
+
def release(self, container_key: int) -> None:
|
|
124
|
+
"""Unmount the subtree for one recycled container, if any."""
|
|
125
|
+
subtree = self._subtrees.pop(container_key, None)
|
|
126
|
+
if subtree is not None:
|
|
127
|
+
subtree.unmount()
|
|
128
|
+
|
|
129
|
+
def release_all(self) -> None:
|
|
130
|
+
"""Unmount every subtree (list destroyed)."""
|
|
131
|
+
subtrees = list(self._subtrees.values())
|
|
132
|
+
self._subtrees.clear()
|
|
133
|
+
for subtree in subtrees:
|
|
134
|
+
subtree.unmount()
|
|
135
|
+
|
|
136
|
+
def __len__(self) -> int:
|
|
137
|
+
return len(self._subtrees)
|
|
@@ -1,26 +1,29 @@
|
|
|
1
|
-
pythonnative/__init__.py,sha256=
|
|
1
|
+
pythonnative/__init__.py,sha256=vDBibKua43iWhsjL-R5bptS2tJKdkf69RqYs2o61NAw,8861
|
|
2
2
|
pythonnative/_ios_log.py,sha256=Oi7V28VxcVoZyrpAirvLeEmUW18McqnU87V4d37Zzlw,2582
|
|
3
3
|
pythonnative/alerts.py,sha256=mIANysFlaHwL5EqKnvNcyiJN9rGiZi9XDrD9Jpz1RFM,9340
|
|
4
4
|
pythonnative/animated.py,sha256=IBokHVfp_Ud5VC8b4drY9DX8A4uG9wqRUjcW3y-EtkI,36233
|
|
5
|
-
pythonnative/
|
|
5
|
+
pythonnative/appearance.py,sha256=vMkDRIz9ptaprMmlPmiYJLVwrDslfnc1bhwyE27M2ZI,3891
|
|
6
|
+
pythonnative/components.py,sha256=zz3SOZDXABRXHE3bmS56Z9v24X0ewebHnbO_y3r5KOc,115170
|
|
6
7
|
pythonnative/element.py,sha256=W9varJj0Cl9HpckL8BcsC1u4ryUQOPVMrvetro4ilAE,2725
|
|
7
8
|
pythonnative/events.py,sha256=H3XmZW99M16Q1OiRq1NbS6e-Pdopi6piCh6qdkmEu40,7632
|
|
8
9
|
pythonnative/gestures.py,sha256=6qe_s3Cv2M5_V-_PgAQ5y9QbYV812B0xVmh8dRDHYMY,29940
|
|
9
|
-
pythonnative/hooks.py,sha256=
|
|
10
|
+
pythonnative/hooks.py,sha256=bM0t1WgkRhJ1myovY0AQY_QsHkO66lkeq4hFfRg8d58,40150
|
|
10
11
|
pythonnative/hot_reload.py,sha256=g-PKXRw7IXZgLyuGwjQmztH10JjT8ULM-szrWWTKe7U,25024
|
|
12
|
+
pythonnative/images.py,sha256=JFjBJdZzZoQmAOfQ7QHqi7dYJ75XTs3u2lweQHGbdPc,6466
|
|
11
13
|
pythonnative/layout.py,sha256=Ck_FCLSk0g4hdOzHo0c50cbvLe8Q8caQAxywXgnFhKM,49077
|
|
12
|
-
pythonnative/mutations.py,sha256=
|
|
14
|
+
pythonnative/mutations.py,sha256=whmxO6ENWjm-yYH0QteoCV1Gdw_v-fJrhicMQJ5A0rk,3827
|
|
13
15
|
pythonnative/navigation.py,sha256=4U57lHqiJJbqRJdTdvveRHKJ58BJhrwvkDOSoFt02I8,35566
|
|
14
16
|
pythonnative/net.py,sha256=8D7EyEC8-JkYxlrtVfTDApOGzzdcA4P4kaCdYBBZI8E,8082
|
|
15
17
|
pythonnative/platform.py,sha256=WtjxR04CqVhSnjJu-3upk8bwXYaSWr2N0MOVoNov-h0,4994
|
|
16
18
|
pythonnative/platform_metrics.py,sha256=1r1kMbgS9LcVTbdpP5qRD4oHEvw70te5BXEyd_16Ihc,8961
|
|
17
|
-
pythonnative/preview.py,sha256=
|
|
19
|
+
pythonnative/preview.py,sha256=bzwW_LgdnCFx8lCBiqlEjwMUa1ggFLYPWmHoMWqyKtg,18041
|
|
18
20
|
pythonnative/reconciler.py,sha256=QFIFG3KjgoPas8LVDHRWouWEEtunegPz-jl6i5Hwno8,57082
|
|
19
21
|
pythonnative/runtime.py,sha256=Ij3xxr_RyWESX7jP7b-RpsYjqjsJi1OpoV3WL3WTBWU,18245
|
|
20
|
-
pythonnative/screen.py,sha256=
|
|
22
|
+
pythonnative/screen.py,sha256=AtoQP37HIWrIReecAvQXWHVx9MfW8tTO6AaBWlvroZI,68876
|
|
21
23
|
pythonnative/storage.py,sha256=pp2mqlAy7wPr8vNwtcmalxc2658lD6z7PU4ilbnxAwE,12001
|
|
22
|
-
pythonnative/style.py,sha256=
|
|
24
|
+
pythonnative/style.py,sha256=kB3tkxJ7LfRr52fodbA2n_OpvSeQAtgMhIVC6oMQISw,17290
|
|
23
25
|
pythonnative/utils.py,sha256=-hwe_YS19ebpjeygdl3dGeVsYzO4G74rYD53svSi0rI,7593
|
|
26
|
+
pythonnative/virtual_rows.py,sha256=4YK3CeZobW-6F6GCXzGNFfmOaAiigmH4HXtqjYDRbyU,5056
|
|
24
27
|
pythonnative/cli/__init__.py,sha256=NM1psvKe8jT0vzp8Ak4MMoygZz4P_msk5g-YEsY8xLk,232
|
|
25
28
|
pythonnative/cli/pn.py,sha256=a0DXYHvcDZtfsmC91mIKgCFTO1Y8T-kkS68RH8_7kaY,28191
|
|
26
29
|
pythonnative/native_modules/__init__.py,sha256=pgigpHuzT-rqwcjlwJvu93_4L8Nozal1HJid0S_JlmM,2636
|
|
@@ -38,15 +41,15 @@ pythonnative/native_modules/notifications.py,sha256=WVtzdimc_aGfnxU6syCFPkjHF9YR
|
|
|
38
41
|
pythonnative/native_modules/permissions.py,sha256=ABIWiCuLIiZJmfA-B7dnw56_Iz7ApGzdtLAs6X694QU,6704
|
|
39
42
|
pythonnative/native_modules/secure_store.py,sha256=PsnUwHzUPt-CzCAwM6BhidOBi9yofRD2uNtQIqAGofU,5953
|
|
40
43
|
pythonnative/native_modules/share.py,sha256=B9ovknmnjeQvGQ8MQ14Hmq6E1x-JA469APMburJ0KUg,4727
|
|
41
|
-
pythonnative/native_views/__init__.py,sha256=
|
|
42
|
-
pythonnative/native_views/android.py,sha256=
|
|
44
|
+
pythonnative/native_views/__init__.py,sha256=93v7pt0_7f8BWqOiwSvlq20F1oJLfCnmQBvLlCDA-Xk,15340
|
|
45
|
+
pythonnative/native_views/android.py,sha256=2pgsv569rC2eWdHGoIrr1kmI-qB4ZklrMV2G9AO6OpQ,130838
|
|
43
46
|
pythonnative/native_views/base.py,sha256=NFDlEIoKCINzcVkf2uobT9TgujPb1RClLS3TzwH72MY,9668
|
|
44
|
-
pythonnative/native_views/desktop.py,sha256=
|
|
45
|
-
pythonnative/native_views/ios.py,sha256=
|
|
47
|
+
pythonnative/native_views/desktop.py,sha256=GnZEchJLUcH74jG_21CCzjdYcEmm-5etUX2D0-_WNtQ,59735
|
|
48
|
+
pythonnative/native_views/ios.py,sha256=fgskhuENQO-aiw527xOrveeRClX8uFt5UdqKSCsBT_8,169080
|
|
46
49
|
pythonnative/project/__init__.py,sha256=kAhWLONs53H1L7xVtczLmzYcQSOOkdRZTAJnIMhpBts,2064
|
|
47
50
|
pythonnative/project/android.py,sha256=SX0uu4-tz4WdYAf9sbycQPSmoQ8fbtAADeUWk9G8ybM,19127
|
|
48
51
|
pythonnative/project/builder.py,sha256=DokY-YidsDeWYgaixrpD3Kzp7_XudibltI8X_WdBIcE,19096
|
|
49
|
-
pythonnative/project/config.py,sha256=
|
|
52
|
+
pythonnative/project/config.py,sha256=jH9_MnE5kmKGe3yA4tfPHic5LlKcWys58jxOmUSJTd4,23839
|
|
50
53
|
pythonnative/project/doctor.py,sha256=ETg-lvEyaNzaxgsDn9f4DBapNKBttMHA-9kwgX-yb3g,7943
|
|
51
54
|
pythonnative/project/icons.py,sha256=GaXpktQ9v4v2JZPM3ppueNPmwjTuFiLanHJDaZbLGuo,7945
|
|
52
55
|
pythonnative/project/ios.py,sha256=DHQs_Wf_uJ9eoI3gqGmcjFuF2shwMwa8mLKGtuTDffw,14004
|
|
@@ -62,9 +65,12 @@ pythonnative/templates/android_template/settings.gradle,sha256=GKZiYUYWsaXxaiKOB
|
|
|
62
65
|
pythonnative/templates/android_template/app/build.gradle,sha256=zHYbYXjKUiW-ZSYXT2GfveyVnjOCNLXvXpPxI76O5t4,1864
|
|
63
66
|
pythonnative/templates/android_template/app/proguard-rules.pro,sha256=Vv2WDPIl9spA-YKxOl27DYvD394T_3ZCKCXGBw0KGJA,750
|
|
64
67
|
pythonnative/templates/android_template/app/src/androidTest/java/com/pythonnative/android_template/ExampleInstrumentedTest.kt,sha256=Am8Yla3i1eR_ac5FVgPU_RsuMrCbyT79h1BcajGE-zI,693
|
|
65
|
-
pythonnative/templates/android_template/app/src/main/AndroidManifest.xml,sha256=
|
|
68
|
+
pythonnative/templates/android_template/app/src/main/AndroidManifest.xml,sha256=eprO6TQuZN0UEVsMcg2oXDaPUuVuYJWMg3GScNsfC8k,995
|
|
66
69
|
pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt,sha256=1dSBEX-AB2aUPxFFDnWwcmVHRi00T-iwbXi4yt4RQk8,1481
|
|
67
70
|
pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/Navigator.kt,sha256=mDfzKTTXRP-zbSnfIPxAYyjtr9_IyyQwXM-dovcfVbg,1723
|
|
71
|
+
pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNAccessibilityDelegate.kt,sha256=R2PC6BA3VCaKET0XV33tXTFf4Ht9udvvLu9TT_RfWp4,1819
|
|
72
|
+
pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNBorderDrawable.kt,sha256=ejdFhpzn0-2TZa0nvG41r2m0xoejU2fXXuJSmO6tnBU,2205
|
|
73
|
+
pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/PNVirtualListView.java,sha256=1ve74nvOFqsduyaLOGPb8Sd9Jrwz-sELRB9y1NMN1AI,6072
|
|
68
74
|
pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/ScreenFragment.kt,sha256=lSxWYH6cGDpGalo0kDzTAT5H3NuhJVLT7BQYcfCydOc,5138
|
|
69
75
|
pythonnative/templates/android_template/app/src/main/res/drawable/ic_launcher_background.xml,sha256=7UI8c6b0Ck0pCfCQHmBSezqAfNWeG1WTvKrhgIscYyE,5606
|
|
70
76
|
pythonnative/templates/android_template/app/src/main/res/drawable-v24/ic_launcher_foreground.xml,sha256=AdGmpsEjTrf-Jw0JfrKD1yucla5RGIhvG2VzqtKA8fc,1702
|
|
@@ -105,9 +111,9 @@ pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/x
|
|
|
105
111
|
pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift,sha256=YnwzZx7yXB13xKAXEGNgz17VuhWeqkHTRTtBJ2Vu3_E,1238
|
|
106
112
|
pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift,sha256=HLRr3cmouRqQeXG13WrZ2XSAmgMgCsNXfZpbwkxeFcs,1385
|
|
107
113
|
pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift,sha256=f5JrG0uVtLMeJQy26Yyz7Om-JUkT220osqcbeIVkj2g,815
|
|
108
|
-
pythonnative-0.
|
|
109
|
-
pythonnative-0.
|
|
110
|
-
pythonnative-0.
|
|
111
|
-
pythonnative-0.
|
|
112
|
-
pythonnative-0.
|
|
113
|
-
pythonnative-0.
|
|
114
|
+
pythonnative-0.23.0.dist-info/licenses/LICENSE,sha256=A69iG7TIAe6KkGQf6xoVHkc5JSZtOr5eRSvC5iuivnI,1067
|
|
115
|
+
pythonnative-0.23.0.dist-info/METADATA,sha256=t0952y_u74dbBtuyPdG1VHdQO3E8M8Iqi_EAxtmPGH4,10347
|
|
116
|
+
pythonnative-0.23.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
117
|
+
pythonnative-0.23.0.dist-info/entry_points.txt,sha256=iUtDawWSAJAEyWTycpZxDuYz73ol31butpzDIEAgPO0,48
|
|
118
|
+
pythonnative-0.23.0.dist-info/top_level.txt,sha256=kT4SEATY2ywzrZ2Pgea6_zxyym44Q_PbOsUoOYjJLFE,13
|
|
119
|
+
pythonnative-0.23.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|