import os import vultron.api class CmdNotFound(Exception): def __str__(self): return f"error: command not found: {self.args[0]}" class NoApiKey(Exception): # FIXME: __str__ message pass class FeatureMissing(Exception): # FIXME: __str__ message pass # FIXME: Move command execution into Command class, so wrapper can do pre/post # work. class Command: """A nop Vultron command. This feature is not implemented yet.""" FTR_PRFX = "vultron_" def __init__(self, prog, api_key, out): self.prog = prog self.out = out self.uses_api = True self.default = "help" self.init() if self.uses_api and api_key is None: raise NoApiKey() self.api = vultron.api.Client(api_key) def init(self): pass def find(self, name): needle = f"{self.FTR_PRFX}{name}".lower() haystack = dir(self) for legume in haystack: if legume.lower().startswith(needle): fn = getattr(self, legume) if callable(fn): return fn else: raise FeatureMissing(legume) raise CmdNotFound(name) def vultron_help(self, *args): """This help message.""" prog = os.path.basename(self.prog) cmd = type(self).__name__.lower() subs = dir(self) print(f"usage: {prog} [options] {cmd} ") print() print("About:") if self.__doc__ is None: print(Command.__doc__) else: print(self.__doc__) print() # FIXME: print global options here print("Sub-commands:") for sub in subs: name = sub.lower() if name.startswith(self.FTR_PRFX): name = name[len(self.FTR_PRFX):] fn = getattr(self, sub) if callable(fn): desc = name if fn.__doc__ is not None: desc += f" - {fn.__doc__}" print(f"\t{desc}") def find_cmd(needle): needle = needle.lower() haystack = Command.__subclasses__() for legume in haystack: if legume.__name__.lower().startswith(needle): return legume raise CmdNotFound(needle)