Skip to content

Commit

Permalink
table improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
willmcgugan committed Jun 30, 2020
1 parent a7396aa commit 11c0022
Show file tree
Hide file tree
Showing 12 changed files with 76 additions and 21 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.0.1] - 2020-06-30

### Added

- Added box.ASCII2
- Added markup argument to logging extra

### Changed

- Setting a non-None width now implies expand=True

## [3.0.0] - 2020-06-28

### Changed
Expand Down
8 changes: 7 additions & 1 deletion docs/source/logging.rst
Expand Up @@ -14,4 +14,10 @@ Here's an example of how to set up a rich logger::
)

log = logging.getLogger("rich")
log.info("Hello, World!")
log.info("Hello, World!")

Rich logs won't process console markup by default, but you can enable markup per log statement with the ``extras`` argument as follows::

log.error("[bold red blink]Server is shutting down![/]", extras={"markup": True})

There are a number of options you can use to configure logging output, see the :class:`~rich.logging.RichHandler` reference for details.
6 changes: 2 additions & 4 deletions docs/source/progress.rst
Expand Up @@ -80,11 +80,9 @@ When you add a task it is automatically *started*, which means it will show a pr
Auto refresh
~~~~~~~~~~~~

By default, the progress information will refresh 10 times a second. Refreshing at a predictable rate can make numbers more readable if they are updating quickly. Auto refresh can also prevent excessive rendering to the terminal.
By default, the progress information will refresh 10 times a second. You can set the refresh rate with the ``refresh_per_second`` argument on the :class:`~rich.progress.Progress` constructor. You should set this to something lower than 10 if you know your updates will not be that frequent.

You can set the refresh rate with the ``refresh_per_second`` argument on the :class:`~rich.progress.Progress` constructor. You could set this to something lower than 10 if you know your updates will not be that frequent.

You can disable auto-refresh by setting ``auto_refresh=False`` on the constructor and call :meth:`~rich.progress.Progress.refresh` manually when there are updates to display.
You might want to disable auto-refresh entirely if your updates are not very frequent, which you can do by setting ``auto_refresh=False`` on the constructor. If you disable auto-refresh you will need to call :meth:`~rich.progress.Progress.refresh` manually after updating your task(s).

Columns
~~~~~~~
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Expand Up @@ -2,7 +2,7 @@
name = "rich"
homepage = "https://github.com/willmcgugan/rich"
documentation = "https://rich.readthedocs.io/en/latest/"
version = "3.0.0"
version = "3.0.1"
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
authors = ["Will McGugan <willmcgugan@gmail.com>"]
license = "MIT"
Expand Down
9 changes: 5 additions & 4 deletions rich/bar.py
Expand Up @@ -170,18 +170,19 @@ def __rich_console__(
complete_style = console.get_style(
self.complete_style if self.completed < self.total else self.finished_style
)
_Segment = Segment
if bar_count:
yield Segment(bar * bar_count, complete_style)
yield _Segment(bar * bar_count, complete_style)
if half_bar_count:
yield Segment(half_bar_right * half_bar_count, complete_style)
yield _Segment(half_bar_right * half_bar_count, complete_style)

remaining_bars = width - bar_count - half_bar_count
if remaining_bars:
if not half_bar_count and bar_count:
yield Segment(half_bar_left, style)
yield _Segment(half_bar_left, style)
remaining_bars -= 1
if remaining_bars:
yield Segment(bar * remaining_bars, style)
yield _Segment(bar * remaining_bars, style)

def __rich_measure__(self, console: Console, max_width: int) -> Measurement:
return (
Expand Down
18 changes: 16 additions & 2 deletions rich/box.py
Expand Up @@ -156,6 +156,19 @@ def get_bottom(self, widths: Iterable[int]) -> str:
"""
)

ASCII2: Box = Box(
"""\
+-++
| ||
+-++
| ||
+-++
+-++
| ||
+-++
"""
)

SQUARE: Box = Box(
"""\
┌─┬┐
Expand Down Expand Up @@ -330,6 +343,7 @@ def get_bottom(self, widths: Iterable[int]) -> str:
"""
)

# Map Boxes that don't render with raster fonts on to equivalent that do
LEGACY_WINDOWS_SUBSTITUTIONS = {
ROUNDED: SQUARE,
MINIMAL_HEAVY_HEAD: MINIMAL,
Expand Down Expand Up @@ -379,6 +393,7 @@ def get_safe_box(box: Optional[Box], legacy_windows: bool) -> Optional[Box]:

BOXES = [
"ASCII",
"ASCII2",
"SQUARE",
"MINIMAL",
"MINIMAL_HEAVY_HEAD",
Expand All @@ -400,9 +415,8 @@ def get_safe_box(box: Optional[Box], legacy_windows: bool) -> Optional[Box]:
columns = Columns(expand=True, padding=2)
for box_name in BOXES:
table = Table(
width=80, show_footer=True, style="dim", border_style="not dim", expand=True
show_footer=True, style="dim", border_style="not dim", expand=True
)
spaces = " " * 10
table.add_column("Header 1", "Footer 1")
table.add_column("Header 2", "Footer 2")
table.add_row("Cell", "Cell")
Expand Down
2 changes: 1 addition & 1 deletion rich/console.py
Expand Up @@ -927,7 +927,7 @@ def _check_buffer(self) -> None:
text = self._render_buffer()
if text:
self.file.write(text)
self.file.flush()
self.file.flush()

def _render_buffer(self) -> str:
"""Render buffered output, and clear buffer."""
Expand Down
2 changes: 1 addition & 1 deletion rich/measure.py
Expand Up @@ -21,7 +21,7 @@ def span(self) -> int:

def normalize(self) -> "Measurement":
minimum, maximum = self
minimum = max(0, minimum)
minimum = min(max(0, minimum), maximum)
return Measurement(minimum, max(minimum, maximum))

def with_maximum(self, width: int) -> "Measurement":
Expand Down
2 changes: 1 addition & 1 deletion rich/progress.py
Expand Up @@ -832,7 +832,7 @@ def process_renderables(

task1 = progress.add_task(" [red]Downloading", total=1000)
task2 = progress.add_task(" [green]Processing", total=1000)
task3 = progress.add_task(" [yellow]Thinking", total=1000, start=False)
# task3 = progress.add_task(" [yellow]Thinking", total=1000, start=False)

while not progress.finished:
progress.update(task1, advance=0.5)
Expand Down
26 changes: 21 additions & 5 deletions rich/table.py
Expand Up @@ -101,7 +101,7 @@ class Table(JupyterMixin):
padding (PaddingDimensions, optional): Padding for cells (top, right, bottom, left). Defaults to (0, 1).
collapse_padding (bool, optional): Enable collapsing of padding around cells. Defaults to False.
pad_edge (bool, optional): Enable padding of edge cells. Defaults to True.
expand (bool, optional): Expand the table to fit the available space if ``True`` otherwise the table width will be auto-calculated. Defaults to False.
expand (bool, optional): Expand the table to fit the available space if ``True``, otherwise the table width will be auto-calculated. Defaults to False.
show_header (bool, optional): Show a header row. Defaults to True.
show_footer (bool, optional): Show a footer row. Defaults to False.
show_edge (bool, optional): Draw a box around the outside of the table. Defaults to True.
Expand Down Expand Up @@ -153,7 +153,7 @@ def __init__(
self.safe_box = safe_box
self._padding = Padding.unpack(padding)
self.pad_edge = pad_edge
self.expand = expand
self._expand = expand
self.show_header = show_header
self.show_footer = show_footer
self.show_edge = show_edge
Expand Down Expand Up @@ -195,6 +195,16 @@ def grid(
pad_edge=pad_edge,
)

@property
def expand(self) -> int:
"""Setting a non-None self.width implies expand."""
return self._expand or self.width is not None

@expand.setter
def expand(self, expand: bool) -> None:
"""Set expand."""
self._expand = expand

@property
def _extra_width(self) -> int:
"""Get extra width to add to cell content."""
Expand Down Expand Up @@ -231,9 +241,15 @@ def __rich_measure__(self, console: "Console", max_width: int) -> Measurement:
measurements = [
_measure_column(console, column, max_width) for column in self.columns
]
minimum_width = sum(measurement.minimum for measurement in measurements)
maximum_width = sum(measurement.maximum for measurement in measurements)
return Measurement(minimum_width + extra_width, maximum_width + extra_width)
minimum_width = (
sum(measurement.minimum for measurement in measurements) + extra_width
)
maximum_width = (
sum(measurement.maximum for measurement in measurements) + extra_width
if (self.width is None)
else self.width
)
return Measurement(minimum_width, maximum_width)

@property
def padding(self) -> Tuple[int, int, int, int]:
Expand Down
9 changes: 9 additions & 0 deletions tests/test_style.py
Expand Up @@ -101,6 +101,15 @@ def test_parse():
Style.parse("link")


def test_link_id():
assert Style().link_id == ""
assert Style.parse("").link_id == ""
assert Style.parse("red").link_id == ""
style = Style.parse("red link https://example.org")
assert isinstance(style.link_id, str)
assert len(style.link_id) > 1


def test_get_html_style():
expected = "color: #7f7fbf; background-color: #800000; font-weight: bold; font-style: italic; text-decoration: underline; text-decoration: line-through; text-decoration: overline"
assert (
Expand Down
2 changes: 1 addition & 1 deletion tests/test_table.py
Expand Up @@ -61,7 +61,7 @@ def render_tables():
console.print(table)

table.width = 20
assert Measurement.get(console, table, 80) == Measurement(46, 52)
assert Measurement.get(console, table, 80) == Measurement(20, 20)
console.print(table)

return console.file.getvalue()
Expand Down

0 comments on commit 11c0022

Please sign in to comment.