From 56227ab3838e8f746654a4e484fcca8ff135555e Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 1 Apr 2022 14:17:21 +0100 Subject: [PATCH 1/4] docs for new progress feature --- docs/source/progress.rst | 39 ++++++++++++++++++++------------------- examples/cp_progress.py | 28 ++++------------------------ 2 files changed, 24 insertions(+), 43 deletions(-) diff --git a/docs/source/progress.rst b/docs/source/progress.rst index f905b255e..9a739f864 100644 --- a/docs/source/progress.rst +++ b/docs/source/progress.rst @@ -212,37 +212,38 @@ If the :class:`~rich.progress.Progress` class doesn't offer exactly what you nee Reading from a file ~~~~~~~~~~~~~~~~~~~ -You can obtain a progress-tracking reader using the :meth:`~rich.progress.Progress.open` method by giving it a path. You can specify the number of bytes to be read, but by default :meth:`~rich.progress.Progress.open` will query the size of the file with :func:`os.stat`. You are responsible for closing the file, and you should consider using a *context* to make sure it is closed :: +Rich provides an easy way to generate a progress bar for reading a file. If you call :func:`~rich.progress.open` it will return a context manager which displays a progress bar while you read. + +The following example shows how we might show progress for reading a JSON file:: import json - from rich.progress import Progress + import rich.progress - with Progress() as progress: - with progress.open("data.json", "rb") as file: - json.load(file) + with rich.progress.open("data.json", "rb") as file: + data = json.load(file) + print(data) +If you already have a file object, you can call :func:`~rich.progress.wrap_file` which returns a context manager that wraps your file so that it generates a progress bar. If you use this function you will need to set the number of bytes or characters you expect to read. -Note that in the above snippet we use the `"rb"` mode, because we needed the file to be opened in binary mode to pass it to :func:`json.load`. If the API consuming the file is expecting an object in *text mode* (for instance, :func:`csv.reader`), you can open the file with the `"r"` mode, which happens to be the default :: +Here's an example that reads a url from the internet:: - from rich.progress import Progress + from time import sleep + from urllib.request import urlopen - with Progress() as progress: - with progress.open("README.md") as file: - for line in file: - print(line) + from rich.progress import wrap_file + response = urlopen("https://www.textualize.io") + size = int(response.headers["Content-Length"]) -Reading from a file-like object -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + with wrap_file(response, size) as file: + for line in file: + print(line.decode("utf-8"), end="") + sleep(0.1) -You can obtain a progress-tracking reader wrapping a file-like object using the :meth:`~rich.progress.Progress.wrap_file` method. The file-like object must be in *binary mode*, and a total must be provided, unless it was provided to a :class:`~rich.progress.Task` created beforehand. The returned reader may be used in a context, but will not take care of closing the wrapped file :: - import json - from rich.progress import Progress +If you expect to be reading from multiple files, you can use :meth:`~rich.progress.Progress.open` or :meth:`~rich.progress.Progress.wrap_file` to add a file progress to an existing Progress instance. - with Progress() as progress: - with open("data.json", "rb") as file: - json.load(progress.wrap_file(file, total=2048)) +See `cp_progress.py ` for a minimal clone of the ``cp`` command which shows a progress bar as the file is copied. Multiple Progress diff --git a/examples/cp_progress.py b/examples/cp_progress.py index 0f4059d02..b5cc4c818 100644 --- a/examples/cp_progress.py +++ b/examples/cp_progress.py @@ -5,35 +5,15 @@ import shutil import sys -from rich.progress import ( - BarColumn, - DownloadColumn, - Progress, - TaskID, - TextColumn, - TimeRemainingColumn, - TransferSpeedColumn, -) - -progress = Progress( - TextColumn("[bold blue]{task.description}", justify="right"), - BarColumn(bar_width=None), - "[progress.percentage]{task.percentage:>3.1f}%", - "•", - DownloadColumn(), - "•", - TransferSpeedColumn(), - "•", - TimeRemainingColumn(), -) +from rich.progress import Progress if __name__ == "__main__": if len(sys.argv) == 3: - - with progress: + with Progress() as progress: desc = os.path.basename(sys.argv[1]) - with progress.read(sys.argv[1], description=desc) as src: + with progress.open(sys.argv[1], "rb", description=desc) as src: with open(sys.argv[2], "wb") as dst: shutil.copyfileobj(src, dst) else: + print("Copy a file with a progress bar.") print("Usage:\n\tpython cp_progress.py SRC DST") From 8745ee5a1139fc101a382e4b178c89b432c487e3 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 1 Apr 2022 14:49:02 +0100 Subject: [PATCH 2/4] progress docs --- docs/source/progress.rst | 4 ++-- examples/file_progress.py | 16 ++++++++++++++++ examples/save_table_svg.py | 26 ++++++++++++++++++++++++++ rich/console.py | 2 +- 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 examples/file_progress.py create mode 100644 examples/save_table_svg.py diff --git a/docs/source/progress.rst b/docs/source/progress.rst index 9a739f864..59813a473 100644 --- a/docs/source/progress.rst +++ b/docs/source/progress.rst @@ -212,7 +212,7 @@ If the :class:`~rich.progress.Progress` class doesn't offer exactly what you nee Reading from a file ~~~~~~~~~~~~~~~~~~~ -Rich provides an easy way to generate a progress bar for reading a file. If you call :func:`~rich.progress.open` it will return a context manager which displays a progress bar while you read. +Rich provides an easy way to generate a progress bar for reading a file. If you call :func:`~rich.progress.open` it will return a context manager which displays a progress bar while you read. This is particularly useful when you can't easily modify the code that does the reading. The following example shows how we might show progress for reading a JSON file:: @@ -223,7 +223,7 @@ The following example shows how we might show progress for reading a JSON file:: data = json.load(file) print(data) -If you already have a file object, you can call :func:`~rich.progress.wrap_file` which returns a context manager that wraps your file so that it generates a progress bar. If you use this function you will need to set the number of bytes or characters you expect to read. +If you already have a file object, you can call :func:`~rich.progress.wrap_file` which returns a context manager that wraps your file so that it displays a progress bar. If you use this function you will need to set the number of bytes or characters you expect to read. Here's an example that reads a url from the internet:: diff --git a/examples/file_progress.py b/examples/file_progress.py new file mode 100644 index 000000000..fd18d7537 --- /dev/null +++ b/examples/file_progress.py @@ -0,0 +1,16 @@ +from time import sleep +from urllib.request import urlopen + +from rich.progress import wrap_file + +# Read a URL with urlopen +response = urlopen("https://www.textualize.io") +# Get the size from the headers +size = int(response.headers["Content-Length"]) + +# Wrap the response so that it update progress + +with wrap_file(response, size) as file: + for line in file: + print(line.decode("utf-8"), end="") + sleep(0.1) diff --git a/examples/save_table_svg.py b/examples/save_table_svg.py new file mode 100644 index 000000000..e22aee22b --- /dev/null +++ b/examples/save_table_svg.py @@ -0,0 +1,26 @@ +""" +Demonstrates how to export a SVG +""" + +from rich.console import Console +from rich.table import Table + +table = Table(title="Star Wars Movies") + +table.add_column("Released", style="cyan", no_wrap=True) +table.add_column("Title", style="magenta") +table.add_column("Box Office", justify="right", style="green") + +table.add_row("Dec 20, 2019", "Star Wars: The Rise of Skywalker", "$952,110,690") +table.add_row("May 25, 2018", "Solo: A Star Wars Story", "$393,151,347") +table.add_row("Dec 15, 2017", "Star Wars Ep. V111: The Last Jedi", "$1,332,539,889") +table.add_row("Dec 16, 2016", "Rogue One: A Star Wars Story", "$1,332,439,889") + +console = Console(record=True) +console.print(table, justify="center") +console.save_svg("table.svg", title="save_table_svg.py") + +import os +import webbrowser + +webbrowser.open(f"file://{os.path.abspath('table.svg')}") diff --git a/rich/console.py b/rich/console.py index bcacbc738..2cdab4280 100644 --- a/rich/console.py +++ b/rich/console.py @@ -2350,7 +2350,7 @@ def export_svg( ) ) - fragments = [] + fragments: List[str] = [] theme_foreground_color = _theme.foreground_color.hex theme_background_color = _theme.background_color.hex From 8dd183755466bb62b08b8f3fa8ef7264961bb3c9 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 3 Apr 2022 14:27:54 +0100 Subject: [PATCH 3/4] changelog --- CHANGELOG.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bbe127ea..342792199 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,14 +5,11 @@ 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). -## 12.1.0 +## [12.1.0] - 2022-04-03 ### Added - Progress.open and Progress.wrap_file method to track the progress while reading from a file or file-like object https://github.com/willmcgugan/rich/pull/1759 - -### Added - - SVG export functionality https://github.com/Textualize/rich/pull/2101 ### Fixed From d852cd144c3bc047f874d1e534758dbcd3f1241e Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 3 Apr 2022 14:30:44 +0100 Subject: [PATCH 4/4] version bump --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c9f22e5cc..45bb0749c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "rich" homepage = "https://github.com/willmcgugan/rich" documentation = "https://rich.readthedocs.io/en/latest/" -version = "12.0.1" +version = "12.1.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" authors = ["Will McGugan "] license = "MIT"