diff --git a/plugins/module_utils/generic.py b/plugins/module_utils/generic.py index 8242d97..b6c6d23 100644 --- a/plugins/module_utils/generic.py +++ b/plugins/module_utils/generic.py @@ -1,4 +1,5 @@ import pathlib +import warnings from typing import Any, Callable, Dict, Optional, Sequence, Tuple, Type, Union __all__ = ( @@ -20,83 +21,10 @@ class _sdict(dict): __name__: str -class _Type(type): - def __new__(metacls, cls, bases, classdict, **kwds): - individual = dict() - virtfunc = None - virtual = () - special = dict() - for key, value in classdict.items(): - if key.startswith("_"): - if key == "__getattr__": - virtfunc = value - special[key] = value - elif key == "__dir__": - virtual = tuple(value(None)) - special[key] = value - elif key in ("__doc__", "__module__", "__qualname__"): - special[key] = value - else: - individual[key] = value - if len(virtual) != 0 and virtfunc is None: # pragma: nocover - raise TypeError("Virtual funcs defined, but no func to generate them defined") - special["_attr"] = tuple(virtual + tuple(individual.keys())) - special["_vfunc"] = virtfunc - special["_virtual"] = virtual - special["_individual"] = individual - annotations = dict() - if len(virtual) != 0 and virtfunc is not None: # pragma: nocover - anno = virtfunc(None, virtual[0]).__annotations__ - for virtualkey in virtual: - annotations[virtualkey] = Callable[[*anno.values()], Dict[str, Any]] - annotations["__dir__"] = Callable[[], Tuple[str]] - special["__annotations__"] = annotations - inst = super().__new__(metacls, cls, bases, special, **kwds) - return inst - - def __getattribute__(self, __name: str) -> Any: - if __name in ( - "__dict__", - "__doc__", - "_attr", - "__annotations__", - "_virtual", - "_vfunc", - "_individual", - ): - return super().__getattribute__(__name) - if __name in self._virtual: - return self._vfunc(self, __name) - if __name in self._individual: - return self._individual[__name] - return super().__getattribute__(__name) - - def __dir__(self): - data = set() - data.update(("__dir__", "__doc__", "__annotations__")) - data.update(self._virtual) - data.update(self._individual.keys()) - return tuple(data) - - -class Types(metaclass=_Type): - """Provides helpers for the ansible types""" - - def list( - elements: Union[Type[object], str], - required: bool = False, - help: Optional[str] = None, - ) -> dict: - if not isinstance(elements, str): - elements = elements.__name__ - option = _sdict(type="list", elements=elements, required=required) - option._help = help - return option - +class _Type: def __dir__(self) -> tuple: return ( "str", - "dict", "bool", "int", "float", @@ -105,9 +33,45 @@ class Types(metaclass=_Type): "jsonarg", "json", "bytes", + "dict", + "list", "bits", + "__doc__", ) + def list( + self, + elements: Union[Type[object], str, dict], + required: bool = False, + help: Optional[str] = None, + ) -> _sdict: + option = _sdict(type="list", required=required) + if not isinstance(elements, (str, _sdict)): + option["elements"] = elements.__name__ + elif isinstance(elements, dict): + option["elements"] = elements["type"] + if elements["type"] == "dict": + option["options"] = dict() + for name, value in elements["option"].items(): + option["options"][name] = value + if isinstance(value, _sdict) and value._help is not None: + option["options"][name]["description"] = value._help + elif "description" in option["options"][name]: + pass + else: + warnings.warn( + "helptext of option {} is unset. Ansible requires suboptions to have an documentation".format(name), + ) + + option._help = help + return option + + def dict(self, required: bool = False, help: Optional[str] = None, **options: dict) -> _sdict: + option = _sdict(type="dict", required=required) + option["option"] = options + option._help = help + return option + def __getattr__(self, name: str): def argument( required: bool = False, @@ -125,10 +89,13 @@ class Types(metaclass=_Type): return output argument.__name__ = name - argument.__doc__ = argument.__doc__.format(name) + argument.__doc__ = argument.__doc__.format(name) # type: ignore return argument +Types = _Type() + + def systemdbool(b: Union[bool, str]) -> str: if b is True: return "yes"