This repository has been archived by the owner on Dec 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Define generic for pretty-printing objects inside a table. (#12)
* Define generic for pretty-printing objects inside a table. Also define a function for formatting a table, so that we don't have to rely on third-party libraries for our pretty-printing.
- Loading branch information
Showing
3 changed files
with
136 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
from functools import singledispatch | ||
from typing import Any, List, Optional, Sequence | ||
|
||
__author__ = "Aaron Lun" | ||
__copyright__ = "LTLA" | ||
__license__ = "MIT" | ||
|
||
|
||
@singledispatch | ||
def show_as_cell(x: Any, indices: Sequence[int]) -> List[str]: | ||
"""Show the contents of ``x`` as a cell of a table, typically for use in the ``__str__`` method of a class that | ||
contains ``x``. | ||
Args: | ||
x: | ||
Any object. By default, we assume that it can be treated as | ||
a sequence, with a valid ``__getitem__`` method for an index. | ||
indices: | ||
List of indices to be extracted. | ||
Returns: | ||
List of strings of length equal to ``indices``, containing a | ||
string summary of each of the specified elements of ``x``. | ||
""" | ||
output = [] | ||
for i in indices: | ||
output.append(str(x[i])) | ||
return output | ||
|
||
|
||
def _get_max_width(col: List[str]): | ||
width = 0 | ||
for y in col: | ||
if len(y) > width: | ||
width = len(y) | ||
return width | ||
|
||
|
||
def format_table( | ||
columns: List[Sequence[str]], | ||
floating_names: Optional[Sequence[str]] = None, | ||
sep: str = " ", | ||
window: Optional[int] = None, | ||
) -> str: | ||
"""Pretty-print a table with wrapping columns. | ||
Args: | ||
columns: List of list of strings, where each inner list is the same length. | ||
Strings are typically generated by :py:meth:`~show_as_cell`. | ||
floating_names: List of strings to be added to the left of the table. This is | ||
printed repeatedly for each set of wrapped columns. | ||
sep: Separator between columns. | ||
window: Size of the terminal window, in characters. We attempt to determine | ||
this automatically, otherwise it is set to 150. | ||
Returns: | ||
str: String containing the pretty-printed table. | ||
""" | ||
if window is None: | ||
import os | ||
|
||
try: | ||
window = os.get_terminal_size().columns | ||
except Exception as _: | ||
window = 150 | ||
|
||
if len(columns) == 0: | ||
raise ValueError("At least one column should be supplied in 'columns'.") | ||
n = len(columns[0]) | ||
|
||
floatwidth = 0 | ||
if floating_names is not None: | ||
floatwidth = _get_max_width(floating_names) | ||
new_floating_names = [] | ||
for y in floating_names: | ||
new_floating_names.append(y.rjust(floatwidth)) | ||
floating_names = new_floating_names | ||
|
||
output = "" | ||
|
||
def reinitialize(): | ||
if floating_names is None: | ||
return [""] * n | ||
else: | ||
return floating_names[:] | ||
|
||
contents = reinitialize() | ||
init = True | ||
used = floatwidth | ||
|
||
for col in columns: | ||
width = _get_max_width(col) | ||
|
||
if not init and used + width + len(sep) > window: | ||
for line in contents: | ||
output += line + "\n" | ||
contents = reinitialize() | ||
init = True | ||
used = floatwidth | ||
|
||
for i, y in enumerate(col): | ||
if used > 0: | ||
contents[i] += sep | ||
contents[i] += y.rjust(width) | ||
used += width + len(sep) | ||
init = False | ||
|
||
output += "\n".join(contents) | ||
return output |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from biocgenerics import show_as_cell, format_table | ||
|
||
|
||
def test_show_as_cell(): | ||
assert show_as_cell([1, 2, 3, 4], range(4)) == ["1", "2", "3", "4"] | ||
assert show_as_cell([1, 2, 3, 4], [1, 3]) == ["2", "4"] | ||
|
||
|
||
def test_format_table(): | ||
contents = [ | ||
["asdasd", "1", "2", "3", "4"], | ||
[""] + ["|"] * 4, | ||
["asyudgausydga", "A", "B", "C", "D"], | ||
] | ||
print(format_table(contents)) | ||
print(format_table(contents, floating_names=["", "aarg", "boo", "ffoo", "stuff"])) | ||
print(format_table(contents, window=10)) | ||
print( | ||
format_table( | ||
contents, window=10, floating_names=["", "AAAR", "BBBB", "XXX", "STUFF"] | ||
) | ||
) |