""" Création dynamique de commandes pour enrober une interface en ligne de commande. Par exemple pour RTC d'IBM: Toutes les commandes commencent par 'scm -a n -u y' Soit donc avec le format 'command [-option option_value]' Les sous-commandes peuvent avoir des arguments avec ou sans étiquette: 'scm checkin --comment "mon commentaire" path/to/checkin/' Les sous-commandes peuvent aussi avoir des sous-commandes: 'scm create workspace --description "bla" --stream "stream" "WS_Name"' Mais cela ne va pas plus loin : 'scm sub1 sub2 options' Toutes les commandes ne supportent pas le format json en sortie Toutes les commandes ne requièrent pas le référentiel Note: Plutôt que de renvoyer un nouvel objet, on devrait faire circuler le parent et le faire évoluer progressivement """ class CommandUncallable: def __init__(self, root, callable, head={}, tail={}): self.root = root self.tail = tail for k, v in head.items(): self.root = self.root + f" -{k} {v}" self.callable = callable def __call__(self, *args, **kwargs): print(' arg: ', args) for arg in args: self.root = " ".join([self.root, arg]) print(' kwa: ', kwargs) for key, value in kwargs.items(): opt = f"-{key} {value}" self.root = " ".join([self.root, opt]) print(' tai: ', self.tail) for key, value in self.tail.items(): opt = f"-{key} {value}" self.root = " ".join([self.root, opt]) print(' obj: ', self) print(' cmd: ', self.root) def __getattr__(self, name): """Return a callable object of this same type so that you can just keep chaining together calls and just adding that missing attribute to the arguments""" return self.callable(" ".join([self.root, name]), self.callable, tail=self.tail) class Command(CommandUncallable): def __call__(self, *args, **kwargs): CommandUncallable.__call__(self, *args, **kwargs) return self class ScmCommand(CommandUncallable): def __init__(self, root): CommandUncallable.__init__( self, root, CommandUncallable, head={'a':'n','u':'y'}, tail={'r':'RTC_CLI', '-json':''} ) class CommandSelf: def __init__(self, root, head={}, tail={}): self.root = root self.command = root for k, v in head.items(): self.command = self.command + f" -{k} {v}" self.tail = tail def toto(self): pass def __call__(self, *args, **kwargs): for arg in args: self.command = " ".join([self.command, arg]) for key, value in kwargs.items(): opt = f"-{key} {value}" self.command = " ".join([self.command, opt]) for key, value in self.tail.items(): opt = f"-{key} {value}" self.command = " ".join([self.command, opt]) print(' cmd: ', self.command) def __getattr__(self, name): print(f" getattr: {name}") for method in vars(self): print(method) #if name in vars(getattr(self, method)): # return getattr(getattr(self, method), name) self.command = " ".join([self.command, name]) return self def set_default(self, opt): print(f" Setting defaults with {opt}") if __name__ == "__main__": command = Command( 'scm', Command, head={'a':'n','u':'y'}, tail={'r':'RTC_CLI'} ) print(' cmd: ', command, '\n') print(f"First command:") command.list.connections('localhost') print(f"\nSecond command:") command.create(style='inplace').workspace('WS_Name', s='S_Name') print(f"\nWith ScmCommand class:") scm = ScmCommand('scm') print(' scm: ', scm) scm.create.workspace('WS_Name', s='Stream_Name') print(f"\nWith CommandSelf class:") scm_self = CommandSelf('scm', {'a':'n','u':'y'}, {'r':'RTC_CLI'}) scm_self.create.workspace('WS_Name', s='Stream_Name')