Skip to content

Commit 373fca9

Browse files
committed
Upgrade rich to 12.5.1
1 parent 73290af commit 373fca9

34 files changed

+1224
-557
lines changed

news/rich.vendor.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Upgrade rich to 12.5.1

src/pip/_vendor/rich/__init__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Rich text and beautiful formatting in the terminal."""
22

33
import os
4-
from typing import Callable, IO, TYPE_CHECKING, Any, Optional, Union
4+
from typing import IO, TYPE_CHECKING, Any, Callable, Optional, Union
55

66
from ._extension import load_ipython_extension # noqa: F401
77

@@ -13,7 +13,11 @@
1313
# Global console used by alternative print
1414
_console: Optional["Console"] = None
1515

16-
_IMPORT_CWD = os.path.abspath(os.getcwd())
16+
try:
17+
_IMPORT_CWD = os.path.abspath(os.getcwd())
18+
except FileNotFoundError:
19+
# Can happen if the cwd has been deleted
20+
_IMPORT_CWD = ""
1721

1822

1923
def get_console() -> "Console":
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
CONSOLE_HTML_FORMAT = """\
2+
<!DOCTYPE html>
3+
<head>
4+
<meta charset="UTF-8">
5+
<style>
6+
{stylesheet}
7+
body {{
8+
color: {foreground};
9+
background-color: {background};
10+
}}
11+
</style>
12+
</head>
13+
<html>
14+
<body>
15+
<code>
16+
<pre style="font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace">{code}</pre>
17+
</code>
18+
</body>
19+
</html>
20+
"""
21+
22+
CONSOLE_SVG_FORMAT = """\
23+
<svg class="rich-terminal" viewBox="0 0 {width} {height}" xmlns="http://www.w3.org/2000/svg">
24+
<!-- Generated with Rich https://www.textualize.io -->
25+
<style>
26+
27+
@font-face {{
28+
font-family: "Fira Code";
29+
src: local("FiraCode-Regular"),
30+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
31+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
32+
font-style: normal;
33+
font-weight: 400;
34+
}}
35+
@font-face {{
36+
font-family: "Fira Code";
37+
src: local("FiraCode-Bold"),
38+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
39+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
40+
font-style: bold;
41+
font-weight: 700;
42+
}}
43+
44+
.{unique_id}-matrix {{
45+
font-family: Fira Code, monospace;
46+
font-size: {char_height}px;
47+
line-height: {line_height}px;
48+
font-variant-east-asian: full-width;
49+
}}
50+
51+
.{unique_id}-title {{
52+
font-size: 18px;
53+
font-weight: bold;
54+
font-family: arial;
55+
}}
56+
57+
{styles}
58+
</style>
59+
60+
<defs>
61+
<clipPath id="{unique_id}-clip-terminal">
62+
<rect x="0" y="0" width="{terminal_width}" height="{terminal_height}" />
63+
</clipPath>
64+
{lines}
65+
</defs>
66+
67+
{chrome}
68+
<g transform="translate({terminal_x}, {terminal_y})" clip-path="url(#{unique_id}-clip-terminal)">
69+
{backgrounds}
70+
<g class="{unique_id}-matrix">
71+
{matrix}
72+
</g>
73+
</g>
74+
</svg>
75+
"""
76+
77+
_SVG_FONT_FAMILY = "Rich Fira Code"
78+
_SVG_CLASSES_PREFIX = "rich-svg"

src/pip/_vendor/rich/_inspect.py

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
import inspect
44
from inspect import cleandoc, getdoc, getfile, isclass, ismodule, signature
5-
from typing import Any, Iterable, Optional, Tuple
5+
from typing import Any, Collection, Iterable, Optional, Tuple, Type, Union
66

77
from .console import Group, RenderableType
8+
from .control import escape_control_codes
89
from .highlighter import ReprHighlighter
910
from .jupyter import JupyterMixin
1011
from .panel import Panel
@@ -19,12 +20,6 @@ def _first_paragraph(doc: str) -> str:
1920
return paragraph
2021

2122

22-
def _reformat_doc(doc: str) -> str:
23-
"""Reformat docstring."""
24-
doc = cleandoc(doc).strip()
25-
return doc
26-
27-
2823
class Inspect(JupyterMixin):
2924
"""A renderable to inspect any Python Object.
3025
@@ -112,11 +107,13 @@ def _get_signature(self, name: str, obj: Any) -> Optional[Text]:
112107
# If obj is a module, there may be classes (which are callable) to display
113108
if inspect.isclass(obj):
114109
prefix = "class"
110+
elif inspect.iscoroutinefunction(obj):
111+
prefix = "async def"
115112
else:
116113
prefix = "def"
117114

118115
qual_signature = Text.assemble(
119-
(f"{prefix} ", f"inspect.{prefix}"),
116+
(f"{prefix} ", f"inspect.{prefix.replace(' ', '_')}"),
120117
(qualname, "inspect.callable"),
121118
signature_text,
122119
)
@@ -161,11 +158,9 @@ def safe_getattr(attr_name: str) -> Tuple[Any, Any]:
161158
yield ""
162159

163160
if self.docs:
164-
_doc = getdoc(obj)
161+
_doc = self._get_formatted_doc(obj)
165162
if _doc is not None:
166-
if not self.help:
167-
_doc = _first_paragraph(_doc)
168-
doc_text = Text(_reformat_doc(_doc), style="inspect.help")
163+
doc_text = Text(_doc, style="inspect.help")
169164
doc_text = highlighter(doc_text)
170165
yield doc_text
171166
yield ""
@@ -200,13 +195,10 @@ def safe_getattr(attr_name: str) -> Tuple[Any, Any]:
200195
add_row(key_text, Pretty(value, highlighter=highlighter))
201196
else:
202197
if self.docs:
203-
docs = getdoc(value)
198+
docs = self._get_formatted_doc(value)
204199
if docs is not None:
205-
_doc = _reformat_doc(str(docs))
206-
if not self.help:
207-
_doc = _first_paragraph(_doc)
208-
_signature_text.append("\n" if "\n" in _doc else " ")
209-
doc = highlighter(_doc)
200+
_signature_text.append("\n" if "\n" in docs else " ")
201+
doc = highlighter(docs)
210202
doc.stylize("inspect.doc")
211203
_signature_text.append(doc)
212204

@@ -220,3 +212,59 @@ def safe_getattr(attr_name: str) -> Tuple[Any, Any]:
220212
f"[b cyan]{not_shown_count}[/][i] attribute(s) not shown.[/i] "
221213
f"Run [b][magenta]inspect[/]([not b]inspect[/])[/b] for options."
222214
)
215+
216+
def _get_formatted_doc(self, object_: Any) -> Optional[str]:
217+
"""
218+
Extract the docstring of an object, process it and returns it.
219+
The processing consists in cleaning up the doctring's indentation,
220+
taking only its 1st paragraph if `self.help` is not True,
221+
and escape its control codes.
222+
223+
Args:
224+
object_ (Any): the object to get the docstring from.
225+
226+
Returns:
227+
Optional[str]: the processed docstring, or None if no docstring was found.
228+
"""
229+
docs = getdoc(object_)
230+
if docs is None:
231+
return None
232+
docs = cleandoc(docs).strip()
233+
if not self.help:
234+
docs = _first_paragraph(docs)
235+
return escape_control_codes(docs)
236+
237+
238+
def get_object_types_mro(obj: Union[object, Type[Any]]) -> Tuple[type, ...]:
239+
"""Returns the MRO of an object's class, or of the object itself if it's a class."""
240+
if not hasattr(obj, "__mro__"):
241+
# N.B. we cannot use `if type(obj) is type` here because it doesn't work with
242+
# some types of classes, such as the ones that use abc.ABCMeta.
243+
obj = type(obj)
244+
return getattr(obj, "__mro__", ())
245+
246+
247+
def get_object_types_mro_as_strings(obj: object) -> Collection[str]:
248+
"""
249+
Returns the MRO of an object's class as full qualified names, or of the object itself if it's a class.
250+
251+
Examples:
252+
`object_types_mro_as_strings(JSONDecoder)` will return `['json.decoder.JSONDecoder', 'builtins.object']`
253+
"""
254+
return [
255+
f'{getattr(type_, "__module__", "")}.{getattr(type_, "__qualname__", "")}'
256+
for type_ in get_object_types_mro(obj)
257+
]
258+
259+
260+
def is_object_one_of_types(
261+
obj: object, fully_qualified_types_names: Collection[str]
262+
) -> bool:
263+
"""
264+
Returns `True` if the given object's class (or the object itself, if it's a class) has one of the
265+
fully qualified names in its MRO.
266+
"""
267+
for type_name in get_object_types_mro_as_strings(obj):
268+
if type_name in fully_qualified_types_names:
269+
return True
270+
return False

src/pip/_vendor/rich/_lru_cache.py

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/pip/_vendor/rich/_win32_console.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,30 @@ def SetConsoleCursorPosition(
263263
return bool(_SetConsoleCursorPosition(std_handle, coords))
264264

265265

266+
_GetConsoleCursorInfo = windll.kernel32.GetConsoleCursorInfo
267+
_GetConsoleCursorInfo.argtypes = [
268+
wintypes.HANDLE,
269+
ctypes.POINTER(CONSOLE_CURSOR_INFO),
270+
]
271+
_GetConsoleCursorInfo.restype = wintypes.BOOL
272+
273+
274+
def GetConsoleCursorInfo(
275+
std_handle: wintypes.HANDLE, cursor_info: CONSOLE_CURSOR_INFO
276+
) -> bool:
277+
"""Get the cursor info - used to get cursor visibility and width
278+
279+
Args:
280+
std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.
281+
cursor_info (CONSOLE_CURSOR_INFO): CONSOLE_CURSOR_INFO ctype struct that receives information
282+
about the console's cursor.
283+
284+
Returns:
285+
bool: True if the function succeeds, otherwise False.
286+
"""
287+
return bool(_GetConsoleCursorInfo(std_handle, byref(cursor_info)))
288+
289+
266290
_SetConsoleCursorInfo = windll.kernel32.SetConsoleCursorInfo
267291
_SetConsoleCursorInfo.argtypes = [
268292
wintypes.HANDLE,
@@ -523,12 +547,14 @@ def move_cursor_backward(self) -> None:
523547

524548
def hide_cursor(self) -> None:
525549
"""Hide the cursor"""
526-
invisible_cursor = CONSOLE_CURSOR_INFO(dwSize=100, bVisible=0)
550+
current_cursor_size = self._get_cursor_size()
551+
invisible_cursor = CONSOLE_CURSOR_INFO(dwSize=current_cursor_size, bVisible=0)
527552
SetConsoleCursorInfo(self._handle, cursor_info=invisible_cursor)
528553

529554
def show_cursor(self) -> None:
530555
"""Show the cursor"""
531-
visible_cursor = CONSOLE_CURSOR_INFO(dwSize=100, bVisible=1)
556+
current_cursor_size = self._get_cursor_size()
557+
visible_cursor = CONSOLE_CURSOR_INFO(dwSize=current_cursor_size, bVisible=1)
532558
SetConsoleCursorInfo(self._handle, cursor_info=visible_cursor)
533559

534560
def set_title(self, title: str) -> None:
@@ -540,6 +566,12 @@ def set_title(self, title: str) -> None:
540566
assert len(title) < 255, "Console title must be less than 255 characters"
541567
SetConsoleTitle(title)
542568

569+
def _get_cursor_size(self) -> int:
570+
"""Get the percentage of the character cell that is filled by the cursor"""
571+
cursor_info = CONSOLE_CURSOR_INFO()
572+
GetConsoleCursorInfo(self._handle, cursor_info=cursor_info)
573+
return int(cursor_info.dwSize)
574+
543575

544576
if __name__ == "__main__":
545577
handle = GetStdHandle()

src/pip/_vendor/rich/_windows_renderer.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,6 @@ def legacy_windows_render(buffer: Iterable[Segment], term: LegacyWindowsTerm) ->
5151
term.erase_start_of_line()
5252
elif mode == 2:
5353
term.erase_line()
54+
elif control_type == ControlType.SET_WINDOW_TITLE:
55+
_, title = cast(Tuple[ControlType, str], control_code)
56+
term.set_title(title)

src/pip/_vendor/rich/_wrap.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import re
22
from typing import Iterable, List, Tuple
33

4-
from .cells import cell_len, chop_cells
54
from ._loop import loop_last
5+
from .cells import cell_len, chop_cells
66

77
re_word = re.compile(r"\s*\S+\s*")
88

@@ -27,14 +27,15 @@ def divide_line(text: str, width: int, fold: bool = True) -> List[int]:
2727
if line_position + word_length > width:
2828
if word_length > width:
2929
if fold:
30-
for last, line in loop_last(
31-
chop_cells(word, width, position=line_position)
32-
):
30+
chopped_words = chop_cells(word, max_size=width, position=0)
31+
for last, line in loop_last(chopped_words):
32+
if start:
33+
append(start)
34+
3335
if last:
3436
line_position = _cell_len(line)
3537
else:
3638
start += len(line)
37-
append(start)
3839
else:
3940
if start:
4041
append(start)

0 commit comments

Comments
 (0)