pip 25.1.1__py3-none-any.whl → 25.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. pip/__init__.py +3 -3
  2. pip/_internal/__init__.py +2 -2
  3. pip/_internal/build_env.py +186 -94
  4. pip/_internal/cache.py +17 -15
  5. pip/_internal/cli/autocompletion.py +13 -4
  6. pip/_internal/cli/base_command.py +18 -7
  7. pip/_internal/cli/cmdoptions.py +57 -80
  8. pip/_internal/cli/command_context.py +4 -3
  9. pip/_internal/cli/index_command.py +11 -9
  10. pip/_internal/cli/main.py +3 -2
  11. pip/_internal/cli/main_parser.py +4 -3
  12. pip/_internal/cli/parser.py +24 -20
  13. pip/_internal/cli/progress_bars.py +19 -12
  14. pip/_internal/cli/req_command.py +57 -33
  15. pip/_internal/cli/spinners.py +81 -5
  16. pip/_internal/commands/__init__.py +5 -3
  17. pip/_internal/commands/cache.py +18 -15
  18. pip/_internal/commands/check.py +1 -2
  19. pip/_internal/commands/completion.py +1 -2
  20. pip/_internal/commands/configuration.py +26 -18
  21. pip/_internal/commands/debug.py +8 -6
  22. pip/_internal/commands/download.py +6 -10
  23. pip/_internal/commands/freeze.py +2 -3
  24. pip/_internal/commands/hash.py +1 -2
  25. pip/_internal/commands/help.py +1 -2
  26. pip/_internal/commands/index.py +15 -9
  27. pip/_internal/commands/inspect.py +4 -4
  28. pip/_internal/commands/install.py +63 -53
  29. pip/_internal/commands/list.py +35 -26
  30. pip/_internal/commands/lock.py +4 -8
  31. pip/_internal/commands/search.py +14 -12
  32. pip/_internal/commands/show.py +14 -11
  33. pip/_internal/commands/uninstall.py +1 -2
  34. pip/_internal/commands/wheel.py +7 -13
  35. pip/_internal/configuration.py +40 -27
  36. pip/_internal/distributions/base.py +6 -4
  37. pip/_internal/distributions/installed.py +8 -4
  38. pip/_internal/distributions/sdist.py +33 -27
  39. pip/_internal/distributions/wheel.py +6 -4
  40. pip/_internal/exceptions.py +78 -42
  41. pip/_internal/index/collector.py +24 -29
  42. pip/_internal/index/package_finder.py +73 -64
  43. pip/_internal/index/sources.py +17 -14
  44. pip/_internal/locations/__init__.py +18 -16
  45. pip/_internal/locations/_distutils.py +12 -11
  46. pip/_internal/locations/_sysconfig.py +5 -4
  47. pip/_internal/locations/base.py +4 -3
  48. pip/_internal/main.py +2 -2
  49. pip/_internal/metadata/__init__.py +14 -7
  50. pip/_internal/metadata/_json.py +5 -4
  51. pip/_internal/metadata/base.py +22 -27
  52. pip/_internal/metadata/importlib/_compat.py +6 -4
  53. pip/_internal/metadata/importlib/_dists.py +20 -19
  54. pip/_internal/metadata/importlib/_envs.py +9 -6
  55. pip/_internal/metadata/pkg_resources.py +11 -14
  56. pip/_internal/models/direct_url.py +24 -21
  57. pip/_internal/models/format_control.py +5 -5
  58. pip/_internal/models/installation_report.py +4 -3
  59. pip/_internal/models/link.py +39 -34
  60. pip/_internal/models/pylock.py +27 -22
  61. pip/_internal/models/search_scope.py +6 -7
  62. pip/_internal/models/selection_prefs.py +3 -3
  63. pip/_internal/models/target_python.py +10 -9
  64. pip/_internal/models/wheel.py +12 -71
  65. pip/_internal/network/auth.py +20 -22
  66. pip/_internal/network/cache.py +28 -17
  67. pip/_internal/network/download.py +169 -141
  68. pip/_internal/network/lazy_wheel.py +15 -10
  69. pip/_internal/network/session.py +32 -27
  70. pip/_internal/network/utils.py +2 -2
  71. pip/_internal/network/xmlrpc.py +2 -2
  72. pip/_internal/operations/build/build_tracker.py +10 -8
  73. pip/_internal/operations/build/wheel.py +7 -6
  74. pip/_internal/operations/build/wheel_editable.py +7 -6
  75. pip/_internal/operations/check.py +21 -26
  76. pip/_internal/operations/freeze.py +12 -9
  77. pip/_internal/operations/install/wheel.py +49 -41
  78. pip/_internal/operations/prepare.py +42 -31
  79. pip/_internal/pyproject.py +7 -69
  80. pip/_internal/req/__init__.py +12 -12
  81. pip/_internal/req/constructors.py +68 -62
  82. pip/_internal/req/req_dependency_group.py +7 -11
  83. pip/_internal/req/req_file.py +32 -36
  84. pip/_internal/req/req_install.py +64 -170
  85. pip/_internal/req/req_set.py +4 -5
  86. pip/_internal/req/req_uninstall.py +20 -17
  87. pip/_internal/resolution/base.py +3 -3
  88. pip/_internal/resolution/legacy/resolver.py +21 -20
  89. pip/_internal/resolution/resolvelib/base.py +16 -13
  90. pip/_internal/resolution/resolvelib/candidates.py +49 -37
  91. pip/_internal/resolution/resolvelib/factory.py +72 -50
  92. pip/_internal/resolution/resolvelib/found_candidates.py +11 -9
  93. pip/_internal/resolution/resolvelib/provider.py +24 -20
  94. pip/_internal/resolution/resolvelib/reporter.py +26 -11
  95. pip/_internal/resolution/resolvelib/requirements.py +8 -6
  96. pip/_internal/resolution/resolvelib/resolver.py +41 -29
  97. pip/_internal/self_outdated_check.py +19 -9
  98. pip/_internal/utils/appdirs.py +1 -2
  99. pip/_internal/utils/compat.py +7 -1
  100. pip/_internal/utils/compatibility_tags.py +17 -16
  101. pip/_internal/utils/deprecation.py +11 -9
  102. pip/_internal/utils/direct_url_helpers.py +2 -2
  103. pip/_internal/utils/egg_link.py +6 -5
  104. pip/_internal/utils/entrypoints.py +3 -2
  105. pip/_internal/utils/filesystem.py +20 -5
  106. pip/_internal/utils/filetypes.py +4 -6
  107. pip/_internal/utils/glibc.py +6 -5
  108. pip/_internal/utils/hashes.py +9 -6
  109. pip/_internal/utils/logging.py +8 -5
  110. pip/_internal/utils/misc.py +37 -45
  111. pip/_internal/utils/packaging.py +3 -2
  112. pip/_internal/utils/retry.py +7 -4
  113. pip/_internal/utils/subprocess.py +20 -17
  114. pip/_internal/utils/temp_dir.py +10 -12
  115. pip/_internal/utils/unpacking.py +31 -4
  116. pip/_internal/utils/urls.py +1 -1
  117. pip/_internal/utils/virtualenv.py +3 -2
  118. pip/_internal/utils/wheel.py +3 -4
  119. pip/_internal/vcs/bazaar.py +26 -8
  120. pip/_internal/vcs/git.py +59 -24
  121. pip/_internal/vcs/mercurial.py +34 -11
  122. pip/_internal/vcs/subversion.py +27 -16
  123. pip/_internal/vcs/versioncontrol.py +56 -51
  124. pip/_internal/wheel_builder.py +30 -101
  125. pip/_vendor/README.rst +180 -0
  126. pip/_vendor/cachecontrol/LICENSE.txt +13 -0
  127. pip/_vendor/cachecontrol/__init__.py +1 -1
  128. pip/_vendor/certifi/LICENSE +20 -0
  129. pip/_vendor/certifi/__init__.py +1 -1
  130. pip/_vendor/certifi/cacert.pem +164 -261
  131. pip/_vendor/certifi/core.py +1 -32
  132. pip/_vendor/dependency_groups/LICENSE.txt +9 -0
  133. pip/_vendor/distlib/LICENSE.txt +284 -0
  134. pip/_vendor/distlib/__init__.py +2 -2
  135. pip/_vendor/distlib/scripts.py +1 -1
  136. pip/_vendor/distro/LICENSE +202 -0
  137. pip/_vendor/idna/LICENSE.md +31 -0
  138. pip/_vendor/msgpack/COPYING +14 -0
  139. pip/_vendor/msgpack/__init__.py +2 -2
  140. pip/_vendor/packaging/LICENSE +3 -0
  141. pip/_vendor/packaging/LICENSE.APACHE +177 -0
  142. pip/_vendor/packaging/LICENSE.BSD +23 -0
  143. pip/_vendor/pkg_resources/LICENSE +17 -0
  144. pip/_vendor/pkg_resources/__init__.py +1 -1
  145. pip/_vendor/platformdirs/LICENSE +21 -0
  146. pip/_vendor/platformdirs/api.py +1 -1
  147. pip/_vendor/platformdirs/macos.py +10 -8
  148. pip/_vendor/platformdirs/version.py +16 -3
  149. pip/_vendor/pygments/LICENSE +25 -0
  150. pip/_vendor/pygments/__init__.py +1 -1
  151. pip/_vendor/pyproject_hooks/LICENSE +21 -0
  152. pip/_vendor/requests/LICENSE +175 -0
  153. pip/_vendor/requests/__version__.py +2 -2
  154. pip/_vendor/requests/adapters.py +17 -40
  155. pip/_vendor/requests/compat.py +12 -0
  156. pip/_vendor/requests/models.py +3 -1
  157. pip/_vendor/requests/sessions.py +1 -1
  158. pip/_vendor/requests/utils.py +6 -16
  159. pip/_vendor/resolvelib/LICENSE +13 -0
  160. pip/_vendor/resolvelib/__init__.py +3 -3
  161. pip/_vendor/resolvelib/reporters.py +1 -1
  162. pip/_vendor/resolvelib/resolvers/__init__.py +4 -4
  163. pip/_vendor/resolvelib/resolvers/abstract.py +3 -3
  164. pip/_vendor/resolvelib/resolvers/resolution.py +96 -10
  165. pip/_vendor/rich/LICENSE +19 -0
  166. pip/_vendor/rich/__main__.py +12 -40
  167. pip/_vendor/rich/_inspect.py +1 -1
  168. pip/_vendor/rich/_ratio.py +1 -7
  169. pip/_vendor/rich/align.py +1 -7
  170. pip/_vendor/rich/box.py +1 -7
  171. pip/_vendor/rich/console.py +25 -20
  172. pip/_vendor/rich/control.py +1 -7
  173. pip/_vendor/rich/diagnose.py +1 -0
  174. pip/_vendor/rich/emoji.py +1 -6
  175. pip/_vendor/rich/live.py +32 -7
  176. pip/_vendor/rich/live_render.py +1 -7
  177. pip/_vendor/rich/logging.py +1 -1
  178. pip/_vendor/rich/panel.py +3 -4
  179. pip/_vendor/rich/progress.py +15 -15
  180. pip/_vendor/rich/spinner.py +7 -13
  181. pip/_vendor/rich/style.py +7 -11
  182. pip/_vendor/rich/syntax.py +24 -5
  183. pip/_vendor/rich/traceback.py +32 -17
  184. pip/_vendor/tomli/LICENSE +21 -0
  185. pip/_vendor/tomli/__init__.py +1 -1
  186. pip/_vendor/tomli/_parser.py +28 -21
  187. pip/_vendor/tomli/_re.py +8 -5
  188. pip/_vendor/tomli_w/LICENSE +21 -0
  189. pip/_vendor/truststore/LICENSE +21 -0
  190. pip/_vendor/truststore/__init__.py +1 -1
  191. pip/_vendor/truststore/_api.py +15 -7
  192. pip/_vendor/truststore/_openssl.py +3 -1
  193. pip/_vendor/urllib3/LICENSE.txt +21 -0
  194. pip/_vendor/vendor.txt +11 -12
  195. {pip-25.1.1.dist-info → pip-25.3.dist-info}/METADATA +32 -11
  196. {pip-25.1.1.dist-info → pip-25.3.dist-info}/RECORD +221 -192
  197. {pip-25.1.1.dist-info → pip-25.3.dist-info}/WHEEL +1 -2
  198. pip-25.3.dist-info/entry_points.txt +4 -0
  199. {pip-25.1.1.dist-info → pip-25.3.dist-info}/licenses/AUTHORS.txt +21 -0
  200. pip-25.3.dist-info/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +13 -0
  201. pip-25.3.dist-info/licenses/src/pip/_vendor/certifi/LICENSE +20 -0
  202. pip-25.3.dist-info/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +9 -0
  203. pip-25.3.dist-info/licenses/src/pip/_vendor/distlib/LICENSE.txt +284 -0
  204. pip-25.3.dist-info/licenses/src/pip/_vendor/distro/LICENSE +202 -0
  205. pip-25.3.dist-info/licenses/src/pip/_vendor/idna/LICENSE.md +31 -0
  206. pip-25.3.dist-info/licenses/src/pip/_vendor/msgpack/COPYING +14 -0
  207. pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE +3 -0
  208. pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +177 -0
  209. pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.BSD +23 -0
  210. pip-25.3.dist-info/licenses/src/pip/_vendor/pkg_resources/LICENSE +17 -0
  211. pip-25.3.dist-info/licenses/src/pip/_vendor/platformdirs/LICENSE +21 -0
  212. pip-25.3.dist-info/licenses/src/pip/_vendor/pygments/LICENSE +25 -0
  213. pip-25.3.dist-info/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +21 -0
  214. pip-25.3.dist-info/licenses/src/pip/_vendor/requests/LICENSE +175 -0
  215. pip-25.3.dist-info/licenses/src/pip/_vendor/resolvelib/LICENSE +13 -0
  216. pip-25.3.dist-info/licenses/src/pip/_vendor/rich/LICENSE +19 -0
  217. pip-25.3.dist-info/licenses/src/pip/_vendor/tomli/LICENSE +21 -0
  218. pip-25.3.dist-info/licenses/src/pip/_vendor/tomli_w/LICENSE +21 -0
  219. pip-25.3.dist-info/licenses/src/pip/_vendor/truststore/LICENSE +21 -0
  220. pip-25.3.dist-info/licenses/src/pip/_vendor/urllib3/LICENSE.txt +21 -0
  221. pip/_internal/operations/build/metadata_legacy.py +0 -73
  222. pip/_internal/operations/build/wheel_legacy.py +0 -118
  223. pip/_internal/operations/install/editable_legacy.py +0 -46
  224. pip/_internal/utils/setuptools_build.py +0 -147
  225. pip/_vendor/distlib/database.py +0 -1329
  226. pip/_vendor/distlib/index.py +0 -508
  227. pip/_vendor/distlib/locators.py +0 -1295
  228. pip/_vendor/distlib/manifest.py +0 -384
  229. pip/_vendor/distlib/markers.py +0 -162
  230. pip/_vendor/distlib/metadata.py +0 -1031
  231. pip/_vendor/distlib/version.py +0 -750
  232. pip/_vendor/distlib/wheel.py +0 -1100
  233. pip/_vendor/typing_extensions.py +0 -4584
  234. pip-25.1.1.dist-info/entry_points.txt +0 -3
  235. pip-25.1.1.dist-info/top_level.txt +0 -1
  236. {pip-25.1.1.dist-info → pip-25.3.dist-info}/licenses/LICENSE.txt +0 -0
@@ -22,27 +22,21 @@ from typing import (
22
22
  Dict,
23
23
  Iterable,
24
24
  List,
25
+ Literal,
25
26
  Mapping,
26
27
  NamedTuple,
27
28
  Optional,
29
+ Protocol,
28
30
  TextIO,
29
31
  Tuple,
30
32
  Type,
31
33
  Union,
32
34
  cast,
35
+ runtime_checkable,
33
36
  )
34
37
 
35
38
  from pip._vendor.rich._null_file import NULL_FILE
36
39
 
37
- if sys.version_info >= (3, 8):
38
- from typing import Literal, Protocol, runtime_checkable
39
- else:
40
- from pip._vendor.typing_extensions import (
41
- Literal,
42
- Protocol,
43
- runtime_checkable,
44
- ) # pragma: no cover
45
-
46
40
  from . import errors, themes
47
41
  from ._emoji_replace import _emoji_replace
48
42
  from ._export_format import CONSOLE_HTML_FORMAT, CONSOLE_SVG_FORMAT
@@ -739,6 +733,14 @@ class Console:
739
733
  if no_color is not None
740
734
  else self._environ.get("NO_COLOR", "") != ""
741
735
  )
736
+ if force_interactive is None:
737
+ tty_interactive = self._environ.get("TTY_INTERACTIVE", None)
738
+ if tty_interactive is not None:
739
+ if tty_interactive == "0":
740
+ force_interactive = False
741
+ elif tty_interactive == "1":
742
+ force_interactive = True
743
+
742
744
  self.is_interactive = (
743
745
  (self.is_terminal and not self.is_dumb_terminal)
744
746
  if force_interactive is None
@@ -751,7 +753,7 @@ class Console:
751
753
  )
752
754
  self._record_buffer: List[Segment] = []
753
755
  self._render_hooks: List[RenderHook] = []
754
- self._live: Optional["Live"] = None
756
+ self._live_stack: List[Live] = []
755
757
  self._is_alt_screen = False
756
758
 
757
759
  def __repr__(self) -> str:
@@ -823,24 +825,26 @@ class Console:
823
825
  self._buffer_index -= 1
824
826
  self._check_buffer()
825
827
 
826
- def set_live(self, live: "Live") -> None:
827
- """Set Live instance. Used by Live context manager.
828
+ def set_live(self, live: "Live") -> bool:
829
+ """Set Live instance. Used by Live context manager (no need to call directly).
828
830
 
829
831
  Args:
830
832
  live (Live): Live instance using this Console.
831
833
 
834
+ Returns:
835
+ Boolean that indicates if the live is the topmost of the stack.
836
+
832
837
  Raises:
833
838
  errors.LiveError: If this Console has a Live context currently active.
834
839
  """
835
840
  with self._lock:
836
- if self._live is not None:
837
- raise errors.LiveError("Only one live display may be active at once")
838
- self._live = live
841
+ self._live_stack.append(live)
842
+ return len(self._live_stack) == 1
839
843
 
840
844
  def clear_live(self) -> None:
841
- """Clear the Live instance."""
845
+ """Clear the Live instance. Used by the Live context manager (no need to call directly)."""
842
846
  with self._lock:
843
- self._live = None
847
+ self._live_stack.pop()
844
848
 
845
849
  def push_render_hook(self, hook: RenderHook) -> None:
846
850
  """Add a new render hook to the stack.
@@ -992,12 +996,13 @@ class Console:
992
996
  @property
993
997
  def options(self) -> ConsoleOptions:
994
998
  """Get default console options."""
999
+ size = self.size
995
1000
  return ConsoleOptions(
996
- max_height=self.size.height,
997
- size=self.size,
1001
+ max_height=size.height,
1002
+ size=size,
998
1003
  legacy_windows=self.legacy_windows,
999
1004
  min_width=1,
1000
- max_width=self.width,
1005
+ max_width=size.width,
1001
1006
  encoding=self.encoding,
1002
1007
  is_terminal=self.is_terminal,
1003
1008
  )
@@ -1,11 +1,5 @@
1
- import sys
2
1
  import time
3
- from typing import TYPE_CHECKING, Callable, Dict, Iterable, List, Union
4
-
5
- if sys.version_info >= (3, 8):
6
- from typing import Final
7
- else:
8
- from pip._vendor.typing_extensions import Final # pragma: no cover
2
+ from typing import TYPE_CHECKING, Callable, Dict, Iterable, List, Union, Final
9
3
 
10
4
  from .segment import ControlCode, ControlType, Segment
11
5
 
@@ -26,6 +26,7 @@ def report() -> None: # pragma: no cover
26
26
  "TERM_PROGRAM",
27
27
  "TERM",
28
28
  "TTY_COMPATIBLE",
29
+ "TTY_INTERACTIVE",
29
30
  "VSCODE_VERBOSE_LOGGING",
30
31
  )
31
32
  env = {name: os.getenv(name) for name in env_names}
pip/_vendor/rich/emoji.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import sys
2
- from typing import TYPE_CHECKING, Optional, Union
2
+ from typing import TYPE_CHECKING, Optional, Union, Literal
3
3
 
4
4
  from .jupyter import JupyterMixin
5
5
  from .segment import Segment
@@ -7,11 +7,6 @@ from .style import Style
7
7
  from ._emoji_codes import EMOJI
8
8
  from ._emoji_replace import _emoji_replace
9
9
 
10
- if sys.version_info >= (3, 8):
11
- from typing import Literal
12
- else:
13
- from pip._vendor.typing_extensions import Literal # pragma: no cover
14
-
15
10
 
16
11
  if TYPE_CHECKING:
17
12
  from .console import Console, ConsoleOptions, RenderResult
pip/_vendor/rich/live.py CHANGED
@@ -1,10 +1,12 @@
1
+ from __future__ import annotations
2
+
1
3
  import sys
2
4
  from threading import Event, RLock, Thread
3
5
  from types import TracebackType
4
- from typing import IO, Any, Callable, List, Optional, TextIO, Type, cast
6
+ from typing import IO, TYPE_CHECKING, Any, Callable, List, Optional, TextIO, Type, cast
5
7
 
6
8
  from . import get_console
7
- from .console import Console, ConsoleRenderable, RenderableType, RenderHook
9
+ from .console import Console, ConsoleRenderable, Group, RenderableType, RenderHook
8
10
  from .control import Control
9
11
  from .file_proxy import FileProxy
10
12
  from .jupyter import JupyterMixin
@@ -12,6 +14,10 @@ from .live_render import LiveRender, VerticalOverflowMethod
12
14
  from .screen import Screen
13
15
  from .text import Text
14
16
 
17
+ if TYPE_CHECKING:
18
+ # Can be replaced with `from typing import Self` in Python 3.11+
19
+ from typing_extensions import Self # pragma: no cover
20
+
15
21
 
16
22
  class _RefreshThread(Thread):
17
23
  """A thread that calls refresh() at regular intervals."""
@@ -87,6 +93,7 @@ class Live(JupyterMixin, RenderHook):
87
93
  self._live_render = LiveRender(
88
94
  self.get_renderable(), vertical_overflow=vertical_overflow
89
95
  )
96
+ self._nested = False
90
97
 
91
98
  @property
92
99
  def is_started(self) -> bool:
@@ -110,8 +117,12 @@ class Live(JupyterMixin, RenderHook):
110
117
  with self._lock:
111
118
  if self._started:
112
119
  return
113
- self.console.set_live(self)
114
120
  self._started = True
121
+
122
+ if not self.console.set_live(self):
123
+ self._nested = True
124
+ return
125
+
115
126
  if self._screen:
116
127
  self._alt_screen = self.console.set_alt_screen(True)
117
128
  self.console.show_cursor(False)
@@ -136,8 +147,12 @@ class Live(JupyterMixin, RenderHook):
136
147
  with self._lock:
137
148
  if not self._started:
138
149
  return
139
- self.console.clear_live()
140
150
  self._started = False
151
+ self.console.clear_live()
152
+ if self._nested:
153
+ if not self.transient:
154
+ self.console.print(self.renderable)
155
+ return
141
156
 
142
157
  if self.auto_refresh and self._refresh_thread is not None:
143
158
  self._refresh_thread.stop()
@@ -156,13 +171,12 @@ class Live(JupyterMixin, RenderHook):
156
171
  self.console.show_cursor(True)
157
172
  if self._alt_screen:
158
173
  self.console.set_alt_screen(False)
159
-
160
174
  if self.transient and not self._alt_screen:
161
175
  self.console.control(self._live_render.restore_cursor())
162
176
  if self.ipy_widget is not None and self.transient:
163
177
  self.ipy_widget.close() # pragma: no cover
164
178
 
165
- def __enter__(self) -> "Live":
179
+ def __enter__(self) -> Self:
166
180
  self.start(refresh=self._renderable is not None)
167
181
  return self
168
182
 
@@ -200,7 +214,13 @@ class Live(JupyterMixin, RenderHook):
200
214
  Returns:
201
215
  RenderableType: Displayed renderable.
202
216
  """
203
- renderable = self.get_renderable()
217
+ live_stack = self.console._live_stack
218
+ renderable: RenderableType
219
+ if live_stack and self is live_stack[0]:
220
+ # The first Live instance will render everything in the Live stack
221
+ renderable = Group(*[live.get_renderable() for live in live_stack])
222
+ else:
223
+ renderable = self.get_renderable()
204
224
  return Screen(renderable) if self._alt_screen else renderable
205
225
 
206
226
  def update(self, renderable: RenderableType, *, refresh: bool = False) -> None:
@@ -221,6 +241,11 @@ class Live(JupyterMixin, RenderHook):
221
241
  """Update the display of the Live Render."""
222
242
  with self._lock:
223
243
  self._live_render.set_renderable(self.renderable)
244
+ if self._nested:
245
+ if self.console._live_stack:
246
+ self.console._live_stack[0].refresh()
247
+ return
248
+
224
249
  if self.console.is_jupyter: # pragma: no cover
225
250
  try:
226
251
  from IPython.display import display
@@ -1,10 +1,4 @@
1
- import sys
2
- from typing import Optional, Tuple
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
1
+ from typing import Optional, Tuple, Literal
8
2
 
9
3
 
10
4
  from ._loop import loop_last
@@ -76,7 +76,7 @@ class RichHandler(Handler):
76
76
  markup: bool = False,
77
77
  rich_tracebacks: bool = False,
78
78
  tracebacks_width: Optional[int] = None,
79
- tracebacks_code_width: int = 88,
79
+ tracebacks_code_width: Optional[int] = 88,
80
80
  tracebacks_extra_lines: int = 3,
81
81
  tracebacks_theme: Optional[str] = None,
82
82
  tracebacks_word_wrap: bool = True,
pip/_vendor/rich/panel.py CHANGED
@@ -146,8 +146,7 @@ class Panel(JupyterMixin):
146
146
  Padding(self.renderable, _padding) if any(_padding) else self.renderable
147
147
  )
148
148
  style = console.get_style(self.style)
149
- partial_border_style = console.get_style(self.border_style)
150
- border_style = style + partial_border_style
149
+ border_style = style + console.get_style(self.border_style)
151
150
  width = (
152
151
  options.max_width
153
152
  if self.width is None
@@ -206,7 +205,7 @@ class Panel(JupyterMixin):
206
205
 
207
206
  title_text = self._title
208
207
  if title_text is not None:
209
- title_text.stylize_before(partial_border_style)
208
+ title_text.stylize_before(border_style)
210
209
 
211
210
  child_width = (
212
211
  width - 2
@@ -255,7 +254,7 @@ class Panel(JupyterMixin):
255
254
 
256
255
  subtitle_text = self._subtitle
257
256
  if subtitle_text is not None:
258
- subtitle_text.stylize_before(partial_border_style)
257
+ subtitle_text.stylize_before(border_style)
259
258
 
260
259
  if subtitle_text is None or width <= 4:
261
260
  yield Segment(box.get_bottom([width - 2]), border_style)
@@ -1,5 +1,6 @@
1
+ from __future__ import annotations
2
+
1
3
  import io
2
- import sys
3
4
  import typing
4
5
  import warnings
5
6
  from abc import ABC, abstractmethod
@@ -14,6 +15,7 @@ from os import PathLike, stat
14
15
  from threading import Event, RLock, Thread
15
16
  from types import TracebackType
16
17
  from typing import (
18
+ TYPE_CHECKING,
17
19
  Any,
18
20
  BinaryIO,
19
21
  Callable,
@@ -23,10 +25,10 @@ from typing import (
23
25
  Generic,
24
26
  Iterable,
25
27
  List,
28
+ Literal,
26
29
  NamedTuple,
27
30
  NewType,
28
31
  Optional,
29
- Sequence,
30
32
  TextIO,
31
33
  Tuple,
32
34
  Type,
@@ -34,15 +36,9 @@ from typing import (
34
36
  Union,
35
37
  )
36
38
 
37
- if sys.version_info >= (3, 8):
38
- from typing import Literal
39
- else:
40
- from pip._vendor.typing_extensions import Literal # pragma: no cover
41
-
42
- if sys.version_info >= (3, 11):
43
- from typing import Self
44
- else:
45
- from pip._vendor.typing_extensions import Self # pragma: no cover
39
+ if TYPE_CHECKING:
40
+ # Can be replaced with `from typing import Self` in Python 3.11+
41
+ from typing_extensions import Self # pragma: no cover
46
42
 
47
43
  from . import filesize, get_console
48
44
  from .console import Console, Group, JustifyMethod, RenderableType
@@ -106,7 +102,7 @@ class _TrackThread(Thread):
106
102
 
107
103
 
108
104
  def track(
109
- sequence: Union[Sequence[ProgressType], Iterable[ProgressType]],
105
+ sequence: Iterable[ProgressType],
110
106
  description: str = "Working...",
111
107
  total: Optional[float] = None,
112
108
  completed: int = 0,
@@ -125,8 +121,10 @@ def track(
125
121
  ) -> Iterable[ProgressType]:
126
122
  """Track progress by iterating over a sequence.
127
123
 
124
+ You can also track progress of an iterable, which might require that you additionally specify ``total``.
125
+
128
126
  Args:
129
- sequence (Iterable[ProgressType]): A sequence (must support "len") you wish to iterate over.
127
+ sequence (Iterable[ProgressType]): Values you wish to iterate over and track progress.
130
128
  description (str, optional): Description of task show next to progress bar. Defaults to "Working".
131
129
  total: (float, optional): Total number of steps. Default is len(sequence).
132
130
  completed (int, optional): Number of steps completed so far. Defaults to 0.
@@ -1192,7 +1190,7 @@ class Progress(JupyterMixin):
1192
1190
 
1193
1191
  def track(
1194
1192
  self,
1195
- sequence: Union[Iterable[ProgressType], Sequence[ProgressType]],
1193
+ sequence: Iterable[ProgressType],
1196
1194
  total: Optional[float] = None,
1197
1195
  completed: int = 0,
1198
1196
  task_id: Optional[TaskID] = None,
@@ -1201,8 +1199,10 @@ class Progress(JupyterMixin):
1201
1199
  ) -> Iterable[ProgressType]:
1202
1200
  """Track progress by iterating over a sequence.
1203
1201
 
1202
+ You can also track progress of an iterable, which might require that you additionally specify ``total``.
1203
+
1204
1204
  Args:
1205
- sequence (Sequence[ProgressType]): A sequence of values you want to iterate over and track progress.
1205
+ sequence (Iterable[ProgressType]): Values you want to iterate over and track progress.
1206
1206
  total: (float, optional): Total number of steps. Default is len(sequence).
1207
1207
  completed (int, optional): Number of steps completed so far. Defaults to 0.
1208
1208
  task_id: (TaskID): Task to track. Default is new task.
@@ -1,4 +1,4 @@
1
- from typing import cast, List, Optional, TYPE_CHECKING, Union
1
+ from typing import TYPE_CHECKING, List, Optional, Union, cast
2
2
 
3
3
  from ._spinners import SPINNERS
4
4
  from .measure import Measurement
@@ -6,7 +6,7 @@ from .table import Table
6
6
  from .text import Text
7
7
 
8
8
  if TYPE_CHECKING:
9
- from .console import Console, ConsoleOptions, RenderResult, RenderableType
9
+ from .console import Console, ConsoleOptions, RenderableType, RenderResult
10
10
  from .style import StyleType
11
11
 
12
12
 
@@ -117,22 +117,16 @@ class Spinner:
117
117
  if __name__ == "__main__": # pragma: no cover
118
118
  from time import sleep
119
119
 
120
- from .columns import Columns
121
- from .panel import Panel
120
+ from .console import Group
122
121
  from .live import Live
123
122
 
124
- all_spinners = Columns(
125
- [
123
+ all_spinners = Group(
124
+ *[
126
125
  Spinner(spinner_name, text=Text(repr(spinner_name), style="green"))
127
126
  for spinner_name in sorted(SPINNERS.keys())
128
- ],
129
- column_first=True,
130
- expand=True,
127
+ ]
131
128
  )
132
129
 
133
- with Live(
134
- Panel(all_spinners, title="Spinners", border_style="blue"),
135
- refresh_per_second=20,
136
- ) as live:
130
+ with Live(all_spinners, refresh_per_second=20) as live:
137
131
  while True:
138
132
  sleep(0.1)
pip/_vendor/rich/style.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import sys
2
2
  from functools import lru_cache
3
- from marshal import dumps, loads
3
+ from operator import attrgetter
4
+ from pickle import dumps, loads
4
5
  from random import randint
5
6
  from typing import Any, Dict, Iterable, List, Optional, Type, Union, cast
6
7
 
@@ -9,6 +10,10 @@ from .color import Color, ColorParseError, ColorSystem, blend_rgb
9
10
  from .repr import Result, rich_repr
10
11
  from .terminal_theme import DEFAULT_TERMINAL_THEME, TerminalTheme
11
12
 
13
+ _hash_getter = attrgetter(
14
+ "_color", "_bgcolor", "_attributes", "_set_attributes", "_link", "_meta"
15
+ )
16
+
12
17
  # Style instances and style definitions are often interchangeable
13
18
  StyleType = Union[str, "Style"]
14
19
 
@@ -432,16 +437,7 @@ class Style:
432
437
  def __hash__(self) -> int:
433
438
  if self._hash is not None:
434
439
  return self._hash
435
- self._hash = hash(
436
- (
437
- self._color,
438
- self._bgcolor,
439
- self._attributes,
440
- self._set_attributes,
441
- self._link,
442
- self._meta,
443
- )
444
- )
440
+ self._hash = hash(_hash_getter(self))
445
441
  return self._hash
446
442
 
447
443
  @property
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import os.path
2
4
  import re
3
5
  import sys
@@ -224,6 +226,17 @@ class _SyntaxHighlightRange(NamedTuple):
224
226
  style_before: bool = False
225
227
 
226
228
 
229
+ class PaddingProperty:
230
+ """Descriptor to get and set padding."""
231
+
232
+ def __get__(self, obj: Syntax, objtype: Type[Syntax]) -> Tuple[int, int, int, int]:
233
+ """Space around the Syntax."""
234
+ return obj._padding
235
+
236
+ def __set__(self, obj: Syntax, padding: PaddingDimensions) -> None:
237
+ obj._padding = Padding.unpack(padding)
238
+
239
+
227
240
  class Syntax(JupyterMixin):
228
241
  """Construct a Syntax object to render syntax highlighted code.
229
242
 
@@ -293,11 +306,13 @@ class Syntax(JupyterMixin):
293
306
  Style(bgcolor=background_color) if background_color else Style()
294
307
  )
295
308
  self.indent_guides = indent_guides
296
- self.padding = padding
309
+ self._padding = Padding.unpack(padding)
297
310
 
298
311
  self._theme = self.get_theme(theme)
299
312
  self._stylized_ranges: List[_SyntaxHighlightRange] = []
300
313
 
314
+ padding = PaddingProperty()
315
+
301
316
  @classmethod
302
317
  def from_path(
303
318
  cls,
@@ -371,8 +386,8 @@ class Syntax(JupyterMixin):
371
386
  is supplied, the lexer will be chosen based on the file extension..
372
387
 
373
388
  Args:
374
- path (AnyStr): The path to the file containing the code you wish to know the lexer for.
375
- code (str, optional): Optional string of code that will be used as a fallback if no lexer
389
+ path (AnyStr): The path to the file containing the code you wish to know the lexer for.
390
+ code (str, optional): Optional string of code that will be used as a fallback if no lexer
376
391
  is found for the supplied path.
377
392
 
378
393
  Returns:
@@ -607,7 +622,7 @@ class Syntax(JupyterMixin):
607
622
  def __rich_measure__(
608
623
  self, console: "Console", options: "ConsoleOptions"
609
624
  ) -> "Measurement":
610
- _, right, _, left = Padding.unpack(self.padding)
625
+ _, right, _, left = self.padding
611
626
  padding = left + right
612
627
  if self.code_width is not None:
613
628
  width = self.code_width + self._numbers_column_width + padding + 1
@@ -626,7 +641,7 @@ class Syntax(JupyterMixin):
626
641
  self, console: Console, options: ConsoleOptions
627
642
  ) -> RenderResult:
628
643
  segments = Segments(self._get_syntax(console, options))
629
- if self.padding:
644
+ if any(self.padding):
630
645
  yield Padding(segments, style=self._get_base_style(), pad=self.padding)
631
646
  else:
632
647
  yield segments
@@ -640,15 +655,19 @@ class Syntax(JupyterMixin):
640
655
  Get the Segments for the Syntax object, excluding any vertical/horizontal padding
641
656
  """
642
657
  transparent_background = self._get_base_style().transparent_background
658
+ _pad_top, pad_right, _pad_bottom, pad_left = self.padding
659
+ horizontal_padding = pad_left + pad_right
643
660
  code_width = (
644
661
  (
645
662
  (options.max_width - self._numbers_column_width - 1)
646
663
  if self.line_numbers
647
664
  else options.max_width
648
665
  )
666
+ - horizontal_padding
649
667
  if self.code_width is None
650
668
  else self.code_width
651
669
  )
670
+ code_width = max(0, code_width)
652
671
 
653
672
  ends_on_nl, processed_code = self._process_code(self.code)
654
673
  text = self.highlight(processed_code, self.line_range)
@@ -14,6 +14,7 @@ from typing import (
14
14
  List,
15
15
  Optional,
16
16
  Sequence,
17
+ Set,
17
18
  Tuple,
18
19
  Type,
19
20
  Union,
@@ -177,7 +178,9 @@ def install(
177
178
 
178
179
  # determine correct tb_offset
179
180
  compiled = tb_data.get("running_compiled_code", False)
180
- tb_offset = tb_data.get("tb_offset", 1 if compiled else 0)
181
+ tb_offset = tb_data.get("tb_offset")
182
+ if tb_offset is None:
183
+ tb_offset = 1 if compiled else 0
181
184
  # remove ipython internal frames from trace with tb_offset
182
185
  for _ in range(tb_offset):
183
186
  if tb is None:
@@ -418,6 +421,7 @@ class Traceback:
418
421
  locals_max_string: int = LOCALS_MAX_STRING,
419
422
  locals_hide_dunder: bool = True,
420
423
  locals_hide_sunder: bool = False,
424
+ _visited_exceptions: Optional[Set[BaseException]] = None,
421
425
  ) -> Trace:
422
426
  """Extract traceback information.
423
427
 
@@ -443,6 +447,10 @@ class Traceback:
443
447
 
444
448
  notes: List[str] = getattr(exc_value, "__notes__", None) or []
445
449
 
450
+ grouped_exceptions: Set[BaseException] = (
451
+ set() if _visited_exceptions is None else _visited_exceptions
452
+ )
453
+
446
454
  def safe_str(_object: Any) -> str:
447
455
  """Don't allow exceptions from __str__ to propagate."""
448
456
  try:
@@ -462,6 +470,9 @@ class Traceback:
462
470
  if isinstance(exc_value, (BaseExceptionGroup, ExceptionGroup)):
463
471
  stack.is_group = True
464
472
  for exception in exc_value.exceptions:
473
+ if exception in grouped_exceptions:
474
+ continue
475
+ grouped_exceptions.add(exception)
465
476
  stack.exceptions.append(
466
477
  Traceback.extract(
467
478
  type(exception),
@@ -471,6 +482,7 @@ class Traceback:
471
482
  locals_max_length=locals_max_length,
472
483
  locals_hide_dunder=locals_hide_dunder,
473
484
  locals_hide_sunder=locals_hide_sunder,
485
+ _visited_exceptions=grouped_exceptions,
474
486
  )
475
487
  )
476
488
 
@@ -561,23 +573,26 @@ class Traceback:
561
573
  if frame_summary.f_locals.get("_rich_traceback_guard", False):
562
574
  del stack.frames[:]
563
575
 
564
- cause = getattr(exc_value, "__cause__", None)
565
- if cause:
566
- exc_type = cause.__class__
567
- exc_value = cause
568
- # __traceback__ can be None, e.g. for exceptions raised by the
569
- # 'multiprocessing' module
570
- traceback = cause.__traceback__
571
- is_cause = True
572
- continue
576
+ if not grouped_exceptions:
577
+ cause = getattr(exc_value, "__cause__", None)
578
+ if cause is not None and cause is not exc_value:
579
+ exc_type = cause.__class__
580
+ exc_value = cause
581
+ # __traceback__ can be None, e.g. for exceptions raised by the
582
+ # 'multiprocessing' module
583
+ traceback = cause.__traceback__
584
+ is_cause = True
585
+ continue
573
586
 
574
- cause = exc_value.__context__
575
- if cause and not getattr(exc_value, "__suppress_context__", False):
576
- exc_type = cause.__class__
577
- exc_value = cause
578
- traceback = cause.__traceback__
579
- is_cause = False
580
- continue
587
+ cause = exc_value.__context__
588
+ if cause is not None and not getattr(
589
+ exc_value, "__suppress_context__", False
590
+ ):
591
+ exc_type = cause.__class__
592
+ exc_value = cause
593
+ traceback = cause.__traceback__
594
+ is_cause = False
595
+ continue
581
596
  # No cover, code is reached but coverage doesn't recognize it.
582
597
  break # pragma: no cover
583
598
 
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Taneli Hukkinen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.