from __future__ import annotations import ast import re import tomllib from importlib.metadata import packages_distributions from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parent.parent RUNTIME_PACKAGE_DIRS = ( "agents", "api", "core", "device", "driver", "perception", "runtime", "semantic", "skills_learning", "storage", "tools", "workflow", "world", ) def test_workspace_distributions_own_expected_import_packages() -> None: distributions = packages_distributions() assert distributions.get("cloud") == ["device-cloud-platform"] assert distributions.get("core") == ["device-agent-runtime"] assert distributions.get("runtime") == ["device-agent-runtime"] def test_runtime_project_does_not_declare_cloud_distribution() -> None: project = tomllib.loads((PROJECT_ROOT / "pyproject.toml").read_text("utf-8")) dependencies = { _requirement_name(requirement) for requirement in project["project"].get("dependencies", []) } package_patterns = project["tool"]["setuptools"]["packages"]["find"]["include"] assert "device-cloud-platform" not in dependencies assert "cloud*" not in package_patterns def test_runtime_source_does_not_import_cloud() -> None: offenders: list[str] = [] for package_dir in RUNTIME_PACKAGE_DIRS: for path in (PROJECT_ROOT / package_dir).rglob("*.py"): tree = ast.parse(path.read_text("utf-8"), filename=str(path)) for node in ast.walk(tree): if isinstance(node, ast.Import): names = [alias.name for alias in node.names] elif isinstance(node, ast.ImportFrom) and node.module: names = [node.module] else: continue if any(name == "cloud" or name.startswith("cloud.") for name in names): offenders.append(str(path.relative_to(PROJECT_ROOT))) assert not offenders, f"runtime distribution imports cloud: {sorted(set(offenders))}" def _requirement_name(requirement: str) -> str: name = re.split(r"[\s<>=!~\[]", requirement, maxsplit=1)[0] return name.lower().replace("_", "-")