mirror of
https://github.com/d9pouces/id_configurator.git
synced 2026-11-09 01:47:21 +01:00
be91425355
Signed-off-by: d9pouces <github@19pouces.net>
52 lines
1.6 KiB
Python
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("\\", "_")
|