Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,45 @@ the lines being wrapped would probably be significantly longer than this.
| | Manager |
+------------+---------+


### Usage as a context manager

You can call `TabulateContextManager` in a `with` statement to incrementally
add rows to the table. Upon exit, the whole table will be printed to the
standard output:

```python
with TabulateContextManager() as t:
t("Bill", 25)
t("Mary", 26)

# <<< ---- --
# ... Bill 25
# ... Mary 26
# ... ---- --
```

`TabulateContextManager` accepts the same parameters as `tabulate`:

```python
with TabulateContextManager(headers="firstrow", tablefmt="github") as t:
t('name', 'age')
t("Bill", 25)
t("Mary", 26)
# <<< | name | age |
# ... |--------|-------|
# ... | Bill | 25 |
# ... | Mary | 26 |
```

If you don't want to print to the standard output, you can supply the
`print_fn` keyword argument which will be called on exit:

```python
with open('output.txt', 'w') as f:
with TabulateContextManager(print_fn=f.write) as t:
t("Bill", 25)
t("Mary", 26)
```

Usage of the command line utility
---------------------------------
Expand Down
53 changes: 53 additions & 0 deletions tabulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -1694,6 +1694,59 @@ def tabulate(
return _format_table(tablefmt, headers, rows, minwidths, aligns, is_multiline)


class TabulateContextManager(object):
""" Use `tabulate` as a context manager. Incrementally add rows to the
table inside the `with` body. Upon exit, the whole table will be
printed to the standard output.

Usage:

with TabulateContextManager() as t:
t("Bill", 25)
t("Mary", 26)

---- --
Bill 25
Mary 26
---- --

Accepts the same parameters as `tabulate`:

with TabulateContextManager(headers="firstrow",
tablefmt="github") as t:
t('name', 'age')
t("Bill", 25)
t("Mary", 26)

| name | age |
|--------|-------|
| Bill | 25 |
| Mary | 26 |

If you don't want to print to the standard output, you can supply the
`print_fn` keyword argument which will be called on exit:

with open('output.txt', 'w') as f:
with TabulateContextManager(print_fn=f.write) as t:
t("Bill", 25)
t("Mary", 26)
"""

def __init__(self, *args, **kwargs):
self.print = kwargs.pop("print_fn", print)
self.args = args
self.kwargs = kwargs
self.rows = []

def __enter__(self):
def t(*values):
self.rows.append(values)
return t

def __exit__(self, exc_type, exc_val, exc_tb):
self.print(tabulate(self.rows, *self.args, **self.kwargs))


def _expand_numparse(disable_numparse, column_count):
"""
Return a list of bools of length `column_count` which indicates whether
Expand Down
38 changes: 37 additions & 1 deletion test/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from __future__ import print_function
from __future__ import unicode_literals
import tabulate as tabulate_module
from tabulate import tabulate, simple_separated_format
from tabulate import tabulate, simple_separated_format, TabulateContextManager
from common import assert_equal, raises, skip


Expand Down Expand Up @@ -1710,3 +1710,39 @@ def test_preserve_whitespace():
expected = "\n".join(["h1 h2 h3", "---- ---- ----", "foo bar foo"])
result = tabulate(test_table, table_headers)
assert_equal(expected, result)


def test_context_manager():
expected = "\n".join(
["strings numbers", "spam 41.9999", "eggs 451"]
)
# Using a list because we need to access this from a nested function so
# this needs to be a mutable variable
result = [""]

def print_fn(value):
result[0] = value

with TabulateContextManager(
tablefmt="plain", headers=_test_table_headers, print_fn=print_fn
) as t:
for row in _test_table:
t(*row)

assert_equal(expected, result[0])


def test_context_manager_headerless():
expected = "\n".join(["spam 41.9999", "eggs 451"])
# Using a list because we need to access this from a nested function so
# this needs to be a mutable variable
result = [""]

def print_fn(value):
result[0] = value

with TabulateContextManager(tablefmt="plain", print_fn=print_fn) as t:
for row in _test_table:
t(*row)

assert_equal(expected, result[0])