1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
17 Tabular formatting utilities.
21 from datetime import datetime
23 from prettytable import PrettyTable
25 from .env import logger
28 def print_data(columns, items, header_text,
29 column_formatters=None, col_max_width=None, defaults=None):
31 Prints data in a tabular form.
33 :param columns: columns of the table, e.g. ``['id','name']``
34 :type columns: iterable of basestring
35 :param items: each element must have keys or attributes corresponding to the ``columns`` items,
36 e.g. ``[{'id':'123', 'name':'Pete'}]``
37 :type data: [{:obj:`basestring`: :obj:`basestring`}]
38 :param column_formatters: maps column name to formatter, a function that may manipulate the
39 string values printed for this column, e.g. ``{'created_at': timestamp_formatter}``
40 :type column_formatters: {:obj:`basestring`: :obj:`function`}
41 :param col_max_width: maximum width of table
42 :type col_max_width: int
43 :param defaults: default values for keys that don't exist in the data itself, e.g.
44 ``{'serviceId':'123'}``
45 :type defaults: {:obj:`basestring`: :obj:`basestring`}
49 elif not isinstance(items, list):
52 pretty_table = _generate(columns, data=items, column_formatters=column_formatters,
55 pretty_table.max_width = col_max_width
56 _log(header_text, pretty_table)
59 def _log(title, table):
60 logger.info('{0}{1}{0}{2}{0}'.format(os.linesep, title, table))
63 def _generate(cols, data, column_formatters=None, defaults=None):
65 Return a new PrettyTable instance representing the list.
67 :param cols: columns of the table, e.g. ``['id','name']``
68 :type cols: iterable of :obj:`basestring`
69 :param data: each element must have keys or attributes corresponding to the ``cols`` items,
70 e.g. ``[{'id':'123', 'name':'Pete'}]``
71 :type data: [{:obj:`basestring`: :obj:`basestring`}]
72 :param column_formatters: maps column name to formatter, a function that may manipulate the
73 string values printed for this column, e.g. ``{'created_at': timestamp_formatter}``
74 :type column_formatters: {:obj:`basestring`: :obj:`function`}
75 :param defaults: default values for keys that don't exist in the data itself, e.g.
76 ``{'serviceId':'123'}``
77 :type defaults: {:obj:`basestring`: :obj:`basestring`}
79 def get_values_per_column(column, row_data):
80 if hasattr(row_data, column) or (isinstance(row_data, dict) and column in row_data):
81 val = row_data[column] if isinstance(row_data, dict) else getattr(row_data, column)
83 if val and isinstance(val, list):
84 val = [str(element) for element in val]
86 elif val is None or isinstance(val, list):
87 # don't print `[]` or `None` (but do print `0`, `False`, etc.)
90 if column in column_formatters:
91 # calling the user's column formatter to manipulate the value
92 val = column_formatters[column](val)
96 return defaults.get(column)
98 column_formatters = column_formatters or dict()
99 defaults = defaults or dict()
100 pretty_table = PrettyTable(list(cols))
105 values_row.append(get_values_per_column(col, datum))
106 pretty_table.add_row(values_row)
111 def timestamp_formatter(value):
113 datetime.strptime(value[:10], '%Y-%m-%d')
114 return value.replace('T', ' ').replace('Z', ' ')
120 def trim_formatter_generator(max_length):
121 def trim_formatter(value):
122 if len(value) >= max_length:
123 value = '{0}..'.format(value[:max_length - 2])
125 return trim_formatter