-
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.
Added a truncated dictionary printer for __repr__'ing metadata.
Also ensure that internal lists/dictionaries are also truncated.
- Loading branch information
Showing
5 changed files
with
157 additions
and
62 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,133 @@ | ||
from typing import Optional, List, Callable, Dict | ||
|
||
|
||
def print_truncated(x, truncated_to: int = 3, full_threshold: int = 10) -> str: | ||
""" | ||
Pretty-print an object, replacing the middle elements of lists/dictionaries | ||
with an ellipsis if there are too many. This provides a useful preview of | ||
an object without spewing out all of its contents on the screen. | ||
Args: | ||
x: Object to be printed. | ||
truncated_to: | ||
Number of elements to truncate to, at the start and end of the list | ||
or dictionary. This should be less than half of ``full_threshold``. | ||
full_threshold: | ||
Threshold on the number of elements, below which the list or | ||
dictionary is shown in its entirety. | ||
Returns: | ||
String containing the pretty-printed contents. | ||
""" | ||
if isinstance(x, dict): | ||
return print_truncated_dict(x, truncated_to=truncated_to, full_threshold=full_threshold) | ||
elif isinstance(x, list): | ||
return print_truncated_list(x, truncated_to=truncated_to, full_threshold=full_threshold) | ||
else: | ||
return repr(x) | ||
|
||
|
||
def print_truncated_list(x: List, truncated_to: int = 3, full_threshold: int = 10, transform: Optional[Callable] = None, sep: str = ", ", include_brackets: bool = True) -> str: | ||
""" | ||
Pretty-print a list, replacing the middle elements with an ellipsis if | ||
there are too many. This provides a useful preview of an object without | ||
spewing out all of its contents on the screen. | ||
Args: | ||
x: List to be printed. | ||
truncated_to: | ||
Number of elements to truncate to, at the start and end of the | ||
list. This should be less than half of ``full_threshold``. | ||
full_threshold: | ||
Threshold on the number of elements, below which the list is | ||
shown in its entirety. | ||
transform: | ||
Optional transformation to apply to the elements of ``x`` | ||
after truncation but before printing. Defaults to | ||
:py:meth:`~print_truncated` if not supplied. | ||
sep: | ||
Separator between elements in the printed list. | ||
include_brackets: | ||
Whether to include the start/end brackets. | ||
Returns: | ||
String containing the pretty-printed truncated list. | ||
""" | ||
collected = [] | ||
if transform is None: | ||
transform = lambda y : print_truncated(y, truncated_to=truncated_to, full_threshold=full_threshold) | ||
|
||
if len(x) > full_threshold and len(x) > truncated_to * 2: | ||
for i in range(truncated_to): | ||
collected.append(transform(x[i])) | ||
collected.append("...") | ||
for i in range(truncated_to, 0, -1): | ||
collected.append(transform(x[len(x) - i])) | ||
else: | ||
for c in x: | ||
collected.append(transform(c)) | ||
|
||
output = sep.join(collected) | ||
if include_brackets: | ||
output = "[" + output + "]" | ||
return output | ||
|
||
|
||
def print_truncated_dict(x: Dict, truncated_to: int = 3, full_threshold: int = 10, transform: Optional[Callable] = None, sep: str = ", ", include_brackets: bool = True) -> str: | ||
""" | ||
Pretty-print a dictionary, replacing the middle elements with an ellipsis | ||
if there are too many. This provides a useful preview of an object without | ||
spewing out all of its contents on the screen. | ||
Args: | ||
x: Dictionary to be printed. | ||
truncated_to: | ||
Number of elements to truncate to, at the start and end of the | ||
sequence. This should be less than half of ``full_threshold``. | ||
full_threshold: | ||
Threshold on the number of elements, below which the list is | ||
shown in its entirety. | ||
transform: | ||
Optional transformation to apply to the values of ``x`` after | ||
truncation but before printing. Defaults to | ||
:py:meth:`~print_truncated` if not supplied. | ||
sep: | ||
Separator between elements in the printed list. | ||
include_brackets: | ||
Whether to include the start/end brackets. | ||
Returns: | ||
String containing the pretty-printed truncated dict. | ||
""" | ||
collected = [] | ||
if transform is None: | ||
transform = lambda y : print_truncated(y, truncated_to=truncated_to, full_threshold=full_threshold) | ||
|
||
all_keys = x.keys() | ||
if len(x) > full_threshold and len(x) > truncated_to * 2: | ||
all_keys = list(all_keys) | ||
for i in range(truncated_to): | ||
collected.append(repr(all_keys[i]) + ": " + transform(x[all_keys[i]])) | ||
collected.append("...") | ||
for i in range(len(x) - truncated_to, len(x)): | ||
collected.append(repr(all_keys[i]) + ": " + transform(x[all_keys[i]])) | ||
else: | ||
for c in all_keys: | ||
collected.append(repr(c) + ": " + transform(x[c])) | ||
|
||
output = sep.join(collected) | ||
if include_brackets: | ||
output = "{" + output + "}" | ||
return output |
This file was deleted.
Oops, something went wrong.
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,23 @@ | ||
from biocutils import print_truncated_list, print_truncated_dict, print_truncated | ||
|
||
|
||
def test_print_truncated_list(): | ||
assert print_truncated_list(range(6)) == repr(list(range(6))) | ||
assert print_truncated_list(range(10)) == repr(list(range(10))) | ||
assert print_truncated_list(range(200)) == "[0, 1, 2, ..., 197, 198, 199]" | ||
assert print_truncated_list(["A", "B", "C", "D", "E", "F"], transform=lambda x : repr("foo_" + x)) == "['foo_A', 'foo_B', 'foo_C', 'foo_D', 'foo_E', 'foo_F']" | ||
assert print_truncated_list(["A", "B", "C", "D", "E", "F"], truncated_to=2, full_threshold=5, transform=lambda x : repr("foo_" + x)) == "['foo_A', 'foo_B', ..., 'foo_E', 'foo_F']" | ||
assert print_truncated_list(range(200), sep=" ", include_brackets=False) == "0 1 2 ... 197 198 199" | ||
|
||
|
||
def test_print_truncated_dict(): | ||
assert print_truncated_dict({"A":"B"}) == "{'A': 'B'}" | ||
assert print_truncated_dict({"A":"B", "C": [1,2,3,4,5,6,7,8,9,10,11]}) == "{'A': 'B', 'C': [1, 2, 3, ..., 9, 10, 11]}" | ||
assert print_truncated_dict({"A":-1, "B": 0, "C": 1, "D": 2, "E": True, "F": False }, truncated_to = 2, full_threshold = 5) == "{'A': -1, 'B': 0, ..., 'E': True, 'F': False}" | ||
assert print_truncated_dict({"A":-1, "B": 0, "C": 1, "D": 2, "E": True, "F": False }, sep=" ", include_brackets=False) == "'A': -1 'B': 0 'C': 1 'D': 2 'E': True 'F': False" | ||
|
||
|
||
def test_print_truncated(): | ||
internal = {"A":-1, "B": 0, "C": 1, "D": 2, "E": True, "F": False } | ||
expected = "{'A': -1, 'B': 0, ..., 'E': True, 'F': False}" | ||
assert print_truncated([internal] * 10, truncated_to = 2, full_threshold = 5) == "[" + (expected + ", " ) * 2 + "..." + (", " + expected) * 2 + "]" |
This file was deleted.
Oops, something went wrong.