""" Library of classes modeling software and software-related data as represented in or used by Ansible. """ from typing import TypeAlias as Neotype from typing import TypedDict as Dict from typing import Never, Union from custtypes import ExecutedPath, IdlePath from enum import Enum from pathlib import Path, PurePath from whereami import USER_PATH, PROJ_ROOT from collections.abc import Sequence AppPath: Neotype = Union[ExecutedPath, IdlePath] class SoftScope(Enum): PERSONAL = 0 LOCAL = 1 GLOBAL = 2 class SoftPathGroup(Enum): CONFIG = 0 DATA = 1 MEM = 2 EXE = 3 _SubAppParams = Dict("_SubAppParams", { SoftScope.PERSONAL.name: IdlePath | list[IdlePath], SoftScope.LOCAL.name: IdlePath | list[IdlePath], SoftScope.GLOBAL.name: IdlePath | list[IdlePath] }, total=False) AppParams = Dict("AppParams", { SoftPathGroup.CONFIG.name: _SubAppParams, SoftPathGroup.DATA.name: _SubAppParams, SoftPathGroup.MEM.name: _SubAppParams, SoftPathGroup.EXE.name: _SubAppParams }, total=False) def __AppsInit(self, CONFIG = None, DATA = None, MEM = None, EXE = None): self.CONFIG = CONFIG self.DATA = DATA self.MEM = MEM self.EXE = EXE __app_input = { SoftPathGroup.CONFIG.name: { SoftScope.PERSONAL.name: [], SoftScope.LOCAL.name: [], SoftScope.GLOBAL.name: [] }, SoftPathGroup.DATA.name: { SoftScope.PERSONAL.name: [], SoftScope.LOCAL.name: [], SoftScope.GLOBAL.name: [] }, SoftPathGroup.MEM.name: { SoftScope.PERSONAL.name: [], SoftScope.LOCAL.name: [], SoftScope.GLOBAL.name: [] }, SoftPathGroup.EXE.name: { SoftScope.PERSONAL.name: [], SoftScope.LOCAL.name: [], SoftScope.GLOBAL.name: [] }, "__init__": __AppsInit } Apps = type("Apps", (), __app_input) # @TODO continue adding magic methods to below class # @NOTE https://rszalski.github.io/magicmethods/#sequence class Software (Sequence): __user_path: ExecutedPath = USER_PATH def __init__(self): self._fqdn: str | None = None # @TODO fix NameError for 'Software' in parameter type check def append(self, name: str, **kwpaths: _SubAppParams) -> AppParams: keyword_args: AppParams = kwpaths app = Apps(**keyword_args) setattr(self, name, app) return app def __getitem__(self, key: str) -> AppParams | Never: if hasattr(self, key): app: Apps = getattr(self, key) else: raise KeyError return app def __setitem__(self, key: tuple[str, SoftPathGroup], **value: IdlePath | list[IdlePath]) -> None | Never: if len(value) < 1 or len(value) > 3: raise ValueError app_params: _SubAppParams = value if hasattr(self, key[0]): app: Apps = getattr(self, key[0]) if hasattr(app, key[1]): app_child: _SubAppParams = getattr(app, key[1]) for k, v in app_params.items(): v = [v] if not isinstance(v, list) else v app_child[k]: IdlePath | list[IdlePath] = v setattr(app, key[1], app_child) else: raise KeyError setattr(self, key[0], app) else: raise KeyError def __delitem__(self, key: tuple[str | SoftPathGroup]) -> None | Never: if len(key) < 1 or len(key) > 3: raise KeyError if not hasattr(self, key[0]): raise KeyError if len(key) == 1: delattr(self, key[0]) elif len(key) > 1: app: Apps = getattr(self, key[0]) delattr(app, key[1]) setattr(self, key[0], app) def show(self, contents: bool = False) -> tuple[str]: apps: tuple[str] | tuple[Apps] = tuple( filter( lambda a: isinstance(getattr(self, a), Apps), dir(self) ) ) if contents: apps = tuple( map( lambda a: getattr(self, a), apps ) ) return apps def __len__(self) -> int: apps: tuple[str] = tuple( filter( lambda a: isinstance(getattr(self, a), Apps), dir(self) ) ) return len(apps) def pop(self) -> Never: raise NotImplementedError def remove(self) -> Never: raise NotImplementedError def __contains__(self) -> Never: raise NotImplementedError def count(self) -> Never: return NotImplementedError def __missing__(self) -> Never: raise NotImplementedError def __iter__(self) -> Never: raise NotImplementedError def reverse(self) -> Never: raise NotImplementedError def sort(self, key: Callable = (lambda e: e), reverse: bool = False) -> Never: raise NotImplementedError class Softs(Enum): ssh = 0