Coverage for src / lexigram / admin / dashboard / naming_policy.py: 55%
20 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-13 22:14 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-13 22:14 +0800
1from __future__ import annotations
3import logging
4from typing import Literal
6logger = logging.getLogger(__name__)
9class NameCollisionError(Exception):
10 """Raised when a name collision occurs in error mode."""
13class NamingPolicy:
14 """Namespacing and collision detection for contributor surface names."""
16 def __init__(self, mode: Literal["warn", "error"] = "warn") -> None:
17 self._mode = mode
18 self._seen: dict[str, dict[str, str]] = {}
20 def namespaced(self, package_source: str, name: str) -> str:
21 """Prefix *name* with *package_source* unless already prefixed."""
22 prefix = f"{package_source}."
23 if name.startswith(prefix):
24 return name
25 return f"{prefix}{name}"
27 def register(self, kind: str, name: str) -> None:
28 """Record a name under *kind*; warn or raise on collision."""
29 if name in self._seen.setdefault(kind, {}):
30 if self._mode == "error":
31 raise NameCollisionError(
32 f"collision on {kind} '{name}': "
33 f"already registered by "
34 f"'{self._seen[kind][name]}'"
35 )
36 logger.warning(
37 "collision on %s '%s'",
38 kind,
39 name,
40 extra={"item_kind": kind, "item_name": name},
41 )
42 else:
43 self._seen[kind][name] = name