Let us walk on the 3-isogeny graph
Loading...
Searching...
No Matches
sdist.py
Go to the documentation of this file.
1import logging
2from typing import Iterable, Set, Tuple
3
4from pip._internal.build_env import BuildEnvironment
5from pip._internal.distributions.base import AbstractDistribution
6from pip._internal.exceptions import InstallationError
7from pip._internal.index.package_finder import PackageFinder
8from pip._internal.metadata import BaseDistribution
9from pip._internal.utils.subprocess import runner_with_spinner_message
10
11logger = logging.getLogger(__name__)
12
13
15 """Represents a source distribution.
16
17 The preparation step for these needs metadata for the packages to be
18 generated, either using PEP 517 or using the legacy `setup.py egg_info`.
19 """
20
21 def get_metadata_distribution(self) -> BaseDistribution:
22 return self.reqreq.get_dist()
23
25 self,
26 finder: PackageFinder,
27 build_isolation: bool,
28 check_build_deps: bool,
29 ) -> None:
30 # Load pyproject.toml, to determine whether PEP 517 is to be used
31 self.reqreq.load_pyproject_toml()
32
33 # Set up the build isolation, if this requirement should be isolated
34 should_isolate = self.reqreq.use_pep517 and build_isolation
35 if should_isolate:
36 # Setup an isolated environment and install the build backend static
37 # requirements in it.
38 self._prepare_build_backend(finder)
39 # Check that if the requirement is editable, it either supports PEP 660 or
40 # has a setup.py or a setup.cfg. This cannot be done earlier because we need
41 # to setup the build backend to verify it supports build_editable, nor can
42 # it be done later, because we want to avoid installing build requirements
43 # needlessly. Doing it here also works around setuptools generating
44 # UNKNOWN.egg-info when running get_requires_for_build_wheel on a directory
45 # without setup.py nor setup.cfg.
46 self.reqreq.isolated_editable_sanity_check()
47 # Install the dynamic build requirements.
48 self._install_build_reqs(finder)
49 # Check if the current environment provides build dependencies
50 should_check_deps = self.reqreq.use_pep517 and check_build_deps
51 if should_check_deps:
52 pyproject_requires = self.reqreq.pyproject_requires
53 assert pyproject_requires is not None
54 conflicting, missing = self.reqreq.build_env.check_requirements(
55 pyproject_requires
56 )
57 if conflicting:
58 self._raise_conflicts("the backend dependencies", conflicting)
59 if missing:
60 self._raise_missing_reqs(missing)
61 self.reqreq.prepare_metadata()
62
63 def _prepare_build_backend(self, finder: PackageFinder) -> None:
64 # Isolate in a BuildEnvironment and install the build-time
65 # requirements.
66 pyproject_requires = self.reqreq.pyproject_requires
67 assert pyproject_requires is not None
68
69 self.reqreq.build_env = BuildEnvironment()
71 finder, pyproject_requires, "overlay", kind="build dependencies"
72 )
73 conflicting, missing = self.reqreq.build_env.check_requirements(
74 self.reqreq.requirements_to_check
75 )
76 if conflicting:
77 self._raise_conflicts("PEP 517/518 supported requirements", conflicting)
78 if missing:
80 "Missing build requirements in pyproject.toml for %s.",
81 self.reqreq,
82 )
84 "The project does not specify a build backend, and "
85 "pip cannot fall back to setuptools without %s.",
86 " and ".join(map(repr, sorted(missing))),
87 )
88
89 def _get_build_requires_wheel(self) -> Iterable[str]:
90 with self.reqreq.build_env:
91 runner = runner_with_spinner_message("Getting requirements to build wheel")
92 backend = self.reqreq.pep517_backend
93 assert backend is not None
94 with backend.subprocess_runner(runner):
96
97 def _get_build_requires_editable(self) -> Iterable[str]:
98 with self.reqreq.build_env:
99 runner = runner_with_spinner_message(
100 "Getting requirements to build editable"
101 )
102 backend = self.reqreq.pep517_backend
103 assert backend is not None
104 with backend.subprocess_runner(runner):
106
107 def _install_build_reqs(self, finder: PackageFinder) -> None:
108 # Install any extra build dependencies that the backend requests.
109 # This must be done in a second pass, as the pyproject.toml
110 # dependencies must be installed before we can call the backend.
111 if (
112 self.reqreq.editable
113 and self.reqreq.permit_editable_wheels
114 and self.reqreq.supports_pyproject_editable()
115 ):
116 build_reqs = self._get_build_requires_editable()
117 else:
118 build_reqs = self._get_build_requires_wheel()
119 conflicting, missing = self.reqreq.build_env.check_requirements(build_reqs)
120 if conflicting:
121 self._raise_conflicts("the backend dependencies", conflicting)
123 finder, missing, "normal", kind="backend dependencies"
124 )
125
127 self, conflicting_with: str, conflicting_reqs: Set[Tuple[str, str]]
128 ) -> None:
129 format_string = (
130 "Some build dependencies for {requirement} "
131 "conflict with {conflicting_with}: {description}."
132 )
133 error_message = format_string.format(
134 requirement=self.reqreq,
135 conflicting_with=conflicting_with,
136 description=", ".join(
137 f"{installed} is incompatible with {wanted}"
138 for installed, wanted in sorted(conflicting_reqs)
139 ),
140 )
141 raise InstallationError(error_message)
142
143 def _raise_missing_reqs(self, missing: Set[str]) -> None:
144 format_string = (
145 "Some build dependencies for {requirement} are missing: {missing}."
146 )
147 error_message = format_string.format(
148 requirement=self.reqreq, missing=", ".join(map(repr, sorted(missing)))
149 )
150 raise InstallationError(error_message)
None _install_build_reqs(self, PackageFinder finder)
Definition sdist.py:107
None _raise_missing_reqs(self, Set[str] missing)
Definition sdist.py:143
None _raise_conflicts(self, str conflicting_with, Set[Tuple[str, str]] conflicting_reqs)
Definition sdist.py:128
None prepare_distribution_metadata(self, PackageFinder finder, bool build_isolation, bool check_build_deps)
Definition sdist.py:29
None _prepare_build_backend(self, PackageFinder finder)
Definition sdist.py:63
for i