portacode 1.4.19__py3-none-any.whl → 1.4.19.dev1__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.
- portacode/_version.py +2 -2
- portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +2 -3
- portacode/connection/handlers/proxmox_infra.py +23 -156
- {portacode-1.4.19.dist-info → portacode-1.4.19.dev1.dist-info}/METADATA +1 -1
- {portacode-1.4.19.dist-info → portacode-1.4.19.dev1.dist-info}/RECORD +9 -9
- {portacode-1.4.19.dist-info → portacode-1.4.19.dev1.dist-info}/WHEEL +0 -0
- {portacode-1.4.19.dist-info → portacode-1.4.19.dev1.dist-info}/entry_points.txt +0 -0
- {portacode-1.4.19.dist-info → portacode-1.4.19.dev1.dist-info}/licenses/LICENSE +0 -0
- {portacode-1.4.19.dist-info → portacode-1.4.19.dev1.dist-info}/top_level.txt +0 -0
portacode/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '1.4.19'
|
|
32
|
-
__version_tuple__ = version_tuple = (1, 4, 19)
|
|
31
|
+
__version__ = version = '1.4.19.dev1'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 4, 19, 'dev1')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -394,7 +394,7 @@ Stops a running Portacode-managed container. Handled by [`StopProxmoxContainerHa
|
|
|
394
394
|
|
|
395
395
|
**Payload Fields:**
|
|
396
396
|
|
|
397
|
-
* `ctid` (string, optional): Identifier of the container to stop. If omitted, the handler resolves the CTID from managed container records
|
|
397
|
+
* `ctid` (string, optional): Identifier of the container to stop. If omitted, the handler resolves the CTID from the managed container records using `child_device_id`.
|
|
398
398
|
* `child_device_id` (string, required): Dashboard `Device.id` that owns the container; the handler rejects the request if the CT is mapped to another device.
|
|
399
399
|
|
|
400
400
|
**Responses:**
|
|
@@ -408,13 +408,12 @@ Deletes a managed container from Proxmox (stopping it first if necessary) and re
|
|
|
408
408
|
|
|
409
409
|
**Payload Fields:**
|
|
410
410
|
|
|
411
|
-
* `ctid` (string, optional): Identifier of the container to delete. If omitted, the handler resolves the CTID from managed container records
|
|
411
|
+
* `ctid` (string, optional): Identifier of the container to delete. If omitted, the handler resolves the CTID from the managed container records using `child_device_id`.
|
|
412
412
|
* `child_device_id` (string, required): Dashboard `Device.id` that should own the container metadata being purged.
|
|
413
413
|
|
|
414
414
|
**Responses:**
|
|
415
415
|
|
|
416
416
|
* Emits a [`proxmox_container_action`](#proxmox_container_action-event) event with `action="remove"` and the refreshed infra snapshot after deletion.
|
|
417
|
-
* If no managed container matches the requested `child_device_id`, emits a `proxmox_container_action` event with `success=false`, `status="not_found"`, and a human-readable message (no error event).
|
|
418
417
|
* Emits an [`error`](#error) event on failure.
|
|
419
418
|
|
|
420
419
|
### `proxmox_container_created`
|
|
@@ -17,7 +17,6 @@ import sys
|
|
|
17
17
|
import tempfile
|
|
18
18
|
import time
|
|
19
19
|
import threading
|
|
20
|
-
import random
|
|
21
20
|
from datetime import datetime, timezone
|
|
22
21
|
from pathlib import Path
|
|
23
22
|
from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Tuple
|
|
@@ -34,44 +33,6 @@ REPO_ROOT = Path(__file__).resolve().parents[3]
|
|
|
34
33
|
NET_SETUP_SCRIPT = REPO_ROOT / "proxmox_management" / "net_setup.py"
|
|
35
34
|
CONTAINERS_DIR = CONFIG_DIR / "containers"
|
|
36
35
|
MANAGED_MARKER = "portacode-managed:true"
|
|
37
|
-
DEVICE_ID_MARKER = "device_id="
|
|
38
|
-
PROVISIONING_ID_MARKER = "provisioning_id="
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def _sanitize_description_value(value: Any) -> str:
|
|
42
|
-
return str(value).strip().replace(";", "_")
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def _build_managed_description(
|
|
46
|
-
base: Optional[str],
|
|
47
|
-
*,
|
|
48
|
-
device_id: Optional[str] = None,
|
|
49
|
-
provisioning_id: Optional[str] = None,
|
|
50
|
-
) -> str:
|
|
51
|
-
parts = [part for part in (base or "").split(";") if part]
|
|
52
|
-
if MANAGED_MARKER not in parts:
|
|
53
|
-
parts.insert(0, MANAGED_MARKER)
|
|
54
|
-
if device_id:
|
|
55
|
-
device_id_value = _sanitize_description_value(device_id)
|
|
56
|
-
if not any(part.startswith(DEVICE_ID_MARKER) for part in parts):
|
|
57
|
-
parts.append(f"{DEVICE_ID_MARKER}{device_id_value}")
|
|
58
|
-
if provisioning_id:
|
|
59
|
-
provisioning_value = _sanitize_description_value(provisioning_id)
|
|
60
|
-
if not any(part.startswith(PROVISIONING_ID_MARKER) for part in parts):
|
|
61
|
-
parts.append(f"{PROVISIONING_ID_MARKER}{provisioning_value}")
|
|
62
|
-
return ";".join(parts)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def _extract_marker_value(description: str, prefix: str) -> Optional[str]:
|
|
66
|
-
for part in description.split(";"):
|
|
67
|
-
part = part.strip()
|
|
68
|
-
if part.startswith(prefix):
|
|
69
|
-
return part[len(prefix) :].strip()
|
|
70
|
-
return None
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def _parse_device_id_from_description(description: str) -> Optional[str]:
|
|
74
|
-
return _extract_marker_value(description, DEVICE_ID_MARKER)
|
|
75
36
|
|
|
76
37
|
DEFAULT_HOST = "localhost"
|
|
77
38
|
DEFAULT_NODE_NAME = os.uname().nodename.split(".", 1)[0]
|
|
@@ -1296,21 +1257,12 @@ def _validate_positive_number(value: Any, default: float) -> float:
|
|
|
1296
1257
|
|
|
1297
1258
|
|
|
1298
1259
|
def _wait_for_task(proxmox: Any, node: str, upid: str) -> Tuple[Dict[str, Any], float]:
|
|
1299
|
-
from proxmoxer.core import ResourceException
|
|
1300
1260
|
start = time.time()
|
|
1301
|
-
poll = 2.0
|
|
1302
1261
|
while True:
|
|
1303
|
-
|
|
1304
|
-
status = proxmox.nodes(node).tasks(upid).status.get()
|
|
1305
|
-
except ResourceException as e:
|
|
1306
|
-
if str(e).startswith("599 "):
|
|
1307
|
-
# transient proxy glitch; task may still be running
|
|
1308
|
-
time.sleep(poll + random.random() * 0.5) # small jitter
|
|
1309
|
-
continue
|
|
1310
|
-
raise
|
|
1262
|
+
status = proxmox.nodes(node).tasks(upid).status.get()
|
|
1311
1263
|
if status.get("status") == "stopped":
|
|
1312
1264
|
return status, time.time() - start
|
|
1313
|
-
time.sleep(
|
|
1265
|
+
time.sleep(1)
|
|
1314
1266
|
|
|
1315
1267
|
|
|
1316
1268
|
def _list_running_managed(proxmox: Any, node: str) -> List[Tuple[str, Dict[str, Any]]]:
|
|
@@ -1448,10 +1400,6 @@ def _parse_ctid(message: Dict[str, Any]) -> int:
|
|
|
1448
1400
|
raise ValueError("ctid is required")
|
|
1449
1401
|
|
|
1450
1402
|
|
|
1451
|
-
class _DeviceLookupError(ValueError):
|
|
1452
|
-
pass
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
1403
|
def _resolve_vmid_for_device(device_id: str) -> int:
|
|
1456
1404
|
_initialize_managed_containers_state()
|
|
1457
1405
|
records = list(_MANAGED_CONTAINERS_STATE.get("records", {}).values())
|
|
@@ -1468,77 +1416,21 @@ def _resolve_vmid_for_device(device_id: str) -> int:
|
|
|
1468
1416
|
return int(str(vmid).strip())
|
|
1469
1417
|
except ValueError:
|
|
1470
1418
|
raise ValueError("ctid must be an integer") from None
|
|
1471
|
-
raise
|
|
1472
|
-
f"No managed container record found for device_id {device_id!r}."
|
|
1473
|
-
)
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
def _resolve_vmid_for_device_in_proxmox(
|
|
1477
|
-
proxmox: Any, node: str, device_id: str
|
|
1478
|
-
) -> int:
|
|
1479
|
-
device_id_value = str(device_id).strip()
|
|
1480
|
-
matches: List[int] = []
|
|
1481
|
-
try:
|
|
1482
|
-
containers = proxmox.nodes(node).lxc.get()
|
|
1483
|
-
except Exception as exc: # pragma: no cover - proxmox failure
|
|
1484
|
-
raise _DeviceLookupError(
|
|
1485
|
-
f"Unable to query Proxmox containers for device_id {device_id_value!r}: {exc}"
|
|
1486
|
-
) from exc
|
|
1487
|
-
for entry in containers or []:
|
|
1488
|
-
vmid = entry.get("vmid")
|
|
1489
|
-
if vmid is None:
|
|
1490
|
-
continue
|
|
1491
|
-
try:
|
|
1492
|
-
cfg = proxmox.nodes(node).lxc(str(vmid)).config.get()
|
|
1493
|
-
except Exception:
|
|
1494
|
-
continue
|
|
1495
|
-
description = (cfg or {}).get("description") or ""
|
|
1496
|
-
if MANAGED_MARKER not in description:
|
|
1497
|
-
continue
|
|
1498
|
-
desc_device_id = _parse_device_id_from_description(description)
|
|
1499
|
-
if desc_device_id is None:
|
|
1500
|
-
continue
|
|
1501
|
-
if str(desc_device_id) != device_id_value:
|
|
1502
|
-
continue
|
|
1503
|
-
matches.append(int(str(vmid).strip()))
|
|
1504
|
-
if not matches:
|
|
1505
|
-
raise _DeviceLookupError(
|
|
1506
|
-
f"No managed container found for device_id {device_id_value!r}. It may already be deleted."
|
|
1507
|
-
)
|
|
1508
|
-
if len(matches) > 1:
|
|
1509
|
-
raise _DeviceLookupError(
|
|
1510
|
-
f"Multiple managed containers found for device_id {device_id_value!r}: {matches}."
|
|
1511
|
-
)
|
|
1512
|
-
return matches[0]
|
|
1419
|
+
raise ValueError("ctid is required for remove_proxmox_container")
|
|
1513
1420
|
|
|
1514
1421
|
|
|
1515
1422
|
def _ensure_container_managed(
|
|
1516
1423
|
proxmox: Any, node: str, vmid: int, *, device_id: Optional[str] = None
|
|
1517
1424
|
) -> Tuple[Dict[str, Any], Dict[str, Any]]:
|
|
1518
|
-
|
|
1519
|
-
record = _read_container_record(vmid)
|
|
1520
|
-
except FileNotFoundError:
|
|
1521
|
-
record = {}
|
|
1425
|
+
record = _read_container_record(vmid)
|
|
1522
1426
|
ct_cfg = proxmox.nodes(node).lxc(str(vmid)).config.get()
|
|
1523
|
-
|
|
1524
|
-
if not ct_cfg or MANAGED_MARKER not in description:
|
|
1427
|
+
if not ct_cfg or MANAGED_MARKER not in (ct_cfg.get("description") or ""):
|
|
1525
1428
|
raise RuntimeError(f"Container {vmid} is not managed by Portacode.")
|
|
1526
1429
|
record_device_id = record.get("device_id")
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
raise RuntimeError(
|
|
1532
|
-
f"Container {vmid} is managed for device {description_device_id!r}, not {device_id_value!r}."
|
|
1533
|
-
)
|
|
1534
|
-
if record_device_id and str(record_device_id) != device_id_value:
|
|
1535
|
-
raise RuntimeError(
|
|
1536
|
-
f"Container {vmid} is managed for device {record_device_id!r}, not {device_id_value!r}."
|
|
1537
|
-
)
|
|
1538
|
-
if not description_device_id and not record_device_id:
|
|
1539
|
-
raise RuntimeError(
|
|
1540
|
-
f"Container {vmid} is missing a device_id marker; refusing to operate without ctid."
|
|
1541
|
-
)
|
|
1430
|
+
if device_id and str(record_device_id or "") != str(device_id):
|
|
1431
|
+
raise RuntimeError(
|
|
1432
|
+
f"Container {vmid} is managed for device {record_device_id!r}, not {device_id!r}."
|
|
1433
|
+
)
|
|
1542
1434
|
return record, ct_cfg
|
|
1543
1435
|
|
|
1544
1436
|
|
|
@@ -2223,11 +2115,7 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
2223
2115
|
payload, device_id=device_id, request_id=request_id
|
|
2224
2116
|
)
|
|
2225
2117
|
provisioning_id = secrets.token_hex(6)
|
|
2226
|
-
payload["description"] =
|
|
2227
|
-
payload.get("description"),
|
|
2228
|
-
device_id=device_id,
|
|
2229
|
-
provisioning_id=provisioning_id,
|
|
2230
|
-
)
|
|
2118
|
+
payload["description"] = f"{payload.get('description', MANAGED_MARKER)};provisioning_id={provisioning_id}"
|
|
2231
2119
|
|
|
2232
2120
|
def _provision_background() -> None:
|
|
2233
2121
|
nonlocal current_step_index
|
|
@@ -2620,16 +2508,13 @@ class StartProxmoxContainerHandler(SyncHandler):
|
|
|
2620
2508
|
child_device_id = (message.get("child_device_id") or "").strip()
|
|
2621
2509
|
if not child_device_id:
|
|
2622
2510
|
raise ValueError("child_device_id is required for start_proxmox_container")
|
|
2623
|
-
config = _ensure_infra_configured()
|
|
2624
|
-
proxmox = _connect_proxmox(config)
|
|
2625
|
-
node = _get_node_from_config(config)
|
|
2626
2511
|
try:
|
|
2627
2512
|
vmid = _parse_ctid(message)
|
|
2628
2513
|
except ValueError:
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2514
|
+
vmid = _resolve_vmid_for_device(child_device_id)
|
|
2515
|
+
config = _ensure_infra_configured()
|
|
2516
|
+
proxmox = _connect_proxmox(config)
|
|
2517
|
+
node = _get_node_from_config(config)
|
|
2633
2518
|
_ensure_container_managed(proxmox, node, vmid, device_id=child_device_id)
|
|
2634
2519
|
|
|
2635
2520
|
status, elapsed = _start_container(proxmox, node, vmid)
|
|
@@ -2659,16 +2544,13 @@ class StopProxmoxContainerHandler(SyncHandler):
|
|
|
2659
2544
|
child_device_id = (message.get("child_device_id") or "").strip()
|
|
2660
2545
|
if not child_device_id:
|
|
2661
2546
|
raise ValueError("child_device_id is required for stop_proxmox_container")
|
|
2662
|
-
config = _ensure_infra_configured()
|
|
2663
|
-
proxmox = _connect_proxmox(config)
|
|
2664
|
-
node = _get_node_from_config(config)
|
|
2665
2547
|
try:
|
|
2666
2548
|
vmid = _parse_ctid(message)
|
|
2667
2549
|
except ValueError:
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2550
|
+
vmid = _resolve_vmid_for_device(child_device_id)
|
|
2551
|
+
config = _ensure_infra_configured()
|
|
2552
|
+
proxmox = _connect_proxmox(config)
|
|
2553
|
+
node = _get_node_from_config(config)
|
|
2672
2554
|
_ensure_container_managed(proxmox, node, vmid, device_id=child_device_id)
|
|
2673
2555
|
|
|
2674
2556
|
status, elapsed = _stop_container(proxmox, node, vmid)
|
|
@@ -2704,30 +2586,14 @@ class RemoveProxmoxContainerHandler(SyncHandler):
|
|
|
2704
2586
|
child_device_id = (message.get("child_device_id") or "").strip()
|
|
2705
2587
|
if not child_device_id:
|
|
2706
2588
|
raise ValueError("child_device_id is required for remove_proxmox_container")
|
|
2589
|
+
try:
|
|
2590
|
+
vmid = _parse_ctid(message)
|
|
2591
|
+
except ValueError:
|
|
2592
|
+
vmid = _resolve_vmid_for_device(child_device_id)
|
|
2707
2593
|
request_id = message.get("request_id")
|
|
2708
2594
|
config = _ensure_infra_configured()
|
|
2709
2595
|
proxmox = _connect_proxmox(config)
|
|
2710
2596
|
node = _get_node_from_config(config)
|
|
2711
|
-
try:
|
|
2712
|
-
vmid = _parse_ctid(message)
|
|
2713
|
-
except ValueError:
|
|
2714
|
-
try:
|
|
2715
|
-
vmid = _resolve_vmid_for_device(child_device_id)
|
|
2716
|
-
except _DeviceLookupError:
|
|
2717
|
-
try:
|
|
2718
|
-
vmid = _resolve_vmid_for_device_in_proxmox(proxmox, node, child_device_id)
|
|
2719
|
-
except _DeviceLookupError as exc:
|
|
2720
|
-
infra = get_infra_snapshot()
|
|
2721
|
-
return {
|
|
2722
|
-
"event": "proxmox_container_action",
|
|
2723
|
-
"action": "remove",
|
|
2724
|
-
"success": False,
|
|
2725
|
-
"message": str(exc),
|
|
2726
|
-
"status": "not_found",
|
|
2727
|
-
"child_device_id": child_device_id,
|
|
2728
|
-
"request_id": request_id,
|
|
2729
|
-
"infra": infra,
|
|
2730
|
-
}
|
|
2731
2597
|
_ensure_container_managed(proxmox, node, vmid, device_id=child_device_id)
|
|
2732
2598
|
|
|
2733
2599
|
stop_status, stop_elapsed = _stop_container(proxmox, node, vmid)
|
|
@@ -2747,6 +2613,7 @@ class RemoveProxmoxContainerHandler(SyncHandler):
|
|
|
2747
2613
|
},
|
|
2748
2614
|
"status": "deleted",
|
|
2749
2615
|
"child_device_id": child_device_id,
|
|
2616
|
+
"on_behalf_of_device": child_device_id,
|
|
2750
2617
|
"request_id": request_id,
|
|
2751
2618
|
"infra": infra,
|
|
2752
2619
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
portacode/README.md,sha256=4dKtpvR8LNgZPVz37GmkQCMWIr_u25Ao63iW56s7Ke4,775
|
|
2
2
|
portacode/__init__.py,sha256=oB3sV1wXr-um-RXio73UG8E5Xx6cF2ZVJveqjNmC-vQ,1086
|
|
3
3
|
portacode/__main__.py,sha256=jmHTGC1hzmo9iKJLv-SSYe9BSIbPPZ2IOpecI03PlTs,296
|
|
4
|
-
portacode/_version.py,sha256=
|
|
4
|
+
portacode/_version.py,sha256=kEqKlKmd7-J1gNSkF12NMt4XjDTKb2p29hHE7_jkufw,719
|
|
5
5
|
portacode/cli.py,sha256=mGLKoZ-T2FBF7IA9wUq0zyG0X9__-A1ao7gajjcVRH8,21828
|
|
6
6
|
portacode/data.py,sha256=5-s291bv8J354myaHm1Y7CQZTZyRzMU3TGe5U4hb-FA,1591
|
|
7
7
|
portacode/keypair.py,sha256=0OO4vHDcF1XMxCDqce61xFTlFwlTcmqe5HyGsXFEt7s,5838
|
|
@@ -14,7 +14,7 @@ portacode/connection/client.py,sha256=jtLb9_YufqPkzi9t8VQH3iz_JEMisbtY6a8L9U5wei
|
|
|
14
14
|
portacode/connection/multiplex.py,sha256=L-TxqJ_ZEbfNEfu1cwxgJ5vUdyRzZjsMy2Kx1diiZys,5237
|
|
15
15
|
portacode/connection/terminal.py,sha256=n1Uu92JacV5K6d1Qwx94Tw9OB2Tpke5HqsW2NDn76Ls,49032
|
|
16
16
|
portacode/connection/handlers/README.md,sha256=HsLZG1QK1JNm67HsgL6WoDg9nxzKXxwkc5fJPFJdX5g,12169
|
|
17
|
-
portacode/connection/handlers/WEBSOCKET_PROTOCOL.md,sha256=
|
|
17
|
+
portacode/connection/handlers/WEBSOCKET_PROTOCOL.md,sha256=1c41G-cOzPRvs6IqkOkU0M_hxo8iHmns815omLCaEcQ,103931
|
|
18
18
|
portacode/connection/handlers/__init__.py,sha256=WSeBmi65GWFQPYt9M3E10rn0uZ_EPCJzNJOzSf2HZyw,2921
|
|
19
19
|
portacode/connection/handlers/base.py,sha256=tMsKJmnNhXA3a4YZA55a0WO2e8-4Uh4BsG9lWAr3Ris,10829
|
|
20
20
|
portacode/connection/handlers/chunked_content.py,sha256=h6hXRmxSeOgnIxoU8CkmvEf2Odv-ajPrpHIe_W3GKcA,9251
|
|
@@ -22,7 +22,7 @@ portacode/connection/handlers/diff_handlers.py,sha256=iYTIRCcpEQ03vIPKZCsMTE5aZb
|
|
|
22
22
|
portacode/connection/handlers/file_handlers.py,sha256=nAJH8nXnX07xxD28ngLpgIUzcTuRwZBNpEGEKdRqohw,39507
|
|
23
23
|
portacode/connection/handlers/project_aware_file_handlers.py,sha256=AqgMnDqX2893T2NsrvUSCwjN5VKj4Pb2TN0S_SuboOE,9803
|
|
24
24
|
portacode/connection/handlers/project_state_handlers.py,sha256=v6ZefGW9i7n1aZLq2jOGumJIjYb6aHlPI4m1jkYewm8,1686
|
|
25
|
-
portacode/connection/handlers/proxmox_infra.py,sha256=
|
|
25
|
+
portacode/connection/handlers/proxmox_infra.py,sha256=NFOPCPHAdf4GQKg6R7jhU-cwR1YD_FB2Ar1eXfsCW2o,101085
|
|
26
26
|
portacode/connection/handlers/registry.py,sha256=elISoWpIXapMuY28x1hzXV-uErtAklsFzMb8yVgp7NU,6456
|
|
27
27
|
portacode/connection/handlers/session.py,sha256=uNGfiO_1B9-_yjJKkpvmbiJhIl6b-UXlT86UTfd6WYE,42219
|
|
28
28
|
portacode/connection/handlers/system_handlers.py,sha256=fr12QpOr_Z8KYGUU-AYrTQwRPAcrLK85hvj3SEq1Kw8,14757
|
|
@@ -65,7 +65,7 @@ portacode/utils/__init__.py,sha256=NgBlWTuNJESfIYJzP_3adI1yJQJR0XJLRpSdVNaBAN0,3
|
|
|
65
65
|
portacode/utils/diff_apply.py,sha256=4Oi7ft3VUCKmiUE4VM-OeqO7Gk6H7PF3WnN4WHXtjxI,15157
|
|
66
66
|
portacode/utils/diff_renderer.py,sha256=S76StnQ2DLfsz4Gg0m07UwPfRp8270PuzbNaQq-rmYk,13850
|
|
67
67
|
portacode/utils/ntp_clock.py,sha256=VqCnWCTehCufE43W23oB-WUdAZGeCcLxkmIOPwInYHc,2499
|
|
68
|
-
portacode-1.4.19.dist-info/licenses/LICENSE,sha256=2FGbCnUDgRYuQTkB1O1dUUpu5CVAjK1j4_p6ack9Z54,1066
|
|
68
|
+
portacode-1.4.19.dev1.dist-info/licenses/LICENSE,sha256=2FGbCnUDgRYuQTkB1O1dUUpu5CVAjK1j4_p6ack9Z54,1066
|
|
69
69
|
test_modules/README.md,sha256=Do_agkm9WhSzueXjRAkV_xEj6Emy5zB3N3VKY5Roce8,9274
|
|
70
70
|
test_modules/__init__.py,sha256=1LcbHodIHsB0g-g4NGjSn6AMuCoGbymvXPYLOb6Z7F0,53
|
|
71
71
|
test_modules/test_device_online.py,sha256=QtYq0Dq9vME8Gp2O4fGSheqVf8LUtpsSKosXXk56gGM,1654
|
|
@@ -91,8 +91,8 @@ testing_framework/core/playwright_manager.py,sha256=Tw46qwxIhOFkS48C2IWIQHHNpEe-
|
|
|
91
91
|
testing_framework/core/runner.py,sha256=j2QwNJmAxVBmJvcbVS7DgPJUKPNzqfLmt_4NNdaKmZU,19297
|
|
92
92
|
testing_framework/core/shared_cli_manager.py,sha256=BESSNtyQb7BOlaOvZmm04T8Uezjms4KCBs2MzTxvzYQ,8790
|
|
93
93
|
testing_framework/core/test_discovery.py,sha256=2FZ9fJ8Dp5dloA-fkgXoJ_gCMC_nYPBnA3Hs2xlagzM,4928
|
|
94
|
-
portacode-1.4.19.dist-info/METADATA,sha256=
|
|
95
|
-
portacode-1.4.19.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
96
|
-
portacode-1.4.19.dist-info/entry_points.txt,sha256=lLUUL-BM6_wwe44Xv0__5NQ1BnAz6jWjSMFvZdWW3zU,48
|
|
97
|
-
portacode-1.4.19.dist-info/top_level.txt,sha256=TGhTYUxfW8SyVZc_zGgzjzc24gGT7nSw8Qf73liVRKM,41
|
|
98
|
-
portacode-1.4.19.dist-info/RECORD,,
|
|
94
|
+
portacode-1.4.19.dev1.dist-info/METADATA,sha256=2B8W6NO6XW1w4ibrmET1NRlKfVU9bOO5CA4RVX-ZJLU,13051
|
|
95
|
+
portacode-1.4.19.dev1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
96
|
+
portacode-1.4.19.dev1.dist-info/entry_points.txt,sha256=lLUUL-BM6_wwe44Xv0__5NQ1BnAz6jWjSMFvZdWW3zU,48
|
|
97
|
+
portacode-1.4.19.dev1.dist-info/top_level.txt,sha256=TGhTYUxfW8SyVZc_zGgzjzc24gGT7nSw8Qf73liVRKM,41
|
|
98
|
+
portacode-1.4.19.dev1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|