mirror of https://github.com/Textualize/rich.git
table tests, optimizations
This commit is contained in:
parent
7e029e343b
commit
17011e3338
|
@ -12,15 +12,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Added overflow methods
|
||||
- Added no_wrap option to print()
|
||||
- Added width option to print
|
||||
- Improved handling of compressed tables
|
||||
|
||||
### Fixed
|
||||
|
||||
- Improved handling of compressed tables
|
||||
- Fixed erroneous space at end of log
|
||||
|
||||
### Changed
|
||||
|
||||
- Renamed \_ratio.ratio_divide to \_ratio.ratio_distribute
|
||||
- Renamed JustifyValues to JustifyMethod
|
||||
- Optimized \_trim_spans
|
||||
|
||||
## [1.3.1] - 2020-06-01
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
from typing import Optional
|
||||
|
||||
|
||||
def pick_bool(*values: Optional[bool]) -> bool:
|
||||
"""Pick the first non-none bool or return the last value.
|
||||
|
||||
Args:
|
||||
*values (bool): Any number of boolean or None values.
|
||||
|
||||
Returns:
|
||||
bool: First non-none boolean.
|
||||
"""
|
||||
assert values, "1 or more values required"
|
||||
for value in values:
|
||||
if value is not None:
|
||||
return value
|
||||
return bool(value)
|
|
@ -93,7 +93,7 @@ class ConsoleOptions:
|
|||
encoding: str
|
||||
justify: Optional[JustifyMethod] = None
|
||||
overflow: Optional[OverflowMethod] = None
|
||||
no_wrap: bool = False
|
||||
no_wrap: Optional[bool] = False
|
||||
|
||||
def update(
|
||||
self,
|
||||
|
|
57
rich/text.py
57
rich/text.py
|
@ -23,6 +23,7 @@ from .containers import Lines
|
|||
from .control import strip_control_codes
|
||||
from .jupyter import JupyterMixin
|
||||
from .measure import Measurement
|
||||
from ._pick import pick_bool
|
||||
from .segment import Segment
|
||||
from .style import Style, StyleType
|
||||
|
||||
|
@ -114,7 +115,7 @@ class Text(JupyterMixin):
|
|||
style: Union[str, Style] = "",
|
||||
justify: "JustifyMethod" = None,
|
||||
overflow: "OverflowMethod" = None,
|
||||
no_wrap: bool = False,
|
||||
no_wrap: bool = None,
|
||||
end: str = "\n",
|
||||
tab_size: Optional[int] = 8,
|
||||
spans: List[Span] = None,
|
||||
|
@ -423,28 +424,16 @@ class Text(JupyterMixin):
|
|||
"OverflowMethod", self.overflow or options.overflow or DEFAULT_OVERFLOW
|
||||
)
|
||||
|
||||
if self.no_wrap or options.no_wrap:
|
||||
render_text = self
|
||||
if overflow in ("crop", "ellipsis"):
|
||||
render_text = self.copy()
|
||||
render_text.truncate(options.max_width, overflow)
|
||||
if justify:
|
||||
lines = Lines([render_text])
|
||||
lines.justify(
|
||||
console, options.max_width, justify=justify, overflow=overflow
|
||||
)
|
||||
render_text = lines[0]
|
||||
yield from render_text.render(console, end=self.end)
|
||||
else:
|
||||
lines = self.wrap(
|
||||
console,
|
||||
options.max_width,
|
||||
justify=justify,
|
||||
overflow=overflow,
|
||||
tab_size=tab_size or 8,
|
||||
)
|
||||
all_lines = Text("\n").join(lines)
|
||||
yield from all_lines.render(console, end=self.end)
|
||||
lines = self.wrap(
|
||||
console,
|
||||
options.max_width,
|
||||
justify=justify,
|
||||
overflow=overflow,
|
||||
tab_size=tab_size or 8,
|
||||
no_wrap=pick_bool(options.no_wrap, self.no_wrap, False),
|
||||
)
|
||||
all_lines = Text("\n").join(lines)
|
||||
yield from all_lines.render(console, end=self.end)
|
||||
|
||||
def __rich_measure__(self, console: "Console", max_width: int) -> Measurement:
|
||||
text = self.plain
|
||||
|
@ -574,7 +563,7 @@ class Text(JupyterMixin):
|
|||
|
||||
Args:
|
||||
max_width (int): Maximum number of characters in text.
|
||||
overflow (str, optional): Overflow method: "crop", "fold", or "ellipisis". Defaults to None, to use self.overflow.
|
||||
overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to None, to use self.overflow.
|
||||
pad (bool, optional): Pad with spaces if the length is less than max_width. Defaults to False.
|
||||
"""
|
||||
length = cell_len(self.plain)
|
||||
|
@ -584,7 +573,6 @@ class Text(JupyterMixin):
|
|||
self.plain = set_cell_size(self.plain, max_width - 1).rstrip() + "…"
|
||||
else:
|
||||
self.plain = set_cell_size(self.plain, max_width)
|
||||
length = cell_len(self.plain)
|
||||
if pad and length < max_width:
|
||||
spaces = max_width - length
|
||||
self.plain = f"{self.plain}{' ' * spaces}"
|
||||
|
@ -785,6 +773,7 @@ class Text(JupyterMixin):
|
|||
justify: "JustifyMethod" = None,
|
||||
overflow: "OverflowMethod" = None,
|
||||
tab_size: int = 8,
|
||||
no_wrap: bool = None,
|
||||
) -> Lines:
|
||||
"""Word wrap the text.
|
||||
|
||||
|
@ -792,9 +781,10 @@ class Text(JupyterMixin):
|
|||
console (Console): Console instance.
|
||||
width (int): Number of characters per line.
|
||||
emoji (bool, optional): Also render emoji code. Defaults to True.
|
||||
justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to "left".
|
||||
overflow (str, optional): Overflow method: "crop", "fold", or "ellipisis". Defaults to None.
|
||||
justify (str, optional): Justify method: "default", "left", "center", "full", "right". Defaults to "default".
|
||||
overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to None.
|
||||
tab_size (int, optional): Default tab size. Defaults to 8.
|
||||
no_wrap (bool, optional): Disable wrapping, Defaults to False.
|
||||
|
||||
Returns:
|
||||
Lines: Number of lines.
|
||||
|
@ -803,23 +793,26 @@ class Text(JupyterMixin):
|
|||
wrap_overflow = cast(
|
||||
"OverflowMethod", overflow or self.overflow or DEFAULT_OVERFLOW
|
||||
)
|
||||
no_wrap = pick_bool(no_wrap, self.no_wrap, False)
|
||||
lines: Lines = Lines()
|
||||
for line in self.split():
|
||||
if "\t" in line:
|
||||
line = line.tabs_to_spaces(tab_size)
|
||||
offsets = divide_line(str(line), width, fold=wrap_overflow == "fold")
|
||||
new_lines = line.divide(offsets)
|
||||
if no_wrap:
|
||||
new_lines = Lines([line])
|
||||
else:
|
||||
offsets = divide_line(str(line), width, fold=wrap_overflow == "fold")
|
||||
new_lines = line.divide(offsets)
|
||||
for line in new_lines:
|
||||
line.rstrip_end(width)
|
||||
if wrap_justify:
|
||||
new_lines.justify(
|
||||
console, width, justify=wrap_justify, overflow=wrap_overflow
|
||||
)
|
||||
for line in new_lines:
|
||||
line.truncate(width, wrap_overflow)
|
||||
lines.extend(new_lines)
|
||||
|
||||
for line in lines:
|
||||
line.truncate(width, wrap_overflow)
|
||||
|
||||
return lines
|
||||
|
||||
def fit(self, width: int) -> Lines:
|
||||
|
|
|
@ -248,6 +248,5 @@ def test_save_html():
|
|||
|
||||
def test_no_wrap():
|
||||
console = Console(width=10, file=io.StringIO())
|
||||
console.print("X" * 15)
|
||||
console.print("Y" * 15, no_wrap=True)
|
||||
assert console.file.getvalue() == "XXXXXXXXXX\nXXXXX\nYYYYYYYYYY\n"
|
||||
console.print("foo bar baz egg", no_wrap=True)
|
||||
assert console.file.getvalue() == "foo bar ba\n"
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# encoding=utf-8
|
||||
|
||||
import io
|
||||
|
||||
|
||||
from rich.console import Console
|
||||
from rich.table import Table
|
||||
|
||||
|
||||
def render_tables():
|
||||
console = Console(width=60, file=io.StringIO())
|
||||
|
||||
table = Table(title="test table", caption="table footer", expand=True)
|
||||
table.add_column("foo", no_wrap=True, overflow="ellipsis")
|
||||
table.add_column("bar", justify="center")
|
||||
table.add_column("baz", justify="right")
|
||||
|
||||
table.add_row("Averlongwordgoeshere", "banana pancakes", None)
|
||||
|
||||
for width in range(10, 60, 5):
|
||||
console.print(table, width=width)
|
||||
|
||||
return console.file.getvalue()
|
||||
|
||||
|
||||
def test_render_table():
|
||||
expected = "test table\n┏━━┳━━┳━━┓\n┃ ┃ ┃ ┃\n┡━━╇━━╇━━┩\n│ │ │ │\n└──┴──┴──┘\n table \n footer \n test table \n┏━━━━━┳━━━━┳━━┓\n┃ foo ┃ b… ┃ ┃\n┡━━━━━╇━━━━╇━━┩\n│ Av… │ b… │ │\n└─────┴────┴──┘\n table footer \n test table \n┏━━━━━━━━┳━━━━━┳━━━┓\n┃ foo ┃ bar ┃ … ┃\n┡━━━━━━━━╇━━━━━╇━━━┩\n│ Averl… │ ba… │ │\n└────────┴─────┴───┘\n table footer \n test table \n┏━━━━━━━━━━━━┳━━━━━━┳━━━┓\n┃ foo ┃ bar ┃ … ┃\n┡━━━━━━━━━━━━╇━━━━━━╇━━━┩\n│ Averlongw… │ ban… │ │\n└────────────┴──────┴───┘\n table footer \n test table \n┏━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━┓\n┃ foo ┃ bar ┃ b… ┃\n┡━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━┩\n│ Averlongword… │ bana… │ │\n└───────────────┴───────┴────┘\n table footer \n test table \n┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━┓\n┃ foo ┃ bar ┃ b… ┃\n┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━┩\n│ Averlongwordgoe… │ banana… │ │\n└──────────────────┴─────────┴────┘\n table footer \n test table \n┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ foo ┃ bar ┃ baz ┃\n┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━┩\n│ Averlongwordgoeshe… │ banana │ │\n│ │ pancakes │ │\n└─────────────────────┴──────────┴─────┘\n table footer \n test table \n┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━┓\n┃ foo ┃ bar ┃ baz ┃\n┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━┩\n│ Averlongwordgoeshere │ banana │ │\n│ │ pancakes │ │\n└──────────────────────┴──────────────┴─────┘\n table footer \n test table \n┏━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━┓\n┃ foo ┃ bar ┃ baz ┃\n┡━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━┩\n│ Averlongwordgoeshere │ banana pancakes │ │\n└───────────────────────┴─────────────────┴──────┘\n table footer \n test table \n┏━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━┓\n┃ foo ┃ bar ┃ baz ┃\n┡━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━┩\n│ Averlongwordgoeshere │ banana pancakes │ │\n└─────────────────────────┴────────────────────┴──────┘\n table footer \n"
|
||||
assert render_tables() == expected
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
render = render_tables()
|
||||
print(render)
|
||||
print(repr(render))
|
Loading…
Reference in New Issue