pythonnative 0.7.0__py3-none-any.whl → 0.9.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 +22 -1
- pythonnative/_ios_log.py +94 -0
- pythonnative/cli/pn.py +131 -11
- pythonnative/components.py +78 -21
- pythonnative/hooks.py +135 -29
- pythonnative/hot_reload.py +2 -2
- pythonnative/native_views/__init__.py +87 -0
- pythonnative/native_views/android.py +832 -0
- pythonnative/native_views/base.py +150 -0
- pythonnative/native_views/ios.py +777 -0
- pythonnative/navigation.py +571 -0
- pythonnative/page.py +77 -17
- pythonnative/reconciler.py +89 -1
- pythonnative/templates/ios_template/ios_template/ViewController.swift +19 -25
- pythonnative/utils.py +40 -1
- {pythonnative-0.7.0.dist-info → pythonnative-0.9.0.dist-info}/METADATA +1 -1
- {pythonnative-0.7.0.dist-info → pythonnative-0.9.0.dist-info}/RECORD +21 -16
- pythonnative/native_views.py +0 -1404
- {pythonnative-0.7.0.dist-info → pythonnative-0.9.0.dist-info}/WHEEL +0 -0
- {pythonnative-0.7.0.dist-info → pythonnative-0.9.0.dist-info}/entry_points.txt +0 -0
- {pythonnative-0.7.0.dist-info → pythonnative-0.9.0.dist-info}/licenses/LICENSE +0 -0
- {pythonnative-0.7.0.dist-info → pythonnative-0.9.0.dist-info}/top_level.txt +0 -0
pythonnative/reconciler.py
CHANGED
|
@@ -11,8 +11,12 @@ Supports:
|
|
|
11
11
|
``@component``). Their hook state is preserved across renders.
|
|
12
12
|
- **Provider elements** (type ``"__Provider__"``), which push/pop
|
|
13
13
|
context values during tree traversal.
|
|
14
|
+
- **Error boundary elements** (type ``"__ErrorBoundary__"``), which
|
|
15
|
+
catch exceptions in child subtrees and render a fallback.
|
|
14
16
|
- **Key-based child reconciliation** for stable identity across
|
|
15
17
|
re-renders.
|
|
18
|
+
- **Post-render effect flushing**: after each mount or reconcile pass,
|
|
19
|
+
all queued effects are executed so they see the committed native tree.
|
|
16
20
|
"""
|
|
17
21
|
|
|
18
22
|
from typing import Any, List, Optional
|
|
@@ -36,6 +40,10 @@ class VNode:
|
|
|
36
40
|
class Reconciler:
|
|
37
41
|
"""Create, diff, and patch native view trees from Element descriptors.
|
|
38
42
|
|
|
43
|
+
After each ``mount`` or ``reconcile`` call the reconciler walks the
|
|
44
|
+
committed tree and flushes all pending effects so that effect
|
|
45
|
+
callbacks run **after** native mutations are applied.
|
|
46
|
+
|
|
39
47
|
Parameters
|
|
40
48
|
----------
|
|
41
49
|
backend:
|
|
@@ -56,6 +64,7 @@ class Reconciler:
|
|
|
56
64
|
def mount(self, element: Element) -> Any:
|
|
57
65
|
"""Build native views from *element* and return the root native view."""
|
|
58
66
|
self._tree = self._create_tree(element)
|
|
67
|
+
self._flush_effects()
|
|
59
68
|
return self._tree.native_view
|
|
60
69
|
|
|
61
70
|
def reconcile(self, new_element: Element) -> Any:
|
|
@@ -65,11 +74,28 @@ class Reconciler:
|
|
|
65
74
|
"""
|
|
66
75
|
if self._tree is None:
|
|
67
76
|
self._tree = self._create_tree(new_element)
|
|
77
|
+
self._flush_effects()
|
|
68
78
|
return self._tree.native_view
|
|
69
79
|
|
|
70
80
|
self._tree = self._reconcile_node(self._tree, new_element)
|
|
81
|
+
self._flush_effects()
|
|
71
82
|
return self._tree.native_view
|
|
72
83
|
|
|
84
|
+
# ------------------------------------------------------------------
|
|
85
|
+
# Effect flushing
|
|
86
|
+
# ------------------------------------------------------------------
|
|
87
|
+
|
|
88
|
+
def _flush_effects(self) -> None:
|
|
89
|
+
"""Walk the committed tree and flush pending effects (depth-first)."""
|
|
90
|
+
if self._tree is not None:
|
|
91
|
+
self._flush_tree_effects(self._tree)
|
|
92
|
+
|
|
93
|
+
def _flush_tree_effects(self, node: VNode) -> None:
|
|
94
|
+
for child in node.children:
|
|
95
|
+
self._flush_tree_effects(child)
|
|
96
|
+
if node.hook_state is not None:
|
|
97
|
+
node.hook_state.flush_pending_effects()
|
|
98
|
+
|
|
73
99
|
# ------------------------------------------------------------------
|
|
74
100
|
# Internal helpers
|
|
75
101
|
# ------------------------------------------------------------------
|
|
@@ -87,6 +113,10 @@ class Reconciler:
|
|
|
87
113
|
children = [child_node] if child_node else []
|
|
88
114
|
return VNode(element, native_view, children)
|
|
89
115
|
|
|
116
|
+
# Error boundary: catch exceptions in the child subtree
|
|
117
|
+
if element.type == "__ErrorBoundary__":
|
|
118
|
+
return self._create_error_boundary(element)
|
|
119
|
+
|
|
90
120
|
# Function component: call with hook context
|
|
91
121
|
if callable(element.type):
|
|
92
122
|
from .hooks import HookState, _set_hook_state
|
|
@@ -114,6 +144,20 @@ class Reconciler:
|
|
|
114
144
|
children.append(child_node)
|
|
115
145
|
return VNode(element, native_view, children)
|
|
116
146
|
|
|
147
|
+
def _create_error_boundary(self, element: Element) -> VNode:
|
|
148
|
+
fallback_fn = element.props.get("__fallback__")
|
|
149
|
+
try:
|
|
150
|
+
child_node = self._create_tree(element.children[0]) if element.children else None
|
|
151
|
+
except Exception as exc:
|
|
152
|
+
if fallback_fn is not None:
|
|
153
|
+
fallback_el = fallback_fn(exc) if callable(fallback_fn) else fallback_fn
|
|
154
|
+
child_node = self._create_tree(fallback_el)
|
|
155
|
+
else:
|
|
156
|
+
raise
|
|
157
|
+
native_view = child_node.native_view if child_node else None
|
|
158
|
+
children = [child_node] if child_node else []
|
|
159
|
+
return VNode(element, native_view, children)
|
|
160
|
+
|
|
117
161
|
def _reconcile_node(self, old: VNode, new_el: Element) -> VNode:
|
|
118
162
|
if not self._same_type(old.element, new_el):
|
|
119
163
|
new_node = self._create_tree(new_el)
|
|
@@ -138,6 +182,10 @@ class Reconciler:
|
|
|
138
182
|
old.element = new_el
|
|
139
183
|
return old
|
|
140
184
|
|
|
185
|
+
# Error boundary
|
|
186
|
+
if new_el.type == "__ErrorBoundary__":
|
|
187
|
+
return self._reconcile_error_boundary(old, new_el)
|
|
188
|
+
|
|
141
189
|
# Function component
|
|
142
190
|
if callable(new_el.type):
|
|
143
191
|
from .hooks import _set_hook_state
|
|
@@ -175,10 +223,34 @@ class Reconciler:
|
|
|
175
223
|
old.element = new_el
|
|
176
224
|
return old
|
|
177
225
|
|
|
226
|
+
def _reconcile_error_boundary(self, old: VNode, new_el: Element) -> VNode:
|
|
227
|
+
fallback_fn = new_el.props.get("__fallback__")
|
|
228
|
+
try:
|
|
229
|
+
if old.children and new_el.children:
|
|
230
|
+
child = self._reconcile_node(old.children[0], new_el.children[0])
|
|
231
|
+
old.children = [child]
|
|
232
|
+
old.native_view = child.native_view
|
|
233
|
+
elif new_el.children:
|
|
234
|
+
child = self._create_tree(new_el.children[0])
|
|
235
|
+
old.children = [child]
|
|
236
|
+
old.native_view = child.native_view
|
|
237
|
+
except Exception as exc:
|
|
238
|
+
for c in old.children:
|
|
239
|
+
self._destroy_tree(c)
|
|
240
|
+
if fallback_fn is not None:
|
|
241
|
+
fallback_el = fallback_fn(exc) if callable(fallback_fn) else fallback_fn
|
|
242
|
+
child = self._create_tree(fallback_el)
|
|
243
|
+
old.children = [child]
|
|
244
|
+
old.native_view = child.native_view
|
|
245
|
+
else:
|
|
246
|
+
raise
|
|
247
|
+
old.element = new_el
|
|
248
|
+
return old
|
|
249
|
+
|
|
178
250
|
def _reconcile_children(self, parent: VNode, new_children: List[Element]) -> None:
|
|
179
251
|
old_children = parent.children
|
|
180
252
|
parent_type = parent.element.type
|
|
181
|
-
is_native = isinstance(parent_type, str) and parent_type
|
|
253
|
+
is_native = isinstance(parent_type, str) and parent_type not in ("__Provider__", "__ErrorBoundary__")
|
|
182
254
|
|
|
183
255
|
old_by_key: dict = {}
|
|
184
256
|
old_unkeyed: list = []
|
|
@@ -215,7 +287,11 @@ class Reconciler:
|
|
|
215
287
|
self.backend.insert_child(parent.native_view, node.native_view, parent_type, i)
|
|
216
288
|
new_child_nodes.append(node)
|
|
217
289
|
else:
|
|
290
|
+
old_native = matched.native_view
|
|
218
291
|
updated = self._reconcile_node(matched, new_el)
|
|
292
|
+
if is_native and updated.native_view is not old_native:
|
|
293
|
+
self.backend.remove_child(parent.native_view, old_native, parent_type)
|
|
294
|
+
self.backend.insert_child(parent.native_view, updated.native_view, parent_type, i)
|
|
219
295
|
new_child_nodes.append(updated)
|
|
220
296
|
|
|
221
297
|
# Destroy unused old nodes
|
|
@@ -229,6 +305,18 @@ class Reconciler:
|
|
|
229
305
|
self.backend.remove_child(parent.native_view, node.native_view, parent_type)
|
|
230
306
|
self._destroy_tree(node)
|
|
231
307
|
|
|
308
|
+
# Reorder native children when keyed children changed positions.
|
|
309
|
+
# Without this, native sibling order drifts from the logical tree
|
|
310
|
+
# when keyed children swap positions across reconcile passes.
|
|
311
|
+
if is_native and used_keyed:
|
|
312
|
+
old_key_order = [c.element.key for c in old_children if c.element.key in used_keyed]
|
|
313
|
+
new_key_order = [n.element.key for n in new_child_nodes if n.element.key in used_keyed]
|
|
314
|
+
if old_key_order != new_key_order:
|
|
315
|
+
for node in new_child_nodes:
|
|
316
|
+
self.backend.remove_child(parent.native_view, node.native_view, parent_type)
|
|
317
|
+
for node in new_child_nodes:
|
|
318
|
+
self.backend.add_child(parent.native_view, node.native_view, parent_type)
|
|
319
|
+
|
|
232
320
|
parent.children = new_child_nodes
|
|
233
321
|
|
|
234
322
|
def _destroy_tree(self, node: VNode) -> None:
|
|
@@ -27,13 +27,18 @@ class ViewController: UIViewController {
|
|
|
27
27
|
super.viewDidLoad()
|
|
28
28
|
// Ensure a visible background when created programmatically (storyboards set this automatically)
|
|
29
29
|
view.backgroundColor = .systemBackground
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
//
|
|
30
|
+
|
|
31
|
+
let firstInit = !ViewController.hasInitializedPython
|
|
32
|
+
|
|
33
|
+
// Signal to pythonnative that we're running on iOS. Read on the
|
|
34
|
+
// Python side (pythonnative.utils.IS_IOS) to gate iOS-only setup
|
|
35
|
+
// like sys.stdout redirection. Set before Python starts so it's
|
|
36
|
+
// visible to the very first import.
|
|
37
|
+
setenv("PN_PLATFORM", "ios", 1)
|
|
38
|
+
|
|
39
|
+
// Configure embedded Python if available in bundle. PYTHONHOME /
|
|
40
|
+
// PYTHONPATH only need to be set once per process, but setting them
|
|
41
|
+
// again is harmless and keeps the flow simple.
|
|
37
42
|
if let resourcePath = Bundle.main.resourcePath {
|
|
38
43
|
let pyStd = "\(resourcePath)/python-stdlib"
|
|
39
44
|
let pyDyn = "\(resourcePath)/python-stdlib/lib-dynload"
|
|
@@ -44,8 +49,6 @@ class ViewController: UIViewController {
|
|
|
44
49
|
}
|
|
45
50
|
setenv("PYTHONHOME", pyStd, 1)
|
|
46
51
|
setenv("PYTHONPATH", pyPath, 1)
|
|
47
|
-
NSLog("[PN] Set PYTHONHOME=\(pyStd)")
|
|
48
|
-
NSLog("[PN] Set PYTHONPATH=\(pyPath)")
|
|
49
52
|
}
|
|
50
53
|
#if canImport(PythonKit)
|
|
51
54
|
// Ensure PythonKit knows where to load the Python library from when using an embedded framework.
|
|
@@ -53,34 +56,25 @@ class ViewController: UIViewController {
|
|
|
53
56
|
let frameworkLib = "\(bundlePath)/Frameworks/Python.framework/Python"
|
|
54
57
|
setenv("PYTHON_LIBRARY", frameworkLib, 1)
|
|
55
58
|
if FileManager.default.fileExists(atPath: frameworkLib) {
|
|
56
|
-
if
|
|
57
|
-
NSLog("[PN] Using embedded Python lib at: \(frameworkLib)")
|
|
59
|
+
if firstInit {
|
|
58
60
|
PythonLibrary.useLibrary(at: frameworkLib)
|
|
59
61
|
ViewController.hasInitializedPython = true
|
|
60
|
-
} else {
|
|
61
|
-
NSLog("[PN] Python library already initialized; skipping useLibrary")
|
|
62
62
|
}
|
|
63
63
|
pythonReady = true
|
|
64
64
|
} else {
|
|
65
65
|
NSLog("[PN] Embedded Python library not found at: \(frameworkLib)")
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
NSLog("[PN] PythonKit available; attempting Python bootstrap")
|
|
69
68
|
let sys = Python.import("sys")
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
if firstInit {
|
|
70
|
+
// One concise bootstrap line per process; per-page detail is left
|
|
71
|
+
// to Python-side print() statements streamed via pn run ios.
|
|
72
|
+
let shortVersion = "\(sys.version)".split(separator: "\n").first.map(String.init) ?? "\(sys.version)"
|
|
73
|
+
NSLog("[PN] Python \(shortVersion) initialized")
|
|
74
|
+
}
|
|
72
75
|
if let resourcePath = Bundle.main.resourcePath {
|
|
73
76
|
sys.path.append(resourcePath)
|
|
74
77
|
sys.path.append("\(resourcePath)/app")
|
|
75
|
-
NSLog("[PN] Updated sys.path: \(sys.path)")
|
|
76
|
-
// List bundled resources to verify Python files are present
|
|
77
|
-
let fm = FileManager.default
|
|
78
|
-
let appDir = "\(resourcePath)/app"
|
|
79
|
-
if let entries = try? fm.contentsOfDirectory(atPath: appDir) {
|
|
80
|
-
NSLog("[PN] Contents of /app in bundle: \(entries)")
|
|
81
|
-
} else {
|
|
82
|
-
NSLog("[PN] Could not list contents of \(appDir).")
|
|
83
|
-
}
|
|
84
78
|
}
|
|
85
79
|
// Determine which Python page to load
|
|
86
80
|
let pagePath: String = requestedPagePath ?? "app.main_page.MainPage"
|
pythonnative/utils.py
CHANGED
|
@@ -5,6 +5,7 @@ importing platform-specific packages at module level.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import os
|
|
8
|
+
import sys
|
|
8
9
|
from typing import Any, Optional
|
|
9
10
|
|
|
10
11
|
# ======================================================================
|
|
@@ -12,6 +13,7 @@ from typing import Any, Optional
|
|
|
12
13
|
# ======================================================================
|
|
13
14
|
|
|
14
15
|
_is_android: Optional[bool] = None
|
|
16
|
+
_is_ios: Optional[bool] = None
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
def _detect_android() -> bool:
|
|
@@ -27,10 +29,40 @@ def _detect_android() -> bool:
|
|
|
27
29
|
return False
|
|
28
30
|
|
|
29
31
|
|
|
32
|
+
def _detect_ios() -> bool:
|
|
33
|
+
"""Detect whether we're running inside an iOS app bundle.
|
|
34
|
+
|
|
35
|
+
Signals, in priority order:
|
|
36
|
+
|
|
37
|
+
- Explicit ``PN_PLATFORM=ios`` env var (set by the iOS template's
|
|
38
|
+
``ViewController.swift`` before Python starts). This is the
|
|
39
|
+
canonical signal and survives even on hosts where ``sys.platform``
|
|
40
|
+
is generic ``darwin``.
|
|
41
|
+
- ``sys.platform == "ios"`` (CPython 3.13+ native iOS builds).
|
|
42
|
+
- ``/CoreSimulator/Devices/`` in ``$HOME`` (iOS Simulator fallback
|
|
43
|
+
if the template signal is missing for some reason).
|
|
44
|
+
|
|
45
|
+
Crucially, having ``rubicon-objc`` importable is *not* enough:
|
|
46
|
+
developers frequently install it on macOS via the ``[ios]`` extra,
|
|
47
|
+
and treating that as iOS would cause subtle side effects
|
|
48
|
+
(e.g. stdout redirection) on desktop machines.
|
|
49
|
+
"""
|
|
50
|
+
if os.environ.get("PN_PLATFORM") == "ios":
|
|
51
|
+
return True
|
|
52
|
+
if sys.platform == "ios":
|
|
53
|
+
return True
|
|
54
|
+
home = os.environ.get("HOME", "")
|
|
55
|
+
if "/CoreSimulator/Devices/" in home:
|
|
56
|
+
return True
|
|
57
|
+
return False
|
|
58
|
+
|
|
59
|
+
|
|
30
60
|
def _ensure_platform_detection() -> None:
|
|
31
|
-
global _is_android
|
|
61
|
+
global _is_android, _is_ios
|
|
32
62
|
if _is_android is None:
|
|
33
63
|
_is_android = _detect_android()
|
|
64
|
+
if _is_ios is None:
|
|
65
|
+
_is_ios = (not _is_android) and _detect_ios()
|
|
34
66
|
|
|
35
67
|
|
|
36
68
|
def _get_is_android() -> bool:
|
|
@@ -39,7 +71,14 @@ def _get_is_android() -> bool:
|
|
|
39
71
|
return _is_android
|
|
40
72
|
|
|
41
73
|
|
|
74
|
+
def _get_is_ios() -> bool:
|
|
75
|
+
_ensure_platform_detection()
|
|
76
|
+
assert _is_ios is not None
|
|
77
|
+
return _is_ios
|
|
78
|
+
|
|
79
|
+
|
|
42
80
|
IS_ANDROID: bool = _get_is_android()
|
|
81
|
+
IS_IOS: bool = _get_is_ios()
|
|
43
82
|
|
|
44
83
|
# ======================================================================
|
|
45
84
|
# Android context management
|
|
@@ -1,20 +1,25 @@
|
|
|
1
|
-
pythonnative/__init__.py,sha256=
|
|
2
|
-
pythonnative/
|
|
1
|
+
pythonnative/__init__.py,sha256=zKplWL38v3kFMeQ8Q2VqnjF-nAM5vx3EW8UIKqJddDo,2038
|
|
2
|
+
pythonnative/_ios_log.py,sha256=dkTSUeOF9xRQjgxMYdH6EohjzjmeInwOfr-_0tkBmpE,2639
|
|
3
|
+
pythonnative/components.py,sha256=zF24vXM6halq-fweLtLHxZrmBrUKCa9c44hf9Bych-Y,12767
|
|
3
4
|
pythonnative/element.py,sha256=RBUsXzzzM7KdK-NqMD-InVPKdAb8XJ0h0VpI2rwsfHs,1795
|
|
4
|
-
pythonnative/hooks.py,sha256=
|
|
5
|
-
pythonnative/hot_reload.py,sha256=
|
|
6
|
-
pythonnative/
|
|
7
|
-
pythonnative/page.py,sha256=
|
|
8
|
-
pythonnative/reconciler.py,sha256=
|
|
5
|
+
pythonnative/hooks.py,sha256=bqnJvEpbYSlbwkBKphT5lLEXQ1mO6AlO4r9SCTBlu7w,13768
|
|
6
|
+
pythonnative/hot_reload.py,sha256=dtppJaQI6Rl7muCTMgLjFNsD4_F4yYnkEpliCLaaWm8,4508
|
|
7
|
+
pythonnative/navigation.py,sha256=dDY9qBPLJKr2NnvdIDs8Xy-6kFesQNCEaLjUDT-0_l8,19042
|
|
8
|
+
pythonnative/page.py,sha256=J1mC6jVAu6IjFSwDGPU3cMfiXLPHoW2RbyZ1kj3OSfk,16814
|
|
9
|
+
pythonnative/reconciler.py,sha256=EuB8InxqlbZpZ0qI8hSjwNQsS-lsvh0vdqGzTnmY1M8,14133
|
|
9
10
|
pythonnative/style.py,sha256=NG58FSJCBTBBWRrDOyUiHZsTxQDA3jg2PSOcCsU2F5g,3882
|
|
10
|
-
pythonnative/utils.py,sha256=
|
|
11
|
+
pythonnative/utils.py,sha256=dp-cOYSflWvsY9Qh851OeBq-x6S8W1cx4nyjDxlsd0M,3859
|
|
11
12
|
pythonnative/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
-
pythonnative/cli/pn.py,sha256=
|
|
13
|
+
pythonnative/cli/pn.py,sha256=KGDbxRYtZHUS4rId_Br6oI7kEGl0pcRAo5UGztUvTN4,37478
|
|
13
14
|
pythonnative/native_modules/__init__.py,sha256=M_4SW-wCZ8azLuB0JLwUc8PESw00xMCM887-HuN9YNo,647
|
|
14
15
|
pythonnative/native_modules/camera.py,sha256=b3UErkABhBm2nQ-e72lEeFOgXoVDY6245cV6TN9iPBk,3509
|
|
15
16
|
pythonnative/native_modules/file_system.py,sha256=2fvYsIboCtjEyxmVeV72glOjtc9fJN3jTM6uaccru6E,4478
|
|
16
17
|
pythonnative/native_modules/location.py,sha256=bMSNbtG60hAorKXh4RR2vybX88M_BwHkCpTprRbMsZU,1883
|
|
17
18
|
pythonnative/native_modules/notifications.py,sha256=g-zT1GD-ojPsLN5eGXWkyNHTncSxdiEYtjllCXlsBSc,5377
|
|
19
|
+
pythonnative/native_views/__init__.py,sha256=0weXhCaDT79sez9Q1JibXSgouRVB1tjucFibhbPQeYc,2984
|
|
20
|
+
pythonnative/native_views/android.py,sha256=59_VzpGlADHFrY2cG8llVn4sDmPkUSGyUVKbyvfkKiU,32686
|
|
21
|
+
pythonnative/native_views/base.py,sha256=IS4_AQd4WsHgn8fka8np9zpaKdAOn1q0Zo09a8wYOtE,4229
|
|
22
|
+
pythonnative/native_views/ios.py,sha256=G5bQz57v5WSw5-wNmpcrcdX3rb7isb126la7UlveZLA,30087
|
|
18
23
|
pythonnative/templates/android_template/build.gradle,sha256=4gE6CRS6RuBu9kp-_e_uYYU9mBgHVZrqQg9caSxgyuc,352
|
|
19
24
|
pythonnative/templates/android_template/gradle.properties,sha256=REPaKLRfQiiVfIV8wYmgwzPWvF1f3bhh_kAMV9p4HME,1358
|
|
20
25
|
pythonnative/templates/android_template/gradlew,sha256=YxNShxF6Hm0SyEWA8fScYdG6AiGOzShmBgXpf5dufWU,5766
|
|
@@ -55,7 +60,7 @@ pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.properties
|
|
|
55
60
|
pythonnative/templates/ios_template/ios_template/AppDelegate.swift,sha256=_6G8GNcw4idXd75qKgQKTDCr45Ez73QB8WTvhBqqcMw,1349
|
|
56
61
|
pythonnative/templates/ios_template/ios_template/Info.plist,sha256=ZQIJGpo8Y2qP0j29xqOsIEGvPpEVICLTAw2NehC5CSo,704
|
|
57
62
|
pythonnative/templates/ios_template/ios_template/SceneDelegate.swift,sha256=lqtre92dc6d6s-f4ieh_M_4xmc_zMGW79j46tDu9cOY,2177
|
|
58
|
-
pythonnative/templates/ios_template/ios_template/ViewController.swift,sha256=
|
|
63
|
+
pythonnative/templates/ios_template/ios_template/ViewController.swift,sha256=5bVNJ4TT6GIaICzVxl8hgcFmBgaPqjiCivlJzFy0p7c,7920
|
|
59
64
|
pythonnative/templates/ios_template/ios_template/Assets.xcassets/Contents.json,sha256=D9Sbo8NYXHCWeOAEaoIcPGBoXscGNyDTDTo0SL46IIs,63
|
|
60
65
|
pythonnative/templates/ios_template/ios_template/Assets.xcassets/AccentColor.colorset/Contents.json,sha256=mvZQhvowtJJS-uGhIlcxaR3nlPd3WvdNcb7-tQfRK3w,123
|
|
61
66
|
pythonnative/templates/ios_template/ios_template/Assets.xcassets/AppIcon.appiconset/Contents.json,sha256=VUwGr7K_geOvQjFh5VKB6iVXV1mi0tjGMinUmB2JvQs,177
|
|
@@ -66,9 +71,9 @@ pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/x
|
|
|
66
71
|
pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift,sha256=YnwzZx7yXB13xKAXEGNgz17VuhWeqkHTRTtBJ2Vu3_E,1238
|
|
67
72
|
pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift,sha256=l2Pwa50F_rv-qPu2go6e4bQernM6PTQJeNPFl_c4ivY,1387
|
|
68
73
|
pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift,sha256=f5JrG0uVtLMeJQy26Yyz7Om-JUkT220osqcbeIVkj2g,815
|
|
69
|
-
pythonnative-0.
|
|
70
|
-
pythonnative-0.
|
|
71
|
-
pythonnative-0.
|
|
72
|
-
pythonnative-0.
|
|
73
|
-
pythonnative-0.
|
|
74
|
-
pythonnative-0.
|
|
74
|
+
pythonnative-0.9.0.dist-info/licenses/LICENSE,sha256=A69iG7TIAe6KkGQf6xoVHkc5JSZtOr5eRSvC5iuivnI,1067
|
|
75
|
+
pythonnative-0.9.0.dist-info/METADATA,sha256=YOu6Me-TqLtHWoWkL8A8UWp6WY9f-OzzkSfXZp8X86s,6692
|
|
76
|
+
pythonnative-0.9.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
77
|
+
pythonnative-0.9.0.dist-info/entry_points.txt,sha256=iUtDawWSAJAEyWTycpZxDuYz73ol31butpzDIEAgPO0,48
|
|
78
|
+
pythonnative-0.9.0.dist-info/top_level.txt,sha256=kT4SEATY2ywzrZ2Pgea6_zxyym44Q_PbOsUoOYjJLFE,13
|
|
79
|
+
pythonnative-0.9.0.dist-info/RECORD,,
|