portacode 1.4.15.dev26__py3-none-any.whl → 1.4.16.dev0__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/project_state/manager.py +25 -3
- portacode/connection/handlers/proxmox_infra.py +22 -4
- portacode/connection/terminal.py +80 -0
- {portacode-1.4.15.dev26.dist-info → portacode-1.4.16.dev0.dist-info}/METADATA +1 -1
- {portacode-1.4.15.dev26.dist-info → portacode-1.4.16.dev0.dist-info}/RECORD +10 -10
- {portacode-1.4.15.dev26.dist-info → portacode-1.4.16.dev0.dist-info}/WHEEL +0 -0
- {portacode-1.4.15.dev26.dist-info → portacode-1.4.16.dev0.dist-info}/entry_points.txt +0 -0
- {portacode-1.4.15.dev26.dist-info → portacode-1.4.16.dev0.dist-info}/licenses/LICENSE +0 -0
- {portacode-1.4.15.dev26.dist-info → portacode-1.4.16.dev0.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.
|
|
32
|
-
__version_tuple__ = version_tuple = (1, 4,
|
|
31
|
+
__version__ = version = '1.4.16.dev0'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 4, 16, 'dev0')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -21,6 +21,24 @@ from .git_manager import GitManager
|
|
|
21
21
|
from .file_system_watcher import FileSystemWatcher
|
|
22
22
|
from ....logging_categories import get_categorized_logger, LogCategory
|
|
23
23
|
|
|
24
|
+
def _deterministic_file_tab_id(file_path: str) -> str:
|
|
25
|
+
try:
|
|
26
|
+
resolved = os.path.abspath(file_path)
|
|
27
|
+
mtime = int(Path(resolved).stat().st_mtime)
|
|
28
|
+
except OSError:
|
|
29
|
+
mtime = "unknown"
|
|
30
|
+
resolved = os.path.abspath(file_path)
|
|
31
|
+
return f"{resolved}:{mtime}"
|
|
32
|
+
|
|
33
|
+
def _deterministic_diff_tab_id(
|
|
34
|
+
file_path: str,
|
|
35
|
+
from_ref: str,
|
|
36
|
+
to_ref: str,
|
|
37
|
+
from_hash: Optional[str],
|
|
38
|
+
to_hash: Optional[str]
|
|
39
|
+
) -> str:
|
|
40
|
+
return f"diff:{os.path.abspath(file_path)}:{from_ref}:{to_ref}:{from_hash or ''}:{to_hash or ''}"
|
|
41
|
+
|
|
24
42
|
logger = get_categorized_logger(__name__)
|
|
25
43
|
|
|
26
44
|
# Global singleton instance
|
|
@@ -657,10 +675,10 @@ class ProjectStateManager:
|
|
|
657
675
|
# Create new file tab using tab factory
|
|
658
676
|
from ..tab_factory import get_tab_factory
|
|
659
677
|
tab_factory = get_tab_factory()
|
|
660
|
-
|
|
678
|
+
|
|
661
679
|
try:
|
|
662
680
|
logger.info(f"About to create tab for file: {file_path}")
|
|
663
|
-
new_tab = await tab_factory.create_file_tab(file_path)
|
|
681
|
+
new_tab = await tab_factory.create_file_tab(file_path, tab_id=_deterministic_file_tab_id(file_path))
|
|
664
682
|
logger.info(f"Tab created successfully, adding to project state")
|
|
665
683
|
project_state.open_tabs[tab_key] = new_tab
|
|
666
684
|
if set_active:
|
|
@@ -842,7 +860,11 @@ class ProjectStateManager:
|
|
|
842
860
|
diff_title = f"{os.path.basename(file_path)} ({' '.join(title_parts)})"
|
|
843
861
|
|
|
844
862
|
diff_tab = await tab_factory.create_diff_tab_with_title(
|
|
845
|
-
file_path,
|
|
863
|
+
file_path,
|
|
864
|
+
original_content,
|
|
865
|
+
modified_content,
|
|
866
|
+
diff_title,
|
|
867
|
+
tab_id=_deterministic_diff_tab_id(file_path, from_ref, to_ref, from_hash, to_hash),
|
|
846
868
|
diff_details=diff_details
|
|
847
869
|
)
|
|
848
870
|
|
|
@@ -410,6 +410,7 @@ def _build_managed_containers_summary(records: List[Dict[str, Any]]) -> Dict[str
|
|
|
410
410
|
containers.append(
|
|
411
411
|
{
|
|
412
412
|
"vmid": str(_as_int(record.get("vmid"))) if record.get("vmid") is not None else None,
|
|
413
|
+
"device_id": record.get("device_id"),
|
|
413
414
|
"hostname": record.get("hostname"),
|
|
414
415
|
"template": record.get("template"),
|
|
415
416
|
"storage": record.get("storage"),
|
|
@@ -876,12 +877,17 @@ def _parse_ctid(message: Dict[str, Any]) -> int:
|
|
|
876
877
|
|
|
877
878
|
|
|
878
879
|
def _ensure_container_managed(
|
|
879
|
-
proxmox: Any, node: str, vmid: int
|
|
880
|
+
proxmox: Any, node: str, vmid: int, *, device_id: Optional[str] = None
|
|
880
881
|
) -> Tuple[Dict[str, Any], Dict[str, Any]]:
|
|
881
882
|
record = _read_container_record(vmid)
|
|
882
883
|
ct_cfg = proxmox.nodes(node).lxc(str(vmid)).config.get()
|
|
883
884
|
if not ct_cfg or MANAGED_MARKER not in (ct_cfg.get("description") or ""):
|
|
884
885
|
raise RuntimeError(f"Container {vmid} is not managed by Portacode.")
|
|
886
|
+
record_device_id = record.get("device_id")
|
|
887
|
+
if device_id and str(record_device_id or "") != str(device_id):
|
|
888
|
+
raise RuntimeError(
|
|
889
|
+
f"Container {vmid} is managed for device {record_device_id!r}, not {device_id!r}."
|
|
890
|
+
)
|
|
885
891
|
return record, ct_cfg
|
|
886
892
|
|
|
887
893
|
|
|
@@ -1835,10 +1841,13 @@ class StartProxmoxContainerHandler(SyncHandler):
|
|
|
1835
1841
|
|
|
1836
1842
|
def execute(self, message: Dict[str, Any]) -> Dict[str, Any]:
|
|
1837
1843
|
vmid = _parse_ctid(message)
|
|
1844
|
+
on_behalf_of_device = (message.get("on_behalf_of_device") or "").strip()
|
|
1845
|
+
if not on_behalf_of_device:
|
|
1846
|
+
raise ValueError("on_behalf_of_device is required for start_proxmox_container")
|
|
1838
1847
|
config = _ensure_infra_configured()
|
|
1839
1848
|
proxmox = _connect_proxmox(config)
|
|
1840
1849
|
node = _get_node_from_config(config)
|
|
1841
|
-
_ensure_container_managed(proxmox, node, vmid)
|
|
1850
|
+
_ensure_container_managed(proxmox, node, vmid, device_id=on_behalf_of_device)
|
|
1842
1851
|
|
|
1843
1852
|
status, elapsed = _start_container(proxmox, node, vmid)
|
|
1844
1853
|
_update_container_record(vmid, {"status": "running"})
|
|
@@ -1853,6 +1862,7 @@ class StartProxmoxContainerHandler(SyncHandler):
|
|
|
1853
1862
|
"details": {"exitstatus": status.get("exitstatus")},
|
|
1854
1863
|
"status": status.get("status"),
|
|
1855
1864
|
"infra": infra,
|
|
1865
|
+
"on_behalf_of_device": on_behalf_of_device,
|
|
1856
1866
|
}
|
|
1857
1867
|
|
|
1858
1868
|
|
|
@@ -1865,10 +1875,13 @@ class StopProxmoxContainerHandler(SyncHandler):
|
|
|
1865
1875
|
|
|
1866
1876
|
def execute(self, message: Dict[str, Any]) -> Dict[str, Any]:
|
|
1867
1877
|
vmid = _parse_ctid(message)
|
|
1878
|
+
on_behalf_of_device = (message.get("on_behalf_of_device") or "").strip()
|
|
1879
|
+
if not on_behalf_of_device:
|
|
1880
|
+
raise ValueError("on_behalf_of_device is required for stop_proxmox_container")
|
|
1868
1881
|
config = _ensure_infra_configured()
|
|
1869
1882
|
proxmox = _connect_proxmox(config)
|
|
1870
1883
|
node = _get_node_from_config(config)
|
|
1871
|
-
_ensure_container_managed(proxmox, node, vmid)
|
|
1884
|
+
_ensure_container_managed(proxmox, node, vmid, device_id=on_behalf_of_device)
|
|
1872
1885
|
|
|
1873
1886
|
status, elapsed = _stop_container(proxmox, node, vmid)
|
|
1874
1887
|
final_status = status.get("status") or "stopped"
|
|
@@ -1889,6 +1902,7 @@ class StopProxmoxContainerHandler(SyncHandler):
|
|
|
1889
1902
|
"details": {"exitstatus": status.get("exitstatus")},
|
|
1890
1903
|
"status": final_status,
|
|
1891
1904
|
"infra": infra,
|
|
1905
|
+
"on_behalf_of_device": on_behalf_of_device,
|
|
1892
1906
|
}
|
|
1893
1907
|
|
|
1894
1908
|
|
|
@@ -1901,10 +1915,13 @@ class RemoveProxmoxContainerHandler(SyncHandler):
|
|
|
1901
1915
|
|
|
1902
1916
|
def execute(self, message: Dict[str, Any]) -> Dict[str, Any]:
|
|
1903
1917
|
vmid = _parse_ctid(message)
|
|
1918
|
+
on_behalf_of_device = (message.get("on_behalf_of_device") or "").strip()
|
|
1919
|
+
if not on_behalf_of_device:
|
|
1920
|
+
raise ValueError("on_behalf_of_device is required for remove_proxmox_container")
|
|
1904
1921
|
config = _ensure_infra_configured()
|
|
1905
1922
|
proxmox = _connect_proxmox(config)
|
|
1906
1923
|
node = _get_node_from_config(config)
|
|
1907
|
-
_ensure_container_managed(proxmox, node, vmid)
|
|
1924
|
+
_ensure_container_managed(proxmox, node, vmid, device_id=on_behalf_of_device)
|
|
1908
1925
|
|
|
1909
1926
|
stop_status, stop_elapsed = _stop_container(proxmox, node, vmid)
|
|
1910
1927
|
delete_status, delete_elapsed = _delete_container(proxmox, node, vmid)
|
|
@@ -1916,6 +1933,7 @@ class RemoveProxmoxContainerHandler(SyncHandler):
|
|
|
1916
1933
|
"action": "remove",
|
|
1917
1934
|
"success": True,
|
|
1918
1935
|
"ctid": str(vmid),
|
|
1936
|
+
"on_behalf_of_device": on_behalf_of_device,
|
|
1919
1937
|
"message": f"Deleted container {vmid} in {delete_elapsed:.1f}s.",
|
|
1920
1938
|
"details": {
|
|
1921
1939
|
"stop_exitstatus": stop_status.get("exitstatus"),
|
portacode/connection/terminal.py
CHANGED
|
@@ -685,6 +685,7 @@ class TerminalManager:
|
|
|
685
685
|
try:
|
|
686
686
|
# Initialize project state
|
|
687
687
|
project_state = await manager.initialize_project_state(session_name, project_folder_path)
|
|
688
|
+
await self._restore_tabs_from_session_metadata(manager, project_state, session)
|
|
688
689
|
|
|
689
690
|
# Send initial project state to the client
|
|
690
691
|
initial_state_payload = {
|
|
@@ -710,6 +711,85 @@ class TerminalManager:
|
|
|
710
711
|
|
|
711
712
|
except Exception as exc:
|
|
712
713
|
logger.exception("terminal_manager: Error initializing project states for new sessions: %s", exc)
|
|
714
|
+
|
|
715
|
+
async def _restore_tabs_from_session_metadata(self, manager, project_state, session):
|
|
716
|
+
"""Restore open tabs/active tab from client session metadata if available."""
|
|
717
|
+
if not session or not project_state:
|
|
718
|
+
return
|
|
719
|
+
|
|
720
|
+
descriptors = session.get("open_tabs") or []
|
|
721
|
+
if not descriptors:
|
|
722
|
+
return
|
|
723
|
+
|
|
724
|
+
session_id = project_state.client_session_id
|
|
725
|
+
logger.info("terminal_manager: 🧭 Restoring %d tabs from metadata for session %s", len(descriptors), session_id)
|
|
726
|
+
|
|
727
|
+
for descriptor in descriptors:
|
|
728
|
+
parsed = self._parse_tab_descriptor(descriptor)
|
|
729
|
+
if not parsed:
|
|
730
|
+
continue
|
|
731
|
+
|
|
732
|
+
tab_type = parsed.get("tab_type")
|
|
733
|
+
file_path = parsed.get("file_path")
|
|
734
|
+
metadata = parsed.get("metadata", {})
|
|
735
|
+
|
|
736
|
+
if tab_type == "file" and file_path:
|
|
737
|
+
try:
|
|
738
|
+
await manager.open_file(session_id, file_path, set_active=False)
|
|
739
|
+
except Exception as exc:
|
|
740
|
+
logger.warning("terminal_manager: Failed to restore file tab %s for session %s: %s", file_path, session_id, exc)
|
|
741
|
+
continue
|
|
742
|
+
|
|
743
|
+
if tab_type == "diff" and file_path:
|
|
744
|
+
from_ref = metadata.get("from") or metadata.get("from_ref")
|
|
745
|
+
to_ref = metadata.get("to") or metadata.get("to_ref")
|
|
746
|
+
if not from_ref or not to_ref:
|
|
747
|
+
logger.warning("terminal_manager: Skipping diff tab %s for session %s because from/to references are missing", file_path, session_id)
|
|
748
|
+
continue
|
|
749
|
+
from_hash = metadata.get("from_hash") or metadata.get("fromHash")
|
|
750
|
+
to_hash = metadata.get("to_hash") or metadata.get("toHash")
|
|
751
|
+
try:
|
|
752
|
+
await manager.open_diff_tab(session_id, file_path, from_ref, to_ref, from_hash=from_hash, to_hash=to_hash)
|
|
753
|
+
except Exception as exc:
|
|
754
|
+
logger.warning("terminal_manager: Failed to restore diff tab %s for session %s: %s", file_path, session_id, exc)
|
|
755
|
+
continue
|
|
756
|
+
|
|
757
|
+
logger.debug("terminal_manager: Unknown tab descriptor ignored for session %s: %s", session_id, descriptor)
|
|
758
|
+
|
|
759
|
+
active_index = session.get("active_tab")
|
|
760
|
+
try:
|
|
761
|
+
active_index_int = int(active_index) if active_index is not None else None
|
|
762
|
+
except (TypeError, ValueError):
|
|
763
|
+
active_index_int = None
|
|
764
|
+
|
|
765
|
+
if active_index_int is not None and active_index_int >= 0:
|
|
766
|
+
current_tabs = list(project_state.open_tabs.values())
|
|
767
|
+
if 0 <= active_index_int < len(current_tabs):
|
|
768
|
+
try:
|
|
769
|
+
await manager.set_active_tab(session_id, current_tabs[active_index_int].tab_id)
|
|
770
|
+
except Exception as exc:
|
|
771
|
+
logger.warning("terminal_manager: Failed to set active tab for session %s: %s", session_id, exc)
|
|
772
|
+
else:
|
|
773
|
+
logger.debug("terminal_manager: Active tab index %s out of range for session %s", active_index_int, session_id)
|
|
774
|
+
|
|
775
|
+
def _parse_tab_descriptor(self, descriptor: str) -> Optional[Dict[str, Any]]:
|
|
776
|
+
"""Parse a URL-friendly tab descriptor string."""
|
|
777
|
+
if not descriptor:
|
|
778
|
+
return None
|
|
779
|
+
|
|
780
|
+
try:
|
|
781
|
+
parts = descriptor.split("|")
|
|
782
|
+
tab_type = parts[0] if parts else None
|
|
783
|
+
file_path = parts[1] if len(parts) > 1 else None
|
|
784
|
+
metadata = {}
|
|
785
|
+
for part in parts[2:]:
|
|
786
|
+
if "=" in part:
|
|
787
|
+
key, value = part.split("=", 1)
|
|
788
|
+
metadata[key] = value
|
|
789
|
+
return {"tab_type": tab_type, "file_path": file_path, "metadata": metadata}
|
|
790
|
+
except Exception as exc:
|
|
791
|
+
logger.warning("terminal_manager: Failed to parse tab descriptor '%s': %s", descriptor, exc)
|
|
792
|
+
return None
|
|
713
793
|
|
|
714
794
|
async def _send_targeted_terminal_list(self, message: Dict[str, Any], target_sessions: List[str]) -> None:
|
|
715
795
|
"""Send terminal_list command to specific client sessions.
|
|
@@ -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=VRcygEdkbj_kT_PkjvrdxuvM8kPIsg1rBzzADtCIQiA,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
|
|
@@ -12,7 +12,7 @@ portacode/connection/README.md,sha256=f9rbuIEKa7cTm9C98rCiBbEtbiIXQU11esGSNhSMiJ
|
|
|
12
12
|
portacode/connection/__init__.py,sha256=atqcVGkViIEd7pRa6cP2do07RJOM0UWpbnz5zXjGktU,250
|
|
13
13
|
portacode/connection/client.py,sha256=jtLb9_YufqPkzi9t8VQH3iz_JEMisbtY6a8L9U5weiU,14181
|
|
14
14
|
portacode/connection/multiplex.py,sha256=L-TxqJ_ZEbfNEfu1cwxgJ5vUdyRzZjsMy2Kx1diiZys,5237
|
|
15
|
-
portacode/connection/terminal.py,sha256=
|
|
15
|
+
portacode/connection/terminal.py,sha256=n1Uu92JacV5K6d1Qwx94Tw9OB2Tpke5HqsW2NDn76Ls,49032
|
|
16
16
|
portacode/connection/handlers/README.md,sha256=HsLZG1QK1JNm67HsgL6WoDg9nxzKXxwkc5fJPFJdX5g,12169
|
|
17
17
|
portacode/connection/handlers/WEBSOCKET_PROTOCOL.md,sha256=OtObmoVAXlf0uU1HidTWNmyJYBS1Yl6Rpgyh6TOTjUQ,100590
|
|
18
18
|
portacode/connection/handlers/__init__.py,sha256=WSeBmi65GWFQPYt9M3E10rn0uZ_EPCJzNJOzSf2HZyw,2921
|
|
@@ -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=Pe-GX5IjQhjyBPxm0hNNLoKm7NZPmOsRCPRdEIkmjhE,73134
|
|
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
|
|
@@ -35,7 +35,7 @@ portacode/connection/handlers/project_state/__init__.py,sha256=5ucIqk6Iclqg6bKkL
|
|
|
35
35
|
portacode/connection/handlers/project_state/file_system_watcher.py,sha256=r9_UKxWTbzum0jGqxIafe68Ced2Y3xOp3ZmkpBOfRpw,8573
|
|
36
36
|
portacode/connection/handlers/project_state/git_manager.py,sha256=iGQ7LYIA7uHsZHdj3HEc_LYo7S1Lqv6-AeyyMwknBPo,70027
|
|
37
37
|
portacode/connection/handlers/project_state/handlers.py,sha256=qgOSt26rxAGNxW07AoevTwDPBdxblX4J-dX-EjOKtg4,38232
|
|
38
|
-
portacode/connection/handlers/project_state/manager.py,sha256=
|
|
38
|
+
portacode/connection/handlers/project_state/manager.py,sha256=ori_QpeoY1sdpY8WDYIx-kl_gNfZ7o8eq84CcOBlvIs,67915
|
|
39
39
|
portacode/connection/handlers/project_state/models.py,sha256=EZTKvxHKs8QlQUbzI0u2IqfzfRRXZixUIDBwTGCJATI,4313
|
|
40
40
|
portacode/connection/handlers/project_state/utils.py,sha256=LsbQr9TH9Bz30FqikmtTxco4PlB_n0kUIuPKQ6Fb_mo,1665
|
|
41
41
|
portacode/link_capture/__init__.py,sha256=93LjyYDqzOimsIDBhsPibTl7tr-8DiIzyDF7JWQkE2A,1231
|
|
@@ -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.
|
|
68
|
+
portacode-1.4.16.dev0.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.
|
|
95
|
-
portacode-1.4.
|
|
96
|
-
portacode-1.4.
|
|
97
|
-
portacode-1.4.
|
|
98
|
-
portacode-1.4.
|
|
94
|
+
portacode-1.4.16.dev0.dist-info/METADATA,sha256=UbwKMn3EpfoXPgYPALM8B5GwR0TluW6buRsbfQZhvlc,13051
|
|
95
|
+
portacode-1.4.16.dev0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
96
|
+
portacode-1.4.16.dev0.dist-info/entry_points.txt,sha256=lLUUL-BM6_wwe44Xv0__5NQ1BnAz6jWjSMFvZdWW3zU,48
|
|
97
|
+
portacode-1.4.16.dev0.dist-info/top_level.txt,sha256=TGhTYUxfW8SyVZc_zGgzjzc24gGT7nSw8Qf73liVRKM,41
|
|
98
|
+
portacode-1.4.16.dev0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|