Add autogenerated help.

This commit is contained in:
Martin Sekera 2019-09-28 03:36:12 +02:00
parent 091db860c2
commit af0881b823
3 changed files with 58 additions and 31 deletions

View file

@ -2,4 +2,5 @@
# encoding: utf-8 # encoding: utf-8
from . import argv from . import argv
from . import aux
from . import cfg from . import cfg

View file

@ -3,12 +3,14 @@
import sys import sys
from . import aux
class Action: class Action:
""" """
A callable with signature: A callable with signature:
p_args is a list of (name, type) tuples p_args is a list of (name, type, desc) tuples
kv_args is a dict with {name: (type, default value), ...} kv_args is a dict with {name: (type, default value, desc), ...}
""" """
p_args = [] p_args = []
@ -94,10 +96,10 @@ class Invocation:
return return
# pre-populate args # pre-populate args
for name, T in self.action.p_args: for name, *_ in self.action.p_args:
self.args[name] = None self.args[name] = None
for name, (T, default) in self.action.kv_args.items(): for name, (T, default, _) in self.action.kv_args.items():
self.args[name] = T(default) self.args[name] = T(default)
# process positional (mandatory) args # process positional (mandatory) args
@ -107,7 +109,7 @@ class Invocation:
if not len(raw_p_args) == count_p_args: if not len(raw_p_args) == count_p_args:
raise IncompleteInvocation raise IncompleteInvocation
for raw, (name, T) in zip(raw_p_args, self.action.p_args): for raw, (name, T, _) in zip(raw_p_args, self.action.p_args):
try: try:
self.args[name] = T(raw) self.args[name] = T(raw)
except: except:
@ -132,34 +134,43 @@ class Invocation:
def execute(self): def execute(self):
self.action(self.cmd, **self.args) self.action(self.cmd, **self.args)
# ~ $ nicectl customer create NAME [--note=xxx] def help(self, stream=sys.stdout):
"""
Prints auto-generated usage information.
"""
# ~ $ nicectl user create CUSTOMER LOGIN print("Usage:")
# ~ generated password is printed
# ~ $ nicectl unit list for cmd, act in aux.flatten_dict(self.routing):
synopsis = ["$", sys.argv[0], cmd]
args = []
# ~ $ nicectl unit create CUSTOMER NAME MODEL [--serial=XXX] [--note=xxx] for name, T, desc in act.p_args:
synopsis.append(name)
args.append("* %s (%s) = %s" %(name, T.__name__, desc))
# ~ routing = { if act.kv_args:
# ~ "customer": { synopsis.append("[")
# ~ "create": customer_create,
# ~ "list": customer_list for name, (T, default, desc) in act.kv_args.items():
# ~ }, synopsis.append("%s=%s" %(name, default or ""))
# ~ "user": { args.append("+ %s (%s) = %s" %(name, T.__name__, desc))
# ~ "create": user_create,
# ~ "list": user_list synopsis.append("]")
# ~ },
# ~ "unit": { print(" " + " ".join(synopsis))
# ~ "create": unit_create, for arg in args:
# ~ "list": unit_list print(" " + arg)
# ~ }
# ~ } print()
print(" " + act.__doc__.strip())
print()
if __name__ == "__main__": if __name__ == "__main__":
class TestActionHello(Action): class TestActionHello(Action):
p_args = [("NAME", str), ("AGE", int)] p_args = [("NAME", str, "description"), ("AGE", int, "another short piece of wisdom")]
kv_args = {"speed": (float, 75)} kv_args = {"speed": (float, 75, "more stuff")}
def __call__(self, cmd, NAME, AGE, speed): def __call__(self, cmd, NAME, AGE, speed):
print("Hello %s, age %d." %(NAME, AGE)) print("Hello %s, age %d." %(NAME, AGE))

15
dtk/aux.py Normal file
View file

@ -0,0 +1,15 @@
#! /usr/bin/env python3
# encoding: utf-8
def flatten_dict(root, glue=" ", prefix=[]):
lines = []
for k, v in root.items():
new_prefix = prefix + [k]
if type(v) == dict:
lines.extend(flatten_dict(v, glue, new_prefix))
else:
lines.append((glue.join(new_prefix), v))
return lines