koichi12 commited on
Commit
6764f79
·
verified ·
1 Parent(s): 3e89aee

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .venv/lib/python3.11/site-packages/pip/_internal/commands/__init__.py +132 -0
  2. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-311.pyc +0 -0
  3. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/cache.cpython-311.pyc +0 -0
  4. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/check.cpython-311.pyc +0 -0
  5. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/completion.cpython-311.pyc +0 -0
  6. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-311.pyc +0 -0
  7. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/debug.cpython-311.pyc +0 -0
  8. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/download.cpython-311.pyc +0 -0
  9. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-311.pyc +0 -0
  10. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/hash.cpython-311.pyc +0 -0
  11. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/help.cpython-311.pyc +0 -0
  12. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/index.cpython-311.pyc +0 -0
  13. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-311.pyc +0 -0
  14. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/install.cpython-311.pyc +0 -0
  15. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/list.cpython-311.pyc +0 -0
  16. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/search.cpython-311.pyc +0 -0
  17. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/show.cpython-311.pyc +0 -0
  18. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-311.pyc +0 -0
  19. .venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-311.pyc +0 -0
  20. .venv/lib/python3.11/site-packages/pip/_internal/commands/cache.py +225 -0
  21. .venv/lib/python3.11/site-packages/pip/_internal/commands/check.py +54 -0
  22. .venv/lib/python3.11/site-packages/pip/_internal/commands/completion.py +130 -0
  23. .venv/lib/python3.11/site-packages/pip/_internal/commands/configuration.py +280 -0
  24. .venv/lib/python3.11/site-packages/pip/_internal/commands/debug.py +201 -0
  25. .venv/lib/python3.11/site-packages/pip/_internal/commands/download.py +147 -0
  26. .venv/lib/python3.11/site-packages/pip/_internal/commands/freeze.py +108 -0
  27. .venv/lib/python3.11/site-packages/pip/_internal/commands/hash.py +59 -0
  28. .venv/lib/python3.11/site-packages/pip/_internal/commands/help.py +41 -0
  29. .venv/lib/python3.11/site-packages/pip/_internal/commands/index.py +139 -0
  30. .venv/lib/python3.11/site-packages/pip/_internal/commands/inspect.py +92 -0
  31. .venv/lib/python3.11/site-packages/pip/_internal/commands/install.py +774 -0
  32. .venv/lib/python3.11/site-packages/pip/_internal/commands/list.py +368 -0
  33. .venv/lib/python3.11/site-packages/pip/_internal/commands/search.py +174 -0
  34. .venv/lib/python3.11/site-packages/pip/_internal/commands/show.py +189 -0
  35. .venv/lib/python3.11/site-packages/pip/_internal/commands/uninstall.py +113 -0
  36. .venv/lib/python3.11/site-packages/pip/_internal/commands/wheel.py +183 -0
  37. .venv/lib/python3.11/site-packages/pip/_internal/locations/__init__.py +467 -0
  38. .venv/lib/python3.11/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-311.pyc +0 -0
  39. .venv/lib/python3.11/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-311.pyc +0 -0
  40. .venv/lib/python3.11/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-311.pyc +0 -0
  41. .venv/lib/python3.11/site-packages/pip/_internal/locations/__pycache__/base.cpython-311.pyc +0 -0
  42. .venv/lib/python3.11/site-packages/pip/_internal/locations/_distutils.py +172 -0
  43. .venv/lib/python3.11/site-packages/pip/_internal/locations/_sysconfig.py +213 -0
  44. .venv/lib/python3.11/site-packages/pip/_internal/locations/base.py +81 -0
  45. .venv/lib/python3.11/site-packages/pip/_internal/models/__pycache__/__init__.cpython-311.pyc +0 -0
  46. .venv/lib/python3.11/site-packages/pip/_internal/models/__pycache__/candidate.cpython-311.pyc +0 -0
  47. .venv/lib/python3.11/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-311.pyc +0 -0
  48. .venv/lib/python3.11/site-packages/pip/_internal/models/__pycache__/format_control.cpython-311.pyc +0 -0
  49. .venv/lib/python3.11/site-packages/pip/_internal/models/__pycache__/index.cpython-311.pyc +0 -0
  50. .venv/lib/python3.11/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-311.pyc +0 -0
.venv/lib/python3.11/site-packages/pip/_internal/commands/__init__.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Package containing all pip commands
3
+ """
4
+
5
+ import importlib
6
+ from collections import namedtuple
7
+ from typing import Any, Dict, Optional
8
+
9
+ from pip._internal.cli.base_command import Command
10
+
11
+ CommandInfo = namedtuple("CommandInfo", "module_path, class_name, summary")
12
+
13
+ # This dictionary does a bunch of heavy lifting for help output:
14
+ # - Enables avoiding additional (costly) imports for presenting `--help`.
15
+ # - The ordering matters for help display.
16
+ #
17
+ # Even though the module path starts with the same "pip._internal.commands"
18
+ # prefix, the full path makes testing easier (specifically when modifying
19
+ # `commands_dict` in test setup / teardown).
20
+ commands_dict: Dict[str, CommandInfo] = {
21
+ "install": CommandInfo(
22
+ "pip._internal.commands.install",
23
+ "InstallCommand",
24
+ "Install packages.",
25
+ ),
26
+ "download": CommandInfo(
27
+ "pip._internal.commands.download",
28
+ "DownloadCommand",
29
+ "Download packages.",
30
+ ),
31
+ "uninstall": CommandInfo(
32
+ "pip._internal.commands.uninstall",
33
+ "UninstallCommand",
34
+ "Uninstall packages.",
35
+ ),
36
+ "freeze": CommandInfo(
37
+ "pip._internal.commands.freeze",
38
+ "FreezeCommand",
39
+ "Output installed packages in requirements format.",
40
+ ),
41
+ "inspect": CommandInfo(
42
+ "pip._internal.commands.inspect",
43
+ "InspectCommand",
44
+ "Inspect the python environment.",
45
+ ),
46
+ "list": CommandInfo(
47
+ "pip._internal.commands.list",
48
+ "ListCommand",
49
+ "List installed packages.",
50
+ ),
51
+ "show": CommandInfo(
52
+ "pip._internal.commands.show",
53
+ "ShowCommand",
54
+ "Show information about installed packages.",
55
+ ),
56
+ "check": CommandInfo(
57
+ "pip._internal.commands.check",
58
+ "CheckCommand",
59
+ "Verify installed packages have compatible dependencies.",
60
+ ),
61
+ "config": CommandInfo(
62
+ "pip._internal.commands.configuration",
63
+ "ConfigurationCommand",
64
+ "Manage local and global configuration.",
65
+ ),
66
+ "search": CommandInfo(
67
+ "pip._internal.commands.search",
68
+ "SearchCommand",
69
+ "Search PyPI for packages.",
70
+ ),
71
+ "cache": CommandInfo(
72
+ "pip._internal.commands.cache",
73
+ "CacheCommand",
74
+ "Inspect and manage pip's wheel cache.",
75
+ ),
76
+ "index": CommandInfo(
77
+ "pip._internal.commands.index",
78
+ "IndexCommand",
79
+ "Inspect information available from package indexes.",
80
+ ),
81
+ "wheel": CommandInfo(
82
+ "pip._internal.commands.wheel",
83
+ "WheelCommand",
84
+ "Build wheels from your requirements.",
85
+ ),
86
+ "hash": CommandInfo(
87
+ "pip._internal.commands.hash",
88
+ "HashCommand",
89
+ "Compute hashes of package archives.",
90
+ ),
91
+ "completion": CommandInfo(
92
+ "pip._internal.commands.completion",
93
+ "CompletionCommand",
94
+ "A helper command used for command completion.",
95
+ ),
96
+ "debug": CommandInfo(
97
+ "pip._internal.commands.debug",
98
+ "DebugCommand",
99
+ "Show information useful for debugging.",
100
+ ),
101
+ "help": CommandInfo(
102
+ "pip._internal.commands.help",
103
+ "HelpCommand",
104
+ "Show help for commands.",
105
+ ),
106
+ }
107
+
108
+
109
+ def create_command(name: str, **kwargs: Any) -> Command:
110
+ """
111
+ Create an instance of the Command class with the given name.
112
+ """
113
+ module_path, class_name, summary = commands_dict[name]
114
+ module = importlib.import_module(module_path)
115
+ command_class = getattr(module, class_name)
116
+ command = command_class(name=name, summary=summary, **kwargs)
117
+
118
+ return command
119
+
120
+
121
+ def get_similar_commands(name: str) -> Optional[str]:
122
+ """Command name auto-correct."""
123
+ from difflib import get_close_matches
124
+
125
+ name = name.lower()
126
+
127
+ close_commands = get_close_matches(name, commands_dict.keys())
128
+
129
+ if close_commands:
130
+ return close_commands[0]
131
+ else:
132
+ return None
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (4.45 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/cache.cpython-311.pyc ADDED
Binary file (10.9 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/check.cpython-311.pyc ADDED
Binary file (2.41 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/completion.cpython-311.pyc ADDED
Binary file (5.62 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-311.pyc ADDED
Binary file (14.8 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/debug.cpython-311.pyc ADDED
Binary file (12.2 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/download.cpython-311.pyc ADDED
Binary file (7.94 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-311.pyc ADDED
Binary file (4.66 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/hash.cpython-311.pyc ADDED
Binary file (3.35 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/help.cpython-311.pyc ADDED
Binary file (1.97 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/index.cpython-311.pyc ADDED
Binary file (7.72 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-311.pyc ADDED
Binary file (4.44 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/install.cpython-311.pyc ADDED
Binary file (31.1 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/list.cpython-311.pyc ADDED
Binary file (17.2 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/search.cpython-311.pyc ADDED
Binary file (8.95 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/show.cpython-311.pyc ADDED
Binary file (11.3 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-311.pyc ADDED
Binary file (5.14 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-311.pyc ADDED
Binary file (9.4 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/commands/cache.py ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import textwrap
3
+ from optparse import Values
4
+ from typing import Any, List
5
+
6
+ from pip._internal.cli.base_command import Command
7
+ from pip._internal.cli.status_codes import ERROR, SUCCESS
8
+ from pip._internal.exceptions import CommandError, PipError
9
+ from pip._internal.utils import filesystem
10
+ from pip._internal.utils.logging import getLogger
11
+
12
+ logger = getLogger(__name__)
13
+
14
+
15
+ class CacheCommand(Command):
16
+ """
17
+ Inspect and manage pip's wheel cache.
18
+
19
+ Subcommands:
20
+
21
+ - dir: Show the cache directory.
22
+ - info: Show information about the cache.
23
+ - list: List filenames of packages stored in the cache.
24
+ - remove: Remove one or more package from the cache.
25
+ - purge: Remove all items from the cache.
26
+
27
+ ``<pattern>`` can be a glob expression or a package name.
28
+ """
29
+
30
+ ignore_require_venv = True
31
+ usage = """
32
+ %prog dir
33
+ %prog info
34
+ %prog list [<pattern>] [--format=[human, abspath]]
35
+ %prog remove <pattern>
36
+ %prog purge
37
+ """
38
+
39
+ def add_options(self) -> None:
40
+ self.cmd_opts.add_option(
41
+ "--format",
42
+ action="store",
43
+ dest="list_format",
44
+ default="human",
45
+ choices=("human", "abspath"),
46
+ help="Select the output format among: human (default) or abspath",
47
+ )
48
+
49
+ self.parser.insert_option_group(0, self.cmd_opts)
50
+
51
+ def run(self, options: Values, args: List[str]) -> int:
52
+ handlers = {
53
+ "dir": self.get_cache_dir,
54
+ "info": self.get_cache_info,
55
+ "list": self.list_cache_items,
56
+ "remove": self.remove_cache_items,
57
+ "purge": self.purge_cache,
58
+ }
59
+
60
+ if not options.cache_dir:
61
+ logger.error("pip cache commands can not function since cache is disabled.")
62
+ return ERROR
63
+
64
+ # Determine action
65
+ if not args or args[0] not in handlers:
66
+ logger.error(
67
+ "Need an action (%s) to perform.",
68
+ ", ".join(sorted(handlers)),
69
+ )
70
+ return ERROR
71
+
72
+ action = args[0]
73
+
74
+ # Error handling happens here, not in the action-handlers.
75
+ try:
76
+ handlers[action](options, args[1:])
77
+ except PipError as e:
78
+ logger.error(e.args[0])
79
+ return ERROR
80
+
81
+ return SUCCESS
82
+
83
+ def get_cache_dir(self, options: Values, args: List[Any]) -> None:
84
+ if args:
85
+ raise CommandError("Too many arguments")
86
+
87
+ logger.info(options.cache_dir)
88
+
89
+ def get_cache_info(self, options: Values, args: List[Any]) -> None:
90
+ if args:
91
+ raise CommandError("Too many arguments")
92
+
93
+ num_http_files = len(self._find_http_files(options))
94
+ num_packages = len(self._find_wheels(options, "*"))
95
+
96
+ http_cache_location = self._cache_dir(options, "http-v2")
97
+ old_http_cache_location = self._cache_dir(options, "http")
98
+ wheels_cache_location = self._cache_dir(options, "wheels")
99
+ http_cache_size = filesystem.format_size(
100
+ filesystem.directory_size(http_cache_location)
101
+ + filesystem.directory_size(old_http_cache_location)
102
+ )
103
+ wheels_cache_size = filesystem.format_directory_size(wheels_cache_location)
104
+
105
+ message = (
106
+ textwrap.dedent(
107
+ """
108
+ Package index page cache location (pip v23.3+): {http_cache_location}
109
+ Package index page cache location (older pips): {old_http_cache_location}
110
+ Package index page cache size: {http_cache_size}
111
+ Number of HTTP files: {num_http_files}
112
+ Locally built wheels location: {wheels_cache_location}
113
+ Locally built wheels size: {wheels_cache_size}
114
+ Number of locally built wheels: {package_count}
115
+ """ # noqa: E501
116
+ )
117
+ .format(
118
+ http_cache_location=http_cache_location,
119
+ old_http_cache_location=old_http_cache_location,
120
+ http_cache_size=http_cache_size,
121
+ num_http_files=num_http_files,
122
+ wheels_cache_location=wheels_cache_location,
123
+ package_count=num_packages,
124
+ wheels_cache_size=wheels_cache_size,
125
+ )
126
+ .strip()
127
+ )
128
+
129
+ logger.info(message)
130
+
131
+ def list_cache_items(self, options: Values, args: List[Any]) -> None:
132
+ if len(args) > 1:
133
+ raise CommandError("Too many arguments")
134
+
135
+ if args:
136
+ pattern = args[0]
137
+ else:
138
+ pattern = "*"
139
+
140
+ files = self._find_wheels(options, pattern)
141
+ if options.list_format == "human":
142
+ self.format_for_human(files)
143
+ else:
144
+ self.format_for_abspath(files)
145
+
146
+ def format_for_human(self, files: List[str]) -> None:
147
+ if not files:
148
+ logger.info("No locally built wheels cached.")
149
+ return
150
+
151
+ results = []
152
+ for filename in files:
153
+ wheel = os.path.basename(filename)
154
+ size = filesystem.format_file_size(filename)
155
+ results.append(f" - {wheel} ({size})")
156
+ logger.info("Cache contents:\n")
157
+ logger.info("\n".join(sorted(results)))
158
+
159
+ def format_for_abspath(self, files: List[str]) -> None:
160
+ if files:
161
+ logger.info("\n".join(sorted(files)))
162
+
163
+ def remove_cache_items(self, options: Values, args: List[Any]) -> None:
164
+ if len(args) > 1:
165
+ raise CommandError("Too many arguments")
166
+
167
+ if not args:
168
+ raise CommandError("Please provide a pattern")
169
+
170
+ files = self._find_wheels(options, args[0])
171
+
172
+ no_matching_msg = "No matching packages"
173
+ if args[0] == "*":
174
+ # Only fetch http files if no specific pattern given
175
+ files += self._find_http_files(options)
176
+ else:
177
+ # Add the pattern to the log message
178
+ no_matching_msg += f' for pattern "{args[0]}"'
179
+
180
+ if not files:
181
+ logger.warning(no_matching_msg)
182
+
183
+ for filename in files:
184
+ os.unlink(filename)
185
+ logger.verbose("Removed %s", filename)
186
+ logger.info("Files removed: %s", len(files))
187
+
188
+ def purge_cache(self, options: Values, args: List[Any]) -> None:
189
+ if args:
190
+ raise CommandError("Too many arguments")
191
+
192
+ return self.remove_cache_items(options, ["*"])
193
+
194
+ def _cache_dir(self, options: Values, subdir: str) -> str:
195
+ return os.path.join(options.cache_dir, subdir)
196
+
197
+ def _find_http_files(self, options: Values) -> List[str]:
198
+ old_http_dir = self._cache_dir(options, "http")
199
+ new_http_dir = self._cache_dir(options, "http-v2")
200
+ return filesystem.find_files(old_http_dir, "*") + filesystem.find_files(
201
+ new_http_dir, "*"
202
+ )
203
+
204
+ def _find_wheels(self, options: Values, pattern: str) -> List[str]:
205
+ wheel_dir = self._cache_dir(options, "wheels")
206
+
207
+ # The wheel filename format, as specified in PEP 427, is:
208
+ # {distribution}-{version}(-{build})?-{python}-{abi}-{platform}.whl
209
+ #
210
+ # Additionally, non-alphanumeric values in the distribution are
211
+ # normalized to underscores (_), meaning hyphens can never occur
212
+ # before `-{version}`.
213
+ #
214
+ # Given that information:
215
+ # - If the pattern we're given contains a hyphen (-), the user is
216
+ # providing at least the version. Thus, we can just append `*.whl`
217
+ # to match the rest of it.
218
+ # - If the pattern we're given doesn't contain a hyphen (-), the
219
+ # user is only providing the name. Thus, we append `-*.whl` to
220
+ # match the hyphen before the version, followed by anything else.
221
+ #
222
+ # PEP 427: https://www.python.org/dev/peps/pep-0427/
223
+ pattern = pattern + ("*.whl" if "-" in pattern else "-*.whl")
224
+
225
+ return filesystem.find_files(wheel_dir, pattern)
.venv/lib/python3.11/site-packages/pip/_internal/commands/check.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ from optparse import Values
3
+ from typing import List
4
+
5
+ from pip._internal.cli.base_command import Command
6
+ from pip._internal.cli.status_codes import ERROR, SUCCESS
7
+ from pip._internal.operations.check import (
8
+ check_package_set,
9
+ create_package_set_from_installed,
10
+ warn_legacy_versions_and_specifiers,
11
+ )
12
+ from pip._internal.utils.misc import write_output
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class CheckCommand(Command):
18
+ """Verify installed packages have compatible dependencies."""
19
+
20
+ usage = """
21
+ %prog [options]"""
22
+
23
+ def run(self, options: Values, args: List[str]) -> int:
24
+ package_set, parsing_probs = create_package_set_from_installed()
25
+ warn_legacy_versions_and_specifiers(package_set)
26
+ missing, conflicting = check_package_set(package_set)
27
+
28
+ for project_name in missing:
29
+ version = package_set[project_name].version
30
+ for dependency in missing[project_name]:
31
+ write_output(
32
+ "%s %s requires %s, which is not installed.",
33
+ project_name,
34
+ version,
35
+ dependency[0],
36
+ )
37
+
38
+ for project_name in conflicting:
39
+ version = package_set[project_name].version
40
+ for dep_name, dep_version, req in conflicting[project_name]:
41
+ write_output(
42
+ "%s %s has requirement %s, but you have %s %s.",
43
+ project_name,
44
+ version,
45
+ req,
46
+ dep_name,
47
+ dep_version,
48
+ )
49
+
50
+ if missing or conflicting or parsing_probs:
51
+ return ERROR
52
+ else:
53
+ write_output("No broken requirements found.")
54
+ return SUCCESS
.venv/lib/python3.11/site-packages/pip/_internal/commands/completion.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import textwrap
3
+ from optparse import Values
4
+ from typing import List
5
+
6
+ from pip._internal.cli.base_command import Command
7
+ from pip._internal.cli.status_codes import SUCCESS
8
+ from pip._internal.utils.misc import get_prog
9
+
10
+ BASE_COMPLETION = """
11
+ # pip {shell} completion start{script}# pip {shell} completion end
12
+ """
13
+
14
+ COMPLETION_SCRIPTS = {
15
+ "bash": """
16
+ _pip_completion()
17
+ {{
18
+ COMPREPLY=( $( COMP_WORDS="${{COMP_WORDS[*]}}" \\
19
+ COMP_CWORD=$COMP_CWORD \\
20
+ PIP_AUTO_COMPLETE=1 $1 2>/dev/null ) )
21
+ }}
22
+ complete -o default -F _pip_completion {prog}
23
+ """,
24
+ "zsh": """
25
+ #compdef -P pip[0-9.]#
26
+ __pip() {{
27
+ compadd $( COMP_WORDS="$words[*]" \\
28
+ COMP_CWORD=$((CURRENT-1)) \\
29
+ PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null )
30
+ }}
31
+ if [[ $zsh_eval_context[-1] == loadautofunc ]]; then
32
+ # autoload from fpath, call function directly
33
+ __pip "$@"
34
+ else
35
+ # eval/source/. command, register function for later
36
+ compdef __pip -P 'pip[0-9.]#'
37
+ fi
38
+ """,
39
+ "fish": """
40
+ function __fish_complete_pip
41
+ set -lx COMP_WORDS (commandline -o) ""
42
+ set -lx COMP_CWORD ( \\
43
+ math (contains -i -- (commandline -t) $COMP_WORDS)-1 \\
44
+ )
45
+ set -lx PIP_AUTO_COMPLETE 1
46
+ string split \\ -- (eval $COMP_WORDS[1])
47
+ end
48
+ complete -fa "(__fish_complete_pip)" -c {prog}
49
+ """,
50
+ "powershell": """
51
+ if ((Test-Path Function:\\TabExpansion) -and -not `
52
+ (Test-Path Function:\\_pip_completeBackup)) {{
53
+ Rename-Item Function:\\TabExpansion _pip_completeBackup
54
+ }}
55
+ function TabExpansion($line, $lastWord) {{
56
+ $lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
57
+ if ($lastBlock.StartsWith("{prog} ")) {{
58
+ $Env:COMP_WORDS=$lastBlock
59
+ $Env:COMP_CWORD=$lastBlock.Split().Length - 1
60
+ $Env:PIP_AUTO_COMPLETE=1
61
+ (& {prog}).Split()
62
+ Remove-Item Env:COMP_WORDS
63
+ Remove-Item Env:COMP_CWORD
64
+ Remove-Item Env:PIP_AUTO_COMPLETE
65
+ }}
66
+ elseif (Test-Path Function:\\_pip_completeBackup) {{
67
+ # Fall back on existing tab expansion
68
+ _pip_completeBackup $line $lastWord
69
+ }}
70
+ }}
71
+ """,
72
+ }
73
+
74
+
75
+ class CompletionCommand(Command):
76
+ """A helper command to be used for command completion."""
77
+
78
+ ignore_require_venv = True
79
+
80
+ def add_options(self) -> None:
81
+ self.cmd_opts.add_option(
82
+ "--bash",
83
+ "-b",
84
+ action="store_const",
85
+ const="bash",
86
+ dest="shell",
87
+ help="Emit completion code for bash",
88
+ )
89
+ self.cmd_opts.add_option(
90
+ "--zsh",
91
+ "-z",
92
+ action="store_const",
93
+ const="zsh",
94
+ dest="shell",
95
+ help="Emit completion code for zsh",
96
+ )
97
+ self.cmd_opts.add_option(
98
+ "--fish",
99
+ "-f",
100
+ action="store_const",
101
+ const="fish",
102
+ dest="shell",
103
+ help="Emit completion code for fish",
104
+ )
105
+ self.cmd_opts.add_option(
106
+ "--powershell",
107
+ "-p",
108
+ action="store_const",
109
+ const="powershell",
110
+ dest="shell",
111
+ help="Emit completion code for powershell",
112
+ )
113
+
114
+ self.parser.insert_option_group(0, self.cmd_opts)
115
+
116
+ def run(self, options: Values, args: List[str]) -> int:
117
+ """Prints the completion code of the given shell"""
118
+ shells = COMPLETION_SCRIPTS.keys()
119
+ shell_options = ["--" + shell for shell in sorted(shells)]
120
+ if options.shell in shells:
121
+ script = textwrap.dedent(
122
+ COMPLETION_SCRIPTS.get(options.shell, "").format(prog=get_prog())
123
+ )
124
+ print(BASE_COMPLETION.format(script=script, shell=options.shell))
125
+ return SUCCESS
126
+ else:
127
+ sys.stderr.write(
128
+ "ERROR: You must pass {}\n".format(" or ".join(shell_options))
129
+ )
130
+ return SUCCESS
.venv/lib/python3.11/site-packages/pip/_internal/commands/configuration.py ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import os
3
+ import subprocess
4
+ from optparse import Values
5
+ from typing import Any, List, Optional
6
+
7
+ from pip._internal.cli.base_command import Command
8
+ from pip._internal.cli.status_codes import ERROR, SUCCESS
9
+ from pip._internal.configuration import (
10
+ Configuration,
11
+ Kind,
12
+ get_configuration_files,
13
+ kinds,
14
+ )
15
+ from pip._internal.exceptions import PipError
16
+ from pip._internal.utils.logging import indent_log
17
+ from pip._internal.utils.misc import get_prog, write_output
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ class ConfigurationCommand(Command):
23
+ """
24
+ Manage local and global configuration.
25
+
26
+ Subcommands:
27
+
28
+ - list: List the active configuration (or from the file specified)
29
+ - edit: Edit the configuration file in an editor
30
+ - get: Get the value associated with command.option
31
+ - set: Set the command.option=value
32
+ - unset: Unset the value associated with command.option
33
+ - debug: List the configuration files and values defined under them
34
+
35
+ Configuration keys should be dot separated command and option name,
36
+ with the special prefix "global" affecting any command. For example,
37
+ "pip config set global.index-url https://example.org/" would configure
38
+ the index url for all commands, but "pip config set download.timeout 10"
39
+ would configure a 10 second timeout only for "pip download" commands.
40
+
41
+ If none of --user, --global and --site are passed, a virtual
42
+ environment configuration file is used if one is active and the file
43
+ exists. Otherwise, all modifications happen to the user file by
44
+ default.
45
+ """
46
+
47
+ ignore_require_venv = True
48
+ usage = """
49
+ %prog [<file-option>] list
50
+ %prog [<file-option>] [--editor <editor-path>] edit
51
+
52
+ %prog [<file-option>] get command.option
53
+ %prog [<file-option>] set command.option value
54
+ %prog [<file-option>] unset command.option
55
+ %prog [<file-option>] debug
56
+ """
57
+
58
+ def add_options(self) -> None:
59
+ self.cmd_opts.add_option(
60
+ "--editor",
61
+ dest="editor",
62
+ action="store",
63
+ default=None,
64
+ help=(
65
+ "Editor to use to edit the file. Uses VISUAL or EDITOR "
66
+ "environment variables if not provided."
67
+ ),
68
+ )
69
+
70
+ self.cmd_opts.add_option(
71
+ "--global",
72
+ dest="global_file",
73
+ action="store_true",
74
+ default=False,
75
+ help="Use the system-wide configuration file only",
76
+ )
77
+
78
+ self.cmd_opts.add_option(
79
+ "--user",
80
+ dest="user_file",
81
+ action="store_true",
82
+ default=False,
83
+ help="Use the user configuration file only",
84
+ )
85
+
86
+ self.cmd_opts.add_option(
87
+ "--site",
88
+ dest="site_file",
89
+ action="store_true",
90
+ default=False,
91
+ help="Use the current environment configuration file only",
92
+ )
93
+
94
+ self.parser.insert_option_group(0, self.cmd_opts)
95
+
96
+ def run(self, options: Values, args: List[str]) -> int:
97
+ handlers = {
98
+ "list": self.list_values,
99
+ "edit": self.open_in_editor,
100
+ "get": self.get_name,
101
+ "set": self.set_name_value,
102
+ "unset": self.unset_name,
103
+ "debug": self.list_config_values,
104
+ }
105
+
106
+ # Determine action
107
+ if not args or args[0] not in handlers:
108
+ logger.error(
109
+ "Need an action (%s) to perform.",
110
+ ", ".join(sorted(handlers)),
111
+ )
112
+ return ERROR
113
+
114
+ action = args[0]
115
+
116
+ # Determine which configuration files are to be loaded
117
+ # Depends on whether the command is modifying.
118
+ try:
119
+ load_only = self._determine_file(
120
+ options, need_value=(action in ["get", "set", "unset", "edit"])
121
+ )
122
+ except PipError as e:
123
+ logger.error(e.args[0])
124
+ return ERROR
125
+
126
+ # Load a new configuration
127
+ self.configuration = Configuration(
128
+ isolated=options.isolated_mode, load_only=load_only
129
+ )
130
+ self.configuration.load()
131
+
132
+ # Error handling happens here, not in the action-handlers.
133
+ try:
134
+ handlers[action](options, args[1:])
135
+ except PipError as e:
136
+ logger.error(e.args[0])
137
+ return ERROR
138
+
139
+ return SUCCESS
140
+
141
+ def _determine_file(self, options: Values, need_value: bool) -> Optional[Kind]:
142
+ file_options = [
143
+ key
144
+ for key, value in (
145
+ (kinds.USER, options.user_file),
146
+ (kinds.GLOBAL, options.global_file),
147
+ (kinds.SITE, options.site_file),
148
+ )
149
+ if value
150
+ ]
151
+
152
+ if not file_options:
153
+ if not need_value:
154
+ return None
155
+ # Default to user, unless there's a site file.
156
+ elif any(
157
+ os.path.exists(site_config_file)
158
+ for site_config_file in get_configuration_files()[kinds.SITE]
159
+ ):
160
+ return kinds.SITE
161
+ else:
162
+ return kinds.USER
163
+ elif len(file_options) == 1:
164
+ return file_options[0]
165
+
166
+ raise PipError(
167
+ "Need exactly one file to operate upon "
168
+ "(--user, --site, --global) to perform."
169
+ )
170
+
171
+ def list_values(self, options: Values, args: List[str]) -> None:
172
+ self._get_n_args(args, "list", n=0)
173
+
174
+ for key, value in sorted(self.configuration.items()):
175
+ write_output("%s=%r", key, value)
176
+
177
+ def get_name(self, options: Values, args: List[str]) -> None:
178
+ key = self._get_n_args(args, "get [name]", n=1)
179
+ value = self.configuration.get_value(key)
180
+
181
+ write_output("%s", value)
182
+
183
+ def set_name_value(self, options: Values, args: List[str]) -> None:
184
+ key, value = self._get_n_args(args, "set [name] [value]", n=2)
185
+ self.configuration.set_value(key, value)
186
+
187
+ self._save_configuration()
188
+
189
+ def unset_name(self, options: Values, args: List[str]) -> None:
190
+ key = self._get_n_args(args, "unset [name]", n=1)
191
+ self.configuration.unset_value(key)
192
+
193
+ self._save_configuration()
194
+
195
+ def list_config_values(self, options: Values, args: List[str]) -> None:
196
+ """List config key-value pairs across different config files"""
197
+ self._get_n_args(args, "debug", n=0)
198
+
199
+ self.print_env_var_values()
200
+ # Iterate over config files and print if they exist, and the
201
+ # key-value pairs present in them if they do
202
+ for variant, files in sorted(self.configuration.iter_config_files()):
203
+ write_output("%s:", variant)
204
+ for fname in files:
205
+ with indent_log():
206
+ file_exists = os.path.exists(fname)
207
+ write_output("%s, exists: %r", fname, file_exists)
208
+ if file_exists:
209
+ self.print_config_file_values(variant)
210
+
211
+ def print_config_file_values(self, variant: Kind) -> None:
212
+ """Get key-value pairs from the file of a variant"""
213
+ for name, value in self.configuration.get_values_in_config(variant).items():
214
+ with indent_log():
215
+ write_output("%s: %s", name, value)
216
+
217
+ def print_env_var_values(self) -> None:
218
+ """Get key-values pairs present as environment variables"""
219
+ write_output("%s:", "env_var")
220
+ with indent_log():
221
+ for key, value in sorted(self.configuration.get_environ_vars()):
222
+ env_var = f"PIP_{key.upper()}"
223
+ write_output("%s=%r", env_var, value)
224
+
225
+ def open_in_editor(self, options: Values, args: List[str]) -> None:
226
+ editor = self._determine_editor(options)
227
+
228
+ fname = self.configuration.get_file_to_edit()
229
+ if fname is None:
230
+ raise PipError("Could not determine appropriate file.")
231
+ elif '"' in fname:
232
+ # This shouldn't happen, unless we see a username like that.
233
+ # If that happens, we'd appreciate a pull request fixing this.
234
+ raise PipError(
235
+ f'Can not open an editor for a file name containing "\n{fname}'
236
+ )
237
+
238
+ try:
239
+ subprocess.check_call(f'{editor} "{fname}"', shell=True)
240
+ except FileNotFoundError as e:
241
+ if not e.filename:
242
+ e.filename = editor
243
+ raise
244
+ except subprocess.CalledProcessError as e:
245
+ raise PipError(f"Editor Subprocess exited with exit code {e.returncode}")
246
+
247
+ def _get_n_args(self, args: List[str], example: str, n: int) -> Any:
248
+ """Helper to make sure the command got the right number of arguments"""
249
+ if len(args) != n:
250
+ msg = (
251
+ f"Got unexpected number of arguments, expected {n}. "
252
+ f'(example: "{get_prog()} config {example}")'
253
+ )
254
+ raise PipError(msg)
255
+
256
+ if n == 1:
257
+ return args[0]
258
+ else:
259
+ return args
260
+
261
+ def _save_configuration(self) -> None:
262
+ # We successfully ran a modifying command. Need to save the
263
+ # configuration.
264
+ try:
265
+ self.configuration.save()
266
+ except Exception:
267
+ logger.exception(
268
+ "Unable to save configuration. Please report this as a bug."
269
+ )
270
+ raise PipError("Internal Error.")
271
+
272
+ def _determine_editor(self, options: Values) -> str:
273
+ if options.editor is not None:
274
+ return options.editor
275
+ elif "VISUAL" in os.environ:
276
+ return os.environ["VISUAL"]
277
+ elif "EDITOR" in os.environ:
278
+ return os.environ["EDITOR"]
279
+ else:
280
+ raise PipError("Could not determine editor to use.")
.venv/lib/python3.11/site-packages/pip/_internal/commands/debug.py ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import importlib.resources
2
+ import locale
3
+ import logging
4
+ import os
5
+ import sys
6
+ from optparse import Values
7
+ from types import ModuleType
8
+ from typing import Any, Dict, List, Optional
9
+
10
+ import pip._vendor
11
+ from pip._vendor.certifi import where
12
+ from pip._vendor.packaging.version import parse as parse_version
13
+
14
+ from pip._internal.cli import cmdoptions
15
+ from pip._internal.cli.base_command import Command
16
+ from pip._internal.cli.cmdoptions import make_target_python
17
+ from pip._internal.cli.status_codes import SUCCESS
18
+ from pip._internal.configuration import Configuration
19
+ from pip._internal.metadata import get_environment
20
+ from pip._internal.utils.logging import indent_log
21
+ from pip._internal.utils.misc import get_pip_version
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ def show_value(name: str, value: Any) -> None:
27
+ logger.info("%s: %s", name, value)
28
+
29
+
30
+ def show_sys_implementation() -> None:
31
+ logger.info("sys.implementation:")
32
+ implementation_name = sys.implementation.name
33
+ with indent_log():
34
+ show_value("name", implementation_name)
35
+
36
+
37
+ def create_vendor_txt_map() -> Dict[str, str]:
38
+ with importlib.resources.open_text("pip._vendor", "vendor.txt") as f:
39
+ # Purge non version specifying lines.
40
+ # Also, remove any space prefix or suffixes (including comments).
41
+ lines = [
42
+ line.strip().split(" ", 1)[0] for line in f.readlines() if "==" in line
43
+ ]
44
+
45
+ # Transform into "module" -> version dict.
46
+ return dict(line.split("==", 1) for line in lines)
47
+
48
+
49
+ def get_module_from_module_name(module_name: str) -> Optional[ModuleType]:
50
+ # Module name can be uppercase in vendor.txt for some reason...
51
+ module_name = module_name.lower().replace("-", "_")
52
+ # PATCH: setuptools is actually only pkg_resources.
53
+ if module_name == "setuptools":
54
+ module_name = "pkg_resources"
55
+
56
+ try:
57
+ __import__(f"pip._vendor.{module_name}", globals(), locals(), level=0)
58
+ return getattr(pip._vendor, module_name)
59
+ except ImportError:
60
+ # We allow 'truststore' to fail to import due
61
+ # to being unavailable on Python 3.9 and earlier.
62
+ if module_name == "truststore" and sys.version_info < (3, 10):
63
+ return None
64
+ raise
65
+
66
+
67
+ def get_vendor_version_from_module(module_name: str) -> Optional[str]:
68
+ module = get_module_from_module_name(module_name)
69
+ version = getattr(module, "__version__", None)
70
+
71
+ if module and not version:
72
+ # Try to find version in debundled module info.
73
+ assert module.__file__ is not None
74
+ env = get_environment([os.path.dirname(module.__file__)])
75
+ dist = env.get_distribution(module_name)
76
+ if dist:
77
+ version = str(dist.version)
78
+
79
+ return version
80
+
81
+
82
+ def show_actual_vendor_versions(vendor_txt_versions: Dict[str, str]) -> None:
83
+ """Log the actual version and print extra info if there is
84
+ a conflict or if the actual version could not be imported.
85
+ """
86
+ for module_name, expected_version in vendor_txt_versions.items():
87
+ extra_message = ""
88
+ actual_version = get_vendor_version_from_module(module_name)
89
+ if not actual_version:
90
+ extra_message = (
91
+ " (Unable to locate actual module version, using"
92
+ " vendor.txt specified version)"
93
+ )
94
+ actual_version = expected_version
95
+ elif parse_version(actual_version) != parse_version(expected_version):
96
+ extra_message = (
97
+ " (CONFLICT: vendor.txt suggests version should"
98
+ f" be {expected_version})"
99
+ )
100
+ logger.info("%s==%s%s", module_name, actual_version, extra_message)
101
+
102
+
103
+ def show_vendor_versions() -> None:
104
+ logger.info("vendored library versions:")
105
+
106
+ vendor_txt_versions = create_vendor_txt_map()
107
+ with indent_log():
108
+ show_actual_vendor_versions(vendor_txt_versions)
109
+
110
+
111
+ def show_tags(options: Values) -> None:
112
+ tag_limit = 10
113
+
114
+ target_python = make_target_python(options)
115
+ tags = target_python.get_sorted_tags()
116
+
117
+ # Display the target options that were explicitly provided.
118
+ formatted_target = target_python.format_given()
119
+ suffix = ""
120
+ if formatted_target:
121
+ suffix = f" (target: {formatted_target})"
122
+
123
+ msg = f"Compatible tags: {len(tags)}{suffix}"
124
+ logger.info(msg)
125
+
126
+ if options.verbose < 1 and len(tags) > tag_limit:
127
+ tags_limited = True
128
+ tags = tags[:tag_limit]
129
+ else:
130
+ tags_limited = False
131
+
132
+ with indent_log():
133
+ for tag in tags:
134
+ logger.info(str(tag))
135
+
136
+ if tags_limited:
137
+ msg = f"...\n[First {tag_limit} tags shown. Pass --verbose to show all.]"
138
+ logger.info(msg)
139
+
140
+
141
+ def ca_bundle_info(config: Configuration) -> str:
142
+ levels = {key.split(".", 1)[0] for key, _ in config.items()}
143
+ if not levels:
144
+ return "Not specified"
145
+
146
+ levels_that_override_global = ["install", "wheel", "download"]
147
+ global_overriding_level = [
148
+ level for level in levels if level in levels_that_override_global
149
+ ]
150
+ if not global_overriding_level:
151
+ return "global"
152
+
153
+ if "global" in levels:
154
+ levels.remove("global")
155
+ return ", ".join(levels)
156
+
157
+
158
+ class DebugCommand(Command):
159
+ """
160
+ Display debug information.
161
+ """
162
+
163
+ usage = """
164
+ %prog <options>"""
165
+ ignore_require_venv = True
166
+
167
+ def add_options(self) -> None:
168
+ cmdoptions.add_target_python_options(self.cmd_opts)
169
+ self.parser.insert_option_group(0, self.cmd_opts)
170
+ self.parser.config.load()
171
+
172
+ def run(self, options: Values, args: List[str]) -> int:
173
+ logger.warning(
174
+ "This command is only meant for debugging. "
175
+ "Do not use this with automation for parsing and getting these "
176
+ "details, since the output and options of this command may "
177
+ "change without notice."
178
+ )
179
+ show_value("pip version", get_pip_version())
180
+ show_value("sys.version", sys.version)
181
+ show_value("sys.executable", sys.executable)
182
+ show_value("sys.getdefaultencoding", sys.getdefaultencoding())
183
+ show_value("sys.getfilesystemencoding", sys.getfilesystemencoding())
184
+ show_value(
185
+ "locale.getpreferredencoding",
186
+ locale.getpreferredencoding(),
187
+ )
188
+ show_value("sys.platform", sys.platform)
189
+ show_sys_implementation()
190
+
191
+ show_value("'cert' config value", ca_bundle_info(self.parser.config))
192
+ show_value("REQUESTS_CA_BUNDLE", os.environ.get("REQUESTS_CA_BUNDLE"))
193
+ show_value("CURL_CA_BUNDLE", os.environ.get("CURL_CA_BUNDLE"))
194
+ show_value("pip._vendor.certifi.where()", where())
195
+ show_value("pip._vendor.DEBUNDLED", pip._vendor.DEBUNDLED)
196
+
197
+ show_vendor_versions()
198
+
199
+ show_tags(options)
200
+
201
+ return SUCCESS
.venv/lib/python3.11/site-packages/pip/_internal/commands/download.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import os
3
+ from optparse import Values
4
+ from typing import List
5
+
6
+ from pip._internal.cli import cmdoptions
7
+ from pip._internal.cli.cmdoptions import make_target_python
8
+ from pip._internal.cli.req_command import RequirementCommand, with_cleanup
9
+ from pip._internal.cli.status_codes import SUCCESS
10
+ from pip._internal.operations.build.build_tracker import get_build_tracker
11
+ from pip._internal.req.req_install import check_legacy_setup_py_options
12
+ from pip._internal.utils.misc import ensure_dir, normalize_path, write_output
13
+ from pip._internal.utils.temp_dir import TempDirectory
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ class DownloadCommand(RequirementCommand):
19
+ """
20
+ Download packages from:
21
+
22
+ - PyPI (and other indexes) using requirement specifiers.
23
+ - VCS project urls.
24
+ - Local project directories.
25
+ - Local or remote source archives.
26
+
27
+ pip also supports downloading from "requirements files", which provide
28
+ an easy way to specify a whole environment to be downloaded.
29
+ """
30
+
31
+ usage = """
32
+ %prog [options] <requirement specifier> [package-index-options] ...
33
+ %prog [options] -r <requirements file> [package-index-options] ...
34
+ %prog [options] <vcs project url> ...
35
+ %prog [options] <local project path> ...
36
+ %prog [options] <archive url/path> ..."""
37
+
38
+ def add_options(self) -> None:
39
+ self.cmd_opts.add_option(cmdoptions.constraints())
40
+ self.cmd_opts.add_option(cmdoptions.requirements())
41
+ self.cmd_opts.add_option(cmdoptions.no_deps())
42
+ self.cmd_opts.add_option(cmdoptions.global_options())
43
+ self.cmd_opts.add_option(cmdoptions.no_binary())
44
+ self.cmd_opts.add_option(cmdoptions.only_binary())
45
+ self.cmd_opts.add_option(cmdoptions.prefer_binary())
46
+ self.cmd_opts.add_option(cmdoptions.src())
47
+ self.cmd_opts.add_option(cmdoptions.pre())
48
+ self.cmd_opts.add_option(cmdoptions.require_hashes())
49
+ self.cmd_opts.add_option(cmdoptions.progress_bar())
50
+ self.cmd_opts.add_option(cmdoptions.no_build_isolation())
51
+ self.cmd_opts.add_option(cmdoptions.use_pep517())
52
+ self.cmd_opts.add_option(cmdoptions.no_use_pep517())
53
+ self.cmd_opts.add_option(cmdoptions.check_build_deps())
54
+ self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
55
+
56
+ self.cmd_opts.add_option(
57
+ "-d",
58
+ "--dest",
59
+ "--destination-dir",
60
+ "--destination-directory",
61
+ dest="download_dir",
62
+ metavar="dir",
63
+ default=os.curdir,
64
+ help="Download packages into <dir>.",
65
+ )
66
+
67
+ cmdoptions.add_target_python_options(self.cmd_opts)
68
+
69
+ index_opts = cmdoptions.make_option_group(
70
+ cmdoptions.index_group,
71
+ self.parser,
72
+ )
73
+
74
+ self.parser.insert_option_group(0, index_opts)
75
+ self.parser.insert_option_group(0, self.cmd_opts)
76
+
77
+ @with_cleanup
78
+ def run(self, options: Values, args: List[str]) -> int:
79
+ options.ignore_installed = True
80
+ # editable doesn't really make sense for `pip download`, but the bowels
81
+ # of the RequirementSet code require that property.
82
+ options.editables = []
83
+
84
+ cmdoptions.check_dist_restriction(options)
85
+
86
+ options.download_dir = normalize_path(options.download_dir)
87
+ ensure_dir(options.download_dir)
88
+
89
+ session = self.get_default_session(options)
90
+
91
+ target_python = make_target_python(options)
92
+ finder = self._build_package_finder(
93
+ options=options,
94
+ session=session,
95
+ target_python=target_python,
96
+ ignore_requires_python=options.ignore_requires_python,
97
+ )
98
+
99
+ build_tracker = self.enter_context(get_build_tracker())
100
+
101
+ directory = TempDirectory(
102
+ delete=not options.no_clean,
103
+ kind="download",
104
+ globally_managed=True,
105
+ )
106
+
107
+ reqs = self.get_requirements(args, options, finder, session)
108
+ check_legacy_setup_py_options(options, reqs)
109
+
110
+ preparer = self.make_requirement_preparer(
111
+ temp_build_dir=directory,
112
+ options=options,
113
+ build_tracker=build_tracker,
114
+ session=session,
115
+ finder=finder,
116
+ download_dir=options.download_dir,
117
+ use_user_site=False,
118
+ verbosity=self.verbosity,
119
+ )
120
+
121
+ resolver = self.make_resolver(
122
+ preparer=preparer,
123
+ finder=finder,
124
+ options=options,
125
+ ignore_requires_python=options.ignore_requires_python,
126
+ use_pep517=options.use_pep517,
127
+ py_version_info=options.python_version,
128
+ )
129
+
130
+ self.trace_basic_info(finder)
131
+
132
+ requirement_set = resolver.resolve(reqs, check_supported_wheels=True)
133
+
134
+ downloaded: List[str] = []
135
+ for req in requirement_set.requirements.values():
136
+ if req.satisfied_by is None:
137
+ assert req.name is not None
138
+ preparer.save_linked_requirement(req)
139
+ downloaded.append(req.name)
140
+
141
+ preparer.prepare_linked_requirements_more(requirement_set.requirements.values())
142
+ requirement_set.warn_legacy_versions_and_specifiers()
143
+
144
+ if downloaded:
145
+ write_output("Successfully downloaded %s", " ".join(downloaded))
146
+
147
+ return SUCCESS
.venv/lib/python3.11/site-packages/pip/_internal/commands/freeze.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ from optparse import Values
3
+ from typing import AbstractSet, List
4
+
5
+ from pip._internal.cli import cmdoptions
6
+ from pip._internal.cli.base_command import Command
7
+ from pip._internal.cli.status_codes import SUCCESS
8
+ from pip._internal.operations.freeze import freeze
9
+ from pip._internal.utils.compat import stdlib_pkgs
10
+
11
+
12
+ def _should_suppress_build_backends() -> bool:
13
+ return sys.version_info < (3, 12)
14
+
15
+
16
+ def _dev_pkgs() -> AbstractSet[str]:
17
+ pkgs = {"pip"}
18
+
19
+ if _should_suppress_build_backends():
20
+ pkgs |= {"setuptools", "distribute", "wheel"}
21
+
22
+ return pkgs
23
+
24
+
25
+ class FreezeCommand(Command):
26
+ """
27
+ Output installed packages in requirements format.
28
+
29
+ packages are listed in a case-insensitive sorted order.
30
+ """
31
+
32
+ usage = """
33
+ %prog [options]"""
34
+ log_streams = ("ext://sys.stderr", "ext://sys.stderr")
35
+
36
+ def add_options(self) -> None:
37
+ self.cmd_opts.add_option(
38
+ "-r",
39
+ "--requirement",
40
+ dest="requirements",
41
+ action="append",
42
+ default=[],
43
+ metavar="file",
44
+ help=(
45
+ "Use the order in the given requirements file and its "
46
+ "comments when generating output. This option can be "
47
+ "used multiple times."
48
+ ),
49
+ )
50
+ self.cmd_opts.add_option(
51
+ "-l",
52
+ "--local",
53
+ dest="local",
54
+ action="store_true",
55
+ default=False,
56
+ help=(
57
+ "If in a virtualenv that has global access, do not output "
58
+ "globally-installed packages."
59
+ ),
60
+ )
61
+ self.cmd_opts.add_option(
62
+ "--user",
63
+ dest="user",
64
+ action="store_true",
65
+ default=False,
66
+ help="Only output packages installed in user-site.",
67
+ )
68
+ self.cmd_opts.add_option(cmdoptions.list_path())
69
+ self.cmd_opts.add_option(
70
+ "--all",
71
+ dest="freeze_all",
72
+ action="store_true",
73
+ help=(
74
+ "Do not skip these packages in the output:"
75
+ " {}".format(", ".join(_dev_pkgs()))
76
+ ),
77
+ )
78
+ self.cmd_opts.add_option(
79
+ "--exclude-editable",
80
+ dest="exclude_editable",
81
+ action="store_true",
82
+ help="Exclude editable package from output.",
83
+ )
84
+ self.cmd_opts.add_option(cmdoptions.list_exclude())
85
+
86
+ self.parser.insert_option_group(0, self.cmd_opts)
87
+
88
+ def run(self, options: Values, args: List[str]) -> int:
89
+ skip = set(stdlib_pkgs)
90
+ if not options.freeze_all:
91
+ skip.update(_dev_pkgs())
92
+
93
+ if options.excludes:
94
+ skip.update(options.excludes)
95
+
96
+ cmdoptions.check_list_path_option(options)
97
+
98
+ for line in freeze(
99
+ requirement=options.requirements,
100
+ local_only=options.local,
101
+ user_only=options.user,
102
+ paths=options.path,
103
+ isolated=options.isolated_mode,
104
+ skip=skip,
105
+ exclude_editable=options.exclude_editable,
106
+ ):
107
+ sys.stdout.write(line + "\n")
108
+ return SUCCESS
.venv/lib/python3.11/site-packages/pip/_internal/commands/hash.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import hashlib
2
+ import logging
3
+ import sys
4
+ from optparse import Values
5
+ from typing import List
6
+
7
+ from pip._internal.cli.base_command import Command
8
+ from pip._internal.cli.status_codes import ERROR, SUCCESS
9
+ from pip._internal.utils.hashes import FAVORITE_HASH, STRONG_HASHES
10
+ from pip._internal.utils.misc import read_chunks, write_output
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ class HashCommand(Command):
16
+ """
17
+ Compute a hash of a local package archive.
18
+
19
+ These can be used with --hash in a requirements file to do repeatable
20
+ installs.
21
+ """
22
+
23
+ usage = "%prog [options] <file> ..."
24
+ ignore_require_venv = True
25
+
26
+ def add_options(self) -> None:
27
+ self.cmd_opts.add_option(
28
+ "-a",
29
+ "--algorithm",
30
+ dest="algorithm",
31
+ choices=STRONG_HASHES,
32
+ action="store",
33
+ default=FAVORITE_HASH,
34
+ help="The hash algorithm to use: one of {}".format(
35
+ ", ".join(STRONG_HASHES)
36
+ ),
37
+ )
38
+ self.parser.insert_option_group(0, self.cmd_opts)
39
+
40
+ def run(self, options: Values, args: List[str]) -> int:
41
+ if not args:
42
+ self.parser.print_usage(sys.stderr)
43
+ return ERROR
44
+
45
+ algorithm = options.algorithm
46
+ for path in args:
47
+ write_output(
48
+ "%s:\n--hash=%s:%s", path, algorithm, _hash_of_file(path, algorithm)
49
+ )
50
+ return SUCCESS
51
+
52
+
53
+ def _hash_of_file(path: str, algorithm: str) -> str:
54
+ """Return the hash digest of a file."""
55
+ with open(path, "rb") as archive:
56
+ hash = hashlib.new(algorithm)
57
+ for chunk in read_chunks(archive):
58
+ hash.update(chunk)
59
+ return hash.hexdigest()
.venv/lib/python3.11/site-packages/pip/_internal/commands/help.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from optparse import Values
2
+ from typing import List
3
+
4
+ from pip._internal.cli.base_command import Command
5
+ from pip._internal.cli.status_codes import SUCCESS
6
+ from pip._internal.exceptions import CommandError
7
+
8
+
9
+ class HelpCommand(Command):
10
+ """Show help for commands"""
11
+
12
+ usage = """
13
+ %prog <command>"""
14
+ ignore_require_venv = True
15
+
16
+ def run(self, options: Values, args: List[str]) -> int:
17
+ from pip._internal.commands import (
18
+ commands_dict,
19
+ create_command,
20
+ get_similar_commands,
21
+ )
22
+
23
+ try:
24
+ # 'pip help' with no args is handled by pip.__init__.parseopt()
25
+ cmd_name = args[0] # the command we need help for
26
+ except IndexError:
27
+ return SUCCESS
28
+
29
+ if cmd_name not in commands_dict:
30
+ guess = get_similar_commands(cmd_name)
31
+
32
+ msg = [f'unknown command "{cmd_name}"']
33
+ if guess:
34
+ msg.append(f'maybe you meant "{guess}"')
35
+
36
+ raise CommandError(" - ".join(msg))
37
+
38
+ command = create_command(cmd_name)
39
+ command.parser.print_help()
40
+
41
+ return SUCCESS
.venv/lib/python3.11/site-packages/pip/_internal/commands/index.py ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ from optparse import Values
3
+ from typing import Any, Iterable, List, Optional, Union
4
+
5
+ from pip._vendor.packaging.version import LegacyVersion, Version
6
+
7
+ from pip._internal.cli import cmdoptions
8
+ from pip._internal.cli.req_command import IndexGroupCommand
9
+ from pip._internal.cli.status_codes import ERROR, SUCCESS
10
+ from pip._internal.commands.search import print_dist_installation_info
11
+ from pip._internal.exceptions import CommandError, DistributionNotFound, PipError
12
+ from pip._internal.index.collector import LinkCollector
13
+ from pip._internal.index.package_finder import PackageFinder
14
+ from pip._internal.models.selection_prefs import SelectionPreferences
15
+ from pip._internal.models.target_python import TargetPython
16
+ from pip._internal.network.session import PipSession
17
+ from pip._internal.utils.misc import write_output
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ class IndexCommand(IndexGroupCommand):
23
+ """
24
+ Inspect information available from package indexes.
25
+ """
26
+
27
+ ignore_require_venv = True
28
+ usage = """
29
+ %prog versions <package>
30
+ """
31
+
32
+ def add_options(self) -> None:
33
+ cmdoptions.add_target_python_options(self.cmd_opts)
34
+
35
+ self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
36
+ self.cmd_opts.add_option(cmdoptions.pre())
37
+ self.cmd_opts.add_option(cmdoptions.no_binary())
38
+ self.cmd_opts.add_option(cmdoptions.only_binary())
39
+
40
+ index_opts = cmdoptions.make_option_group(
41
+ cmdoptions.index_group,
42
+ self.parser,
43
+ )
44
+
45
+ self.parser.insert_option_group(0, index_opts)
46
+ self.parser.insert_option_group(0, self.cmd_opts)
47
+
48
+ def run(self, options: Values, args: List[str]) -> int:
49
+ handlers = {
50
+ "versions": self.get_available_package_versions,
51
+ }
52
+
53
+ logger.warning(
54
+ "pip index is currently an experimental command. "
55
+ "It may be removed/changed in a future release "
56
+ "without prior warning."
57
+ )
58
+
59
+ # Determine action
60
+ if not args or args[0] not in handlers:
61
+ logger.error(
62
+ "Need an action (%s) to perform.",
63
+ ", ".join(sorted(handlers)),
64
+ )
65
+ return ERROR
66
+
67
+ action = args[0]
68
+
69
+ # Error handling happens here, not in the action-handlers.
70
+ try:
71
+ handlers[action](options, args[1:])
72
+ except PipError as e:
73
+ logger.error(e.args[0])
74
+ return ERROR
75
+
76
+ return SUCCESS
77
+
78
+ def _build_package_finder(
79
+ self,
80
+ options: Values,
81
+ session: PipSession,
82
+ target_python: Optional[TargetPython] = None,
83
+ ignore_requires_python: Optional[bool] = None,
84
+ ) -> PackageFinder:
85
+ """
86
+ Create a package finder appropriate to the index command.
87
+ """
88
+ link_collector = LinkCollector.create(session, options=options)
89
+
90
+ # Pass allow_yanked=False to ignore yanked versions.
91
+ selection_prefs = SelectionPreferences(
92
+ allow_yanked=False,
93
+ allow_all_prereleases=options.pre,
94
+ ignore_requires_python=ignore_requires_python,
95
+ )
96
+
97
+ return PackageFinder.create(
98
+ link_collector=link_collector,
99
+ selection_prefs=selection_prefs,
100
+ target_python=target_python,
101
+ )
102
+
103
+ def get_available_package_versions(self, options: Values, args: List[Any]) -> None:
104
+ if len(args) != 1:
105
+ raise CommandError("You need to specify exactly one argument")
106
+
107
+ target_python = cmdoptions.make_target_python(options)
108
+ query = args[0]
109
+
110
+ with self._build_session(options) as session:
111
+ finder = self._build_package_finder(
112
+ options=options,
113
+ session=session,
114
+ target_python=target_python,
115
+ ignore_requires_python=options.ignore_requires_python,
116
+ )
117
+
118
+ versions: Iterable[Union[LegacyVersion, Version]] = (
119
+ candidate.version for candidate in finder.find_all_candidates(query)
120
+ )
121
+
122
+ if not options.pre:
123
+ # Remove prereleases
124
+ versions = (
125
+ version for version in versions if not version.is_prerelease
126
+ )
127
+ versions = set(versions)
128
+
129
+ if not versions:
130
+ raise DistributionNotFound(
131
+ f"No matching distribution found for {query}"
132
+ )
133
+
134
+ formatted_versions = [str(ver) for ver in sorted(versions, reverse=True)]
135
+ latest = formatted_versions[0]
136
+
137
+ write_output(f"{query} ({latest})")
138
+ write_output("Available versions: {}".format(", ".join(formatted_versions)))
139
+ print_dist_installation_info(query, latest)
.venv/lib/python3.11/site-packages/pip/_internal/commands/inspect.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ from optparse import Values
3
+ from typing import Any, Dict, List
4
+
5
+ from pip._vendor.packaging.markers import default_environment
6
+ from pip._vendor.rich import print_json
7
+
8
+ from pip import __version__
9
+ from pip._internal.cli import cmdoptions
10
+ from pip._internal.cli.req_command import Command
11
+ from pip._internal.cli.status_codes import SUCCESS
12
+ from pip._internal.metadata import BaseDistribution, get_environment
13
+ from pip._internal.utils.compat import stdlib_pkgs
14
+ from pip._internal.utils.urls import path_to_url
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class InspectCommand(Command):
20
+ """
21
+ Inspect the content of a Python environment and produce a report in JSON format.
22
+ """
23
+
24
+ ignore_require_venv = True
25
+ usage = """
26
+ %prog [options]"""
27
+
28
+ def add_options(self) -> None:
29
+ self.cmd_opts.add_option(
30
+ "--local",
31
+ action="store_true",
32
+ default=False,
33
+ help=(
34
+ "If in a virtualenv that has global access, do not list "
35
+ "globally-installed packages."
36
+ ),
37
+ )
38
+ self.cmd_opts.add_option(
39
+ "--user",
40
+ dest="user",
41
+ action="store_true",
42
+ default=False,
43
+ help="Only output packages installed in user-site.",
44
+ )
45
+ self.cmd_opts.add_option(cmdoptions.list_path())
46
+ self.parser.insert_option_group(0, self.cmd_opts)
47
+
48
+ def run(self, options: Values, args: List[str]) -> int:
49
+ cmdoptions.check_list_path_option(options)
50
+ dists = get_environment(options.path).iter_installed_distributions(
51
+ local_only=options.local,
52
+ user_only=options.user,
53
+ skip=set(stdlib_pkgs),
54
+ )
55
+ output = {
56
+ "version": "1",
57
+ "pip_version": __version__,
58
+ "installed": [self._dist_to_dict(dist) for dist in dists],
59
+ "environment": default_environment(),
60
+ # TODO tags? scheme?
61
+ }
62
+ print_json(data=output)
63
+ return SUCCESS
64
+
65
+ def _dist_to_dict(self, dist: BaseDistribution) -> Dict[str, Any]:
66
+ res: Dict[str, Any] = {
67
+ "metadata": dist.metadata_dict,
68
+ "metadata_location": dist.info_location,
69
+ }
70
+ # direct_url. Note that we don't have download_info (as in the installation
71
+ # report) since it is not recorded in installed metadata.
72
+ direct_url = dist.direct_url
73
+ if direct_url is not None:
74
+ res["direct_url"] = direct_url.to_dict()
75
+ else:
76
+ # Emulate direct_url for legacy editable installs.
77
+ editable_project_location = dist.editable_project_location
78
+ if editable_project_location is not None:
79
+ res["direct_url"] = {
80
+ "url": path_to_url(editable_project_location),
81
+ "dir_info": {
82
+ "editable": True,
83
+ },
84
+ }
85
+ # installer
86
+ installer = dist.installer
87
+ if dist.installer:
88
+ res["installer"] = installer
89
+ # requested
90
+ if dist.installed_with_dist_info:
91
+ res["requested"] = dist.requested
92
+ return res
.venv/lib/python3.11/site-packages/pip/_internal/commands/install.py ADDED
@@ -0,0 +1,774 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import errno
2
+ import json
3
+ import operator
4
+ import os
5
+ import shutil
6
+ import site
7
+ from optparse import SUPPRESS_HELP, Values
8
+ from typing import List, Optional
9
+
10
+ from pip._vendor.rich import print_json
11
+
12
+ from pip._internal.cache import WheelCache
13
+ from pip._internal.cli import cmdoptions
14
+ from pip._internal.cli.cmdoptions import make_target_python
15
+ from pip._internal.cli.req_command import (
16
+ RequirementCommand,
17
+ warn_if_run_as_root,
18
+ with_cleanup,
19
+ )
20
+ from pip._internal.cli.status_codes import ERROR, SUCCESS
21
+ from pip._internal.exceptions import CommandError, InstallationError
22
+ from pip._internal.locations import get_scheme
23
+ from pip._internal.metadata import get_environment
24
+ from pip._internal.models.installation_report import InstallationReport
25
+ from pip._internal.operations.build.build_tracker import get_build_tracker
26
+ from pip._internal.operations.check import ConflictDetails, check_install_conflicts
27
+ from pip._internal.req import install_given_reqs
28
+ from pip._internal.req.req_install import (
29
+ InstallRequirement,
30
+ check_legacy_setup_py_options,
31
+ )
32
+ from pip._internal.utils.compat import WINDOWS
33
+ from pip._internal.utils.filesystem import test_writable_dir
34
+ from pip._internal.utils.logging import getLogger
35
+ from pip._internal.utils.misc import (
36
+ check_externally_managed,
37
+ ensure_dir,
38
+ get_pip_version,
39
+ protect_pip_from_modification_on_windows,
40
+ write_output,
41
+ )
42
+ from pip._internal.utils.temp_dir import TempDirectory
43
+ from pip._internal.utils.virtualenv import (
44
+ running_under_virtualenv,
45
+ virtualenv_no_global,
46
+ )
47
+ from pip._internal.wheel_builder import build, should_build_for_install_command
48
+
49
+ logger = getLogger(__name__)
50
+
51
+
52
+ class InstallCommand(RequirementCommand):
53
+ """
54
+ Install packages from:
55
+
56
+ - PyPI (and other indexes) using requirement specifiers.
57
+ - VCS project urls.
58
+ - Local project directories.
59
+ - Local or remote source archives.
60
+
61
+ pip also supports installing from "requirements files", which provide
62
+ an easy way to specify a whole environment to be installed.
63
+ """
64
+
65
+ usage = """
66
+ %prog [options] <requirement specifier> [package-index-options] ...
67
+ %prog [options] -r <requirements file> [package-index-options] ...
68
+ %prog [options] [-e] <vcs project url> ...
69
+ %prog [options] [-e] <local project path> ...
70
+ %prog [options] <archive url/path> ..."""
71
+
72
+ def add_options(self) -> None:
73
+ self.cmd_opts.add_option(cmdoptions.requirements())
74
+ self.cmd_opts.add_option(cmdoptions.constraints())
75
+ self.cmd_opts.add_option(cmdoptions.no_deps())
76
+ self.cmd_opts.add_option(cmdoptions.pre())
77
+
78
+ self.cmd_opts.add_option(cmdoptions.editable())
79
+ self.cmd_opts.add_option(
80
+ "--dry-run",
81
+ action="store_true",
82
+ dest="dry_run",
83
+ default=False,
84
+ help=(
85
+ "Don't actually install anything, just print what would be. "
86
+ "Can be used in combination with --ignore-installed "
87
+ "to 'resolve' the requirements."
88
+ ),
89
+ )
90
+ self.cmd_opts.add_option(
91
+ "-t",
92
+ "--target",
93
+ dest="target_dir",
94
+ metavar="dir",
95
+ default=None,
96
+ help=(
97
+ "Install packages into <dir>. "
98
+ "By default this will not replace existing files/folders in "
99
+ "<dir>. Use --upgrade to replace existing packages in <dir> "
100
+ "with new versions."
101
+ ),
102
+ )
103
+ cmdoptions.add_target_python_options(self.cmd_opts)
104
+
105
+ self.cmd_opts.add_option(
106
+ "--user",
107
+ dest="use_user_site",
108
+ action="store_true",
109
+ help=(
110
+ "Install to the Python user install directory for your "
111
+ "platform. Typically ~/.local/, or %APPDATA%\\Python on "
112
+ "Windows. (See the Python documentation for site.USER_BASE "
113
+ "for full details.)"
114
+ ),
115
+ )
116
+ self.cmd_opts.add_option(
117
+ "--no-user",
118
+ dest="use_user_site",
119
+ action="store_false",
120
+ help=SUPPRESS_HELP,
121
+ )
122
+ self.cmd_opts.add_option(
123
+ "--root",
124
+ dest="root_path",
125
+ metavar="dir",
126
+ default=None,
127
+ help="Install everything relative to this alternate root directory.",
128
+ )
129
+ self.cmd_opts.add_option(
130
+ "--prefix",
131
+ dest="prefix_path",
132
+ metavar="dir",
133
+ default=None,
134
+ help=(
135
+ "Installation prefix where lib, bin and other top-level "
136
+ "folders are placed. Note that the resulting installation may "
137
+ "contain scripts and other resources which reference the "
138
+ "Python interpreter of pip, and not that of ``--prefix``. "
139
+ "See also the ``--python`` option if the intention is to "
140
+ "install packages into another (possibly pip-free) "
141
+ "environment."
142
+ ),
143
+ )
144
+
145
+ self.cmd_opts.add_option(cmdoptions.src())
146
+
147
+ self.cmd_opts.add_option(
148
+ "-U",
149
+ "--upgrade",
150
+ dest="upgrade",
151
+ action="store_true",
152
+ help=(
153
+ "Upgrade all specified packages to the newest available "
154
+ "version. The handling of dependencies depends on the "
155
+ "upgrade-strategy used."
156
+ ),
157
+ )
158
+
159
+ self.cmd_opts.add_option(
160
+ "--upgrade-strategy",
161
+ dest="upgrade_strategy",
162
+ default="only-if-needed",
163
+ choices=["only-if-needed", "eager"],
164
+ help=(
165
+ "Determines how dependency upgrading should be handled "
166
+ "[default: %default]. "
167
+ '"eager" - dependencies are upgraded regardless of '
168
+ "whether the currently installed version satisfies the "
169
+ "requirements of the upgraded package(s). "
170
+ '"only-if-needed" - are upgraded only when they do not '
171
+ "satisfy the requirements of the upgraded package(s)."
172
+ ),
173
+ )
174
+
175
+ self.cmd_opts.add_option(
176
+ "--force-reinstall",
177
+ dest="force_reinstall",
178
+ action="store_true",
179
+ help="Reinstall all packages even if they are already up-to-date.",
180
+ )
181
+
182
+ self.cmd_opts.add_option(
183
+ "-I",
184
+ "--ignore-installed",
185
+ dest="ignore_installed",
186
+ action="store_true",
187
+ help=(
188
+ "Ignore the installed packages, overwriting them. "
189
+ "This can break your system if the existing package "
190
+ "is of a different version or was installed "
191
+ "with a different package manager!"
192
+ ),
193
+ )
194
+
195
+ self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
196
+ self.cmd_opts.add_option(cmdoptions.no_build_isolation())
197
+ self.cmd_opts.add_option(cmdoptions.use_pep517())
198
+ self.cmd_opts.add_option(cmdoptions.no_use_pep517())
199
+ self.cmd_opts.add_option(cmdoptions.check_build_deps())
200
+ self.cmd_opts.add_option(cmdoptions.override_externally_managed())
201
+
202
+ self.cmd_opts.add_option(cmdoptions.config_settings())
203
+ self.cmd_opts.add_option(cmdoptions.global_options())
204
+
205
+ self.cmd_opts.add_option(
206
+ "--compile",
207
+ action="store_true",
208
+ dest="compile",
209
+ default=True,
210
+ help="Compile Python source files to bytecode",
211
+ )
212
+
213
+ self.cmd_opts.add_option(
214
+ "--no-compile",
215
+ action="store_false",
216
+ dest="compile",
217
+ help="Do not compile Python source files to bytecode",
218
+ )
219
+
220
+ self.cmd_opts.add_option(
221
+ "--no-warn-script-location",
222
+ action="store_false",
223
+ dest="warn_script_location",
224
+ default=True,
225
+ help="Do not warn when installing scripts outside PATH",
226
+ )
227
+ self.cmd_opts.add_option(
228
+ "--no-warn-conflicts",
229
+ action="store_false",
230
+ dest="warn_about_conflicts",
231
+ default=True,
232
+ help="Do not warn about broken dependencies",
233
+ )
234
+ self.cmd_opts.add_option(cmdoptions.no_binary())
235
+ self.cmd_opts.add_option(cmdoptions.only_binary())
236
+ self.cmd_opts.add_option(cmdoptions.prefer_binary())
237
+ self.cmd_opts.add_option(cmdoptions.require_hashes())
238
+ self.cmd_opts.add_option(cmdoptions.progress_bar())
239
+ self.cmd_opts.add_option(cmdoptions.root_user_action())
240
+
241
+ index_opts = cmdoptions.make_option_group(
242
+ cmdoptions.index_group,
243
+ self.parser,
244
+ )
245
+
246
+ self.parser.insert_option_group(0, index_opts)
247
+ self.parser.insert_option_group(0, self.cmd_opts)
248
+
249
+ self.cmd_opts.add_option(
250
+ "--report",
251
+ dest="json_report_file",
252
+ metavar="file",
253
+ default=None,
254
+ help=(
255
+ "Generate a JSON file describing what pip did to install "
256
+ "the provided requirements. "
257
+ "Can be used in combination with --dry-run and --ignore-installed "
258
+ "to 'resolve' the requirements. "
259
+ "When - is used as file name it writes to stdout. "
260
+ "When writing to stdout, please combine with the --quiet option "
261
+ "to avoid mixing pip logging output with JSON output."
262
+ ),
263
+ )
264
+
265
+ @with_cleanup
266
+ def run(self, options: Values, args: List[str]) -> int:
267
+ if options.use_user_site and options.target_dir is not None:
268
+ raise CommandError("Can not combine '--user' and '--target'")
269
+
270
+ # Check whether the environment we're installing into is externally
271
+ # managed, as specified in PEP 668. Specifying --root, --target, or
272
+ # --prefix disables the check, since there's no reliable way to locate
273
+ # the EXTERNALLY-MANAGED file for those cases. An exception is also
274
+ # made specifically for "--dry-run --report" for convenience.
275
+ installing_into_current_environment = (
276
+ not (options.dry_run and options.json_report_file)
277
+ and options.root_path is None
278
+ and options.target_dir is None
279
+ and options.prefix_path is None
280
+ )
281
+ if (
282
+ installing_into_current_environment
283
+ and not options.override_externally_managed
284
+ ):
285
+ check_externally_managed()
286
+
287
+ upgrade_strategy = "to-satisfy-only"
288
+ if options.upgrade:
289
+ upgrade_strategy = options.upgrade_strategy
290
+
291
+ cmdoptions.check_dist_restriction(options, check_target=True)
292
+
293
+ logger.verbose("Using %s", get_pip_version())
294
+ options.use_user_site = decide_user_install(
295
+ options.use_user_site,
296
+ prefix_path=options.prefix_path,
297
+ target_dir=options.target_dir,
298
+ root_path=options.root_path,
299
+ isolated_mode=options.isolated_mode,
300
+ )
301
+
302
+ target_temp_dir: Optional[TempDirectory] = None
303
+ target_temp_dir_path: Optional[str] = None
304
+ if options.target_dir:
305
+ options.ignore_installed = True
306
+ options.target_dir = os.path.abspath(options.target_dir)
307
+ if (
308
+ # fmt: off
309
+ os.path.exists(options.target_dir) and
310
+ not os.path.isdir(options.target_dir)
311
+ # fmt: on
312
+ ):
313
+ raise CommandError(
314
+ "Target path exists but is not a directory, will not continue."
315
+ )
316
+
317
+ # Create a target directory for using with the target option
318
+ target_temp_dir = TempDirectory(kind="target")
319
+ target_temp_dir_path = target_temp_dir.path
320
+ self.enter_context(target_temp_dir)
321
+
322
+ global_options = options.global_options or []
323
+
324
+ session = self.get_default_session(options)
325
+
326
+ target_python = make_target_python(options)
327
+ finder = self._build_package_finder(
328
+ options=options,
329
+ session=session,
330
+ target_python=target_python,
331
+ ignore_requires_python=options.ignore_requires_python,
332
+ )
333
+ build_tracker = self.enter_context(get_build_tracker())
334
+
335
+ directory = TempDirectory(
336
+ delete=not options.no_clean,
337
+ kind="install",
338
+ globally_managed=True,
339
+ )
340
+
341
+ try:
342
+ reqs = self.get_requirements(args, options, finder, session)
343
+ check_legacy_setup_py_options(options, reqs)
344
+
345
+ wheel_cache = WheelCache(options.cache_dir)
346
+
347
+ # Only when installing is it permitted to use PEP 660.
348
+ # In other circumstances (pip wheel, pip download) we generate
349
+ # regular (i.e. non editable) metadata and wheels.
350
+ for req in reqs:
351
+ req.permit_editable_wheels = True
352
+
353
+ preparer = self.make_requirement_preparer(
354
+ temp_build_dir=directory,
355
+ options=options,
356
+ build_tracker=build_tracker,
357
+ session=session,
358
+ finder=finder,
359
+ use_user_site=options.use_user_site,
360
+ verbosity=self.verbosity,
361
+ )
362
+ resolver = self.make_resolver(
363
+ preparer=preparer,
364
+ finder=finder,
365
+ options=options,
366
+ wheel_cache=wheel_cache,
367
+ use_user_site=options.use_user_site,
368
+ ignore_installed=options.ignore_installed,
369
+ ignore_requires_python=options.ignore_requires_python,
370
+ force_reinstall=options.force_reinstall,
371
+ upgrade_strategy=upgrade_strategy,
372
+ use_pep517=options.use_pep517,
373
+ )
374
+
375
+ self.trace_basic_info(finder)
376
+
377
+ requirement_set = resolver.resolve(
378
+ reqs, check_supported_wheels=not options.target_dir
379
+ )
380
+
381
+ if options.json_report_file:
382
+ report = InstallationReport(requirement_set.requirements_to_install)
383
+ if options.json_report_file == "-":
384
+ print_json(data=report.to_dict())
385
+ else:
386
+ with open(options.json_report_file, "w", encoding="utf-8") as f:
387
+ json.dump(report.to_dict(), f, indent=2, ensure_ascii=False)
388
+
389
+ if options.dry_run:
390
+ # In non dry-run mode, the legacy versions and specifiers check
391
+ # will be done as part of conflict detection.
392
+ requirement_set.warn_legacy_versions_and_specifiers()
393
+ would_install_items = sorted(
394
+ (r.metadata["name"], r.metadata["version"])
395
+ for r in requirement_set.requirements_to_install
396
+ )
397
+ if would_install_items:
398
+ write_output(
399
+ "Would install %s",
400
+ " ".join("-".join(item) for item in would_install_items),
401
+ )
402
+ return SUCCESS
403
+
404
+ try:
405
+ pip_req = requirement_set.get_requirement("pip")
406
+ except KeyError:
407
+ modifying_pip = False
408
+ else:
409
+ # If we're not replacing an already installed pip,
410
+ # we're not modifying it.
411
+ modifying_pip = pip_req.satisfied_by is None
412
+ protect_pip_from_modification_on_windows(modifying_pip=modifying_pip)
413
+
414
+ reqs_to_build = [
415
+ r
416
+ for r in requirement_set.requirements.values()
417
+ if should_build_for_install_command(r)
418
+ ]
419
+
420
+ _, build_failures = build(
421
+ reqs_to_build,
422
+ wheel_cache=wheel_cache,
423
+ verify=True,
424
+ build_options=[],
425
+ global_options=global_options,
426
+ )
427
+
428
+ if build_failures:
429
+ raise InstallationError(
430
+ "Could not build wheels for {}, which is required to "
431
+ "install pyproject.toml-based projects".format(
432
+ ", ".join(r.name for r in build_failures) # type: ignore
433
+ )
434
+ )
435
+
436
+ to_install = resolver.get_installation_order(requirement_set)
437
+
438
+ # Check for conflicts in the package set we're installing.
439
+ conflicts: Optional[ConflictDetails] = None
440
+ should_warn_about_conflicts = (
441
+ not options.ignore_dependencies and options.warn_about_conflicts
442
+ )
443
+ if should_warn_about_conflicts:
444
+ conflicts = self._determine_conflicts(to_install)
445
+
446
+ # Don't warn about script install locations if
447
+ # --target or --prefix has been specified
448
+ warn_script_location = options.warn_script_location
449
+ if options.target_dir or options.prefix_path:
450
+ warn_script_location = False
451
+
452
+ installed = install_given_reqs(
453
+ to_install,
454
+ global_options,
455
+ root=options.root_path,
456
+ home=target_temp_dir_path,
457
+ prefix=options.prefix_path,
458
+ warn_script_location=warn_script_location,
459
+ use_user_site=options.use_user_site,
460
+ pycompile=options.compile,
461
+ )
462
+
463
+ lib_locations = get_lib_location_guesses(
464
+ user=options.use_user_site,
465
+ home=target_temp_dir_path,
466
+ root=options.root_path,
467
+ prefix=options.prefix_path,
468
+ isolated=options.isolated_mode,
469
+ )
470
+ env = get_environment(lib_locations)
471
+
472
+ installed.sort(key=operator.attrgetter("name"))
473
+ items = []
474
+ for result in installed:
475
+ item = result.name
476
+ try:
477
+ installed_dist = env.get_distribution(item)
478
+ if installed_dist is not None:
479
+ item = f"{item}-{installed_dist.version}"
480
+ except Exception:
481
+ pass
482
+ items.append(item)
483
+
484
+ if conflicts is not None:
485
+ self._warn_about_conflicts(
486
+ conflicts,
487
+ resolver_variant=self.determine_resolver_variant(options),
488
+ )
489
+
490
+ installed_desc = " ".join(items)
491
+ if installed_desc:
492
+ write_output(
493
+ "Successfully installed %s",
494
+ installed_desc,
495
+ )
496
+ except OSError as error:
497
+ show_traceback = self.verbosity >= 1
498
+
499
+ message = create_os_error_message(
500
+ error,
501
+ show_traceback,
502
+ options.use_user_site,
503
+ )
504
+ logger.error(message, exc_info=show_traceback)
505
+
506
+ return ERROR
507
+
508
+ if options.target_dir:
509
+ assert target_temp_dir
510
+ self._handle_target_dir(
511
+ options.target_dir, target_temp_dir, options.upgrade
512
+ )
513
+ if options.root_user_action == "warn":
514
+ warn_if_run_as_root()
515
+ return SUCCESS
516
+
517
+ def _handle_target_dir(
518
+ self, target_dir: str, target_temp_dir: TempDirectory, upgrade: bool
519
+ ) -> None:
520
+ ensure_dir(target_dir)
521
+
522
+ # Checking both purelib and platlib directories for installed
523
+ # packages to be moved to target directory
524
+ lib_dir_list = []
525
+
526
+ # Checking both purelib and platlib directories for installed
527
+ # packages to be moved to target directory
528
+ scheme = get_scheme("", home=target_temp_dir.path)
529
+ purelib_dir = scheme.purelib
530
+ platlib_dir = scheme.platlib
531
+ data_dir = scheme.data
532
+
533
+ if os.path.exists(purelib_dir):
534
+ lib_dir_list.append(purelib_dir)
535
+ if os.path.exists(platlib_dir) and platlib_dir != purelib_dir:
536
+ lib_dir_list.append(platlib_dir)
537
+ if os.path.exists(data_dir):
538
+ lib_dir_list.append(data_dir)
539
+
540
+ for lib_dir in lib_dir_list:
541
+ for item in os.listdir(lib_dir):
542
+ if lib_dir == data_dir:
543
+ ddir = os.path.join(data_dir, item)
544
+ if any(s.startswith(ddir) for s in lib_dir_list[:-1]):
545
+ continue
546
+ target_item_dir = os.path.join(target_dir, item)
547
+ if os.path.exists(target_item_dir):
548
+ if not upgrade:
549
+ logger.warning(
550
+ "Target directory %s already exists. Specify "
551
+ "--upgrade to force replacement.",
552
+ target_item_dir,
553
+ )
554
+ continue
555
+ if os.path.islink(target_item_dir):
556
+ logger.warning(
557
+ "Target directory %s already exists and is "
558
+ "a link. pip will not automatically replace "
559
+ "links, please remove if replacement is "
560
+ "desired.",
561
+ target_item_dir,
562
+ )
563
+ continue
564
+ if os.path.isdir(target_item_dir):
565
+ shutil.rmtree(target_item_dir)
566
+ else:
567
+ os.remove(target_item_dir)
568
+
569
+ shutil.move(os.path.join(lib_dir, item), target_item_dir)
570
+
571
+ def _determine_conflicts(
572
+ self, to_install: List[InstallRequirement]
573
+ ) -> Optional[ConflictDetails]:
574
+ try:
575
+ return check_install_conflicts(to_install)
576
+ except Exception:
577
+ logger.exception(
578
+ "Error while checking for conflicts. Please file an issue on "
579
+ "pip's issue tracker: https://github.com/pypa/pip/issues/new"
580
+ )
581
+ return None
582
+
583
+ def _warn_about_conflicts(
584
+ self, conflict_details: ConflictDetails, resolver_variant: str
585
+ ) -> None:
586
+ package_set, (missing, conflicting) = conflict_details
587
+ if not missing and not conflicting:
588
+ return
589
+
590
+ parts: List[str] = []
591
+ if resolver_variant == "legacy":
592
+ parts.append(
593
+ "pip's legacy dependency resolver does not consider dependency "
594
+ "conflicts when selecting packages. This behaviour is the "
595
+ "source of the following dependency conflicts."
596
+ )
597
+ else:
598
+ assert resolver_variant == "resolvelib"
599
+ parts.append(
600
+ "pip's dependency resolver does not currently take into account "
601
+ "all the packages that are installed. This behaviour is the "
602
+ "source of the following dependency conflicts."
603
+ )
604
+
605
+ # NOTE: There is some duplication here, with commands/check.py
606
+ for project_name in missing:
607
+ version = package_set[project_name][0]
608
+ for dependency in missing[project_name]:
609
+ message = (
610
+ f"{project_name} {version} requires {dependency[1]}, "
611
+ "which is not installed."
612
+ )
613
+ parts.append(message)
614
+
615
+ for project_name in conflicting:
616
+ version = package_set[project_name][0]
617
+ for dep_name, dep_version, req in conflicting[project_name]:
618
+ message = (
619
+ "{name} {version} requires {requirement}, but {you} have "
620
+ "{dep_name} {dep_version} which is incompatible."
621
+ ).format(
622
+ name=project_name,
623
+ version=version,
624
+ requirement=req,
625
+ dep_name=dep_name,
626
+ dep_version=dep_version,
627
+ you=("you" if resolver_variant == "resolvelib" else "you'll"),
628
+ )
629
+ parts.append(message)
630
+
631
+ logger.critical("\n".join(parts))
632
+
633
+
634
+ def get_lib_location_guesses(
635
+ user: bool = False,
636
+ home: Optional[str] = None,
637
+ root: Optional[str] = None,
638
+ isolated: bool = False,
639
+ prefix: Optional[str] = None,
640
+ ) -> List[str]:
641
+ scheme = get_scheme(
642
+ "",
643
+ user=user,
644
+ home=home,
645
+ root=root,
646
+ isolated=isolated,
647
+ prefix=prefix,
648
+ )
649
+ return [scheme.purelib, scheme.platlib]
650
+
651
+
652
+ def site_packages_writable(root: Optional[str], isolated: bool) -> bool:
653
+ return all(
654
+ test_writable_dir(d)
655
+ for d in set(get_lib_location_guesses(root=root, isolated=isolated))
656
+ )
657
+
658
+
659
+ def decide_user_install(
660
+ use_user_site: Optional[bool],
661
+ prefix_path: Optional[str] = None,
662
+ target_dir: Optional[str] = None,
663
+ root_path: Optional[str] = None,
664
+ isolated_mode: bool = False,
665
+ ) -> bool:
666
+ """Determine whether to do a user install based on the input options.
667
+
668
+ If use_user_site is False, no additional checks are done.
669
+ If use_user_site is True, it is checked for compatibility with other
670
+ options.
671
+ If use_user_site is None, the default behaviour depends on the environment,
672
+ which is provided by the other arguments.
673
+ """
674
+ # In some cases (config from tox), use_user_site can be set to an integer
675
+ # rather than a bool, which 'use_user_site is False' wouldn't catch.
676
+ if (use_user_site is not None) and (not use_user_site):
677
+ logger.debug("Non-user install by explicit request")
678
+ return False
679
+
680
+ if use_user_site:
681
+ if prefix_path:
682
+ raise CommandError(
683
+ "Can not combine '--user' and '--prefix' as they imply "
684
+ "different installation locations"
685
+ )
686
+ if virtualenv_no_global():
687
+ raise InstallationError(
688
+ "Can not perform a '--user' install. User site-packages "
689
+ "are not visible in this virtualenv."
690
+ )
691
+ logger.debug("User install by explicit request")
692
+ return True
693
+
694
+ # If we are here, user installs have not been explicitly requested/avoided
695
+ assert use_user_site is None
696
+
697
+ # user install incompatible with --prefix/--target
698
+ if prefix_path or target_dir:
699
+ logger.debug("Non-user install due to --prefix or --target option")
700
+ return False
701
+
702
+ # If user installs are not enabled, choose a non-user install
703
+ if not site.ENABLE_USER_SITE:
704
+ logger.debug("Non-user install because user site-packages disabled")
705
+ return False
706
+
707
+ # If we have permission for a non-user install, do that,
708
+ # otherwise do a user install.
709
+ if site_packages_writable(root=root_path, isolated=isolated_mode):
710
+ logger.debug("Non-user install because site-packages writeable")
711
+ return False
712
+
713
+ logger.info(
714
+ "Defaulting to user installation because normal site-packages "
715
+ "is not writeable"
716
+ )
717
+ return True
718
+
719
+
720
+ def create_os_error_message(
721
+ error: OSError, show_traceback: bool, using_user_site: bool
722
+ ) -> str:
723
+ """Format an error message for an OSError
724
+
725
+ It may occur anytime during the execution of the install command.
726
+ """
727
+ parts = []
728
+
729
+ # Mention the error if we are not going to show a traceback
730
+ parts.append("Could not install packages due to an OSError")
731
+ if not show_traceback:
732
+ parts.append(": ")
733
+ parts.append(str(error))
734
+ else:
735
+ parts.append(".")
736
+
737
+ # Spilt the error indication from a helper message (if any)
738
+ parts[-1] += "\n"
739
+
740
+ # Suggest useful actions to the user:
741
+ # (1) using user site-packages or (2) verifying the permissions
742
+ if error.errno == errno.EACCES:
743
+ user_option_part = "Consider using the `--user` option"
744
+ permissions_part = "Check the permissions"
745
+
746
+ if not running_under_virtualenv() and not using_user_site:
747
+ parts.extend(
748
+ [
749
+ user_option_part,
750
+ " or ",
751
+ permissions_part.lower(),
752
+ ]
753
+ )
754
+ else:
755
+ parts.append(permissions_part)
756
+ parts.append(".\n")
757
+
758
+ # Suggest the user to enable Long Paths if path length is
759
+ # more than 260
760
+ if (
761
+ WINDOWS
762
+ and error.errno == errno.ENOENT
763
+ and error.filename
764
+ and len(error.filename) > 260
765
+ ):
766
+ parts.append(
767
+ "HINT: This error might have occurred since "
768
+ "this system does not have Windows Long Path "
769
+ "support enabled. You can find information on "
770
+ "how to enable this at "
771
+ "https://pip.pypa.io/warnings/enable-long-paths\n"
772
+ )
773
+
774
+ return "".join(parts).strip() + "\n"
.venv/lib/python3.11/site-packages/pip/_internal/commands/list.py ADDED
@@ -0,0 +1,368 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import logging
3
+ from optparse import Values
4
+ from typing import TYPE_CHECKING, Generator, List, Optional, Sequence, Tuple, cast
5
+
6
+ from pip._vendor.packaging.utils import canonicalize_name
7
+
8
+ from pip._internal.cli import cmdoptions
9
+ from pip._internal.cli.req_command import IndexGroupCommand
10
+ from pip._internal.cli.status_codes import SUCCESS
11
+ from pip._internal.exceptions import CommandError
12
+ from pip._internal.index.collector import LinkCollector
13
+ from pip._internal.index.package_finder import PackageFinder
14
+ from pip._internal.metadata import BaseDistribution, get_environment
15
+ from pip._internal.models.selection_prefs import SelectionPreferences
16
+ from pip._internal.network.session import PipSession
17
+ from pip._internal.utils.compat import stdlib_pkgs
18
+ from pip._internal.utils.misc import tabulate, write_output
19
+
20
+ if TYPE_CHECKING:
21
+ from pip._internal.metadata.base import DistributionVersion
22
+
23
+ class _DistWithLatestInfo(BaseDistribution):
24
+ """Give the distribution object a couple of extra fields.
25
+
26
+ These will be populated during ``get_outdated()``. This is dirty but
27
+ makes the rest of the code much cleaner.
28
+ """
29
+
30
+ latest_version: DistributionVersion
31
+ latest_filetype: str
32
+
33
+ _ProcessedDists = Sequence[_DistWithLatestInfo]
34
+
35
+
36
+ logger = logging.getLogger(__name__)
37
+
38
+
39
+ class ListCommand(IndexGroupCommand):
40
+ """
41
+ List installed packages, including editables.
42
+
43
+ Packages are listed in a case-insensitive sorted order.
44
+ """
45
+
46
+ ignore_require_venv = True
47
+ usage = """
48
+ %prog [options]"""
49
+
50
+ def add_options(self) -> None:
51
+ self.cmd_opts.add_option(
52
+ "-o",
53
+ "--outdated",
54
+ action="store_true",
55
+ default=False,
56
+ help="List outdated packages",
57
+ )
58
+ self.cmd_opts.add_option(
59
+ "-u",
60
+ "--uptodate",
61
+ action="store_true",
62
+ default=False,
63
+ help="List uptodate packages",
64
+ )
65
+ self.cmd_opts.add_option(
66
+ "-e",
67
+ "--editable",
68
+ action="store_true",
69
+ default=False,
70
+ help="List editable projects.",
71
+ )
72
+ self.cmd_opts.add_option(
73
+ "-l",
74
+ "--local",
75
+ action="store_true",
76
+ default=False,
77
+ help=(
78
+ "If in a virtualenv that has global access, do not list "
79
+ "globally-installed packages."
80
+ ),
81
+ )
82
+ self.cmd_opts.add_option(
83
+ "--user",
84
+ dest="user",
85
+ action="store_true",
86
+ default=False,
87
+ help="Only output packages installed in user-site.",
88
+ )
89
+ self.cmd_opts.add_option(cmdoptions.list_path())
90
+ self.cmd_opts.add_option(
91
+ "--pre",
92
+ action="store_true",
93
+ default=False,
94
+ help=(
95
+ "Include pre-release and development versions. By default, "
96
+ "pip only finds stable versions."
97
+ ),
98
+ )
99
+
100
+ self.cmd_opts.add_option(
101
+ "--format",
102
+ action="store",
103
+ dest="list_format",
104
+ default="columns",
105
+ choices=("columns", "freeze", "json"),
106
+ help=(
107
+ "Select the output format among: columns (default), freeze, or json. "
108
+ "The 'freeze' format cannot be used with the --outdated option."
109
+ ),
110
+ )
111
+
112
+ self.cmd_opts.add_option(
113
+ "--not-required",
114
+ action="store_true",
115
+ dest="not_required",
116
+ help="List packages that are not dependencies of installed packages.",
117
+ )
118
+
119
+ self.cmd_opts.add_option(
120
+ "--exclude-editable",
121
+ action="store_false",
122
+ dest="include_editable",
123
+ help="Exclude editable package from output.",
124
+ )
125
+ self.cmd_opts.add_option(
126
+ "--include-editable",
127
+ action="store_true",
128
+ dest="include_editable",
129
+ help="Include editable package from output.",
130
+ default=True,
131
+ )
132
+ self.cmd_opts.add_option(cmdoptions.list_exclude())
133
+ index_opts = cmdoptions.make_option_group(cmdoptions.index_group, self.parser)
134
+
135
+ self.parser.insert_option_group(0, index_opts)
136
+ self.parser.insert_option_group(0, self.cmd_opts)
137
+
138
+ def _build_package_finder(
139
+ self, options: Values, session: PipSession
140
+ ) -> PackageFinder:
141
+ """
142
+ Create a package finder appropriate to this list command.
143
+ """
144
+ link_collector = LinkCollector.create(session, options=options)
145
+
146
+ # Pass allow_yanked=False to ignore yanked versions.
147
+ selection_prefs = SelectionPreferences(
148
+ allow_yanked=False,
149
+ allow_all_prereleases=options.pre,
150
+ )
151
+
152
+ return PackageFinder.create(
153
+ link_collector=link_collector,
154
+ selection_prefs=selection_prefs,
155
+ )
156
+
157
+ def run(self, options: Values, args: List[str]) -> int:
158
+ if options.outdated and options.uptodate:
159
+ raise CommandError("Options --outdated and --uptodate cannot be combined.")
160
+
161
+ if options.outdated and options.list_format == "freeze":
162
+ raise CommandError(
163
+ "List format 'freeze' cannot be used with the --outdated option."
164
+ )
165
+
166
+ cmdoptions.check_list_path_option(options)
167
+
168
+ skip = set(stdlib_pkgs)
169
+ if options.excludes:
170
+ skip.update(canonicalize_name(n) for n in options.excludes)
171
+
172
+ packages: "_ProcessedDists" = [
173
+ cast("_DistWithLatestInfo", d)
174
+ for d in get_environment(options.path).iter_installed_distributions(
175
+ local_only=options.local,
176
+ user_only=options.user,
177
+ editables_only=options.editable,
178
+ include_editables=options.include_editable,
179
+ skip=skip,
180
+ )
181
+ ]
182
+
183
+ # get_not_required must be called firstly in order to find and
184
+ # filter out all dependencies correctly. Otherwise a package
185
+ # can't be identified as requirement because some parent packages
186
+ # could be filtered out before.
187
+ if options.not_required:
188
+ packages = self.get_not_required(packages, options)
189
+
190
+ if options.outdated:
191
+ packages = self.get_outdated(packages, options)
192
+ elif options.uptodate:
193
+ packages = self.get_uptodate(packages, options)
194
+
195
+ self.output_package_listing(packages, options)
196
+ return SUCCESS
197
+
198
+ def get_outdated(
199
+ self, packages: "_ProcessedDists", options: Values
200
+ ) -> "_ProcessedDists":
201
+ return [
202
+ dist
203
+ for dist in self.iter_packages_latest_infos(packages, options)
204
+ if dist.latest_version > dist.version
205
+ ]
206
+
207
+ def get_uptodate(
208
+ self, packages: "_ProcessedDists", options: Values
209
+ ) -> "_ProcessedDists":
210
+ return [
211
+ dist
212
+ for dist in self.iter_packages_latest_infos(packages, options)
213
+ if dist.latest_version == dist.version
214
+ ]
215
+
216
+ def get_not_required(
217
+ self, packages: "_ProcessedDists", options: Values
218
+ ) -> "_ProcessedDists":
219
+ dep_keys = {
220
+ canonicalize_name(dep.name)
221
+ for dist in packages
222
+ for dep in (dist.iter_dependencies() or ())
223
+ }
224
+
225
+ # Create a set to remove duplicate packages, and cast it to a list
226
+ # to keep the return type consistent with get_outdated and
227
+ # get_uptodate
228
+ return list({pkg for pkg in packages if pkg.canonical_name not in dep_keys})
229
+
230
+ def iter_packages_latest_infos(
231
+ self, packages: "_ProcessedDists", options: Values
232
+ ) -> Generator["_DistWithLatestInfo", None, None]:
233
+ with self._build_session(options) as session:
234
+ finder = self._build_package_finder(options, session)
235
+
236
+ def latest_info(
237
+ dist: "_DistWithLatestInfo",
238
+ ) -> Optional["_DistWithLatestInfo"]:
239
+ all_candidates = finder.find_all_candidates(dist.canonical_name)
240
+ if not options.pre:
241
+ # Remove prereleases
242
+ all_candidates = [
243
+ candidate
244
+ for candidate in all_candidates
245
+ if not candidate.version.is_prerelease
246
+ ]
247
+
248
+ evaluator = finder.make_candidate_evaluator(
249
+ project_name=dist.canonical_name,
250
+ )
251
+ best_candidate = evaluator.sort_best_candidate(all_candidates)
252
+ if best_candidate is None:
253
+ return None
254
+
255
+ remote_version = best_candidate.version
256
+ if best_candidate.link.is_wheel:
257
+ typ = "wheel"
258
+ else:
259
+ typ = "sdist"
260
+ dist.latest_version = remote_version
261
+ dist.latest_filetype = typ
262
+ return dist
263
+
264
+ for dist in map(latest_info, packages):
265
+ if dist is not None:
266
+ yield dist
267
+
268
+ def output_package_listing(
269
+ self, packages: "_ProcessedDists", options: Values
270
+ ) -> None:
271
+ packages = sorted(
272
+ packages,
273
+ key=lambda dist: dist.canonical_name,
274
+ )
275
+ if options.list_format == "columns" and packages:
276
+ data, header = format_for_columns(packages, options)
277
+ self.output_package_listing_columns(data, header)
278
+ elif options.list_format == "freeze":
279
+ for dist in packages:
280
+ if options.verbose >= 1:
281
+ write_output(
282
+ "%s==%s (%s)", dist.raw_name, dist.version, dist.location
283
+ )
284
+ else:
285
+ write_output("%s==%s", dist.raw_name, dist.version)
286
+ elif options.list_format == "json":
287
+ write_output(format_for_json(packages, options))
288
+
289
+ def output_package_listing_columns(
290
+ self, data: List[List[str]], header: List[str]
291
+ ) -> None:
292
+ # insert the header first: we need to know the size of column names
293
+ if len(data) > 0:
294
+ data.insert(0, header)
295
+
296
+ pkg_strings, sizes = tabulate(data)
297
+
298
+ # Create and add a separator.
299
+ if len(data) > 0:
300
+ pkg_strings.insert(1, " ".join("-" * x for x in sizes))
301
+
302
+ for val in pkg_strings:
303
+ write_output(val)
304
+
305
+
306
+ def format_for_columns(
307
+ pkgs: "_ProcessedDists", options: Values
308
+ ) -> Tuple[List[List[str]], List[str]]:
309
+ """
310
+ Convert the package data into something usable
311
+ by output_package_listing_columns.
312
+ """
313
+ header = ["Package", "Version"]
314
+
315
+ running_outdated = options.outdated
316
+ if running_outdated:
317
+ header.extend(["Latest", "Type"])
318
+
319
+ has_editables = any(x.editable for x in pkgs)
320
+ if has_editables:
321
+ header.append("Editable project location")
322
+
323
+ if options.verbose >= 1:
324
+ header.append("Location")
325
+ if options.verbose >= 1:
326
+ header.append("Installer")
327
+
328
+ data = []
329
+ for proj in pkgs:
330
+ # if we're working on the 'outdated' list, separate out the
331
+ # latest_version and type
332
+ row = [proj.raw_name, str(proj.version)]
333
+
334
+ if running_outdated:
335
+ row.append(str(proj.latest_version))
336
+ row.append(proj.latest_filetype)
337
+
338
+ if has_editables:
339
+ row.append(proj.editable_project_location or "")
340
+
341
+ if options.verbose >= 1:
342
+ row.append(proj.location or "")
343
+ if options.verbose >= 1:
344
+ row.append(proj.installer)
345
+
346
+ data.append(row)
347
+
348
+ return data, header
349
+
350
+
351
+ def format_for_json(packages: "_ProcessedDists", options: Values) -> str:
352
+ data = []
353
+ for dist in packages:
354
+ info = {
355
+ "name": dist.raw_name,
356
+ "version": str(dist.version),
357
+ }
358
+ if options.verbose >= 1:
359
+ info["location"] = dist.location or ""
360
+ info["installer"] = dist.installer
361
+ if options.outdated:
362
+ info["latest_version"] = str(dist.latest_version)
363
+ info["latest_filetype"] = dist.latest_filetype
364
+ editable_project_location = dist.editable_project_location
365
+ if editable_project_location:
366
+ info["editable_project_location"] = editable_project_location
367
+ data.append(info)
368
+ return json.dumps(data)
.venv/lib/python3.11/site-packages/pip/_internal/commands/search.py ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import shutil
3
+ import sys
4
+ import textwrap
5
+ import xmlrpc.client
6
+ from collections import OrderedDict
7
+ from optparse import Values
8
+ from typing import TYPE_CHECKING, Dict, List, Optional
9
+
10
+ from pip._vendor.packaging.version import parse as parse_version
11
+
12
+ from pip._internal.cli.base_command import Command
13
+ from pip._internal.cli.req_command import SessionCommandMixin
14
+ from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS
15
+ from pip._internal.exceptions import CommandError
16
+ from pip._internal.metadata import get_default_environment
17
+ from pip._internal.models.index import PyPI
18
+ from pip._internal.network.xmlrpc import PipXmlrpcTransport
19
+ from pip._internal.utils.logging import indent_log
20
+ from pip._internal.utils.misc import write_output
21
+
22
+ if TYPE_CHECKING:
23
+ from typing import TypedDict
24
+
25
+ class TransformedHit(TypedDict):
26
+ name: str
27
+ summary: str
28
+ versions: List[str]
29
+
30
+
31
+ logger = logging.getLogger(__name__)
32
+
33
+
34
+ class SearchCommand(Command, SessionCommandMixin):
35
+ """Search for PyPI packages whose name or summary contains <query>."""
36
+
37
+ usage = """
38
+ %prog [options] <query>"""
39
+ ignore_require_venv = True
40
+
41
+ def add_options(self) -> None:
42
+ self.cmd_opts.add_option(
43
+ "-i",
44
+ "--index",
45
+ dest="index",
46
+ metavar="URL",
47
+ default=PyPI.pypi_url,
48
+ help="Base URL of Python Package Index (default %default)",
49
+ )
50
+
51
+ self.parser.insert_option_group(0, self.cmd_opts)
52
+
53
+ def run(self, options: Values, args: List[str]) -> int:
54
+ if not args:
55
+ raise CommandError("Missing required argument (search query).")
56
+ query = args
57
+ pypi_hits = self.search(query, options)
58
+ hits = transform_hits(pypi_hits)
59
+
60
+ terminal_width = None
61
+ if sys.stdout.isatty():
62
+ terminal_width = shutil.get_terminal_size()[0]
63
+
64
+ print_results(hits, terminal_width=terminal_width)
65
+ if pypi_hits:
66
+ return SUCCESS
67
+ return NO_MATCHES_FOUND
68
+
69
+ def search(self, query: List[str], options: Values) -> List[Dict[str, str]]:
70
+ index_url = options.index
71
+
72
+ session = self.get_default_session(options)
73
+
74
+ transport = PipXmlrpcTransport(index_url, session)
75
+ pypi = xmlrpc.client.ServerProxy(index_url, transport)
76
+ try:
77
+ hits = pypi.search({"name": query, "summary": query}, "or")
78
+ except xmlrpc.client.Fault as fault:
79
+ message = "XMLRPC request failed [code: {code}]\n{string}".format(
80
+ code=fault.faultCode,
81
+ string=fault.faultString,
82
+ )
83
+ raise CommandError(message)
84
+ assert isinstance(hits, list)
85
+ return hits
86
+
87
+
88
+ def transform_hits(hits: List[Dict[str, str]]) -> List["TransformedHit"]:
89
+ """
90
+ The list from pypi is really a list of versions. We want a list of
91
+ packages with the list of versions stored inline. This converts the
92
+ list from pypi into one we can use.
93
+ """
94
+ packages: Dict[str, "TransformedHit"] = OrderedDict()
95
+ for hit in hits:
96
+ name = hit["name"]
97
+ summary = hit["summary"]
98
+ version = hit["version"]
99
+
100
+ if name not in packages.keys():
101
+ packages[name] = {
102
+ "name": name,
103
+ "summary": summary,
104
+ "versions": [version],
105
+ }
106
+ else:
107
+ packages[name]["versions"].append(version)
108
+
109
+ # if this is the highest version, replace summary and score
110
+ if version == highest_version(packages[name]["versions"]):
111
+ packages[name]["summary"] = summary
112
+
113
+ return list(packages.values())
114
+
115
+
116
+ def print_dist_installation_info(name: str, latest: str) -> None:
117
+ env = get_default_environment()
118
+ dist = env.get_distribution(name)
119
+ if dist is not None:
120
+ with indent_log():
121
+ if dist.version == latest:
122
+ write_output("INSTALLED: %s (latest)", dist.version)
123
+ else:
124
+ write_output("INSTALLED: %s", dist.version)
125
+ if parse_version(latest).pre:
126
+ write_output(
127
+ "LATEST: %s (pre-release; install"
128
+ " with `pip install --pre`)",
129
+ latest,
130
+ )
131
+ else:
132
+ write_output("LATEST: %s", latest)
133
+
134
+
135
+ def print_results(
136
+ hits: List["TransformedHit"],
137
+ name_column_width: Optional[int] = None,
138
+ terminal_width: Optional[int] = None,
139
+ ) -> None:
140
+ if not hits:
141
+ return
142
+ if name_column_width is None:
143
+ name_column_width = (
144
+ max(
145
+ [
146
+ len(hit["name"]) + len(highest_version(hit.get("versions", ["-"])))
147
+ for hit in hits
148
+ ]
149
+ )
150
+ + 4
151
+ )
152
+
153
+ for hit in hits:
154
+ name = hit["name"]
155
+ summary = hit["summary"] or ""
156
+ latest = highest_version(hit.get("versions", ["-"]))
157
+ if terminal_width is not None:
158
+ target_width = terminal_width - name_column_width - 5
159
+ if target_width > 10:
160
+ # wrap and indent summary to fit terminal
161
+ summary_lines = textwrap.wrap(summary, target_width)
162
+ summary = ("\n" + " " * (name_column_width + 3)).join(summary_lines)
163
+
164
+ name_latest = f"{name} ({latest})"
165
+ line = f"{name_latest:{name_column_width}} - {summary}"
166
+ try:
167
+ write_output(line)
168
+ print_dist_installation_info(name, latest)
169
+ except UnicodeEncodeError:
170
+ pass
171
+
172
+
173
+ def highest_version(versions: List[str]) -> str:
174
+ return max(versions, key=parse_version)
.venv/lib/python3.11/site-packages/pip/_internal/commands/show.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ from optparse import Values
3
+ from typing import Generator, Iterable, Iterator, List, NamedTuple, Optional
4
+
5
+ from pip._vendor.packaging.utils import canonicalize_name
6
+
7
+ from pip._internal.cli.base_command import Command
8
+ from pip._internal.cli.status_codes import ERROR, SUCCESS
9
+ from pip._internal.metadata import BaseDistribution, get_default_environment
10
+ from pip._internal.utils.misc import write_output
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ class ShowCommand(Command):
16
+ """
17
+ Show information about one or more installed packages.
18
+
19
+ The output is in RFC-compliant mail header format.
20
+ """
21
+
22
+ usage = """
23
+ %prog [options] <package> ..."""
24
+ ignore_require_venv = True
25
+
26
+ def add_options(self) -> None:
27
+ self.cmd_opts.add_option(
28
+ "-f",
29
+ "--files",
30
+ dest="files",
31
+ action="store_true",
32
+ default=False,
33
+ help="Show the full list of installed files for each package.",
34
+ )
35
+
36
+ self.parser.insert_option_group(0, self.cmd_opts)
37
+
38
+ def run(self, options: Values, args: List[str]) -> int:
39
+ if not args:
40
+ logger.warning("ERROR: Please provide a package name or names.")
41
+ return ERROR
42
+ query = args
43
+
44
+ results = search_packages_info(query)
45
+ if not print_results(
46
+ results, list_files=options.files, verbose=options.verbose
47
+ ):
48
+ return ERROR
49
+ return SUCCESS
50
+
51
+
52
+ class _PackageInfo(NamedTuple):
53
+ name: str
54
+ version: str
55
+ location: str
56
+ editable_project_location: Optional[str]
57
+ requires: List[str]
58
+ required_by: List[str]
59
+ installer: str
60
+ metadata_version: str
61
+ classifiers: List[str]
62
+ summary: str
63
+ homepage: str
64
+ project_urls: List[str]
65
+ author: str
66
+ author_email: str
67
+ license: str
68
+ entry_points: List[str]
69
+ files: Optional[List[str]]
70
+
71
+
72
+ def search_packages_info(query: List[str]) -> Generator[_PackageInfo, None, None]:
73
+ """
74
+ Gather details from installed distributions. Print distribution name,
75
+ version, location, and installed files. Installed files requires a
76
+ pip generated 'installed-files.txt' in the distributions '.egg-info'
77
+ directory.
78
+ """
79
+ env = get_default_environment()
80
+
81
+ installed = {dist.canonical_name: dist for dist in env.iter_all_distributions()}
82
+ query_names = [canonicalize_name(name) for name in query]
83
+ missing = sorted(
84
+ [name for name, pkg in zip(query, query_names) if pkg not in installed]
85
+ )
86
+ if missing:
87
+ logger.warning("Package(s) not found: %s", ", ".join(missing))
88
+
89
+ def _get_requiring_packages(current_dist: BaseDistribution) -> Iterator[str]:
90
+ return (
91
+ dist.metadata["Name"] or "UNKNOWN"
92
+ for dist in installed.values()
93
+ if current_dist.canonical_name
94
+ in {canonicalize_name(d.name) for d in dist.iter_dependencies()}
95
+ )
96
+
97
+ for query_name in query_names:
98
+ try:
99
+ dist = installed[query_name]
100
+ except KeyError:
101
+ continue
102
+
103
+ requires = sorted((req.name for req in dist.iter_dependencies()), key=str.lower)
104
+ required_by = sorted(_get_requiring_packages(dist), key=str.lower)
105
+
106
+ try:
107
+ entry_points_text = dist.read_text("entry_points.txt")
108
+ entry_points = entry_points_text.splitlines(keepends=False)
109
+ except FileNotFoundError:
110
+ entry_points = []
111
+
112
+ files_iter = dist.iter_declared_entries()
113
+ if files_iter is None:
114
+ files: Optional[List[str]] = None
115
+ else:
116
+ files = sorted(files_iter)
117
+
118
+ metadata = dist.metadata
119
+
120
+ yield _PackageInfo(
121
+ name=dist.raw_name,
122
+ version=str(dist.version),
123
+ location=dist.location or "",
124
+ editable_project_location=dist.editable_project_location,
125
+ requires=requires,
126
+ required_by=required_by,
127
+ installer=dist.installer,
128
+ metadata_version=dist.metadata_version or "",
129
+ classifiers=metadata.get_all("Classifier", []),
130
+ summary=metadata.get("Summary", ""),
131
+ homepage=metadata.get("Home-page", ""),
132
+ project_urls=metadata.get_all("Project-URL", []),
133
+ author=metadata.get("Author", ""),
134
+ author_email=metadata.get("Author-email", ""),
135
+ license=metadata.get("License", ""),
136
+ entry_points=entry_points,
137
+ files=files,
138
+ )
139
+
140
+
141
+ def print_results(
142
+ distributions: Iterable[_PackageInfo],
143
+ list_files: bool,
144
+ verbose: bool,
145
+ ) -> bool:
146
+ """
147
+ Print the information from installed distributions found.
148
+ """
149
+ results_printed = False
150
+ for i, dist in enumerate(distributions):
151
+ results_printed = True
152
+ if i > 0:
153
+ write_output("---")
154
+
155
+ write_output("Name: %s", dist.name)
156
+ write_output("Version: %s", dist.version)
157
+ write_output("Summary: %s", dist.summary)
158
+ write_output("Home-page: %s", dist.homepage)
159
+ write_output("Author: %s", dist.author)
160
+ write_output("Author-email: %s", dist.author_email)
161
+ write_output("License: %s", dist.license)
162
+ write_output("Location: %s", dist.location)
163
+ if dist.editable_project_location is not None:
164
+ write_output(
165
+ "Editable project location: %s", dist.editable_project_location
166
+ )
167
+ write_output("Requires: %s", ", ".join(dist.requires))
168
+ write_output("Required-by: %s", ", ".join(dist.required_by))
169
+
170
+ if verbose:
171
+ write_output("Metadata-Version: %s", dist.metadata_version)
172
+ write_output("Installer: %s", dist.installer)
173
+ write_output("Classifiers:")
174
+ for classifier in dist.classifiers:
175
+ write_output(" %s", classifier)
176
+ write_output("Entry-points:")
177
+ for entry in dist.entry_points:
178
+ write_output(" %s", entry.strip())
179
+ write_output("Project-URLs:")
180
+ for project_url in dist.project_urls:
181
+ write_output(" %s", project_url)
182
+ if list_files:
183
+ write_output("Files:")
184
+ if dist.files is None:
185
+ write_output("Cannot locate RECORD or installed-files.txt")
186
+ else:
187
+ for line in dist.files:
188
+ write_output(" %s", line.strip())
189
+ return results_printed
.venv/lib/python3.11/site-packages/pip/_internal/commands/uninstall.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ from optparse import Values
3
+ from typing import List
4
+
5
+ from pip._vendor.packaging.utils import canonicalize_name
6
+
7
+ from pip._internal.cli import cmdoptions
8
+ from pip._internal.cli.base_command import Command
9
+ from pip._internal.cli.req_command import SessionCommandMixin, warn_if_run_as_root
10
+ from pip._internal.cli.status_codes import SUCCESS
11
+ from pip._internal.exceptions import InstallationError
12
+ from pip._internal.req import parse_requirements
13
+ from pip._internal.req.constructors import (
14
+ install_req_from_line,
15
+ install_req_from_parsed_requirement,
16
+ )
17
+ from pip._internal.utils.misc import (
18
+ check_externally_managed,
19
+ protect_pip_from_modification_on_windows,
20
+ )
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ class UninstallCommand(Command, SessionCommandMixin):
26
+ """
27
+ Uninstall packages.
28
+
29
+ pip is able to uninstall most installed packages. Known exceptions are:
30
+
31
+ - Pure distutils packages installed with ``python setup.py install``, which
32
+ leave behind no metadata to determine what files were installed.
33
+ - Script wrappers installed by ``python setup.py develop``.
34
+ """
35
+
36
+ usage = """
37
+ %prog [options] <package> ...
38
+ %prog [options] -r <requirements file> ..."""
39
+
40
+ def add_options(self) -> None:
41
+ self.cmd_opts.add_option(
42
+ "-r",
43
+ "--requirement",
44
+ dest="requirements",
45
+ action="append",
46
+ default=[],
47
+ metavar="file",
48
+ help=(
49
+ "Uninstall all the packages listed in the given requirements "
50
+ "file. This option can be used multiple times."
51
+ ),
52
+ )
53
+ self.cmd_opts.add_option(
54
+ "-y",
55
+ "--yes",
56
+ dest="yes",
57
+ action="store_true",
58
+ help="Don't ask for confirmation of uninstall deletions.",
59
+ )
60
+ self.cmd_opts.add_option(cmdoptions.root_user_action())
61
+ self.cmd_opts.add_option(cmdoptions.override_externally_managed())
62
+ self.parser.insert_option_group(0, self.cmd_opts)
63
+
64
+ def run(self, options: Values, args: List[str]) -> int:
65
+ session = self.get_default_session(options)
66
+
67
+ reqs_to_uninstall = {}
68
+ for name in args:
69
+ req = install_req_from_line(
70
+ name,
71
+ isolated=options.isolated_mode,
72
+ )
73
+ if req.name:
74
+ reqs_to_uninstall[canonicalize_name(req.name)] = req
75
+ else:
76
+ logger.warning(
77
+ "Invalid requirement: %r ignored -"
78
+ " the uninstall command expects named"
79
+ " requirements.",
80
+ name,
81
+ )
82
+ for filename in options.requirements:
83
+ for parsed_req in parse_requirements(
84
+ filename, options=options, session=session
85
+ ):
86
+ req = install_req_from_parsed_requirement(
87
+ parsed_req, isolated=options.isolated_mode
88
+ )
89
+ if req.name:
90
+ reqs_to_uninstall[canonicalize_name(req.name)] = req
91
+ if not reqs_to_uninstall:
92
+ raise InstallationError(
93
+ f"You must give at least one requirement to {self.name} (see "
94
+ f'"pip help {self.name}")'
95
+ )
96
+
97
+ if not options.override_externally_managed:
98
+ check_externally_managed()
99
+
100
+ protect_pip_from_modification_on_windows(
101
+ modifying_pip="pip" in reqs_to_uninstall
102
+ )
103
+
104
+ for req in reqs_to_uninstall.values():
105
+ uninstall_pathset = req.uninstall(
106
+ auto_confirm=options.yes,
107
+ verbose=self.verbosity > 0,
108
+ )
109
+ if uninstall_pathset:
110
+ uninstall_pathset.commit()
111
+ if options.root_user_action == "warn":
112
+ warn_if_run_as_root()
113
+ return SUCCESS
.venv/lib/python3.11/site-packages/pip/_internal/commands/wheel.py ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import os
3
+ import shutil
4
+ from optparse import Values
5
+ from typing import List
6
+
7
+ from pip._internal.cache import WheelCache
8
+ from pip._internal.cli import cmdoptions
9
+ from pip._internal.cli.req_command import RequirementCommand, with_cleanup
10
+ from pip._internal.cli.status_codes import SUCCESS
11
+ from pip._internal.exceptions import CommandError
12
+ from pip._internal.operations.build.build_tracker import get_build_tracker
13
+ from pip._internal.req.req_install import (
14
+ InstallRequirement,
15
+ check_legacy_setup_py_options,
16
+ )
17
+ from pip._internal.utils.misc import ensure_dir, normalize_path
18
+ from pip._internal.utils.temp_dir import TempDirectory
19
+ from pip._internal.wheel_builder import build, should_build_for_wheel_command
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ class WheelCommand(RequirementCommand):
25
+ """
26
+ Build Wheel archives for your requirements and dependencies.
27
+
28
+ Wheel is a built-package format, and offers the advantage of not
29
+ recompiling your software during every install. For more details, see the
30
+ wheel docs: https://wheel.readthedocs.io/en/latest/
31
+
32
+ 'pip wheel' uses the build system interface as described here:
33
+ https://pip.pypa.io/en/stable/reference/build-system/
34
+
35
+ """
36
+
37
+ usage = """
38
+ %prog [options] <requirement specifier> ...
39
+ %prog [options] -r <requirements file> ...
40
+ %prog [options] [-e] <vcs project url> ...
41
+ %prog [options] [-e] <local project path> ...
42
+ %prog [options] <archive url/path> ..."""
43
+
44
+ def add_options(self) -> None:
45
+ self.cmd_opts.add_option(
46
+ "-w",
47
+ "--wheel-dir",
48
+ dest="wheel_dir",
49
+ metavar="dir",
50
+ default=os.curdir,
51
+ help=(
52
+ "Build wheels into <dir>, where the default is the "
53
+ "current working directory."
54
+ ),
55
+ )
56
+ self.cmd_opts.add_option(cmdoptions.no_binary())
57
+ self.cmd_opts.add_option(cmdoptions.only_binary())
58
+ self.cmd_opts.add_option(cmdoptions.prefer_binary())
59
+ self.cmd_opts.add_option(cmdoptions.no_build_isolation())
60
+ self.cmd_opts.add_option(cmdoptions.use_pep517())
61
+ self.cmd_opts.add_option(cmdoptions.no_use_pep517())
62
+ self.cmd_opts.add_option(cmdoptions.check_build_deps())
63
+ self.cmd_opts.add_option(cmdoptions.constraints())
64
+ self.cmd_opts.add_option(cmdoptions.editable())
65
+ self.cmd_opts.add_option(cmdoptions.requirements())
66
+ self.cmd_opts.add_option(cmdoptions.src())
67
+ self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
68
+ self.cmd_opts.add_option(cmdoptions.no_deps())
69
+ self.cmd_opts.add_option(cmdoptions.progress_bar())
70
+
71
+ self.cmd_opts.add_option(
72
+ "--no-verify",
73
+ dest="no_verify",
74
+ action="store_true",
75
+ default=False,
76
+ help="Don't verify if built wheel is valid.",
77
+ )
78
+
79
+ self.cmd_opts.add_option(cmdoptions.config_settings())
80
+ self.cmd_opts.add_option(cmdoptions.build_options())
81
+ self.cmd_opts.add_option(cmdoptions.global_options())
82
+
83
+ self.cmd_opts.add_option(
84
+ "--pre",
85
+ action="store_true",
86
+ default=False,
87
+ help=(
88
+ "Include pre-release and development versions. By default, "
89
+ "pip only finds stable versions."
90
+ ),
91
+ )
92
+
93
+ self.cmd_opts.add_option(cmdoptions.require_hashes())
94
+
95
+ index_opts = cmdoptions.make_option_group(
96
+ cmdoptions.index_group,
97
+ self.parser,
98
+ )
99
+
100
+ self.parser.insert_option_group(0, index_opts)
101
+ self.parser.insert_option_group(0, self.cmd_opts)
102
+
103
+ @with_cleanup
104
+ def run(self, options: Values, args: List[str]) -> int:
105
+ session = self.get_default_session(options)
106
+
107
+ finder = self._build_package_finder(options, session)
108
+
109
+ options.wheel_dir = normalize_path(options.wheel_dir)
110
+ ensure_dir(options.wheel_dir)
111
+
112
+ build_tracker = self.enter_context(get_build_tracker())
113
+
114
+ directory = TempDirectory(
115
+ delete=not options.no_clean,
116
+ kind="wheel",
117
+ globally_managed=True,
118
+ )
119
+
120
+ reqs = self.get_requirements(args, options, finder, session)
121
+ check_legacy_setup_py_options(options, reqs)
122
+
123
+ wheel_cache = WheelCache(options.cache_dir)
124
+
125
+ preparer = self.make_requirement_preparer(
126
+ temp_build_dir=directory,
127
+ options=options,
128
+ build_tracker=build_tracker,
129
+ session=session,
130
+ finder=finder,
131
+ download_dir=options.wheel_dir,
132
+ use_user_site=False,
133
+ verbosity=self.verbosity,
134
+ )
135
+
136
+ resolver = self.make_resolver(
137
+ preparer=preparer,
138
+ finder=finder,
139
+ options=options,
140
+ wheel_cache=wheel_cache,
141
+ ignore_requires_python=options.ignore_requires_python,
142
+ use_pep517=options.use_pep517,
143
+ )
144
+
145
+ self.trace_basic_info(finder)
146
+
147
+ requirement_set = resolver.resolve(reqs, check_supported_wheels=True)
148
+
149
+ reqs_to_build: List[InstallRequirement] = []
150
+ for req in requirement_set.requirements.values():
151
+ if req.is_wheel:
152
+ preparer.save_linked_requirement(req)
153
+ elif should_build_for_wheel_command(req):
154
+ reqs_to_build.append(req)
155
+
156
+ preparer.prepare_linked_requirements_more(requirement_set.requirements.values())
157
+ requirement_set.warn_legacy_versions_and_specifiers()
158
+
159
+ # build wheels
160
+ build_successes, build_failures = build(
161
+ reqs_to_build,
162
+ wheel_cache=wheel_cache,
163
+ verify=(not options.no_verify),
164
+ build_options=options.build_options or [],
165
+ global_options=options.global_options or [],
166
+ )
167
+ for req in build_successes:
168
+ assert req.link and req.link.is_wheel
169
+ assert req.local_file_path
170
+ # copy from cache to target directory
171
+ try:
172
+ shutil.copy(req.local_file_path, options.wheel_dir)
173
+ except OSError as e:
174
+ logger.warning(
175
+ "Building wheel for %s failed: %s",
176
+ req.name,
177
+ e,
178
+ )
179
+ build_failures.append(req)
180
+ if len(build_failures) != 0:
181
+ raise CommandError("Failed to build one or more wheels")
182
+
183
+ return SUCCESS
.venv/lib/python3.11/site-packages/pip/_internal/locations/__init__.py ADDED
@@ -0,0 +1,467 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import functools
2
+ import logging
3
+ import os
4
+ import pathlib
5
+ import sys
6
+ import sysconfig
7
+ from typing import Any, Dict, Generator, Optional, Tuple
8
+
9
+ from pip._internal.models.scheme import SCHEME_KEYS, Scheme
10
+ from pip._internal.utils.compat import WINDOWS
11
+ from pip._internal.utils.deprecation import deprecated
12
+ from pip._internal.utils.virtualenv import running_under_virtualenv
13
+
14
+ from . import _sysconfig
15
+ from .base import (
16
+ USER_CACHE_DIR,
17
+ get_major_minor_version,
18
+ get_src_prefix,
19
+ is_osx_framework,
20
+ site_packages,
21
+ user_site,
22
+ )
23
+
24
+ __all__ = [
25
+ "USER_CACHE_DIR",
26
+ "get_bin_prefix",
27
+ "get_bin_user",
28
+ "get_major_minor_version",
29
+ "get_platlib",
30
+ "get_purelib",
31
+ "get_scheme",
32
+ "get_src_prefix",
33
+ "site_packages",
34
+ "user_site",
35
+ ]
36
+
37
+
38
+ logger = logging.getLogger(__name__)
39
+
40
+
41
+ _PLATLIBDIR: str = getattr(sys, "platlibdir", "lib")
42
+
43
+ _USE_SYSCONFIG_DEFAULT = sys.version_info >= (3, 10)
44
+
45
+
46
+ def _should_use_sysconfig() -> bool:
47
+ """This function determines the value of _USE_SYSCONFIG.
48
+
49
+ By default, pip uses sysconfig on Python 3.10+.
50
+ But Python distributors can override this decision by setting:
51
+ sysconfig._PIP_USE_SYSCONFIG = True / False
52
+ Rationale in https://github.com/pypa/pip/issues/10647
53
+
54
+ This is a function for testability, but should be constant during any one
55
+ run.
56
+ """
57
+ return bool(getattr(sysconfig, "_PIP_USE_SYSCONFIG", _USE_SYSCONFIG_DEFAULT))
58
+
59
+
60
+ _USE_SYSCONFIG = _should_use_sysconfig()
61
+
62
+ if not _USE_SYSCONFIG:
63
+ # Import distutils lazily to avoid deprecation warnings,
64
+ # but import it soon enough that it is in memory and available during
65
+ # a pip reinstall.
66
+ from . import _distutils
67
+
68
+ # Be noisy about incompatibilities if this platforms "should" be using
69
+ # sysconfig, but is explicitly opting out and using distutils instead.
70
+ if _USE_SYSCONFIG_DEFAULT and not _USE_SYSCONFIG:
71
+ _MISMATCH_LEVEL = logging.WARNING
72
+ else:
73
+ _MISMATCH_LEVEL = logging.DEBUG
74
+
75
+
76
+ def _looks_like_bpo_44860() -> bool:
77
+ """The resolution to bpo-44860 will change this incorrect platlib.
78
+
79
+ See <https://bugs.python.org/issue44860>.
80
+ """
81
+ from distutils.command.install import INSTALL_SCHEMES
82
+
83
+ try:
84
+ unix_user_platlib = INSTALL_SCHEMES["unix_user"]["platlib"]
85
+ except KeyError:
86
+ return False
87
+ return unix_user_platlib == "$usersite"
88
+
89
+
90
+ def _looks_like_red_hat_patched_platlib_purelib(scheme: Dict[str, str]) -> bool:
91
+ platlib = scheme["platlib"]
92
+ if "/$platlibdir/" in platlib:
93
+ platlib = platlib.replace("/$platlibdir/", f"/{_PLATLIBDIR}/")
94
+ if "/lib64/" not in platlib:
95
+ return False
96
+ unpatched = platlib.replace("/lib64/", "/lib/")
97
+ return unpatched.replace("$platbase/", "$base/") == scheme["purelib"]
98
+
99
+
100
+ @functools.lru_cache(maxsize=None)
101
+ def _looks_like_red_hat_lib() -> bool:
102
+ """Red Hat patches platlib in unix_prefix and unix_home, but not purelib.
103
+
104
+ This is the only way I can see to tell a Red Hat-patched Python.
105
+ """
106
+ from distutils.command.install import INSTALL_SCHEMES
107
+
108
+ return all(
109
+ k in INSTALL_SCHEMES
110
+ and _looks_like_red_hat_patched_platlib_purelib(INSTALL_SCHEMES[k])
111
+ for k in ("unix_prefix", "unix_home")
112
+ )
113
+
114
+
115
+ @functools.lru_cache(maxsize=None)
116
+ def _looks_like_debian_scheme() -> bool:
117
+ """Debian adds two additional schemes."""
118
+ from distutils.command.install import INSTALL_SCHEMES
119
+
120
+ return "deb_system" in INSTALL_SCHEMES and "unix_local" in INSTALL_SCHEMES
121
+
122
+
123
+ @functools.lru_cache(maxsize=None)
124
+ def _looks_like_red_hat_scheme() -> bool:
125
+ """Red Hat patches ``sys.prefix`` and ``sys.exec_prefix``.
126
+
127
+ Red Hat's ``00251-change-user-install-location.patch`` changes the install
128
+ command's ``prefix`` and ``exec_prefix`` to append ``"/local"``. This is
129
+ (fortunately?) done quite unconditionally, so we create a default command
130
+ object without any configuration to detect this.
131
+ """
132
+ from distutils.command.install import install
133
+ from distutils.dist import Distribution
134
+
135
+ cmd: Any = install(Distribution())
136
+ cmd.finalize_options()
137
+ return (
138
+ cmd.exec_prefix == f"{os.path.normpath(sys.exec_prefix)}/local"
139
+ and cmd.prefix == f"{os.path.normpath(sys.prefix)}/local"
140
+ )
141
+
142
+
143
+ @functools.lru_cache(maxsize=None)
144
+ def _looks_like_slackware_scheme() -> bool:
145
+ """Slackware patches sysconfig but fails to patch distutils and site.
146
+
147
+ Slackware changes sysconfig's user scheme to use ``"lib64"`` for the lib
148
+ path, but does not do the same to the site module.
149
+ """
150
+ if user_site is None: # User-site not available.
151
+ return False
152
+ try:
153
+ paths = sysconfig.get_paths(scheme="posix_user", expand=False)
154
+ except KeyError: # User-site not available.
155
+ return False
156
+ return "/lib64/" in paths["purelib"] and "/lib64/" not in user_site
157
+
158
+
159
+ @functools.lru_cache(maxsize=None)
160
+ def _looks_like_msys2_mingw_scheme() -> bool:
161
+ """MSYS2 patches distutils and sysconfig to use a UNIX-like scheme.
162
+
163
+ However, MSYS2 incorrectly patches sysconfig ``nt`` scheme. The fix is
164
+ likely going to be included in their 3.10 release, so we ignore the warning.
165
+ See msys2/MINGW-packages#9319.
166
+
167
+ MSYS2 MINGW's patch uses lowercase ``"lib"`` instead of the usual uppercase,
168
+ and is missing the final ``"site-packages"``.
169
+ """
170
+ paths = sysconfig.get_paths("nt", expand=False)
171
+ return all(
172
+ "Lib" not in p and "lib" in p and not p.endswith("site-packages")
173
+ for p in (paths[key] for key in ("platlib", "purelib"))
174
+ )
175
+
176
+
177
+ def _fix_abiflags(parts: Tuple[str]) -> Generator[str, None, None]:
178
+ ldversion = sysconfig.get_config_var("LDVERSION")
179
+ abiflags = getattr(sys, "abiflags", None)
180
+
181
+ # LDVERSION does not end with sys.abiflags. Just return the path unchanged.
182
+ if not ldversion or not abiflags or not ldversion.endswith(abiflags):
183
+ yield from parts
184
+ return
185
+
186
+ # Strip sys.abiflags from LDVERSION-based path components.
187
+ for part in parts:
188
+ if part.endswith(ldversion):
189
+ part = part[: (0 - len(abiflags))]
190
+ yield part
191
+
192
+
193
+ @functools.lru_cache(maxsize=None)
194
+ def _warn_mismatched(old: pathlib.Path, new: pathlib.Path, *, key: str) -> None:
195
+ issue_url = "https://github.com/pypa/pip/issues/10151"
196
+ message = (
197
+ "Value for %s does not match. Please report this to <%s>"
198
+ "\ndistutils: %s"
199
+ "\nsysconfig: %s"
200
+ )
201
+ logger.log(_MISMATCH_LEVEL, message, key, issue_url, old, new)
202
+
203
+
204
+ def _warn_if_mismatch(old: pathlib.Path, new: pathlib.Path, *, key: str) -> bool:
205
+ if old == new:
206
+ return False
207
+ _warn_mismatched(old, new, key=key)
208
+ return True
209
+
210
+
211
+ @functools.lru_cache(maxsize=None)
212
+ def _log_context(
213
+ *,
214
+ user: bool = False,
215
+ home: Optional[str] = None,
216
+ root: Optional[str] = None,
217
+ prefix: Optional[str] = None,
218
+ ) -> None:
219
+ parts = [
220
+ "Additional context:",
221
+ "user = %r",
222
+ "home = %r",
223
+ "root = %r",
224
+ "prefix = %r",
225
+ ]
226
+
227
+ logger.log(_MISMATCH_LEVEL, "\n".join(parts), user, home, root, prefix)
228
+
229
+
230
+ def get_scheme(
231
+ dist_name: str,
232
+ user: bool = False,
233
+ home: Optional[str] = None,
234
+ root: Optional[str] = None,
235
+ isolated: bool = False,
236
+ prefix: Optional[str] = None,
237
+ ) -> Scheme:
238
+ new = _sysconfig.get_scheme(
239
+ dist_name,
240
+ user=user,
241
+ home=home,
242
+ root=root,
243
+ isolated=isolated,
244
+ prefix=prefix,
245
+ )
246
+ if _USE_SYSCONFIG:
247
+ return new
248
+
249
+ old = _distutils.get_scheme(
250
+ dist_name,
251
+ user=user,
252
+ home=home,
253
+ root=root,
254
+ isolated=isolated,
255
+ prefix=prefix,
256
+ )
257
+
258
+ warning_contexts = []
259
+ for k in SCHEME_KEYS:
260
+ old_v = pathlib.Path(getattr(old, k))
261
+ new_v = pathlib.Path(getattr(new, k))
262
+
263
+ if old_v == new_v:
264
+ continue
265
+
266
+ # distutils incorrectly put PyPy packages under ``site-packages/python``
267
+ # in the ``posix_home`` scheme, but PyPy devs said they expect the
268
+ # directory name to be ``pypy`` instead. So we treat this as a bug fix
269
+ # and not warn about it. See bpo-43307 and python/cpython#24628.
270
+ skip_pypy_special_case = (
271
+ sys.implementation.name == "pypy"
272
+ and home is not None
273
+ and k in ("platlib", "purelib")
274
+ and old_v.parent == new_v.parent
275
+ and old_v.name.startswith("python")
276
+ and new_v.name.startswith("pypy")
277
+ )
278
+ if skip_pypy_special_case:
279
+ continue
280
+
281
+ # sysconfig's ``osx_framework_user`` does not include ``pythonX.Y`` in
282
+ # the ``include`` value, but distutils's ``headers`` does. We'll let
283
+ # CPython decide whether this is a bug or feature. See bpo-43948.
284
+ skip_osx_framework_user_special_case = (
285
+ user
286
+ and is_osx_framework()
287
+ and k == "headers"
288
+ and old_v.parent.parent == new_v.parent
289
+ and old_v.parent.name.startswith("python")
290
+ )
291
+ if skip_osx_framework_user_special_case:
292
+ continue
293
+
294
+ # On Red Hat and derived Linux distributions, distutils is patched to
295
+ # use "lib64" instead of "lib" for platlib.
296
+ if k == "platlib" and _looks_like_red_hat_lib():
297
+ continue
298
+
299
+ # On Python 3.9+, sysconfig's posix_user scheme sets platlib against
300
+ # sys.platlibdir, but distutils's unix_user incorrectly coninutes
301
+ # using the same $usersite for both platlib and purelib. This creates a
302
+ # mismatch when sys.platlibdir is not "lib".
303
+ skip_bpo_44860 = (
304
+ user
305
+ and k == "platlib"
306
+ and not WINDOWS
307
+ and sys.version_info >= (3, 9)
308
+ and _PLATLIBDIR != "lib"
309
+ and _looks_like_bpo_44860()
310
+ )
311
+ if skip_bpo_44860:
312
+ continue
313
+
314
+ # Slackware incorrectly patches posix_user to use lib64 instead of lib,
315
+ # but not usersite to match the location.
316
+ skip_slackware_user_scheme = (
317
+ user
318
+ and k in ("platlib", "purelib")
319
+ and not WINDOWS
320
+ and _looks_like_slackware_scheme()
321
+ )
322
+ if skip_slackware_user_scheme:
323
+ continue
324
+
325
+ # Both Debian and Red Hat patch Python to place the system site under
326
+ # /usr/local instead of /usr. Debian also places lib in dist-packages
327
+ # instead of site-packages, but the /usr/local check should cover it.
328
+ skip_linux_system_special_case = (
329
+ not (user or home or prefix or running_under_virtualenv())
330
+ and old_v.parts[1:3] == ("usr", "local")
331
+ and len(new_v.parts) > 1
332
+ and new_v.parts[1] == "usr"
333
+ and (len(new_v.parts) < 3 or new_v.parts[2] != "local")
334
+ and (_looks_like_red_hat_scheme() or _looks_like_debian_scheme())
335
+ )
336
+ if skip_linux_system_special_case:
337
+ continue
338
+
339
+ # On Python 3.7 and earlier, sysconfig does not include sys.abiflags in
340
+ # the "pythonX.Y" part of the path, but distutils does.
341
+ skip_sysconfig_abiflag_bug = (
342
+ sys.version_info < (3, 8)
343
+ and not WINDOWS
344
+ and k in ("headers", "platlib", "purelib")
345
+ and tuple(_fix_abiflags(old_v.parts)) == new_v.parts
346
+ )
347
+ if skip_sysconfig_abiflag_bug:
348
+ continue
349
+
350
+ # MSYS2 MINGW's sysconfig patch does not include the "site-packages"
351
+ # part of the path. This is incorrect and will be fixed in MSYS.
352
+ skip_msys2_mingw_bug = (
353
+ WINDOWS and k in ("platlib", "purelib") and _looks_like_msys2_mingw_scheme()
354
+ )
355
+ if skip_msys2_mingw_bug:
356
+ continue
357
+
358
+ # CPython's POSIX install script invokes pip (via ensurepip) against the
359
+ # interpreter located in the source tree, not the install site. This
360
+ # triggers special logic in sysconfig that's not present in distutils.
361
+ # https://github.com/python/cpython/blob/8c21941ddaf/Lib/sysconfig.py#L178-L194
362
+ skip_cpython_build = (
363
+ sysconfig.is_python_build(check_home=True)
364
+ and not WINDOWS
365
+ and k in ("headers", "include", "platinclude")
366
+ )
367
+ if skip_cpython_build:
368
+ continue
369
+
370
+ warning_contexts.append((old_v, new_v, f"scheme.{k}"))
371
+
372
+ if not warning_contexts:
373
+ return old
374
+
375
+ # Check if this path mismatch is caused by distutils config files. Those
376
+ # files will no longer work once we switch to sysconfig, so this raises a
377
+ # deprecation message for them.
378
+ default_old = _distutils.distutils_scheme(
379
+ dist_name,
380
+ user,
381
+ home,
382
+ root,
383
+ isolated,
384
+ prefix,
385
+ ignore_config_files=True,
386
+ )
387
+ if any(default_old[k] != getattr(old, k) for k in SCHEME_KEYS):
388
+ deprecated(
389
+ reason=(
390
+ "Configuring installation scheme with distutils config files "
391
+ "is deprecated and will no longer work in the near future. If you "
392
+ "are using a Homebrew or Linuxbrew Python, please see discussion "
393
+ "at https://github.com/Homebrew/homebrew-core/issues/76621"
394
+ ),
395
+ replacement=None,
396
+ gone_in=None,
397
+ )
398
+ return old
399
+
400
+ # Post warnings about this mismatch so user can report them back.
401
+ for old_v, new_v, key in warning_contexts:
402
+ _warn_mismatched(old_v, new_v, key=key)
403
+ _log_context(user=user, home=home, root=root, prefix=prefix)
404
+
405
+ return old
406
+
407
+
408
+ def get_bin_prefix() -> str:
409
+ new = _sysconfig.get_bin_prefix()
410
+ if _USE_SYSCONFIG:
411
+ return new
412
+
413
+ old = _distutils.get_bin_prefix()
414
+ if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="bin_prefix"):
415
+ _log_context()
416
+ return old
417
+
418
+
419
+ def get_bin_user() -> str:
420
+ return _sysconfig.get_scheme("", user=True).scripts
421
+
422
+
423
+ def _looks_like_deb_system_dist_packages(value: str) -> bool:
424
+ """Check if the value is Debian's APT-controlled dist-packages.
425
+
426
+ Debian's ``distutils.sysconfig.get_python_lib()`` implementation returns the
427
+ default package path controlled by APT, but does not patch ``sysconfig`` to
428
+ do the same. This is similar to the bug worked around in ``get_scheme()``,
429
+ but here the default is ``deb_system`` instead of ``unix_local``. Ultimately
430
+ we can't do anything about this Debian bug, and this detection allows us to
431
+ skip the warning when needed.
432
+ """
433
+ if not _looks_like_debian_scheme():
434
+ return False
435
+ if value == "/usr/lib/python3/dist-packages":
436
+ return True
437
+ return False
438
+
439
+
440
+ def get_purelib() -> str:
441
+ """Return the default pure-Python lib location."""
442
+ new = _sysconfig.get_purelib()
443
+ if _USE_SYSCONFIG:
444
+ return new
445
+
446
+ old = _distutils.get_purelib()
447
+ if _looks_like_deb_system_dist_packages(old):
448
+ return old
449
+ if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="purelib"):
450
+ _log_context()
451
+ return old
452
+
453
+
454
+ def get_platlib() -> str:
455
+ """Return the default platform-shared lib location."""
456
+ new = _sysconfig.get_platlib()
457
+ if _USE_SYSCONFIG:
458
+ return new
459
+
460
+ from . import _distutils
461
+
462
+ old = _distutils.get_platlib()
463
+ if _looks_like_deb_system_dist_packages(old):
464
+ return old
465
+ if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="platlib"):
466
+ _log_context()
467
+ return old
.venv/lib/python3.11/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (18.2 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-311.pyc ADDED
Binary file (7.55 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-311.pyc ADDED
Binary file (8.88 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/locations/__pycache__/base.cpython-311.pyc ADDED
Binary file (4 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/locations/_distutils.py ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Locations where we look for configs, install stuff, etc"""
2
+
3
+ # The following comment should be removed at some point in the future.
4
+ # mypy: strict-optional=False
5
+
6
+ # If pip's going to use distutils, it should not be using the copy that setuptools
7
+ # might have injected into the environment. This is done by removing the injected
8
+ # shim, if it's injected.
9
+ #
10
+ # See https://github.com/pypa/pip/issues/8761 for the original discussion and
11
+ # rationale for why this is done within pip.
12
+ try:
13
+ __import__("_distutils_hack").remove_shim()
14
+ except (ImportError, AttributeError):
15
+ pass
16
+
17
+ import logging
18
+ import os
19
+ import sys
20
+ from distutils.cmd import Command as DistutilsCommand
21
+ from distutils.command.install import SCHEME_KEYS
22
+ from distutils.command.install import install as distutils_install_command
23
+ from distutils.sysconfig import get_python_lib
24
+ from typing import Dict, List, Optional, Union, cast
25
+
26
+ from pip._internal.models.scheme import Scheme
27
+ from pip._internal.utils.compat import WINDOWS
28
+ from pip._internal.utils.virtualenv import running_under_virtualenv
29
+
30
+ from .base import get_major_minor_version
31
+
32
+ logger = logging.getLogger(__name__)
33
+
34
+
35
+ def distutils_scheme(
36
+ dist_name: str,
37
+ user: bool = False,
38
+ home: Optional[str] = None,
39
+ root: Optional[str] = None,
40
+ isolated: bool = False,
41
+ prefix: Optional[str] = None,
42
+ *,
43
+ ignore_config_files: bool = False,
44
+ ) -> Dict[str, str]:
45
+ """
46
+ Return a distutils install scheme
47
+ """
48
+ from distutils.dist import Distribution
49
+
50
+ dist_args: Dict[str, Union[str, List[str]]] = {"name": dist_name}
51
+ if isolated:
52
+ dist_args["script_args"] = ["--no-user-cfg"]
53
+
54
+ d = Distribution(dist_args)
55
+ if not ignore_config_files:
56
+ try:
57
+ d.parse_config_files()
58
+ except UnicodeDecodeError:
59
+ paths = d.find_config_files()
60
+ logger.warning(
61
+ "Ignore distutils configs in %s due to encoding errors.",
62
+ ", ".join(os.path.basename(p) for p in paths),
63
+ )
64
+ obj: Optional[DistutilsCommand] = None
65
+ obj = d.get_command_obj("install", create=True)
66
+ assert obj is not None
67
+ i = cast(distutils_install_command, obj)
68
+ # NOTE: setting user or home has the side-effect of creating the home dir
69
+ # or user base for installations during finalize_options()
70
+ # ideally, we'd prefer a scheme class that has no side-effects.
71
+ assert not (user and prefix), f"user={user} prefix={prefix}"
72
+ assert not (home and prefix), f"home={home} prefix={prefix}"
73
+ i.user = user or i.user
74
+ if user or home:
75
+ i.prefix = ""
76
+ i.prefix = prefix or i.prefix
77
+ i.home = home or i.home
78
+ i.root = root or i.root
79
+ i.finalize_options()
80
+
81
+ scheme = {}
82
+ for key in SCHEME_KEYS:
83
+ scheme[key] = getattr(i, "install_" + key)
84
+
85
+ # install_lib specified in setup.cfg should install *everything*
86
+ # into there (i.e. it takes precedence over both purelib and
87
+ # platlib). Note, i.install_lib is *always* set after
88
+ # finalize_options(); we only want to override here if the user
89
+ # has explicitly requested it hence going back to the config
90
+ if "install_lib" in d.get_option_dict("install"):
91
+ scheme.update({"purelib": i.install_lib, "platlib": i.install_lib})
92
+
93
+ if running_under_virtualenv():
94
+ if home:
95
+ prefix = home
96
+ elif user:
97
+ prefix = i.install_userbase
98
+ else:
99
+ prefix = i.prefix
100
+ scheme["headers"] = os.path.join(
101
+ prefix,
102
+ "include",
103
+ "site",
104
+ f"python{get_major_minor_version()}",
105
+ dist_name,
106
+ )
107
+
108
+ if root is not None:
109
+ path_no_drive = os.path.splitdrive(os.path.abspath(scheme["headers"]))[1]
110
+ scheme["headers"] = os.path.join(root, path_no_drive[1:])
111
+
112
+ return scheme
113
+
114
+
115
+ def get_scheme(
116
+ dist_name: str,
117
+ user: bool = False,
118
+ home: Optional[str] = None,
119
+ root: Optional[str] = None,
120
+ isolated: bool = False,
121
+ prefix: Optional[str] = None,
122
+ ) -> Scheme:
123
+ """
124
+ Get the "scheme" corresponding to the input parameters. The distutils
125
+ documentation provides the context for the available schemes:
126
+ https://docs.python.org/3/install/index.html#alternate-installation
127
+
128
+ :param dist_name: the name of the package to retrieve the scheme for, used
129
+ in the headers scheme path
130
+ :param user: indicates to use the "user" scheme
131
+ :param home: indicates to use the "home" scheme and provides the base
132
+ directory for the same
133
+ :param root: root under which other directories are re-based
134
+ :param isolated: equivalent to --no-user-cfg, i.e. do not consider
135
+ ~/.pydistutils.cfg (posix) or ~/pydistutils.cfg (non-posix) for
136
+ scheme paths
137
+ :param prefix: indicates to use the "prefix" scheme and provides the
138
+ base directory for the same
139
+ """
140
+ scheme = distutils_scheme(dist_name, user, home, root, isolated, prefix)
141
+ return Scheme(
142
+ platlib=scheme["platlib"],
143
+ purelib=scheme["purelib"],
144
+ headers=scheme["headers"],
145
+ scripts=scheme["scripts"],
146
+ data=scheme["data"],
147
+ )
148
+
149
+
150
+ def get_bin_prefix() -> str:
151
+ # XXX: In old virtualenv versions, sys.prefix can contain '..' components,
152
+ # so we need to call normpath to eliminate them.
153
+ prefix = os.path.normpath(sys.prefix)
154
+ if WINDOWS:
155
+ bin_py = os.path.join(prefix, "Scripts")
156
+ # buildout uses 'bin' on Windows too?
157
+ if not os.path.exists(bin_py):
158
+ bin_py = os.path.join(prefix, "bin")
159
+ return bin_py
160
+ # Forcing to use /usr/local/bin for standard macOS framework installs
161
+ # Also log to ~/Library/Logs/ for use with the Console.app log viewer
162
+ if sys.platform[:6] == "darwin" and prefix[:16] == "/System/Library/":
163
+ return "/usr/local/bin"
164
+ return os.path.join(prefix, "bin")
165
+
166
+
167
+ def get_purelib() -> str:
168
+ return get_python_lib(plat_specific=False)
169
+
170
+
171
+ def get_platlib() -> str:
172
+ return get_python_lib(plat_specific=True)
.venv/lib/python3.11/site-packages/pip/_internal/locations/_sysconfig.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import os
3
+ import sys
4
+ import sysconfig
5
+ import typing
6
+
7
+ from pip._internal.exceptions import InvalidSchemeCombination, UserInstallationInvalid
8
+ from pip._internal.models.scheme import SCHEME_KEYS, Scheme
9
+ from pip._internal.utils.virtualenv import running_under_virtualenv
10
+
11
+ from .base import change_root, get_major_minor_version, is_osx_framework
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ # Notes on _infer_* functions.
17
+ # Unfortunately ``get_default_scheme()`` didn't exist before 3.10, so there's no
18
+ # way to ask things like "what is the '_prefix' scheme on this platform". These
19
+ # functions try to answer that with some heuristics while accounting for ad-hoc
20
+ # platforms not covered by CPython's default sysconfig implementation. If the
21
+ # ad-hoc implementation does not fully implement sysconfig, we'll fall back to
22
+ # a POSIX scheme.
23
+
24
+ _AVAILABLE_SCHEMES = set(sysconfig.get_scheme_names())
25
+
26
+ _PREFERRED_SCHEME_API = getattr(sysconfig, "get_preferred_scheme", None)
27
+
28
+
29
+ def _should_use_osx_framework_prefix() -> bool:
30
+ """Check for Apple's ``osx_framework_library`` scheme.
31
+
32
+ Python distributed by Apple's Command Line Tools has this special scheme
33
+ that's used when:
34
+
35
+ * This is a framework build.
36
+ * We are installing into the system prefix.
37
+
38
+ This does not account for ``pip install --prefix`` (also means we're not
39
+ installing to the system prefix), which should use ``posix_prefix``, but
40
+ logic here means ``_infer_prefix()`` outputs ``osx_framework_library``. But
41
+ since ``prefix`` is not available for ``sysconfig.get_default_scheme()``,
42
+ which is the stdlib replacement for ``_infer_prefix()``, presumably Apple
43
+ wouldn't be able to magically switch between ``osx_framework_library`` and
44
+ ``posix_prefix``. ``_infer_prefix()`` returning ``osx_framework_library``
45
+ means its behavior is consistent whether we use the stdlib implementation
46
+ or our own, and we deal with this special case in ``get_scheme()`` instead.
47
+ """
48
+ return (
49
+ "osx_framework_library" in _AVAILABLE_SCHEMES
50
+ and not running_under_virtualenv()
51
+ and is_osx_framework()
52
+ )
53
+
54
+
55
+ def _infer_prefix() -> str:
56
+ """Try to find a prefix scheme for the current platform.
57
+
58
+ This tries:
59
+
60
+ * A special ``osx_framework_library`` for Python distributed by Apple's
61
+ Command Line Tools, when not running in a virtual environment.
62
+ * Implementation + OS, used by PyPy on Windows (``pypy_nt``).
63
+ * Implementation without OS, used by PyPy on POSIX (``pypy``).
64
+ * OS + "prefix", used by CPython on POSIX (``posix_prefix``).
65
+ * Just the OS name, used by CPython on Windows (``nt``).
66
+
67
+ If none of the above works, fall back to ``posix_prefix``.
68
+ """
69
+ if _PREFERRED_SCHEME_API:
70
+ return _PREFERRED_SCHEME_API("prefix")
71
+ if _should_use_osx_framework_prefix():
72
+ return "osx_framework_library"
73
+ implementation_suffixed = f"{sys.implementation.name}_{os.name}"
74
+ if implementation_suffixed in _AVAILABLE_SCHEMES:
75
+ return implementation_suffixed
76
+ if sys.implementation.name in _AVAILABLE_SCHEMES:
77
+ return sys.implementation.name
78
+ suffixed = f"{os.name}_prefix"
79
+ if suffixed in _AVAILABLE_SCHEMES:
80
+ return suffixed
81
+ if os.name in _AVAILABLE_SCHEMES: # On Windows, prefx is just called "nt".
82
+ return os.name
83
+ return "posix_prefix"
84
+
85
+
86
+ def _infer_user() -> str:
87
+ """Try to find a user scheme for the current platform."""
88
+ if _PREFERRED_SCHEME_API:
89
+ return _PREFERRED_SCHEME_API("user")
90
+ if is_osx_framework() and not running_under_virtualenv():
91
+ suffixed = "osx_framework_user"
92
+ else:
93
+ suffixed = f"{os.name}_user"
94
+ if suffixed in _AVAILABLE_SCHEMES:
95
+ return suffixed
96
+ if "posix_user" not in _AVAILABLE_SCHEMES: # User scheme unavailable.
97
+ raise UserInstallationInvalid()
98
+ return "posix_user"
99
+
100
+
101
+ def _infer_home() -> str:
102
+ """Try to find a home for the current platform."""
103
+ if _PREFERRED_SCHEME_API:
104
+ return _PREFERRED_SCHEME_API("home")
105
+ suffixed = f"{os.name}_home"
106
+ if suffixed in _AVAILABLE_SCHEMES:
107
+ return suffixed
108
+ return "posix_home"
109
+
110
+
111
+ # Update these keys if the user sets a custom home.
112
+ _HOME_KEYS = [
113
+ "installed_base",
114
+ "base",
115
+ "installed_platbase",
116
+ "platbase",
117
+ "prefix",
118
+ "exec_prefix",
119
+ ]
120
+ if sysconfig.get_config_var("userbase") is not None:
121
+ _HOME_KEYS.append("userbase")
122
+
123
+
124
+ def get_scheme(
125
+ dist_name: str,
126
+ user: bool = False,
127
+ home: typing.Optional[str] = None,
128
+ root: typing.Optional[str] = None,
129
+ isolated: bool = False,
130
+ prefix: typing.Optional[str] = None,
131
+ ) -> Scheme:
132
+ """
133
+ Get the "scheme" corresponding to the input parameters.
134
+
135
+ :param dist_name: the name of the package to retrieve the scheme for, used
136
+ in the headers scheme path
137
+ :param user: indicates to use the "user" scheme
138
+ :param home: indicates to use the "home" scheme
139
+ :param root: root under which other directories are re-based
140
+ :param isolated: ignored, but kept for distutils compatibility (where
141
+ this controls whether the user-site pydistutils.cfg is honored)
142
+ :param prefix: indicates to use the "prefix" scheme and provides the
143
+ base directory for the same
144
+ """
145
+ if user and prefix:
146
+ raise InvalidSchemeCombination("--user", "--prefix")
147
+ if home and prefix:
148
+ raise InvalidSchemeCombination("--home", "--prefix")
149
+
150
+ if home is not None:
151
+ scheme_name = _infer_home()
152
+ elif user:
153
+ scheme_name = _infer_user()
154
+ else:
155
+ scheme_name = _infer_prefix()
156
+
157
+ # Special case: When installing into a custom prefix, use posix_prefix
158
+ # instead of osx_framework_library. See _should_use_osx_framework_prefix()
159
+ # docstring for details.
160
+ if prefix is not None and scheme_name == "osx_framework_library":
161
+ scheme_name = "posix_prefix"
162
+
163
+ if home is not None:
164
+ variables = {k: home for k in _HOME_KEYS}
165
+ elif prefix is not None:
166
+ variables = {k: prefix for k in _HOME_KEYS}
167
+ else:
168
+ variables = {}
169
+
170
+ paths = sysconfig.get_paths(scheme=scheme_name, vars=variables)
171
+
172
+ # Logic here is very arbitrary, we're doing it for compatibility, don't ask.
173
+ # 1. Pip historically uses a special header path in virtual environments.
174
+ # 2. If the distribution name is not known, distutils uses 'UNKNOWN'. We
175
+ # only do the same when not running in a virtual environment because
176
+ # pip's historical header path logic (see point 1) did not do this.
177
+ if running_under_virtualenv():
178
+ if user:
179
+ base = variables.get("userbase", sys.prefix)
180
+ else:
181
+ base = variables.get("base", sys.prefix)
182
+ python_xy = f"python{get_major_minor_version()}"
183
+ paths["include"] = os.path.join(base, "include", "site", python_xy)
184
+ elif not dist_name:
185
+ dist_name = "UNKNOWN"
186
+
187
+ scheme = Scheme(
188
+ platlib=paths["platlib"],
189
+ purelib=paths["purelib"],
190
+ headers=os.path.join(paths["include"], dist_name),
191
+ scripts=paths["scripts"],
192
+ data=paths["data"],
193
+ )
194
+ if root is not None:
195
+ for key in SCHEME_KEYS:
196
+ value = change_root(root, getattr(scheme, key))
197
+ setattr(scheme, key, value)
198
+ return scheme
199
+
200
+
201
+ def get_bin_prefix() -> str:
202
+ # Forcing to use /usr/local/bin for standard macOS framework installs.
203
+ if sys.platform[:6] == "darwin" and sys.prefix[:16] == "/System/Library/":
204
+ return "/usr/local/bin"
205
+ return sysconfig.get_paths()["scripts"]
206
+
207
+
208
+ def get_purelib() -> str:
209
+ return sysconfig.get_paths()["purelib"]
210
+
211
+
212
+ def get_platlib() -> str:
213
+ return sysconfig.get_paths()["platlib"]
.venv/lib/python3.11/site-packages/pip/_internal/locations/base.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import functools
2
+ import os
3
+ import site
4
+ import sys
5
+ import sysconfig
6
+ import typing
7
+
8
+ from pip._internal.exceptions import InstallationError
9
+ from pip._internal.utils import appdirs
10
+ from pip._internal.utils.virtualenv import running_under_virtualenv
11
+
12
+ # Application Directories
13
+ USER_CACHE_DIR = appdirs.user_cache_dir("pip")
14
+
15
+ # FIXME doesn't account for venv linked to global site-packages
16
+ site_packages: str = sysconfig.get_path("purelib")
17
+
18
+
19
+ def get_major_minor_version() -> str:
20
+ """
21
+ Return the major-minor version of the current Python as a string, e.g.
22
+ "3.7" or "3.10".
23
+ """
24
+ return "{}.{}".format(*sys.version_info)
25
+
26
+
27
+ def change_root(new_root: str, pathname: str) -> str:
28
+ """Return 'pathname' with 'new_root' prepended.
29
+
30
+ If 'pathname' is relative, this is equivalent to os.path.join(new_root, pathname).
31
+ Otherwise, it requires making 'pathname' relative and then joining the
32
+ two, which is tricky on DOS/Windows and Mac OS.
33
+
34
+ This is borrowed from Python's standard library's distutils module.
35
+ """
36
+ if os.name == "posix":
37
+ if not os.path.isabs(pathname):
38
+ return os.path.join(new_root, pathname)
39
+ else:
40
+ return os.path.join(new_root, pathname[1:])
41
+
42
+ elif os.name == "nt":
43
+ (drive, path) = os.path.splitdrive(pathname)
44
+ if path[0] == "\\":
45
+ path = path[1:]
46
+ return os.path.join(new_root, path)
47
+
48
+ else:
49
+ raise InstallationError(
50
+ f"Unknown platform: {os.name}\n"
51
+ "Can not change root path prefix on unknown platform."
52
+ )
53
+
54
+
55
+ def get_src_prefix() -> str:
56
+ if running_under_virtualenv():
57
+ src_prefix = os.path.join(sys.prefix, "src")
58
+ else:
59
+ # FIXME: keep src in cwd for now (it is not a temporary folder)
60
+ try:
61
+ src_prefix = os.path.join(os.getcwd(), "src")
62
+ except OSError:
63
+ # In case the current working directory has been renamed or deleted
64
+ sys.exit("The folder you are executing pip from can no longer be found.")
65
+
66
+ # under macOS + virtualenv sys.prefix is not properly resolved
67
+ # it is something like /path/to/python/bin/..
68
+ return os.path.abspath(src_prefix)
69
+
70
+
71
+ try:
72
+ # Use getusersitepackages if this is present, as it ensures that the
73
+ # value is initialised properly.
74
+ user_site: typing.Optional[str] = site.getusersitepackages()
75
+ except AttributeError:
76
+ user_site = site.USER_SITE
77
+
78
+
79
+ @functools.lru_cache(maxsize=None)
80
+ def is_osx_framework() -> bool:
81
+ return bool(sysconfig.get_config_var("PYTHONFRAMEWORK"))
.venv/lib/python3.11/site-packages/pip/_internal/models/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (271 Bytes). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/models/__pycache__/candidate.cpython-311.pyc ADDED
Binary file (2.08 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-311.pyc ADDED
Binary file (12.8 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/models/__pycache__/format_control.cpython-311.pyc ADDED
Binary file (4.63 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/models/__pycache__/index.cpython-311.pyc ADDED
Binary file (1.9 kB). View file
 
.venv/lib/python3.11/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-311.pyc ADDED
Binary file (2.6 kB). View file