From e089dbc82a62683835512cd56c248ca3046e8ac8 Mon Sep 17 00:00:00 2001 From: Sebastian Tobie Date: Sat, 24 Feb 2024 10:20:47 +0100 Subject: [PATCH] rewrote the Types class --- galaxy.yml | 2 +- plugins/module_utils/generic.py | 131 ++++++++++++++++++++------------ src/ansible_module/__init__.py | 2 +- 3 files changed, 86 insertions(+), 49 deletions(-) diff --git a/galaxy.yml b/galaxy.yml index 5bc454b..361a8fa 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,7 +1,7 @@ --- namespace: sebastian name: base -version: 0.2.0 +version: 0.3.0 readme: README.md diff --git a/plugins/module_utils/generic.py b/plugins/module_utils/generic.py index ffa517a..0e992c2 100644 --- a/plugins/module_utils/generic.py +++ b/plugins/module_utils/generic.py @@ -19,36 +19,90 @@ SYSTEMD_SERVICE_CONFIG = SYSTEMD_CONFIG_ROOT / "system" AnsibleParameter = Dict[str, Any] -class _Type: - def __dir__(self) -> tuple: # pragma: nocover - return ( - "str", - "bool", - "int", - "float", - "path", - "raw", - "jsonarg", - "json", - "bytes", - "dict", - "list", - "bits", - "__doc__", +def wrap_func(func, **updates): + def wrapper(*args, **kwargs): + return func(*args, **kwargs) + + attrs = frozenset( + ('__module__', '__name__', '__qualname__', '__doc__', '__annotations__', '__type_params__') + ) - frozenset(updates.keys()) + for attr in attrs: + try: + value = getattr(func, attr) + except AttributeError: + pass + else: + print(f"changing:\n {value}\n {getattr(wrapper, attr)}") + setattr(wrapper, attr, value) + for attr, value in updates.items(): + setattr(wrapper, attr, value) + wrapper.__dict__.update(func.__dict__) + setattr(wrapper, "__wrapped__", func) + return wrapper + + +GENERIC_DOC = """Returns an dictionary for the Ansible {type} type.""" + + +def default(name: str): + def wrapped( + required: bool = False, + help: Optional[str] = None, + choices: Optional[Sequence] = None, + default: Optional[Any] = None, + ) -> AnsibleParameter: + option: AnsibleParameter = dict(type=name, required=required) + if choices is not None: + option["choices"] = choices + if default is not None: + option["default"] = default + if help is not None: + option["description"] = help.split("\n") + return option + + return wrapped + + +class meta(type): + def __new__(cls, clsname, bases, attrs): + types = frozenset( + ( + "str", + "bool", + "int", + "float", + "path", + "raw", + "jsonarg", + "json", + "bytes", + "dict", + "list", + "bits", + ) ) + for attr in types - set(attrs.keys()): + print(f"adding {attr} function") + attrs[attr] = wrap_func( + default(attr), __doc__=GENERIC_DOC.format(type=attr), __name__=attr, __qualname__=f"{clsname}.{attr}" + ) + attrs["__slots__"] = () + return super().__new__(cls, clsname, bases, attrs) - def __repr__(self) -> str: # pragma: nocover - return "Types()" - - def __call__(self) -> "_Type": # pragma: nocover - return self +class Types(metaclass=meta): def list( - self, elements: Union[Type[object], str, AnsibleParameter], required: bool = False, help: Optional[str] = None, ) -> AnsibleParameter: + """Wrapper for the Ansible list type + + Args: + elements: The type of the elements + required: if the item is absolutly required + help: an helptext for the ansible-doc + """ option: AnsibleParameter = dict(type="list", required=required) if not isinstance(elements, (str, dict)): option["elements"] = elements.__name__ @@ -67,37 +121,20 @@ class _Type: option["description"] = help.split("\n") return option - def dict(self, required: bool = False, help: Optional[str] = None, **options: dict) -> AnsibleParameter: + def dict(required: bool = False, help: Optional[str] = None, **options: AnsibleParameter) -> AnsibleParameter: + """Wrapper for the Ansible dict type + + Args: + required: if the item is absolutly required + help: an helptext for the ansible-doc + options: The individual options that this parameter has + """ option: AnsibleParameter = dict(type="dict", required=required) option["option"] = options if help is not None: option["description"] = help.split("\n") return option - def __getattr__(self, name: str): - def argument( - required: bool = False, - help: Optional[str] = None, - choices: Optional[Sequence] = None, - default: Optional[Any] = None, - ) -> AnsibleParameter: - option: AnsibleParameter = dict(type=name, required=required) - if choices is not None: - option["choices"] = choices - if default is not None: - option["default"] = default - if help is not None: - option["description"] = help.split("\n") - return option - - argument.__name__ = name - argument.__qualname__ = f"Types.{name}" - argument.__doc__ = f"Simple wrapper for Ansible {name} argument dict" - return argument - - -Types = _Type() - def systemdbool(b: Union[bool, str]) -> str: """Converts values into things systemd can parse""" diff --git a/src/ansible_module/__init__.py b/src/ansible_module/__init__.py index d3ec452..493f741 100644 --- a/src/ansible_module/__init__.py +++ b/src/ansible_module/__init__.py @@ -1 +1 @@ -__version__ = "0.2.0" +__version__ = "0.3.0"