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

139 lines
3.9 KiB
Python
Raw Normal View History

2022-03-22 15:13:27 +00:00
#!/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_html(self, max_rows=20, max_columns=6, output=sys.stdout, max_column_width=20, locale=None):
"""
Print an HTML version of this table.
: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. Defaults to :code:`sys.stdout`, unless
running in Jupyter. (See above.)
: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.
"""
if max_rows is None:
max_rows = len(self._rows)
if max_columns is None:
max_columns = len(self._columns)
ellipsis = config.get_option('ellipsis_chars')
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 = list(self._column_names[:max_columns])
if columns_truncated:
column_names.append(ellipsis)
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])
number_formatters.append(utils.make_number_formatter(max_places))
else:
number_formatters.append(None)
# Format data
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]
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.
"""
write('<tr>')
for j, d in enumerate(formatted_row):
# Text is left-justified, all other values are right-justified
if isinstance(self._column_types[j], Text):
write('<td style="text-align: left;">%s</td>' % d)
else:
write('<td style="text-align: right;">%s</td>' % d)
write('</tr>')
# Header
write('<table>')
write('<thead>')
write('<tr>')
for i, col in enumerate(column_names):
write('<th>%s</th>' % col)
write('</tr>')
write('</thead>')
write('<tbody>')
# 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])
# Footer
write('</tbody>')
write('</table>')