Skip to content

Commit

Permalink
Merge pull request #1992 from bhrutledge/condensed-time-column
Browse files Browse the repository at this point in the history
Add condensed time column
  • Loading branch information
willmcgugan committed Feb 27, 2022
2 parents e78acae + e2ccd5b commit 646d933
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 7 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -9,6 +9,8 @@ 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).
https://github.com/Textualize/rich/pull/1941
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTORS.md
Expand Up @@ -33,4 +33,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

0 comments on commit 646d933

Please sign in to comment.