mirror of
https://github.com/yogeshojha/rengine.git
synced 2026-10-20 07:11:28 +02:00
Every plug-and-play surface carried its own "import the modules beside me and collect the subclasses" loop: mcp tools, toolbox tools, the two scanner directories, and the stage, section, provider and connector registries. shared/plugins.py holds it once, as classes_in_modules for a directory of modules and classes_in_packages for a directory of sub-packages; each registry keeps its own naming and duplicate rules. The copies had drifted. stages/dast_scan checked obj.__module__ so a scanner imported from another module is not registered twice; stages/vulnerability_scan did not, and would have registered the wrong class the day a second scanner lands. Both now hold the guard. The scanner copies also suppressed ModuleNotFoundError in silence, so a typo inside a scanner read as "not installed" rather than an error. Every skipped module is logged. Registry contents are unchanged: stages 27, sections 30, providers 3, connectors 1, mcp tools 26, toolbox tools 6, vuln scanners 1, dast scanners 2. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DafWxfoWZXVDgr9KroJBDZ
22 lines
500 B
Python
22 lines
500 B
Python
"""Tools are discovered by module."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from functools import lru_cache
|
|
from pathlib import Path
|
|
|
|
from shared.plugins import classes_in_modules
|
|
from toolbox.base import Tool
|
|
|
|
|
|
@lru_cache(maxsize=1)
|
|
def discover() -> dict[str, type[Tool]]:
|
|
found: dict[str, type[Tool]] = {}
|
|
for cls in classes_in_modules("toolbox.tools", Path(__file__).parent, Tool):
|
|
if cls.name:
|
|
found.setdefault(cls.name, cls)
|
|
return found
|
|
|
|
|
|
__all__ = ["discover"]
|