portacode 1.4.16.dev8__py3-none-any.whl → 1.4.16.dev9__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.dev8'
32
- __version_tuple__ = version_tuple = (1, 4, 16, 'dev8')
31
+ __version__ = version = '1.4.16.dev9'
32
+ __version_tuple__ = version_tuple = (1, 4, 16, 'dev9')
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -270,6 +270,142 @@ def _extract_storage(value: Any) -> str:
270
270
  return storage or "unknown"
271
271
 
272
272
 
273
+ def _size_token_to_gib(token: str) -> float:
274
+ match = re.match(r"^\s*([0-9]+(?:\.[0-9]+)?)\s*([KMGTP])?([iI]?[bB])?\s*$", token)
275
+ if not match:
276
+ return 0.0
277
+ number = float(match.group(1))
278
+ unit = (match.group(2) or "").upper()
279
+ scale = {
280
+ "": 1,
281
+ "K": 1024**1,
282
+ "M": 1024**2,
283
+ "G": 1024**3,
284
+ "T": 1024**4,
285
+ "P": 1024**5,
286
+ }.get(unit, 1)
287
+ return (number * scale) / 1024**3
288
+
289
+
290
+ def _extract_size_gib(value: Any) -> float:
291
+ if not value:
292
+ return 0.0
293
+ text = str(value)
294
+ for part in text.split(","):
295
+ if "size=" in part:
296
+ token = part.split("=", 1)[1]
297
+ return _size_token_to_gib(token)
298
+ return _size_token_to_gib(text)
299
+
300
+
301
+ def _storage_from_lxc(cfg: Dict[str, Any], entry: Dict[str, Any]) -> str:
302
+ rootfs = cfg.get("rootfs") or entry.get("rootfs")
303
+ storage = _extract_storage(rootfs)
304
+ if storage != "unknown":
305
+ return storage
306
+ for idx in range(0, 10):
307
+ mp_value = cfg.get(f"mp{idx}")
308
+ storage = _extract_storage(mp_value)
309
+ if storage != "unknown":
310
+ return storage
311
+ return "unknown"
312
+
313
+
314
+ def _storage_from_qemu(cfg: Dict[str, Any]) -> str:
315
+ preferred_keys = []
316
+ for prefix in ("scsi", "virtio", "sata", "ide"):
317
+ preferred_keys.extend(f"{prefix}{idx}" for idx in range(0, 6))
318
+ seen = set()
319
+ for key in preferred_keys:
320
+ value = cfg.get(key)
321
+ if value is None:
322
+ continue
323
+ seen.add(key)
324
+ text = str(value)
325
+ if "media=cdrom" in text or "cloudinit" in text:
326
+ continue
327
+ storage = _extract_storage(text)
328
+ if storage != "unknown":
329
+ return storage
330
+ for key in sorted(cfg.keys()):
331
+ if key in seen:
332
+ continue
333
+ if not any(key.startswith(prefix) for prefix in ("scsi", "virtio", "sata", "ide")):
334
+ continue
335
+ value = cfg.get(key)
336
+ if value is None:
337
+ continue
338
+ text = str(value)
339
+ if "media=cdrom" in text or "cloudinit" in text:
340
+ continue
341
+ storage = _extract_storage(text)
342
+ if storage != "unknown":
343
+ return storage
344
+ for key in ("efidisk0", "tpmstate0"):
345
+ storage = _extract_storage(cfg.get(key))
346
+ if storage != "unknown":
347
+ return storage
348
+ return "unknown"
349
+
350
+
351
+ def _primary_lxc_disk(cfg: Dict[str, Any], entry: Dict[str, Any]) -> str:
352
+ return str(cfg.get("rootfs") or entry.get("rootfs") or "")
353
+
354
+
355
+ def _primary_qemu_disk(cfg: Dict[str, Any]) -> str:
356
+ preferred_keys = []
357
+ for prefix in ("scsi", "virtio", "sata", "ide"):
358
+ preferred_keys.extend(f"{prefix}{idx}" for idx in range(0, 6))
359
+ seen = set()
360
+ for key in preferred_keys:
361
+ value = cfg.get(key)
362
+ if value is None:
363
+ continue
364
+ seen.add(key)
365
+ text = str(value)
366
+ if "media=cdrom" in text or "cloudinit" in text:
367
+ continue
368
+ return text
369
+ for key in sorted(cfg.keys()):
370
+ if key in seen:
371
+ continue
372
+ if not any(key.startswith(prefix) for prefix in ("scsi", "virtio", "sata", "ide")):
373
+ continue
374
+ value = cfg.get(key)
375
+ if value is None:
376
+ continue
377
+ text = str(value)
378
+ if "media=cdrom" in text or "cloudinit" in text:
379
+ continue
380
+ return text
381
+ return ""
382
+
383
+
384
+ def _pick_storage(kind: str, cfg: Dict[str, Any], entry: Dict[str, Any]) -> str:
385
+ storage = _extract_storage(cfg.get("storage") or entry.get("storage"))
386
+ if storage != "unknown":
387
+ return storage
388
+ if kind == "lxc":
389
+ return _storage_from_lxc(cfg, entry)
390
+ return _storage_from_qemu(cfg)
391
+
392
+
393
+ def _pick_disk_gib(kind: str, cfg: Dict[str, Any], entry: Dict[str, Any]) -> float:
394
+ if kind == "lxc":
395
+ size = _extract_size_gib(_primary_lxc_disk(cfg, entry))
396
+ if size:
397
+ return size
398
+ else:
399
+ size = _extract_size_gib(_primary_qemu_disk(cfg))
400
+ if size:
401
+ return size
402
+ for candidate in (entry.get("maxdisk"), entry.get("disk"), cfg.get("disk")):
403
+ if candidate in (None, 0):
404
+ continue
405
+ return _bytes_to_gib(candidate)
406
+ return 0.0
407
+
408
+
273
409
  def _normalize_storage_name(name: Any) -> str:
274
410
  if not name:
275
411
  return ""
@@ -511,8 +647,7 @@ def _build_unmanaged_container_entry(
511
647
  entry_type: str = "lxc",
512
648
  ) -> Dict[str, Any]:
513
649
  ram_mib = _to_int(cfg.get("memory")) or _bytes_to_mib(ct.get("maxmem"))
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)
650
+ disk_gib = disk_gib_override if disk_gib_override is not None else _pick_disk_gib(entry_type, cfg, ct)
516
651
  cpu_share = _to_float(
517
652
  cfg.get("cpulimit")
518
653
  or cfg.get("cpus")
@@ -521,10 +656,7 @@ def _build_unmanaged_container_entry(
521
656
  or ct.get("cpu")
522
657
  )
523
658
  hostname = ct.get("name") or cfg.get("hostname") or f"ct{vmid}"
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)
659
+ storage = storage_override or _pick_storage(entry_type, cfg, ct)
528
660
  status = (ct.get("status") or "unknown").lower()
529
661
  reserved = _parse_bool_flag(cfg.get("onboot"))
530
662
  storage_matches_default = _storage_matches_default(storage, default_storage)
@@ -586,10 +718,10 @@ def _extract_qemu_disk_info(cfg: Dict[str, Any]) -> Tuple[str | None, int]:
586
718
 
587
719
  def _storage_matches_default(storage_name: Any, default_storage: str | None) -> bool:
588
720
  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
721
+ return False
722
+ storage = _extract_storage(storage_name)
723
+ default = str(default_storage).strip()
724
+ return storage.lower() == default.lower()
593
725
 
594
726
 
595
727
  def _build_managed_containers_summary(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: portacode
3
- Version: 1.4.16.dev8
3
+ Version: 1.4.16.dev9
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=VGaY-LcOZhWVvp6-lz1Mul_hv8BD77OfZQu3NhYJfE8,719
4
+ portacode/_version.py,sha256=MiVkLaI5JqUCo1IS8Z-ZuJxS2iDsMOn2RV8qQYxQ5kE,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
@@ -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=CDrPWs-WLVMd95AKRukeUwZkW4J0kcWh3Vb3oLNNDCU,84394
25
+ portacode/connection/handlers/proxmox_infra.py,sha256=CcPTFTM5TMJ9uX4-Ndrfao6Xx_8zdMMPlvze08SHWgU,88344
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.dev8.dist-info/licenses/LICENSE,sha256=2FGbCnUDgRYuQTkB1O1dUUpu5CVAjK1j4_p6ack9Z54,1066
68
+ portacode-1.4.16.dev9.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.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,,
94
+ portacode-1.4.16.dev9.dist-info/METADATA,sha256=IwtVePxyAtqCsSSOTisxusWv8gBIvL1DSCoT96cNDj0,13051
95
+ portacode-1.4.16.dev9.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
96
+ portacode-1.4.16.dev9.dist-info/entry_points.txt,sha256=lLUUL-BM6_wwe44Xv0__5NQ1BnAz6jWjSMFvZdWW3zU,48
97
+ portacode-1.4.16.dev9.dist-info/top_level.txt,sha256=TGhTYUxfW8SyVZc_zGgzjzc24gGT7nSw8Qf73liVRKM,41
98
+ portacode-1.4.16.dev9.dist-info/RECORD,,