]> jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/pip/_internal/locations/_sysconfig.py
init: venv aand flask
[dlqueue.git] / venv / lib / python3.11 / site-packages / pip / _internal / locations / _sysconfig.py
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"]