Commit f55d3a15 authored by Stavros Sachtouris's avatar Stavros Sachtouris
Browse files

Simplify listings

    Modify print_list/dict/items methods of kamaki.cli.utils to be simpler
    and print output in a simpler form

    key: value
    key:
        key: value
        key:
            key: value
            ...
        key:
            list-item

            list-item
        key-for-list-of-dicts:
            key: value
            key: value

            key: value
            ...
parent a57402cd
...@@ -7,6 +7,7 @@ Changes: ...@@ -7,6 +7,7 @@ Changes:
- Adjust astakos authenticate to the new url scheme of synnefo >= 0.14 [#3832, #3874] - Adjust astakos authenticate to the new url scheme of synnefo >= 0.14 [#3832, #3874]
as a side effect, some renamings in astakos.AstakosClient: as a side effect, some renamings in astakos.AstakosClient:
info --> user_info, user --> list_users info --> user_info, user --> list_users
- Simplify listings (kamaki.cli.utils: print methods)
Features: Features:
......
...@@ -289,7 +289,7 @@ class Shell(Cmd): ...@@ -289,7 +289,7 @@ class Shell(Cmd):
cmd_args = {} cmd_args = {}
for arg in instance.arguments.values(): for arg in instance.arguments.values():
cmd_args[','.join(arg.parsed_name)] = arg.help cmd_args[','.join(arg.parsed_name)] = arg.help
print_dict(cmd_args, ident=2) print_dict(cmd_args, indent=2)
stdout.write('%s %s' % (self.prompt, line)) stdout.write('%s %s' % (self.prompt, line))
return subcmd.get_subnames() return subcmd.get_subnames()
self._register_method(complete_method, 'complete_%s' % cmd.name) self._register_method(complete_method, 'complete_%s' % cmd.name)
......
...@@ -39,6 +39,10 @@ from json import dumps ...@@ -39,6 +39,10 @@ from json import dumps
from kamaki.cli.errors import raiseCLIError from kamaki.cli.errors import raiseCLIError
IDENT_TAB = 4
suggest = dict(ansicolors=dict( suggest = dict(ansicolors=dict(
active=False, active=False,
url='#install-ansicolors-progress', url='#install-ansicolors-progress',
...@@ -109,7 +113,7 @@ def print_json(data): ...@@ -109,7 +113,7 @@ def print_json(data):
:param data: json-dumpable data :param data: json-dumpable data
""" """
print(dumps(data, indent=2)) print(dumps(data, indent=IDENT_TAB))
def pretty_dict(d, *args, **kwargs): def pretty_dict(d, *args, **kwargs):
...@@ -117,132 +121,99 @@ def pretty_dict(d, *args, **kwargs): ...@@ -117,132 +121,99 @@ def pretty_dict(d, *args, **kwargs):
def print_dict( def print_dict(
d, exclude=(), ident=0, d,
exclude=(), indent=0,
with_enumeration=False, recursive_enumeration=False): with_enumeration=False, recursive_enumeration=False):
""" """Pretty-print a dictionary object
Pretty-print a dictionary object <indent>key: <non iterable item>
<indent>key:
<indent + IDENT_TAB><pretty-print iterable>
:param d: (dict) the input :param d: (dict)
:param excelude: (set or list) keys to exclude from printing :param exclude: (iterable of strings) keys to exclude from printing
:param ident: (int) initial indentation (recursive) :param indent: (int) initial indentation (recursive)
:param with_enumeration: (bool) enumerate each 1st level key if true :param with_enumeration: (bool) enumerate 1st-level keys
:recursive_enumeration: (bool) recursively enumerate dicts and lists of :param recursive_enumeration: (bool) recursively enumerate iterables (does
2nd level or deeper not enumerate 1st level keys)
:raises CLIError: (TypeError wrapper) non-dict input :raises CLIError: if preconditions fail
""" """
if not isinstance(d, dict): assert isinstance(d, dict), 'print_dict input must be a dict'
raiseCLIError(TypeError('Cannot dict_print a non-dict object')) assert indent >= 0, 'print_dict indent must be >= 0'
if d:
margin = max(len(('%s' % key).strip()) for key in d.keys() if (
key not in exclude))
counter = 1 for i, (k, v) in enumerate(d.items()):
for key, val in sorted(d.items()): k = ('%s' % k).strip()
key = '%s' % key if k in exclude:
if key in exclude:
continue continue
print_str = '' print_str = ' ' * indent
if with_enumeration: print_str += '%s.' % (i + 1) if with_enumeration else ''
print_str = '%s. ' % counter print_str += '%s:' % k
counter += 1 if isinstance(v, dict):
print_str = '%s%s' % (' ' * (ident - len(print_str)), print_str) print print_str
print_str += key.strip()
print_str += ':'
print_str += ' ' * (margin - len(key.strip()))
#print_str += ':'
if isinstance(val, dict):
print(print_str)
print_dict( print_dict(
val, v, exclude, indent + IDENT_TAB,
exclude=exclude, recursive_enumeration, recursive_enumeration)
ident=margin + ident, elif isinstance(v, list) or isinstance(v, tuple):
with_enumeration=recursive_enumeration, print print_str
recursive_enumeration=recursive_enumeration)
elif isinstance(val, list):
print(print_str)
print_list( print_list(
val, v, exclude, indent + IDENT_TAB,
exclude=exclude, recursive_enumeration, recursive_enumeration)
ident=margin + ident,
with_enumeration=recursive_enumeration,
recursive_enumeration=recursive_enumeration)
else: else:
print print_str + ' ' + ('%s' % val).strip() print '%s %s' % (print_str, v)
def print_list( def print_list(
l, exclude=(), ident=0, l,
exclude=(), indent=0,
with_enumeration=False, recursive_enumeration=False): with_enumeration=False, recursive_enumeration=False):
""" """Pretty-print a list of items
Pretty-print a list object <indent>key: <non iterable item>
<indent>key:
<indent + IDENT_TAB><pretty-print iterable>
:param l: (list) the input :param l: (list)
:param excelude: (object - anytype) values to exclude from printing :param exclude: (iterable of strings) items to exclude from printing
:param ident: (int) initial indentation (recursive) :param indent: (int) initial indentation (recursive)
:param with_enumeration: (bool) enumerate each 1st level value if true :param with_enumeration: (bool) enumerate 1st-level items
:recursive_enumeration: (bool) recursively enumerate dicts and lists of :param recursive_enumeration: (bool) recursively enumerate iterables (does
2nd level or deeper not enumerate 1st level keys)
:raises CLIError: (TypeError wrapper) non-list input :raises CLIError: if preconditions fail
""" """
if not isinstance(l, list): assert isinstance(l, list) or isinstance(l, tuple), (
raiseCLIError(TypeError('Cannot list_print a non-list object')) 'print_list prinbts a list or tuple')
assert indent >= 0, 'print_list indent must be >= 0'
if l: for i, item in enumerate(l):
try: print_str = ' ' * indent
margin = max(len(('%s' % item).strip()) for item in l if not ( print_str += '%s.' % (i + 1) if with_enumeration else ''
isinstance(item, dict) or
isinstance(item, list) or
item in exclude))
except ValueError:
margin = (2 + len(('%s' % len(l)))) if enumerate else 1
counter = 1
prefix = ''
item_sep = False
for item in sorted(l):
if ('%s' % item) in exclude:
continue
elif with_enumeration:
prefix = '%s. ' % counter
counter += 1
prefix = '%s%s' % (' ' * (ident - len(prefix)), prefix)
else:
prefix = ' ' * ident
if item_sep:
print '%s. . . . . . .' % prefix
else:
item_sep = True
if isinstance(item, dict): if isinstance(item, dict):
if with_enumeration: if with_enumeration:
print(prefix) print print_str
print_dict( print_dict(
item, item, exclude, indent,
exclude=exclude, recursive_enumeration, recursive_enumeration)
ident=margin + ident, elif isinstance(item, list) or isinstance(item, tuple):
with_enumeration=recursive_enumeration,
recursive_enumeration=recursive_enumeration)
elif isinstance(item, list):
if with_enumeration: if with_enumeration:
print(prefix) print print_str
print_list( print_list(
item, item, exclude, indent + IDENT_TAB,
exclude=exclude, recursive_enumeration, recursive_enumeration)
ident=margin + ident,
with_enumeration=recursive_enumeration,
recursive_enumeration=recursive_enumeration)
else: else:
print('%s%s' % (prefix, item)) item = ('%s' % item).strip()
if item in exclude:
continue
print '%s%s' % (print_str, item)
if (i + 1) < len(l):
print
def page_hold(index, limit, maxlen): def page_hold(index, limit, maxlen):
...@@ -274,9 +245,13 @@ def print_items( ...@@ -274,9 +245,13 @@ def print_items(
Objects of next level don't inherit enumeration (default: off) or titles Objects of next level don't inherit enumeration (default: off) or titles
:param items: (list) items are lists or dict :param items: (list) items are lists or dict
:param title: (tuple) keys to use their values as title :param title: (tuple) keys to use their values as title
:param with_enumeration: (boolean) enumerate items (order id on title) :param with_enumeration: (boolean) enumerate items (order id on title)
:param with_redundancy: (boolean) values in title also appear on body :param with_redundancy: (boolean) values in title also appear on body
:param page_size: (int) show results in pages of page_size items, enter to :param page_size: (int) show results in pages of page_size items, enter to
continue continue
""" """
...@@ -299,9 +274,9 @@ def print_items( ...@@ -299,9 +274,9 @@ def print_items(
header = ' '.join('%s' % item.pop(key) for key in title) header = ' '.join('%s' % item.pop(key) for key in title)
print(bold(header)) print(bold(header))
if isinstance(item, dict): if isinstance(item, dict):
print_dict(item, ident=1) print_dict(item, indent=IDENT_TAB)
elif isinstance(item, list): elif isinstance(item, list):
print_list(item, ident=1) print_list(item, indent=IDENT_TAB)
else: else:
print(' %s' % item) print(' %s' % item)
page_hold(i + 1, page_size, len(items)) page_hold(i + 1, page_size, len(items))
...@@ -433,17 +408,17 @@ def split_input(line): ...@@ -433,17 +408,17 @@ def split_input(line):
return terms return terms
def ask_user(msg, true_resp=['Y', 'y']): def ask_user(msg, true_resp=('y', )):
"""Print msg and read user response """Print msg and read user response
:param true_resp: (tuple of chars) :param true_resp: (tuple of chars)
:returns: (bool) True if reponse in true responses, False otherwise :returns: (bool) True if reponse in true responses, False otherwise
""" """
stdout.write('%s (%s or enter for yes):' % (msg, ', '.join(true_resp))) stdout.write('%s [%s/N]: ' % (msg, ', '.join(true_resp)))
stdout.flush() stdout.flush()
user_response = stdin.readline() user_response = stdin.readline()
return user_response[0] in true_resp + ['\n'] return user_response[0].lower() in true_resp
def spiner(size=None): def spiner(size=None):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment