Skip to content

Commit a47fc78

Browse files
committed
Upgrade rich to 11.0.0
1 parent 388af2d commit a47fc78

21 files changed

+742
-391
lines changed

news/rich.vendor.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Add rich 10.14.0 as a vendored dependency.
1+
Upgrade rich to 11.0.0

src/pip/_vendor/rich/__main__.py

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,7 @@
44

55
from pip._vendor.rich import box
66
from pip._vendor.rich.color import Color
7-
from pip._vendor.rich.console import (
8-
Console,
9-
ConsoleOptions,
10-
Group,
11-
RenderResult,
12-
RenderableType,
13-
)
7+
from pip._vendor.rich.console import Console, ConsoleOptions, Group, RenderableType, RenderResult
148
from pip._vendor.rich.markdown import Markdown
159
from pip._vendor.rich.measure import Measurement
1610
from pip._vendor.rich.pretty import Pretty
@@ -222,7 +216,10 @@ def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]:
222216
test_card = make_test_card()
223217

224218
# Print once to warm cache
219+
start = process_time()
225220
console.print(test_card)
221+
pre_cache_taken = round((process_time() - start) * 1000.0, 1)
222+
226223
console.file = io.StringIO()
227224

228225
start = process_time()
@@ -234,7 +231,8 @@ def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]:
234231
for line in text.splitlines(True):
235232
print(line, end="")
236233

237-
print(f"rendered in {taken}ms")
234+
print(f"rendered in {pre_cache_taken}ms (cold cache)")
235+
print(f"rendered in {taken}ms (warm cache)")
238236

239237
from pip._vendor.rich.panel import Panel
240238

@@ -243,13 +241,10 @@ def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]:
243241
sponsor_message = Table.grid(padding=1)
244242
sponsor_message.add_column(style="green", justify="right")
245243
sponsor_message.add_column(no_wrap=True)
244+
246245
sponsor_message.add_row(
247-
"Sponsor me",
248-
"[u blue link=https://github.com/sponsors/willmcgugan]https://github.com/sponsors/willmcgugan",
249-
)
250-
sponsor_message.add_row(
251-
"Buy me a :coffee:",
252-
"[u blue link=https://ko-fi.com/willmcgugan]https://ko-fi.com/willmcgugan",
246+
"Buy devs a :coffee:",
247+
"[u blue link=https://ko-fi.com/textualize]https://ko-fi.com/textualize",
253248
)
254249
sponsor_message.add_row(
255250
"Twitter",
@@ -261,9 +256,9 @@ def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]:
261256

262257
intro_message = Text.from_markup(
263258
"""\
264-
It takes a lot of time to develop Rich and to provide support.
259+
We hope you enjoy using Rich!
265260
266-
Consider supporting my work via Github Sponsors (ask your company / organization), or buy me a coffee to say thanks.
261+
Rich is maintained with :heart: by [link=https://www.textualize.io]Textualize.io[/]
267262
268263
- Will McGugan"""
269264
)

src/pip/_vendor/rich/_windows.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import sys
2-
32
from dataclasses import dataclass
43

54

@@ -15,8 +14,7 @@ class WindowsConsoleFeatures:
1514

1615
try:
1716
import ctypes
18-
from ctypes import wintypes
19-
from ctypes import LibraryLoader
17+
from ctypes import LibraryLoader, wintypes
2018

2119
if sys.platform == "win32":
2220
windll = LibraryLoader(ctypes.WinDLL)
@@ -30,7 +28,6 @@ def get_windows_console_features() -> WindowsConsoleFeatures:
3028
features = WindowsConsoleFeatures()
3129
return features
3230

33-
3431
else:
3532

3633
STDOUT = -11

src/pip/_vendor/rich/cells.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
from functools import lru_cache
2+
import re
23
from typing import Dict, List
34

45
from ._cell_widths import CELL_WIDTHS
56
from ._lru_cache import LRUCache
67

8+
# Regex to match sequence of the most common character ranges
9+
_is_single_cell_widths = re.compile("^[\u0020-\u006f\u00a0\u02ff\u0370-\u0482]*$").match
10+
711

812
def cell_len(text: str, _cache: Dict[str, int] = LRUCache(1024 * 4)) -> int:
913
"""Get the number of cells required to display text.
@@ -12,16 +16,19 @@ def cell_len(text: str, _cache: Dict[str, int] = LRUCache(1024 * 4)) -> int:
1216
text (str): Text to display.
1317
1418
Returns:
15-
int: Number of cells required to display the text.
19+
int: Get the number of cells required to display text.
1620
"""
17-
cached_result = _cache.get(text, None)
18-
if cached_result is not None:
19-
return cached_result
20-
21-
_get_size = get_character_cell_size
22-
total_size = sum(_get_size(character) for character in text)
23-
if len(text) <= 64:
24-
_cache[text] = total_size
21+
22+
if _is_single_cell_widths(text):
23+
return len(text)
24+
else:
25+
cached_result = _cache.get(text, None)
26+
if cached_result is not None:
27+
return cached_result
28+
_get_size = get_character_cell_size
29+
total_size = sum(_get_size(character) for character in text)
30+
if len(text) <= 64:
31+
_cache[text] = total_size
2532
return total_size
2633

2734

@@ -35,12 +42,10 @@ def get_character_cell_size(character: str) -> int:
3542
Returns:
3643
int: Number of cells (0, 1 or 2) occupied by that character.
3744
"""
38-
39-
codepoint = ord(character)
40-
if 127 > codepoint > 31:
41-
# Shortcut for ascii
45+
if _is_single_cell_widths(character):
4246
return 1
43-
return _get_codepoint_cell_size(codepoint)
47+
48+
return _get_codepoint_cell_size(ord(character))
4449

4550

4651
@lru_cache(maxsize=4096)
@@ -74,6 +79,13 @@ def _get_codepoint_cell_size(codepoint: int) -> int:
7479

7580
def set_cell_size(text: str, total: int) -> str:
7681
"""Set the length of a string to fit within given number of cells."""
82+
83+
if _is_single_cell_widths(text):
84+
size = len(text)
85+
if size < total:
86+
return text + " " * (total - size)
87+
return text[:total]
88+
7789
if not total:
7890
return ""
7991
cell_size = cell_len(text)

src/pip/_vendor/rich/console.py

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import inspect
22
import os
33
import platform
4-
import shutil
54
import sys
65
import threading
76
from abc import ABC, abstractmethod
@@ -12,8 +11,9 @@
1211
from html import escape
1312
from inspect import isclass
1413
from itertools import islice
14+
from threading import RLock
1515
from time import monotonic
16-
from types import FrameType, TracebackType, ModuleType
16+
from types import FrameType, ModuleType, TracebackType
1717
from typing import (
1818
IO,
1919
TYPE_CHECKING,
@@ -25,7 +25,6 @@
2525
Mapping,
2626
NamedTuple,
2727
Optional,
28-
Set,
2928
TextIO,
3029
Tuple,
3130
Type,
@@ -212,6 +211,19 @@ def update_width(self, width: int) -> "ConsoleOptions":
212211
options.min_width = options.max_width = max(0, width)
213212
return options
214213

214+
def update_height(self, height: int) -> "ConsoleOptions":
215+
"""Update the height, and return a copy.
216+
217+
Args:
218+
height (int): New height
219+
220+
Returns:
221+
~ConsoleOptions: New Console options instance.
222+
"""
223+
options = self.copy()
224+
options.max_height = options.height = height
225+
return options
226+
215227
def update_dimensions(self, width: int, height: int) -> "ConsoleOptions":
216228
"""Update the width and height, and return a copy.
217229
@@ -224,8 +236,7 @@ def update_dimensions(self, width: int, height: int) -> "ConsoleOptions":
224236
"""
225237
options = self.copy()
226238
options.min_width = options.max_width = max(0, width)
227-
options.height = height
228-
options.max_height = height
239+
options.height = options.max_height = height
229240
return options
230241

231242

@@ -247,11 +258,12 @@ def __rich_console__(
247258
...
248259

249260

261+
# A type that may be rendered by Console.
250262
RenderableType = Union[ConsoleRenderable, RichCast, str]
251-
"""A type that may be rendered by Console."""
252263

264+
265+
# The result of calling a __rich_console__ method.
253266
RenderResult = Iterable[Union[RenderableType, Segment]]
254-
"""The result of calling a __rich_console__ method."""
255267

256268

257269
_null_highlighter = NullHighlighter()
@@ -464,9 +476,6 @@ def __rich_console__(
464476
yield from self.renderables
465477

466478

467-
RenderGroup = Group # TODO: deprecate at some point
468-
469-
470479
def group(fit: bool = True) -> Callable[..., Callable[..., Group]]:
471480
"""A decorator that turns an iterable of renderables in to a group.
472481
@@ -477,7 +486,7 @@ def group(fit: bool = True) -> Callable[..., Callable[..., Group]]:
477486
def decorator(
478487
method: Callable[..., Iterable[RenderableType]]
479488
) -> Callable[..., Group]:
480-
"""Convert a method that returns an iterable of renderables in to a RenderGroup."""
489+
"""Convert a method that returns an iterable of renderables in to a Group."""
481490

482491
@wraps(method)
483492
def _replace(*args: Any, **kwargs: Any) -> Group:
@@ -489,9 +498,6 @@ def _replace(*args: Any, **kwargs: Any) -> Group:
489498
return decorator
490499

491500

492-
render_group = group
493-
494-
495501
def _is_jupyter() -> bool: # pragma: no cover
496502
"""Check if we're running in a Jupyter notebook."""
497503
try:
@@ -813,12 +819,13 @@ def push_render_hook(self, hook: RenderHook) -> None:
813819
Args:
814820
hook (RenderHook): Render hook instance.
815821
"""
816-
817-
self._render_hooks.append(hook)
822+
with self._lock:
823+
self._render_hooks.append(hook)
818824

819825
def pop_render_hook(self) -> None:
820826
"""Pop the last renderhook from the stack."""
821-
self._render_hooks.pop()
827+
with self._lock:
828+
self._render_hooks.pop()
822829

823830
def __enter__(self) -> "Console":
824831
"""Own context manager to enter buffer context."""
@@ -1495,9 +1502,8 @@ def control(self, *control: Control) -> None:
14951502
control_codes (str): Control codes, such as those that may move the cursor.
14961503
"""
14971504
if not self.is_dumb_terminal:
1498-
for _control in control:
1499-
self._buffer.append(_control.segment)
1500-
self._check_buffer()
1505+
with self:
1506+
self._buffer.extend(_control.segment for _control in control)
15011507

15021508
def out(
15031509
self,
@@ -1579,7 +1585,7 @@ def print(
15791585
if overflow is None:
15801586
overflow = "ignore"
15811587
crop = False
1582-
1588+
render_hooks = self._render_hooks[:]
15831589
with self:
15841590
renderables = self._collect_renderables(
15851591
objects,
@@ -1590,7 +1596,7 @@ def print(
15901596
markup=markup,
15911597
highlight=highlight,
15921598
)
1593-
for hook in self._render_hooks:
1599+
for hook in render_hooks:
15941600
renderables = hook.process_renderables(renderables)
15951601
render_options = self.options.update(
15961602
justify=justify,
@@ -1847,6 +1853,8 @@ def log(
18471853
if not objects:
18481854
objects = (NewLine(),)
18491855

1856+
render_hooks = self._render_hooks[:]
1857+
18501858
with self:
18511859
renderables = self._collect_renderables(
18521860
objects,
@@ -1881,7 +1889,7 @@ def log(
18811889
link_path=link_path,
18821890
)
18831891
]
1884-
for hook in self._render_hooks:
1892+
for hook in render_hooks:
18851893
renderables = hook.process_renderables(renderables)
18861894
new_segments: List[Segment] = []
18871895
extend = new_segments.extend

src/pip/_vendor/rich/default_styles.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,27 @@
157157
"markdown.link": Style(color="bright_blue"),
158158
"markdown.link_url": Style(color="blue"),
159159
}
160+
161+
162+
if __name__ == "__main__": # pragma: no cover
163+
import argparse
164+
import io
165+
166+
from pip._vendor.rich.console import Console
167+
from pip._vendor.rich.table import Table
168+
from pip._vendor.rich.text import Text
169+
170+
parser = argparse.ArgumentParser()
171+
parser.add_argument("--html", action="store_true", help="Export as HTML table")
172+
args = parser.parse_args()
173+
html: bool = args.html
174+
console = Console(record=True, width=70, file=io.StringIO()) if html else Console()
175+
176+
table = Table("Name", "Styling")
177+
178+
for style_name, style in DEFAULT_STYLES.items():
179+
table.add_row(Text(style_name, style=style), str(style))
180+
181+
console.print(table)
182+
if html:
183+
print(console.export_html(inline_styles=True))

src/pip/_vendor/rich/file_proxy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def write(self, text: str) -> int:
4444
output = Text("\n").join(
4545
self.__ansi_decoder.decode_line(line) for line in lines
4646
)
47-
console.print(output, markup=False, emoji=False, highlight=False)
47+
console.print(output)
4848
return len(text)
4949

5050
def flush(self) -> None:

src/pip/_vendor/rich/jupyter.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from .segment import Segment
55
from .terminal_theme import DEFAULT_TERMINAL_THEME
66

7-
87
JUPYTER_HTML_FORMAT = """\
98
<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace">{code}</pre>
109
"""
@@ -75,11 +74,16 @@ def escape(text: str) -> str:
7574

7675
def display(segments: Iterable[Segment], text: str) -> None:
7776
"""Render segments to Jupyter."""
78-
from IPython.display import display as ipython_display
79-
8077
html = _render_segments(segments)
8178
jupyter_renderable = JupyterRenderable(html, text)
82-
ipython_display(jupyter_renderable)
79+
try:
80+
from IPython.display import display as ipython_display
81+
82+
ipython_display(jupyter_renderable)
83+
except ModuleNotFoundError:
84+
# Handle the case where the Console has force_jupyter=True,
85+
# but IPython is not installed.
86+
pass
8387

8488

8589
def print(*args: Any, **kwargs: Any) -> None:

0 commit comments

Comments
 (0)