# pibootctl.formatter

The `pibootctl.formatter` module contains some generic text formatting routines, including the `TableWrapper` class (akin to `TextWrapper` but specific to table output), `TransMap` for partially formatting templates, and the `render()` function: a crude markup renderer.

class `pibootctl.formatter.``TableWrapper`(width=70, header_rows=1, footer_rows=0, cell_separator=' ', internal_line='-', internal_separator=' ', borders='', '', '', '', corners='', '', '', '', internal_borders='', '', '', '', align=None, format=None)

  Similar to `TextWrapper`, this class provides facilities for wrapping text to a particular width, but with a focus on table-based output.

  The constructor takes numerous arguments, but typically you don’t need to specify them all (or at all). A series of dictionaries are provided with “common” configurations: `pretty_table`, `curvy_table`, `unicode_table`, and `curvy_unicode_table`. For example:

      >>> from pibootctl.formatter import *
      >>> wrapper = TableWrapper(width=80, **curvy_table)
      >>> data = [
      ... ('Name', 'Length', 'Position'),
      ... ('foo', 3, 1),
      ... ('bar', 3, 2),
      ... ('baz', 3, 3),
      ... ('quux', 4, 4)]
      >>> print(wrapper.fill(data))
      ,------+--------+----------.
      | Name | Length | Position |
      |------+--------+----------|
      | foo  | 3      | 1        |
      | bar  | 3      | 2        |
      | baz  | 3      | 3        |
      | quux | 4      | 4        |
      `------+--------+----------'

  The `TableWrapper` instance attributes (and keyword arguments to the constructor) are as follows:

  `width`

    (default 70) The maximum number of characters that the table can take up horizontally. `TableWrapper` guarantees that no output line will be longer than `width` characters.

  `header_rows`

    (default 1) The number of rows at the top of the table that will be separated from the following rows by a horizontal border (`internal_line`).

  `footer_rows`

    (default 0) The number of rows at the bottom of the table that will be separated from the preceding rows by a horizontal border (`internal_line`).

  `cell_separator`

    (default `' '`) The string used to separate columns of cells.

  `internal_line`

    (default `'-'`) The string used to draw horizontal lines inside the table for `header_rows` and `footer_rows`.

  `internal_separator`

    (default `' '`) The string used within runs of `internal_line` to separate columns.

  `borders`

    (default `('', '', '', '')`) A 4-tuple of strings which specify the characters used to create the left, top, right, and bottom borders of the table respectively.

  `corners`

    (default `('', '', '', '')`) A 4-tuple of strings which specify the characters used for the top-left, top-right, bottom-right, and bottom-left corners of the table respectively.

  `internal_borders`

    (default `('', '', '', '')`) A 4-tuple of strings which specify the characters used to interrupt runs of the `borders` characters to draw row and column separators. Like `borders` these are the left, top, right, and bottom characters respectively.

  `align`

    A callable accepting three parameters: 0-based row index, 0-based column index, and the cell data. The callable must return a character indicating the intended alignment of data within the cell. “<” for left justification, “^” for centered alignment, and “>” for right justification (as in `str.format()`). The default is to left align everything.

  `format`

    A callable accepting three parameters: 0-based row index, 0-based column index, and the cell data. The callable must return the desired string representation of the cell data. The default simply calls `str` on everything.

  `TableWrapper` also provides similar public methods to `TextWrapper`:

  `wrap`(data)

    Wraps the table data returning a list of output lines without final newlines. data must be a sequence of row tuples, each of which is assumed to be the same length.

    If the current `width` does not permit at least a single character per column (after taking account of the width of borders, internal separators, etc.) then `ValueError` will be raised.

  `fill`(data)

    Wraps the table data returning a string containing the wrapped output.

`pibootctl.formatter.``pretty_table`

  Uses simple ASCII characters to produce a typical “box-like” table appearance:

      >>> from pibootctl.formatter import *
      >>> wrapper = TableWrapper(width=80, **pretty_table)
      >>> data = [
      ... ('Name', 'Length', 'Position'),
      ... ('foo', 3, 1),
      ... ('bar', 3, 2),
      ... ('baz', 3, 3),
      ... ('quux', 4, 4)]
      >>> print(wrapper.fill(data))
      +------+--------+----------+
      | Name | Length | Position |
      |------+--------+----------|
      | foo  | 3      | 1        |
      | bar  | 3      | 2        |
      | baz  | 3      | 3        |
      | quux | 4      | 4        |
      +------+--------+----------+

`pibootctl.formatter.``curvy_table`

  Uses simple ASCII characters to produce a “round-edged” table appearance:

      >>> from pibootctl.formatter import *
      >>> wrapper = TableWrapper(width=80, **curvy_table)
      >>> data = [
      ... ('Name', 'Length', 'Position'),
      ... ('foo', 3, 1),
      ... ('bar', 3, 2),
      ... ('baz', 3, 3),
      ... ('quux', 4, 4)]
      >>> print(wrapper.fill(data))
      ,------+--------+----------.
      | Name | Length | Position |
      |------+--------+----------|
      | foo  | 3      | 1        |
      | bar  | 3      | 2        |
      | baz  | 3      | 3        |
      | quux | 4      | 4        |
      `------+--------+----------'

`pibootctl.formatter.``unicode_table`

  Uses unicode box-drawing characters to produce a typical “box-like” table appearance:

      >>> from pibootctl.formatter import *
      >>> wrapper = TableWrapper(width=80, **unicode_table)
      >>> data = [
      ... ('Name', 'Length', 'Position'),
      ... ('foo', 3, 1),
      ... ('bar', 3, 2),
      ... ('baz', 3, 3),
      ... ('quux', 4, 4)]
      >>> print(wrapper.fill(data))
      ┌──────┬────────┬──────────┐
      │ Name │ Length │ Position │
      ├──────┼────────┼──────────┤
      │ foo  │ 3      │ 1        │
      │ bar  │ 3      │ 2        │
      │ baz  │ 3      │ 3        │
      │ quux │ 4      │ 4        │
      └──────┴────────┴──────────┘

`pibootctl.formatter.``curvy_unicode_table`

  Uses unicode box-drawing characters to produce a “round-edged” table appearance:

      >>> from pibootctl.formatter import *
      >>> wrapper = TableWrapper(width=80, **curvy_unicode_table)
      >>> data = [
      ... ('Name', 'Length', 'Position'),
      ... ('foo', 3, 1),
      ... ('bar', 3, 2),
      ... ('baz', 3, 3),
      ... ('quux', 4, 4)]
      >>> print(wrapper.fill(data))
      ╭──────┬────────┬──────────╮
      │ Name │ Length │ Position │
      ├──────┼────────┼──────────┤
      │ foo  │ 3      │ 1        │
      │ bar  │ 3      │ 2        │
      │ baz  │ 3      │ 3        │
      │ quux │ 4      │ 4        │
      ╰──────┴────────┴──────────╯

class `pibootctl.formatter.``TransMap`(**kw)

  Used with `str.format_map()` to substitute only a subset of values in a given template, passing the rest through for later processing. For example:

      >>> '{foo}{bar}'.format_map(TransMap(foo=1))
      '1{bar}'
      >>> '{foo:02d}{bar:02d}{baz:02d}'.format_map(TransMap(foo=1, baz=3))
      '01{bar:02d}03'

  Note

  One exception is that the `!a` conversion is not handled correctly. This is erroneously converted to `!r`. Unfortunately there’s no solution to this; it’s a side-effect of the means by which the `!a` conversion is performed.

class `pibootctl.formatter.``FormatDict`(data, key_title='Key', value_title='Value', sort_key=None)

  Used to format data, a `dict`, in a format acceptable as input to the `render()` function. The key_title and value_title strings provide the cells for the single header row.

  This class is intended to be used within a string for `str.format()`. For example:

      >>> from pibootctl.formatter import FormatDict
      >>> d = {'foo': 100, 'bar': 200}
      >>> print('An example table:\n\n{s}'.format(s=FormatDict(d)))
      An example table:

      | Key | Value |
      | foo | 100 |
      | bar | 200 |

  The format specification in the format string can be used to request different kinds of output, for instance:

      >>> f = FormatDict({'foo': 100, 'bar': 200})
      >>> print('An example list:\n\n{f:list}'.format(f=f))
      An example list:

      * foo = 100
      * bar = 200
      >>> print('An example reference list:\n\n{f:refs}'.format(f=f))
      An example reference list:

      [foo]: 100
      [bar]: 200

  The default format specification is “table”, naturally.

  If the values are tuples that should be expanded into multiple columns, set value_title to a tuple with the corresponding column titles:

      >>> from pibootctl.formatter import FormatDict
      >>> d = {'foo': (1, 100), 'bar': (2, 200)}
      >>> print('An example table:\n\n{s}'.format(s=FormatDict(d,
      ... value_title=('col1', 'col2'))))
      An example table:

      | Key | col1 | col2 |
      | foo | 1 | 100 |
      | bar | 2 | 200 |

  Tuple values are only supported for table output.

  Note

  In Python versions before 3.7, you may need to use `collections.OrderedDict` to ensure output of the elements of data in a particular order. Alternatively, you may specify a sort_key value which will be applied to the key values of the dict to sort them prior to output.

`pibootctl.formatter.``int_ranges`(values, range_sep='-', list_sep=', ')

  Given a set of integer values, returns a compressed string representation of all values in the set. For example:

      >>> int_ranges({1, 2})
      '1, 2'
      >>> int_ranges({1, 2, 3})
      '1-3'
      >>> int_ranges({1, 2, 3, 4, 8})
      '1-4, 8'
      >>> int_ranges({1, 2, 3, 4, 8, 9})
      '1-4, 8-9'

  range_sep and list_sep can be optionally specified to customize the strings used to separate ranges and lists of ranges respectively.

`pibootctl.formatter.``render`(text, width=70, list_space=False, table_style=None)

  A crude renderer for a crude markup language intended for formatting documentation for the console.

  The markup recognized by this routine is as follows:

      * Paragraphs must be separated by at least one blank line. They will be
        wrapped to *width*.

      * Items in bulleted lists must start with an asterisk. No list nesting
        is permitted, but items may span several lines (without blank lines
        between them). Items will be wrapped to *width* and indented
        appropriately.

      * Lines beginning and ending with a pipe character are assumed to be
        table rows. Pipe characters also delimit columns within the row. The
        first row is assumed to be a header row and will be separated from
        the rest.

      An example table is shown below:

      | Command | Description |
      | cd | changes the current directory |
      | ls | lists the content of a directory |
      | cp | copies files |
      | mv | renames files |
      | rm | removes files |