Similar to prettytable, print formatted tables in python using f-string. Tables can be split into a list of strings if requested, which is useful when sending messages via 3rd party libraries that limit messages on length of a string.
Handles wide characters (including East Asian languages that have double-width spacing) using the wcwidth library for accurate display width calculations. Initial logic inspired by: this @gullevek post
With no options added at init, just adds rows and prints entire value with newline separation.
>>> from dappertable import DapperTable
>>> x = DapperTable()
>>> x.add_row('first row')
True
>>> x.add_row('second row')
True
>>> x.print()
'first row\nsecond row'
Similar to pretty table, set headers first and then add each individual row. The DapperTableHeader object will set the top header row and the max length of each column. If an column in a row later on is added with a length greater than the one in the column, it will be shortened with a ... suffix added.
Example:
>>> from dappertable import DapperTable, DapperTableHeader, DapperTableHeaderOptions
>>> t = DapperTable(header_options=DapperTableHeaderOptions([DapperTableHeader('pos', 3), DapperTableHeader('name', 10)]))
>>> t.add_row([1, 'foo'])
>>> t.add_row([2, 'example title'])
>>> t.print()
'pos|| name\n----------------\n1 || foo\n2 || example ..'
If you pass pagination_options you can setup output to return a list of strings that match the params.
For example you can use PaginationRows with the rows_per_message value into the initial table, this will split the table into a list of multiple strings. This is useful for clients sending requests via an API, so you can 'paginate' the table in a manner of speaking.
>>> from dappertable import DapperTable, DapperTableHeader, DapperTableHeaderOptions, PaginationRows
>>> t = DapperTable(header_options=DapperTableHeaderOptions([DapperTableHeader('pos', 3), DapperTableHeader('name', 10)]), pagination_options=PaginationRows(2))
>>> t.add_row([1, 'foo'])
>>> t.add_row([2, 'example'])
>>> t.add_row([3, 'bar'])
>>> t.print()
['pos|| name\n----------------', '1 || foo\n2 || example', '3 || bar']
You can also use PaginationLength to with the length_per_message value to split up the output into multiple strings where the max length of each string is this value.
>>> from dappertable import DapperTable, PaginationLength
>>> t = DapperTable(pagination_options=PaginationLength(10))
>>> t.add_row('12345')
>>> t.add_row('12345')
>>> t.add_row('12345')
>>> t.print()
['12345\n12345', '12345']
You can add a prefix and/or suffix to your table output that will be prepended to the first page and appended to the last page respectively. This is particularly useful when you want to add context or formatting around your table output.
>>> from dappertable import DapperTable, PaginationLength
>>> t = DapperTable(pagination_options=PaginationLength(50), prefix='--- Report Start ---\n', suffix='\n--- Report End ---')
>>> t.add_row('Data point 1')
>>> t.add_row('Data point 2')
>>> t.add_row('Data point 3')
>>> t.print()
['--- Report Start ---\nData point 1\nData point 2\nData point 3\n--- Report End ---']Important notes:
- Prefix appears only on the first page, suffix only on the last page
- With
PaginationLength, the prefix/suffix lengths are accounted for in pagination calculations- The first page reserves space for the prefix
- The last page reserves space for the suffix
- If a row doesn't fit with the prefix/suffix, an additional page is created for just the prefix/suffix
- With
PaginationRows, prefix/suffix are simply added to the first/last pages without affecting row count logic - Prefix and suffix must not exceed the
length_per_messagevalue (validation happens at initialization) - CJK characters in prefix/suffix are handled correctly using display width calculations
You can wrap your table content with enclosure_start and enclosure_end strings on every page. This is particularly useful for wrapping tables in markdown code blocks or other formatting that needs to be applied to each page's content, while keeping prefix/suffix outside the enclosure.
>>> from dappertable import DapperTable, PaginationLength
>>> t = DapperTable(pagination_options=PaginationLength(100),
... prefix='**Data Table:**\n',
... enclosure_start='```\n',
... enclosure_end='\n```',
... suffix='\n*Page 1 of 1*')
>>> t.add_row('Row 1')
>>> t.add_row('Row 2')
>>> t.print()
['**Data Table:**\n```\nRow 1\nRow 2\n```\n*Page 1 of 1*']Important notes:
- Enclosure wraps every page's content, not just first/last
- Order of wrapping:
prefix→enclosure_start→ content →enclosure_end→suffix - With
PaginationLength, enclosure lengths are accounted for in pagination calculations- Each page reserves space for both
enclosure_startandenclosure_end - Content is automatically split to fit within the available space after accounting for enclosures
- Each page reserves space for both
- With
PaginationRows, enclosures are simply wrapped around each page without affecting row count logic - CJK characters in enclosures are handled correctly using display width calculations
- Common use case: wrapping tables in markdown code blocks (```) for Discord/Slack bots
The headers have an zero_pad_index option to format index like column options to include leading 0s to make the output look a bit cleaner. Take the following example:
>>> from dappertable import DapperTable, DapperTableHeader, DapperTableHeaderOptions
>>> t = DapperTable(header_options=DapperTableHeaderOptions([DapperTableHeader('pos', 3, zero_pad_index=True), DapperTableHeader('name', 10)]))
>>> for count in range(15):
... t.add_row([count, 'foo'])
...
>>> t.print()
'pos|| name\n----------------\n00 || foo\n01 || foo\n02 || foo\n03 || foo\n04 || foo\n05 || foo\n06 || foo\n07 || foo\n08 || foo\n09 || foo\n10 || foo\n11 || foo\n12 || foo\n13 || foo\n14 || foo'
By default collapse_newlines is set to True, this removes double newlines (\n\n) from outputs.
You can also request a list of rows from after pagination processing and use methods to print these directly. This is if you want to get the pagination for some 'locked' input and edit the DapperRow instances themselves.
You can use get_paginated_rows to get a List of DapperRow objects which contain the formatted or unformatted strings (depending on header inputs), and then pass this data into print_rows to get the list of outputs.
If you want you can edit the DapperRow object directly with .edit() to directly modify input if you want to skip some formatting options.