From ad6d2b41f9119320813582d52af7896b9bc5e5a9 Mon Sep 17 00:00:00 2001 From: Sven Augustin Date: Tue, 22 Oct 2024 11:42:48 +0200 Subject: [PATCH 1/9] added SpeedColumn (displays a generic speed in it/s like TaskProgressColumn without total) --- rich/progress.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/rich/progress.py b/rich/progress.py index 1e92eb6b1..03e94fd74 100644 --- a/rich/progress.py +++ b/rich/progress.py @@ -925,6 +925,15 @@ def render(self, task: "Task") -> Text: return Text(f"{data_speed}/s", style="progress.data.speed") +class SpeedColumn(ProgressColumn): + """Renders human readable speed.""" + + def render(self, task: "Task") -> Text: + """Show speed.""" + speed = task.finished_speed or task.speed + return TaskProgressColumn.render_speed(speed) + + class ProgressSample(NamedTuple): """Sample of progress for a given time.""" From e10e4180d55ea6d0afa421ebc6a5fad637fd6609 Mon Sep 17 00:00:00 2001 From: Sven Augustin Date: Tue, 22 Oct 2024 11:54:11 +0200 Subject: [PATCH 2/9] allow setting the physical units in SpeedColumn and TaskProgressColumn.render_speed --- rich/progress.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/rich/progress.py b/rich/progress.py index 03e94fd74..59c032314 100644 --- a/rich/progress.py +++ b/rich/progress.py @@ -736,11 +736,12 @@ def __init__( ) @classmethod - def render_speed(cls, speed: Optional[float]) -> Text: - """Render the speed in iterations per second. + def render_speed(cls, speed: Optional[float], units: str="it/s") -> Text: + """Render the speed in iterations per second or the supplied units. Args: - task (Task): A Task object. + speed (float): Current value of the speed. + units (str): Units of the speed. Defaults to it/s. Returns: Text: Text object containing the task speed. @@ -753,7 +754,7 @@ def render_speed(cls, speed: Optional[float]) -> Text: 1000, ) data_speed = speed / unit - return Text(f"{data_speed:.1f}{suffix} it/s", style="progress.percentage") + return Text(f"{data_speed:.1f}{suffix} {units}", style="progress.percentage") def render(self, task: "Task") -> Text: if task.total is None and self.show_speed: @@ -928,10 +929,14 @@ def render(self, task: "Task") -> Text: class SpeedColumn(ProgressColumn): """Renders human readable speed.""" + def __init__(self, *args, units: str = "it/s", **kwargs) -> None: + self.units = units + super().__init__(*args, **kwargs) + def render(self, task: "Task") -> Text: """Show speed.""" speed = task.finished_speed or task.speed - return TaskProgressColumn.render_speed(speed) + return TaskProgressColumn.render_speed(speed, units=self.units) class ProgressSample(NamedTuple): From 6ce2ee8d820701a92b4798bdcce38da2b4ffcad1 Mon Sep 17 00:00:00 2001 From: Sven Augustin Date: Tue, 22 Oct 2024 12:07:23 +0200 Subject: [PATCH 3/9] allow setting the physical units of the speed (speed_units) in TaskProgressColumn --- rich/progress.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rich/progress.py b/rich/progress.py index 59c032314..79aff664e 100644 --- a/rich/progress.py +++ b/rich/progress.py @@ -711,6 +711,7 @@ class TaskProgressColumn(TextColumn): highlighter (Optional[Highlighter], optional): Highlighter to apply to output. Defaults to None. table_column (Optional[Column], optional): Table Column to use. Defaults to None. show_speed (bool, optional): Show speed if total is unknown. Defaults to False. + speed_units (str, optional): Units of the speed. Defaults to it/s. """ def __init__( @@ -723,9 +724,11 @@ def __init__( highlighter: Optional[Highlighter] = None, table_column: Optional[Column] = None, show_speed: bool = False, + speed_units: str = "it/s", ) -> None: self.text_format_no_percentage = text_format_no_percentage self.show_speed = show_speed + self.speed_units = speed_units super().__init__( text_format=text_format, style=style, @@ -758,7 +761,7 @@ def render_speed(cls, speed: Optional[float], units: str="it/s") -> Text: def render(self, task: "Task") -> Text: if task.total is None and self.show_speed: - return self.render_speed(task.finished_speed or task.speed) + return self.render_speed(task.finished_speed or task.speed, units=self.speed_units) text_format = ( self.text_format_no_percentage if task.total is None else self.text_format ) From 6f5ece1c4ed344a7eb0cc42fb339a78908bdc7bd Mon Sep 17 00:00:00 2001 From: Sven Augustin Date: Tue, 22 Oct 2024 12:12:03 +0200 Subject: [PATCH 4/9] added Args to docstring of SpeedColumn --- rich/progress.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rich/progress.py b/rich/progress.py index 79aff664e..4c925cb98 100644 --- a/rich/progress.py +++ b/rich/progress.py @@ -930,7 +930,12 @@ def render(self, task: "Task") -> Text: class SpeedColumn(ProgressColumn): - """Renders human readable speed.""" + """Renders human readable speed. + + Args: + table_column (Optional[Column], optional): Table Column to use. Defaults to None. + units (str, optional): Units of the speed. Defaults to it/s. + """ def __init__(self, *args, units: str = "it/s", **kwargs) -> None: self.units = units From 744ace501621946e711997baba25d4d699239d52 Mon Sep 17 00:00:00 2001 From: Sven Augustin Date: Tue, 22 Oct 2024 12:14:06 +0200 Subject: [PATCH 5/9] added SpeedColumn to test_columns mimicking TransferSpeedColumn --- tests/test_progress.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_progress.py b/tests/test_progress.py index 0be683c3e..2772f1f95 100644 --- a/tests/test_progress.py +++ b/tests/test_progress.py @@ -17,6 +17,7 @@ MofNCompleteColumn, Progress, RenderableColumn, + SpeedColumn, SpinnerColumn, Task, TaskID, @@ -355,6 +356,7 @@ def test_columns() -> None: FileSizeColumn(), TotalFileSizeColumn(), DownloadColumn(), + SpeedColumn(), TransferSpeedColumn(), MofNCompleteColumn(), MofNCompleteColumn(separator=" of "), From a22ed75da8c47d2e3e16f0e68c71eff1e8fc17db Mon Sep 17 00:00:00 2001 From: Sven Augustin Date: Tue, 22 Oct 2024 12:18:59 +0200 Subject: [PATCH 6/9] added SpeedColumn --- docs/source/progress.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/progress.rst b/docs/source/progress.rst index baeb3a25a..62f669c1a 100644 --- a/docs/source/progress.rst +++ b/docs/source/progress.rst @@ -161,6 +161,7 @@ The following column objects are available: - :class:`~rich.progress.TotalFileSizeColumn` Displays total file size (assumes the steps are bytes). - :class:`~rich.progress.DownloadColumn` Displays download progress (assumes the steps are bytes). - :class:`~rich.progress.TransferSpeedColumn` Displays transfer speed (assumes the steps are bytes). +- :class:`~rich.progress.SpeedColumn` Displays generic speed in customizable units (defaults to it/s). - :class:`~rich.progress.SpinnerColumn` Displays a "spinner" animation. - :class:`~rich.progress.RenderableColumn` Displays an arbitrary Rich renderable in the column. - :class:`~rich.progress.IterationSpeedColumn` Displays iteration speed in it/s (iterations per second). From a99e35194e362750e32888d390581acea245fc82 Mon Sep 17 00:00:00 2001 From: Sven Augustin Date: Tue, 22 Oct 2024 12:24:00 +0200 Subject: [PATCH 7/9] black --- rich/progress.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rich/progress.py b/rich/progress.py index 4c925cb98..c8bb8ef41 100644 --- a/rich/progress.py +++ b/rich/progress.py @@ -739,7 +739,7 @@ def __init__( ) @classmethod - def render_speed(cls, speed: Optional[float], units: str="it/s") -> Text: + def render_speed(cls, speed: Optional[float], units: str = "it/s") -> Text: """Render the speed in iterations per second or the supplied units. Args: @@ -761,7 +761,9 @@ def render_speed(cls, speed: Optional[float], units: str="it/s") -> Text: def render(self, task: "Task") -> Text: if task.total is None and self.show_speed: - return self.render_speed(task.finished_speed or task.speed, units=self.speed_units) + return self.render_speed( + task.finished_speed or task.speed, units=self.speed_units + ) text_format = ( self.text_format_no_percentage if task.total is None else self.text_format ) From 89642d725fc12a44e1d7548e19e25a6b8a2bb8b3 Mon Sep 17 00:00:00 2001 From: Sven Augustin Date: Tue, 22 Oct 2024 12:30:32 +0200 Subject: [PATCH 8/9] updated CHANGELOG.md and CONTRIBUTORS.md --- CHANGELOG.md | 6 ++++++ CONTRIBUTORS.md | 1 + 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3e1a20c1..0165c8ea7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## [Unreleased] + +### Added + +- Added `progress.SpeedColumn` a generic speed column with customizable units + ## [13.9.2] - 2024-10-04 ### Fixed diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index d8985ca13..4edc03cc1 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -91,3 +91,4 @@ The following people have contributed to the development of Rich: - [L. Yeung](https://github.com/lewis-yeung) - [chthollyphile](https://github.com/chthollyphile) - [Jonathan Helmus](https://github.com/jjhelmus) +- [Sven Augustin](https://github.com/nichtjens) From cebef48de5db3a31bf37667535fc7242e4608804 Mon Sep 17 00:00:00 2001 From: Sven Augustin Date: Tue, 22 Oct 2024 13:17:02 +0200 Subject: [PATCH 9/9] added tests for TaskProgressColumn.render_speed with custom units; fixed test_columns --- tests/test_progress.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/test_progress.py b/tests/test_progress.py index 2772f1f95..a546364cf 100644 --- a/tests/test_progress.py +++ b/tests/test_progress.py @@ -356,8 +356,8 @@ def test_columns() -> None: FileSizeColumn(), TotalFileSizeColumn(), DownloadColumn(), - SpeedColumn(), TransferSpeedColumn(), + SpeedColumn(), MofNCompleteColumn(), MofNCompleteColumn(separator=" of "), transient=True, @@ -379,7 +379,7 @@ def test_columns() -> None: result = replace_link_ids(console.file.getvalue()) print(repr(result)) - expected = "\x1b[?25ltest foo \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:07\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m10 bytes\x1b[0m \x1b[32m0/10 bytes\x1b[0m \x1b[31m?\x1b[0m \x1b[32m 0/10\x1b[0m \x1b[32m 0 of 10\x1b[0m\ntest bar \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:18\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m7 bytes \x1b[0m \x1b[32m0/7 bytes \x1b[0m \x1b[31m?\x1b[0m \x1b[32m0/7 \x1b[0m \x1b[32m0 of 7 \x1b[0m\r\x1b[2K\x1b[1A\x1b[2Kfoo\ntest foo \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:07\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m10 bytes\x1b[0m \x1b[32m0/10 bytes\x1b[0m \x1b[31m?\x1b[0m \x1b[32m 0/10\x1b[0m \x1b[32m 0 of 10\x1b[0m\ntest bar \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:18\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m7 bytes \x1b[0m \x1b[32m0/7 bytes \x1b[0m \x1b[31m?\x1b[0m \x1b[32m0/7 \x1b[0m \x1b[32m0 of 7 \x1b[0m\r\x1b[2K\x1b[1A\x1b[2K\x1b[2;36m[TIME]\x1b[0m\x1b[2;36m \x1b[0mhello \ntest foo \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:07\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m10 bytes\x1b[0m \x1b[32m0/10 bytes\x1b[0m \x1b[31m?\x1b[0m \x1b[32m 0/10\x1b[0m \x1b[32m 0 of 10\x1b[0m\ntest bar \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:18\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m7 bytes \x1b[0m \x1b[32m0/7 bytes \x1b[0m \x1b[31m?\x1b[0m \x1b[32m0/7 \x1b[0m \x1b[32m0 of 7 \x1b[0m\r\x1b[2K\x1b[1A\x1b[2Kworld\ntest foo \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:07\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m10 bytes\x1b[0m \x1b[32m0/10 bytes\x1b[0m \x1b[31m?\x1b[0m \x1b[32m 0/10\x1b[0m \x1b[32m 0 of 10\x1b[0m\ntest bar \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:18\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m7 bytes \x1b[0m \x1b[32m0/7 bytes \x1b[0m \x1b[31m?\x1b[0m \x1b[32m0/7 \x1b[0m \x1b[32m0 of 7 \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[33m0:00:34\x1b[0m \x1b[32m12 \x1b[0m \x1b[32m10 \x1b[0m \x1b[32m12/10 \x1b[0m \x1b[31m1 \x1b[0m \x1b[32m12/10\x1b[0m \x1b[32m12 of 10\x1b[0m\n \x1b[32mbytes \x1b[0m \x1b[32mbytes \x1b[0m \x1b[32mbytes \x1b[0m \x1b[31mbyte/s \x1b[0m \ntest bar \x1b[38;2;114;156;31m━━━━━━━\x1b[0m \x1b[36m0:00:00\x1b[0m \x1b[33m0:00:29\x1b[0m \x1b[32m16 \x1b[0m \x1b[32m7 bytes\x1b[0m \x1b[32m16/7 \x1b[0m \x1b[31m2 \x1b[0m \x1b[32m16/7 \x1b[0m \x1b[32m16 of 7 \x1b[0m\n \x1b[32mbytes \x1b[0m \x1b[32mbytes \x1b[0m \x1b[31mbytes/s\x1b[0m \r\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2Ktest foo \x1b[38;2;114;156;31m━━━━━━━\x1b[0m \x1b[36m0:00:00\x1b[0m \x1b[33m0:00:34\x1b[0m \x1b[32m12 \x1b[0m \x1b[32m10 \x1b[0m \x1b[32m12/10 \x1b[0m \x1b[31m1 \x1b[0m \x1b[32m12/10\x1b[0m \x1b[32m12 of 10\x1b[0m\n \x1b[32mbytes \x1b[0m \x1b[32mbytes \x1b[0m \x1b[32mbytes \x1b[0m \x1b[31mbyte/s \x1b[0m \ntest bar \x1b[38;2;114;156;31m━━━━━━━\x1b[0m \x1b[36m0:00:00\x1b[0m \x1b[33m0:00:29\x1b[0m \x1b[32m16 \x1b[0m \x1b[32m7 bytes\x1b[0m \x1b[32m16/7 \x1b[0m \x1b[31m2 \x1b[0m \x1b[32m16/7 \x1b[0m \x1b[32m16 of 7 \x1b[0m\n \x1b[32mbytes \x1b[0m \x1b[32mbytes \x1b[0m \x1b[31mbytes/s\x1b[0m \n\x1b[?25h\r\x1b[1A\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2K" + expected = "\x1b[?25ltest foo \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:07\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m10 bytes\x1b[0m \x1b[32m0/10 \x1b[0m \x1b[31m?\x1b[0m \x1b[32m 0/10\x1b[0m \x1b[32m 0 of 10\x1b[0m\n \x1b[32mbytes \x1b[0m \ntest bar \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:19\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m7 bytes \x1b[0m \x1b[32m0/7 bytes\x1b[0m \x1b[31m?\x1b[0m \x1b[32m0/7 \x1b[0m \x1b[32m0 of 7 \x1b[0m\r\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2Kfoo\ntest foo \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:07\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m10 bytes\x1b[0m \x1b[32m0/10 \x1b[0m \x1b[31m?\x1b[0m \x1b[32m 0/10\x1b[0m \x1b[32m 0 of 10\x1b[0m\n \x1b[32mbytes \x1b[0m \ntest bar \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:19\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m7 bytes \x1b[0m \x1b[32m0/7 bytes\x1b[0m \x1b[31m?\x1b[0m \x1b[32m0/7 \x1b[0m \x1b[32m0 of 7 \x1b[0m\r\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2K\x1b[2;36m[TIME]\x1b[0m\x1b[2;36m \x1b[0mhello \ntest foo \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:07\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m10 bytes\x1b[0m \x1b[32m0/10 \x1b[0m \x1b[31m?\x1b[0m \x1b[32m 0/10\x1b[0m \x1b[32m 0 of 10\x1b[0m\n \x1b[32mbytes \x1b[0m \ntest bar \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:19\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m7 bytes \x1b[0m \x1b[32m0/7 bytes\x1b[0m \x1b[31m?\x1b[0m \x1b[32m0/7 \x1b[0m \x1b[32m0 of 7 \x1b[0m\r\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2Kworld\ntest foo \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:07\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m10 bytes\x1b[0m \x1b[32m0/10 \x1b[0m \x1b[31m?\x1b[0m \x1b[32m 0/10\x1b[0m \x1b[32m 0 of 10\x1b[0m\n \x1b[32mbytes \x1b[0m \ntest bar \x1b[38;5;237m━━━━━━━━━━\x1b[0m \x1b[36m-:--:--\x1b[0m \x1b[33m0:00:19\x1b[0m \x1b[32m0 bytes\x1b[0m \x1b[32m7 bytes \x1b[0m \x1b[32m0/7 bytes\x1b[0m \x1b[31m?\x1b[0m \x1b[32m0/7 \x1b[0m \x1b[32m0 of 7 \x1b[0m\r\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2Ktest foo \x1b[38;2;114;156;31m━━━━━━\x1b[0m \x1b[36m0:00:…\x1b[0m \x1b[33m0:00:…\x1b[0m \x1b[32m12 \x1b[0m \x1b[32m10 \x1b[0m \x1b[32m12/10 \x1b[0m \x1b[31m1 \x1b[0m \x1b[35m1.3 \x1b[0m \x1b[32m12/10\x1b[0m \x1b[32m12 of \x1b[0m\n \x1b[32mbytes \x1b[0m \x1b[32mbytes \x1b[0m \x1b[32mbytes \x1b[0m \x1b[31mbyte/s\x1b[0m \x1b[35mit/s \x1b[0m \x1b[32m10 \x1b[0m\ntest bar \x1b[38;2;114;156;31m━━━━━━\x1b[0m \x1b[36m0:00:…\x1b[0m \x1b[33m0:00:…\x1b[0m \x1b[32m16 \x1b[0m \x1b[32m7 \x1b[0m \x1b[32m16/7 \x1b[0m \x1b[31m2 \x1b[0m \x1b[35m2.0 \x1b[0m \x1b[32m16/7 \x1b[0m \x1b[32m16 of 7\x1b[0m\n \x1b[32mbytes \x1b[0m \x1b[32mbytes \x1b[0m \x1b[32mbytes \x1b[0m \x1b[31mbytes…\x1b[0m \x1b[35mit/s \x1b[0m \r\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2Ktest foo \x1b[38;2;114;156;31m━━━━━━\x1b[0m \x1b[36m0:00:…\x1b[0m \x1b[33m0:00:…\x1b[0m \x1b[32m12 \x1b[0m \x1b[32m10 \x1b[0m \x1b[32m12/10 \x1b[0m \x1b[31m1 \x1b[0m \x1b[35m1.3 \x1b[0m \x1b[32m12/10\x1b[0m \x1b[32m12 of \x1b[0m\n \x1b[32mbytes \x1b[0m \x1b[32mbytes \x1b[0m \x1b[32mbytes \x1b[0m \x1b[31mbyte/s\x1b[0m \x1b[35mit/s \x1b[0m \x1b[32m10 \x1b[0m\ntest bar \x1b[38;2;114;156;31m━━━━━━\x1b[0m \x1b[36m0:00:…\x1b[0m \x1b[33m0:00:…\x1b[0m \x1b[32m16 \x1b[0m \x1b[32m7 \x1b[0m \x1b[32m16/7 \x1b[0m \x1b[31m2 \x1b[0m \x1b[35m2.0 \x1b[0m \x1b[32m16/7 \x1b[0m \x1b[32m16 of 7\x1b[0m\n \x1b[32mbytes \x1b[0m \x1b[32mbytes \x1b[0m \x1b[32mbytes \x1b[0m \x1b[31mbytes…\x1b[0m \x1b[35mit/s \x1b[0m \n\x1b[?25h\r\x1b[1A\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2K" assert result == expected @@ -661,6 +661,15 @@ def test_task_progress_column_speed() -> None: speed_text = TaskProgressColumn.render_speed(8888888) assert speed_text.plain == "8.9×10⁶ it/s" + speed_text = TaskProgressColumn.render_speed(5, units="Hz") + assert speed_text.plain == "5.0 Hz" + + speed_text = TaskProgressColumn.render_speed(5000, units="Hz") + assert speed_text.plain == "5.0×10³ Hz" + + speed_text = TaskProgressColumn.render_speed(8888888, units="Hz") + assert speed_text.plain == "8.9×10⁶ Hz" + if __name__ == "__main__": _render = render_progress()