portacode 1.4.16.dev3__py3-none-any.whl → 1.4.16.dev8__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 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.16.dev3'
32
- __version_tuple__ = version_tuple = (1, 4, 16, 'dev3')
31
+ __version__ = version = '1.4.16.dev8'
32
+ __version_tuple__ = version_tuple = (1, 4, 16, 'dev8')
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -1153,17 +1153,26 @@ Provides system information in response to a `system_info` action. Handled by [`
1153
1153
  * `status` (string): Lowercase lifecycle status (e.g., `running`, `stopped`, `deleted`).
1154
1154
  * `created_at` (string|null): ISO timestamp recorded when the CT was provisioned.
1155
1155
  * `managed` (boolean): `true` for Portacode-managed entries.
1156
+ * `matches_default_storage` (boolean): `true` when this container is backed by the default storage pool used for new Portacode containers.
1157
+ * `type` (string): Either `lxc` or `qemu`, indicating whether we enumerated the container from the LXC or QEMU APIs.
1156
1158
  * `unmanaged_containers` (array[object]): Facts about containers Portacode did not provision; fields mirror the managed list but are marked `managed=false`.
1157
- * `unmanaged_count` (integer): Number of unmanaged containers detected on the node.
1158
- * `allocated_ram_mib` (integer): Total RAM reserved by both managed and unmanaged containers.
1159
- * `allocated_disk_gib` (integer): Total disk reserved by both managed and unmanaged containers.
1160
- * `allocated_cpu_share` (number): Total CPU shares requested by both managed and unmanaged containers.
1161
- * `available_ram_mib` (integer|null): Remaining RAM after subtracting all reservations from the host total (null when unavailable).
1162
- * `available_disk_gib` (integer|null): Remaining disk GB after subtracting allocations from the host total.
1163
- * `available_cpu_share` (number|null): Remaining CPU shares after allocations.
1164
- * `host_total_ram_mib` (integer|null): Host memory capacity observed via Proxmox.
1165
- * `host_total_disk_gib` (integer|null): Host disk capacity observed via Proxmox.
1166
- * `host_total_cpu_cores` (integer|null): Number of CPU cores reported by Proxmox.
1159
+ * `reserve_on_boot` (boolean): `true` when the CT is configured to start at boot; this flag is used to decide if its RAM and CPU allocations count toward the available totals.
1160
+ * `unmanaged_count` (integer): Number of unmanaged containers detected on the node.
1161
+ * `allocated_ram_mib` (integer): Total RAM reserved by both managed and unmanaged containers.
1162
+ * `allocated_disk_gib` (integer): Total disk reserved by both managed and unmanaged containers.
1163
+ * `allocated_cpu_share` (number): Total CPU shares requested by both managed and unmanaged containers.
1164
+ * `available_ram_mib` (integer|null): Remaining RAM after subtracting all reservations from the host total (null when unavailable).
1165
+ * `available_disk_gib` (integer|null): Remaining disk GB after subtracting allocations from the host total.
1166
+ * `available_cpu_share` (number|null): Remaining CPU shares after allocations.
1167
+ * `host_total_ram_mib` (integer|null): Host memory capacity observed via Proxmox.
1168
+ * `host_total_disk_gib` (integer|null): Host disk capacity observed via Proxmox.
1169
+ * `host_total_cpu_cores` (integer|null): Number of CPU cores reported by Proxmox.
1170
+ * `default_storage` (string|null): Storage pool name selected during infrastructure configuration.
1171
+ * `default_storage_snapshot` (object|null): Fresh stats for the default storage pool:
1172
+ * `storage` (string): Storage pool identifier.
1173
+ * `total_gib` (integer|null): Capacity of the storage pool.
1174
+ * `avail_gib` (integer|null): Available space remaining.
1175
+ * `used_gib` (integer|null): Space already consumed.
1167
1176
  * `portacode_version` (string): Installed CLI version returned by `portacode.__version__`.
1168
1177
 
1169
1178
  ### `proxmox_infra_configured`
@@ -259,6 +259,30 @@ def _bytes_to_gib(value: Any) -> int:
259
259
  return int(round(_normalize_bytes(value) / (1024**3)))
260
260
 
261
261
 
262
+ def _extract_storage(value: Any) -> str:
263
+ if not value:
264
+ return "unknown"
265
+ text = str(value).strip()
266
+ if not text:
267
+ return "unknown"
268
+ primary = text.split(",", 1)[0]
269
+ storage = primary.split(":", 1)[0].strip()
270
+ return storage or "unknown"
271
+
272
+
273
+ def _normalize_storage_name(name: Any) -> str:
274
+ if not name:
275
+ return ""
276
+ return str(name).strip().lower()
277
+
278
+
279
+ def _parse_bool_flag(value: Any) -> bool:
280
+ if isinstance(value, bool):
281
+ return value
282
+ text = str(value or "").strip().lower()
283
+ return text in {"1", "true", "yes", "on"}
284
+
285
+
262
286
  def _parse_iso_timestamp(value: str) -> Optional[datetime]:
263
287
  if not value:
264
288
  return None
@@ -451,9 +475,44 @@ def _extract_host_totals(node_status: Dict[str, Any] | None) -> Tuple[Optional[i
451
475
  return host_ram, host_disk, host_cpu
452
476
 
453
477
 
454
- def _build_unmanaged_container_entry(ct: Dict[str, Any], cfg: Dict[str, Any], vmid: str) -> Dict[str, Any]:
478
+ def _parse_disk_reference(value: Any) -> Tuple[str | None, int]:
479
+ if not value:
480
+ return None, 0
481
+ text = str(value)
482
+ primary = text.split(",", 1)[0]
483
+ if ":" not in primary:
484
+ return primary.strip() or None, 0
485
+ storage_name, size_part = primary.split(":", 1)
486
+ storage_name = storage_name.strip() or None
487
+ size_text = size_part.strip()
488
+ if not size_text:
489
+ return storage_name, 0
490
+ unit = size_text[-1].upper()
491
+ number = size_text[:-1] if unit in {"G", "M"} else size_text
492
+ try:
493
+ value_num = float(number)
494
+ except ValueError:
495
+ return storage_name, 0
496
+ if unit == "M":
497
+ gib = value_num / 1024.0
498
+ else:
499
+ gib = value_num
500
+ return storage_name, int(round(gib))
501
+
502
+
503
+ def _build_unmanaged_container_entry(
504
+ ct: Dict[str, Any],
505
+ cfg: Dict[str, Any],
506
+ vmid: str,
507
+ default_storage: str | None,
508
+ *,
509
+ disk_gib_override: int | None = None,
510
+ storage_override: str | None = None,
511
+ entry_type: str = "lxc",
512
+ ) -> Dict[str, Any]:
455
513
  ram_mib = _to_int(cfg.get("memory")) or _bytes_to_mib(ct.get("maxmem"))
456
- disk_gib = _bytes_to_gib(ct.get("maxdisk"))
514
+ disk_source = cfg.get("disk") or ct.get("disk") or ct.get("maxdisk")
515
+ disk_gib = disk_gib_override if disk_gib_override is not None else _bytes_to_gib(disk_source)
457
516
  cpu_share = _to_float(
458
517
  cfg.get("cpulimit")
459
518
  or cfg.get("cpus")
@@ -462,8 +521,13 @@ def _build_unmanaged_container_entry(ct: Dict[str, Any], cfg: Dict[str, Any], vm
462
521
  or ct.get("cpu")
463
522
  )
464
523
  hostname = ct.get("name") or cfg.get("hostname") or f"ct{vmid}"
465
- storage = cfg.get("storage") or ct.get("storage")
524
+ storage_source = (
525
+ storage_override or cfg.get("storage") or ct.get("storage") or ct.get("rootfs")
526
+ )
527
+ storage = _extract_storage(storage_source)
466
528
  status = (ct.get("status") or "unknown").lower()
529
+ reserved = _parse_bool_flag(cfg.get("onboot"))
530
+ storage_matches_default = _storage_matches_default(storage, default_storage)
467
531
  return {
468
532
  "vmid": vmid,
469
533
  "hostname": hostname,
@@ -472,16 +536,68 @@ def _build_unmanaged_container_entry(ct: Dict[str, Any], cfg: Dict[str, Any], vm
472
536
  "disk_gib": disk_gib,
473
537
  "ram_mib": ram_mib,
474
538
  "cpu_share": cpu_share,
539
+ "reserve_on_boot": reserved,
540
+ "matches_default_storage": storage_matches_default,
541
+ "type": entry_type,
475
542
  "status": status,
476
543
  "managed": False,
477
544
  }
478
545
 
479
546
 
547
+ def _get_storage_snapshot(proxmox: Any, node: str, storage_name: str | None) -> Dict[str, Any] | None:
548
+ if not storage_name:
549
+ return None
550
+ try:
551
+ storage = proxmox.nodes(node).storage(storage_name).status.get()
552
+ except Exception as exc:
553
+ logger.debug("Unable to read storage status %s:%s: %s", node, storage_name, exc)
554
+ return None
555
+ total_bytes = storage.get("total")
556
+ avail_bytes = storage.get("avail")
557
+ used_bytes = storage.get("used")
558
+ return {
559
+ "storage": storage_name,
560
+ "total_gib": _bytes_to_gib(total_bytes) if total_bytes is not None else None,
561
+ "avail_gib": _bytes_to_gib(avail_bytes) if avail_bytes is not None else None,
562
+ "used_gib": _bytes_to_gib(used_bytes) if used_bytes is not None else None,
563
+ }
564
+
565
+
566
+ def _extract_qemu_disk_info(cfg: Dict[str, Any]) -> Tuple[str | None, int]:
567
+ disk_keys = sorted(
568
+ key
569
+ for key in cfg.keys()
570
+ if (
571
+ key.startswith("ide")
572
+ or key.startswith("sata")
573
+ or key.startswith("scsi")
574
+ or key.startswith("virtio")
575
+ or key.startswith("efidisk")
576
+ or key.startswith("raid")
577
+ )
578
+ and cfg.get(key)
579
+ )
580
+ for key in disk_keys:
581
+ storage_name, size_gib = _parse_disk_reference(cfg.get(key))
582
+ if storage_name or size_gib:
583
+ return storage_name, size_gib
584
+ return None, 0
585
+
586
+
587
+ def _storage_matches_default(storage_name: Any, default_storage: str | None) -> bool:
588
+ if not default_storage:
589
+ return True
590
+ normalized_storage = _normalize_storage_name(_extract_storage(storage_name))
591
+ normalized_default = _normalize_storage_name(_extract_storage(default_storage))
592
+ return normalized_storage == normalized_default
593
+
480
594
 
481
595
  def _build_managed_containers_summary(
482
596
  records: List[Dict[str, Any]],
483
597
  unmanaged_records: List[Dict[str, Any]],
484
598
  node_status: Dict[str, Any] | None,
599
+ storage_snapshot: Dict[str, Any] | None,
600
+ default_storage: str | None,
485
601
  ) -> Dict[str, Any]:
486
602
  managed_containers: List[Dict[str, Any]] = []
487
603
  total_ram = 0
@@ -509,18 +625,36 @@ def _build_managed_containers_summary(
509
625
  "created_at": record.get("created_at"),
510
626
  "status": status,
511
627
  "managed": True,
628
+ "matches_default_storage": _storage_matches_default(record.get("storage"), default_storage),
512
629
  }
513
630
  )
514
631
 
515
- unmanaged_total_ram = sum(_to_int(entry.get("ram_mib")) for entry in unmanaged_records)
516
- unmanaged_total_disk = sum(_to_int(entry.get("disk_gib")) for entry in unmanaged_records)
517
- unmanaged_total_cpu = sum(_to_float(entry.get("cpu_share")) for entry in unmanaged_records)
632
+ unmanaged_total_ram = sum(
633
+ _to_int(entry.get("ram_mib"))
634
+ for entry in unmanaged_records
635
+ if entry.get("reserve_on_boot")
636
+ )
637
+ unmanaged_total_disk = sum(
638
+ _to_int(entry.get("disk_gib"))
639
+ for entry in unmanaged_records
640
+ if entry.get("matches_default_storage")
641
+ )
642
+ unmanaged_total_cpu = sum(
643
+ _to_float(entry.get("cpu_share"))
644
+ for entry in unmanaged_records
645
+ if entry.get("reserve_on_boot")
646
+ )
518
647
 
519
648
  allocated_ram = total_ram + unmanaged_total_ram
520
649
  allocated_disk = total_disk + unmanaged_total_disk
521
650
  allocated_cpu = total_cpu_share + unmanaged_total_cpu
522
651
 
523
- host_ram, host_disk, host_cpu = _extract_host_totals(node_status)
652
+ host_ram_node, host_disk_node, host_cpu_node = _extract_host_totals(node_status)
653
+ storage_host_disk = storage_snapshot.get("total_gib") if storage_snapshot else None
654
+ host_ram = host_ram_node
655
+ host_disk = storage_host_disk if storage_host_disk is not None else host_disk_node
656
+ host_cpu = host_cpu_node
657
+
524
658
 
525
659
  return {
526
660
  "updated_at": datetime.utcnow().isoformat() + "Z",
@@ -540,6 +674,8 @@ def _build_managed_containers_summary(
540
674
  "host_total_ram_mib": host_ram,
541
675
  "host_total_disk_gib": host_disk,
542
676
  "host_total_cpu_cores": host_cpu,
677
+ "default_storage": default_storage,
678
+ "default_storage_snapshot": storage_snapshot,
543
679
  }
544
680
 
545
681
 
@@ -548,12 +684,15 @@ def _get_managed_containers_summary(force: bool = False) -> Dict[str, Any]:
548
684
  records: List[Dict[str, Any]],
549
685
  config: Dict[str, Any] | None,
550
686
  managed_vmids: Set[str],
551
- ) -> Tuple[Dict[str, str], List[Dict[str, Any]], Dict[str, Any] | None]:
687
+ default_storage: str | None,
688
+ ) -> Tuple[Dict[str, str], List[Dict[str, Any]], Dict[str, Any] | None, Dict[str, Any] | None]:
552
689
  statuses: Dict[str, str] = {}
553
690
  unmanaged: List[Dict[str, Any]] = []
554
691
  node_status: Dict[str, Any] | None = None
555
692
  if not config:
556
- return statuses, unmanaged, node_status
693
+ return statuses, unmanaged, node_status, None
694
+ proxmox = None
695
+ node = None
557
696
  try:
558
697
  proxmox = _connect_proxmox(config)
559
698
  node = _get_node_from_config(config)
@@ -574,10 +713,45 @@ def _get_managed_containers_summary(force: bool = False) -> Dict[str, Any]:
574
713
  description = (cfg.get("description") or "")
575
714
  if MANAGED_MARKER in description:
576
715
  continue
577
- unmanaged.append(_build_unmanaged_container_entry(ct, cfg, vmid_key))
716
+ unmanaged.append(
717
+ _build_unmanaged_container_entry(ct, cfg, vmid_key, default_storage, entry_type="lxc")
718
+ )
719
+ for vm in proxmox.nodes(node).qemu.get():
720
+ vmid_val = vm.get("vmid")
721
+ if vmid_val is None:
722
+ continue
723
+ vmid_key = str(_to_int(vmid_val))
724
+ statuses[vmid_key] = (vm.get("status") or "unknown").lower()
725
+ if vmid_key in managed_vmids:
726
+ continue
727
+ cfg: Dict[str, Any] = {}
728
+ try:
729
+ cfg = proxmox.nodes(node).qemu(vmid_key).config.get() or {}
730
+ except Exception as exc:
731
+ logger.debug("Failed to read config for VM %s: %s", vmid_key, exc)
732
+ description = (cfg.get("description") or "")
733
+ if MANAGED_MARKER in description:
734
+ continue
735
+ storage_name, disk_gib_override = _extract_qemu_disk_info(cfg)
736
+ unmanaged.append(
737
+ _build_unmanaged_container_entry(
738
+ vm,
739
+ cfg,
740
+ vmid_key,
741
+ default_storage,
742
+ disk_gib_override=disk_gib_override,
743
+ storage_override=storage_name,
744
+ entry_type="qemu",
745
+ )
746
+ )
578
747
  except Exception as exc: # pragma: no cover - best effort
579
748
  logger.debug("Failed to refresh container statuses: %s", exc)
580
- return statuses, unmanaged, node_status
749
+ storage_snapshot = (
750
+ _get_storage_snapshot(proxmox, node, default_storage)
751
+ if proxmox and node
752
+ else None
753
+ )
754
+ return statuses, unmanaged, node_status, storage_snapshot
581
755
 
582
756
  now = time.monotonic()
583
757
  with _MANAGED_CONTAINERS_CACHE_LOCK:
@@ -590,7 +764,10 @@ def _get_managed_containers_summary(force: bool = False) -> Dict[str, Any]:
590
764
  managed_vmids: Set[str] = {
591
765
  str(_to_int(record.get("vmid"))) for record in records if record.get("vmid") is not None
592
766
  }
593
- statuses, unmanaged, node_status = _refresh_container_statuses(records, config, managed_vmids)
767
+ default_storage = config.get("default_storage") if config else None
768
+ statuses, unmanaged, node_status, storage_snapshot = _refresh_container_statuses(
769
+ records, config, managed_vmids, default_storage
770
+ )
594
771
  for record in records:
595
772
  vmid = record.get("vmid")
596
773
  if vmid is None:
@@ -599,7 +776,7 @@ def _get_managed_containers_summary(force: bool = False) -> Dict[str, Any]:
599
776
  status = statuses.get(vmid_key)
600
777
  if status:
601
778
  record["status"] = status
602
- summary = _build_managed_containers_summary(records, unmanaged, node_status)
779
+ summary = _build_managed_containers_summary(records, unmanaged, node_status, storage_snapshot, default_storage)
603
780
  with _MANAGED_CONTAINERS_CACHE_LOCK:
604
781
  _MANAGED_CONTAINERS_CACHE["timestamp"] = now
605
782
  _MANAGED_CONTAINERS_CACHE["summary"] = summary
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: portacode
3
- Version: 1.4.16.dev3
3
+ Version: 1.4.16.dev8
4
4
  Summary: Portacode CLI client and SDK
5
5
  Home-page: https://github.com/portacode/portacode
6
6
  Author: Meena Erian
@@ -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=HLH9O1BtoKVO_ZLCnGRXJ_xMQe43OyaD07QzQgNnelQ,719
4
+ portacode/_version.py,sha256=VGaY-LcOZhWVvp6-lz1Mul_hv8BD77OfZQu3NhYJfE8,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=U7zkUpwscWf5aqimNIP3uYXvg-t9S0MhyaZ3ygF-ADk,102593
17
+ portacode/connection/handlers/WEBSOCKET_PROTOCOL.md,sha256=R9trHDWDuADIY2Xs2LrpIw1himtxE-NDb_6CzNVNVcM,103625
18
18
  portacode/connection/handlers/__init__.py,sha256=WSeBmi65GWFQPYt9M3E10rn0uZ_EPCJzNJOzSf2HZyw,2921
19
19
  portacode/connection/handlers/base.py,sha256=oENFb-Fcfzwk99Qx8gJQriEMiwSxwygwjOiuCH36hM4,10231
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=IG8qp607grx4v9jSWL5TawUrIN0VElIR2swjA_rpn9U,78132
25
+ portacode/connection/handlers/proxmox_infra.py,sha256=CDrPWs-WLVMd95AKRukeUwZkW4J0kcWh3Vb3oLNNDCU,84394
26
26
  portacode/connection/handlers/registry.py,sha256=qXGE60sYEWg6ZtVQzFcZ5YI2XWR6lMgw4hAL9x5qR1I,6181
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.16.dev3.dist-info/licenses/LICENSE,sha256=2FGbCnUDgRYuQTkB1O1dUUpu5CVAjK1j4_p6ack9Z54,1066
68
+ portacode-1.4.16.dev8.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.16.dev3.dist-info/METADATA,sha256=ulkuZ2NkbFWXncNI8ZPHvWD2ThvRJ3-rFMYBNuFHpG8,13051
95
- portacode-1.4.16.dev3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
96
- portacode-1.4.16.dev3.dist-info/entry_points.txt,sha256=lLUUL-BM6_wwe44Xv0__5NQ1BnAz6jWjSMFvZdWW3zU,48
97
- portacode-1.4.16.dev3.dist-info/top_level.txt,sha256=TGhTYUxfW8SyVZc_zGgzjzc24gGT7nSw8Qf73liVRKM,41
98
- portacode-1.4.16.dev3.dist-info/RECORD,,
94
+ portacode-1.4.16.dev8.dist-info/METADATA,sha256=oXg32kxrBFgBp8Che47OV2D20d5zz0Vdyc517TAdzCU,13051
95
+ portacode-1.4.16.dev8.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
96
+ portacode-1.4.16.dev8.dist-info/entry_points.txt,sha256=lLUUL-BM6_wwe44Xv0__5NQ1BnAz6jWjSMFvZdWW3zU,48
97
+ portacode-1.4.16.dev8.dist-info/top_level.txt,sha256=TGhTYUxfW8SyVZc_zGgzjzc24gGT7nSw8Qf73liVRKM,41
98
+ portacode-1.4.16.dev8.dist-info/RECORD,,