rich/tests/test_progress.py

263 lines
12 KiB
Python
Raw Normal View History

2020-06-06 13:26:58 +00:00
# encoding=utf-8
2020-04-26 11:25:53 +00:00
import io
2020-04-14 15:40:42 +00:00
from time import time
2020-05-22 09:33:57 +00:00
import pytest
2020-04-14 15:40:42 +00:00
from rich.bar import Bar
2020-05-22 09:33:57 +00:00
from rich.console import Console
from rich.highlighter import NullHighlighter
from rich.progress import (
BarColumn,
FileSizeColumn,
TotalFileSizeColumn,
DownloadColumn,
TransferSpeedColumn,
Progress,
Task,
TextColumn,
TimeRemainingColumn,
track,
2020-05-22 13:57:50 +00:00
TaskID,
_RefreshThread,
2020-05-22 09:33:57 +00:00
)
from rich.text import Text
2020-04-14 15:40:42 +00:00
class MockClock:
"""A clock that is manually advanced."""
def __init__(self, time=0.0, auto=True) -> None:
self.time = time
self.auto = auto
def __call__(self) -> float:
try:
return self.time
finally:
if self.auto:
self.time += 1
def tick(self, advance: float = 1) -> None:
self.time += advance
2020-04-14 15:40:42 +00:00
def test_bar_columns():
2020-04-26 11:25:53 +00:00
bar_column = BarColumn(100)
2020-04-14 15:40:42 +00:00
assert bar_column.bar_width == 100
2020-05-24 14:43:33 +00:00
task = Task(1, "test", 100, 20, _get_time=lambda: 1.0)
2020-04-14 15:40:42 +00:00
bar = bar_column(task)
assert isinstance(bar, Bar)
assert bar.completed == 20
assert bar.total == 100
2020-05-22 09:33:57 +00:00
def test_text_column():
text_column = TextColumn("[b]foo", highlighter=NullHighlighter())
2020-05-24 14:43:33 +00:00
task = Task(1, "test", 100, 20, _get_time=lambda: 1.0)
2020-05-22 09:33:57 +00:00
text = text_column.render(task)
assert str(text) == "foo"
text_column = TextColumn("[b]bar", markup=False)
2020-05-24 14:43:33 +00:00
task = Task(1, "test", 100, 20, _get_time=lambda: 1.0)
2020-05-22 09:33:57 +00:00
text = text_column.render(task)
assert text == Text("[b]bar")
2020-04-14 15:40:42 +00:00
def test_time_remaining_column():
2020-04-26 11:25:53 +00:00
class FakeTask(Task):
2020-04-14 15:40:42 +00:00
time_remaining = 60
2020-04-26 11:25:53 +00:00
column = TimeRemainingColumn()
2020-05-24 14:43:33 +00:00
task = Task(1, "test", 100, 20, _get_time=lambda: 1.0)
2020-04-14 15:40:42 +00:00
text = column(task)
assert str(text) == "-:--:--"
2020-05-24 14:43:33 +00:00
text = column(FakeTask(1, "test", 100, 20, _get_time=lambda: 1.0))
2020-04-14 15:40:42 +00:00
assert str(text) == "0:01:00"
2020-04-26 11:25:53 +00:00
def test_task_ids():
progress = make_progress()
assert progress.task_ids == [0, 1, 2, 4]
def test_finished():
progress = make_progress()
assert not progress.finished
def make_progress() -> Progress:
2020-05-24 14:43:33 +00:00
_time = 0.0
2020-05-24 11:06:46 +00:00
def fake_time():
2020-05-24 14:43:33 +00:00
nonlocal _time
try:
return _time
finally:
_time += 1
2020-05-24 11:06:46 +00:00
console = Console(
2020-05-24 15:09:06 +00:00
file=io.StringIO(), force_terminal=True, color_system="truecolor", width=80
2020-05-24 11:06:46 +00:00
)
progress = Progress(console=console, get_time=fake_time, auto_refresh=False)
2020-04-26 11:25:53 +00:00
task1 = progress.add_task("foo")
2020-05-24 15:01:28 +00:00
task2 = progress.add_task("bar", total=30)
2020-04-26 11:25:53 +00:00
progress.advance(task2, 16)
task3 = progress.add_task("baz", visible=False)
task4 = progress.add_task("egg")
progress.remove_task(task4)
task4 = progress.add_task("foo2", completed=50, start=False)
progress.start_task(task4)
progress.update(
task4, total=200, advance=50, completed=200, visible=True, refresh=True
)
return progress
def render_progress() -> str:
progress = make_progress()
with progress:
pass
2020-04-26 11:25:53 +00:00
progress_render = progress.console.file.getvalue()
return progress_render
2020-05-20 17:55:23 +00:00
def test_expand_bar() -> None:
2020-05-24 14:28:34 +00:00
console = Console(
file=io.StringIO(), force_terminal=True, width=10, color_system="truecolor"
)
2020-05-24 15:09:06 +00:00
progress = Progress(
BarColumn(bar_width=None),
console=console,
get_time=lambda: 1.0,
auto_refresh=False,
)
2020-05-20 17:55:23 +00:00
progress.add_task("foo")
with progress:
pass
expected = "\x1b[?25l\x1b[38;5;237m━━━━━━━━━━\x1b[0m\r\x1b[2K\x1b[38;5;237m━━━━━━━━━━\x1b[0m\n\x1b[?25h"
2020-06-06 16:47:29 +00:00
render_result = console.file.getvalue()
print(repr(render_result))
assert render_result == expected
2020-05-20 17:55:23 +00:00
2020-04-26 11:25:53 +00:00
def test_render() -> None:
expected = "\x1b[?25lfoo \x1b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[35m 0%\x1b[0m \x1b[36m-:--:--\x1b[0m\nbar \x1b[38;2;249;38;114m━━━━━━━━━━━━━━━━━━━━━\x1b[0m\x1b[38;5;237m╺\x1b[0m\x1b[38;5;237m━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[35m 53%\x1b[0m \x1b[36m-:--:--\x1b[0m\nfoo2 \x1b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[35m100%\x1b[0m \x1b[36m0:00:00\x1b[0m\r\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2Kfoo \x1b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[35m 0%\x1b[0m \x1b[36m-:--:--\x1b[0m\nbar \x1b[38;2;249;38;114m━━━━━━━━━━━━━━━━━━━━━\x1b[0m\x1b[38;5;237m╺\x1b[0m\x1b[38;5;237m━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[35m 53%\x1b[0m \x1b[36m-:--:--\x1b[0m\nfoo2 \x1b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[35m100%\x1b[0m \x1b[36m0:00:00\x1b[0m\n\x1b[?25h"
2020-06-06 16:47:29 +00:00
render_result = render_progress()
print(repr(render_result))
assert render_result == expected
2020-04-26 11:25:53 +00:00
2020-05-22 09:33:57 +00:00
def test_track() -> None:
2020-05-24 14:28:34 +00:00
console = Console(
2020-06-06 13:26:58 +00:00
file=io.StringIO(), force_terminal=True, width=60, color_system="truecolor"
2020-05-24 14:28:34 +00:00
)
2020-05-22 09:33:57 +00:00
test = ["foo", "bar", "baz"]
expected_values = iter(test)
2020-05-24 14:28:34 +00:00
for value in track(
test, "test", console=console, auto_refresh=False, get_time=MockClock(auto=True)
2020-05-24 14:28:34 +00:00
):
2020-05-22 09:33:57 +00:00
assert value == next(expected_values)
result = console.file.getvalue()
2020-05-24 14:28:34 +00:00
print(repr(result))
expected = "\x1b[?25ltest \x1b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[35m 0%\x1b[0m \x1b[36m-:--:--\x1b[0m\r\x1b[2Ktest \x1b[38;2;249;38;114m━━━━━━━━━━━━━\x1b[0m\x1b[38;5;237m╺\x1b[0m\x1b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[35m 33%\x1b[0m \x1b[36m-:--:--\x1b[0m\r\x1b[2Ktest \x1b[38;2;249;38;114m━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m\x1b[38;2;249;38;114m╸\x1b[0m\x1b[38;5;237m━━━━━━━━━━━━━\x1b[0m \x1b[35m 67%\x1b[0m \x1b[36m0:00:06\x1b[0m\r\x1b[2Ktest \x1b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[35m100%\x1b[0m \x1b[36m0:00:00\x1b[0m\r\x1b[2Ktest \x1b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[35m100%\x1b[0m \x1b[36m0:00:00\x1b[0m\n\x1b[?25h"
2020-05-22 09:33:57 +00:00
assert result == expected
with pytest.raises(ValueError):
for n in track(5):
pass
def test_columns() -> None:
console = Console(
2020-05-24 15:14:38 +00:00
file=io.StringIO(),
force_terminal=True,
width=80,
log_time_format="[TIME]",
color_system="truecolor",
2020-05-22 09:33:57 +00:00
)
progress = Progress(
"test",
TextColumn("{task.description}"),
BarColumn(bar_width=None),
TimeRemainingColumn(),
FileSizeColumn(),
TotalFileSizeColumn(),
DownloadColumn(),
TransferSpeedColumn(),
transient=True,
2020-05-22 09:33:57 +00:00
console=console,
auto_refresh=False,
get_time=MockClock(),
2020-05-22 09:33:57 +00:00
)
task1 = progress.add_task("foo", total=10)
task2 = progress.add_task("bar", total=7)
with progress:
for n in range(4):
progress.advance(task1, 3)
progress.advance(task2, 4)
print("foo")
console.log("hello")
console.print("world")
2020-05-22 09:33:57 +00:00
progress.refresh()
result = console.file.getvalue()
2020-05-24 10:52:33 +00:00
print(repr(result))
2020-06-14 13:51:19 +00:00
expected = "\x1b[?25ltest foo \x1b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m10 bytes\x1b[0m \x1b[32m0/10 bytes\x1b[0m \x1b[31m?\x1b[0m\ntest bar \x1b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m7 bytes \x1b[0m \x1b[32m0/7 bytes \x1b[0m \x1b[31m?\x1b[0m\r\x1b[2K\x1b[1A\x1b[2Kfoo\ntest foo \x1b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m10 bytes\x1b[0m \x1b[32m0/10 bytes\x1b[0m \x1b[31m?\x1b[0m\ntest bar \x1b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m7 bytes \x1b[0m \x1b[32m0/7 bytes \x1b[0m \x1b[31m?\x1b[0m\r\x1b[2K\x1b[1A\x1b[2K\x1b[2;36m[TIME]\x1b[0m\x1b[2;36m \x1b[0mhello \x1b]8;id=1924337197;file://test_progress.py\x1b\\\x1b[2mtest_progress.py\x1b[0m\x1b]8;;\x1b\\\x1b[2m:204\x1b[0m\ntest foo \x1b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m10 bytes\x1b[0m \x1b[32m0/10 bytes\x1b[0m \x1b[31m?\x1b[0m\ntest bar \x1b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m7 bytes \x1b[0m \x1b[32m0/7 bytes \x1b[0m \x1b[31m?\x1b[0m\r\x1b[2K\x1b[1A\x1b[2Kworld\ntest foo \x1b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m10 bytes\x1b[0m \x1b[32m0/10 bytes\x1b[0m \x1b[31m?\x1b[0m\ntest bar \x1b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m7 bytes \x1b[0m \x1b[32m0/7 bytes \x1b[0m \x1b[31m?\x1b[0m\r\x1b[2K\x1b[1A\x1b[2Ktest foo \x1b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[36m0:00:00\x1b[0m \x1b[32m12 bytes\x1b[0m \x1b[32m10 bytes\x1b[0m \x1b[32m12/10 bytes\x1b[0m \x1b[31m1 byte/s \x1b[0m\ntest bar \x1b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[36m0:00:00\x1b[0m \x1b[32m16 bytes\x1b[0m \x1b[32m7 bytes \x1b[0m \x1b[32m16/7 bytes \x1b[0m \x1b[31m2 bytes/s\x1b[0m\r\x1b[2K\x1b[1A\x1b[2Ktest foo \x1b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[36m0:00:00\x1b[0m \x1b[32m12 bytes\x1b[0m \x1b[32m10 bytes\x1b[0m \x1b[32m12/10 bytes\x1b[0m \x1b[31m1 byte/s \x1b[0m\ntest bar \x1b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m \x1b[36m0:00:00\x1b[0m \x1b[32m16 bytes\x1b[0m \x1b[32m7 bytes \x1b[0m \x1b[32m16/7 bytes \x1b[0m \x1b[31m2 bytes/s\x1b[0m\n\x1b[?25h\r\x1b[1A\x1b[2K\x1b[1A\x1b[2K"
2020-05-22 09:33:57 +00:00
assert result == expected
2020-05-22 13:57:50 +00:00
def test_task_create() -> None:
2020-05-24 14:43:33 +00:00
task = Task(TaskID(1), "foo", 100, 0, _get_time=lambda: 1)
2020-05-22 13:57:50 +00:00
assert task.elapsed is None
assert not task.finished
assert task.percentage == 0.0
assert task.speed is None
assert task.time_remaining is None
def test_task_start() -> None:
current_time = 1
def get_time():
nonlocal current_time
return current_time
task = Task(TaskID(1), "foo", 100, 0, _get_time=get_time)
task.start_time = get_time()
assert task.started == True
assert task.elapsed == 0
current_time += 1
assert task.elapsed == 1
current_time += 1
task.stop_time = get_time()
current_time += 1
assert task.elapsed == 2
def test_task_zero_total() -> None:
task = Task(TaskID(1), "foo", 0, 0, _get_time=lambda: 1)
assert task.percentage == 0
2020-05-22 13:57:50 +00:00
def test_progress_create() -> None:
progress = Progress()
assert progress.finished
assert progress.tasks == []
assert progress.task_ids == []
def test_refresh_thread() -> None:
progress = Progress()
thread = _RefreshThread(progress, 10)
assert thread.progress == progress
2020-04-26 11:25:53 +00:00
if __name__ == "__main__":
_render = render_progress()
print(_render)
print(repr(_render))