Files
id_configurator/id_configurator/modules/base.py
T
2026-09-09 23:18:24 +02:00

52 lines
1.6 KiB
Python

"""Base class and registry for configuration modules.
Each module inspects the configuration and the source filesystem (via the
`Context`) to decide whether it applies, then writes the resulting files to
the destination directory.
"""
from __future__ import annotations
from abc import ABC, abstractmethod
from id_configurator.context import Context
_REGISTRY: list[type[Module]] = []
class Module(ABC):
name: str
@abstractmethod
def is_relevant(self, context: Context) -> bool:
"""Return True if this module has something to do for the given configuration."""
@abstractmethod
def apply(self, context: Context) -> None:
"""Write the module's changes to the destination directory."""
def register(module_cls: type[Module]) -> type[Module]:
"""Class decorator registering a module so it is picked up by the CLI."""
_REGISTRY.append(module_cls)
return module_cls
def all_modules() -> list[type[Module]]:
return list(_REGISTRY)
def sanitize_filename(name: str) -> str:
"""Make a user-supplied name safe to use as a single filesystem path
component.
Modules that derive a file's name from configuration data (a
certificate's name, a repository's name, ...) must run it through this
first: without it, a name containing `/` (or `\\`, harmless on the
target systems this tool writes to but stripped for good measure)
would silently turn into extra, unintended path segments - creating
nested directories a careless or malicious name shouldn't be able to
create - instead of the single file the caller asked for.
"""
return name.replace("/", "_").replace("\\", "_")