orchestrata_ultimate.core.banned_libraries
Reference › orchestrata_ultimate › core › banned_libraries
The one reader of the banned-dependency registry, .claude/banned-libraries.txt. Before it existed, checkers kept their own hardcoded ban lists, which drifted from the registry (one codemod review check omitted several banned packages while its message claimed to read the file). Now the gates (differential and fact_extractor), the codemod review and a test-purity script all call it.
load_banned_libraries(path) returns (name, rationale) pairs; the comment block immediately above a run of entries becomes that run's rationale, clamped to 400 characters, so a finding can say why a package is banned. A missing registry gives an empty list rather than an error. normalise_package folds - and _ together, banned_names returns the normalised name set, ban_targets lists the names an import could match by, and is_banned checks an import at whichever granularity the registry declares.
At a glance
| Source | src/orchestrata_ultimate/core/banned_libraries.py |
| Lines of code | 118 |
| Classes | 0 |
| Functions | 5 |
| Imports (internal) | none |
| Imported by | orchestrata_ultimate.gates.differential, orchestrata_ultimate.gates.fact_extractor, orchestrata_ultimate.refactor.codemod.review, scripts.audit_test_purity |
| Tests that import it | tests/core/test_banned_libraries.py, tests/generated_core/test_banned_libraries_generated.py |
Class diagram
No classes; see Functions.
Dependency diagram
API
Functions
| Function | Signature | Summary |
|---|---|---|
load_banned_libraries |
load_banned_libraries(path: Path) -> list[tuple[str, str]] |
Return (name, rationale) for every entry in the registry. |
normalise_package |
normalise_package(name: str) -> str |
PyPI treats - and _ as the same character in a distribution name. |
banned_names |
banned_names(path: Path) -> set[str] |
Just the names, normalised — for callers that do not need rationales. |
ban_targets |
ban_targets(module: str) -> tuple[str, ...] |
The names a ban registry could match this import by. |
is_banned |
is_banned(module: str, banned: set[str] | frozenset[str]) -> bool |
Is this import banned, at whichever granularity the registry declared? |
Source
"""The banned-dependency registry, read from one place by everything.
`.claude/banned-libraries.txt` is the single source of truth CLAUDE.md names,
and this module is the single source of truth for READING it. The registry
being shared data is only half the property that matters; a second parser is a
second chance to disagree about what an entry means.
The reason this exists at all was measured, twice, in the same phase:
- `serialize_codebase_ast.py standards` held `_FORBIDDEN_IMPORTS = {"pyswip"}`
in code. Nothing else knew pyswip was banned, and the P5 differential is
the only reason anyone found out before that checker was deleted.
- `refactor/codemod/review.py` held `("pytest_xdist", "xdist")` in code while
its own finding message told the reader the list came from
`.claude/banned-libraries.txt`. It was missing docker, grpcio, grpcio-tools,
grpc, unittest.mock, mock and pyswip — so an agent's pending edit could
introduce any of them and the codemod review would pass.
A hardcoded copy does not announce itself. It looks exactly like an enforcement
point that works, right up until the registry gains an entry it never hears
about, and the gap only shows when something compares the two.
"""
from __future__ import annotations
from pathlib import Path
#: Where the registry lives, relative to the repo root.
BANNED_LIBRARIES = Path(".claude/banned-libraries.txt")
#: Rationales are clamped so one verbose entry cannot dominate a fact base or a
#: finding message. Long enough for the reason, short enough to read.
_REASON_LIMIT = 400
def load_banned_libraries(path: Path) -> list[tuple[str, str]]:
"""Return ``(name, rationale)`` for every entry in the registry.
The comment block immediately ABOVE a run of entries is that run's
rationale. Carrying it through means a violation can report WHY a package
is banned rather than only that it is — the difference between an
actionable finding and a wall.
A missing registry yields an empty list rather than raising: the callers
are checkers, and a checker that explodes on a missing config file is worse
than one that reports nothing, which is visible in its own output.
"""
path = Path(path)
if not path.is_file():
return []
entries: list[tuple[str, str]] = []
pending: list[str] = []
after_entry = False
for raw in path.read_text(encoding="utf-8").splitlines():
line = raw.strip()
if not line:
continue
if line.startswith("#"):
# A comment FOLLOWING entries starts a new block's rationale.
# Without this reset every reason accumulated the file header plus
# every earlier block, and the clamp then cut the actual reason off
# the end — so the first entries carried prose about the wrong
# package. Measured on `xdist`, whose "deadlocks THIS suite" never
# survived the truncation.
if after_entry:
pending = []
after_entry = False
comment = line.lstrip("#").strip()
if comment.startswith("---"):
# The registry's own "--- entries ---" divider. Everything above
# it documents the FILE, not any package.
pending = []
continue
if comment:
pending.append(comment)
continue
name = line.split("==")[0].split(">=")[0].split("<")[0].split("[")[0].strip()
if name:
entries.append((name, " ".join(pending)[:_REASON_LIMIT]))
after_entry = True
return entries
def normalise_package(name: str) -> str:
"""PyPI treats ``-`` and ``_`` as the same character in a distribution name.
Mirrors ``normalise_package/2`` in ``gate_rules.pl``.
"""
return name.replace("-", "_")
def banned_names(path: Path) -> set[str]:
"""Just the names, normalised — for callers that do not need rationales."""
return {normalise_package(name) for name, _ in load_banned_libraries(path)}
def ban_targets(module: str) -> tuple[str, ...]:
"""The names a ban registry could match this import by.
Mirrors ``ban_target/3`` in ``gate_rules.pl``. A DOTLESS registry entry
names a distribution, so the comparison is against the import's top-level
package and every submodule of it is caught. A DOTTED entry names one
module inside a package that is otherwise fine — ``unittest.mock`` is
banned, ``unittest`` is not — so the comparison is against the full path.
A caller does not know which form the entry took, so it tries both.
Folding to the top level alone is the bug this replaced: it made
``from unittest.mock import patch`` look like an import of ``unittest``,
which no registry entry matches, so the ban was unenforceable.
"""
top = module.split(".")[0]
return (module,) if module == top else (module, top)
def is_banned(module: str, banned: set[str] | frozenset[str]) -> bool:
"""Is this import banned, at whichever granularity the registry declared?"""
return any(normalise_package(t).lower() in banned for t in ban_targets(module))