armi.utils.tabulate module

Pretty-print tabular data.

This file started out as the MIT-licensed “tabulate”. Though we have made, and will continue to make, many arbitrary changes as we need. Thanks to the tabulate team.

https://github.com/astanin/python-tabulate

Usage

The module provides just one function, tabulate, which takes a list of lists or other tabular data type as the first argument, and outputs anicely-formatted plain-text table:

>>> from armi.utils.tabulate import tabulate

>>> table = [["Sun",696000,1989100000],["Earth",6371,5973.6],
...          ["Moon",1737,73.5],["Mars",3390,641.85]]

>>> print(tabulate(table))
-----  ------  -------------
Sun    696000     1.9891e+09
Earth    6371  5973.6
Moon     1737    73.5
Mars     3390   641.85
-----  ------  -------------

The following tabular data types are supported:

  • list of lists or another iterable of iterables

  • list or another iterable of dicts (keys as columns)

  • dict of iterables (keys as columns)

  • list of dataclasses (field names as columns)

  • two-dimensional NumPy array

  • NumPy record arrays (names as columns)

Table headers

To print nice column headers, supply the second argument (headers):

  • headers can be an explicit list of column headers

  • if headers=”firstrow”, then the first row of data is used

  • if headers=”keys”, then dictionary keys or column indices are used

Otherwise a headerless table is produced.

If the number of headers is less than the number of columns, they are supposed to be names of the last columns. This is consistent with the plain-text format of R:

>>> print(tabulate([["sex","age"],["Alice","F",24],["Bob","M",19]],
...       headers="firstrow"))
       sex      age
-----  -----  -----
Alice  F         24
Bob    M         19

Column and Headers alignment

tabulate tries to detect column types automatically, and aligns the values properly. By default it aligns decimal points of the numbers (or flushes integer numbers to the right), and flushes everything else to the left. Possible column alignments (numAlign, strAlign) are: “right”, “center”, “left”, “decimal” (only for numAlign), and None (to disable alignment).

colGlobalAlign allows for global alignment of columns, before any specific override from

colAlign. Possible values are: None (defaults according to coltype), “right”, “center”, “decimal”, “left”.

colAlign allows for column-wise override starting from left-most column. Possible values are:

“global” (no override), “right”, “center”, “decimal”, “left”.

headersGlobalAlign allows for global headers alignment, before any specific override from

headersAlign. Possible values are: None (follow columns alignment), “right”, “center”, “left”.

headersAlign allows for header-wise override starting from left-most given header. Possible

values are: “global” (no override), “same” (follow column alignment), “right”, “center”, “left”.

Note on intended behaviour: If there is no data, any column alignment argument is ignored. Hence, in this case, header alignment cannot be inferred from column alignment.

Table formats

intFmt is a format specification used for columns which contain numeric data without a decimal point. This can also be a list or tuple of format strings, one per column.

floatFmt is a format specification used for columns which contain numeric data with a decimal point. This can also be a list or tuple of format strings, one per column.

None values are replaced with a missingVal string (like floatFmt, this can also be a list of values for different columns):

>>> print(tabulate([["spam", 1, None],
...                 ["eggs", 42, 3.14],
...                 ["other", None, 2.7]], missingVal="?"))
-----  --  ----
spam    1  ?
eggs   42  3.14
other   ?  2.7
-----  --  ----

Various plain-text table formats (tableFmt) are supported: ‘plain’, ‘simple’, ‘grid’, ‘rst’, and tsv. Variable tabulateFormats contains the list of currently supported formats.

“plain” format doesn’t use any pseudographics to draw tables, it separates columns with a double space:

>>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]],
...                 ["strings", "numbers"], "plain"))
strings      numbers
spam         41.9999
eggs        451

>>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]], tableFmt="plain"))
spam   41.9999
eggs  451

“simple” format is like Pandoc simple_tables:

>>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]],
...                 ["strings", "numbers"], "simple"))
strings      numbers
---------  ---------
spam         41.9999
eggs        451

>>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]], tableFmt="simple"))
----  --------
spam   41.9999
eggs  451
----  --------

“grid” is similar to tables produced by Emacs table.el package or Pandoc grid_tables:

>>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]],
...                ["strings", "numbers"], "grid"))
+-----------+-----------+
| strings   |   numbers |
+===========+===========+
| spam      |   41.9999 |
+-----------+-----------+
| eggs      |  451      |
+-----------+-----------+

>>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]], tableFmt="grid"))
+------+----------+
| spam |  41.9999 |
+------+----------+
| eggs | 451      |
+------+----------+

“rst” is like a simple table format from reStructuredText; please note that reStructuredText accepts also “grid” tables:

>>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]],
...                ["strings", "numbers"], "rst"))
=========  =========
strings      numbers
=========  =========
spam         41.9999
eggs        451
=========  =========

>>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]], tableFmt="rst"))
====  ========
spam   41.9999
eggs  451
====  ========

Number parsing

By default, anything which can be parsed as a number is a number. This ensures numbers represented as strings are aligned properly. This can lead to weird results for particular strings such as specific git SHAs e.g. “42992e1” will be parsed into the number 429920 and aligned as such.

To completely disable number parsing (and alignment), use disableNumParse=True. For more fine grained control, a list column indices is used to disable number parsing only on those columns e.g. disableNumParse=[0, 2] would disable number parsing only on the first and third columns.

Column Widths and Auto Line Wrapping

Tabulate will, by default, set the width of each column to the length of the longest element in that column. However, in situations where fields are expected to reasonably be too long to look good as a single line, tabulate can help automate word wrapping long fields for you. Use the parameter maxcolwidth to provide a list of maximal column widths:

>>> print(tabulate( \
      [('1', 'John Smith', \
        'This is a rather long description that might look better if it is wrapped a bit')], \
      headers=("Issue Id", "Author", "Description"), \
      maxColWidths=[None, None, 30], \
      tableFmt="grid"  \
    ))
+------------+------------+-------------------------------+
|   Issue Id | Author     | Description                   |
+============+============+===============================+
|          1 | John Smith | This is a rather long         |
|            |            | description that might look   |
|            |            | better if it is wrapped a bit |
+------------+------------+-------------------------------+

Header column width can be specified in a similar way using maxheadercolwidth.

class armi.utils.tabulate.Line(begin, hline, sep, end)

Bases: tuple

Create new instance of Line(begin, hline, sep, end)

begin

Alias for field number 0

end

Alias for field number 3

hline

Alias for field number 1

sep

Alias for field number 2

class armi.utils.tabulate.DataRow(begin, sep, end)

Bases: tuple

Create new instance of DataRow(begin, sep, end)

begin

Alias for field number 0

end

Alias for field number 2

sep

Alias for field number 1

class armi.utils.tabulate.TableFormat(lineabove, linebelowheader, linebetweenrows, linebelow, headerrow, datarow, padding, withHeaderHide)

Bases: tuple

Create new instance of TableFormat(lineabove, linebelowheader, linebetweenrows, linebelow, headerrow, datarow, padding, withHeaderHide)

datarow

Alias for field number 5

headerrow

Alias for field number 4

lineabove

Alias for field number 0

linebelow

Alias for field number 3

linebelowheader

Alias for field number 1

linebetweenrows

Alias for field number 2

padding

Alias for field number 6

withHeaderHide

Alias for field number 7

armi.utils.tabulate.tabulate(data, headers=(), tableFmt='simple', floatFmt='g', intFmt='', numAlign='default', strAlign='default', missingVal='', showIndex='default', disableNumParse=False, colGlobalAlign=None, colAlign=None, maxColWidths=None, headersGlobalAlign=None, headersAlign=None, rowAlign=None, maxHeaderColWidths=None)[source]

Format a fixed width table for pretty printing.

Parameters:
  • data (object) – The tabular data you want to print. This can be a list-of-lists/iterables, dict-of-lists/ iterables, 2D numpy arrays, or list of dataclasses.

  • headers=() – Nice column names. If this is “firstrow”, the first row of the data will be used. If it is “keys”m, then dictionary keys or column indices are used.

  • optional – Nice column names. If this is “firstrow”, the first row of the data will be used. If it is “keys”m, then dictionary keys or column indices are used.

  • tableFmt (str, optional) – There are custom table formats defined in this file, and you can choose between them with this string: “armi”, “simple”, “plain”, “grid”, “github”, “pretty”, “psql”, “rst”, “tsv”.

  • floatFmt (str, optional) – A format specification used for columns which contain numeric data with a decimal point. This can also be a list or tuple of format strings, one per column.

  • intFmt (str, optional) – A format specification used for columns which contain numeric data without a decimal point. This can also be a list or tuple of format strings, one per column.

  • numAlign (str, optional) – Specially align numbers, options: “right”, “center”, “left”, “decimal”.

  • strAlign (str, optional) – Specially align strings, options: “right”, “center”, “left”.

  • missingVal (str, optional) – None values are replaced with a missingVal string.

  • showIndex (str, optional) – Show these rows of data. If “always”, show row indices for all types of data. If “never”, don’t show row indices for all types of data. If showIndex is an iterable, show its values..

  • disableNumParse (bool, optional) – To disable number parsing (and alignment), use disableNumParse=True. For more fine grained control, [0, 2] would disable number parsing on the first and third columns.

  • colGlobalAlign (str, optional) – Allows for global alignment of columns, before any specific override from colAlign. Possible values are: None, “right”, “center”, “decimal”, “left”.

  • colAlign (str, optional) – Allows for column-wise override starting from left-most column. Possible values are: “global” (no override), “right”, “center”, “decimal”, “left”.

  • maxColWidths (list, optional) – A list of the maximum column widths.

  • headersGlobalAlign (str, optional) – Allows for global headers alignment, before any specific override from headersAlign. Possible values are: None (follow columns alignment), “right”, “center”, “left”.

  • headersAlign (str, optional) – Allows for header-wise override starting from left-most given header. Possible values are: “global” (no override), “same” (follow column alignment), “right”, “center”, “left”.

  • rowAlign (str, optional) – How do you want to align rows: “right”, “center”, “decimal”, “left”.

  • maxHeaderColWidths (list, optional) – List of column widths for the header.

Returns:

A text representation of the tabular data.

Return type:

str