test(workspace): verify distribution boundaries
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
|
||||
- [x] 2.1 Move the existing `cloud` package under `packages/cloud-platform` while preserving every `cloud.*` import path.
|
||||
- [x] 2.2 Remove `cloud*` from the root distribution's setuptools discovery and update path-sensitive composition tests or tooling.
|
||||
- [ ] 2.3 Add packaging tests that identify the owning distribution for Runtime and cloud modules and reject reverse cloud dependencies.
|
||||
- [x] 2.3 Add packaging tests that identify the owning distribution for Runtime and cloud modules and reject reverse cloud dependencies.
|
||||
|
||||
## 3. Locking And Developer Commands
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
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("_", "-")
|
||||
Reference in New Issue
Block a user