pythonnative 0.30.0__py3-none-any.whl → 0.31.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 +1 -1
- pythonnative/cli/pn.py +37 -6
- pythonnative/project/devices.py +14 -1
- {pythonnative-0.30.0.dist-info → pythonnative-0.31.0.dist-info}/METADATA +1 -1
- {pythonnative-0.30.0.dist-info → pythonnative-0.31.0.dist-info}/RECORD +9 -9
- {pythonnative-0.30.0.dist-info → pythonnative-0.31.0.dist-info}/WHEEL +0 -0
- {pythonnative-0.30.0.dist-info → pythonnative-0.31.0.dist-info}/entry_points.txt +0 -0
- {pythonnative-0.30.0.dist-info → pythonnative-0.31.0.dist-info}/licenses/LICENSE +0 -0
- {pythonnative-0.30.0.dist-info → pythonnative-0.31.0.dist-info}/top_level.txt +0 -0
pythonnative/__init__.py
CHANGED
pythonnative/cli/pn.py
CHANGED
|
@@ -9,7 +9,7 @@ The console script `pn` (declared in `pyproject.toml`) dispatches to:
|
|
|
9
9
|
- `pn preview [component]`: render the app in a desktop (Tkinter) window
|
|
10
10
|
with Fast Refresh, the fast inner dev loop, no device required.
|
|
11
11
|
- `pn devices [platform]`: list connected devices, emulators, and
|
|
12
|
-
simulators
|
|
12
|
+
simulators, as a table or as JSON with `--json`.
|
|
13
13
|
- `pn run android|ios [--device D]`: stage + build + install + launch on
|
|
14
14
|
a device, emulator, or simulator, with optional on-device hot reload.
|
|
15
15
|
- `pn logs android|ios`: stream logs from the running app without
|
|
@@ -38,7 +38,7 @@ import sys
|
|
|
38
38
|
import time
|
|
39
39
|
from importlib.metadata import version as pkg_version
|
|
40
40
|
from pathlib import Path
|
|
41
|
-
from typing import Any, Dict, List, Optional
|
|
41
|
+
from typing import Any, Dict, List, Optional, TextIO
|
|
42
42
|
|
|
43
43
|
from ..project import builder as builder_mod
|
|
44
44
|
from ..project import devices as devices_mod
|
|
@@ -298,18 +298,46 @@ def _preview_entry(project_dir: Path) -> str:
|
|
|
298
298
|
# ======================================================================
|
|
299
299
|
|
|
300
300
|
|
|
301
|
+
def _print_no_devices_hints(stream: TextIO) -> None:
|
|
302
|
+
"""Print the "no devices" guidance to ``stream``.
|
|
303
|
+
|
|
304
|
+
Shared by both output modes so the wording can't drift between the
|
|
305
|
+
table (which sends it to stdout) and ``--json`` (stderr).
|
|
306
|
+
|
|
307
|
+
Args:
|
|
308
|
+
stream: Where to write, ``sys.stdout`` or ``sys.stderr``.
|
|
309
|
+
"""
|
|
310
|
+
print("No devices found.", file=stream)
|
|
311
|
+
print("Android: start an emulator or connect a device with USB debugging enabled.", file=stream)
|
|
312
|
+
print("iOS: open Xcode once to install Simulators, or plug in a device.", file=stream)
|
|
313
|
+
|
|
314
|
+
|
|
301
315
|
def devices_command(args: argparse.Namespace) -> None:
|
|
302
316
|
"""List connected devices, emulators, and simulators.
|
|
303
317
|
|
|
318
|
+
Prints an aligned table and exits 1 when nothing is connected.
|
|
319
|
+
|
|
320
|
+
With ``--json``, stdout carries a JSON array and nothing else, one
|
|
321
|
+
object per device (see ``Device.to_dict``), so it stays parseable.
|
|
322
|
+
The "no devices" hints go to stderr instead, an empty result prints
|
|
323
|
+
``[]``, and the exit status is 0 either way, since "no devices" is a
|
|
324
|
+
valid answer for a script rather than a failure.
|
|
325
|
+
|
|
304
326
|
Args:
|
|
305
|
-
args: Parsed namespace with optional ``platform``.
|
|
327
|
+
args: Parsed namespace with optional ``platform`` and ``json``.
|
|
306
328
|
"""
|
|
307
329
|
platform: Optional[str] = getattr(args, "platform", None)
|
|
330
|
+
as_json: bool = getattr(args, "json", False)
|
|
308
331
|
devices = devices_mod.list_devices(platform)
|
|
332
|
+
|
|
333
|
+
if as_json:
|
|
334
|
+
if not devices:
|
|
335
|
+
_print_no_devices_hints(sys.stderr)
|
|
336
|
+
print(json.dumps([device.to_dict() for device in devices], indent=2))
|
|
337
|
+
return
|
|
338
|
+
|
|
309
339
|
if not devices:
|
|
310
|
-
|
|
311
|
-
print("Android: start an emulator or connect a device with USB debugging enabled.")
|
|
312
|
-
print("iOS: open Xcode once to install Simulators, or plug in a device.")
|
|
340
|
+
_print_no_devices_hints(sys.stdout)
|
|
313
341
|
sys.exit(1)
|
|
314
342
|
print(f" {'IDENTIFIER':<40} {'KIND':<10} {'STATE':<10} NAME")
|
|
315
343
|
for device in devices:
|
|
@@ -943,6 +971,9 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
943
971
|
|
|
944
972
|
parser_devices = subparsers.add_parser("devices", help="List devices, emulators, and simulators")
|
|
945
973
|
parser_devices.add_argument("platform", nargs="?", choices=["android", "ios"], help="Restrict to a platform")
|
|
974
|
+
parser_devices.add_argument(
|
|
975
|
+
"--json", action="store_true", help="Print a JSON array to stdout for scripting (hints go to stderr)"
|
|
976
|
+
)
|
|
946
977
|
parser_devices.set_defaults(func=devices_command)
|
|
947
978
|
|
|
948
979
|
parser_run = subparsers.add_parser("run", help="Build, install, and launch on a device/simulator")
|
pythonnative/project/devices.py
CHANGED
|
@@ -18,7 +18,7 @@ import json
|
|
|
18
18
|
import re
|
|
19
19
|
import subprocess
|
|
20
20
|
import tempfile
|
|
21
|
-
from dataclasses import dataclass
|
|
21
|
+
from dataclasses import asdict, dataclass
|
|
22
22
|
from pathlib import Path
|
|
23
23
|
from typing import Any, Dict, List, Optional
|
|
24
24
|
|
|
@@ -64,6 +64,19 @@ class Device:
|
|
|
64
64
|
return self.state in ("booted", "shutdown")
|
|
65
65
|
return self.state in ("booted", "connected")
|
|
66
66
|
|
|
67
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
68
|
+
"""Return a JSON-serializable view of this target.
|
|
69
|
+
|
|
70
|
+
Derived from the dataclass fields so a field added later is
|
|
71
|
+
carried into the payload automatically, plus the computed
|
|
72
|
+
``is_ready`` that consumers would otherwise have to re-derive
|
|
73
|
+
from ``kind`` and ``state``.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
The declared fields in declaration order, then ``is_ready``.
|
|
77
|
+
"""
|
|
78
|
+
return {**asdict(self), "is_ready": self.is_ready}
|
|
79
|
+
|
|
67
80
|
def format(self) -> str:
|
|
68
81
|
"""Return one aligned listing row for the CLI."""
|
|
69
82
|
os_part = f" ({self.os_version})" if self.os_version else ""
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
pythonnative/__init__.py,sha256=
|
|
1
|
+
pythonnative/__init__.py,sha256=NYhhv97vyRgN8SNgJM-O864UVk1rDOAg8lgja3EKvyc,8680
|
|
2
2
|
pythonnative/_ios_log.py,sha256=Oi7V28VxcVoZyrpAirvLeEmUW18McqnU87V4d37Zzlw,2582
|
|
3
3
|
pythonnative/alerts.py,sha256=mIANysFlaHwL5EqKnvNcyiJN9rGiZi9XDrD9Jpz1RFM,9340
|
|
4
4
|
pythonnative/animated.py,sha256=A4IOBf_GD6lUn0H8ArFH6URf0-m0PG__8uaxcw6-ECE,60373
|
|
@@ -27,7 +27,7 @@ pythonnative/suspense.py,sha256=IxWGXFP3Odriy0uQe9zhrNrObdKer0_WT6v9Vi8Vatg,1466
|
|
|
27
27
|
pythonnative/utils.py,sha256=-hwe_YS19ebpjeygdl3dGeVsYzO4G74rYD53svSi0rI,7593
|
|
28
28
|
pythonnative/virtual_rows.py,sha256=4YK3CeZobW-6F6GCXzGNFfmOaAiigmH4HXtqjYDRbyU,5056
|
|
29
29
|
pythonnative/cli/__init__.py,sha256=NM1psvKe8jT0vzp8Ak4MMoygZz4P_msk5g-YEsY8xLk,232
|
|
30
|
-
pythonnative/cli/pn.py,sha256=
|
|
30
|
+
pythonnative/cli/pn.py,sha256=FCNAjbWrOWnm5rEE0n9k2Ys1AY3O11ZuCqV1vaq9-SM,38269
|
|
31
31
|
pythonnative/native_modules/__init__.py,sha256=pgigpHuzT-rqwcjlwJvu93_4L8Nozal1HJid0S_JlmM,2636
|
|
32
32
|
pythonnative/native_modules/app_state.py,sha256=CKAwDQIwoGElSLE3l7Bekk0qRbFVFOTSuSCBybumZEk,2742
|
|
33
33
|
pythonnative/native_modules/battery.py,sha256=-lJu8LURw-yEObXUyhNq_jHFDa1_33lgzbJzXaGqUL4,4429
|
|
@@ -52,7 +52,7 @@ pythonnative/project/__init__.py,sha256=kAhWLONs53H1L7xVtczLmzYcQSOOkdRZTAJnIMhp
|
|
|
52
52
|
pythonnative/project/android.py,sha256=ynRQwVvv1trFB2eFaUv38-48q4m0_Z4cTbAFEOiKnhE,19797
|
|
53
53
|
pythonnative/project/builder.py,sha256=TTN_ymdSyF4wVtSRRwOnSmc91LMn_g_M7_jTI0NtbVU,23946
|
|
54
54
|
pythonnative/project/config.py,sha256=CmN6VojcuDRVnLwKFnQyd9B20_HL9l0RWDnO91G_JaY,25001
|
|
55
|
-
pythonnative/project/devices.py,sha256=
|
|
55
|
+
pythonnative/project/devices.py,sha256=zH0v95vOqWxXGdeTDljrZTA0RWBuU79v3zTQSaXkDh8,10106
|
|
56
56
|
pythonnative/project/doctor.py,sha256=cNCUWyzu4WBJ9peARIgQ2AyoAGp81NKKM5VkIx7dpFE,8623
|
|
57
57
|
pythonnative/project/icons.py,sha256=GaXpktQ9v4v2JZPM3ppueNPmwjTuFiLanHJDaZbLGuo,7945
|
|
58
58
|
pythonnative/project/ios.py,sha256=Xrx2Jh1v4-3ftLkvKAHQuXCA5nuBdKV5nmTTXkDFaNA,13077
|
|
@@ -116,9 +116,9 @@ pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/x
|
|
|
116
116
|
pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift,sha256=YnwzZx7yXB13xKAXEGNgz17VuhWeqkHTRTtBJ2Vu3_E,1238
|
|
117
117
|
pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift,sha256=HLRr3cmouRqQeXG13WrZ2XSAmgMgCsNXfZpbwkxeFcs,1385
|
|
118
118
|
pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift,sha256=f5JrG0uVtLMeJQy26Yyz7Om-JUkT220osqcbeIVkj2g,815
|
|
119
|
-
pythonnative-0.
|
|
120
|
-
pythonnative-0.
|
|
121
|
-
pythonnative-0.
|
|
122
|
-
pythonnative-0.
|
|
123
|
-
pythonnative-0.
|
|
124
|
-
pythonnative-0.
|
|
119
|
+
pythonnative-0.31.0.dist-info/licenses/LICENSE,sha256=A69iG7TIAe6KkGQf6xoVHkc5JSZtOr5eRSvC5iuivnI,1067
|
|
120
|
+
pythonnative-0.31.0.dist-info/METADATA,sha256=XvvvqmJj-vvntCv003W8cuH9I7dSJ5SvSlM8KDHi1r0,11895
|
|
121
|
+
pythonnative-0.31.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
122
|
+
pythonnative-0.31.0.dist-info/entry_points.txt,sha256=iUtDawWSAJAEyWTycpZxDuYz73ol31butpzDIEAgPO0,48
|
|
123
|
+
pythonnative-0.31.0.dist-info/top_level.txt,sha256=kT4SEATY2ywzrZ2Pgea6_zxyym44Q_PbOsUoOYjJLFE,13
|
|
124
|
+
pythonnative-0.31.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|