dbt-selly/dbt-env/lib/python3.8/site-packages/agate/table/print_table.py

161 lines
5.0 KiB
Python

#!/usr/bin/env python
# pylint: disable=W0212
import sys
from babel.numbers import format_decimal
import six
from agate import config
from agate.data_types import Number, Text
from agate import utils
def print_table(self, max_rows=20, max_columns=6, output=sys.stdout, max_column_width=20, locale=None, max_precision=3):
"""
Print a text-based view of the data in this table.
The output of this method is Github Friendly Markdown (GFM) compatible.
:param max_rows:
The maximum number of rows to display before truncating the data. This
defaults to :code:`20` to prevent accidental printing of the entire
table. Pass :code:`None` to disable the limit.
:param max_columns:
The maximum number of columns to display before truncating the data.
This defaults to :code:`6` to prevent wrapping in most cases. Pass
:code:`None` to disable the limit.
:param output:
A file-like object to print to.
:param max_column_width:
Truncate all columns to at most this width. The remainder will be
replaced with ellipsis.
:param locale:
Provide a locale you would like to be used to format the output.
By default it will use the system's setting.
:max_precision:
Puts a limit on the maximum precision displayed for number types.
Numbers with lesser precision won't be affected.
This defaults to :code:`3`. Pass :code:`None` to disable limit.
"""
if max_rows is None:
max_rows = len(self._rows)
if max_columns is None:
max_columns = len(self._columns)
if max_precision is None:
max_precision = float('inf')
ellipsis = config.get_option('ellipsis_chars')
h_line = config.get_option('horizontal_line_char')
v_line = config.get_option('vertical_line_char')
locale = locale or config.get_option('default_locale')
rows_truncated = max_rows < len(self._rows)
columns_truncated = max_columns < len(self._column_names)
column_names = []
for column_name in self.column_names[:max_columns]:
if max_column_width is not None and len(column_name) > max_column_width:
column_names.append('%s...' % column_name[:max_column_width - 3])
else:
column_names.append(column_name)
if columns_truncated:
column_names.append(ellipsis)
widths = [len(n) for n in column_names]
number_formatters = []
formatted_data = []
# Determine correct number of decimal places for each Number column
for i, c in enumerate(self._columns):
if i >= max_columns:
break
if isinstance(c.data_type, Number):
max_places = utils.max_precision(c[:max_rows])
add_ellipsis = False
if max_places > max_precision:
add_ellipsis = True
max_places = max_precision
number_formatters.append(utils.make_number_formatter(max_places, add_ellipsis))
else:
number_formatters.append(None)
# Format data and display column widths
for i, row in enumerate(self._rows):
if i >= max_rows:
break
formatted_row = []
for j, v in enumerate(row):
if j >= max_columns:
v = ellipsis
elif v is None:
v = ''
elif number_formatters[j] is not None:
v = format_decimal(
v,
format=number_formatters[j],
locale=locale
)
else:
v = six.text_type(v)
if max_column_width is not None and len(v) > max_column_width:
v = '%s...' % v[:max_column_width - 3]
if len(v) > widths[j]:
widths[j] = len(v)
formatted_row.append(v)
if j >= max_columns:
break
formatted_data.append(formatted_row)
def write(line):
output.write(line + '\n')
def write_row(formatted_row):
"""
Helper function that formats individual rows.
"""
row_output = []
for j, d in enumerate(formatted_row):
# Text is left-justified, all other values are right-justified
if isinstance(self._column_types[j], Text):
output = ' %s ' % d.ljust(widths[j])
else:
output = ' %s ' % d.rjust(widths[j])
row_output.append(output)
text = v_line.join(row_output)
write('%s%s%s' % (v_line, text, v_line))
# Dashes span each width with '+' character at intersection of
# horizontal and vertical dividers.
divider = '%(v_line)s %(columns)s %(v_line)s' % {
'h_line': h_line,
'v_line': v_line,
'columns': ' | '.join(h_line * w for w in widths)
}
# Headers
write_row(column_names)
write(divider)
# Rows
for formatted_row in formatted_data:
write_row(formatted_row)
# Row indicating data was truncated
if rows_truncated:
write_row([ellipsis for n in column_names])