diff --git a/tests/test_repo_hygiene.py b/tests/test_repo_hygiene.py index c8ef1d0..fdc6039 100644 --- a/tests/test_repo_hygiene.py +++ b/tests/test_repo_hygiene.py @@ -40,8 +40,22 @@ re.compile(r"ali-pod\d"), ] -_MLX_IMPORT = re.compile(r"^\s*(?:from\s+mlx(?:\s|\.)|import\s+mlx(?:\s|\.))", - re.MULTILINE) +# ```` after ``mlx(?:_lm)?`` matches ``import mlx``, ``import mlx.core``, +# ``from mlx_lm.models...`` and ``from mlx_lm import ...`` alike, while a +# hypothetical ``mlxfoo`` package still does not match. The previous +# pattern required a space or dot right after ``mlx`` and therefore let +# ``mlx_lm`` imports through. +_MLX_IMPORT = re.compile(r"^\s*(?:from|import)\s+mlx(?:_lm)?", re.MULTILINE) + +# Files outside ``backends/mlx`` that currently import MLX packages. Each +# entry is a known boundary violation tracked for removal; delete the entry +# once the import is gone so the guard starts enforcing it again. +_MLX_IMPORT_KNOWN_VIOLATIONS = { + # ``_gather_sort`` / ``_scatter_unsort`` come from + # ``mlx_lm.models.switch_layers``; they should move into the framework + # so the streaming layer is importable on other backends. + "src/edge0/streaming/layer.py", +} _SECRET_PATTERNS = [ re.compile(r"\bsk-[A-Za-z0-9_-]{20,}\b"), @@ -88,7 +102,10 @@ def test_mlx_imports_stay_inside_the_backend(): for path in (ROOT / "src" / "edge0").rglob("*.py"): rel = path.relative_to(ROOT) text = path.read_text(encoding="utf-8") - if _MLX_IMPORT.search(text) and "backends/mlx" not in rel.as_posix(): + posix = rel.as_posix() + if "backends/mlx" in posix or posix in _MLX_IMPORT_KNOWN_VIOLATIONS: + continue + if _MLX_IMPORT.search(text): bad.append(str(rel)) assert not bad, ( "MLX imports must live under edge0/backends/mlx/ only:\n"