50 lines
1.7 KiB
Python
50 lines
1.7 KiB
Python
"""Registry that auto-discovers mutation rules from the rules directory."""
|
|
|
|
import importlib
|
|
import inspect
|
|
from pathlib import Path
|
|
from typing import Dict, List, Type
|
|
|
|
from app.dataset.rules.base import MutationRule
|
|
|
|
|
|
class RuleRegistry:
|
|
def __init__(self, rules_dir: Path):
|
|
self.rules_dir = rules_dir
|
|
self._rules: Dict[str, List[MutationRule]] = {}
|
|
|
|
def discover(self) -> None:
|
|
"""Scan rules directory and register all MutationRule subclasses."""
|
|
self._rules.clear()
|
|
for lang_dir in self.rules_dir.iterdir():
|
|
if not lang_dir.is_dir():
|
|
continue
|
|
for py_file in lang_dir.glob("*.py"):
|
|
if py_file.name.startswith("_"):
|
|
continue
|
|
module_name = f"app.dataset.rules.{lang_dir.name}.{py_file.stem}"
|
|
try:
|
|
module = importlib.import_module(module_name)
|
|
except Exception:
|
|
continue
|
|
for _, obj in inspect.getmembers(module, inspect.isclass):
|
|
if (
|
|
issubclass(obj, MutationRule)
|
|
and obj is not MutationRule
|
|
and not getattr(obj, "__abstractmethods__", False)
|
|
):
|
|
rule = obj()
|
|
self._rules.setdefault(rule.language, []).append(rule)
|
|
|
|
def rules_for(self, language: str) -> List[MutationRule]:
|
|
return self._rules.get(language, [])
|
|
|
|
def all_rules(self) -> Dict[str, List[MutationRule]]:
|
|
return self._rules.copy()
|
|
|
|
|
|
def get_registry() -> RuleRegistry:
|
|
registry = RuleRegistry(Path(__file__).parent)
|
|
registry.discover()
|
|
return registry
|