python (3.12.0)
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 ESC[4;38;5;81mDownloadCommand(ESC[4;38;5;149mRequirementCommand):
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