diff --git a/awxkit/awxkit/cli/docs/source/output.rst b/awxkit/awxkit/cli/docs/source/output.rst index 0c4eabde3c..6cba583bdc 100644 --- a/awxkit/awxkit/cli/docs/source/output.rst +++ b/awxkit/awxkit/cli/docs/source/output.rst @@ -20,16 +20,14 @@ To print results in YAML, specify ``-f yaml``: Human-Readable (Tabular) Formatting ----------------------------------- -|prog| provides *optional* support for printing results in a human-readable -tabular format, but it requires an additional Python software dependency, -``tabulate``. - -To use ``-f human``, you must install the optional dependency via ``pip install tabulate``. +|prog| also provides support for printing results in a human-readable +ASCII table format: .. code:: bash awx jobs list -f human awx jobs list -f human --filter name,created,status + awx jobs list -f human --filter * Custom Formatting with jq diff --git a/awxkit/awxkit/cli/format.py b/awxkit/awxkit/cli/format.py index 8ddc7d8fff..29dd54064d 100644 --- a/awxkit/awxkit/cli/format.py +++ b/awxkit/awxkit/cli/format.py @@ -1,3 +1,4 @@ +import locale import json from distutils.util import strtobool @@ -136,32 +137,49 @@ def format_yaml(output, fmt): def format_human(output, fmt): + lines = [] if fmt == '.': fmt = 'id,name' column_names = fmt.split(',') - try: - from tabulate import tabulate - except ImportError: - raise ImportError( - 'To use `-f human`, you must install the optional tabulate ' - 'dependency.\n`pip install tabulate`', - ) if 'count' in output: output = output['results'] else: output = [output] - return tabulate( - [ - dict( - (col, record.get(col, '')) - for col in column_names - ) - for record in output - ], - headers='keys', - tablefmt='rst' - ) + if fmt == '*' and len(output): + column_names = list(output[0].keys()) + for k in ('summary_fields', 'related'): + if k in column_names: + column_names.remove(k) + + table = [column_names] + table.extend([ + [record.get(col, '') for col in column_names] + for record in output + ]) + col_paddings = [] + + def format_num(v): + try: + return locale.format("%.*f", (0, int(v)), True) + except (ValueError, TypeError): + return v + + # calculate the max width of each column + for i, _ in enumerate(column_names): + max_width = max([len(format_num(row[i])) for row in table]) + col_paddings.append(max_width) + + # insert a row of === header lines + table.insert(1, ['=' * i for i in col_paddings]) + + # print each row of the table data, justified based on col_paddings + for row in table: + line = '' + for i, value in enumerate(row): + line += format_num(value).ljust(col_paddings[i] + 1) + lines.append(line) + return '\n'.join(lines) FORMATTERS = { diff --git a/awxkit/setup.py b/awxkit/setup.py index 3e76944fa0..0c0d12a2ee 100644 --- a/awxkit/setup.py +++ b/awxkit/setup.py @@ -69,7 +69,7 @@ setup( install_requires=requirements, python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*", extras_require={ - 'formatting': ['jq', 'tabulate'], + 'formatting': ['jq'], 'websockets': ['websocket-client>0.54.0'], }, entry_points={