diff --git a/moulinette/__init__.py b/moulinette/__init__.py index 8686c2c2..69fa24b0 100755 --- a/moulinette/__init__.py +++ b/moulinette/__init__.py @@ -94,7 +94,7 @@ def api(namespaces, host='localhost', port=80, routes={}, 'use_cache': use_cache }) moulinette.run(host, port) -def cli(namespaces, args, print_json=False, use_cache=True): +def cli(namespaces, args, print_json=False, print_plain=False, use_cache=True): """Command line interface Execute an action with the moulinette from the CLI and print its @@ -104,6 +104,7 @@ def cli(namespaces, args, print_json=False, use_cache=True): - namespaces -- The list of namespaces to use - args -- A list of argument strings - print_json -- True to print result as a JSON encoded string + - print_plain -- True to print result as a script-usable string - use_cache -- False if it should parse the actions map file instead of using the cached one @@ -114,7 +115,7 @@ def cli(namespaces, args, print_json=False, use_cache=True): moulinette = init_interface('cli', actionsmap={'namespaces': namespaces, 'use_cache': use_cache}) - moulinette.run(args, print_json) + moulinette.run(args, print_json, print_plain) except MoulinetteError as e: print('%s %s' % (colorize(m18n.g('error'), 'red'), e.strerror)) return e.errno diff --git a/moulinette/interfaces/cli.py b/moulinette/interfaces/cli.py index 46fe1abc..3411323b 100644 --- a/moulinette/interfaces/cli.py +++ b/moulinette/interfaces/cli.py @@ -42,8 +42,47 @@ def colorize(astr, color): else: return astr +def plain_print_dict(d, depth=0): + """Print in a plain way a dictionary recursively + + Print a dictionary recursively for scripting usage to the standard output. + + Output formatting: + >>> d = {'key': 'value', 'list': [1,2], 'dict': {'key2': 'value2'}} + >>> plain_print_dict(d) + #key + value + #list + 1 + 2 + #dict + ##key2 + value2 + + Keyword arguments: + - d -- The dictionary to print + - depth -- The recursive depth of the dictionary + + """ + # skip first key printing + if depth == 0 and (isinstance(d, dict) and len(d) == 1): + _, d = d.popitem() + if isinstance(d, (tuple, set)): + d = list(d) + if isinstance(d, list): + for v in d: + plain_print_dict(v, depth+1) + elif isinstance(d, dict): + for k,v in d.items(): + print("{}{}".format("#" * (depth+1), k)) + plain_print_dict(v, depth+1) + else: + if isinstance(d, unicode): + d = d.encode('utf-8') + print(d) + def pretty_print_dict(d, depth=0): - """Print a dictionary recursively + """Print in a pretty way a dictionary recursively Print a dictionary recursively with colors to the standard output. @@ -187,7 +226,7 @@ class Interface(BaseInterface): self.actionsmap = actionsmap - def run(self, args, print_json=False): + def run(self, args, print_json=False, print_plain=False): """Run the moulinette Process the action corresponding to the given arguments 'args' @@ -196,8 +235,12 @@ class Interface(BaseInterface): Keyword arguments: - args -- A list of argument strings - print_json -- True to print result as a JSON encoded string + - print_plain -- True to print result as a script-usable string """ + if print_json and print_plain: + raise MoulinetteError(errno.EINVAL, m18n.g('invalid_usage')) + try: ret = self.actionsmap.process(args, timeout=5) except KeyboardInterrupt, EOFError: @@ -211,6 +254,8 @@ class Interface(BaseInterface): import json from moulinette.utils.serialize import JSONExtendedEncoder print(json.dumps(ret, cls=JSONExtendedEncoder)) + elif print_plain: + plain_print_dict(ret) elif isinstance(ret, dict): pretty_print_dict(ret) else: