Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .venv/lib/python3.11/site-packages/pip/_vendor/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/__pycache__/six.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/__init__.py +7 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/ansi.py +102 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/ansitowin32.py +277 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/initialise.py +121 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__init__.py +1 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__pycache__/ansi_test.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__pycache__/ansitowin32_test.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__pycache__/initialise_test.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__pycache__/isatty_test.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__pycache__/utils.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__pycache__/winterm_test.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/ansi_test.py +76 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/ansitowin32_test.py +294 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/initialise_test.py +189 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/isatty_test.py +57 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/utils.py +49 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/winterm_test.py +131 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/win32.py +180 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/colorama/winterm.py +195 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-311.pyc +0 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/__main__.py +274 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/_export_format.py +76 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/_extension.py +10 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/_fileno.py +24 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/_inspect.py +270 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/_log_render.py +94 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/_loop.py +43 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/_null_file.py +69 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/_pick.py +17 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/_timer.py +19 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/_win32_console.py +662 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/_windows.py +72 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/abc.py +33 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/align.py +311 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/bar.py +94 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/box.py +517 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/cells.py +154 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/columns.py +187 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/containers.py +167 -0
- .venv/lib/python3.11/site-packages/pip/_vendor/rich/default_styles.py +190 -0
.venv/lib/python3.11/site-packages/pip/_vendor/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (5.66 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/__pycache__/six.cpython-311.pyc
ADDED
|
Binary file (46.4 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/__init__.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
| 2 |
+
from .initialise import init, deinit, reinit, colorama_text, just_fix_windows_console
|
| 3 |
+
from .ansi import Fore, Back, Style, Cursor
|
| 4 |
+
from .ansitowin32 import AnsiToWin32
|
| 5 |
+
|
| 6 |
+
__version__ = '0.4.6'
|
| 7 |
+
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (568 Bytes). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-311.pyc
ADDED
|
Binary file (4.57 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-311.pyc
ADDED
|
Binary file (16.2 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-311.pyc
ADDED
|
Binary file (3.93 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-311.pyc
ADDED
|
Binary file (7.92 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-311.pyc
ADDED
|
Binary file (9.14 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/ansi.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
| 2 |
+
'''
|
| 3 |
+
This module generates ANSI character codes to printing colors to terminals.
|
| 4 |
+
See: http://en.wikipedia.org/wiki/ANSI_escape_code
|
| 5 |
+
'''
|
| 6 |
+
|
| 7 |
+
CSI = '\033['
|
| 8 |
+
OSC = '\033]'
|
| 9 |
+
BEL = '\a'
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def code_to_chars(code):
|
| 13 |
+
return CSI + str(code) + 'm'
|
| 14 |
+
|
| 15 |
+
def set_title(title):
|
| 16 |
+
return OSC + '2;' + title + BEL
|
| 17 |
+
|
| 18 |
+
def clear_screen(mode=2):
|
| 19 |
+
return CSI + str(mode) + 'J'
|
| 20 |
+
|
| 21 |
+
def clear_line(mode=2):
|
| 22 |
+
return CSI + str(mode) + 'K'
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
class AnsiCodes(object):
|
| 26 |
+
def __init__(self):
|
| 27 |
+
# the subclasses declare class attributes which are numbers.
|
| 28 |
+
# Upon instantiation we define instance attributes, which are the same
|
| 29 |
+
# as the class attributes but wrapped with the ANSI escape sequence
|
| 30 |
+
for name in dir(self):
|
| 31 |
+
if not name.startswith('_'):
|
| 32 |
+
value = getattr(self, name)
|
| 33 |
+
setattr(self, name, code_to_chars(value))
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
class AnsiCursor(object):
|
| 37 |
+
def UP(self, n=1):
|
| 38 |
+
return CSI + str(n) + 'A'
|
| 39 |
+
def DOWN(self, n=1):
|
| 40 |
+
return CSI + str(n) + 'B'
|
| 41 |
+
def FORWARD(self, n=1):
|
| 42 |
+
return CSI + str(n) + 'C'
|
| 43 |
+
def BACK(self, n=1):
|
| 44 |
+
return CSI + str(n) + 'D'
|
| 45 |
+
def POS(self, x=1, y=1):
|
| 46 |
+
return CSI + str(y) + ';' + str(x) + 'H'
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
class AnsiFore(AnsiCodes):
|
| 50 |
+
BLACK = 30
|
| 51 |
+
RED = 31
|
| 52 |
+
GREEN = 32
|
| 53 |
+
YELLOW = 33
|
| 54 |
+
BLUE = 34
|
| 55 |
+
MAGENTA = 35
|
| 56 |
+
CYAN = 36
|
| 57 |
+
WHITE = 37
|
| 58 |
+
RESET = 39
|
| 59 |
+
|
| 60 |
+
# These are fairly well supported, but not part of the standard.
|
| 61 |
+
LIGHTBLACK_EX = 90
|
| 62 |
+
LIGHTRED_EX = 91
|
| 63 |
+
LIGHTGREEN_EX = 92
|
| 64 |
+
LIGHTYELLOW_EX = 93
|
| 65 |
+
LIGHTBLUE_EX = 94
|
| 66 |
+
LIGHTMAGENTA_EX = 95
|
| 67 |
+
LIGHTCYAN_EX = 96
|
| 68 |
+
LIGHTWHITE_EX = 97
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
class AnsiBack(AnsiCodes):
|
| 72 |
+
BLACK = 40
|
| 73 |
+
RED = 41
|
| 74 |
+
GREEN = 42
|
| 75 |
+
YELLOW = 43
|
| 76 |
+
BLUE = 44
|
| 77 |
+
MAGENTA = 45
|
| 78 |
+
CYAN = 46
|
| 79 |
+
WHITE = 47
|
| 80 |
+
RESET = 49
|
| 81 |
+
|
| 82 |
+
# These are fairly well supported, but not part of the standard.
|
| 83 |
+
LIGHTBLACK_EX = 100
|
| 84 |
+
LIGHTRED_EX = 101
|
| 85 |
+
LIGHTGREEN_EX = 102
|
| 86 |
+
LIGHTYELLOW_EX = 103
|
| 87 |
+
LIGHTBLUE_EX = 104
|
| 88 |
+
LIGHTMAGENTA_EX = 105
|
| 89 |
+
LIGHTCYAN_EX = 106
|
| 90 |
+
LIGHTWHITE_EX = 107
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
class AnsiStyle(AnsiCodes):
|
| 94 |
+
BRIGHT = 1
|
| 95 |
+
DIM = 2
|
| 96 |
+
NORMAL = 22
|
| 97 |
+
RESET_ALL = 0
|
| 98 |
+
|
| 99 |
+
Fore = AnsiFore()
|
| 100 |
+
Back = AnsiBack()
|
| 101 |
+
Style = AnsiStyle()
|
| 102 |
+
Cursor = AnsiCursor()
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/ansitowin32.py
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
| 2 |
+
import re
|
| 3 |
+
import sys
|
| 4 |
+
import os
|
| 5 |
+
|
| 6 |
+
from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style, BEL
|
| 7 |
+
from .winterm import enable_vt_processing, WinTerm, WinColor, WinStyle
|
| 8 |
+
from .win32 import windll, winapi_test
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
winterm = None
|
| 12 |
+
if windll is not None:
|
| 13 |
+
winterm = WinTerm()
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class StreamWrapper(object):
|
| 17 |
+
'''
|
| 18 |
+
Wraps a stream (such as stdout), acting as a transparent proxy for all
|
| 19 |
+
attribute access apart from method 'write()', which is delegated to our
|
| 20 |
+
Converter instance.
|
| 21 |
+
'''
|
| 22 |
+
def __init__(self, wrapped, converter):
|
| 23 |
+
# double-underscore everything to prevent clashes with names of
|
| 24 |
+
# attributes on the wrapped stream object.
|
| 25 |
+
self.__wrapped = wrapped
|
| 26 |
+
self.__convertor = converter
|
| 27 |
+
|
| 28 |
+
def __getattr__(self, name):
|
| 29 |
+
return getattr(self.__wrapped, name)
|
| 30 |
+
|
| 31 |
+
def __enter__(self, *args, **kwargs):
|
| 32 |
+
# special method lookup bypasses __getattr__/__getattribute__, see
|
| 33 |
+
# https://stackoverflow.com/questions/12632894/why-doesnt-getattr-work-with-exit
|
| 34 |
+
# thus, contextlib magic methods are not proxied via __getattr__
|
| 35 |
+
return self.__wrapped.__enter__(*args, **kwargs)
|
| 36 |
+
|
| 37 |
+
def __exit__(self, *args, **kwargs):
|
| 38 |
+
return self.__wrapped.__exit__(*args, **kwargs)
|
| 39 |
+
|
| 40 |
+
def __setstate__(self, state):
|
| 41 |
+
self.__dict__ = state
|
| 42 |
+
|
| 43 |
+
def __getstate__(self):
|
| 44 |
+
return self.__dict__
|
| 45 |
+
|
| 46 |
+
def write(self, text):
|
| 47 |
+
self.__convertor.write(text)
|
| 48 |
+
|
| 49 |
+
def isatty(self):
|
| 50 |
+
stream = self.__wrapped
|
| 51 |
+
if 'PYCHARM_HOSTED' in os.environ:
|
| 52 |
+
if stream is not None and (stream is sys.__stdout__ or stream is sys.__stderr__):
|
| 53 |
+
return True
|
| 54 |
+
try:
|
| 55 |
+
stream_isatty = stream.isatty
|
| 56 |
+
except AttributeError:
|
| 57 |
+
return False
|
| 58 |
+
else:
|
| 59 |
+
return stream_isatty()
|
| 60 |
+
|
| 61 |
+
@property
|
| 62 |
+
def closed(self):
|
| 63 |
+
stream = self.__wrapped
|
| 64 |
+
try:
|
| 65 |
+
return stream.closed
|
| 66 |
+
# AttributeError in the case that the stream doesn't support being closed
|
| 67 |
+
# ValueError for the case that the stream has already been detached when atexit runs
|
| 68 |
+
except (AttributeError, ValueError):
|
| 69 |
+
return True
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
class AnsiToWin32(object):
|
| 73 |
+
'''
|
| 74 |
+
Implements a 'write()' method which, on Windows, will strip ANSI character
|
| 75 |
+
sequences from the text, and if outputting to a tty, will convert them into
|
| 76 |
+
win32 function calls.
|
| 77 |
+
'''
|
| 78 |
+
ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer
|
| 79 |
+
ANSI_OSC_RE = re.compile('\001?\033\\]([^\a]*)(\a)\002?') # Operating System Command
|
| 80 |
+
|
| 81 |
+
def __init__(self, wrapped, convert=None, strip=None, autoreset=False):
|
| 82 |
+
# The wrapped stream (normally sys.stdout or sys.stderr)
|
| 83 |
+
self.wrapped = wrapped
|
| 84 |
+
|
| 85 |
+
# should we reset colors to defaults after every .write()
|
| 86 |
+
self.autoreset = autoreset
|
| 87 |
+
|
| 88 |
+
# create the proxy wrapping our output stream
|
| 89 |
+
self.stream = StreamWrapper(wrapped, self)
|
| 90 |
+
|
| 91 |
+
on_windows = os.name == 'nt'
|
| 92 |
+
# We test if the WinAPI works, because even if we are on Windows
|
| 93 |
+
# we may be using a terminal that doesn't support the WinAPI
|
| 94 |
+
# (e.g. Cygwin Terminal). In this case it's up to the terminal
|
| 95 |
+
# to support the ANSI codes.
|
| 96 |
+
conversion_supported = on_windows and winapi_test()
|
| 97 |
+
try:
|
| 98 |
+
fd = wrapped.fileno()
|
| 99 |
+
except Exception:
|
| 100 |
+
fd = -1
|
| 101 |
+
system_has_native_ansi = not on_windows or enable_vt_processing(fd)
|
| 102 |
+
have_tty = not self.stream.closed and self.stream.isatty()
|
| 103 |
+
need_conversion = conversion_supported and not system_has_native_ansi
|
| 104 |
+
|
| 105 |
+
# should we strip ANSI sequences from our output?
|
| 106 |
+
if strip is None:
|
| 107 |
+
strip = need_conversion or not have_tty
|
| 108 |
+
self.strip = strip
|
| 109 |
+
|
| 110 |
+
# should we should convert ANSI sequences into win32 calls?
|
| 111 |
+
if convert is None:
|
| 112 |
+
convert = need_conversion and have_tty
|
| 113 |
+
self.convert = convert
|
| 114 |
+
|
| 115 |
+
# dict of ansi codes to win32 functions and parameters
|
| 116 |
+
self.win32_calls = self.get_win32_calls()
|
| 117 |
+
|
| 118 |
+
# are we wrapping stderr?
|
| 119 |
+
self.on_stderr = self.wrapped is sys.stderr
|
| 120 |
+
|
| 121 |
+
def should_wrap(self):
|
| 122 |
+
'''
|
| 123 |
+
True if this class is actually needed. If false, then the output
|
| 124 |
+
stream will not be affected, nor will win32 calls be issued, so
|
| 125 |
+
wrapping stdout is not actually required. This will generally be
|
| 126 |
+
False on non-Windows platforms, unless optional functionality like
|
| 127 |
+
autoreset has been requested using kwargs to init()
|
| 128 |
+
'''
|
| 129 |
+
return self.convert or self.strip or self.autoreset
|
| 130 |
+
|
| 131 |
+
def get_win32_calls(self):
|
| 132 |
+
if self.convert and winterm:
|
| 133 |
+
return {
|
| 134 |
+
AnsiStyle.RESET_ALL: (winterm.reset_all, ),
|
| 135 |
+
AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT),
|
| 136 |
+
AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL),
|
| 137 |
+
AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL),
|
| 138 |
+
AnsiFore.BLACK: (winterm.fore, WinColor.BLACK),
|
| 139 |
+
AnsiFore.RED: (winterm.fore, WinColor.RED),
|
| 140 |
+
AnsiFore.GREEN: (winterm.fore, WinColor.GREEN),
|
| 141 |
+
AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW),
|
| 142 |
+
AnsiFore.BLUE: (winterm.fore, WinColor.BLUE),
|
| 143 |
+
AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA),
|
| 144 |
+
AnsiFore.CYAN: (winterm.fore, WinColor.CYAN),
|
| 145 |
+
AnsiFore.WHITE: (winterm.fore, WinColor.GREY),
|
| 146 |
+
AnsiFore.RESET: (winterm.fore, ),
|
| 147 |
+
AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True),
|
| 148 |
+
AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True),
|
| 149 |
+
AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True),
|
| 150 |
+
AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True),
|
| 151 |
+
AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True),
|
| 152 |
+
AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True),
|
| 153 |
+
AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True),
|
| 154 |
+
AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True),
|
| 155 |
+
AnsiBack.BLACK: (winterm.back, WinColor.BLACK),
|
| 156 |
+
AnsiBack.RED: (winterm.back, WinColor.RED),
|
| 157 |
+
AnsiBack.GREEN: (winterm.back, WinColor.GREEN),
|
| 158 |
+
AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW),
|
| 159 |
+
AnsiBack.BLUE: (winterm.back, WinColor.BLUE),
|
| 160 |
+
AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA),
|
| 161 |
+
AnsiBack.CYAN: (winterm.back, WinColor.CYAN),
|
| 162 |
+
AnsiBack.WHITE: (winterm.back, WinColor.GREY),
|
| 163 |
+
AnsiBack.RESET: (winterm.back, ),
|
| 164 |
+
AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True),
|
| 165 |
+
AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True),
|
| 166 |
+
AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True),
|
| 167 |
+
AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True),
|
| 168 |
+
AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True),
|
| 169 |
+
AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True),
|
| 170 |
+
AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True),
|
| 171 |
+
AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True),
|
| 172 |
+
}
|
| 173 |
+
return dict()
|
| 174 |
+
|
| 175 |
+
def write(self, text):
|
| 176 |
+
if self.strip or self.convert:
|
| 177 |
+
self.write_and_convert(text)
|
| 178 |
+
else:
|
| 179 |
+
self.wrapped.write(text)
|
| 180 |
+
self.wrapped.flush()
|
| 181 |
+
if self.autoreset:
|
| 182 |
+
self.reset_all()
|
| 183 |
+
|
| 184 |
+
|
| 185 |
+
def reset_all(self):
|
| 186 |
+
if self.convert:
|
| 187 |
+
self.call_win32('m', (0,))
|
| 188 |
+
elif not self.strip and not self.stream.closed:
|
| 189 |
+
self.wrapped.write(Style.RESET_ALL)
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
def write_and_convert(self, text):
|
| 193 |
+
'''
|
| 194 |
+
Write the given text to our wrapped stream, stripping any ANSI
|
| 195 |
+
sequences from the text, and optionally converting them into win32
|
| 196 |
+
calls.
|
| 197 |
+
'''
|
| 198 |
+
cursor = 0
|
| 199 |
+
text = self.convert_osc(text)
|
| 200 |
+
for match in self.ANSI_CSI_RE.finditer(text):
|
| 201 |
+
start, end = match.span()
|
| 202 |
+
self.write_plain_text(text, cursor, start)
|
| 203 |
+
self.convert_ansi(*match.groups())
|
| 204 |
+
cursor = end
|
| 205 |
+
self.write_plain_text(text, cursor, len(text))
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
def write_plain_text(self, text, start, end):
|
| 209 |
+
if start < end:
|
| 210 |
+
self.wrapped.write(text[start:end])
|
| 211 |
+
self.wrapped.flush()
|
| 212 |
+
|
| 213 |
+
|
| 214 |
+
def convert_ansi(self, paramstring, command):
|
| 215 |
+
if self.convert:
|
| 216 |
+
params = self.extract_params(command, paramstring)
|
| 217 |
+
self.call_win32(command, params)
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def extract_params(self, command, paramstring):
|
| 221 |
+
if command in 'Hf':
|
| 222 |
+
params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';'))
|
| 223 |
+
while len(params) < 2:
|
| 224 |
+
# defaults:
|
| 225 |
+
params = params + (1,)
|
| 226 |
+
else:
|
| 227 |
+
params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0)
|
| 228 |
+
if len(params) == 0:
|
| 229 |
+
# defaults:
|
| 230 |
+
if command in 'JKm':
|
| 231 |
+
params = (0,)
|
| 232 |
+
elif command in 'ABCD':
|
| 233 |
+
params = (1,)
|
| 234 |
+
|
| 235 |
+
return params
|
| 236 |
+
|
| 237 |
+
|
| 238 |
+
def call_win32(self, command, params):
|
| 239 |
+
if command == 'm':
|
| 240 |
+
for param in params:
|
| 241 |
+
if param in self.win32_calls:
|
| 242 |
+
func_args = self.win32_calls[param]
|
| 243 |
+
func = func_args[0]
|
| 244 |
+
args = func_args[1:]
|
| 245 |
+
kwargs = dict(on_stderr=self.on_stderr)
|
| 246 |
+
func(*args, **kwargs)
|
| 247 |
+
elif command in 'J':
|
| 248 |
+
winterm.erase_screen(params[0], on_stderr=self.on_stderr)
|
| 249 |
+
elif command in 'K':
|
| 250 |
+
winterm.erase_line(params[0], on_stderr=self.on_stderr)
|
| 251 |
+
elif command in 'Hf': # cursor position - absolute
|
| 252 |
+
winterm.set_cursor_position(params, on_stderr=self.on_stderr)
|
| 253 |
+
elif command in 'ABCD': # cursor position - relative
|
| 254 |
+
n = params[0]
|
| 255 |
+
# A - up, B - down, C - forward, D - back
|
| 256 |
+
x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command]
|
| 257 |
+
winterm.cursor_adjust(x, y, on_stderr=self.on_stderr)
|
| 258 |
+
|
| 259 |
+
|
| 260 |
+
def convert_osc(self, text):
|
| 261 |
+
for match in self.ANSI_OSC_RE.finditer(text):
|
| 262 |
+
start, end = match.span()
|
| 263 |
+
text = text[:start] + text[end:]
|
| 264 |
+
paramstring, command = match.groups()
|
| 265 |
+
if command == BEL:
|
| 266 |
+
if paramstring.count(";") == 1:
|
| 267 |
+
params = paramstring.split(";")
|
| 268 |
+
# 0 - change title and icon (we will only change title)
|
| 269 |
+
# 1 - change icon (we don't support this)
|
| 270 |
+
# 2 - change title
|
| 271 |
+
if params[0] in '02':
|
| 272 |
+
winterm.set_title(params[1])
|
| 273 |
+
return text
|
| 274 |
+
|
| 275 |
+
|
| 276 |
+
def flush(self):
|
| 277 |
+
self.wrapped.flush()
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/initialise.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
| 2 |
+
import atexit
|
| 3 |
+
import contextlib
|
| 4 |
+
import sys
|
| 5 |
+
|
| 6 |
+
from .ansitowin32 import AnsiToWin32
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def _wipe_internal_state_for_tests():
|
| 10 |
+
global orig_stdout, orig_stderr
|
| 11 |
+
orig_stdout = None
|
| 12 |
+
orig_stderr = None
|
| 13 |
+
|
| 14 |
+
global wrapped_stdout, wrapped_stderr
|
| 15 |
+
wrapped_stdout = None
|
| 16 |
+
wrapped_stderr = None
|
| 17 |
+
|
| 18 |
+
global atexit_done
|
| 19 |
+
atexit_done = False
|
| 20 |
+
|
| 21 |
+
global fixed_windows_console
|
| 22 |
+
fixed_windows_console = False
|
| 23 |
+
|
| 24 |
+
try:
|
| 25 |
+
# no-op if it wasn't registered
|
| 26 |
+
atexit.unregister(reset_all)
|
| 27 |
+
except AttributeError:
|
| 28 |
+
# python 2: no atexit.unregister. Oh well, we did our best.
|
| 29 |
+
pass
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def reset_all():
|
| 33 |
+
if AnsiToWin32 is not None: # Issue #74: objects might become None at exit
|
| 34 |
+
AnsiToWin32(orig_stdout).reset_all()
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def init(autoreset=False, convert=None, strip=None, wrap=True):
|
| 38 |
+
|
| 39 |
+
if not wrap and any([autoreset, convert, strip]):
|
| 40 |
+
raise ValueError('wrap=False conflicts with any other arg=True')
|
| 41 |
+
|
| 42 |
+
global wrapped_stdout, wrapped_stderr
|
| 43 |
+
global orig_stdout, orig_stderr
|
| 44 |
+
|
| 45 |
+
orig_stdout = sys.stdout
|
| 46 |
+
orig_stderr = sys.stderr
|
| 47 |
+
|
| 48 |
+
if sys.stdout is None:
|
| 49 |
+
wrapped_stdout = None
|
| 50 |
+
else:
|
| 51 |
+
sys.stdout = wrapped_stdout = \
|
| 52 |
+
wrap_stream(orig_stdout, convert, strip, autoreset, wrap)
|
| 53 |
+
if sys.stderr is None:
|
| 54 |
+
wrapped_stderr = None
|
| 55 |
+
else:
|
| 56 |
+
sys.stderr = wrapped_stderr = \
|
| 57 |
+
wrap_stream(orig_stderr, convert, strip, autoreset, wrap)
|
| 58 |
+
|
| 59 |
+
global atexit_done
|
| 60 |
+
if not atexit_done:
|
| 61 |
+
atexit.register(reset_all)
|
| 62 |
+
atexit_done = True
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
def deinit():
|
| 66 |
+
if orig_stdout is not None:
|
| 67 |
+
sys.stdout = orig_stdout
|
| 68 |
+
if orig_stderr is not None:
|
| 69 |
+
sys.stderr = orig_stderr
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def just_fix_windows_console():
|
| 73 |
+
global fixed_windows_console
|
| 74 |
+
|
| 75 |
+
if sys.platform != "win32":
|
| 76 |
+
return
|
| 77 |
+
if fixed_windows_console:
|
| 78 |
+
return
|
| 79 |
+
if wrapped_stdout is not None or wrapped_stderr is not None:
|
| 80 |
+
# Someone already ran init() and it did stuff, so we won't second-guess them
|
| 81 |
+
return
|
| 82 |
+
|
| 83 |
+
# On newer versions of Windows, AnsiToWin32.__init__ will implicitly enable the
|
| 84 |
+
# native ANSI support in the console as a side-effect. We only need to actually
|
| 85 |
+
# replace sys.stdout/stderr if we're in the old-style conversion mode.
|
| 86 |
+
new_stdout = AnsiToWin32(sys.stdout, convert=None, strip=None, autoreset=False)
|
| 87 |
+
if new_stdout.convert:
|
| 88 |
+
sys.stdout = new_stdout
|
| 89 |
+
new_stderr = AnsiToWin32(sys.stderr, convert=None, strip=None, autoreset=False)
|
| 90 |
+
if new_stderr.convert:
|
| 91 |
+
sys.stderr = new_stderr
|
| 92 |
+
|
| 93 |
+
fixed_windows_console = True
|
| 94 |
+
|
| 95 |
+
@contextlib.contextmanager
|
| 96 |
+
def colorama_text(*args, **kwargs):
|
| 97 |
+
init(*args, **kwargs)
|
| 98 |
+
try:
|
| 99 |
+
yield
|
| 100 |
+
finally:
|
| 101 |
+
deinit()
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
def reinit():
|
| 105 |
+
if wrapped_stdout is not None:
|
| 106 |
+
sys.stdout = wrapped_stdout
|
| 107 |
+
if wrapped_stderr is not None:
|
| 108 |
+
sys.stderr = wrapped_stderr
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
def wrap_stream(stream, convert, strip, autoreset, wrap):
|
| 112 |
+
if wrap:
|
| 113 |
+
wrapper = AnsiToWin32(stream,
|
| 114 |
+
convert=convert, strip=strip, autoreset=autoreset)
|
| 115 |
+
if wrapper.should_wrap():
|
| 116 |
+
stream = wrapper.stream
|
| 117 |
+
return stream
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
# Use this for initial setup as well, to reduce code duplication
|
| 121 |
+
_wipe_internal_state_for_tests()
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (199 Bytes). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__pycache__/ansi_test.cpython-311.pyc
ADDED
|
Binary file (5.84 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__pycache__/ansitowin32_test.cpython-311.pyc
ADDED
|
Binary file (21.5 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__pycache__/initialise_test.cpython-311.pyc
ADDED
|
Binary file (14.1 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__pycache__/isatty_test.cpython-311.pyc
ADDED
|
Binary file (6.7 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__pycache__/utils.cpython-311.pyc
ADDED
|
Binary file (2.88 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/__pycache__/winterm_test.cpython-311.pyc
ADDED
|
Binary file (7.23 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/ansi_test.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
| 2 |
+
import sys
|
| 3 |
+
from unittest import TestCase, main
|
| 4 |
+
|
| 5 |
+
from ..ansi import Back, Fore, Style
|
| 6 |
+
from ..ansitowin32 import AnsiToWin32
|
| 7 |
+
|
| 8 |
+
stdout_orig = sys.stdout
|
| 9 |
+
stderr_orig = sys.stderr
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class AnsiTest(TestCase):
|
| 13 |
+
|
| 14 |
+
def setUp(self):
|
| 15 |
+
# sanity check: stdout should be a file or StringIO object.
|
| 16 |
+
# It will only be AnsiToWin32 if init() has previously wrapped it
|
| 17 |
+
self.assertNotEqual(type(sys.stdout), AnsiToWin32)
|
| 18 |
+
self.assertNotEqual(type(sys.stderr), AnsiToWin32)
|
| 19 |
+
|
| 20 |
+
def tearDown(self):
|
| 21 |
+
sys.stdout = stdout_orig
|
| 22 |
+
sys.stderr = stderr_orig
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def testForeAttributes(self):
|
| 26 |
+
self.assertEqual(Fore.BLACK, '\033[30m')
|
| 27 |
+
self.assertEqual(Fore.RED, '\033[31m')
|
| 28 |
+
self.assertEqual(Fore.GREEN, '\033[32m')
|
| 29 |
+
self.assertEqual(Fore.YELLOW, '\033[33m')
|
| 30 |
+
self.assertEqual(Fore.BLUE, '\033[34m')
|
| 31 |
+
self.assertEqual(Fore.MAGENTA, '\033[35m')
|
| 32 |
+
self.assertEqual(Fore.CYAN, '\033[36m')
|
| 33 |
+
self.assertEqual(Fore.WHITE, '\033[37m')
|
| 34 |
+
self.assertEqual(Fore.RESET, '\033[39m')
|
| 35 |
+
|
| 36 |
+
# Check the light, extended versions.
|
| 37 |
+
self.assertEqual(Fore.LIGHTBLACK_EX, '\033[90m')
|
| 38 |
+
self.assertEqual(Fore.LIGHTRED_EX, '\033[91m')
|
| 39 |
+
self.assertEqual(Fore.LIGHTGREEN_EX, '\033[92m')
|
| 40 |
+
self.assertEqual(Fore.LIGHTYELLOW_EX, '\033[93m')
|
| 41 |
+
self.assertEqual(Fore.LIGHTBLUE_EX, '\033[94m')
|
| 42 |
+
self.assertEqual(Fore.LIGHTMAGENTA_EX, '\033[95m')
|
| 43 |
+
self.assertEqual(Fore.LIGHTCYAN_EX, '\033[96m')
|
| 44 |
+
self.assertEqual(Fore.LIGHTWHITE_EX, '\033[97m')
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def testBackAttributes(self):
|
| 48 |
+
self.assertEqual(Back.BLACK, '\033[40m')
|
| 49 |
+
self.assertEqual(Back.RED, '\033[41m')
|
| 50 |
+
self.assertEqual(Back.GREEN, '\033[42m')
|
| 51 |
+
self.assertEqual(Back.YELLOW, '\033[43m')
|
| 52 |
+
self.assertEqual(Back.BLUE, '\033[44m')
|
| 53 |
+
self.assertEqual(Back.MAGENTA, '\033[45m')
|
| 54 |
+
self.assertEqual(Back.CYAN, '\033[46m')
|
| 55 |
+
self.assertEqual(Back.WHITE, '\033[47m')
|
| 56 |
+
self.assertEqual(Back.RESET, '\033[49m')
|
| 57 |
+
|
| 58 |
+
# Check the light, extended versions.
|
| 59 |
+
self.assertEqual(Back.LIGHTBLACK_EX, '\033[100m')
|
| 60 |
+
self.assertEqual(Back.LIGHTRED_EX, '\033[101m')
|
| 61 |
+
self.assertEqual(Back.LIGHTGREEN_EX, '\033[102m')
|
| 62 |
+
self.assertEqual(Back.LIGHTYELLOW_EX, '\033[103m')
|
| 63 |
+
self.assertEqual(Back.LIGHTBLUE_EX, '\033[104m')
|
| 64 |
+
self.assertEqual(Back.LIGHTMAGENTA_EX, '\033[105m')
|
| 65 |
+
self.assertEqual(Back.LIGHTCYAN_EX, '\033[106m')
|
| 66 |
+
self.assertEqual(Back.LIGHTWHITE_EX, '\033[107m')
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def testStyleAttributes(self):
|
| 70 |
+
self.assertEqual(Style.DIM, '\033[2m')
|
| 71 |
+
self.assertEqual(Style.NORMAL, '\033[22m')
|
| 72 |
+
self.assertEqual(Style.BRIGHT, '\033[1m')
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
if __name__ == '__main__':
|
| 76 |
+
main()
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/ansitowin32_test.py
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
| 2 |
+
from io import StringIO, TextIOWrapper
|
| 3 |
+
from unittest import TestCase, main
|
| 4 |
+
try:
|
| 5 |
+
from contextlib import ExitStack
|
| 6 |
+
except ImportError:
|
| 7 |
+
# python 2
|
| 8 |
+
from contextlib2 import ExitStack
|
| 9 |
+
|
| 10 |
+
try:
|
| 11 |
+
from unittest.mock import MagicMock, Mock, patch
|
| 12 |
+
except ImportError:
|
| 13 |
+
from mock import MagicMock, Mock, patch
|
| 14 |
+
|
| 15 |
+
from ..ansitowin32 import AnsiToWin32, StreamWrapper
|
| 16 |
+
from ..win32 import ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
| 17 |
+
from .utils import osname
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class StreamWrapperTest(TestCase):
|
| 21 |
+
|
| 22 |
+
def testIsAProxy(self):
|
| 23 |
+
mockStream = Mock()
|
| 24 |
+
wrapper = StreamWrapper(mockStream, None)
|
| 25 |
+
self.assertTrue( wrapper.random_attr is mockStream.random_attr )
|
| 26 |
+
|
| 27 |
+
def testDelegatesWrite(self):
|
| 28 |
+
mockStream = Mock()
|
| 29 |
+
mockConverter = Mock()
|
| 30 |
+
wrapper = StreamWrapper(mockStream, mockConverter)
|
| 31 |
+
wrapper.write('hello')
|
| 32 |
+
self.assertTrue(mockConverter.write.call_args, (('hello',), {}))
|
| 33 |
+
|
| 34 |
+
def testDelegatesContext(self):
|
| 35 |
+
mockConverter = Mock()
|
| 36 |
+
s = StringIO()
|
| 37 |
+
with StreamWrapper(s, mockConverter) as fp:
|
| 38 |
+
fp.write(u'hello')
|
| 39 |
+
self.assertTrue(s.closed)
|
| 40 |
+
|
| 41 |
+
def testProxyNoContextManager(self):
|
| 42 |
+
mockStream = MagicMock()
|
| 43 |
+
mockStream.__enter__.side_effect = AttributeError()
|
| 44 |
+
mockConverter = Mock()
|
| 45 |
+
with self.assertRaises(AttributeError) as excinfo:
|
| 46 |
+
with StreamWrapper(mockStream, mockConverter) as wrapper:
|
| 47 |
+
wrapper.write('hello')
|
| 48 |
+
|
| 49 |
+
def test_closed_shouldnt_raise_on_closed_stream(self):
|
| 50 |
+
stream = StringIO()
|
| 51 |
+
stream.close()
|
| 52 |
+
wrapper = StreamWrapper(stream, None)
|
| 53 |
+
self.assertEqual(wrapper.closed, True)
|
| 54 |
+
|
| 55 |
+
def test_closed_shouldnt_raise_on_detached_stream(self):
|
| 56 |
+
stream = TextIOWrapper(StringIO())
|
| 57 |
+
stream.detach()
|
| 58 |
+
wrapper = StreamWrapper(stream, None)
|
| 59 |
+
self.assertEqual(wrapper.closed, True)
|
| 60 |
+
|
| 61 |
+
class AnsiToWin32Test(TestCase):
|
| 62 |
+
|
| 63 |
+
def testInit(self):
|
| 64 |
+
mockStdout = Mock()
|
| 65 |
+
auto = Mock()
|
| 66 |
+
stream = AnsiToWin32(mockStdout, autoreset=auto)
|
| 67 |
+
self.assertEqual(stream.wrapped, mockStdout)
|
| 68 |
+
self.assertEqual(stream.autoreset, auto)
|
| 69 |
+
|
| 70 |
+
@patch('colorama.ansitowin32.winterm', None)
|
| 71 |
+
@patch('colorama.ansitowin32.winapi_test', lambda *_: True)
|
| 72 |
+
def testStripIsTrueOnWindows(self):
|
| 73 |
+
with osname('nt'):
|
| 74 |
+
mockStdout = Mock()
|
| 75 |
+
stream = AnsiToWin32(mockStdout)
|
| 76 |
+
self.assertTrue(stream.strip)
|
| 77 |
+
|
| 78 |
+
def testStripIsFalseOffWindows(self):
|
| 79 |
+
with osname('posix'):
|
| 80 |
+
mockStdout = Mock(closed=False)
|
| 81 |
+
stream = AnsiToWin32(mockStdout)
|
| 82 |
+
self.assertFalse(stream.strip)
|
| 83 |
+
|
| 84 |
+
def testWriteStripsAnsi(self):
|
| 85 |
+
mockStdout = Mock()
|
| 86 |
+
stream = AnsiToWin32(mockStdout)
|
| 87 |
+
stream.wrapped = Mock()
|
| 88 |
+
stream.write_and_convert = Mock()
|
| 89 |
+
stream.strip = True
|
| 90 |
+
|
| 91 |
+
stream.write('abc')
|
| 92 |
+
|
| 93 |
+
self.assertFalse(stream.wrapped.write.called)
|
| 94 |
+
self.assertEqual(stream.write_and_convert.call_args, (('abc',), {}))
|
| 95 |
+
|
| 96 |
+
def testWriteDoesNotStripAnsi(self):
|
| 97 |
+
mockStdout = Mock()
|
| 98 |
+
stream = AnsiToWin32(mockStdout)
|
| 99 |
+
stream.wrapped = Mock()
|
| 100 |
+
stream.write_and_convert = Mock()
|
| 101 |
+
stream.strip = False
|
| 102 |
+
stream.convert = False
|
| 103 |
+
|
| 104 |
+
stream.write('abc')
|
| 105 |
+
|
| 106 |
+
self.assertFalse(stream.write_and_convert.called)
|
| 107 |
+
self.assertEqual(stream.wrapped.write.call_args, (('abc',), {}))
|
| 108 |
+
|
| 109 |
+
def assert_autoresets(self, convert, autoreset=True):
|
| 110 |
+
stream = AnsiToWin32(Mock())
|
| 111 |
+
stream.convert = convert
|
| 112 |
+
stream.reset_all = Mock()
|
| 113 |
+
stream.autoreset = autoreset
|
| 114 |
+
stream.winterm = Mock()
|
| 115 |
+
|
| 116 |
+
stream.write('abc')
|
| 117 |
+
|
| 118 |
+
self.assertEqual(stream.reset_all.called, autoreset)
|
| 119 |
+
|
| 120 |
+
def testWriteAutoresets(self):
|
| 121 |
+
self.assert_autoresets(convert=True)
|
| 122 |
+
self.assert_autoresets(convert=False)
|
| 123 |
+
self.assert_autoresets(convert=True, autoreset=False)
|
| 124 |
+
self.assert_autoresets(convert=False, autoreset=False)
|
| 125 |
+
|
| 126 |
+
def testWriteAndConvertWritesPlainText(self):
|
| 127 |
+
stream = AnsiToWin32(Mock())
|
| 128 |
+
stream.write_and_convert( 'abc' )
|
| 129 |
+
self.assertEqual( stream.wrapped.write.call_args, (('abc',), {}) )
|
| 130 |
+
|
| 131 |
+
def testWriteAndConvertStripsAllValidAnsi(self):
|
| 132 |
+
stream = AnsiToWin32(Mock())
|
| 133 |
+
stream.call_win32 = Mock()
|
| 134 |
+
data = [
|
| 135 |
+
'abc\033[mdef',
|
| 136 |
+
'abc\033[0mdef',
|
| 137 |
+
'abc\033[2mdef',
|
| 138 |
+
'abc\033[02mdef',
|
| 139 |
+
'abc\033[002mdef',
|
| 140 |
+
'abc\033[40mdef',
|
| 141 |
+
'abc\033[040mdef',
|
| 142 |
+
'abc\033[0;1mdef',
|
| 143 |
+
'abc\033[40;50mdef',
|
| 144 |
+
'abc\033[50;30;40mdef',
|
| 145 |
+
'abc\033[Adef',
|
| 146 |
+
'abc\033[0Gdef',
|
| 147 |
+
'abc\033[1;20;128Hdef',
|
| 148 |
+
]
|
| 149 |
+
for datum in data:
|
| 150 |
+
stream.wrapped.write.reset_mock()
|
| 151 |
+
stream.write_and_convert( datum )
|
| 152 |
+
self.assertEqual(
|
| 153 |
+
[args[0] for args in stream.wrapped.write.call_args_list],
|
| 154 |
+
[ ('abc',), ('def',) ]
|
| 155 |
+
)
|
| 156 |
+
|
| 157 |
+
def testWriteAndConvertSkipsEmptySnippets(self):
|
| 158 |
+
stream = AnsiToWin32(Mock())
|
| 159 |
+
stream.call_win32 = Mock()
|
| 160 |
+
stream.write_and_convert( '\033[40m\033[41m' )
|
| 161 |
+
self.assertFalse( stream.wrapped.write.called )
|
| 162 |
+
|
| 163 |
+
def testWriteAndConvertCallsWin32WithParamsAndCommand(self):
|
| 164 |
+
stream = AnsiToWin32(Mock())
|
| 165 |
+
stream.convert = True
|
| 166 |
+
stream.call_win32 = Mock()
|
| 167 |
+
stream.extract_params = Mock(return_value='params')
|
| 168 |
+
data = {
|
| 169 |
+
'abc\033[adef': ('a', 'params'),
|
| 170 |
+
'abc\033[;;bdef': ('b', 'params'),
|
| 171 |
+
'abc\033[0cdef': ('c', 'params'),
|
| 172 |
+
'abc\033[;;0;;Gdef': ('G', 'params'),
|
| 173 |
+
'abc\033[1;20;128Hdef': ('H', 'params'),
|
| 174 |
+
}
|
| 175 |
+
for datum, expected in data.items():
|
| 176 |
+
stream.call_win32.reset_mock()
|
| 177 |
+
stream.write_and_convert( datum )
|
| 178 |
+
self.assertEqual( stream.call_win32.call_args[0], expected )
|
| 179 |
+
|
| 180 |
+
def test_reset_all_shouldnt_raise_on_closed_orig_stdout(self):
|
| 181 |
+
stream = StringIO()
|
| 182 |
+
converter = AnsiToWin32(stream)
|
| 183 |
+
stream.close()
|
| 184 |
+
|
| 185 |
+
converter.reset_all()
|
| 186 |
+
|
| 187 |
+
def test_wrap_shouldnt_raise_on_closed_orig_stdout(self):
|
| 188 |
+
stream = StringIO()
|
| 189 |
+
stream.close()
|
| 190 |
+
with \
|
| 191 |
+
patch("colorama.ansitowin32.os.name", "nt"), \
|
| 192 |
+
patch("colorama.ansitowin32.winapi_test", lambda: True):
|
| 193 |
+
converter = AnsiToWin32(stream)
|
| 194 |
+
self.assertTrue(converter.strip)
|
| 195 |
+
self.assertFalse(converter.convert)
|
| 196 |
+
|
| 197 |
+
def test_wrap_shouldnt_raise_on_missing_closed_attr(self):
|
| 198 |
+
with \
|
| 199 |
+
patch("colorama.ansitowin32.os.name", "nt"), \
|
| 200 |
+
patch("colorama.ansitowin32.winapi_test", lambda: True):
|
| 201 |
+
converter = AnsiToWin32(object())
|
| 202 |
+
self.assertTrue(converter.strip)
|
| 203 |
+
self.assertFalse(converter.convert)
|
| 204 |
+
|
| 205 |
+
def testExtractParams(self):
|
| 206 |
+
stream = AnsiToWin32(Mock())
|
| 207 |
+
data = {
|
| 208 |
+
'': (0,),
|
| 209 |
+
';;': (0,),
|
| 210 |
+
'2': (2,),
|
| 211 |
+
';;002;;': (2,),
|
| 212 |
+
'0;1': (0, 1),
|
| 213 |
+
';;003;;456;;': (3, 456),
|
| 214 |
+
'11;22;33;44;55': (11, 22, 33, 44, 55),
|
| 215 |
+
}
|
| 216 |
+
for datum, expected in data.items():
|
| 217 |
+
self.assertEqual(stream.extract_params('m', datum), expected)
|
| 218 |
+
|
| 219 |
+
def testCallWin32UsesLookup(self):
|
| 220 |
+
listener = Mock()
|
| 221 |
+
stream = AnsiToWin32(listener)
|
| 222 |
+
stream.win32_calls = {
|
| 223 |
+
1: (lambda *_, **__: listener(11),),
|
| 224 |
+
2: (lambda *_, **__: listener(22),),
|
| 225 |
+
3: (lambda *_, **__: listener(33),),
|
| 226 |
+
}
|
| 227 |
+
stream.call_win32('m', (3, 1, 99, 2))
|
| 228 |
+
self.assertEqual(
|
| 229 |
+
[a[0][0] for a in listener.call_args_list],
|
| 230 |
+
[33, 11, 22] )
|
| 231 |
+
|
| 232 |
+
def test_osc_codes(self):
|
| 233 |
+
mockStdout = Mock()
|
| 234 |
+
stream = AnsiToWin32(mockStdout, convert=True)
|
| 235 |
+
with patch('colorama.ansitowin32.winterm') as winterm:
|
| 236 |
+
data = [
|
| 237 |
+
'\033]0\x07', # missing arguments
|
| 238 |
+
'\033]0;foo\x08', # wrong OSC command
|
| 239 |
+
'\033]0;colorama_test_title\x07', # should work
|
| 240 |
+
'\033]1;colorama_test_title\x07', # wrong set command
|
| 241 |
+
'\033]2;colorama_test_title\x07', # should work
|
| 242 |
+
'\033]' + ';' * 64 + '\x08', # see issue #247
|
| 243 |
+
]
|
| 244 |
+
for code in data:
|
| 245 |
+
stream.write(code)
|
| 246 |
+
self.assertEqual(winterm.set_title.call_count, 2)
|
| 247 |
+
|
| 248 |
+
def test_native_windows_ansi(self):
|
| 249 |
+
with ExitStack() as stack:
|
| 250 |
+
def p(a, b):
|
| 251 |
+
stack.enter_context(patch(a, b, create=True))
|
| 252 |
+
# Pretend to be on Windows
|
| 253 |
+
p("colorama.ansitowin32.os.name", "nt")
|
| 254 |
+
p("colorama.ansitowin32.winapi_test", lambda: True)
|
| 255 |
+
p("colorama.win32.winapi_test", lambda: True)
|
| 256 |
+
p("colorama.winterm.win32.windll", "non-None")
|
| 257 |
+
p("colorama.winterm.get_osfhandle", lambda _: 1234)
|
| 258 |
+
|
| 259 |
+
# Pretend that our mock stream has native ANSI support
|
| 260 |
+
p(
|
| 261 |
+
"colorama.winterm.win32.GetConsoleMode",
|
| 262 |
+
lambda _: ENABLE_VIRTUAL_TERMINAL_PROCESSING,
|
| 263 |
+
)
|
| 264 |
+
SetConsoleMode = Mock()
|
| 265 |
+
p("colorama.winterm.win32.SetConsoleMode", SetConsoleMode)
|
| 266 |
+
|
| 267 |
+
stdout = Mock()
|
| 268 |
+
stdout.closed = False
|
| 269 |
+
stdout.isatty.return_value = True
|
| 270 |
+
stdout.fileno.return_value = 1
|
| 271 |
+
|
| 272 |
+
# Our fake console says it has native vt support, so AnsiToWin32 should
|
| 273 |
+
# enable that support and do nothing else.
|
| 274 |
+
stream = AnsiToWin32(stdout)
|
| 275 |
+
SetConsoleMode.assert_called_with(1234, ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
| 276 |
+
self.assertFalse(stream.strip)
|
| 277 |
+
self.assertFalse(stream.convert)
|
| 278 |
+
self.assertFalse(stream.should_wrap())
|
| 279 |
+
|
| 280 |
+
# Now let's pretend we're on an old Windows console, that doesn't have
|
| 281 |
+
# native ANSI support.
|
| 282 |
+
p("colorama.winterm.win32.GetConsoleMode", lambda _: 0)
|
| 283 |
+
SetConsoleMode = Mock()
|
| 284 |
+
p("colorama.winterm.win32.SetConsoleMode", SetConsoleMode)
|
| 285 |
+
|
| 286 |
+
stream = AnsiToWin32(stdout)
|
| 287 |
+
SetConsoleMode.assert_called_with(1234, ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
| 288 |
+
self.assertTrue(stream.strip)
|
| 289 |
+
self.assertTrue(stream.convert)
|
| 290 |
+
self.assertTrue(stream.should_wrap())
|
| 291 |
+
|
| 292 |
+
|
| 293 |
+
if __name__ == '__main__':
|
| 294 |
+
main()
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/initialise_test.py
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
| 2 |
+
import sys
|
| 3 |
+
from unittest import TestCase, main, skipUnless
|
| 4 |
+
|
| 5 |
+
try:
|
| 6 |
+
from unittest.mock import patch, Mock
|
| 7 |
+
except ImportError:
|
| 8 |
+
from mock import patch, Mock
|
| 9 |
+
|
| 10 |
+
from ..ansitowin32 import StreamWrapper
|
| 11 |
+
from ..initialise import init, just_fix_windows_console, _wipe_internal_state_for_tests
|
| 12 |
+
from .utils import osname, replace_by
|
| 13 |
+
|
| 14 |
+
orig_stdout = sys.stdout
|
| 15 |
+
orig_stderr = sys.stderr
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
class InitTest(TestCase):
|
| 19 |
+
|
| 20 |
+
@skipUnless(sys.stdout.isatty(), "sys.stdout is not a tty")
|
| 21 |
+
def setUp(self):
|
| 22 |
+
# sanity check
|
| 23 |
+
self.assertNotWrapped()
|
| 24 |
+
|
| 25 |
+
def tearDown(self):
|
| 26 |
+
_wipe_internal_state_for_tests()
|
| 27 |
+
sys.stdout = orig_stdout
|
| 28 |
+
sys.stderr = orig_stderr
|
| 29 |
+
|
| 30 |
+
def assertWrapped(self):
|
| 31 |
+
self.assertIsNot(sys.stdout, orig_stdout, 'stdout should be wrapped')
|
| 32 |
+
self.assertIsNot(sys.stderr, orig_stderr, 'stderr should be wrapped')
|
| 33 |
+
self.assertTrue(isinstance(sys.stdout, StreamWrapper),
|
| 34 |
+
'bad stdout wrapper')
|
| 35 |
+
self.assertTrue(isinstance(sys.stderr, StreamWrapper),
|
| 36 |
+
'bad stderr wrapper')
|
| 37 |
+
|
| 38 |
+
def assertNotWrapped(self):
|
| 39 |
+
self.assertIs(sys.stdout, orig_stdout, 'stdout should not be wrapped')
|
| 40 |
+
self.assertIs(sys.stderr, orig_stderr, 'stderr should not be wrapped')
|
| 41 |
+
|
| 42 |
+
@patch('colorama.initialise.reset_all')
|
| 43 |
+
@patch('colorama.ansitowin32.winapi_test', lambda *_: True)
|
| 44 |
+
@patch('colorama.ansitowin32.enable_vt_processing', lambda *_: False)
|
| 45 |
+
def testInitWrapsOnWindows(self, _):
|
| 46 |
+
with osname("nt"):
|
| 47 |
+
init()
|
| 48 |
+
self.assertWrapped()
|
| 49 |
+
|
| 50 |
+
@patch('colorama.initialise.reset_all')
|
| 51 |
+
@patch('colorama.ansitowin32.winapi_test', lambda *_: False)
|
| 52 |
+
def testInitDoesntWrapOnEmulatedWindows(self, _):
|
| 53 |
+
with osname("nt"):
|
| 54 |
+
init()
|
| 55 |
+
self.assertNotWrapped()
|
| 56 |
+
|
| 57 |
+
def testInitDoesntWrapOnNonWindows(self):
|
| 58 |
+
with osname("posix"):
|
| 59 |
+
init()
|
| 60 |
+
self.assertNotWrapped()
|
| 61 |
+
|
| 62 |
+
def testInitDoesntWrapIfNone(self):
|
| 63 |
+
with replace_by(None):
|
| 64 |
+
init()
|
| 65 |
+
# We can't use assertNotWrapped here because replace_by(None)
|
| 66 |
+
# changes stdout/stderr already.
|
| 67 |
+
self.assertIsNone(sys.stdout)
|
| 68 |
+
self.assertIsNone(sys.stderr)
|
| 69 |
+
|
| 70 |
+
def testInitAutoresetOnWrapsOnAllPlatforms(self):
|
| 71 |
+
with osname("posix"):
|
| 72 |
+
init(autoreset=True)
|
| 73 |
+
self.assertWrapped()
|
| 74 |
+
|
| 75 |
+
def testInitWrapOffDoesntWrapOnWindows(self):
|
| 76 |
+
with osname("nt"):
|
| 77 |
+
init(wrap=False)
|
| 78 |
+
self.assertNotWrapped()
|
| 79 |
+
|
| 80 |
+
def testInitWrapOffIncompatibleWithAutoresetOn(self):
|
| 81 |
+
self.assertRaises(ValueError, lambda: init(autoreset=True, wrap=False))
|
| 82 |
+
|
| 83 |
+
@patch('colorama.win32.SetConsoleTextAttribute')
|
| 84 |
+
@patch('colorama.initialise.AnsiToWin32')
|
| 85 |
+
def testAutoResetPassedOn(self, mockATW32, _):
|
| 86 |
+
with osname("nt"):
|
| 87 |
+
init(autoreset=True)
|
| 88 |
+
self.assertEqual(len(mockATW32.call_args_list), 2)
|
| 89 |
+
self.assertEqual(mockATW32.call_args_list[1][1]['autoreset'], True)
|
| 90 |
+
self.assertEqual(mockATW32.call_args_list[0][1]['autoreset'], True)
|
| 91 |
+
|
| 92 |
+
@patch('colorama.initialise.AnsiToWin32')
|
| 93 |
+
def testAutoResetChangeable(self, mockATW32):
|
| 94 |
+
with osname("nt"):
|
| 95 |
+
init()
|
| 96 |
+
|
| 97 |
+
init(autoreset=True)
|
| 98 |
+
self.assertEqual(len(mockATW32.call_args_list), 4)
|
| 99 |
+
self.assertEqual(mockATW32.call_args_list[2][1]['autoreset'], True)
|
| 100 |
+
self.assertEqual(mockATW32.call_args_list[3][1]['autoreset'], True)
|
| 101 |
+
|
| 102 |
+
init()
|
| 103 |
+
self.assertEqual(len(mockATW32.call_args_list), 6)
|
| 104 |
+
self.assertEqual(
|
| 105 |
+
mockATW32.call_args_list[4][1]['autoreset'], False)
|
| 106 |
+
self.assertEqual(
|
| 107 |
+
mockATW32.call_args_list[5][1]['autoreset'], False)
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
@patch('colorama.initialise.atexit.register')
|
| 111 |
+
def testAtexitRegisteredOnlyOnce(self, mockRegister):
|
| 112 |
+
init()
|
| 113 |
+
self.assertTrue(mockRegister.called)
|
| 114 |
+
mockRegister.reset_mock()
|
| 115 |
+
init()
|
| 116 |
+
self.assertFalse(mockRegister.called)
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
class JustFixWindowsConsoleTest(TestCase):
|
| 120 |
+
def _reset(self):
|
| 121 |
+
_wipe_internal_state_for_tests()
|
| 122 |
+
sys.stdout = orig_stdout
|
| 123 |
+
sys.stderr = orig_stderr
|
| 124 |
+
|
| 125 |
+
def tearDown(self):
|
| 126 |
+
self._reset()
|
| 127 |
+
|
| 128 |
+
@patch("colorama.ansitowin32.winapi_test", lambda: True)
|
| 129 |
+
def testJustFixWindowsConsole(self):
|
| 130 |
+
if sys.platform != "win32":
|
| 131 |
+
# just_fix_windows_console should be a no-op
|
| 132 |
+
just_fix_windows_console()
|
| 133 |
+
self.assertIs(sys.stdout, orig_stdout)
|
| 134 |
+
self.assertIs(sys.stderr, orig_stderr)
|
| 135 |
+
else:
|
| 136 |
+
def fake_std():
|
| 137 |
+
# Emulate stdout=not a tty, stderr=tty
|
| 138 |
+
# to check that we handle both cases correctly
|
| 139 |
+
stdout = Mock()
|
| 140 |
+
stdout.closed = False
|
| 141 |
+
stdout.isatty.return_value = False
|
| 142 |
+
stdout.fileno.return_value = 1
|
| 143 |
+
sys.stdout = stdout
|
| 144 |
+
|
| 145 |
+
stderr = Mock()
|
| 146 |
+
stderr.closed = False
|
| 147 |
+
stderr.isatty.return_value = True
|
| 148 |
+
stderr.fileno.return_value = 2
|
| 149 |
+
sys.stderr = stderr
|
| 150 |
+
|
| 151 |
+
for native_ansi in [False, True]:
|
| 152 |
+
with patch(
|
| 153 |
+
'colorama.ansitowin32.enable_vt_processing',
|
| 154 |
+
lambda *_: native_ansi
|
| 155 |
+
):
|
| 156 |
+
self._reset()
|
| 157 |
+
fake_std()
|
| 158 |
+
|
| 159 |
+
# Regular single-call test
|
| 160 |
+
prev_stdout = sys.stdout
|
| 161 |
+
prev_stderr = sys.stderr
|
| 162 |
+
just_fix_windows_console()
|
| 163 |
+
self.assertIs(sys.stdout, prev_stdout)
|
| 164 |
+
if native_ansi:
|
| 165 |
+
self.assertIs(sys.stderr, prev_stderr)
|
| 166 |
+
else:
|
| 167 |
+
self.assertIsNot(sys.stderr, prev_stderr)
|
| 168 |
+
|
| 169 |
+
# second call without resetting is always a no-op
|
| 170 |
+
prev_stdout = sys.stdout
|
| 171 |
+
prev_stderr = sys.stderr
|
| 172 |
+
just_fix_windows_console()
|
| 173 |
+
self.assertIs(sys.stdout, prev_stdout)
|
| 174 |
+
self.assertIs(sys.stderr, prev_stderr)
|
| 175 |
+
|
| 176 |
+
self._reset()
|
| 177 |
+
fake_std()
|
| 178 |
+
|
| 179 |
+
# If init() runs first, just_fix_windows_console should be a no-op
|
| 180 |
+
init()
|
| 181 |
+
prev_stdout = sys.stdout
|
| 182 |
+
prev_stderr = sys.stderr
|
| 183 |
+
just_fix_windows_console()
|
| 184 |
+
self.assertIs(prev_stdout, sys.stdout)
|
| 185 |
+
self.assertIs(prev_stderr, sys.stderr)
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
if __name__ == '__main__':
|
| 189 |
+
main()
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/isatty_test.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
| 2 |
+
import sys
|
| 3 |
+
from unittest import TestCase, main
|
| 4 |
+
|
| 5 |
+
from ..ansitowin32 import StreamWrapper, AnsiToWin32
|
| 6 |
+
from .utils import pycharm, replace_by, replace_original_by, StreamTTY, StreamNonTTY
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def is_a_tty(stream):
|
| 10 |
+
return StreamWrapper(stream, None).isatty()
|
| 11 |
+
|
| 12 |
+
class IsattyTest(TestCase):
|
| 13 |
+
|
| 14 |
+
def test_TTY(self):
|
| 15 |
+
tty = StreamTTY()
|
| 16 |
+
self.assertTrue(is_a_tty(tty))
|
| 17 |
+
with pycharm():
|
| 18 |
+
self.assertTrue(is_a_tty(tty))
|
| 19 |
+
|
| 20 |
+
def test_nonTTY(self):
|
| 21 |
+
non_tty = StreamNonTTY()
|
| 22 |
+
self.assertFalse(is_a_tty(non_tty))
|
| 23 |
+
with pycharm():
|
| 24 |
+
self.assertFalse(is_a_tty(non_tty))
|
| 25 |
+
|
| 26 |
+
def test_withPycharm(self):
|
| 27 |
+
with pycharm():
|
| 28 |
+
self.assertTrue(is_a_tty(sys.stderr))
|
| 29 |
+
self.assertTrue(is_a_tty(sys.stdout))
|
| 30 |
+
|
| 31 |
+
def test_withPycharmTTYOverride(self):
|
| 32 |
+
tty = StreamTTY()
|
| 33 |
+
with pycharm(), replace_by(tty):
|
| 34 |
+
self.assertTrue(is_a_tty(tty))
|
| 35 |
+
|
| 36 |
+
def test_withPycharmNonTTYOverride(self):
|
| 37 |
+
non_tty = StreamNonTTY()
|
| 38 |
+
with pycharm(), replace_by(non_tty):
|
| 39 |
+
self.assertFalse(is_a_tty(non_tty))
|
| 40 |
+
|
| 41 |
+
def test_withPycharmNoneOverride(self):
|
| 42 |
+
with pycharm():
|
| 43 |
+
with replace_by(None), replace_original_by(None):
|
| 44 |
+
self.assertFalse(is_a_tty(None))
|
| 45 |
+
self.assertFalse(is_a_tty(StreamNonTTY()))
|
| 46 |
+
self.assertTrue(is_a_tty(StreamTTY()))
|
| 47 |
+
|
| 48 |
+
def test_withPycharmStreamWrapped(self):
|
| 49 |
+
with pycharm():
|
| 50 |
+
self.assertTrue(AnsiToWin32(StreamTTY()).stream.isatty())
|
| 51 |
+
self.assertFalse(AnsiToWin32(StreamNonTTY()).stream.isatty())
|
| 52 |
+
self.assertTrue(AnsiToWin32(sys.stdout).stream.isatty())
|
| 53 |
+
self.assertTrue(AnsiToWin32(sys.stderr).stream.isatty())
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
if __name__ == '__main__':
|
| 57 |
+
main()
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/utils.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
| 2 |
+
from contextlib import contextmanager
|
| 3 |
+
from io import StringIO
|
| 4 |
+
import sys
|
| 5 |
+
import os
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class StreamTTY(StringIO):
|
| 9 |
+
def isatty(self):
|
| 10 |
+
return True
|
| 11 |
+
|
| 12 |
+
class StreamNonTTY(StringIO):
|
| 13 |
+
def isatty(self):
|
| 14 |
+
return False
|
| 15 |
+
|
| 16 |
+
@contextmanager
|
| 17 |
+
def osname(name):
|
| 18 |
+
orig = os.name
|
| 19 |
+
os.name = name
|
| 20 |
+
yield
|
| 21 |
+
os.name = orig
|
| 22 |
+
|
| 23 |
+
@contextmanager
|
| 24 |
+
def replace_by(stream):
|
| 25 |
+
orig_stdout = sys.stdout
|
| 26 |
+
orig_stderr = sys.stderr
|
| 27 |
+
sys.stdout = stream
|
| 28 |
+
sys.stderr = stream
|
| 29 |
+
yield
|
| 30 |
+
sys.stdout = orig_stdout
|
| 31 |
+
sys.stderr = orig_stderr
|
| 32 |
+
|
| 33 |
+
@contextmanager
|
| 34 |
+
def replace_original_by(stream):
|
| 35 |
+
orig_stdout = sys.__stdout__
|
| 36 |
+
orig_stderr = sys.__stderr__
|
| 37 |
+
sys.__stdout__ = stream
|
| 38 |
+
sys.__stderr__ = stream
|
| 39 |
+
yield
|
| 40 |
+
sys.__stdout__ = orig_stdout
|
| 41 |
+
sys.__stderr__ = orig_stderr
|
| 42 |
+
|
| 43 |
+
@contextmanager
|
| 44 |
+
def pycharm():
|
| 45 |
+
os.environ["PYCHARM_HOSTED"] = "1"
|
| 46 |
+
non_tty = StreamNonTTY()
|
| 47 |
+
with replace_by(non_tty), replace_original_by(non_tty):
|
| 48 |
+
yield
|
| 49 |
+
del os.environ["PYCHARM_HOSTED"]
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/tests/winterm_test.py
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
| 2 |
+
import sys
|
| 3 |
+
from unittest import TestCase, main, skipUnless
|
| 4 |
+
|
| 5 |
+
try:
|
| 6 |
+
from unittest.mock import Mock, patch
|
| 7 |
+
except ImportError:
|
| 8 |
+
from mock import Mock, patch
|
| 9 |
+
|
| 10 |
+
from ..winterm import WinColor, WinStyle, WinTerm
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class WinTermTest(TestCase):
|
| 14 |
+
|
| 15 |
+
@patch('colorama.winterm.win32')
|
| 16 |
+
def testInit(self, mockWin32):
|
| 17 |
+
mockAttr = Mock()
|
| 18 |
+
mockAttr.wAttributes = 7 + 6 * 16 + 8
|
| 19 |
+
mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr
|
| 20 |
+
term = WinTerm()
|
| 21 |
+
self.assertEqual(term._fore, 7)
|
| 22 |
+
self.assertEqual(term._back, 6)
|
| 23 |
+
self.assertEqual(term._style, 8)
|
| 24 |
+
|
| 25 |
+
@skipUnless(sys.platform.startswith("win"), "requires Windows")
|
| 26 |
+
def testGetAttrs(self):
|
| 27 |
+
term = WinTerm()
|
| 28 |
+
|
| 29 |
+
term._fore = 0
|
| 30 |
+
term._back = 0
|
| 31 |
+
term._style = 0
|
| 32 |
+
self.assertEqual(term.get_attrs(), 0)
|
| 33 |
+
|
| 34 |
+
term._fore = WinColor.YELLOW
|
| 35 |
+
self.assertEqual(term.get_attrs(), WinColor.YELLOW)
|
| 36 |
+
|
| 37 |
+
term._back = WinColor.MAGENTA
|
| 38 |
+
self.assertEqual(
|
| 39 |
+
term.get_attrs(),
|
| 40 |
+
WinColor.YELLOW + WinColor.MAGENTA * 16)
|
| 41 |
+
|
| 42 |
+
term._style = WinStyle.BRIGHT
|
| 43 |
+
self.assertEqual(
|
| 44 |
+
term.get_attrs(),
|
| 45 |
+
WinColor.YELLOW + WinColor.MAGENTA * 16 + WinStyle.BRIGHT)
|
| 46 |
+
|
| 47 |
+
@patch('colorama.winterm.win32')
|
| 48 |
+
def testResetAll(self, mockWin32):
|
| 49 |
+
mockAttr = Mock()
|
| 50 |
+
mockAttr.wAttributes = 1 + 2 * 16 + 8
|
| 51 |
+
mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr
|
| 52 |
+
term = WinTerm()
|
| 53 |
+
|
| 54 |
+
term.set_console = Mock()
|
| 55 |
+
term._fore = -1
|
| 56 |
+
term._back = -1
|
| 57 |
+
term._style = -1
|
| 58 |
+
|
| 59 |
+
term.reset_all()
|
| 60 |
+
|
| 61 |
+
self.assertEqual(term._fore, 1)
|
| 62 |
+
self.assertEqual(term._back, 2)
|
| 63 |
+
self.assertEqual(term._style, 8)
|
| 64 |
+
self.assertEqual(term.set_console.called, True)
|
| 65 |
+
|
| 66 |
+
@skipUnless(sys.platform.startswith("win"), "requires Windows")
|
| 67 |
+
def testFore(self):
|
| 68 |
+
term = WinTerm()
|
| 69 |
+
term.set_console = Mock()
|
| 70 |
+
term._fore = 0
|
| 71 |
+
|
| 72 |
+
term.fore(5)
|
| 73 |
+
|
| 74 |
+
self.assertEqual(term._fore, 5)
|
| 75 |
+
self.assertEqual(term.set_console.called, True)
|
| 76 |
+
|
| 77 |
+
@skipUnless(sys.platform.startswith("win"), "requires Windows")
|
| 78 |
+
def testBack(self):
|
| 79 |
+
term = WinTerm()
|
| 80 |
+
term.set_console = Mock()
|
| 81 |
+
term._back = 0
|
| 82 |
+
|
| 83 |
+
term.back(5)
|
| 84 |
+
|
| 85 |
+
self.assertEqual(term._back, 5)
|
| 86 |
+
self.assertEqual(term.set_console.called, True)
|
| 87 |
+
|
| 88 |
+
@skipUnless(sys.platform.startswith("win"), "requires Windows")
|
| 89 |
+
def testStyle(self):
|
| 90 |
+
term = WinTerm()
|
| 91 |
+
term.set_console = Mock()
|
| 92 |
+
term._style = 0
|
| 93 |
+
|
| 94 |
+
term.style(22)
|
| 95 |
+
|
| 96 |
+
self.assertEqual(term._style, 22)
|
| 97 |
+
self.assertEqual(term.set_console.called, True)
|
| 98 |
+
|
| 99 |
+
@patch('colorama.winterm.win32')
|
| 100 |
+
def testSetConsole(self, mockWin32):
|
| 101 |
+
mockAttr = Mock()
|
| 102 |
+
mockAttr.wAttributes = 0
|
| 103 |
+
mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr
|
| 104 |
+
term = WinTerm()
|
| 105 |
+
term.windll = Mock()
|
| 106 |
+
|
| 107 |
+
term.set_console()
|
| 108 |
+
|
| 109 |
+
self.assertEqual(
|
| 110 |
+
mockWin32.SetConsoleTextAttribute.call_args,
|
| 111 |
+
((mockWin32.STDOUT, term.get_attrs()), {})
|
| 112 |
+
)
|
| 113 |
+
|
| 114 |
+
@patch('colorama.winterm.win32')
|
| 115 |
+
def testSetConsoleOnStderr(self, mockWin32):
|
| 116 |
+
mockAttr = Mock()
|
| 117 |
+
mockAttr.wAttributes = 0
|
| 118 |
+
mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr
|
| 119 |
+
term = WinTerm()
|
| 120 |
+
term.windll = Mock()
|
| 121 |
+
|
| 122 |
+
term.set_console(on_stderr=True)
|
| 123 |
+
|
| 124 |
+
self.assertEqual(
|
| 125 |
+
mockWin32.SetConsoleTextAttribute.call_args,
|
| 126 |
+
((mockWin32.STDERR, term.get_attrs()), {})
|
| 127 |
+
)
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
if __name__ == '__main__':
|
| 131 |
+
main()
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/win32.py
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
| 2 |
+
|
| 3 |
+
# from winbase.h
|
| 4 |
+
STDOUT = -11
|
| 5 |
+
STDERR = -12
|
| 6 |
+
|
| 7 |
+
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
|
| 8 |
+
|
| 9 |
+
try:
|
| 10 |
+
import ctypes
|
| 11 |
+
from ctypes import LibraryLoader
|
| 12 |
+
windll = LibraryLoader(ctypes.WinDLL)
|
| 13 |
+
from ctypes import wintypes
|
| 14 |
+
except (AttributeError, ImportError):
|
| 15 |
+
windll = None
|
| 16 |
+
SetConsoleTextAttribute = lambda *_: None
|
| 17 |
+
winapi_test = lambda *_: None
|
| 18 |
+
else:
|
| 19 |
+
from ctypes import byref, Structure, c_char, POINTER
|
| 20 |
+
|
| 21 |
+
COORD = wintypes._COORD
|
| 22 |
+
|
| 23 |
+
class CONSOLE_SCREEN_BUFFER_INFO(Structure):
|
| 24 |
+
"""struct in wincon.h."""
|
| 25 |
+
_fields_ = [
|
| 26 |
+
("dwSize", COORD),
|
| 27 |
+
("dwCursorPosition", COORD),
|
| 28 |
+
("wAttributes", wintypes.WORD),
|
| 29 |
+
("srWindow", wintypes.SMALL_RECT),
|
| 30 |
+
("dwMaximumWindowSize", COORD),
|
| 31 |
+
]
|
| 32 |
+
def __str__(self):
|
| 33 |
+
return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % (
|
| 34 |
+
self.dwSize.Y, self.dwSize.X
|
| 35 |
+
, self.dwCursorPosition.Y, self.dwCursorPosition.X
|
| 36 |
+
, self.wAttributes
|
| 37 |
+
, self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right
|
| 38 |
+
, self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X
|
| 39 |
+
)
|
| 40 |
+
|
| 41 |
+
_GetStdHandle = windll.kernel32.GetStdHandle
|
| 42 |
+
_GetStdHandle.argtypes = [
|
| 43 |
+
wintypes.DWORD,
|
| 44 |
+
]
|
| 45 |
+
_GetStdHandle.restype = wintypes.HANDLE
|
| 46 |
+
|
| 47 |
+
_GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo
|
| 48 |
+
_GetConsoleScreenBufferInfo.argtypes = [
|
| 49 |
+
wintypes.HANDLE,
|
| 50 |
+
POINTER(CONSOLE_SCREEN_BUFFER_INFO),
|
| 51 |
+
]
|
| 52 |
+
_GetConsoleScreenBufferInfo.restype = wintypes.BOOL
|
| 53 |
+
|
| 54 |
+
_SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
|
| 55 |
+
_SetConsoleTextAttribute.argtypes = [
|
| 56 |
+
wintypes.HANDLE,
|
| 57 |
+
wintypes.WORD,
|
| 58 |
+
]
|
| 59 |
+
_SetConsoleTextAttribute.restype = wintypes.BOOL
|
| 60 |
+
|
| 61 |
+
_SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition
|
| 62 |
+
_SetConsoleCursorPosition.argtypes = [
|
| 63 |
+
wintypes.HANDLE,
|
| 64 |
+
COORD,
|
| 65 |
+
]
|
| 66 |
+
_SetConsoleCursorPosition.restype = wintypes.BOOL
|
| 67 |
+
|
| 68 |
+
_FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA
|
| 69 |
+
_FillConsoleOutputCharacterA.argtypes = [
|
| 70 |
+
wintypes.HANDLE,
|
| 71 |
+
c_char,
|
| 72 |
+
wintypes.DWORD,
|
| 73 |
+
COORD,
|
| 74 |
+
POINTER(wintypes.DWORD),
|
| 75 |
+
]
|
| 76 |
+
_FillConsoleOutputCharacterA.restype = wintypes.BOOL
|
| 77 |
+
|
| 78 |
+
_FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute
|
| 79 |
+
_FillConsoleOutputAttribute.argtypes = [
|
| 80 |
+
wintypes.HANDLE,
|
| 81 |
+
wintypes.WORD,
|
| 82 |
+
wintypes.DWORD,
|
| 83 |
+
COORD,
|
| 84 |
+
POINTER(wintypes.DWORD),
|
| 85 |
+
]
|
| 86 |
+
_FillConsoleOutputAttribute.restype = wintypes.BOOL
|
| 87 |
+
|
| 88 |
+
_SetConsoleTitleW = windll.kernel32.SetConsoleTitleW
|
| 89 |
+
_SetConsoleTitleW.argtypes = [
|
| 90 |
+
wintypes.LPCWSTR
|
| 91 |
+
]
|
| 92 |
+
_SetConsoleTitleW.restype = wintypes.BOOL
|
| 93 |
+
|
| 94 |
+
_GetConsoleMode = windll.kernel32.GetConsoleMode
|
| 95 |
+
_GetConsoleMode.argtypes = [
|
| 96 |
+
wintypes.HANDLE,
|
| 97 |
+
POINTER(wintypes.DWORD)
|
| 98 |
+
]
|
| 99 |
+
_GetConsoleMode.restype = wintypes.BOOL
|
| 100 |
+
|
| 101 |
+
_SetConsoleMode = windll.kernel32.SetConsoleMode
|
| 102 |
+
_SetConsoleMode.argtypes = [
|
| 103 |
+
wintypes.HANDLE,
|
| 104 |
+
wintypes.DWORD
|
| 105 |
+
]
|
| 106 |
+
_SetConsoleMode.restype = wintypes.BOOL
|
| 107 |
+
|
| 108 |
+
def _winapi_test(handle):
|
| 109 |
+
csbi = CONSOLE_SCREEN_BUFFER_INFO()
|
| 110 |
+
success = _GetConsoleScreenBufferInfo(
|
| 111 |
+
handle, byref(csbi))
|
| 112 |
+
return bool(success)
|
| 113 |
+
|
| 114 |
+
def winapi_test():
|
| 115 |
+
return any(_winapi_test(h) for h in
|
| 116 |
+
(_GetStdHandle(STDOUT), _GetStdHandle(STDERR)))
|
| 117 |
+
|
| 118 |
+
def GetConsoleScreenBufferInfo(stream_id=STDOUT):
|
| 119 |
+
handle = _GetStdHandle(stream_id)
|
| 120 |
+
csbi = CONSOLE_SCREEN_BUFFER_INFO()
|
| 121 |
+
success = _GetConsoleScreenBufferInfo(
|
| 122 |
+
handle, byref(csbi))
|
| 123 |
+
return csbi
|
| 124 |
+
|
| 125 |
+
def SetConsoleTextAttribute(stream_id, attrs):
|
| 126 |
+
handle = _GetStdHandle(stream_id)
|
| 127 |
+
return _SetConsoleTextAttribute(handle, attrs)
|
| 128 |
+
|
| 129 |
+
def SetConsoleCursorPosition(stream_id, position, adjust=True):
|
| 130 |
+
position = COORD(*position)
|
| 131 |
+
# If the position is out of range, do nothing.
|
| 132 |
+
if position.Y <= 0 or position.X <= 0:
|
| 133 |
+
return
|
| 134 |
+
# Adjust for Windows' SetConsoleCursorPosition:
|
| 135 |
+
# 1. being 0-based, while ANSI is 1-based.
|
| 136 |
+
# 2. expecting (x,y), while ANSI uses (y,x).
|
| 137 |
+
adjusted_position = COORD(position.Y - 1, position.X - 1)
|
| 138 |
+
if adjust:
|
| 139 |
+
# Adjust for viewport's scroll position
|
| 140 |
+
sr = GetConsoleScreenBufferInfo(STDOUT).srWindow
|
| 141 |
+
adjusted_position.Y += sr.Top
|
| 142 |
+
adjusted_position.X += sr.Left
|
| 143 |
+
# Resume normal processing
|
| 144 |
+
handle = _GetStdHandle(stream_id)
|
| 145 |
+
return _SetConsoleCursorPosition(handle, adjusted_position)
|
| 146 |
+
|
| 147 |
+
def FillConsoleOutputCharacter(stream_id, char, length, start):
|
| 148 |
+
handle = _GetStdHandle(stream_id)
|
| 149 |
+
char = c_char(char.encode())
|
| 150 |
+
length = wintypes.DWORD(length)
|
| 151 |
+
num_written = wintypes.DWORD(0)
|
| 152 |
+
# Note that this is hard-coded for ANSI (vs wide) bytes.
|
| 153 |
+
success = _FillConsoleOutputCharacterA(
|
| 154 |
+
handle, char, length, start, byref(num_written))
|
| 155 |
+
return num_written.value
|
| 156 |
+
|
| 157 |
+
def FillConsoleOutputAttribute(stream_id, attr, length, start):
|
| 158 |
+
''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )'''
|
| 159 |
+
handle = _GetStdHandle(stream_id)
|
| 160 |
+
attribute = wintypes.WORD(attr)
|
| 161 |
+
length = wintypes.DWORD(length)
|
| 162 |
+
num_written = wintypes.DWORD(0)
|
| 163 |
+
# Note that this is hard-coded for ANSI (vs wide) bytes.
|
| 164 |
+
return _FillConsoleOutputAttribute(
|
| 165 |
+
handle, attribute, length, start, byref(num_written))
|
| 166 |
+
|
| 167 |
+
def SetConsoleTitle(title):
|
| 168 |
+
return _SetConsoleTitleW(title)
|
| 169 |
+
|
| 170 |
+
def GetConsoleMode(handle):
|
| 171 |
+
mode = wintypes.DWORD()
|
| 172 |
+
success = _GetConsoleMode(handle, byref(mode))
|
| 173 |
+
if not success:
|
| 174 |
+
raise ctypes.WinError()
|
| 175 |
+
return mode.value
|
| 176 |
+
|
| 177 |
+
def SetConsoleMode(handle, mode):
|
| 178 |
+
success = _SetConsoleMode(handle, mode)
|
| 179 |
+
if not success:
|
| 180 |
+
raise ctypes.WinError()
|
.venv/lib/python3.11/site-packages/pip/_vendor/colorama/winterm.py
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
|
| 2 |
+
try:
|
| 3 |
+
from msvcrt import get_osfhandle
|
| 4 |
+
except ImportError:
|
| 5 |
+
def get_osfhandle(_):
|
| 6 |
+
raise OSError("This isn't windows!")
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
from . import win32
|
| 10 |
+
|
| 11 |
+
# from wincon.h
|
| 12 |
+
class WinColor(object):
|
| 13 |
+
BLACK = 0
|
| 14 |
+
BLUE = 1
|
| 15 |
+
GREEN = 2
|
| 16 |
+
CYAN = 3
|
| 17 |
+
RED = 4
|
| 18 |
+
MAGENTA = 5
|
| 19 |
+
YELLOW = 6
|
| 20 |
+
GREY = 7
|
| 21 |
+
|
| 22 |
+
# from wincon.h
|
| 23 |
+
class WinStyle(object):
|
| 24 |
+
NORMAL = 0x00 # dim text, dim background
|
| 25 |
+
BRIGHT = 0x08 # bright text, dim background
|
| 26 |
+
BRIGHT_BACKGROUND = 0x80 # dim text, bright background
|
| 27 |
+
|
| 28 |
+
class WinTerm(object):
|
| 29 |
+
|
| 30 |
+
def __init__(self):
|
| 31 |
+
self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes
|
| 32 |
+
self.set_attrs(self._default)
|
| 33 |
+
self._default_fore = self._fore
|
| 34 |
+
self._default_back = self._back
|
| 35 |
+
self._default_style = self._style
|
| 36 |
+
# In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style.
|
| 37 |
+
# So that LIGHT_EX colors and BRIGHT style do not clobber each other,
|
| 38 |
+
# we track them separately, since LIGHT_EX is overwritten by Fore/Back
|
| 39 |
+
# and BRIGHT is overwritten by Style codes.
|
| 40 |
+
self._light = 0
|
| 41 |
+
|
| 42 |
+
def get_attrs(self):
|
| 43 |
+
return self._fore + self._back * 16 + (self._style | self._light)
|
| 44 |
+
|
| 45 |
+
def set_attrs(self, value):
|
| 46 |
+
self._fore = value & 7
|
| 47 |
+
self._back = (value >> 4) & 7
|
| 48 |
+
self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND)
|
| 49 |
+
|
| 50 |
+
def reset_all(self, on_stderr=None):
|
| 51 |
+
self.set_attrs(self._default)
|
| 52 |
+
self.set_console(attrs=self._default)
|
| 53 |
+
self._light = 0
|
| 54 |
+
|
| 55 |
+
def fore(self, fore=None, light=False, on_stderr=False):
|
| 56 |
+
if fore is None:
|
| 57 |
+
fore = self._default_fore
|
| 58 |
+
self._fore = fore
|
| 59 |
+
# Emulate LIGHT_EX with BRIGHT Style
|
| 60 |
+
if light:
|
| 61 |
+
self._light |= WinStyle.BRIGHT
|
| 62 |
+
else:
|
| 63 |
+
self._light &= ~WinStyle.BRIGHT
|
| 64 |
+
self.set_console(on_stderr=on_stderr)
|
| 65 |
+
|
| 66 |
+
def back(self, back=None, light=False, on_stderr=False):
|
| 67 |
+
if back is None:
|
| 68 |
+
back = self._default_back
|
| 69 |
+
self._back = back
|
| 70 |
+
# Emulate LIGHT_EX with BRIGHT_BACKGROUND Style
|
| 71 |
+
if light:
|
| 72 |
+
self._light |= WinStyle.BRIGHT_BACKGROUND
|
| 73 |
+
else:
|
| 74 |
+
self._light &= ~WinStyle.BRIGHT_BACKGROUND
|
| 75 |
+
self.set_console(on_stderr=on_stderr)
|
| 76 |
+
|
| 77 |
+
def style(self, style=None, on_stderr=False):
|
| 78 |
+
if style is None:
|
| 79 |
+
style = self._default_style
|
| 80 |
+
self._style = style
|
| 81 |
+
self.set_console(on_stderr=on_stderr)
|
| 82 |
+
|
| 83 |
+
def set_console(self, attrs=None, on_stderr=False):
|
| 84 |
+
if attrs is None:
|
| 85 |
+
attrs = self.get_attrs()
|
| 86 |
+
handle = win32.STDOUT
|
| 87 |
+
if on_stderr:
|
| 88 |
+
handle = win32.STDERR
|
| 89 |
+
win32.SetConsoleTextAttribute(handle, attrs)
|
| 90 |
+
|
| 91 |
+
def get_position(self, handle):
|
| 92 |
+
position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition
|
| 93 |
+
# Because Windows coordinates are 0-based,
|
| 94 |
+
# and win32.SetConsoleCursorPosition expects 1-based.
|
| 95 |
+
position.X += 1
|
| 96 |
+
position.Y += 1
|
| 97 |
+
return position
|
| 98 |
+
|
| 99 |
+
def set_cursor_position(self, position=None, on_stderr=False):
|
| 100 |
+
if position is None:
|
| 101 |
+
# I'm not currently tracking the position, so there is no default.
|
| 102 |
+
# position = self.get_position()
|
| 103 |
+
return
|
| 104 |
+
handle = win32.STDOUT
|
| 105 |
+
if on_stderr:
|
| 106 |
+
handle = win32.STDERR
|
| 107 |
+
win32.SetConsoleCursorPosition(handle, position)
|
| 108 |
+
|
| 109 |
+
def cursor_adjust(self, x, y, on_stderr=False):
|
| 110 |
+
handle = win32.STDOUT
|
| 111 |
+
if on_stderr:
|
| 112 |
+
handle = win32.STDERR
|
| 113 |
+
position = self.get_position(handle)
|
| 114 |
+
adjusted_position = (position.Y + y, position.X + x)
|
| 115 |
+
win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False)
|
| 116 |
+
|
| 117 |
+
def erase_screen(self, mode=0, on_stderr=False):
|
| 118 |
+
# 0 should clear from the cursor to the end of the screen.
|
| 119 |
+
# 1 should clear from the cursor to the beginning of the screen.
|
| 120 |
+
# 2 should clear the entire screen, and move cursor to (1,1)
|
| 121 |
+
handle = win32.STDOUT
|
| 122 |
+
if on_stderr:
|
| 123 |
+
handle = win32.STDERR
|
| 124 |
+
csbi = win32.GetConsoleScreenBufferInfo(handle)
|
| 125 |
+
# get the number of character cells in the current buffer
|
| 126 |
+
cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y
|
| 127 |
+
# get number of character cells before current cursor position
|
| 128 |
+
cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X
|
| 129 |
+
if mode == 0:
|
| 130 |
+
from_coord = csbi.dwCursorPosition
|
| 131 |
+
cells_to_erase = cells_in_screen - cells_before_cursor
|
| 132 |
+
elif mode == 1:
|
| 133 |
+
from_coord = win32.COORD(0, 0)
|
| 134 |
+
cells_to_erase = cells_before_cursor
|
| 135 |
+
elif mode == 2:
|
| 136 |
+
from_coord = win32.COORD(0, 0)
|
| 137 |
+
cells_to_erase = cells_in_screen
|
| 138 |
+
else:
|
| 139 |
+
# invalid mode
|
| 140 |
+
return
|
| 141 |
+
# fill the entire screen with blanks
|
| 142 |
+
win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord)
|
| 143 |
+
# now set the buffer's attributes accordingly
|
| 144 |
+
win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord)
|
| 145 |
+
if mode == 2:
|
| 146 |
+
# put the cursor where needed
|
| 147 |
+
win32.SetConsoleCursorPosition(handle, (1, 1))
|
| 148 |
+
|
| 149 |
+
def erase_line(self, mode=0, on_stderr=False):
|
| 150 |
+
# 0 should clear from the cursor to the end of the line.
|
| 151 |
+
# 1 should clear from the cursor to the beginning of the line.
|
| 152 |
+
# 2 should clear the entire line.
|
| 153 |
+
handle = win32.STDOUT
|
| 154 |
+
if on_stderr:
|
| 155 |
+
handle = win32.STDERR
|
| 156 |
+
csbi = win32.GetConsoleScreenBufferInfo(handle)
|
| 157 |
+
if mode == 0:
|
| 158 |
+
from_coord = csbi.dwCursorPosition
|
| 159 |
+
cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X
|
| 160 |
+
elif mode == 1:
|
| 161 |
+
from_coord = win32.COORD(0, csbi.dwCursorPosition.Y)
|
| 162 |
+
cells_to_erase = csbi.dwCursorPosition.X
|
| 163 |
+
elif mode == 2:
|
| 164 |
+
from_coord = win32.COORD(0, csbi.dwCursorPosition.Y)
|
| 165 |
+
cells_to_erase = csbi.dwSize.X
|
| 166 |
+
else:
|
| 167 |
+
# invalid mode
|
| 168 |
+
return
|
| 169 |
+
# fill the entire screen with blanks
|
| 170 |
+
win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord)
|
| 171 |
+
# now set the buffer's attributes accordingly
|
| 172 |
+
win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord)
|
| 173 |
+
|
| 174 |
+
def set_title(self, title):
|
| 175 |
+
win32.SetConsoleTitle(title)
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
def enable_vt_processing(fd):
|
| 179 |
+
if win32.windll is None or not win32.winapi_test():
|
| 180 |
+
return False
|
| 181 |
+
|
| 182 |
+
try:
|
| 183 |
+
handle = get_osfhandle(fd)
|
| 184 |
+
mode = win32.GetConsoleMode(handle)
|
| 185 |
+
win32.SetConsoleMode(
|
| 186 |
+
handle,
|
| 187 |
+
mode | win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING,
|
| 188 |
+
)
|
| 189 |
+
|
| 190 |
+
mode = win32.GetConsoleMode(handle)
|
| 191 |
+
if mode & win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING:
|
| 192 |
+
return True
|
| 193 |
+
# Can get TypeError in testsuite where 'fd' is a Mock()
|
| 194 |
+
except (OSError, TypeError):
|
| 195 |
+
return False
|
.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (2.07 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-311.pyc
ADDED
|
Binary file (2.37 kB). View file
|
|
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/__main__.py
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import colorsys
|
| 2 |
+
import io
|
| 3 |
+
from time import process_time
|
| 4 |
+
|
| 5 |
+
from pip._vendor.rich import box
|
| 6 |
+
from pip._vendor.rich.color import Color
|
| 7 |
+
from pip._vendor.rich.console import Console, ConsoleOptions, Group, RenderableType, RenderResult
|
| 8 |
+
from pip._vendor.rich.markdown import Markdown
|
| 9 |
+
from pip._vendor.rich.measure import Measurement
|
| 10 |
+
from pip._vendor.rich.pretty import Pretty
|
| 11 |
+
from pip._vendor.rich.segment import Segment
|
| 12 |
+
from pip._vendor.rich.style import Style
|
| 13 |
+
from pip._vendor.rich.syntax import Syntax
|
| 14 |
+
from pip._vendor.rich.table import Table
|
| 15 |
+
from pip._vendor.rich.text import Text
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
class ColorBox:
|
| 19 |
+
def __rich_console__(
|
| 20 |
+
self, console: Console, options: ConsoleOptions
|
| 21 |
+
) -> RenderResult:
|
| 22 |
+
for y in range(0, 5):
|
| 23 |
+
for x in range(options.max_width):
|
| 24 |
+
h = x / options.max_width
|
| 25 |
+
l = 0.1 + ((y / 5) * 0.7)
|
| 26 |
+
r1, g1, b1 = colorsys.hls_to_rgb(h, l, 1.0)
|
| 27 |
+
r2, g2, b2 = colorsys.hls_to_rgb(h, l + 0.7 / 10, 1.0)
|
| 28 |
+
bgcolor = Color.from_rgb(r1 * 255, g1 * 255, b1 * 255)
|
| 29 |
+
color = Color.from_rgb(r2 * 255, g2 * 255, b2 * 255)
|
| 30 |
+
yield Segment("▄", Style(color=color, bgcolor=bgcolor))
|
| 31 |
+
yield Segment.line()
|
| 32 |
+
|
| 33 |
+
def __rich_measure__(
|
| 34 |
+
self, console: "Console", options: ConsoleOptions
|
| 35 |
+
) -> Measurement:
|
| 36 |
+
return Measurement(1, options.max_width)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def make_test_card() -> Table:
|
| 40 |
+
"""Get a renderable that demonstrates a number of features."""
|
| 41 |
+
table = Table.grid(padding=1, pad_edge=True)
|
| 42 |
+
table.title = "Rich features"
|
| 43 |
+
table.add_column("Feature", no_wrap=True, justify="center", style="bold red")
|
| 44 |
+
table.add_column("Demonstration")
|
| 45 |
+
|
| 46 |
+
color_table = Table(
|
| 47 |
+
box=None,
|
| 48 |
+
expand=False,
|
| 49 |
+
show_header=False,
|
| 50 |
+
show_edge=False,
|
| 51 |
+
pad_edge=False,
|
| 52 |
+
)
|
| 53 |
+
color_table.add_row(
|
| 54 |
+
(
|
| 55 |
+
"✓ [bold green]4-bit color[/]\n"
|
| 56 |
+
"✓ [bold blue]8-bit color[/]\n"
|
| 57 |
+
"✓ [bold magenta]Truecolor (16.7 million)[/]\n"
|
| 58 |
+
"✓ [bold yellow]Dumb terminals[/]\n"
|
| 59 |
+
"✓ [bold cyan]Automatic color conversion"
|
| 60 |
+
),
|
| 61 |
+
ColorBox(),
|
| 62 |
+
)
|
| 63 |
+
|
| 64 |
+
table.add_row("Colors", color_table)
|
| 65 |
+
|
| 66 |
+
table.add_row(
|
| 67 |
+
"Styles",
|
| 68 |
+
"All ansi styles: [bold]bold[/], [dim]dim[/], [italic]italic[/italic], [underline]underline[/], [strike]strikethrough[/], [reverse]reverse[/], and even [blink]blink[/].",
|
| 69 |
+
)
|
| 70 |
+
|
| 71 |
+
lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque in metus sed sapien ultricies pretium a at justo. Maecenas luctus velit et auctor maximus."
|
| 72 |
+
lorem_table = Table.grid(padding=1, collapse_padding=True)
|
| 73 |
+
lorem_table.pad_edge = False
|
| 74 |
+
lorem_table.add_row(
|
| 75 |
+
Text(lorem, justify="left", style="green"),
|
| 76 |
+
Text(lorem, justify="center", style="yellow"),
|
| 77 |
+
Text(lorem, justify="right", style="blue"),
|
| 78 |
+
Text(lorem, justify="full", style="red"),
|
| 79 |
+
)
|
| 80 |
+
table.add_row(
|
| 81 |
+
"Text",
|
| 82 |
+
Group(
|
| 83 |
+
Text.from_markup(
|
| 84 |
+
"""Word wrap text. Justify [green]left[/], [yellow]center[/], [blue]right[/] or [red]full[/].\n"""
|
| 85 |
+
),
|
| 86 |
+
lorem_table,
|
| 87 |
+
),
|
| 88 |
+
)
|
| 89 |
+
|
| 90 |
+
def comparison(renderable1: RenderableType, renderable2: RenderableType) -> Table:
|
| 91 |
+
table = Table(show_header=False, pad_edge=False, box=None, expand=True)
|
| 92 |
+
table.add_column("1", ratio=1)
|
| 93 |
+
table.add_column("2", ratio=1)
|
| 94 |
+
table.add_row(renderable1, renderable2)
|
| 95 |
+
return table
|
| 96 |
+
|
| 97 |
+
table.add_row(
|
| 98 |
+
"Asian\nlanguage\nsupport",
|
| 99 |
+
":flag_for_china: 该库支持中文,日文和韩文文本!\n:flag_for_japan: ライブラリは中国語、日本語、韓国語のテキストをサポートしています\n:flag_for_south_korea: 이 라이브러리는 중국어, 일본어 및 한국어 텍스트를 지원합니다",
|
| 100 |
+
)
|
| 101 |
+
|
| 102 |
+
markup_example = (
|
| 103 |
+
"[bold magenta]Rich[/] supports a simple [i]bbcode[/i]-like [b]markup[/b] for [yellow]color[/], [underline]style[/], and emoji! "
|
| 104 |
+
":+1: :apple: :ant: :bear: :baguette_bread: :bus: "
|
| 105 |
+
)
|
| 106 |
+
table.add_row("Markup", markup_example)
|
| 107 |
+
|
| 108 |
+
example_table = Table(
|
| 109 |
+
show_edge=False,
|
| 110 |
+
show_header=True,
|
| 111 |
+
expand=False,
|
| 112 |
+
row_styles=["none", "dim"],
|
| 113 |
+
box=box.SIMPLE,
|
| 114 |
+
)
|
| 115 |
+
example_table.add_column("[green]Date", style="green", no_wrap=True)
|
| 116 |
+
example_table.add_column("[blue]Title", style="blue")
|
| 117 |
+
example_table.add_column(
|
| 118 |
+
"[cyan]Production Budget",
|
| 119 |
+
style="cyan",
|
| 120 |
+
justify="right",
|
| 121 |
+
no_wrap=True,
|
| 122 |
+
)
|
| 123 |
+
example_table.add_column(
|
| 124 |
+
"[magenta]Box Office",
|
| 125 |
+
style="magenta",
|
| 126 |
+
justify="right",
|
| 127 |
+
no_wrap=True,
|
| 128 |
+
)
|
| 129 |
+
example_table.add_row(
|
| 130 |
+
"Dec 20, 2019",
|
| 131 |
+
"Star Wars: The Rise of Skywalker",
|
| 132 |
+
"$275,000,000",
|
| 133 |
+
"$375,126,118",
|
| 134 |
+
)
|
| 135 |
+
example_table.add_row(
|
| 136 |
+
"May 25, 2018",
|
| 137 |
+
"[b]Solo[/]: A Star Wars Story",
|
| 138 |
+
"$275,000,000",
|
| 139 |
+
"$393,151,347",
|
| 140 |
+
)
|
| 141 |
+
example_table.add_row(
|
| 142 |
+
"Dec 15, 2017",
|
| 143 |
+
"Star Wars Ep. VIII: The Last Jedi",
|
| 144 |
+
"$262,000,000",
|
| 145 |
+
"[bold]$1,332,539,889[/bold]",
|
| 146 |
+
)
|
| 147 |
+
example_table.add_row(
|
| 148 |
+
"May 19, 1999",
|
| 149 |
+
"Star Wars Ep. [b]I[/b]: [i]The phantom Menace",
|
| 150 |
+
"$115,000,000",
|
| 151 |
+
"$1,027,044,677",
|
| 152 |
+
)
|
| 153 |
+
|
| 154 |
+
table.add_row("Tables", example_table)
|
| 155 |
+
|
| 156 |
+
code = '''\
|
| 157 |
+
def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]:
|
| 158 |
+
"""Iterate and generate a tuple with a flag for last value."""
|
| 159 |
+
iter_values = iter(values)
|
| 160 |
+
try:
|
| 161 |
+
previous_value = next(iter_values)
|
| 162 |
+
except StopIteration:
|
| 163 |
+
return
|
| 164 |
+
for value in iter_values:
|
| 165 |
+
yield False, previous_value
|
| 166 |
+
previous_value = value
|
| 167 |
+
yield True, previous_value'''
|
| 168 |
+
|
| 169 |
+
pretty_data = {
|
| 170 |
+
"foo": [
|
| 171 |
+
3.1427,
|
| 172 |
+
(
|
| 173 |
+
"Paul Atreides",
|
| 174 |
+
"Vladimir Harkonnen",
|
| 175 |
+
"Thufir Hawat",
|
| 176 |
+
),
|
| 177 |
+
],
|
| 178 |
+
"atomic": (False, True, None),
|
| 179 |
+
}
|
| 180 |
+
table.add_row(
|
| 181 |
+
"Syntax\nhighlighting\n&\npretty\nprinting",
|
| 182 |
+
comparison(
|
| 183 |
+
Syntax(code, "python3", line_numbers=True, indent_guides=True),
|
| 184 |
+
Pretty(pretty_data, indent_guides=True),
|
| 185 |
+
),
|
| 186 |
+
)
|
| 187 |
+
|
| 188 |
+
markdown_example = """\
|
| 189 |
+
# Markdown
|
| 190 |
+
|
| 191 |
+
Supports much of the *markdown* __syntax__!
|
| 192 |
+
|
| 193 |
+
- Headers
|
| 194 |
+
- Basic formatting: **bold**, *italic*, `code`
|
| 195 |
+
- Block quotes
|
| 196 |
+
- Lists, and more...
|
| 197 |
+
"""
|
| 198 |
+
table.add_row(
|
| 199 |
+
"Markdown", comparison("[cyan]" + markdown_example, Markdown(markdown_example))
|
| 200 |
+
)
|
| 201 |
+
|
| 202 |
+
table.add_row(
|
| 203 |
+
"+more!",
|
| 204 |
+
"""Progress bars, columns, styled logging handler, tracebacks, etc...""",
|
| 205 |
+
)
|
| 206 |
+
return table
|
| 207 |
+
|
| 208 |
+
|
| 209 |
+
if __name__ == "__main__": # pragma: no cover
|
| 210 |
+
|
| 211 |
+
console = Console(
|
| 212 |
+
file=io.StringIO(),
|
| 213 |
+
force_terminal=True,
|
| 214 |
+
)
|
| 215 |
+
test_card = make_test_card()
|
| 216 |
+
|
| 217 |
+
# Print once to warm cache
|
| 218 |
+
start = process_time()
|
| 219 |
+
console.print(test_card)
|
| 220 |
+
pre_cache_taken = round((process_time() - start) * 1000.0, 1)
|
| 221 |
+
|
| 222 |
+
console.file = io.StringIO()
|
| 223 |
+
|
| 224 |
+
start = process_time()
|
| 225 |
+
console.print(test_card)
|
| 226 |
+
taken = round((process_time() - start) * 1000.0, 1)
|
| 227 |
+
|
| 228 |
+
c = Console(record=True)
|
| 229 |
+
c.print(test_card)
|
| 230 |
+
|
| 231 |
+
print(f"rendered in {pre_cache_taken}ms (cold cache)")
|
| 232 |
+
print(f"rendered in {taken}ms (warm cache)")
|
| 233 |
+
|
| 234 |
+
from pip._vendor.rich.panel import Panel
|
| 235 |
+
|
| 236 |
+
console = Console()
|
| 237 |
+
|
| 238 |
+
sponsor_message = Table.grid(padding=1)
|
| 239 |
+
sponsor_message.add_column(style="green", justify="right")
|
| 240 |
+
sponsor_message.add_column(no_wrap=True)
|
| 241 |
+
|
| 242 |
+
sponsor_message.add_row(
|
| 243 |
+
"Textualize",
|
| 244 |
+
"[u blue link=https://github.com/textualize]https://github.com/textualize",
|
| 245 |
+
)
|
| 246 |
+
sponsor_message.add_row(
|
| 247 |
+
"Twitter",
|
| 248 |
+
"[u blue link=https://twitter.com/willmcgugan]https://twitter.com/willmcgugan",
|
| 249 |
+
)
|
| 250 |
+
|
| 251 |
+
intro_message = Text.from_markup(
|
| 252 |
+
"""\
|
| 253 |
+
We hope you enjoy using Rich!
|
| 254 |
+
|
| 255 |
+
Rich is maintained with [red]:heart:[/] by [link=https://www.textualize.io]Textualize.io[/]
|
| 256 |
+
|
| 257 |
+
- Will McGugan"""
|
| 258 |
+
)
|
| 259 |
+
|
| 260 |
+
message = Table.grid(padding=2)
|
| 261 |
+
message.add_column()
|
| 262 |
+
message.add_column(no_wrap=True)
|
| 263 |
+
message.add_row(intro_message, sponsor_message)
|
| 264 |
+
|
| 265 |
+
console.print(
|
| 266 |
+
Panel.fit(
|
| 267 |
+
message,
|
| 268 |
+
box=box.ROUNDED,
|
| 269 |
+
padding=(1, 2),
|
| 270 |
+
title="[b red]Thanks for trying out Rich!",
|
| 271 |
+
border_style="bright_blue",
|
| 272 |
+
),
|
| 273 |
+
justify="center",
|
| 274 |
+
)
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/_export_format.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
<pre style="font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><code>{code}</code></pre>
|
| 16 |
+
</body>
|
| 17 |
+
</html>
|
| 18 |
+
"""
|
| 19 |
+
|
| 20 |
+
CONSOLE_SVG_FORMAT = """\
|
| 21 |
+
<svg class="rich-terminal" viewBox="0 0 {width} {height}" xmlns="http://www.w3.org/2000/svg">
|
| 22 |
+
<!-- Generated with Rich https://www.textualize.io -->
|
| 23 |
+
<style>
|
| 24 |
+
|
| 25 |
+
@font-face {{
|
| 26 |
+
font-family: "Fira Code";
|
| 27 |
+
src: local("FiraCode-Regular"),
|
| 28 |
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
|
| 29 |
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
|
| 30 |
+
font-style: normal;
|
| 31 |
+
font-weight: 400;
|
| 32 |
+
}}
|
| 33 |
+
@font-face {{
|
| 34 |
+
font-family: "Fira Code";
|
| 35 |
+
src: local("FiraCode-Bold"),
|
| 36 |
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
|
| 37 |
+
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
|
| 38 |
+
font-style: bold;
|
| 39 |
+
font-weight: 700;
|
| 40 |
+
}}
|
| 41 |
+
|
| 42 |
+
.{unique_id}-matrix {{
|
| 43 |
+
font-family: Fira Code, monospace;
|
| 44 |
+
font-size: {char_height}px;
|
| 45 |
+
line-height: {line_height}px;
|
| 46 |
+
font-variant-east-asian: full-width;
|
| 47 |
+
}}
|
| 48 |
+
|
| 49 |
+
.{unique_id}-title {{
|
| 50 |
+
font-size: 18px;
|
| 51 |
+
font-weight: bold;
|
| 52 |
+
font-family: arial;
|
| 53 |
+
}}
|
| 54 |
+
|
| 55 |
+
{styles}
|
| 56 |
+
</style>
|
| 57 |
+
|
| 58 |
+
<defs>
|
| 59 |
+
<clipPath id="{unique_id}-clip-terminal">
|
| 60 |
+
<rect x="0" y="0" width="{terminal_width}" height="{terminal_height}" />
|
| 61 |
+
</clipPath>
|
| 62 |
+
{lines}
|
| 63 |
+
</defs>
|
| 64 |
+
|
| 65 |
+
{chrome}
|
| 66 |
+
<g transform="translate({terminal_x}, {terminal_y})" clip-path="url(#{unique_id}-clip-terminal)">
|
| 67 |
+
{backgrounds}
|
| 68 |
+
<g class="{unique_id}-matrix">
|
| 69 |
+
{matrix}
|
| 70 |
+
</g>
|
| 71 |
+
</g>
|
| 72 |
+
</svg>
|
| 73 |
+
"""
|
| 74 |
+
|
| 75 |
+
_SVG_FONT_FAMILY = "Rich Fira Code"
|
| 76 |
+
_SVG_CLASSES_PREFIX = "rich-svg"
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/_extension.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Any
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def load_ipython_extension(ip: Any) -> None: # pragma: no cover
|
| 5 |
+
# prevent circular import
|
| 6 |
+
from pip._vendor.rich.pretty import install
|
| 7 |
+
from pip._vendor.rich.traceback import install as tr_install
|
| 8 |
+
|
| 9 |
+
install()
|
| 10 |
+
tr_install()
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/_fileno.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
from typing import IO, Callable
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def get_fileno(file_like: IO[str]) -> int | None:
|
| 7 |
+
"""Get fileno() from a file, accounting for poorly implemented file-like objects.
|
| 8 |
+
|
| 9 |
+
Args:
|
| 10 |
+
file_like (IO): A file-like object.
|
| 11 |
+
|
| 12 |
+
Returns:
|
| 13 |
+
int | None: The result of fileno if available, or None if operation failed.
|
| 14 |
+
"""
|
| 15 |
+
fileno: Callable[[], int] | None = getattr(file_like, "fileno", None)
|
| 16 |
+
if fileno is not None:
|
| 17 |
+
try:
|
| 18 |
+
return fileno()
|
| 19 |
+
except Exception:
|
| 20 |
+
# `fileno` is documented as potentially raising a OSError
|
| 21 |
+
# Alas, from the issues, there are so many poorly implemented file-like objects,
|
| 22 |
+
# that `fileno()` can raise just about anything.
|
| 23 |
+
return None
|
| 24 |
+
return None
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/_inspect.py
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
import inspect
|
| 4 |
+
from inspect import cleandoc, getdoc, getfile, isclass, ismodule, signature
|
| 5 |
+
from typing import Any, Collection, Iterable, Optional, Tuple, Type, Union
|
| 6 |
+
|
| 7 |
+
from .console import Group, RenderableType
|
| 8 |
+
from .control import escape_control_codes
|
| 9 |
+
from .highlighter import ReprHighlighter
|
| 10 |
+
from .jupyter import JupyterMixin
|
| 11 |
+
from .panel import Panel
|
| 12 |
+
from .pretty import Pretty
|
| 13 |
+
from .table import Table
|
| 14 |
+
from .text import Text, TextType
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def _first_paragraph(doc: str) -> str:
|
| 18 |
+
"""Get the first paragraph from a docstring."""
|
| 19 |
+
paragraph, _, _ = doc.partition("\n\n")
|
| 20 |
+
return paragraph
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
class Inspect(JupyterMixin):
|
| 24 |
+
"""A renderable to inspect any Python Object.
|
| 25 |
+
|
| 26 |
+
Args:
|
| 27 |
+
obj (Any): An object to inspect.
|
| 28 |
+
title (str, optional): Title to display over inspect result, or None use type. Defaults to None.
|
| 29 |
+
help (bool, optional): Show full help text rather than just first paragraph. Defaults to False.
|
| 30 |
+
methods (bool, optional): Enable inspection of callables. Defaults to False.
|
| 31 |
+
docs (bool, optional): Also render doc strings. Defaults to True.
|
| 32 |
+
private (bool, optional): Show private attributes (beginning with underscore). Defaults to False.
|
| 33 |
+
dunder (bool, optional): Show attributes starting with double underscore. Defaults to False.
|
| 34 |
+
sort (bool, optional): Sort attributes alphabetically. Defaults to True.
|
| 35 |
+
all (bool, optional): Show all attributes. Defaults to False.
|
| 36 |
+
value (bool, optional): Pretty print value of object. Defaults to True.
|
| 37 |
+
"""
|
| 38 |
+
|
| 39 |
+
def __init__(
|
| 40 |
+
self,
|
| 41 |
+
obj: Any,
|
| 42 |
+
*,
|
| 43 |
+
title: Optional[TextType] = None,
|
| 44 |
+
help: bool = False,
|
| 45 |
+
methods: bool = False,
|
| 46 |
+
docs: bool = True,
|
| 47 |
+
private: bool = False,
|
| 48 |
+
dunder: bool = False,
|
| 49 |
+
sort: bool = True,
|
| 50 |
+
all: bool = True,
|
| 51 |
+
value: bool = True,
|
| 52 |
+
) -> None:
|
| 53 |
+
self.highlighter = ReprHighlighter()
|
| 54 |
+
self.obj = obj
|
| 55 |
+
self.title = title or self._make_title(obj)
|
| 56 |
+
if all:
|
| 57 |
+
methods = private = dunder = True
|
| 58 |
+
self.help = help
|
| 59 |
+
self.methods = methods
|
| 60 |
+
self.docs = docs or help
|
| 61 |
+
self.private = private or dunder
|
| 62 |
+
self.dunder = dunder
|
| 63 |
+
self.sort = sort
|
| 64 |
+
self.value = value
|
| 65 |
+
|
| 66 |
+
def _make_title(self, obj: Any) -> Text:
|
| 67 |
+
"""Make a default title."""
|
| 68 |
+
title_str = (
|
| 69 |
+
str(obj)
|
| 70 |
+
if (isclass(obj) or callable(obj) or ismodule(obj))
|
| 71 |
+
else str(type(obj))
|
| 72 |
+
)
|
| 73 |
+
title_text = self.highlighter(title_str)
|
| 74 |
+
return title_text
|
| 75 |
+
|
| 76 |
+
def __rich__(self) -> Panel:
|
| 77 |
+
return Panel.fit(
|
| 78 |
+
Group(*self._render()),
|
| 79 |
+
title=self.title,
|
| 80 |
+
border_style="scope.border",
|
| 81 |
+
padding=(0, 1),
|
| 82 |
+
)
|
| 83 |
+
|
| 84 |
+
def _get_signature(self, name: str, obj: Any) -> Optional[Text]:
|
| 85 |
+
"""Get a signature for a callable."""
|
| 86 |
+
try:
|
| 87 |
+
_signature = str(signature(obj)) + ":"
|
| 88 |
+
except ValueError:
|
| 89 |
+
_signature = "(...)"
|
| 90 |
+
except TypeError:
|
| 91 |
+
return None
|
| 92 |
+
|
| 93 |
+
source_filename: Optional[str] = None
|
| 94 |
+
try:
|
| 95 |
+
source_filename = getfile(obj)
|
| 96 |
+
except (OSError, TypeError):
|
| 97 |
+
# OSError is raised if obj has no source file, e.g. when defined in REPL.
|
| 98 |
+
pass
|
| 99 |
+
|
| 100 |
+
callable_name = Text(name, style="inspect.callable")
|
| 101 |
+
if source_filename:
|
| 102 |
+
callable_name.stylize(f"link file://{source_filename}")
|
| 103 |
+
signature_text = self.highlighter(_signature)
|
| 104 |
+
|
| 105 |
+
qualname = name or getattr(obj, "__qualname__", name)
|
| 106 |
+
|
| 107 |
+
# If obj is a module, there may be classes (which are callable) to display
|
| 108 |
+
if inspect.isclass(obj):
|
| 109 |
+
prefix = "class"
|
| 110 |
+
elif inspect.iscoroutinefunction(obj):
|
| 111 |
+
prefix = "async def"
|
| 112 |
+
else:
|
| 113 |
+
prefix = "def"
|
| 114 |
+
|
| 115 |
+
qual_signature = Text.assemble(
|
| 116 |
+
(f"{prefix} ", f"inspect.{prefix.replace(' ', '_')}"),
|
| 117 |
+
(qualname, "inspect.callable"),
|
| 118 |
+
signature_text,
|
| 119 |
+
)
|
| 120 |
+
|
| 121 |
+
return qual_signature
|
| 122 |
+
|
| 123 |
+
def _render(self) -> Iterable[RenderableType]:
|
| 124 |
+
"""Render object."""
|
| 125 |
+
|
| 126 |
+
def sort_items(item: Tuple[str, Any]) -> Tuple[bool, str]:
|
| 127 |
+
key, (_error, value) = item
|
| 128 |
+
return (callable(value), key.strip("_").lower())
|
| 129 |
+
|
| 130 |
+
def safe_getattr(attr_name: str) -> Tuple[Any, Any]:
|
| 131 |
+
"""Get attribute or any exception."""
|
| 132 |
+
try:
|
| 133 |
+
return (None, getattr(obj, attr_name))
|
| 134 |
+
except Exception as error:
|
| 135 |
+
return (error, None)
|
| 136 |
+
|
| 137 |
+
obj = self.obj
|
| 138 |
+
keys = dir(obj)
|
| 139 |
+
total_items = len(keys)
|
| 140 |
+
if not self.dunder:
|
| 141 |
+
keys = [key for key in keys if not key.startswith("__")]
|
| 142 |
+
if not self.private:
|
| 143 |
+
keys = [key for key in keys if not key.startswith("_")]
|
| 144 |
+
not_shown_count = total_items - len(keys)
|
| 145 |
+
items = [(key, safe_getattr(key)) for key in keys]
|
| 146 |
+
if self.sort:
|
| 147 |
+
items.sort(key=sort_items)
|
| 148 |
+
|
| 149 |
+
items_table = Table.grid(padding=(0, 1), expand=False)
|
| 150 |
+
items_table.add_column(justify="right")
|
| 151 |
+
add_row = items_table.add_row
|
| 152 |
+
highlighter = self.highlighter
|
| 153 |
+
|
| 154 |
+
if callable(obj):
|
| 155 |
+
signature = self._get_signature("", obj)
|
| 156 |
+
if signature is not None:
|
| 157 |
+
yield signature
|
| 158 |
+
yield ""
|
| 159 |
+
|
| 160 |
+
if self.docs:
|
| 161 |
+
_doc = self._get_formatted_doc(obj)
|
| 162 |
+
if _doc is not None:
|
| 163 |
+
doc_text = Text(_doc, style="inspect.help")
|
| 164 |
+
doc_text = highlighter(doc_text)
|
| 165 |
+
yield doc_text
|
| 166 |
+
yield ""
|
| 167 |
+
|
| 168 |
+
if self.value and not (isclass(obj) or callable(obj) or ismodule(obj)):
|
| 169 |
+
yield Panel(
|
| 170 |
+
Pretty(obj, indent_guides=True, max_length=10, max_string=60),
|
| 171 |
+
border_style="inspect.value.border",
|
| 172 |
+
)
|
| 173 |
+
yield ""
|
| 174 |
+
|
| 175 |
+
for key, (error, value) in items:
|
| 176 |
+
key_text = Text.assemble(
|
| 177 |
+
(
|
| 178 |
+
key,
|
| 179 |
+
"inspect.attr.dunder" if key.startswith("__") else "inspect.attr",
|
| 180 |
+
),
|
| 181 |
+
(" =", "inspect.equals"),
|
| 182 |
+
)
|
| 183 |
+
if error is not None:
|
| 184 |
+
warning = key_text.copy()
|
| 185 |
+
warning.stylize("inspect.error")
|
| 186 |
+
add_row(warning, highlighter(repr(error)))
|
| 187 |
+
continue
|
| 188 |
+
|
| 189 |
+
if callable(value):
|
| 190 |
+
if not self.methods:
|
| 191 |
+
continue
|
| 192 |
+
|
| 193 |
+
_signature_text = self._get_signature(key, value)
|
| 194 |
+
if _signature_text is None:
|
| 195 |
+
add_row(key_text, Pretty(value, highlighter=highlighter))
|
| 196 |
+
else:
|
| 197 |
+
if self.docs:
|
| 198 |
+
docs = self._get_formatted_doc(value)
|
| 199 |
+
if docs is not None:
|
| 200 |
+
_signature_text.append("\n" if "\n" in docs else " ")
|
| 201 |
+
doc = highlighter(docs)
|
| 202 |
+
doc.stylize("inspect.doc")
|
| 203 |
+
_signature_text.append(doc)
|
| 204 |
+
|
| 205 |
+
add_row(key_text, _signature_text)
|
| 206 |
+
else:
|
| 207 |
+
add_row(key_text, Pretty(value, highlighter=highlighter))
|
| 208 |
+
if items_table.row_count:
|
| 209 |
+
yield items_table
|
| 210 |
+
elif not_shown_count:
|
| 211 |
+
yield Text.from_markup(
|
| 212 |
+
f"[b cyan]{not_shown_count}[/][i] attribute(s) not shown.[/i] "
|
| 213 |
+
f"Run [b][magenta]inspect[/]([not b]inspect[/])[/b] for options."
|
| 214 |
+
)
|
| 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
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/_log_render.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from datetime import datetime
|
| 2 |
+
from typing import Iterable, List, Optional, TYPE_CHECKING, Union, Callable
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
from .text import Text, TextType
|
| 6 |
+
|
| 7 |
+
if TYPE_CHECKING:
|
| 8 |
+
from .console import Console, ConsoleRenderable, RenderableType
|
| 9 |
+
from .table import Table
|
| 10 |
+
|
| 11 |
+
FormatTimeCallable = Callable[[datetime], Text]
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class LogRender:
|
| 15 |
+
def __init__(
|
| 16 |
+
self,
|
| 17 |
+
show_time: bool = True,
|
| 18 |
+
show_level: bool = False,
|
| 19 |
+
show_path: bool = True,
|
| 20 |
+
time_format: Union[str, FormatTimeCallable] = "[%x %X]",
|
| 21 |
+
omit_repeated_times: bool = True,
|
| 22 |
+
level_width: Optional[int] = 8,
|
| 23 |
+
) -> None:
|
| 24 |
+
self.show_time = show_time
|
| 25 |
+
self.show_level = show_level
|
| 26 |
+
self.show_path = show_path
|
| 27 |
+
self.time_format = time_format
|
| 28 |
+
self.omit_repeated_times = omit_repeated_times
|
| 29 |
+
self.level_width = level_width
|
| 30 |
+
self._last_time: Optional[Text] = None
|
| 31 |
+
|
| 32 |
+
def __call__(
|
| 33 |
+
self,
|
| 34 |
+
console: "Console",
|
| 35 |
+
renderables: Iterable["ConsoleRenderable"],
|
| 36 |
+
log_time: Optional[datetime] = None,
|
| 37 |
+
time_format: Optional[Union[str, FormatTimeCallable]] = None,
|
| 38 |
+
level: TextType = "",
|
| 39 |
+
path: Optional[str] = None,
|
| 40 |
+
line_no: Optional[int] = None,
|
| 41 |
+
link_path: Optional[str] = None,
|
| 42 |
+
) -> "Table":
|
| 43 |
+
from .containers import Renderables
|
| 44 |
+
from .table import Table
|
| 45 |
+
|
| 46 |
+
output = Table.grid(padding=(0, 1))
|
| 47 |
+
output.expand = True
|
| 48 |
+
if self.show_time:
|
| 49 |
+
output.add_column(style="log.time")
|
| 50 |
+
if self.show_level:
|
| 51 |
+
output.add_column(style="log.level", width=self.level_width)
|
| 52 |
+
output.add_column(ratio=1, style="log.message", overflow="fold")
|
| 53 |
+
if self.show_path and path:
|
| 54 |
+
output.add_column(style="log.path")
|
| 55 |
+
row: List["RenderableType"] = []
|
| 56 |
+
if self.show_time:
|
| 57 |
+
log_time = log_time or console.get_datetime()
|
| 58 |
+
time_format = time_format or self.time_format
|
| 59 |
+
if callable(time_format):
|
| 60 |
+
log_time_display = time_format(log_time)
|
| 61 |
+
else:
|
| 62 |
+
log_time_display = Text(log_time.strftime(time_format))
|
| 63 |
+
if log_time_display == self._last_time and self.omit_repeated_times:
|
| 64 |
+
row.append(Text(" " * len(log_time_display)))
|
| 65 |
+
else:
|
| 66 |
+
row.append(log_time_display)
|
| 67 |
+
self._last_time = log_time_display
|
| 68 |
+
if self.show_level:
|
| 69 |
+
row.append(level)
|
| 70 |
+
|
| 71 |
+
row.append(Renderables(renderables))
|
| 72 |
+
if self.show_path and path:
|
| 73 |
+
path_text = Text()
|
| 74 |
+
path_text.append(
|
| 75 |
+
path, style=f"link file://{link_path}" if link_path else ""
|
| 76 |
+
)
|
| 77 |
+
if line_no:
|
| 78 |
+
path_text.append(":")
|
| 79 |
+
path_text.append(
|
| 80 |
+
f"{line_no}",
|
| 81 |
+
style=f"link file://{link_path}#{line_no}" if link_path else "",
|
| 82 |
+
)
|
| 83 |
+
row.append(path_text)
|
| 84 |
+
|
| 85 |
+
output.add_row(*row)
|
| 86 |
+
return output
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
if __name__ == "__main__": # pragma: no cover
|
| 90 |
+
from pip._vendor.rich.console import Console
|
| 91 |
+
|
| 92 |
+
c = Console()
|
| 93 |
+
c.print("[on blue]Hello", justify="right")
|
| 94 |
+
c.log("[on blue]hello", justify="right")
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/_loop.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Iterable, Tuple, TypeVar
|
| 2 |
+
|
| 3 |
+
T = TypeVar("T")
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def loop_first(values: Iterable[T]) -> Iterable[Tuple[bool, T]]:
|
| 7 |
+
"""Iterate and generate a tuple with a flag for first value."""
|
| 8 |
+
iter_values = iter(values)
|
| 9 |
+
try:
|
| 10 |
+
value = next(iter_values)
|
| 11 |
+
except StopIteration:
|
| 12 |
+
return
|
| 13 |
+
yield True, value
|
| 14 |
+
for value in iter_values:
|
| 15 |
+
yield False, value
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def loop_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]:
|
| 19 |
+
"""Iterate and generate a tuple with a flag for last value."""
|
| 20 |
+
iter_values = iter(values)
|
| 21 |
+
try:
|
| 22 |
+
previous_value = next(iter_values)
|
| 23 |
+
except StopIteration:
|
| 24 |
+
return
|
| 25 |
+
for value in iter_values:
|
| 26 |
+
yield False, previous_value
|
| 27 |
+
previous_value = value
|
| 28 |
+
yield True, previous_value
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def loop_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]:
|
| 32 |
+
"""Iterate and generate a tuple with a flag for first and last value."""
|
| 33 |
+
iter_values = iter(values)
|
| 34 |
+
try:
|
| 35 |
+
previous_value = next(iter_values)
|
| 36 |
+
except StopIteration:
|
| 37 |
+
return
|
| 38 |
+
first = True
|
| 39 |
+
for value in iter_values:
|
| 40 |
+
yield first, False, previous_value
|
| 41 |
+
first = False
|
| 42 |
+
previous_value = value
|
| 43 |
+
yield first, True, previous_value
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/_null_file.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from types import TracebackType
|
| 2 |
+
from typing import IO, Iterable, Iterator, List, Optional, Type
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class NullFile(IO[str]):
|
| 6 |
+
def close(self) -> None:
|
| 7 |
+
pass
|
| 8 |
+
|
| 9 |
+
def isatty(self) -> bool:
|
| 10 |
+
return False
|
| 11 |
+
|
| 12 |
+
def read(self, __n: int = 1) -> str:
|
| 13 |
+
return ""
|
| 14 |
+
|
| 15 |
+
def readable(self) -> bool:
|
| 16 |
+
return False
|
| 17 |
+
|
| 18 |
+
def readline(self, __limit: int = 1) -> str:
|
| 19 |
+
return ""
|
| 20 |
+
|
| 21 |
+
def readlines(self, __hint: int = 1) -> List[str]:
|
| 22 |
+
return []
|
| 23 |
+
|
| 24 |
+
def seek(self, __offset: int, __whence: int = 1) -> int:
|
| 25 |
+
return 0
|
| 26 |
+
|
| 27 |
+
def seekable(self) -> bool:
|
| 28 |
+
return False
|
| 29 |
+
|
| 30 |
+
def tell(self) -> int:
|
| 31 |
+
return 0
|
| 32 |
+
|
| 33 |
+
def truncate(self, __size: Optional[int] = 1) -> int:
|
| 34 |
+
return 0
|
| 35 |
+
|
| 36 |
+
def writable(self) -> bool:
|
| 37 |
+
return False
|
| 38 |
+
|
| 39 |
+
def writelines(self, __lines: Iterable[str]) -> None:
|
| 40 |
+
pass
|
| 41 |
+
|
| 42 |
+
def __next__(self) -> str:
|
| 43 |
+
return ""
|
| 44 |
+
|
| 45 |
+
def __iter__(self) -> Iterator[str]:
|
| 46 |
+
return iter([""])
|
| 47 |
+
|
| 48 |
+
def __enter__(self) -> IO[str]:
|
| 49 |
+
pass
|
| 50 |
+
|
| 51 |
+
def __exit__(
|
| 52 |
+
self,
|
| 53 |
+
__t: Optional[Type[BaseException]],
|
| 54 |
+
__value: Optional[BaseException],
|
| 55 |
+
__traceback: Optional[TracebackType],
|
| 56 |
+
) -> None:
|
| 57 |
+
pass
|
| 58 |
+
|
| 59 |
+
def write(self, text: str) -> int:
|
| 60 |
+
return 0
|
| 61 |
+
|
| 62 |
+
def flush(self) -> None:
|
| 63 |
+
pass
|
| 64 |
+
|
| 65 |
+
def fileno(self) -> int:
|
| 66 |
+
return -1
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
NULL_FILE = NullFile()
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/_pick.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Optional
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def pick_bool(*values: Optional[bool]) -> bool:
|
| 5 |
+
"""Pick the first non-none bool or return the last value.
|
| 6 |
+
|
| 7 |
+
Args:
|
| 8 |
+
*values (bool): Any number of boolean or None values.
|
| 9 |
+
|
| 10 |
+
Returns:
|
| 11 |
+
bool: First non-none boolean.
|
| 12 |
+
"""
|
| 13 |
+
assert values, "1 or more values required"
|
| 14 |
+
for value in values:
|
| 15 |
+
if value is not None:
|
| 16 |
+
return value
|
| 17 |
+
return bool(value)
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/_timer.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Timer context manager, only used in debug.
|
| 3 |
+
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
from time import time
|
| 7 |
+
|
| 8 |
+
import contextlib
|
| 9 |
+
from typing import Generator
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
@contextlib.contextmanager
|
| 13 |
+
def timer(subject: str = "time") -> Generator[None, None, None]:
|
| 14 |
+
"""print the elapsed time. (only used in debugging)"""
|
| 15 |
+
start = time()
|
| 16 |
+
yield
|
| 17 |
+
elapsed = time() - start
|
| 18 |
+
elapsed_ms = elapsed * 1000
|
| 19 |
+
print(f"{subject} elapsed {elapsed_ms:.1f}ms")
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/_win32_console.py
ADDED
|
@@ -0,0 +1,662 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Light wrapper around the Win32 Console API - this module should only be imported on Windows
|
| 2 |
+
|
| 3 |
+
The API that this module wraps is documented at https://docs.microsoft.com/en-us/windows/console/console-functions
|
| 4 |
+
"""
|
| 5 |
+
import ctypes
|
| 6 |
+
import sys
|
| 7 |
+
from typing import Any
|
| 8 |
+
|
| 9 |
+
windll: Any = None
|
| 10 |
+
if sys.platform == "win32":
|
| 11 |
+
windll = ctypes.LibraryLoader(ctypes.WinDLL)
|
| 12 |
+
else:
|
| 13 |
+
raise ImportError(f"{__name__} can only be imported on Windows")
|
| 14 |
+
|
| 15 |
+
import time
|
| 16 |
+
from ctypes import Structure, byref, wintypes
|
| 17 |
+
from typing import IO, NamedTuple, Type, cast
|
| 18 |
+
|
| 19 |
+
from pip._vendor.rich.color import ColorSystem
|
| 20 |
+
from pip._vendor.rich.style import Style
|
| 21 |
+
|
| 22 |
+
STDOUT = -11
|
| 23 |
+
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4
|
| 24 |
+
|
| 25 |
+
COORD = wintypes._COORD
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
class LegacyWindowsError(Exception):
|
| 29 |
+
pass
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class WindowsCoordinates(NamedTuple):
|
| 33 |
+
"""Coordinates in the Windows Console API are (y, x), not (x, y).
|
| 34 |
+
This class is intended to prevent that confusion.
|
| 35 |
+
Rows and columns are indexed from 0.
|
| 36 |
+
This class can be used in place of wintypes._COORD in arguments and argtypes.
|
| 37 |
+
"""
|
| 38 |
+
|
| 39 |
+
row: int
|
| 40 |
+
col: int
|
| 41 |
+
|
| 42 |
+
@classmethod
|
| 43 |
+
def from_param(cls, value: "WindowsCoordinates") -> COORD:
|
| 44 |
+
"""Converts a WindowsCoordinates into a wintypes _COORD structure.
|
| 45 |
+
This classmethod is internally called by ctypes to perform the conversion.
|
| 46 |
+
|
| 47 |
+
Args:
|
| 48 |
+
value (WindowsCoordinates): The input coordinates to convert.
|
| 49 |
+
|
| 50 |
+
Returns:
|
| 51 |
+
wintypes._COORD: The converted coordinates struct.
|
| 52 |
+
"""
|
| 53 |
+
return COORD(value.col, value.row)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
class CONSOLE_SCREEN_BUFFER_INFO(Structure):
|
| 57 |
+
_fields_ = [
|
| 58 |
+
("dwSize", COORD),
|
| 59 |
+
("dwCursorPosition", COORD),
|
| 60 |
+
("wAttributes", wintypes.WORD),
|
| 61 |
+
("srWindow", wintypes.SMALL_RECT),
|
| 62 |
+
("dwMaximumWindowSize", COORD),
|
| 63 |
+
]
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
class CONSOLE_CURSOR_INFO(ctypes.Structure):
|
| 67 |
+
_fields_ = [("dwSize", wintypes.DWORD), ("bVisible", wintypes.BOOL)]
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
_GetStdHandle = windll.kernel32.GetStdHandle
|
| 71 |
+
_GetStdHandle.argtypes = [
|
| 72 |
+
wintypes.DWORD,
|
| 73 |
+
]
|
| 74 |
+
_GetStdHandle.restype = wintypes.HANDLE
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def GetStdHandle(handle: int = STDOUT) -> wintypes.HANDLE:
|
| 78 |
+
"""Retrieves a handle to the specified standard device (standard input, standard output, or standard error).
|
| 79 |
+
|
| 80 |
+
Args:
|
| 81 |
+
handle (int): Integer identifier for the handle. Defaults to -11 (stdout).
|
| 82 |
+
|
| 83 |
+
Returns:
|
| 84 |
+
wintypes.HANDLE: The handle
|
| 85 |
+
"""
|
| 86 |
+
return cast(wintypes.HANDLE, _GetStdHandle(handle))
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
_GetConsoleMode = windll.kernel32.GetConsoleMode
|
| 90 |
+
_GetConsoleMode.argtypes = [wintypes.HANDLE, wintypes.LPDWORD]
|
| 91 |
+
_GetConsoleMode.restype = wintypes.BOOL
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def GetConsoleMode(std_handle: wintypes.HANDLE) -> int:
|
| 95 |
+
"""Retrieves the current input mode of a console's input buffer
|
| 96 |
+
or the current output mode of a console screen buffer.
|
| 97 |
+
|
| 98 |
+
Args:
|
| 99 |
+
std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.
|
| 100 |
+
|
| 101 |
+
Raises:
|
| 102 |
+
LegacyWindowsError: If any error occurs while calling the Windows console API.
|
| 103 |
+
|
| 104 |
+
Returns:
|
| 105 |
+
int: Value representing the current console mode as documented at
|
| 106 |
+
https://docs.microsoft.com/en-us/windows/console/getconsolemode#parameters
|
| 107 |
+
"""
|
| 108 |
+
|
| 109 |
+
console_mode = wintypes.DWORD()
|
| 110 |
+
success = bool(_GetConsoleMode(std_handle, console_mode))
|
| 111 |
+
if not success:
|
| 112 |
+
raise LegacyWindowsError("Unable to get legacy Windows Console Mode")
|
| 113 |
+
return console_mode.value
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
_FillConsoleOutputCharacterW = windll.kernel32.FillConsoleOutputCharacterW
|
| 117 |
+
_FillConsoleOutputCharacterW.argtypes = [
|
| 118 |
+
wintypes.HANDLE,
|
| 119 |
+
ctypes.c_char,
|
| 120 |
+
wintypes.DWORD,
|
| 121 |
+
cast(Type[COORD], WindowsCoordinates),
|
| 122 |
+
ctypes.POINTER(wintypes.DWORD),
|
| 123 |
+
]
|
| 124 |
+
_FillConsoleOutputCharacterW.restype = wintypes.BOOL
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
def FillConsoleOutputCharacter(
|
| 128 |
+
std_handle: wintypes.HANDLE,
|
| 129 |
+
char: str,
|
| 130 |
+
length: int,
|
| 131 |
+
start: WindowsCoordinates,
|
| 132 |
+
) -> int:
|
| 133 |
+
"""Writes a character to the console screen buffer a specified number of times, beginning at the specified coordinates.
|
| 134 |
+
|
| 135 |
+
Args:
|
| 136 |
+
std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.
|
| 137 |
+
char (str): The character to write. Must be a string of length 1.
|
| 138 |
+
length (int): The number of times to write the character.
|
| 139 |
+
start (WindowsCoordinates): The coordinates to start writing at.
|
| 140 |
+
|
| 141 |
+
Returns:
|
| 142 |
+
int: The number of characters written.
|
| 143 |
+
"""
|
| 144 |
+
character = ctypes.c_char(char.encode())
|
| 145 |
+
num_characters = wintypes.DWORD(length)
|
| 146 |
+
num_written = wintypes.DWORD(0)
|
| 147 |
+
_FillConsoleOutputCharacterW(
|
| 148 |
+
std_handle,
|
| 149 |
+
character,
|
| 150 |
+
num_characters,
|
| 151 |
+
start,
|
| 152 |
+
byref(num_written),
|
| 153 |
+
)
|
| 154 |
+
return num_written.value
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
_FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute
|
| 158 |
+
_FillConsoleOutputAttribute.argtypes = [
|
| 159 |
+
wintypes.HANDLE,
|
| 160 |
+
wintypes.WORD,
|
| 161 |
+
wintypes.DWORD,
|
| 162 |
+
cast(Type[COORD], WindowsCoordinates),
|
| 163 |
+
ctypes.POINTER(wintypes.DWORD),
|
| 164 |
+
]
|
| 165 |
+
_FillConsoleOutputAttribute.restype = wintypes.BOOL
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
def FillConsoleOutputAttribute(
|
| 169 |
+
std_handle: wintypes.HANDLE,
|
| 170 |
+
attributes: int,
|
| 171 |
+
length: int,
|
| 172 |
+
start: WindowsCoordinates,
|
| 173 |
+
) -> int:
|
| 174 |
+
"""Sets the character attributes for a specified number of character cells,
|
| 175 |
+
beginning at the specified coordinates in a screen buffer.
|
| 176 |
+
|
| 177 |
+
Args:
|
| 178 |
+
std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.
|
| 179 |
+
attributes (int): Integer value representing the foreground and background colours of the cells.
|
| 180 |
+
length (int): The number of cells to set the output attribute of.
|
| 181 |
+
start (WindowsCoordinates): The coordinates of the first cell whose attributes are to be set.
|
| 182 |
+
|
| 183 |
+
Returns:
|
| 184 |
+
int: The number of cells whose attributes were actually set.
|
| 185 |
+
"""
|
| 186 |
+
num_cells = wintypes.DWORD(length)
|
| 187 |
+
style_attrs = wintypes.WORD(attributes)
|
| 188 |
+
num_written = wintypes.DWORD(0)
|
| 189 |
+
_FillConsoleOutputAttribute(
|
| 190 |
+
std_handle, style_attrs, num_cells, start, byref(num_written)
|
| 191 |
+
)
|
| 192 |
+
return num_written.value
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
_SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
|
| 196 |
+
_SetConsoleTextAttribute.argtypes = [
|
| 197 |
+
wintypes.HANDLE,
|
| 198 |
+
wintypes.WORD,
|
| 199 |
+
]
|
| 200 |
+
_SetConsoleTextAttribute.restype = wintypes.BOOL
|
| 201 |
+
|
| 202 |
+
|
| 203 |
+
def SetConsoleTextAttribute(
|
| 204 |
+
std_handle: wintypes.HANDLE, attributes: wintypes.WORD
|
| 205 |
+
) -> bool:
|
| 206 |
+
"""Set the colour attributes for all text written after this function is called.
|
| 207 |
+
|
| 208 |
+
Args:
|
| 209 |
+
std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.
|
| 210 |
+
attributes (int): Integer value representing the foreground and background colours.
|
| 211 |
+
|
| 212 |
+
|
| 213 |
+
Returns:
|
| 214 |
+
bool: True if the attribute was set successfully, otherwise False.
|
| 215 |
+
"""
|
| 216 |
+
return bool(_SetConsoleTextAttribute(std_handle, attributes))
|
| 217 |
+
|
| 218 |
+
|
| 219 |
+
_GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo
|
| 220 |
+
_GetConsoleScreenBufferInfo.argtypes = [
|
| 221 |
+
wintypes.HANDLE,
|
| 222 |
+
ctypes.POINTER(CONSOLE_SCREEN_BUFFER_INFO),
|
| 223 |
+
]
|
| 224 |
+
_GetConsoleScreenBufferInfo.restype = wintypes.BOOL
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
def GetConsoleScreenBufferInfo(
|
| 228 |
+
std_handle: wintypes.HANDLE,
|
| 229 |
+
) -> CONSOLE_SCREEN_BUFFER_INFO:
|
| 230 |
+
"""Retrieves information about the specified console screen buffer.
|
| 231 |
+
|
| 232 |
+
Args:
|
| 233 |
+
std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.
|
| 234 |
+
|
| 235 |
+
Returns:
|
| 236 |
+
CONSOLE_SCREEN_BUFFER_INFO: A CONSOLE_SCREEN_BUFFER_INFO ctype struct contain information about
|
| 237 |
+
screen size, cursor position, colour attributes, and more."""
|
| 238 |
+
console_screen_buffer_info = CONSOLE_SCREEN_BUFFER_INFO()
|
| 239 |
+
_GetConsoleScreenBufferInfo(std_handle, byref(console_screen_buffer_info))
|
| 240 |
+
return console_screen_buffer_info
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
_SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition
|
| 244 |
+
_SetConsoleCursorPosition.argtypes = [
|
| 245 |
+
wintypes.HANDLE,
|
| 246 |
+
cast(Type[COORD], WindowsCoordinates),
|
| 247 |
+
]
|
| 248 |
+
_SetConsoleCursorPosition.restype = wintypes.BOOL
|
| 249 |
+
|
| 250 |
+
|
| 251 |
+
def SetConsoleCursorPosition(
|
| 252 |
+
std_handle: wintypes.HANDLE, coords: WindowsCoordinates
|
| 253 |
+
) -> bool:
|
| 254 |
+
"""Set the position of the cursor in the console screen
|
| 255 |
+
|
| 256 |
+
Args:
|
| 257 |
+
std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.
|
| 258 |
+
coords (WindowsCoordinates): The coordinates to move the cursor to.
|
| 259 |
+
|
| 260 |
+
Returns:
|
| 261 |
+
bool: True if the function succeeds, otherwise False.
|
| 262 |
+
"""
|
| 263 |
+
return bool(_SetConsoleCursorPosition(std_handle, coords))
|
| 264 |
+
|
| 265 |
+
|
| 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 |
+
|
| 290 |
+
_SetConsoleCursorInfo = windll.kernel32.SetConsoleCursorInfo
|
| 291 |
+
_SetConsoleCursorInfo.argtypes = [
|
| 292 |
+
wintypes.HANDLE,
|
| 293 |
+
ctypes.POINTER(CONSOLE_CURSOR_INFO),
|
| 294 |
+
]
|
| 295 |
+
_SetConsoleCursorInfo.restype = wintypes.BOOL
|
| 296 |
+
|
| 297 |
+
|
| 298 |
+
def SetConsoleCursorInfo(
|
| 299 |
+
std_handle: wintypes.HANDLE, cursor_info: CONSOLE_CURSOR_INFO
|
| 300 |
+
) -> bool:
|
| 301 |
+
"""Set the cursor info - used for adjusting cursor visibility and width
|
| 302 |
+
|
| 303 |
+
Args:
|
| 304 |
+
std_handle (wintypes.HANDLE): A handle to the console input buffer or the console screen buffer.
|
| 305 |
+
cursor_info (CONSOLE_CURSOR_INFO): CONSOLE_CURSOR_INFO ctype struct containing the new cursor info.
|
| 306 |
+
|
| 307 |
+
Returns:
|
| 308 |
+
bool: True if the function succeeds, otherwise False.
|
| 309 |
+
"""
|
| 310 |
+
return bool(_SetConsoleCursorInfo(std_handle, byref(cursor_info)))
|
| 311 |
+
|
| 312 |
+
|
| 313 |
+
_SetConsoleTitle = windll.kernel32.SetConsoleTitleW
|
| 314 |
+
_SetConsoleTitle.argtypes = [wintypes.LPCWSTR]
|
| 315 |
+
_SetConsoleTitle.restype = wintypes.BOOL
|
| 316 |
+
|
| 317 |
+
|
| 318 |
+
def SetConsoleTitle(title: str) -> bool:
|
| 319 |
+
"""Sets the title of the current console window
|
| 320 |
+
|
| 321 |
+
Args:
|
| 322 |
+
title (str): The new title of the console window.
|
| 323 |
+
|
| 324 |
+
Returns:
|
| 325 |
+
bool: True if the function succeeds, otherwise False.
|
| 326 |
+
"""
|
| 327 |
+
return bool(_SetConsoleTitle(title))
|
| 328 |
+
|
| 329 |
+
|
| 330 |
+
class LegacyWindowsTerm:
|
| 331 |
+
"""This class allows interaction with the legacy Windows Console API. It should only be used in the context
|
| 332 |
+
of environments where virtual terminal processing is not available. However, if it is used in a Windows environment,
|
| 333 |
+
the entire API should work.
|
| 334 |
+
|
| 335 |
+
Args:
|
| 336 |
+
file (IO[str]): The file which the Windows Console API HANDLE is retrieved from, defaults to sys.stdout.
|
| 337 |
+
"""
|
| 338 |
+
|
| 339 |
+
BRIGHT_BIT = 8
|
| 340 |
+
|
| 341 |
+
# Indices are ANSI color numbers, values are the corresponding Windows Console API color numbers
|
| 342 |
+
ANSI_TO_WINDOWS = [
|
| 343 |
+
0, # black The Windows colours are defined in wincon.h as follows:
|
| 344 |
+
4, # red define FOREGROUND_BLUE 0x0001 -- 0000 0001
|
| 345 |
+
2, # green define FOREGROUND_GREEN 0x0002 -- 0000 0010
|
| 346 |
+
6, # yellow define FOREGROUND_RED 0x0004 -- 0000 0100
|
| 347 |
+
1, # blue define FOREGROUND_INTENSITY 0x0008 -- 0000 1000
|
| 348 |
+
5, # magenta define BACKGROUND_BLUE 0x0010 -- 0001 0000
|
| 349 |
+
3, # cyan define BACKGROUND_GREEN 0x0020 -- 0010 0000
|
| 350 |
+
7, # white define BACKGROUND_RED 0x0040 -- 0100 0000
|
| 351 |
+
8, # bright black (grey) define BACKGROUND_INTENSITY 0x0080 -- 1000 0000
|
| 352 |
+
12, # bright red
|
| 353 |
+
10, # bright green
|
| 354 |
+
14, # bright yellow
|
| 355 |
+
9, # bright blue
|
| 356 |
+
13, # bright magenta
|
| 357 |
+
11, # bright cyan
|
| 358 |
+
15, # bright white
|
| 359 |
+
]
|
| 360 |
+
|
| 361 |
+
def __init__(self, file: "IO[str]") -> None:
|
| 362 |
+
handle = GetStdHandle(STDOUT)
|
| 363 |
+
self._handle = handle
|
| 364 |
+
default_text = GetConsoleScreenBufferInfo(handle).wAttributes
|
| 365 |
+
self._default_text = default_text
|
| 366 |
+
|
| 367 |
+
self._default_fore = default_text & 7
|
| 368 |
+
self._default_back = (default_text >> 4) & 7
|
| 369 |
+
self._default_attrs = self._default_fore | (self._default_back << 4)
|
| 370 |
+
|
| 371 |
+
self._file = file
|
| 372 |
+
self.write = file.write
|
| 373 |
+
self.flush = file.flush
|
| 374 |
+
|
| 375 |
+
@property
|
| 376 |
+
def cursor_position(self) -> WindowsCoordinates:
|
| 377 |
+
"""Returns the current position of the cursor (0-based)
|
| 378 |
+
|
| 379 |
+
Returns:
|
| 380 |
+
WindowsCoordinates: The current cursor position.
|
| 381 |
+
"""
|
| 382 |
+
coord: COORD = GetConsoleScreenBufferInfo(self._handle).dwCursorPosition
|
| 383 |
+
return WindowsCoordinates(row=cast(int, coord.Y), col=cast(int, coord.X))
|
| 384 |
+
|
| 385 |
+
@property
|
| 386 |
+
def screen_size(self) -> WindowsCoordinates:
|
| 387 |
+
"""Returns the current size of the console screen buffer, in character columns and rows
|
| 388 |
+
|
| 389 |
+
Returns:
|
| 390 |
+
WindowsCoordinates: The width and height of the screen as WindowsCoordinates.
|
| 391 |
+
"""
|
| 392 |
+
screen_size: COORD = GetConsoleScreenBufferInfo(self._handle).dwSize
|
| 393 |
+
return WindowsCoordinates(
|
| 394 |
+
row=cast(int, screen_size.Y), col=cast(int, screen_size.X)
|
| 395 |
+
)
|
| 396 |
+
|
| 397 |
+
def write_text(self, text: str) -> None:
|
| 398 |
+
"""Write text directly to the terminal without any modification of styles
|
| 399 |
+
|
| 400 |
+
Args:
|
| 401 |
+
text (str): The text to write to the console
|
| 402 |
+
"""
|
| 403 |
+
self.write(text)
|
| 404 |
+
self.flush()
|
| 405 |
+
|
| 406 |
+
def write_styled(self, text: str, style: Style) -> None:
|
| 407 |
+
"""Write styled text to the terminal.
|
| 408 |
+
|
| 409 |
+
Args:
|
| 410 |
+
text (str): The text to write
|
| 411 |
+
style (Style): The style of the text
|
| 412 |
+
"""
|
| 413 |
+
color = style.color
|
| 414 |
+
bgcolor = style.bgcolor
|
| 415 |
+
if style.reverse:
|
| 416 |
+
color, bgcolor = bgcolor, color
|
| 417 |
+
|
| 418 |
+
if color:
|
| 419 |
+
fore = color.downgrade(ColorSystem.WINDOWS).number
|
| 420 |
+
fore = fore if fore is not None else 7 # Default to ANSI 7: White
|
| 421 |
+
if style.bold:
|
| 422 |
+
fore = fore | self.BRIGHT_BIT
|
| 423 |
+
if style.dim:
|
| 424 |
+
fore = fore & ~self.BRIGHT_BIT
|
| 425 |
+
fore = self.ANSI_TO_WINDOWS[fore]
|
| 426 |
+
else:
|
| 427 |
+
fore = self._default_fore
|
| 428 |
+
|
| 429 |
+
if bgcolor:
|
| 430 |
+
back = bgcolor.downgrade(ColorSystem.WINDOWS).number
|
| 431 |
+
back = back if back is not None else 0 # Default to ANSI 0: Black
|
| 432 |
+
back = self.ANSI_TO_WINDOWS[back]
|
| 433 |
+
else:
|
| 434 |
+
back = self._default_back
|
| 435 |
+
|
| 436 |
+
assert fore is not None
|
| 437 |
+
assert back is not None
|
| 438 |
+
|
| 439 |
+
SetConsoleTextAttribute(
|
| 440 |
+
self._handle, attributes=ctypes.c_ushort(fore | (back << 4))
|
| 441 |
+
)
|
| 442 |
+
self.write_text(text)
|
| 443 |
+
SetConsoleTextAttribute(self._handle, attributes=self._default_text)
|
| 444 |
+
|
| 445 |
+
def move_cursor_to(self, new_position: WindowsCoordinates) -> None:
|
| 446 |
+
"""Set the position of the cursor
|
| 447 |
+
|
| 448 |
+
Args:
|
| 449 |
+
new_position (WindowsCoordinates): The WindowsCoordinates representing the new position of the cursor.
|
| 450 |
+
"""
|
| 451 |
+
if new_position.col < 0 or new_position.row < 0:
|
| 452 |
+
return
|
| 453 |
+
SetConsoleCursorPosition(self._handle, coords=new_position)
|
| 454 |
+
|
| 455 |
+
def erase_line(self) -> None:
|
| 456 |
+
"""Erase all content on the line the cursor is currently located at"""
|
| 457 |
+
screen_size = self.screen_size
|
| 458 |
+
cursor_position = self.cursor_position
|
| 459 |
+
cells_to_erase = screen_size.col
|
| 460 |
+
start_coordinates = WindowsCoordinates(row=cursor_position.row, col=0)
|
| 461 |
+
FillConsoleOutputCharacter(
|
| 462 |
+
self._handle, " ", length=cells_to_erase, start=start_coordinates
|
| 463 |
+
)
|
| 464 |
+
FillConsoleOutputAttribute(
|
| 465 |
+
self._handle,
|
| 466 |
+
self._default_attrs,
|
| 467 |
+
length=cells_to_erase,
|
| 468 |
+
start=start_coordinates,
|
| 469 |
+
)
|
| 470 |
+
|
| 471 |
+
def erase_end_of_line(self) -> None:
|
| 472 |
+
"""Erase all content from the cursor position to the end of that line"""
|
| 473 |
+
cursor_position = self.cursor_position
|
| 474 |
+
cells_to_erase = self.screen_size.col - cursor_position.col
|
| 475 |
+
FillConsoleOutputCharacter(
|
| 476 |
+
self._handle, " ", length=cells_to_erase, start=cursor_position
|
| 477 |
+
)
|
| 478 |
+
FillConsoleOutputAttribute(
|
| 479 |
+
self._handle,
|
| 480 |
+
self._default_attrs,
|
| 481 |
+
length=cells_to_erase,
|
| 482 |
+
start=cursor_position,
|
| 483 |
+
)
|
| 484 |
+
|
| 485 |
+
def erase_start_of_line(self) -> None:
|
| 486 |
+
"""Erase all content from the cursor position to the start of that line"""
|
| 487 |
+
row, col = self.cursor_position
|
| 488 |
+
start = WindowsCoordinates(row, 0)
|
| 489 |
+
FillConsoleOutputCharacter(self._handle, " ", length=col, start=start)
|
| 490 |
+
FillConsoleOutputAttribute(
|
| 491 |
+
self._handle, self._default_attrs, length=col, start=start
|
| 492 |
+
)
|
| 493 |
+
|
| 494 |
+
def move_cursor_up(self) -> None:
|
| 495 |
+
"""Move the cursor up a single cell"""
|
| 496 |
+
cursor_position = self.cursor_position
|
| 497 |
+
SetConsoleCursorPosition(
|
| 498 |
+
self._handle,
|
| 499 |
+
coords=WindowsCoordinates(
|
| 500 |
+
row=cursor_position.row - 1, col=cursor_position.col
|
| 501 |
+
),
|
| 502 |
+
)
|
| 503 |
+
|
| 504 |
+
def move_cursor_down(self) -> None:
|
| 505 |
+
"""Move the cursor down a single cell"""
|
| 506 |
+
cursor_position = self.cursor_position
|
| 507 |
+
SetConsoleCursorPosition(
|
| 508 |
+
self._handle,
|
| 509 |
+
coords=WindowsCoordinates(
|
| 510 |
+
row=cursor_position.row + 1,
|
| 511 |
+
col=cursor_position.col,
|
| 512 |
+
),
|
| 513 |
+
)
|
| 514 |
+
|
| 515 |
+
def move_cursor_forward(self) -> None:
|
| 516 |
+
"""Move the cursor forward a single cell. Wrap to the next line if required."""
|
| 517 |
+
row, col = self.cursor_position
|
| 518 |
+
if col == self.screen_size.col - 1:
|
| 519 |
+
row += 1
|
| 520 |
+
col = 0
|
| 521 |
+
else:
|
| 522 |
+
col += 1
|
| 523 |
+
SetConsoleCursorPosition(
|
| 524 |
+
self._handle, coords=WindowsCoordinates(row=row, col=col)
|
| 525 |
+
)
|
| 526 |
+
|
| 527 |
+
def move_cursor_to_column(self, column: int) -> None:
|
| 528 |
+
"""Move cursor to the column specified by the zero-based column index, staying on the same row
|
| 529 |
+
|
| 530 |
+
Args:
|
| 531 |
+
column (int): The zero-based column index to move the cursor to.
|
| 532 |
+
"""
|
| 533 |
+
row, _ = self.cursor_position
|
| 534 |
+
SetConsoleCursorPosition(self._handle, coords=WindowsCoordinates(row, column))
|
| 535 |
+
|
| 536 |
+
def move_cursor_backward(self) -> None:
|
| 537 |
+
"""Move the cursor backward a single cell. Wrap to the previous line if required."""
|
| 538 |
+
row, col = self.cursor_position
|
| 539 |
+
if col == 0:
|
| 540 |
+
row -= 1
|
| 541 |
+
col = self.screen_size.col - 1
|
| 542 |
+
else:
|
| 543 |
+
col -= 1
|
| 544 |
+
SetConsoleCursorPosition(
|
| 545 |
+
self._handle, coords=WindowsCoordinates(row=row, col=col)
|
| 546 |
+
)
|
| 547 |
+
|
| 548 |
+
def hide_cursor(self) -> None:
|
| 549 |
+
"""Hide the cursor"""
|
| 550 |
+
current_cursor_size = self._get_cursor_size()
|
| 551 |
+
invisible_cursor = CONSOLE_CURSOR_INFO(dwSize=current_cursor_size, bVisible=0)
|
| 552 |
+
SetConsoleCursorInfo(self._handle, cursor_info=invisible_cursor)
|
| 553 |
+
|
| 554 |
+
def show_cursor(self) -> None:
|
| 555 |
+
"""Show the cursor"""
|
| 556 |
+
current_cursor_size = self._get_cursor_size()
|
| 557 |
+
visible_cursor = CONSOLE_CURSOR_INFO(dwSize=current_cursor_size, bVisible=1)
|
| 558 |
+
SetConsoleCursorInfo(self._handle, cursor_info=visible_cursor)
|
| 559 |
+
|
| 560 |
+
def set_title(self, title: str) -> None:
|
| 561 |
+
"""Set the title of the terminal window
|
| 562 |
+
|
| 563 |
+
Args:
|
| 564 |
+
title (str): The new title of the console window
|
| 565 |
+
"""
|
| 566 |
+
assert len(title) < 255, "Console title must be less than 255 characters"
|
| 567 |
+
SetConsoleTitle(title)
|
| 568 |
+
|
| 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 |
+
|
| 575 |
+
|
| 576 |
+
if __name__ == "__main__":
|
| 577 |
+
handle = GetStdHandle()
|
| 578 |
+
|
| 579 |
+
from pip._vendor.rich.console import Console
|
| 580 |
+
|
| 581 |
+
console = Console()
|
| 582 |
+
|
| 583 |
+
term = LegacyWindowsTerm(sys.stdout)
|
| 584 |
+
term.set_title("Win32 Console Examples")
|
| 585 |
+
|
| 586 |
+
style = Style(color="black", bgcolor="red")
|
| 587 |
+
|
| 588 |
+
heading = Style.parse("black on green")
|
| 589 |
+
|
| 590 |
+
# Check colour output
|
| 591 |
+
console.rule("Checking colour output")
|
| 592 |
+
console.print("[on red]on red!")
|
| 593 |
+
console.print("[blue]blue!")
|
| 594 |
+
console.print("[yellow]yellow!")
|
| 595 |
+
console.print("[bold yellow]bold yellow!")
|
| 596 |
+
console.print("[bright_yellow]bright_yellow!")
|
| 597 |
+
console.print("[dim bright_yellow]dim bright_yellow!")
|
| 598 |
+
console.print("[italic cyan]italic cyan!")
|
| 599 |
+
console.print("[bold white on blue]bold white on blue!")
|
| 600 |
+
console.print("[reverse bold white on blue]reverse bold white on blue!")
|
| 601 |
+
console.print("[bold black on cyan]bold black on cyan!")
|
| 602 |
+
console.print("[black on green]black on green!")
|
| 603 |
+
console.print("[blue on green]blue on green!")
|
| 604 |
+
console.print("[white on black]white on black!")
|
| 605 |
+
console.print("[black on white]black on white!")
|
| 606 |
+
console.print("[#1BB152 on #DA812D]#1BB152 on #DA812D!")
|
| 607 |
+
|
| 608 |
+
# Check cursor movement
|
| 609 |
+
console.rule("Checking cursor movement")
|
| 610 |
+
console.print()
|
| 611 |
+
term.move_cursor_backward()
|
| 612 |
+
term.move_cursor_backward()
|
| 613 |
+
term.write_text("went back and wrapped to prev line")
|
| 614 |
+
time.sleep(1)
|
| 615 |
+
term.move_cursor_up()
|
| 616 |
+
term.write_text("we go up")
|
| 617 |
+
time.sleep(1)
|
| 618 |
+
term.move_cursor_down()
|
| 619 |
+
term.write_text("and down")
|
| 620 |
+
time.sleep(1)
|
| 621 |
+
term.move_cursor_up()
|
| 622 |
+
term.move_cursor_backward()
|
| 623 |
+
term.move_cursor_backward()
|
| 624 |
+
term.write_text("we went up and back 2")
|
| 625 |
+
time.sleep(1)
|
| 626 |
+
term.move_cursor_down()
|
| 627 |
+
term.move_cursor_backward()
|
| 628 |
+
term.move_cursor_backward()
|
| 629 |
+
term.write_text("we went down and back 2")
|
| 630 |
+
time.sleep(1)
|
| 631 |
+
|
| 632 |
+
# Check erasing of lines
|
| 633 |
+
term.hide_cursor()
|
| 634 |
+
console.print()
|
| 635 |
+
console.rule("Checking line erasing")
|
| 636 |
+
console.print("\n...Deleting to the start of the line...")
|
| 637 |
+
term.write_text("The red arrow shows the cursor location, and direction of erase")
|
| 638 |
+
time.sleep(1)
|
| 639 |
+
term.move_cursor_to_column(16)
|
| 640 |
+
term.write_styled("<", Style.parse("black on red"))
|
| 641 |
+
term.move_cursor_backward()
|
| 642 |
+
time.sleep(1)
|
| 643 |
+
term.erase_start_of_line()
|
| 644 |
+
time.sleep(1)
|
| 645 |
+
|
| 646 |
+
console.print("\n\n...And to the end of the line...")
|
| 647 |
+
term.write_text("The red arrow shows the cursor location, and direction of erase")
|
| 648 |
+
time.sleep(1)
|
| 649 |
+
|
| 650 |
+
term.move_cursor_to_column(16)
|
| 651 |
+
term.write_styled(">", Style.parse("black on red"))
|
| 652 |
+
time.sleep(1)
|
| 653 |
+
term.erase_end_of_line()
|
| 654 |
+
time.sleep(1)
|
| 655 |
+
|
| 656 |
+
console.print("\n\n...Now the whole line will be erased...")
|
| 657 |
+
term.write_styled("I'm going to disappear!", style=Style.parse("black on cyan"))
|
| 658 |
+
time.sleep(1)
|
| 659 |
+
term.erase_line()
|
| 660 |
+
|
| 661 |
+
term.show_cursor()
|
| 662 |
+
print("\n")
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/_windows.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
from dataclasses import dataclass
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
@dataclass
|
| 6 |
+
class WindowsConsoleFeatures:
|
| 7 |
+
"""Windows features available."""
|
| 8 |
+
|
| 9 |
+
vt: bool = False
|
| 10 |
+
"""The console supports VT codes."""
|
| 11 |
+
truecolor: bool = False
|
| 12 |
+
"""The console supports truecolor."""
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
try:
|
| 16 |
+
import ctypes
|
| 17 |
+
from ctypes import LibraryLoader
|
| 18 |
+
|
| 19 |
+
if sys.platform == "win32":
|
| 20 |
+
windll = LibraryLoader(ctypes.WinDLL)
|
| 21 |
+
else:
|
| 22 |
+
windll = None
|
| 23 |
+
raise ImportError("Not windows")
|
| 24 |
+
|
| 25 |
+
from pip._vendor.rich._win32_console import (
|
| 26 |
+
ENABLE_VIRTUAL_TERMINAL_PROCESSING,
|
| 27 |
+
GetConsoleMode,
|
| 28 |
+
GetStdHandle,
|
| 29 |
+
LegacyWindowsError,
|
| 30 |
+
)
|
| 31 |
+
|
| 32 |
+
except (AttributeError, ImportError, ValueError):
|
| 33 |
+
|
| 34 |
+
# Fallback if we can't load the Windows DLL
|
| 35 |
+
def get_windows_console_features() -> WindowsConsoleFeatures:
|
| 36 |
+
features = WindowsConsoleFeatures()
|
| 37 |
+
return features
|
| 38 |
+
|
| 39 |
+
else:
|
| 40 |
+
|
| 41 |
+
def get_windows_console_features() -> WindowsConsoleFeatures:
|
| 42 |
+
"""Get windows console features.
|
| 43 |
+
|
| 44 |
+
Returns:
|
| 45 |
+
WindowsConsoleFeatures: An instance of WindowsConsoleFeatures.
|
| 46 |
+
"""
|
| 47 |
+
handle = GetStdHandle()
|
| 48 |
+
try:
|
| 49 |
+
console_mode = GetConsoleMode(handle)
|
| 50 |
+
success = True
|
| 51 |
+
except LegacyWindowsError:
|
| 52 |
+
console_mode = 0
|
| 53 |
+
success = False
|
| 54 |
+
vt = bool(success and console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
| 55 |
+
truecolor = False
|
| 56 |
+
if vt:
|
| 57 |
+
win_version = sys.getwindowsversion()
|
| 58 |
+
truecolor = win_version.major > 10 or (
|
| 59 |
+
win_version.major == 10 and win_version.build >= 15063
|
| 60 |
+
)
|
| 61 |
+
features = WindowsConsoleFeatures(vt=vt, truecolor=truecolor)
|
| 62 |
+
return features
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
if __name__ == "__main__":
|
| 66 |
+
import platform
|
| 67 |
+
|
| 68 |
+
features = get_windows_console_features()
|
| 69 |
+
from pip._vendor.rich import print
|
| 70 |
+
|
| 71 |
+
print(f'platform="{platform.system()}"')
|
| 72 |
+
print(repr(features))
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/abc.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from abc import ABC
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class RichRenderable(ABC):
|
| 5 |
+
"""An abstract base class for Rich renderables.
|
| 6 |
+
|
| 7 |
+
Note that there is no need to extend this class, the intended use is to check if an
|
| 8 |
+
object supports the Rich renderable protocol. For example::
|
| 9 |
+
|
| 10 |
+
if isinstance(my_object, RichRenderable):
|
| 11 |
+
console.print(my_object)
|
| 12 |
+
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
@classmethod
|
| 16 |
+
def __subclasshook__(cls, other: type) -> bool:
|
| 17 |
+
"""Check if this class supports the rich render protocol."""
|
| 18 |
+
return hasattr(other, "__rich_console__") or hasattr(other, "__rich__")
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
if __name__ == "__main__": # pragma: no cover
|
| 22 |
+
from pip._vendor.rich.text import Text
|
| 23 |
+
|
| 24 |
+
t = Text()
|
| 25 |
+
print(isinstance(Text, RichRenderable))
|
| 26 |
+
print(isinstance(t, RichRenderable))
|
| 27 |
+
|
| 28 |
+
class Foo:
|
| 29 |
+
pass
|
| 30 |
+
|
| 31 |
+
f = Foo()
|
| 32 |
+
print(isinstance(f, RichRenderable))
|
| 33 |
+
print(isinstance("", RichRenderable))
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/align.py
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
from itertools import chain
|
| 3 |
+
from typing import TYPE_CHECKING, Iterable, Optional
|
| 4 |
+
|
| 5 |
+
if sys.version_info >= (3, 8):
|
| 6 |
+
from typing import Literal
|
| 7 |
+
else:
|
| 8 |
+
from pip._vendor.typing_extensions import Literal # pragma: no cover
|
| 9 |
+
|
| 10 |
+
from .constrain import Constrain
|
| 11 |
+
from .jupyter import JupyterMixin
|
| 12 |
+
from .measure import Measurement
|
| 13 |
+
from .segment import Segment
|
| 14 |
+
from .style import StyleType
|
| 15 |
+
|
| 16 |
+
if TYPE_CHECKING:
|
| 17 |
+
from .console import Console, ConsoleOptions, RenderableType, RenderResult
|
| 18 |
+
|
| 19 |
+
AlignMethod = Literal["left", "center", "right"]
|
| 20 |
+
VerticalAlignMethod = Literal["top", "middle", "bottom"]
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
class Align(JupyterMixin):
|
| 24 |
+
"""Align a renderable by adding spaces if necessary.
|
| 25 |
+
|
| 26 |
+
Args:
|
| 27 |
+
renderable (RenderableType): A console renderable.
|
| 28 |
+
align (AlignMethod): One of "left", "center", or "right""
|
| 29 |
+
style (StyleType, optional): An optional style to apply to the background.
|
| 30 |
+
vertical (Optional[VerticalAlginMethod], optional): Optional vertical align, one of "top", "middle", or "bottom". Defaults to None.
|
| 31 |
+
pad (bool, optional): Pad the right with spaces. Defaults to True.
|
| 32 |
+
width (int, optional): Restrict contents to given width, or None to use default width. Defaults to None.
|
| 33 |
+
height (int, optional): Set height of align renderable, or None to fit to contents. Defaults to None.
|
| 34 |
+
|
| 35 |
+
Raises:
|
| 36 |
+
ValueError: if ``align`` is not one of the expected values.
|
| 37 |
+
"""
|
| 38 |
+
|
| 39 |
+
def __init__(
|
| 40 |
+
self,
|
| 41 |
+
renderable: "RenderableType",
|
| 42 |
+
align: AlignMethod = "left",
|
| 43 |
+
style: Optional[StyleType] = None,
|
| 44 |
+
*,
|
| 45 |
+
vertical: Optional[VerticalAlignMethod] = None,
|
| 46 |
+
pad: bool = True,
|
| 47 |
+
width: Optional[int] = None,
|
| 48 |
+
height: Optional[int] = None,
|
| 49 |
+
) -> None:
|
| 50 |
+
if align not in ("left", "center", "right"):
|
| 51 |
+
raise ValueError(
|
| 52 |
+
f'invalid value for align, expected "left", "center", or "right" (not {align!r})'
|
| 53 |
+
)
|
| 54 |
+
if vertical is not None and vertical not in ("top", "middle", "bottom"):
|
| 55 |
+
raise ValueError(
|
| 56 |
+
f'invalid value for vertical, expected "top", "middle", or "bottom" (not {vertical!r})'
|
| 57 |
+
)
|
| 58 |
+
self.renderable = renderable
|
| 59 |
+
self.align = align
|
| 60 |
+
self.style = style
|
| 61 |
+
self.vertical = vertical
|
| 62 |
+
self.pad = pad
|
| 63 |
+
self.width = width
|
| 64 |
+
self.height = height
|
| 65 |
+
|
| 66 |
+
def __repr__(self) -> str:
|
| 67 |
+
return f"Align({self.renderable!r}, {self.align!r})"
|
| 68 |
+
|
| 69 |
+
@classmethod
|
| 70 |
+
def left(
|
| 71 |
+
cls,
|
| 72 |
+
renderable: "RenderableType",
|
| 73 |
+
style: Optional[StyleType] = None,
|
| 74 |
+
*,
|
| 75 |
+
vertical: Optional[VerticalAlignMethod] = None,
|
| 76 |
+
pad: bool = True,
|
| 77 |
+
width: Optional[int] = None,
|
| 78 |
+
height: Optional[int] = None,
|
| 79 |
+
) -> "Align":
|
| 80 |
+
"""Align a renderable to the left."""
|
| 81 |
+
return cls(
|
| 82 |
+
renderable,
|
| 83 |
+
"left",
|
| 84 |
+
style=style,
|
| 85 |
+
vertical=vertical,
|
| 86 |
+
pad=pad,
|
| 87 |
+
width=width,
|
| 88 |
+
height=height,
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
+
@classmethod
|
| 92 |
+
def center(
|
| 93 |
+
cls,
|
| 94 |
+
renderable: "RenderableType",
|
| 95 |
+
style: Optional[StyleType] = None,
|
| 96 |
+
*,
|
| 97 |
+
vertical: Optional[VerticalAlignMethod] = None,
|
| 98 |
+
pad: bool = True,
|
| 99 |
+
width: Optional[int] = None,
|
| 100 |
+
height: Optional[int] = None,
|
| 101 |
+
) -> "Align":
|
| 102 |
+
"""Align a renderable to the center."""
|
| 103 |
+
return cls(
|
| 104 |
+
renderable,
|
| 105 |
+
"center",
|
| 106 |
+
style=style,
|
| 107 |
+
vertical=vertical,
|
| 108 |
+
pad=pad,
|
| 109 |
+
width=width,
|
| 110 |
+
height=height,
|
| 111 |
+
)
|
| 112 |
+
|
| 113 |
+
@classmethod
|
| 114 |
+
def right(
|
| 115 |
+
cls,
|
| 116 |
+
renderable: "RenderableType",
|
| 117 |
+
style: Optional[StyleType] = None,
|
| 118 |
+
*,
|
| 119 |
+
vertical: Optional[VerticalAlignMethod] = None,
|
| 120 |
+
pad: bool = True,
|
| 121 |
+
width: Optional[int] = None,
|
| 122 |
+
height: Optional[int] = None,
|
| 123 |
+
) -> "Align":
|
| 124 |
+
"""Align a renderable to the right."""
|
| 125 |
+
return cls(
|
| 126 |
+
renderable,
|
| 127 |
+
"right",
|
| 128 |
+
style=style,
|
| 129 |
+
vertical=vertical,
|
| 130 |
+
pad=pad,
|
| 131 |
+
width=width,
|
| 132 |
+
height=height,
|
| 133 |
+
)
|
| 134 |
+
|
| 135 |
+
def __rich_console__(
|
| 136 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 137 |
+
) -> "RenderResult":
|
| 138 |
+
align = self.align
|
| 139 |
+
width = console.measure(self.renderable, options=options).maximum
|
| 140 |
+
rendered = console.render(
|
| 141 |
+
Constrain(
|
| 142 |
+
self.renderable, width if self.width is None else min(width, self.width)
|
| 143 |
+
),
|
| 144 |
+
options.update(height=None),
|
| 145 |
+
)
|
| 146 |
+
lines = list(Segment.split_lines(rendered))
|
| 147 |
+
width, height = Segment.get_shape(lines)
|
| 148 |
+
lines = Segment.set_shape(lines, width, height)
|
| 149 |
+
new_line = Segment.line()
|
| 150 |
+
excess_space = options.max_width - width
|
| 151 |
+
style = console.get_style(self.style) if self.style is not None else None
|
| 152 |
+
|
| 153 |
+
def generate_segments() -> Iterable[Segment]:
|
| 154 |
+
if excess_space <= 0:
|
| 155 |
+
# Exact fit
|
| 156 |
+
for line in lines:
|
| 157 |
+
yield from line
|
| 158 |
+
yield new_line
|
| 159 |
+
|
| 160 |
+
elif align == "left":
|
| 161 |
+
# Pad on the right
|
| 162 |
+
pad = Segment(" " * excess_space, style) if self.pad else None
|
| 163 |
+
for line in lines:
|
| 164 |
+
yield from line
|
| 165 |
+
if pad:
|
| 166 |
+
yield pad
|
| 167 |
+
yield new_line
|
| 168 |
+
|
| 169 |
+
elif align == "center":
|
| 170 |
+
# Pad left and right
|
| 171 |
+
left = excess_space // 2
|
| 172 |
+
pad = Segment(" " * left, style)
|
| 173 |
+
pad_right = (
|
| 174 |
+
Segment(" " * (excess_space - left), style) if self.pad else None
|
| 175 |
+
)
|
| 176 |
+
for line in lines:
|
| 177 |
+
if left:
|
| 178 |
+
yield pad
|
| 179 |
+
yield from line
|
| 180 |
+
if pad_right:
|
| 181 |
+
yield pad_right
|
| 182 |
+
yield new_line
|
| 183 |
+
|
| 184 |
+
elif align == "right":
|
| 185 |
+
# Padding on left
|
| 186 |
+
pad = Segment(" " * excess_space, style)
|
| 187 |
+
for line in lines:
|
| 188 |
+
yield pad
|
| 189 |
+
yield from line
|
| 190 |
+
yield new_line
|
| 191 |
+
|
| 192 |
+
blank_line = (
|
| 193 |
+
Segment(f"{' ' * (self.width or options.max_width)}\n", style)
|
| 194 |
+
if self.pad
|
| 195 |
+
else Segment("\n")
|
| 196 |
+
)
|
| 197 |
+
|
| 198 |
+
def blank_lines(count: int) -> Iterable[Segment]:
|
| 199 |
+
if count > 0:
|
| 200 |
+
for _ in range(count):
|
| 201 |
+
yield blank_line
|
| 202 |
+
|
| 203 |
+
vertical_height = self.height or options.height
|
| 204 |
+
iter_segments: Iterable[Segment]
|
| 205 |
+
if self.vertical and vertical_height is not None:
|
| 206 |
+
if self.vertical == "top":
|
| 207 |
+
bottom_space = vertical_height - height
|
| 208 |
+
iter_segments = chain(generate_segments(), blank_lines(bottom_space))
|
| 209 |
+
elif self.vertical == "middle":
|
| 210 |
+
top_space = (vertical_height - height) // 2
|
| 211 |
+
bottom_space = vertical_height - top_space - height
|
| 212 |
+
iter_segments = chain(
|
| 213 |
+
blank_lines(top_space),
|
| 214 |
+
generate_segments(),
|
| 215 |
+
blank_lines(bottom_space),
|
| 216 |
+
)
|
| 217 |
+
else: # self.vertical == "bottom":
|
| 218 |
+
top_space = vertical_height - height
|
| 219 |
+
iter_segments = chain(blank_lines(top_space), generate_segments())
|
| 220 |
+
else:
|
| 221 |
+
iter_segments = generate_segments()
|
| 222 |
+
if self.style:
|
| 223 |
+
style = console.get_style(self.style)
|
| 224 |
+
iter_segments = Segment.apply_style(iter_segments, style)
|
| 225 |
+
yield from iter_segments
|
| 226 |
+
|
| 227 |
+
def __rich_measure__(
|
| 228 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 229 |
+
) -> Measurement:
|
| 230 |
+
measurement = Measurement.get(console, options, self.renderable)
|
| 231 |
+
return measurement
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
class VerticalCenter(JupyterMixin):
|
| 235 |
+
"""Vertically aligns a renderable.
|
| 236 |
+
|
| 237 |
+
Warn:
|
| 238 |
+
This class is deprecated and may be removed in a future version. Use Align class with
|
| 239 |
+
`vertical="middle"`.
|
| 240 |
+
|
| 241 |
+
Args:
|
| 242 |
+
renderable (RenderableType): A renderable object.
|
| 243 |
+
"""
|
| 244 |
+
|
| 245 |
+
def __init__(
|
| 246 |
+
self,
|
| 247 |
+
renderable: "RenderableType",
|
| 248 |
+
style: Optional[StyleType] = None,
|
| 249 |
+
) -> None:
|
| 250 |
+
self.renderable = renderable
|
| 251 |
+
self.style = style
|
| 252 |
+
|
| 253 |
+
def __repr__(self) -> str:
|
| 254 |
+
return f"VerticalCenter({self.renderable!r})"
|
| 255 |
+
|
| 256 |
+
def __rich_console__(
|
| 257 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 258 |
+
) -> "RenderResult":
|
| 259 |
+
style = console.get_style(self.style) if self.style is not None else None
|
| 260 |
+
lines = console.render_lines(
|
| 261 |
+
self.renderable, options.update(height=None), pad=False
|
| 262 |
+
)
|
| 263 |
+
width, _height = Segment.get_shape(lines)
|
| 264 |
+
new_line = Segment.line()
|
| 265 |
+
height = options.height or options.size.height
|
| 266 |
+
top_space = (height - len(lines)) // 2
|
| 267 |
+
bottom_space = height - top_space - len(lines)
|
| 268 |
+
blank_line = Segment(f"{' ' * width}", style)
|
| 269 |
+
|
| 270 |
+
def blank_lines(count: int) -> Iterable[Segment]:
|
| 271 |
+
for _ in range(count):
|
| 272 |
+
yield blank_line
|
| 273 |
+
yield new_line
|
| 274 |
+
|
| 275 |
+
if top_space > 0:
|
| 276 |
+
yield from blank_lines(top_space)
|
| 277 |
+
for line in lines:
|
| 278 |
+
yield from line
|
| 279 |
+
yield new_line
|
| 280 |
+
if bottom_space > 0:
|
| 281 |
+
yield from blank_lines(bottom_space)
|
| 282 |
+
|
| 283 |
+
def __rich_measure__(
|
| 284 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 285 |
+
) -> Measurement:
|
| 286 |
+
measurement = Measurement.get(console, options, self.renderable)
|
| 287 |
+
return measurement
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
if __name__ == "__main__": # pragma: no cover
|
| 291 |
+
from pip._vendor.rich.console import Console, Group
|
| 292 |
+
from pip._vendor.rich.highlighter import ReprHighlighter
|
| 293 |
+
from pip._vendor.rich.panel import Panel
|
| 294 |
+
|
| 295 |
+
highlighter = ReprHighlighter()
|
| 296 |
+
console = Console()
|
| 297 |
+
|
| 298 |
+
panel = Panel(
|
| 299 |
+
Group(
|
| 300 |
+
Align.left(highlighter("align='left'")),
|
| 301 |
+
Align.center(highlighter("align='center'")),
|
| 302 |
+
Align.right(highlighter("align='right'")),
|
| 303 |
+
),
|
| 304 |
+
width=60,
|
| 305 |
+
style="on dark_blue",
|
| 306 |
+
title="Align",
|
| 307 |
+
)
|
| 308 |
+
|
| 309 |
+
console.print(
|
| 310 |
+
Align.center(panel, vertical="middle", style="on red", height=console.height)
|
| 311 |
+
)
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/bar.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Optional, Union
|
| 2 |
+
|
| 3 |
+
from .color import Color
|
| 4 |
+
from .console import Console, ConsoleOptions, RenderResult
|
| 5 |
+
from .jupyter import JupyterMixin
|
| 6 |
+
from .measure import Measurement
|
| 7 |
+
from .segment import Segment
|
| 8 |
+
from .style import Style
|
| 9 |
+
|
| 10 |
+
# There are left-aligned characters for 1/8 to 7/8, but
|
| 11 |
+
# the right-aligned characters exist only for 1/8 and 4/8.
|
| 12 |
+
BEGIN_BLOCK_ELEMENTS = ["█", "█", "█", "▐", "▐", "▐", "▕", "▕"]
|
| 13 |
+
END_BLOCK_ELEMENTS = [" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉"]
|
| 14 |
+
FULL_BLOCK = "█"
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class Bar(JupyterMixin):
|
| 18 |
+
"""Renders a solid block bar.
|
| 19 |
+
|
| 20 |
+
Args:
|
| 21 |
+
size (float): Value for the end of the bar.
|
| 22 |
+
begin (float): Begin point (between 0 and size, inclusive).
|
| 23 |
+
end (float): End point (between 0 and size, inclusive).
|
| 24 |
+
width (int, optional): Width of the bar, or ``None`` for maximum width. Defaults to None.
|
| 25 |
+
color (Union[Color, str], optional): Color of the bar. Defaults to "default".
|
| 26 |
+
bgcolor (Union[Color, str], optional): Color of bar background. Defaults to "default".
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
def __init__(
|
| 30 |
+
self,
|
| 31 |
+
size: float,
|
| 32 |
+
begin: float,
|
| 33 |
+
end: float,
|
| 34 |
+
*,
|
| 35 |
+
width: Optional[int] = None,
|
| 36 |
+
color: Union[Color, str] = "default",
|
| 37 |
+
bgcolor: Union[Color, str] = "default",
|
| 38 |
+
):
|
| 39 |
+
self.size = size
|
| 40 |
+
self.begin = max(begin, 0)
|
| 41 |
+
self.end = min(end, size)
|
| 42 |
+
self.width = width
|
| 43 |
+
self.style = Style(color=color, bgcolor=bgcolor)
|
| 44 |
+
|
| 45 |
+
def __repr__(self) -> str:
|
| 46 |
+
return f"Bar({self.size}, {self.begin}, {self.end})"
|
| 47 |
+
|
| 48 |
+
def __rich_console__(
|
| 49 |
+
self, console: Console, options: ConsoleOptions
|
| 50 |
+
) -> RenderResult:
|
| 51 |
+
|
| 52 |
+
width = min(
|
| 53 |
+
self.width if self.width is not None else options.max_width,
|
| 54 |
+
options.max_width,
|
| 55 |
+
)
|
| 56 |
+
|
| 57 |
+
if self.begin >= self.end:
|
| 58 |
+
yield Segment(" " * width, self.style)
|
| 59 |
+
yield Segment.line()
|
| 60 |
+
return
|
| 61 |
+
|
| 62 |
+
prefix_complete_eights = int(width * 8 * self.begin / self.size)
|
| 63 |
+
prefix_bar_count = prefix_complete_eights // 8
|
| 64 |
+
prefix_eights_count = prefix_complete_eights % 8
|
| 65 |
+
|
| 66 |
+
body_complete_eights = int(width * 8 * self.end / self.size)
|
| 67 |
+
body_bar_count = body_complete_eights // 8
|
| 68 |
+
body_eights_count = body_complete_eights % 8
|
| 69 |
+
|
| 70 |
+
# When start and end fall into the same cell, we ideally should render
|
| 71 |
+
# a symbol that's "center-aligned", but there is no good symbol in Unicode.
|
| 72 |
+
# In this case, we fall back to right-aligned block symbol for simplicity.
|
| 73 |
+
|
| 74 |
+
prefix = " " * prefix_bar_count
|
| 75 |
+
if prefix_eights_count:
|
| 76 |
+
prefix += BEGIN_BLOCK_ELEMENTS[prefix_eights_count]
|
| 77 |
+
|
| 78 |
+
body = FULL_BLOCK * body_bar_count
|
| 79 |
+
if body_eights_count:
|
| 80 |
+
body += END_BLOCK_ELEMENTS[body_eights_count]
|
| 81 |
+
|
| 82 |
+
suffix = " " * (width - len(body))
|
| 83 |
+
|
| 84 |
+
yield Segment(prefix + body[len(prefix) :] + suffix, self.style)
|
| 85 |
+
yield Segment.line()
|
| 86 |
+
|
| 87 |
+
def __rich_measure__(
|
| 88 |
+
self, console: Console, options: ConsoleOptions
|
| 89 |
+
) -> Measurement:
|
| 90 |
+
return (
|
| 91 |
+
Measurement(self.width, self.width)
|
| 92 |
+
if self.width is not None
|
| 93 |
+
else Measurement(4, options.max_width)
|
| 94 |
+
)
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/box.py
ADDED
|
@@ -0,0 +1,517 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
from typing import TYPE_CHECKING, Iterable, List
|
| 3 |
+
|
| 4 |
+
if sys.version_info >= (3, 8):
|
| 5 |
+
from typing import Literal
|
| 6 |
+
else:
|
| 7 |
+
from pip._vendor.typing_extensions import Literal # pragma: no cover
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
from ._loop import loop_last
|
| 11 |
+
|
| 12 |
+
if TYPE_CHECKING:
|
| 13 |
+
from pip._vendor.rich.console import ConsoleOptions
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class Box:
|
| 17 |
+
"""Defines characters to render boxes.
|
| 18 |
+
|
| 19 |
+
┌─┬┐ top
|
| 20 |
+
│ ││ head
|
| 21 |
+
├─┼┤ head_row
|
| 22 |
+
│ ││ mid
|
| 23 |
+
├─┼┤ row
|
| 24 |
+
├─┼┤ foot_row
|
| 25 |
+
│ ││ foot
|
| 26 |
+
└─┴┘ bottom
|
| 27 |
+
|
| 28 |
+
Args:
|
| 29 |
+
box (str): Characters making up box.
|
| 30 |
+
ascii (bool, optional): True if this box uses ascii characters only. Default is False.
|
| 31 |
+
"""
|
| 32 |
+
|
| 33 |
+
def __init__(self, box: str, *, ascii: bool = False) -> None:
|
| 34 |
+
self._box = box
|
| 35 |
+
self.ascii = ascii
|
| 36 |
+
line1, line2, line3, line4, line5, line6, line7, line8 = box.splitlines()
|
| 37 |
+
# top
|
| 38 |
+
self.top_left, self.top, self.top_divider, self.top_right = iter(line1)
|
| 39 |
+
# head
|
| 40 |
+
self.head_left, _, self.head_vertical, self.head_right = iter(line2)
|
| 41 |
+
# head_row
|
| 42 |
+
(
|
| 43 |
+
self.head_row_left,
|
| 44 |
+
self.head_row_horizontal,
|
| 45 |
+
self.head_row_cross,
|
| 46 |
+
self.head_row_right,
|
| 47 |
+
) = iter(line3)
|
| 48 |
+
|
| 49 |
+
# mid
|
| 50 |
+
self.mid_left, _, self.mid_vertical, self.mid_right = iter(line4)
|
| 51 |
+
# row
|
| 52 |
+
self.row_left, self.row_horizontal, self.row_cross, self.row_right = iter(line5)
|
| 53 |
+
# foot_row
|
| 54 |
+
(
|
| 55 |
+
self.foot_row_left,
|
| 56 |
+
self.foot_row_horizontal,
|
| 57 |
+
self.foot_row_cross,
|
| 58 |
+
self.foot_row_right,
|
| 59 |
+
) = iter(line6)
|
| 60 |
+
# foot
|
| 61 |
+
self.foot_left, _, self.foot_vertical, self.foot_right = iter(line7)
|
| 62 |
+
# bottom
|
| 63 |
+
self.bottom_left, self.bottom, self.bottom_divider, self.bottom_right = iter(
|
| 64 |
+
line8
|
| 65 |
+
)
|
| 66 |
+
|
| 67 |
+
def __repr__(self) -> str:
|
| 68 |
+
return "Box(...)"
|
| 69 |
+
|
| 70 |
+
def __str__(self) -> str:
|
| 71 |
+
return self._box
|
| 72 |
+
|
| 73 |
+
def substitute(self, options: "ConsoleOptions", safe: bool = True) -> "Box":
|
| 74 |
+
"""Substitute this box for another if it won't render due to platform issues.
|
| 75 |
+
|
| 76 |
+
Args:
|
| 77 |
+
options (ConsoleOptions): Console options used in rendering.
|
| 78 |
+
safe (bool, optional): Substitute this for another Box if there are known problems
|
| 79 |
+
displaying on the platform (currently only relevant on Windows). Default is True.
|
| 80 |
+
|
| 81 |
+
Returns:
|
| 82 |
+
Box: A different Box or the same Box.
|
| 83 |
+
"""
|
| 84 |
+
box = self
|
| 85 |
+
if options.legacy_windows and safe:
|
| 86 |
+
box = LEGACY_WINDOWS_SUBSTITUTIONS.get(box, box)
|
| 87 |
+
if options.ascii_only and not box.ascii:
|
| 88 |
+
box = ASCII
|
| 89 |
+
return box
|
| 90 |
+
|
| 91 |
+
def get_plain_headed_box(self) -> "Box":
|
| 92 |
+
"""If this box uses special characters for the borders of the header, then
|
| 93 |
+
return the equivalent box that does not.
|
| 94 |
+
|
| 95 |
+
Returns:
|
| 96 |
+
Box: The most similar Box that doesn't use header-specific box characters.
|
| 97 |
+
If the current Box already satisfies this criterion, then it's returned.
|
| 98 |
+
"""
|
| 99 |
+
return PLAIN_HEADED_SUBSTITUTIONS.get(self, self)
|
| 100 |
+
|
| 101 |
+
def get_top(self, widths: Iterable[int]) -> str:
|
| 102 |
+
"""Get the top of a simple box.
|
| 103 |
+
|
| 104 |
+
Args:
|
| 105 |
+
widths (List[int]): Widths of columns.
|
| 106 |
+
|
| 107 |
+
Returns:
|
| 108 |
+
str: A string of box characters.
|
| 109 |
+
"""
|
| 110 |
+
|
| 111 |
+
parts: List[str] = []
|
| 112 |
+
append = parts.append
|
| 113 |
+
append(self.top_left)
|
| 114 |
+
for last, width in loop_last(widths):
|
| 115 |
+
append(self.top * width)
|
| 116 |
+
if not last:
|
| 117 |
+
append(self.top_divider)
|
| 118 |
+
append(self.top_right)
|
| 119 |
+
return "".join(parts)
|
| 120 |
+
|
| 121 |
+
def get_row(
|
| 122 |
+
self,
|
| 123 |
+
widths: Iterable[int],
|
| 124 |
+
level: Literal["head", "row", "foot", "mid"] = "row",
|
| 125 |
+
edge: bool = True,
|
| 126 |
+
) -> str:
|
| 127 |
+
"""Get the top of a simple box.
|
| 128 |
+
|
| 129 |
+
Args:
|
| 130 |
+
width (List[int]): Widths of columns.
|
| 131 |
+
|
| 132 |
+
Returns:
|
| 133 |
+
str: A string of box characters.
|
| 134 |
+
"""
|
| 135 |
+
if level == "head":
|
| 136 |
+
left = self.head_row_left
|
| 137 |
+
horizontal = self.head_row_horizontal
|
| 138 |
+
cross = self.head_row_cross
|
| 139 |
+
right = self.head_row_right
|
| 140 |
+
elif level == "row":
|
| 141 |
+
left = self.row_left
|
| 142 |
+
horizontal = self.row_horizontal
|
| 143 |
+
cross = self.row_cross
|
| 144 |
+
right = self.row_right
|
| 145 |
+
elif level == "mid":
|
| 146 |
+
left = self.mid_left
|
| 147 |
+
horizontal = " "
|
| 148 |
+
cross = self.mid_vertical
|
| 149 |
+
right = self.mid_right
|
| 150 |
+
elif level == "foot":
|
| 151 |
+
left = self.foot_row_left
|
| 152 |
+
horizontal = self.foot_row_horizontal
|
| 153 |
+
cross = self.foot_row_cross
|
| 154 |
+
right = self.foot_row_right
|
| 155 |
+
else:
|
| 156 |
+
raise ValueError("level must be 'head', 'row' or 'foot'")
|
| 157 |
+
|
| 158 |
+
parts: List[str] = []
|
| 159 |
+
append = parts.append
|
| 160 |
+
if edge:
|
| 161 |
+
append(left)
|
| 162 |
+
for last, width in loop_last(widths):
|
| 163 |
+
append(horizontal * width)
|
| 164 |
+
if not last:
|
| 165 |
+
append(cross)
|
| 166 |
+
if edge:
|
| 167 |
+
append(right)
|
| 168 |
+
return "".join(parts)
|
| 169 |
+
|
| 170 |
+
def get_bottom(self, widths: Iterable[int]) -> str:
|
| 171 |
+
"""Get the bottom of a simple box.
|
| 172 |
+
|
| 173 |
+
Args:
|
| 174 |
+
widths (List[int]): Widths of columns.
|
| 175 |
+
|
| 176 |
+
Returns:
|
| 177 |
+
str: A string of box characters.
|
| 178 |
+
"""
|
| 179 |
+
|
| 180 |
+
parts: List[str] = []
|
| 181 |
+
append = parts.append
|
| 182 |
+
append(self.bottom_left)
|
| 183 |
+
for last, width in loop_last(widths):
|
| 184 |
+
append(self.bottom * width)
|
| 185 |
+
if not last:
|
| 186 |
+
append(self.bottom_divider)
|
| 187 |
+
append(self.bottom_right)
|
| 188 |
+
return "".join(parts)
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
ASCII: Box = Box(
|
| 192 |
+
"""\
|
| 193 |
+
+--+
|
| 194 |
+
| ||
|
| 195 |
+
|-+|
|
| 196 |
+
| ||
|
| 197 |
+
|-+|
|
| 198 |
+
|-+|
|
| 199 |
+
| ||
|
| 200 |
+
+--+
|
| 201 |
+
""",
|
| 202 |
+
ascii=True,
|
| 203 |
+
)
|
| 204 |
+
|
| 205 |
+
ASCII2: Box = Box(
|
| 206 |
+
"""\
|
| 207 |
+
+-++
|
| 208 |
+
| ||
|
| 209 |
+
+-++
|
| 210 |
+
| ||
|
| 211 |
+
+-++
|
| 212 |
+
+-++
|
| 213 |
+
| ||
|
| 214 |
+
+-++
|
| 215 |
+
""",
|
| 216 |
+
ascii=True,
|
| 217 |
+
)
|
| 218 |
+
|
| 219 |
+
ASCII_DOUBLE_HEAD: Box = Box(
|
| 220 |
+
"""\
|
| 221 |
+
+-++
|
| 222 |
+
| ||
|
| 223 |
+
+=++
|
| 224 |
+
| ||
|
| 225 |
+
+-++
|
| 226 |
+
+-++
|
| 227 |
+
| ||
|
| 228 |
+
+-++
|
| 229 |
+
""",
|
| 230 |
+
ascii=True,
|
| 231 |
+
)
|
| 232 |
+
|
| 233 |
+
SQUARE: Box = Box(
|
| 234 |
+
"""\
|
| 235 |
+
┌─┬┐
|
| 236 |
+
│ ││
|
| 237 |
+
├─┼┤
|
| 238 |
+
│ ││
|
| 239 |
+
├─┼┤
|
| 240 |
+
├─┼┤
|
| 241 |
+
│ ││
|
| 242 |
+
└─┴┘
|
| 243 |
+
"""
|
| 244 |
+
)
|
| 245 |
+
|
| 246 |
+
SQUARE_DOUBLE_HEAD: Box = Box(
|
| 247 |
+
"""\
|
| 248 |
+
┌─┬┐
|
| 249 |
+
│ ││
|
| 250 |
+
╞═╪╡
|
| 251 |
+
│ ││
|
| 252 |
+
├─┼┤
|
| 253 |
+
├─┼┤
|
| 254 |
+
│ ││
|
| 255 |
+
└─┴┘
|
| 256 |
+
"""
|
| 257 |
+
)
|
| 258 |
+
|
| 259 |
+
MINIMAL: Box = Box(
|
| 260 |
+
"""\
|
| 261 |
+
╷
|
| 262 |
+
│
|
| 263 |
+
╶─┼╴
|
| 264 |
+
│
|
| 265 |
+
╶─┼╴
|
| 266 |
+
╶─┼╴
|
| 267 |
+
│
|
| 268 |
+
╵
|
| 269 |
+
"""
|
| 270 |
+
)
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
MINIMAL_HEAVY_HEAD: Box = Box(
|
| 274 |
+
"""\
|
| 275 |
+
╷
|
| 276 |
+
│
|
| 277 |
+
╺━┿╸
|
| 278 |
+
│
|
| 279 |
+
╶─┼╴
|
| 280 |
+
╶─┼╴
|
| 281 |
+
│
|
| 282 |
+
╵
|
| 283 |
+
"""
|
| 284 |
+
)
|
| 285 |
+
|
| 286 |
+
MINIMAL_DOUBLE_HEAD: Box = Box(
|
| 287 |
+
"""\
|
| 288 |
+
╷
|
| 289 |
+
│
|
| 290 |
+
═╪
|
| 291 |
+
│
|
| 292 |
+
─┼
|
| 293 |
+
─┼
|
| 294 |
+
│
|
| 295 |
+
╵
|
| 296 |
+
"""
|
| 297 |
+
)
|
| 298 |
+
|
| 299 |
+
|
| 300 |
+
SIMPLE: Box = Box(
|
| 301 |
+
"""\
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
──
|
| 305 |
+
|
| 306 |
+
|
| 307 |
+
──
|
| 308 |
+
|
| 309 |
+
|
| 310 |
+
"""
|
| 311 |
+
)
|
| 312 |
+
|
| 313 |
+
SIMPLE_HEAD: Box = Box(
|
| 314 |
+
"""\
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
──
|
| 318 |
+
|
| 319 |
+
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
"""
|
| 324 |
+
)
|
| 325 |
+
|
| 326 |
+
|
| 327 |
+
SIMPLE_HEAVY: Box = Box(
|
| 328 |
+
"""\
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
━━
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
━━
|
| 335 |
+
|
| 336 |
+
|
| 337 |
+
"""
|
| 338 |
+
)
|
| 339 |
+
|
| 340 |
+
|
| 341 |
+
HORIZONTALS: Box = Box(
|
| 342 |
+
"""\
|
| 343 |
+
──
|
| 344 |
+
|
| 345 |
+
──
|
| 346 |
+
|
| 347 |
+
──
|
| 348 |
+
──
|
| 349 |
+
|
| 350 |
+
──
|
| 351 |
+
"""
|
| 352 |
+
)
|
| 353 |
+
|
| 354 |
+
ROUNDED: Box = Box(
|
| 355 |
+
"""\
|
| 356 |
+
╭─┬╮
|
| 357 |
+
│ ││
|
| 358 |
+
├─┼┤
|
| 359 |
+
│ ││
|
| 360 |
+
├─┼┤
|
| 361 |
+
├─┼┤
|
| 362 |
+
│ ││
|
| 363 |
+
╰─┴╯
|
| 364 |
+
"""
|
| 365 |
+
)
|
| 366 |
+
|
| 367 |
+
HEAVY: Box = Box(
|
| 368 |
+
"""\
|
| 369 |
+
┏━┳┓
|
| 370 |
+
┃ ┃┃
|
| 371 |
+
┣━╋┫
|
| 372 |
+
┃ ┃┃
|
| 373 |
+
┣━╋┫
|
| 374 |
+
┣━╋┫
|
| 375 |
+
┃ ┃┃
|
| 376 |
+
┗━┻┛
|
| 377 |
+
"""
|
| 378 |
+
)
|
| 379 |
+
|
| 380 |
+
HEAVY_EDGE: Box = Box(
|
| 381 |
+
"""\
|
| 382 |
+
┏━┯┓
|
| 383 |
+
┃ │┃
|
| 384 |
+
┠─┼┨
|
| 385 |
+
┃ │┃
|
| 386 |
+
┠─┼┨
|
| 387 |
+
┠─┼┨
|
| 388 |
+
┃ │┃
|
| 389 |
+
┗━┷┛
|
| 390 |
+
"""
|
| 391 |
+
)
|
| 392 |
+
|
| 393 |
+
HEAVY_HEAD: Box = Box(
|
| 394 |
+
"""\
|
| 395 |
+
┏━┳┓
|
| 396 |
+
┃ ┃┃
|
| 397 |
+
┡━╇┩
|
| 398 |
+
│ ││
|
| 399 |
+
├─┼┤
|
| 400 |
+
├─┼┤
|
| 401 |
+
│ ││
|
| 402 |
+
└─┴┘
|
| 403 |
+
"""
|
| 404 |
+
)
|
| 405 |
+
|
| 406 |
+
DOUBLE: Box = Box(
|
| 407 |
+
"""\
|
| 408 |
+
╔═╦╗
|
| 409 |
+
║ ║║
|
| 410 |
+
╠═╬╣
|
| 411 |
+
║ ║║
|
| 412 |
+
╠═╬╣
|
| 413 |
+
╠═╬╣
|
| 414 |
+
║ ║║
|
| 415 |
+
╚═╩╝
|
| 416 |
+
"""
|
| 417 |
+
)
|
| 418 |
+
|
| 419 |
+
DOUBLE_EDGE: Box = Box(
|
| 420 |
+
"""\
|
| 421 |
+
╔═╤╗
|
| 422 |
+
║ │║
|
| 423 |
+
╟─┼╢
|
| 424 |
+
║ │║
|
| 425 |
+
╟─┼╢
|
| 426 |
+
╟─┼╢
|
| 427 |
+
║ │║
|
| 428 |
+
╚═╧╝
|
| 429 |
+
"""
|
| 430 |
+
)
|
| 431 |
+
|
| 432 |
+
MARKDOWN: Box = Box(
|
| 433 |
+
"""\
|
| 434 |
+
|
| 435 |
+
| ||
|
| 436 |
+
|-||
|
| 437 |
+
| ||
|
| 438 |
+
|-||
|
| 439 |
+
|-||
|
| 440 |
+
| ||
|
| 441 |
+
|
| 442 |
+
""",
|
| 443 |
+
ascii=True,
|
| 444 |
+
)
|
| 445 |
+
|
| 446 |
+
# Map Boxes that don't render with raster fonts on to equivalent that do
|
| 447 |
+
LEGACY_WINDOWS_SUBSTITUTIONS = {
|
| 448 |
+
ROUNDED: SQUARE,
|
| 449 |
+
MINIMAL_HEAVY_HEAD: MINIMAL,
|
| 450 |
+
SIMPLE_HEAVY: SIMPLE,
|
| 451 |
+
HEAVY: SQUARE,
|
| 452 |
+
HEAVY_EDGE: SQUARE,
|
| 453 |
+
HEAVY_HEAD: SQUARE,
|
| 454 |
+
}
|
| 455 |
+
|
| 456 |
+
# Map headed boxes to their headerless equivalents
|
| 457 |
+
PLAIN_HEADED_SUBSTITUTIONS = {
|
| 458 |
+
HEAVY_HEAD: SQUARE,
|
| 459 |
+
SQUARE_DOUBLE_HEAD: SQUARE,
|
| 460 |
+
MINIMAL_DOUBLE_HEAD: MINIMAL,
|
| 461 |
+
MINIMAL_HEAVY_HEAD: MINIMAL,
|
| 462 |
+
ASCII_DOUBLE_HEAD: ASCII2,
|
| 463 |
+
}
|
| 464 |
+
|
| 465 |
+
|
| 466 |
+
if __name__ == "__main__": # pragma: no cover
|
| 467 |
+
|
| 468 |
+
from pip._vendor.rich.columns import Columns
|
| 469 |
+
from pip._vendor.rich.panel import Panel
|
| 470 |
+
|
| 471 |
+
from . import box as box
|
| 472 |
+
from .console import Console
|
| 473 |
+
from .table import Table
|
| 474 |
+
from .text import Text
|
| 475 |
+
|
| 476 |
+
console = Console(record=True)
|
| 477 |
+
|
| 478 |
+
BOXES = [
|
| 479 |
+
"ASCII",
|
| 480 |
+
"ASCII2",
|
| 481 |
+
"ASCII_DOUBLE_HEAD",
|
| 482 |
+
"SQUARE",
|
| 483 |
+
"SQUARE_DOUBLE_HEAD",
|
| 484 |
+
"MINIMAL",
|
| 485 |
+
"MINIMAL_HEAVY_HEAD",
|
| 486 |
+
"MINIMAL_DOUBLE_HEAD",
|
| 487 |
+
"SIMPLE",
|
| 488 |
+
"SIMPLE_HEAD",
|
| 489 |
+
"SIMPLE_HEAVY",
|
| 490 |
+
"HORIZONTALS",
|
| 491 |
+
"ROUNDED",
|
| 492 |
+
"HEAVY",
|
| 493 |
+
"HEAVY_EDGE",
|
| 494 |
+
"HEAVY_HEAD",
|
| 495 |
+
"DOUBLE",
|
| 496 |
+
"DOUBLE_EDGE",
|
| 497 |
+
"MARKDOWN",
|
| 498 |
+
]
|
| 499 |
+
|
| 500 |
+
console.print(Panel("[bold green]Box Constants", style="green"), justify="center")
|
| 501 |
+
console.print()
|
| 502 |
+
|
| 503 |
+
columns = Columns(expand=True, padding=2)
|
| 504 |
+
for box_name in sorted(BOXES):
|
| 505 |
+
table = Table(
|
| 506 |
+
show_footer=True, style="dim", border_style="not dim", expand=True
|
| 507 |
+
)
|
| 508 |
+
table.add_column("Header 1", "Footer 1")
|
| 509 |
+
table.add_column("Header 2", "Footer 2")
|
| 510 |
+
table.add_row("Cell", "Cell")
|
| 511 |
+
table.add_row("Cell", "Cell")
|
| 512 |
+
table.box = getattr(box, box_name)
|
| 513 |
+
table.title = Text(f"box.{box_name}", style="magenta")
|
| 514 |
+
columns.add_renderable(table)
|
| 515 |
+
console.print(columns)
|
| 516 |
+
|
| 517 |
+
# console.save_svg("box.svg")
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/cells.py
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
from functools import lru_cache
|
| 3 |
+
from typing import Callable, List
|
| 4 |
+
|
| 5 |
+
from ._cell_widths import CELL_WIDTHS
|
| 6 |
+
|
| 7 |
+
# Regex to match sequence of the most common character ranges
|
| 8 |
+
_is_single_cell_widths = re.compile("^[\u0020-\u006f\u00a0\u02ff\u0370-\u0482]*$").match
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
@lru_cache(4096)
|
| 12 |
+
def cached_cell_len(text: str) -> int:
|
| 13 |
+
"""Get the number of cells required to display text.
|
| 14 |
+
|
| 15 |
+
This method always caches, which may use up a lot of memory. It is recommended to use
|
| 16 |
+
`cell_len` over this method.
|
| 17 |
+
|
| 18 |
+
Args:
|
| 19 |
+
text (str): Text to display.
|
| 20 |
+
|
| 21 |
+
Returns:
|
| 22 |
+
int: Get the number of cells required to display text.
|
| 23 |
+
"""
|
| 24 |
+
_get_size = get_character_cell_size
|
| 25 |
+
total_size = sum(_get_size(character) for character in text)
|
| 26 |
+
return total_size
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def cell_len(text: str, _cell_len: Callable[[str], int] = cached_cell_len) -> int:
|
| 30 |
+
"""Get the number of cells required to display text.
|
| 31 |
+
|
| 32 |
+
Args:
|
| 33 |
+
text (str): Text to display.
|
| 34 |
+
|
| 35 |
+
Returns:
|
| 36 |
+
int: Get the number of cells required to display text.
|
| 37 |
+
"""
|
| 38 |
+
if len(text) < 512:
|
| 39 |
+
return _cell_len(text)
|
| 40 |
+
_get_size = get_character_cell_size
|
| 41 |
+
total_size = sum(_get_size(character) for character in text)
|
| 42 |
+
return total_size
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
@lru_cache(maxsize=4096)
|
| 46 |
+
def get_character_cell_size(character: str) -> int:
|
| 47 |
+
"""Get the cell size of a character.
|
| 48 |
+
|
| 49 |
+
Args:
|
| 50 |
+
character (str): A single character.
|
| 51 |
+
|
| 52 |
+
Returns:
|
| 53 |
+
int: Number of cells (0, 1 or 2) occupied by that character.
|
| 54 |
+
"""
|
| 55 |
+
return _get_codepoint_cell_size(ord(character))
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
@lru_cache(maxsize=4096)
|
| 59 |
+
def _get_codepoint_cell_size(codepoint: int) -> int:
|
| 60 |
+
"""Get the cell size of a character.
|
| 61 |
+
|
| 62 |
+
Args:
|
| 63 |
+
codepoint (int): Codepoint of a character.
|
| 64 |
+
|
| 65 |
+
Returns:
|
| 66 |
+
int: Number of cells (0, 1 or 2) occupied by that character.
|
| 67 |
+
"""
|
| 68 |
+
|
| 69 |
+
_table = CELL_WIDTHS
|
| 70 |
+
lower_bound = 0
|
| 71 |
+
upper_bound = len(_table) - 1
|
| 72 |
+
index = (lower_bound + upper_bound) // 2
|
| 73 |
+
while True:
|
| 74 |
+
start, end, width = _table[index]
|
| 75 |
+
if codepoint < start:
|
| 76 |
+
upper_bound = index - 1
|
| 77 |
+
elif codepoint > end:
|
| 78 |
+
lower_bound = index + 1
|
| 79 |
+
else:
|
| 80 |
+
return 0 if width == -1 else width
|
| 81 |
+
if upper_bound < lower_bound:
|
| 82 |
+
break
|
| 83 |
+
index = (lower_bound + upper_bound) // 2
|
| 84 |
+
return 1
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def set_cell_size(text: str, total: int) -> str:
|
| 88 |
+
"""Set the length of a string to fit within given number of cells."""
|
| 89 |
+
|
| 90 |
+
if _is_single_cell_widths(text):
|
| 91 |
+
size = len(text)
|
| 92 |
+
if size < total:
|
| 93 |
+
return text + " " * (total - size)
|
| 94 |
+
return text[:total]
|
| 95 |
+
|
| 96 |
+
if total <= 0:
|
| 97 |
+
return ""
|
| 98 |
+
cell_size = cell_len(text)
|
| 99 |
+
if cell_size == total:
|
| 100 |
+
return text
|
| 101 |
+
if cell_size < total:
|
| 102 |
+
return text + " " * (total - cell_size)
|
| 103 |
+
|
| 104 |
+
start = 0
|
| 105 |
+
end = len(text)
|
| 106 |
+
|
| 107 |
+
# Binary search until we find the right size
|
| 108 |
+
while True:
|
| 109 |
+
pos = (start + end) // 2
|
| 110 |
+
before = text[: pos + 1]
|
| 111 |
+
before_len = cell_len(before)
|
| 112 |
+
if before_len == total + 1 and cell_len(before[-1]) == 2:
|
| 113 |
+
return before[:-1] + " "
|
| 114 |
+
if before_len == total:
|
| 115 |
+
return before
|
| 116 |
+
if before_len > total:
|
| 117 |
+
end = pos
|
| 118 |
+
else:
|
| 119 |
+
start = pos
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
# TODO: This is inefficient
|
| 123 |
+
# TODO: This might not work with CWJ type characters
|
| 124 |
+
def chop_cells(text: str, max_size: int, position: int = 0) -> List[str]:
|
| 125 |
+
"""Break text in to equal (cell) length strings, returning the characters in reverse
|
| 126 |
+
order"""
|
| 127 |
+
_get_character_cell_size = get_character_cell_size
|
| 128 |
+
characters = [
|
| 129 |
+
(character, _get_character_cell_size(character)) for character in text
|
| 130 |
+
]
|
| 131 |
+
total_size = position
|
| 132 |
+
lines: List[List[str]] = [[]]
|
| 133 |
+
append = lines[-1].append
|
| 134 |
+
|
| 135 |
+
for character, size in reversed(characters):
|
| 136 |
+
if total_size + size > max_size:
|
| 137 |
+
lines.append([character])
|
| 138 |
+
append = lines[-1].append
|
| 139 |
+
total_size = size
|
| 140 |
+
else:
|
| 141 |
+
total_size += size
|
| 142 |
+
append(character)
|
| 143 |
+
|
| 144 |
+
return ["".join(line) for line in lines]
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
if __name__ == "__main__": # pragma: no cover
|
| 148 |
+
|
| 149 |
+
print(get_character_cell_size("😽"))
|
| 150 |
+
for line in chop_cells("""这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑。""", 8):
|
| 151 |
+
print(line)
|
| 152 |
+
for n in range(80, 1, -1):
|
| 153 |
+
print(set_cell_size("""这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑。""", n) + "|")
|
| 154 |
+
print("x" * n)
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/columns.py
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from collections import defaultdict
|
| 2 |
+
from itertools import chain
|
| 3 |
+
from operator import itemgetter
|
| 4 |
+
from typing import Dict, Iterable, List, Optional, Tuple
|
| 5 |
+
|
| 6 |
+
from .align import Align, AlignMethod
|
| 7 |
+
from .console import Console, ConsoleOptions, RenderableType, RenderResult
|
| 8 |
+
from .constrain import Constrain
|
| 9 |
+
from .measure import Measurement
|
| 10 |
+
from .padding import Padding, PaddingDimensions
|
| 11 |
+
from .table import Table
|
| 12 |
+
from .text import TextType
|
| 13 |
+
from .jupyter import JupyterMixin
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class Columns(JupyterMixin):
|
| 17 |
+
"""Display renderables in neat columns.
|
| 18 |
+
|
| 19 |
+
Args:
|
| 20 |
+
renderables (Iterable[RenderableType]): Any number of Rich renderables (including str).
|
| 21 |
+
width (int, optional): The desired width of the columns, or None to auto detect. Defaults to None.
|
| 22 |
+
padding (PaddingDimensions, optional): Optional padding around cells. Defaults to (0, 1).
|
| 23 |
+
expand (bool, optional): Expand columns to full width. Defaults to False.
|
| 24 |
+
equal (bool, optional): Arrange in to equal sized columns. Defaults to False.
|
| 25 |
+
column_first (bool, optional): Align items from top to bottom (rather than left to right). Defaults to False.
|
| 26 |
+
right_to_left (bool, optional): Start column from right hand side. Defaults to False.
|
| 27 |
+
align (str, optional): Align value ("left", "right", or "center") or None for default. Defaults to None.
|
| 28 |
+
title (TextType, optional): Optional title for Columns.
|
| 29 |
+
"""
|
| 30 |
+
|
| 31 |
+
def __init__(
|
| 32 |
+
self,
|
| 33 |
+
renderables: Optional[Iterable[RenderableType]] = None,
|
| 34 |
+
padding: PaddingDimensions = (0, 1),
|
| 35 |
+
*,
|
| 36 |
+
width: Optional[int] = None,
|
| 37 |
+
expand: bool = False,
|
| 38 |
+
equal: bool = False,
|
| 39 |
+
column_first: bool = False,
|
| 40 |
+
right_to_left: bool = False,
|
| 41 |
+
align: Optional[AlignMethod] = None,
|
| 42 |
+
title: Optional[TextType] = None,
|
| 43 |
+
) -> None:
|
| 44 |
+
self.renderables = list(renderables or [])
|
| 45 |
+
self.width = width
|
| 46 |
+
self.padding = padding
|
| 47 |
+
self.expand = expand
|
| 48 |
+
self.equal = equal
|
| 49 |
+
self.column_first = column_first
|
| 50 |
+
self.right_to_left = right_to_left
|
| 51 |
+
self.align: Optional[AlignMethod] = align
|
| 52 |
+
self.title = title
|
| 53 |
+
|
| 54 |
+
def add_renderable(self, renderable: RenderableType) -> None:
|
| 55 |
+
"""Add a renderable to the columns.
|
| 56 |
+
|
| 57 |
+
Args:
|
| 58 |
+
renderable (RenderableType): Any renderable object.
|
| 59 |
+
"""
|
| 60 |
+
self.renderables.append(renderable)
|
| 61 |
+
|
| 62 |
+
def __rich_console__(
|
| 63 |
+
self, console: Console, options: ConsoleOptions
|
| 64 |
+
) -> RenderResult:
|
| 65 |
+
render_str = console.render_str
|
| 66 |
+
renderables = [
|
| 67 |
+
render_str(renderable) if isinstance(renderable, str) else renderable
|
| 68 |
+
for renderable in self.renderables
|
| 69 |
+
]
|
| 70 |
+
if not renderables:
|
| 71 |
+
return
|
| 72 |
+
_top, right, _bottom, left = Padding.unpack(self.padding)
|
| 73 |
+
width_padding = max(left, right)
|
| 74 |
+
max_width = options.max_width
|
| 75 |
+
widths: Dict[int, int] = defaultdict(int)
|
| 76 |
+
column_count = len(renderables)
|
| 77 |
+
|
| 78 |
+
get_measurement = Measurement.get
|
| 79 |
+
renderable_widths = [
|
| 80 |
+
get_measurement(console, options, renderable).maximum
|
| 81 |
+
for renderable in renderables
|
| 82 |
+
]
|
| 83 |
+
if self.equal:
|
| 84 |
+
renderable_widths = [max(renderable_widths)] * len(renderable_widths)
|
| 85 |
+
|
| 86 |
+
def iter_renderables(
|
| 87 |
+
column_count: int,
|
| 88 |
+
) -> Iterable[Tuple[int, Optional[RenderableType]]]:
|
| 89 |
+
item_count = len(renderables)
|
| 90 |
+
if self.column_first:
|
| 91 |
+
width_renderables = list(zip(renderable_widths, renderables))
|
| 92 |
+
|
| 93 |
+
column_lengths: List[int] = [item_count // column_count] * column_count
|
| 94 |
+
for col_no in range(item_count % column_count):
|
| 95 |
+
column_lengths[col_no] += 1
|
| 96 |
+
|
| 97 |
+
row_count = (item_count + column_count - 1) // column_count
|
| 98 |
+
cells = [[-1] * column_count for _ in range(row_count)]
|
| 99 |
+
row = col = 0
|
| 100 |
+
for index in range(item_count):
|
| 101 |
+
cells[row][col] = index
|
| 102 |
+
column_lengths[col] -= 1
|
| 103 |
+
if column_lengths[col]:
|
| 104 |
+
row += 1
|
| 105 |
+
else:
|
| 106 |
+
col += 1
|
| 107 |
+
row = 0
|
| 108 |
+
for index in chain.from_iterable(cells):
|
| 109 |
+
if index == -1:
|
| 110 |
+
break
|
| 111 |
+
yield width_renderables[index]
|
| 112 |
+
else:
|
| 113 |
+
yield from zip(renderable_widths, renderables)
|
| 114 |
+
# Pad odd elements with spaces
|
| 115 |
+
if item_count % column_count:
|
| 116 |
+
for _ in range(column_count - (item_count % column_count)):
|
| 117 |
+
yield 0, None
|
| 118 |
+
|
| 119 |
+
table = Table.grid(padding=self.padding, collapse_padding=True, pad_edge=False)
|
| 120 |
+
table.expand = self.expand
|
| 121 |
+
table.title = self.title
|
| 122 |
+
|
| 123 |
+
if self.width is not None:
|
| 124 |
+
column_count = (max_width) // (self.width + width_padding)
|
| 125 |
+
for _ in range(column_count):
|
| 126 |
+
table.add_column(width=self.width)
|
| 127 |
+
else:
|
| 128 |
+
while column_count > 1:
|
| 129 |
+
widths.clear()
|
| 130 |
+
column_no = 0
|
| 131 |
+
for renderable_width, _ in iter_renderables(column_count):
|
| 132 |
+
widths[column_no] = max(widths[column_no], renderable_width)
|
| 133 |
+
total_width = sum(widths.values()) + width_padding * (
|
| 134 |
+
len(widths) - 1
|
| 135 |
+
)
|
| 136 |
+
if total_width > max_width:
|
| 137 |
+
column_count = len(widths) - 1
|
| 138 |
+
break
|
| 139 |
+
else:
|
| 140 |
+
column_no = (column_no + 1) % column_count
|
| 141 |
+
else:
|
| 142 |
+
break
|
| 143 |
+
|
| 144 |
+
get_renderable = itemgetter(1)
|
| 145 |
+
_renderables = [
|
| 146 |
+
get_renderable(_renderable)
|
| 147 |
+
for _renderable in iter_renderables(column_count)
|
| 148 |
+
]
|
| 149 |
+
if self.equal:
|
| 150 |
+
_renderables = [
|
| 151 |
+
None
|
| 152 |
+
if renderable is None
|
| 153 |
+
else Constrain(renderable, renderable_widths[0])
|
| 154 |
+
for renderable in _renderables
|
| 155 |
+
]
|
| 156 |
+
if self.align:
|
| 157 |
+
align = self.align
|
| 158 |
+
_Align = Align
|
| 159 |
+
_renderables = [
|
| 160 |
+
None if renderable is None else _Align(renderable, align)
|
| 161 |
+
for renderable in _renderables
|
| 162 |
+
]
|
| 163 |
+
|
| 164 |
+
right_to_left = self.right_to_left
|
| 165 |
+
add_row = table.add_row
|
| 166 |
+
for start in range(0, len(_renderables), column_count):
|
| 167 |
+
row = _renderables[start : start + column_count]
|
| 168 |
+
if right_to_left:
|
| 169 |
+
row = row[::-1]
|
| 170 |
+
add_row(*row)
|
| 171 |
+
yield table
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
if __name__ == "__main__": # pragma: no cover
|
| 175 |
+
import os
|
| 176 |
+
|
| 177 |
+
console = Console()
|
| 178 |
+
|
| 179 |
+
files = [f"{i} {s}" for i, s in enumerate(sorted(os.listdir()))]
|
| 180 |
+
columns = Columns(files, padding=(0, 1), expand=False, equal=False)
|
| 181 |
+
console.print(columns)
|
| 182 |
+
console.rule()
|
| 183 |
+
columns.column_first = True
|
| 184 |
+
console.print(columns)
|
| 185 |
+
columns.right_to_left = True
|
| 186 |
+
console.rule()
|
| 187 |
+
console.print(columns)
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/containers.py
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from itertools import zip_longest
|
| 2 |
+
from typing import (
|
| 3 |
+
Iterator,
|
| 4 |
+
Iterable,
|
| 5 |
+
List,
|
| 6 |
+
Optional,
|
| 7 |
+
Union,
|
| 8 |
+
overload,
|
| 9 |
+
TypeVar,
|
| 10 |
+
TYPE_CHECKING,
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
if TYPE_CHECKING:
|
| 14 |
+
from .console import (
|
| 15 |
+
Console,
|
| 16 |
+
ConsoleOptions,
|
| 17 |
+
JustifyMethod,
|
| 18 |
+
OverflowMethod,
|
| 19 |
+
RenderResult,
|
| 20 |
+
RenderableType,
|
| 21 |
+
)
|
| 22 |
+
from .text import Text
|
| 23 |
+
|
| 24 |
+
from .cells import cell_len
|
| 25 |
+
from .measure import Measurement
|
| 26 |
+
|
| 27 |
+
T = TypeVar("T")
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class Renderables:
|
| 31 |
+
"""A list subclass which renders its contents to the console."""
|
| 32 |
+
|
| 33 |
+
def __init__(
|
| 34 |
+
self, renderables: Optional[Iterable["RenderableType"]] = None
|
| 35 |
+
) -> None:
|
| 36 |
+
self._renderables: List["RenderableType"] = (
|
| 37 |
+
list(renderables) if renderables is not None else []
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
def __rich_console__(
|
| 41 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 42 |
+
) -> "RenderResult":
|
| 43 |
+
"""Console render method to insert line-breaks."""
|
| 44 |
+
yield from self._renderables
|
| 45 |
+
|
| 46 |
+
def __rich_measure__(
|
| 47 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 48 |
+
) -> "Measurement":
|
| 49 |
+
dimensions = [
|
| 50 |
+
Measurement.get(console, options, renderable)
|
| 51 |
+
for renderable in self._renderables
|
| 52 |
+
]
|
| 53 |
+
if not dimensions:
|
| 54 |
+
return Measurement(1, 1)
|
| 55 |
+
_min = max(dimension.minimum for dimension in dimensions)
|
| 56 |
+
_max = max(dimension.maximum for dimension in dimensions)
|
| 57 |
+
return Measurement(_min, _max)
|
| 58 |
+
|
| 59 |
+
def append(self, renderable: "RenderableType") -> None:
|
| 60 |
+
self._renderables.append(renderable)
|
| 61 |
+
|
| 62 |
+
def __iter__(self) -> Iterable["RenderableType"]:
|
| 63 |
+
return iter(self._renderables)
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
class Lines:
|
| 67 |
+
"""A list subclass which can render to the console."""
|
| 68 |
+
|
| 69 |
+
def __init__(self, lines: Iterable["Text"] = ()) -> None:
|
| 70 |
+
self._lines: List["Text"] = list(lines)
|
| 71 |
+
|
| 72 |
+
def __repr__(self) -> str:
|
| 73 |
+
return f"Lines({self._lines!r})"
|
| 74 |
+
|
| 75 |
+
def __iter__(self) -> Iterator["Text"]:
|
| 76 |
+
return iter(self._lines)
|
| 77 |
+
|
| 78 |
+
@overload
|
| 79 |
+
def __getitem__(self, index: int) -> "Text":
|
| 80 |
+
...
|
| 81 |
+
|
| 82 |
+
@overload
|
| 83 |
+
def __getitem__(self, index: slice) -> List["Text"]:
|
| 84 |
+
...
|
| 85 |
+
|
| 86 |
+
def __getitem__(self, index: Union[slice, int]) -> Union["Text", List["Text"]]:
|
| 87 |
+
return self._lines[index]
|
| 88 |
+
|
| 89 |
+
def __setitem__(self, index: int, value: "Text") -> "Lines":
|
| 90 |
+
self._lines[index] = value
|
| 91 |
+
return self
|
| 92 |
+
|
| 93 |
+
def __len__(self) -> int:
|
| 94 |
+
return self._lines.__len__()
|
| 95 |
+
|
| 96 |
+
def __rich_console__(
|
| 97 |
+
self, console: "Console", options: "ConsoleOptions"
|
| 98 |
+
) -> "RenderResult":
|
| 99 |
+
"""Console render method to insert line-breaks."""
|
| 100 |
+
yield from self._lines
|
| 101 |
+
|
| 102 |
+
def append(self, line: "Text") -> None:
|
| 103 |
+
self._lines.append(line)
|
| 104 |
+
|
| 105 |
+
def extend(self, lines: Iterable["Text"]) -> None:
|
| 106 |
+
self._lines.extend(lines)
|
| 107 |
+
|
| 108 |
+
def pop(self, index: int = -1) -> "Text":
|
| 109 |
+
return self._lines.pop(index)
|
| 110 |
+
|
| 111 |
+
def justify(
|
| 112 |
+
self,
|
| 113 |
+
console: "Console",
|
| 114 |
+
width: int,
|
| 115 |
+
justify: "JustifyMethod" = "left",
|
| 116 |
+
overflow: "OverflowMethod" = "fold",
|
| 117 |
+
) -> None:
|
| 118 |
+
"""Justify and overflow text to a given width.
|
| 119 |
+
|
| 120 |
+
Args:
|
| 121 |
+
console (Console): Console instance.
|
| 122 |
+
width (int): Number of characters per line.
|
| 123 |
+
justify (str, optional): Default justify method for text: "left", "center", "full" or "right". Defaults to "left".
|
| 124 |
+
overflow (str, optional): Default overflow for text: "crop", "fold", or "ellipsis". Defaults to "fold".
|
| 125 |
+
|
| 126 |
+
"""
|
| 127 |
+
from .text import Text
|
| 128 |
+
|
| 129 |
+
if justify == "left":
|
| 130 |
+
for line in self._lines:
|
| 131 |
+
line.truncate(width, overflow=overflow, pad=True)
|
| 132 |
+
elif justify == "center":
|
| 133 |
+
for line in self._lines:
|
| 134 |
+
line.rstrip()
|
| 135 |
+
line.truncate(width, overflow=overflow)
|
| 136 |
+
line.pad_left((width - cell_len(line.plain)) // 2)
|
| 137 |
+
line.pad_right(width - cell_len(line.plain))
|
| 138 |
+
elif justify == "right":
|
| 139 |
+
for line in self._lines:
|
| 140 |
+
line.rstrip()
|
| 141 |
+
line.truncate(width, overflow=overflow)
|
| 142 |
+
line.pad_left(width - cell_len(line.plain))
|
| 143 |
+
elif justify == "full":
|
| 144 |
+
for line_index, line in enumerate(self._lines):
|
| 145 |
+
if line_index == len(self._lines) - 1:
|
| 146 |
+
break
|
| 147 |
+
words = line.split(" ")
|
| 148 |
+
words_size = sum(cell_len(word.plain) for word in words)
|
| 149 |
+
num_spaces = len(words) - 1
|
| 150 |
+
spaces = [1 for _ in range(num_spaces)]
|
| 151 |
+
index = 0
|
| 152 |
+
if spaces:
|
| 153 |
+
while words_size + num_spaces < width:
|
| 154 |
+
spaces[len(spaces) - index - 1] += 1
|
| 155 |
+
num_spaces += 1
|
| 156 |
+
index = (index + 1) % len(spaces)
|
| 157 |
+
tokens: List[Text] = []
|
| 158 |
+
for index, (word, next_word) in enumerate(
|
| 159 |
+
zip_longest(words, words[1:])
|
| 160 |
+
):
|
| 161 |
+
tokens.append(word)
|
| 162 |
+
if index < len(spaces):
|
| 163 |
+
style = word.get_style_at_offset(console, -1)
|
| 164 |
+
next_style = next_word.get_style_at_offset(console, 0)
|
| 165 |
+
space_style = style if style == next_style else line.style
|
| 166 |
+
tokens.append(Text(" " * spaces[index], style=space_style))
|
| 167 |
+
self[line_index] = Text("").join(tokens)
|
.venv/lib/python3.11/site-packages/pip/_vendor/rich/default_styles.py
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Dict
|
| 2 |
+
|
| 3 |
+
from .style import Style
|
| 4 |
+
|
| 5 |
+
DEFAULT_STYLES: Dict[str, Style] = {
|
| 6 |
+
"none": Style.null(),
|
| 7 |
+
"reset": Style(
|
| 8 |
+
color="default",
|
| 9 |
+
bgcolor="default",
|
| 10 |
+
dim=False,
|
| 11 |
+
bold=False,
|
| 12 |
+
italic=False,
|
| 13 |
+
underline=False,
|
| 14 |
+
blink=False,
|
| 15 |
+
blink2=False,
|
| 16 |
+
reverse=False,
|
| 17 |
+
conceal=False,
|
| 18 |
+
strike=False,
|
| 19 |
+
),
|
| 20 |
+
"dim": Style(dim=True),
|
| 21 |
+
"bright": Style(dim=False),
|
| 22 |
+
"bold": Style(bold=True),
|
| 23 |
+
"strong": Style(bold=True),
|
| 24 |
+
"code": Style(reverse=True, bold=True),
|
| 25 |
+
"italic": Style(italic=True),
|
| 26 |
+
"emphasize": Style(italic=True),
|
| 27 |
+
"underline": Style(underline=True),
|
| 28 |
+
"blink": Style(blink=True),
|
| 29 |
+
"blink2": Style(blink2=True),
|
| 30 |
+
"reverse": Style(reverse=True),
|
| 31 |
+
"strike": Style(strike=True),
|
| 32 |
+
"black": Style(color="black"),
|
| 33 |
+
"red": Style(color="red"),
|
| 34 |
+
"green": Style(color="green"),
|
| 35 |
+
"yellow": Style(color="yellow"),
|
| 36 |
+
"magenta": Style(color="magenta"),
|
| 37 |
+
"cyan": Style(color="cyan"),
|
| 38 |
+
"white": Style(color="white"),
|
| 39 |
+
"inspect.attr": Style(color="yellow", italic=True),
|
| 40 |
+
"inspect.attr.dunder": Style(color="yellow", italic=True, dim=True),
|
| 41 |
+
"inspect.callable": Style(bold=True, color="red"),
|
| 42 |
+
"inspect.async_def": Style(italic=True, color="bright_cyan"),
|
| 43 |
+
"inspect.def": Style(italic=True, color="bright_cyan"),
|
| 44 |
+
"inspect.class": Style(italic=True, color="bright_cyan"),
|
| 45 |
+
"inspect.error": Style(bold=True, color="red"),
|
| 46 |
+
"inspect.equals": Style(),
|
| 47 |
+
"inspect.help": Style(color="cyan"),
|
| 48 |
+
"inspect.doc": Style(dim=True),
|
| 49 |
+
"inspect.value.border": Style(color="green"),
|
| 50 |
+
"live.ellipsis": Style(bold=True, color="red"),
|
| 51 |
+
"layout.tree.row": Style(dim=False, color="red"),
|
| 52 |
+
"layout.tree.column": Style(dim=False, color="blue"),
|
| 53 |
+
"logging.keyword": Style(bold=True, color="yellow"),
|
| 54 |
+
"logging.level.notset": Style(dim=True),
|
| 55 |
+
"logging.level.debug": Style(color="green"),
|
| 56 |
+
"logging.level.info": Style(color="blue"),
|
| 57 |
+
"logging.level.warning": Style(color="red"),
|
| 58 |
+
"logging.level.error": Style(color="red", bold=True),
|
| 59 |
+
"logging.level.critical": Style(color="red", bold=True, reverse=True),
|
| 60 |
+
"log.level": Style.null(),
|
| 61 |
+
"log.time": Style(color="cyan", dim=True),
|
| 62 |
+
"log.message": Style.null(),
|
| 63 |
+
"log.path": Style(dim=True),
|
| 64 |
+
"repr.ellipsis": Style(color="yellow"),
|
| 65 |
+
"repr.indent": Style(color="green", dim=True),
|
| 66 |
+
"repr.error": Style(color="red", bold=True),
|
| 67 |
+
"repr.str": Style(color="green", italic=False, bold=False),
|
| 68 |
+
"repr.brace": Style(bold=True),
|
| 69 |
+
"repr.comma": Style(bold=True),
|
| 70 |
+
"repr.ipv4": Style(bold=True, color="bright_green"),
|
| 71 |
+
"repr.ipv6": Style(bold=True, color="bright_green"),
|
| 72 |
+
"repr.eui48": Style(bold=True, color="bright_green"),
|
| 73 |
+
"repr.eui64": Style(bold=True, color="bright_green"),
|
| 74 |
+
"repr.tag_start": Style(bold=True),
|
| 75 |
+
"repr.tag_name": Style(color="bright_magenta", bold=True),
|
| 76 |
+
"repr.tag_contents": Style(color="default"),
|
| 77 |
+
"repr.tag_end": Style(bold=True),
|
| 78 |
+
"repr.attrib_name": Style(color="yellow", italic=False),
|
| 79 |
+
"repr.attrib_equal": Style(bold=True),
|
| 80 |
+
"repr.attrib_value": Style(color="magenta", italic=False),
|
| 81 |
+
"repr.number": Style(color="cyan", bold=True, italic=False),
|
| 82 |
+
"repr.number_complex": Style(color="cyan", bold=True, italic=False), # same
|
| 83 |
+
"repr.bool_true": Style(color="bright_green", italic=True),
|
| 84 |
+
"repr.bool_false": Style(color="bright_red", italic=True),
|
| 85 |
+
"repr.none": Style(color="magenta", italic=True),
|
| 86 |
+
"repr.url": Style(underline=True, color="bright_blue", italic=False, bold=False),
|
| 87 |
+
"repr.uuid": Style(color="bright_yellow", bold=False),
|
| 88 |
+
"repr.call": Style(color="magenta", bold=True),
|
| 89 |
+
"repr.path": Style(color="magenta"),
|
| 90 |
+
"repr.filename": Style(color="bright_magenta"),
|
| 91 |
+
"rule.line": Style(color="bright_green"),
|
| 92 |
+
"rule.text": Style.null(),
|
| 93 |
+
"json.brace": Style(bold=True),
|
| 94 |
+
"json.bool_true": Style(color="bright_green", italic=True),
|
| 95 |
+
"json.bool_false": Style(color="bright_red", italic=True),
|
| 96 |
+
"json.null": Style(color="magenta", italic=True),
|
| 97 |
+
"json.number": Style(color="cyan", bold=True, italic=False),
|
| 98 |
+
"json.str": Style(color="green", italic=False, bold=False),
|
| 99 |
+
"json.key": Style(color="blue", bold=True),
|
| 100 |
+
"prompt": Style.null(),
|
| 101 |
+
"prompt.choices": Style(color="magenta", bold=True),
|
| 102 |
+
"prompt.default": Style(color="cyan", bold=True),
|
| 103 |
+
"prompt.invalid": Style(color="red"),
|
| 104 |
+
"prompt.invalid.choice": Style(color="red"),
|
| 105 |
+
"pretty": Style.null(),
|
| 106 |
+
"scope.border": Style(color="blue"),
|
| 107 |
+
"scope.key": Style(color="yellow", italic=True),
|
| 108 |
+
"scope.key.special": Style(color="yellow", italic=True, dim=True),
|
| 109 |
+
"scope.equals": Style(color="red"),
|
| 110 |
+
"table.header": Style(bold=True),
|
| 111 |
+
"table.footer": Style(bold=True),
|
| 112 |
+
"table.cell": Style.null(),
|
| 113 |
+
"table.title": Style(italic=True),
|
| 114 |
+
"table.caption": Style(italic=True, dim=True),
|
| 115 |
+
"traceback.error": Style(color="red", italic=True),
|
| 116 |
+
"traceback.border.syntax_error": Style(color="bright_red"),
|
| 117 |
+
"traceback.border": Style(color="red"),
|
| 118 |
+
"traceback.text": Style.null(),
|
| 119 |
+
"traceback.title": Style(color="red", bold=True),
|
| 120 |
+
"traceback.exc_type": Style(color="bright_red", bold=True),
|
| 121 |
+
"traceback.exc_value": Style.null(),
|
| 122 |
+
"traceback.offset": Style(color="bright_red", bold=True),
|
| 123 |
+
"bar.back": Style(color="grey23"),
|
| 124 |
+
"bar.complete": Style(color="rgb(249,38,114)"),
|
| 125 |
+
"bar.finished": Style(color="rgb(114,156,31)"),
|
| 126 |
+
"bar.pulse": Style(color="rgb(249,38,114)"),
|
| 127 |
+
"progress.description": Style.null(),
|
| 128 |
+
"progress.filesize": Style(color="green"),
|
| 129 |
+
"progress.filesize.total": Style(color="green"),
|
| 130 |
+
"progress.download": Style(color="green"),
|
| 131 |
+
"progress.elapsed": Style(color="yellow"),
|
| 132 |
+
"progress.percentage": Style(color="magenta"),
|
| 133 |
+
"progress.remaining": Style(color="cyan"),
|
| 134 |
+
"progress.data.speed": Style(color="red"),
|
| 135 |
+
"progress.spinner": Style(color="green"),
|
| 136 |
+
"status.spinner": Style(color="green"),
|
| 137 |
+
"tree": Style(),
|
| 138 |
+
"tree.line": Style(),
|
| 139 |
+
"markdown.paragraph": Style(),
|
| 140 |
+
"markdown.text": Style(),
|
| 141 |
+
"markdown.em": Style(italic=True),
|
| 142 |
+
"markdown.emph": Style(italic=True), # For commonmark backwards compatibility
|
| 143 |
+
"markdown.strong": Style(bold=True),
|
| 144 |
+
"markdown.code": Style(bold=True, color="cyan", bgcolor="black"),
|
| 145 |
+
"markdown.code_block": Style(color="cyan", bgcolor="black"),
|
| 146 |
+
"markdown.block_quote": Style(color="magenta"),
|
| 147 |
+
"markdown.list": Style(color="cyan"),
|
| 148 |
+
"markdown.item": Style(),
|
| 149 |
+
"markdown.item.bullet": Style(color="yellow", bold=True),
|
| 150 |
+
"markdown.item.number": Style(color="yellow", bold=True),
|
| 151 |
+
"markdown.hr": Style(color="yellow"),
|
| 152 |
+
"markdown.h1.border": Style(),
|
| 153 |
+
"markdown.h1": Style(bold=True),
|
| 154 |
+
"markdown.h2": Style(bold=True, underline=True),
|
| 155 |
+
"markdown.h3": Style(bold=True),
|
| 156 |
+
"markdown.h4": Style(bold=True, dim=True),
|
| 157 |
+
"markdown.h5": Style(underline=True),
|
| 158 |
+
"markdown.h6": Style(italic=True),
|
| 159 |
+
"markdown.h7": Style(italic=True, dim=True),
|
| 160 |
+
"markdown.link": Style(color="bright_blue"),
|
| 161 |
+
"markdown.link_url": Style(color="blue", underline=True),
|
| 162 |
+
"markdown.s": Style(strike=True),
|
| 163 |
+
"iso8601.date": Style(color="blue"),
|
| 164 |
+
"iso8601.time": Style(color="magenta"),
|
| 165 |
+
"iso8601.timezone": Style(color="yellow"),
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
if __name__ == "__main__": # pragma: no cover
|
| 170 |
+
import argparse
|
| 171 |
+
import io
|
| 172 |
+
|
| 173 |
+
from pip._vendor.rich.console import Console
|
| 174 |
+
from pip._vendor.rich.table import Table
|
| 175 |
+
from pip._vendor.rich.text import Text
|
| 176 |
+
|
| 177 |
+
parser = argparse.ArgumentParser()
|
| 178 |
+
parser.add_argument("--html", action="store_true", help="Export as HTML table")
|
| 179 |
+
args = parser.parse_args()
|
| 180 |
+
html: bool = args.html
|
| 181 |
+
console = Console(record=True, width=70, file=io.StringIO()) if html else Console()
|
| 182 |
+
|
| 183 |
+
table = Table("Name", "Styling")
|
| 184 |
+
|
| 185 |
+
for style_name, style in DEFAULT_STYLES.items():
|
| 186 |
+
table.add_row(Text(style_name, style=style), str(style))
|
| 187 |
+
|
| 188 |
+
console.print(table)
|
| 189 |
+
if html:
|
| 190 |
+
print(console.export_html(inline_styles=True))
|