Skip to content

Commit 5ccc6dc

Browse files
committed
Recognize custom registered family authorities
Treat custom AutoRegisterMeta-derived metaclasses and nominal Registered family bases as satisfying semantic inheritance membership SSOT. Add a regression test for derived registered family roots so the advisor does not push duplicate registry declarations when a shared nominal base already owns registration semantics.
1 parent ca6d8fc commit 5ccc6dc

2 files changed

Lines changed: 24 additions & 3 deletions

File tree

nominal_refactor_advisor/detectors/_helpers.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,15 @@ def declaration_scaffold(
617617
def declares_autoregister_meta(self, node: ast.ClassDef) -> bool:
618618
return any(
619619
(
620-
_ast_terminal_name(keyword.value) == "AutoRegisterMeta"
620+
(metaclass_name := _ast_terminal_name(keyword.value)) is not None
621+
and (
622+
metaclass_name == "AutoRegisterMeta"
623+
or metaclass_name.endswith("AutoRegisterMeta")
624+
or (
625+
"Registered" in metaclass_name
626+
and metaclass_name.endswith("Meta")
627+
)
628+
)
621629
for keyword in node.keywords
622630
if keyword.arg == "metaclass"
623631
)
@@ -629,8 +637,7 @@ def inherits_named_registration_authority(self, node: ast.ClassDef) -> bool:
629637
(base_name := _ast_terminal_name(base)) is not None
630638
and (
631639
"AutoRegister" in base_name
632-
or base_name.startswith("Registered")
633-
or base_name.endswith("Registered")
640+
or "Registered" in base_name
634641
)
635642
for base in node.bases
636643
)

tests/test_refactor_advisor.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5733,6 +5733,20 @@ def test_ignores_semantic_inheritance_family_with_inherited_registry_authority(
57335733
)
57345734

57355735

5736+
def test_ignores_semantic_inheritance_family_with_custom_registered_family_base(
5737+
tmp_path: Path,
5738+
) -> None:
5739+
_write_module(
5740+
tmp_path,
5741+
"pkg/mod.py",
5742+
'\nfrom abc import ABC\nfrom metaclass_registry import AutoRegisterMeta\n\n\nclass DerivedRegisteredFamilyMeta(AutoRegisterMeta):\n pass\n\n\nclass DerivedRegisteredFamily(ABC, metaclass=DerivedRegisteredFamilyMeta):\n __registry_key__ = "derived_key"\n __skip_if_no_key__ = True\n\n\nclass PayloadCarrier(DerivedRegisteredFamily):\n def mapping(self):\n return {}\n\n\nclass AlphaPayload(PayloadCarrier):\n def mapping(self):\n return {"case": "alpha"}\n\n\nclass BetaPayload(PayloadCarrier):\n def mapping(self):\n return {"case": "beta"}\n',
5743+
)
5744+
assert not any(
5745+
finding.detector_id == "semantic_inheritance_family_ssot"
5746+
for finding in analyze_path(tmp_path)
5747+
)
5748+
5749+
57365750
def test_detects_autoregister_meta_family_without_rent_proof(
57375751
tmp_path: Path,
57385752
) -> None:

0 commit comments

Comments
 (0)