Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add condensed time column #1992

Merged
merged 3 commits into from Feb 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Expand Up @@ -9,8 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Added options to TimeRemainingColumn to render a compact time format and render elapsed time when a task is
finished. https://github.com/Textualize/rich/pull/1992
- Added ProgressColumn `MofNCompleteColumn` to display raw `completed/total` column (similar to DownloadColumn,
but displays values as ints, does not convert to floats or add bit/bytes units).
but displays values as ints, does not convert to floats or add bit/bytes units).
https://github.com/Textualize/rich/pull/1941

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTORS.md
Expand Up @@ -31,4 +31,4 @@ The following people have contributed to the development of Rich:
- [Dennis Brakhane](https://github.com/brakhane)
- [Michał Górny](https://github.com/mgorny)
- [Arian Mollik Wasi](https://github.com/wasi-master)

- [Brian Rutledge](https://github.com/bhrutledge)
42 changes: 36 additions & 6 deletions rich/progress.py
Expand Up @@ -343,18 +343,48 @@ def render(self, task: "Task") -> Text:


class TimeRemainingColumn(ProgressColumn):
"""Renders estimated time remaining."""
"""Renders estimated time remaining.

Args:
compact (bool, optional): Render MM:SS when time remaining is less than an hour. Defaults to False.
elapsed_when_finished (bool, optional): Render time elapsed when the task is finished. Defaults to False.
"""

# Only refresh twice a second to prevent jitter
max_refresh = 0.5

def __init__(
self,
compact: bool = False,
elapsed_when_finished: bool = False,
table_column: Optional[Column] = None,
):
self.compact = compact
self.elapsed_when_finished = elapsed_when_finished
super().__init__(table_column=table_column)

def render(self, task: "Task") -> Text:
"""Show time remaining."""
remaining = task.time_remaining
if remaining is None:
return Text("-:--:--", style="progress.remaining")
remaining_delta = timedelta(seconds=int(remaining))
return Text(str(remaining_delta), style="progress.remaining")
if self.elapsed_when_finished and task.finished:
task_time = task.finished_time
style = "progress.elapsed"
else:
task_time = task.time_remaining
style = "progress.remaining"

if task_time is None:
return Text("--:--" if self.compact else "-:--:--", style=style)

# Based on https://github.com/tqdm/tqdm/blob/master/tqdm/std.py
minutes, seconds = divmod(int(task_time), 60)
hours, minutes = divmod(minutes, 60)

if self.compact and not hours:
formatted = f"{minutes:02d}:{seconds:02d}"
else:
formatted = f"{hours:d}:{minutes:02d}:{seconds:02d}"

return Text(formatted, style=style)


class FileSizeColumn(ProgressColumn):
Expand Down
28 changes: 28 additions & 0 deletions tests/test_progress.py
Expand Up @@ -2,6 +2,7 @@

import io
from time import sleep
from types import SimpleNamespace

import pytest

Expand Down Expand Up @@ -89,6 +90,33 @@ class FakeTask(Task):
assert str(text) == "0:01:00"


@pytest.mark.parametrize(
"task_time, formatted",
[
(None, "--:--"),
(0, "00:00"),
(59, "00:59"),
(71, "01:11"),
(4210, "1:10:10"),
],
)
def test_compact_time_remaining_column(task_time, formatted):
task = SimpleNamespace(finished=False, time_remaining=task_time)
column = TimeRemainingColumn(compact=True)

assert str(column.render(task)) == formatted


def test_time_remaining_column_elapsed_when_finished():
task_time = 71
formatted = "0:01:11"

task = SimpleNamespace(finished=True, finished_time=task_time)
column = TimeRemainingColumn(elapsed_when_finished=True)

assert str(column.render(task)) == formatted


def test_renderable_column():
column = RenderableColumn("foo")
task = Task(1, "test", 100, 20, _get_time=lambda: 1.0)
Expand Down