Files
skato-ansible/softman.py

153 lines
4.8 KiB
Python

"""
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
AppPath: Neotype = Union[ExecutedPath, IdlePath]
class SoftScope(Enum):
PERSONAL = 0
LOCAL = 1
GLOBAL = 2
class SoftPathGroup(Enum):
CONFIG = 0
DATA = 1
MEM = 2
# @TODO continue adding magic methods to below class
# @NOTE https://rszalski.github.io/magicmethods/#sequence
class Software:
# @TODO 2 options: add additional requirements to type definition below,
# or ensure attribute which stores data of this type also stores other data
_AppParams = Dict("_AppParams", {
SoftPathGroup.CONFIG.name: {
SoftScope.PERSONAL.name: IdlePath | list[IdlePath],
SoftScope.LOCAL.name: IdlePath | list[IdlePath],
SoftScope.GLOBAL.name: IdlePath | list[IdlePath]
},
SoftPathGroup.DATA.name: {
SoftScope.PERSONAL.name: IdlePath | list[IdlePath],
SoftScope.LOCAL.name: IdlePath | list[IdlePath],
SoftScope.GLOBAL.name: IdlePath | list[IdlePath]
},
SoftPathGroup.MEM.name: {
SoftScope.PERSONAL.name: IdlePath | list[IdlePath],
SoftScope.LOCAL.name: IdlePath | list[IdlePath],
SoftScope.GLOBAL.name: IdlePath | list[IdlePath]
}
}, total=False)
_SubAppParams = Dict("_SubAppParams", {
SoftScope.PERSONAL.name: IdlePath | list[IdlePath],
SoftScope.LOCAL.name: IdlePath | list[IdlePath],
SoftScope.GLOBAL.name: IdlePath | list[IdlePath]
}, total=False)
__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: []
}
}
_Apps = type("_Apps", (), **__app_input)
__user_path: ExecutedPath = USER_PATH
def __init__(self):
self._fqdn: str | None = None
def declare(self, name: str, **kwpaths: Software._SubAppParams) -> Software._AppParams:
keyword_args: Software._AppParams = kwpaths
app = Software._Apps(**keyword_args)
setattr(self, name, app)
return app
def __getitem__(self, key: str) -> Software._AppParams | Never:
if hasattr(self, key):
app: Software._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: Software._SubAppParams = value
if hasattr(self, key[0]):
app: Software._Apps = getattr(self, key[0])
if hasattr(app, key[1]):
app_child: Software._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: Software._Apps = getattr(self, key[0])
delattr(app, key[1])
setattr(self, key[0], app)
def list(self, contents: bool = False) -> tuple[str]:
apps: tuple[str] | tuple[Software._Apps] = tuple(
filter(
lambda a: isinstance(getattr(self, a), Software._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), Software._Apps),
dir(self)
)
)
return len(apps)