]> jfr.im git - dlqueue.git/blame - venv/lib/python3.11/site-packages/pip/_internal/distributions/sdist.py
init: venv aand flask
[dlqueue.git] / venv / lib / python3.11 / site-packages / pip / _internal / distributions / sdist.py
CommitLineData
e0df8241
JR
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
14class SourceDistribution(AbstractDistribution):
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.req.get_dist()
23
24 def prepare_distribution_metadata(
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.req.load_pyproject_toml()
32
33 # Set up the build isolation, if this requirement should be isolated
34 should_isolate = self.req.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.req.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.req.use_pep517 and check_build_deps
51 if should_check_deps:
52 pyproject_requires = self.req.pyproject_requires
53 assert pyproject_requires is not None
54 conflicting, missing = self.req.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.req.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.req.pyproject_requires
67 assert pyproject_requires is not None
68
69 self.req.build_env = BuildEnvironment()
70 self.req.build_env.install_requirements(
71 finder, pyproject_requires, "overlay", kind="build dependencies"
72 )
73 conflicting, missing = self.req.build_env.check_requirements(
74 self.req.requirements_to_check
75 )
76 if conflicting:
77 self._raise_conflicts("PEP 517/518 supported requirements", conflicting)
78 if missing:
79 logger.warning(
80 "Missing build requirements in pyproject.toml for %s.",
81 self.req,
82 )
83 logger.warning(
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.req.build_env:
91 runner = runner_with_spinner_message("Getting requirements to build wheel")
92 backend = self.req.pep517_backend
93 assert backend is not None
94 with backend.subprocess_runner(runner):
95 return backend.get_requires_for_build_wheel()
96
97 def _get_build_requires_editable(self) -> Iterable[str]:
98 with self.req.build_env:
99 runner = runner_with_spinner_message(
100 "Getting requirements to build editable"
101 )
102 backend = self.req.pep517_backend
103 assert backend is not None
104 with backend.subprocess_runner(runner):
105 return backend.get_requires_for_build_editable()
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.req.editable
113 and self.req.permit_editable_wheels
114 and self.req.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.req.build_env.check_requirements(build_reqs)
120 if conflicting:
121 self._raise_conflicts("the backend dependencies", conflicting)
122 self.req.build_env.install_requirements(
123 finder, missing, "normal", kind="backend dependencies"
124 )
125
126 def _raise_conflicts(
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.req,
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.req, missing=", ".join(map(repr, sorted(missing)))
149 )
150 raise InstallationError(error_message)