Skip to content

Commit 489fafc

Browse files
authored
Merge pull request #2141 from Textualize/progress-docs
Progress docs
2 parents 6b9adfa + d852cd1 commit 489fafc

File tree

6 files changed

+68
-48
lines changed

6 files changed

+68
-48
lines changed

CHANGELOG.md

+1-4
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,11 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## 12.1.0
8+
## [12.1.0] - 2022-04-03
99

1010
### Added
1111

1212
- 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
13-
14-
### Added
15-
1613
- SVG export functionality https://github.com/Textualize/rich/pull/2101
1714

1815
### Fixed

docs/source/progress.rst

+20-19
Original file line numberDiff line numberDiff line change
@@ -212,37 +212,38 @@ If the :class:`~rich.progress.Progress` class doesn't offer exactly what you nee
212212
Reading from a file
213213
~~~~~~~~~~~~~~~~~~~
214214

215-
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 ::
215+
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.
216+
217+
The following example shows how we might show progress for reading a JSON file::
216218

217219
import json
218-
from rich.progress import Progress
220+
import rich.progress
219221

220-
with Progress() as progress:
221-
with progress.open("data.json", "rb") as file:
222-
json.load(file)
222+
with rich.progress.open("data.json", "rb") as file:
223+
data = json.load(file)
224+
print(data)
223225

226+
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.
224227

225-
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 ::
228+
Here's an example that reads a url from the internet::
226229

227-
from rich.progress import Progress
230+
from time import sleep
231+
from urllib.request import urlopen
228232

229-
with Progress() as progress:
230-
with progress.open("README.md") as file:
231-
for line in file:
232-
print(line)
233+
from rich.progress import wrap_file
233234

235+
response = urlopen("https://www.textualize.io")
236+
size = int(response.headers["Content-Length"])
234237

235-
Reading from a file-like object
236-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
238+
with wrap_file(response, size) as file:
239+
for line in file:
240+
print(line.decode("utf-8"), end="")
241+
sleep(0.1)
237242

238-
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 ::
239243

240-
import json
241-
from rich.progress import Progress
244+
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.
242245

243-
with Progress() as progress:
244-
with open("data.json", "rb") as file:
245-
json.load(progress.wrap_file(file, total=2048))
246+
See `cp_progress.py <https://github.com/willmcgugan/rich/blob/master/examples/cp_progress.py>` for a minimal clone of the ``cp`` command which shows a progress bar as the file is copied.
246247

247248

248249
Multiple Progress

examples/cp_progress.py

+4-24
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,15 @@
55
import shutil
66
import sys
77

8-
from rich.progress import (
9-
BarColumn,
10-
DownloadColumn,
11-
Progress,
12-
TaskID,
13-
TextColumn,
14-
TimeRemainingColumn,
15-
TransferSpeedColumn,
16-
)
17-
18-
progress = Progress(
19-
TextColumn("[bold blue]{task.description}", justify="right"),
20-
BarColumn(bar_width=None),
21-
"[progress.percentage]{task.percentage:>3.1f}%",
22-
"•",
23-
DownloadColumn(),
24-
"•",
25-
TransferSpeedColumn(),
26-
"•",
27-
TimeRemainingColumn(),
28-
)
8+
from rich.progress import Progress
299

3010
if __name__ == "__main__":
3111
if len(sys.argv) == 3:
32-
33-
with progress:
12+
with Progress() as progress:
3413
desc = os.path.basename(sys.argv[1])
35-
with progress.read(sys.argv[1], description=desc) as src:
14+
with progress.open(sys.argv[1], "rb", description=desc) as src:
3615
with open(sys.argv[2], "wb") as dst:
3716
shutil.copyfileobj(src, dst)
3817
else:
18+
print("Copy a file with a progress bar.")
3919
print("Usage:\n\tpython cp_progress.py SRC DST")

examples/file_progress.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from time import sleep
2+
from urllib.request import urlopen
3+
4+
from rich.progress import wrap_file
5+
6+
# Read a URL with urlopen
7+
response = urlopen("https://www.textualize.io")
8+
# Get the size from the headers
9+
size = int(response.headers["Content-Length"])
10+
11+
# Wrap the response so that it update progress
12+
13+
with wrap_file(response, size) as file:
14+
for line in file:
15+
print(line.decode("utf-8"), end="")
16+
sleep(0.1)

examples/save_table_svg.py

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""
2+
Demonstrates how to export a SVG
3+
"""
4+
5+
from rich.console import Console
6+
from rich.table import Table
7+
8+
table = Table(title="Star Wars Movies")
9+
10+
table.add_column("Released", style="cyan", no_wrap=True)
11+
table.add_column("Title", style="magenta")
12+
table.add_column("Box Office", justify="right", style="green")
13+
14+
table.add_row("Dec 20, 2019", "Star Wars: The Rise of Skywalker", "$952,110,690")
15+
table.add_row("May 25, 2018", "Solo: A Star Wars Story", "$393,151,347")
16+
table.add_row("Dec 15, 2017", "Star Wars Ep. V111: The Last Jedi", "$1,332,539,889")
17+
table.add_row("Dec 16, 2016", "Rogue One: A Star Wars Story", "$1,332,439,889")
18+
19+
console = Console(record=True)
20+
console.print(table, justify="center")
21+
console.save_svg("table.svg", title="save_table_svg.py")
22+
23+
import os
24+
import webbrowser
25+
26+
webbrowser.open(f"file://{os.path.abspath('table.svg')}")

rich/console.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2350,7 +2350,7 @@ def export_svg(
23502350
)
23512351
)
23522352

2353-
fragments = []
2353+
fragments: List[str] = []
23542354
theme_foreground_color = _theme.foreground_color.hex
23552355
theme_background_color = _theme.background_color.hex
23562356

0 commit comments

Comments
 (0)