pex 2.54.2__py2.py3-none-any.whl → 2.69.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pex might be problematic. Click here for more details.
- pex/auth.py +1 -1
- pex/bin/pex.py +15 -2
- pex/build_backend/configuration.py +5 -5
- pex/build_backend/wrap.py +27 -23
- pex/build_system/pep_517.py +4 -1
- pex/cache/dirs.py +17 -12
- pex/cli/commands/lock.py +302 -165
- pex/cli/commands/pip/core.py +4 -12
- pex/cli/commands/pip/wheel.py +1 -1
- pex/cli/commands/run.py +13 -20
- pex/cli/commands/venv.py +85 -16
- pex/cli/pex.py +11 -4
- pex/common.py +57 -7
- pex/compatibility.py +1 -1
- pex/dependency_configuration.py +87 -15
- pex/dist_metadata.py +143 -25
- pex/docs/html/_pagefind/fragment/en_4250138.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_7125dad.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_785d562.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_8e94bb8.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_a0396bb.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_a8a3588.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_c07d988.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_d718411.pf_fragment +0 -0
- pex/docs/html/_pagefind/index/en_a2e3c5e.pf_index +0 -0
- pex/docs/html/_pagefind/pagefind-entry.json +1 -1
- pex/docs/html/_pagefind/pagefind.en_4ce1afa9e3.pf_meta +0 -0
- pex/docs/html/_static/documentation_options.js +1 -1
- pex/docs/html/_static/pygments.css +164 -146
- pex/docs/html/_static/styles/furo.css +1 -1
- pex/docs/html/_static/styles/furo.css.map +1 -1
- pex/docs/html/api/vars.html +25 -34
- pex/docs/html/buildingpex.html +25 -34
- pex/docs/html/genindex.html +24 -33
- pex/docs/html/index.html +25 -34
- pex/docs/html/recipes.html +25 -34
- pex/docs/html/scie.html +25 -34
- pex/docs/html/search.html +24 -33
- pex/docs/html/whatispex.html +25 -34
- pex/entry_points_txt.py +98 -0
- pex/environment.py +54 -33
- pex/finders.py +1 -1
- pex/hashing.py +71 -9
- pex/installed_wheel.py +141 -0
- pex/interpreter.py +41 -38
- pex/interpreter_constraints.py +25 -25
- pex/interpreter_implementation.py +40 -0
- pex/jobs.py +13 -6
- pex/pep_376.py +68 -384
- pex/pep_425.py +11 -2
- pex/pep_427.py +937 -205
- pex/pep_508.py +4 -5
- pex/pex_builder.py +5 -8
- pex/pex_info.py +14 -9
- pex/pip/dependencies/__init__.py +85 -13
- pex/pip/dependencies/requires.py +38 -3
- pex/pip/foreign_platform/__init__.py +4 -3
- pex/pip/installation.py +2 -2
- pex/pip/local_project.py +6 -14
- pex/pip/package_repositories/__init__.py +78 -0
- pex/pip/package_repositories/link_collector.py +96 -0
- pex/pip/tool.py +139 -33
- pex/pip/vcs.py +109 -43
- pex/pip/version.py +8 -1
- pex/requirements.py +121 -16
- pex/resolve/config.py +5 -1
- pex/resolve/configured_resolve.py +32 -10
- pex/resolve/configured_resolver.py +10 -39
- pex/resolve/downloads.py +4 -3
- pex/resolve/lock_downloader.py +16 -23
- pex/resolve/lock_resolver.py +41 -51
- pex/resolve/locked_resolve.py +89 -32
- pex/resolve/locker.py +145 -101
- pex/resolve/locker_patches.py +123 -197
- pex/resolve/lockfile/create.py +232 -87
- pex/resolve/lockfile/download_manager.py +5 -1
- pex/resolve/lockfile/json_codec.py +103 -28
- pex/resolve/lockfile/model.py +13 -35
- pex/resolve/lockfile/pep_751.py +117 -98
- pex/resolve/lockfile/requires_dist.py +17 -262
- pex/resolve/lockfile/subset.py +11 -0
- pex/resolve/lockfile/targets.py +445 -0
- pex/resolve/lockfile/updater.py +22 -10
- pex/resolve/package_repository.py +406 -0
- pex/resolve/pex_repository_resolver.py +1 -1
- pex/resolve/pre_resolved_resolver.py +19 -16
- pex/resolve/project.py +233 -47
- pex/resolve/requirement_configuration.py +28 -10
- pex/resolve/resolver_configuration.py +18 -32
- pex/resolve/resolver_options.py +234 -28
- pex/resolve/resolvers.py +3 -12
- pex/resolve/target_options.py +18 -2
- pex/resolve/target_system.py +908 -0
- pex/resolve/venv_resolver.py +670 -0
- pex/resolver.py +673 -209
- pex/scie/__init__.py +40 -1
- pex/scie/model.py +2 -0
- pex/scie/science.py +25 -3
- pex/sdist.py +219 -0
- pex/sh_boot.py +24 -21
- pex/sysconfig.py +5 -3
- pex/targets.py +31 -10
- pex/third_party/__init__.py +1 -1
- pex/tools/commands/repository.py +48 -25
- pex/vendor/__init__.py +4 -9
- pex/vendor/__main__.py +65 -41
- pex/vendor/_vendored/ansicolors/.layout.json +1 -1
- pex/vendor/_vendored/ansicolors/ansicolors-1.1.8.dist-info/RECORD +11 -0
- pex/vendor/_vendored/ansicolors/ansicolors-1.1.8.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/appdirs/.layout.json +1 -1
- pex/vendor/_vendored/appdirs/appdirs-1.4.4.dist-info/RECORD +7 -0
- pex/vendor/_vendored/appdirs/appdirs-1.4.4.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/attrs/.layout.json +1 -1
- pex/vendor/_vendored/attrs/attrs-21.5.0.dev0.dist-info/RECORD +37 -0
- pex/vendor/_vendored/attrs/attrs-21.5.0.dev0.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/packaging_20_9/.layout.json +1 -1
- pex/vendor/_vendored/packaging_20_9/packaging-20.9.dist-info/RECORD +20 -0
- pex/vendor/_vendored/packaging_20_9/packaging-20.9.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/packaging_20_9/pyparsing-2.4.7.dist-info/RECORD +7 -0
- pex/vendor/_vendored/packaging_20_9/pyparsing-2.4.7.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/packaging_21_3/.layout.json +1 -1
- pex/vendor/_vendored/packaging_21_3/packaging-21.3.dist-info/RECORD +20 -0
- pex/vendor/_vendored/packaging_21_3/packaging-21.3.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/packaging_21_3/pyparsing-3.0.7.dist-info/RECORD +18 -0
- pex/vendor/_vendored/packaging_21_3/pyparsing-3.0.7.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/packaging_24_0/.layout.json +1 -1
- pex/vendor/_vendored/packaging_24_0/packaging-24.0.dist-info/RECORD +22 -0
- pex/vendor/_vendored/packaging_24_0/packaging-24.0.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/packaging_25_0/.layout.json +1 -1
- pex/vendor/_vendored/packaging_25_0/packaging-25.0.dist-info/RECORD +24 -0
- pex/vendor/_vendored/packaging_25_0/packaging-25.0.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/pip/.layout.json +1 -1
- pex/vendor/_vendored/pip/pip/_vendor/certifi/cacert.pem +63 -1
- pex/vendor/_vendored/pip/pip-20.3.4.dist-info/RECORD +388 -0
- pex/vendor/_vendored/pip/pip-20.3.4.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/setuptools/.layout.json +1 -1
- pex/vendor/_vendored/setuptools/setuptools-44.0.0+3acb925dd708430aeaf197ea53ac8a752f7c1863.dist-info/RECORD +107 -0
- pex/vendor/_vendored/setuptools/setuptools-44.0.0+3acb925dd708430aeaf197ea53ac8a752f7c1863.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/toml/.layout.json +1 -1
- pex/vendor/_vendored/toml/toml-0.10.2.dist-info/RECORD +11 -0
- pex/vendor/_vendored/toml/toml-0.10.2.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/tomli/.layout.json +1 -1
- pex/vendor/_vendored/tomli/tomli-2.0.1.dist-info/RECORD +10 -0
- pex/vendor/_vendored/tomli/tomli-2.0.1.pex-info/original-whl-info.json +1 -0
- pex/venv/installer.py +46 -19
- pex/venv/venv_pex.py +6 -3
- pex/version.py +1 -1
- pex/wheel.py +188 -40
- pex/whl.py +67 -0
- pex/windows/__init__.py +14 -11
- {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/METADATA +6 -5
- {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/RECORD +157 -133
- {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/entry_points.txt +1 -0
- {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/pylock/pylock.toml +1 -1
- pex/docs/html/_pagefind/fragment/en_42c9d8c.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_45dd5a2.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_4ca74d2.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_77273d5.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_87a59c5.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_8dc89b5.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_9d1319b.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_e55df9d.pf_fragment +0 -0
- pex/docs/html/_pagefind/index/en_1e98c6f.pf_index +0 -0
- pex/docs/html/_pagefind/pagefind.en_d1c488ecae.pf_meta +0 -0
- pex/vendor/_vendored/ansicolors/ansicolors-1.1.8.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/appdirs/appdirs-1.4.4.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/attrs/attrs-21.5.0.dev0.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/packaging_20_9/packaging-20.9.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/packaging_20_9/pyparsing-2.4.7.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/packaging_21_3/packaging-21.3.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/packaging_21_3/pyparsing-3.0.7.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/packaging_24_0/packaging-24.0.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/packaging_25_0/packaging-25.0.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/pip/pip-20.3.4.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/setuptools/setuptools-44.0.0+3acb925dd708430aeaf197ea53ac8a752f7c1863.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/toml/toml-0.10.2.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/tomli/tomli-2.0.1.dist-info/INSTALLER +0 -1
- {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/WHEEL +0 -0
- {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/licenses/LICENSE +0 -0
- {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/top_level.txt +0 -0
pex/resolve/resolver_options.py
CHANGED
|
@@ -5,22 +5,26 @@ from __future__ import absolute_import
|
|
|
5
5
|
|
|
6
6
|
import glob
|
|
7
7
|
import os
|
|
8
|
+
import sys
|
|
8
9
|
import tempfile
|
|
9
10
|
from argparse import Action, ArgumentError, ArgumentTypeError, Namespace, _ActionsContainer
|
|
11
|
+
from collections import OrderedDict, defaultdict
|
|
10
12
|
|
|
11
13
|
from pex import pex_warnings
|
|
12
14
|
from pex.argparse import HandleBoolAction
|
|
15
|
+
from pex.common import pluralize
|
|
13
16
|
from pex.dist_metadata import Requirement, is_sdist, is_wheel
|
|
14
17
|
from pex.fetcher import initialize_ssl_context
|
|
15
18
|
from pex.network_configuration import NetworkConfiguration
|
|
16
19
|
from pex.orderedset import OrderedSet
|
|
20
|
+
from pex.os import is_exe
|
|
17
21
|
from pex.pep_503 import ProjectName
|
|
18
22
|
from pex.pip.version import PipVersion, PipVersionValue
|
|
19
23
|
from pex.resolve.lockfile import json_codec
|
|
20
24
|
from pex.resolve.lockfile.model import Lockfile
|
|
25
|
+
from pex.resolve.package_repository import PYPI, Repo, ReposConfiguration, Scope
|
|
21
26
|
from pex.resolve.path_mappings import PathMapping, PathMappings
|
|
22
27
|
from pex.resolve.resolver_configuration import (
|
|
23
|
-
PYPI,
|
|
24
28
|
BuildConfiguration,
|
|
25
29
|
LockRepositoryConfiguration,
|
|
26
30
|
PexRepositoryConfiguration,
|
|
@@ -28,41 +32,81 @@ from pex.resolve.resolver_configuration import (
|
|
|
28
32
|
PipLog,
|
|
29
33
|
PreResolvedConfiguration,
|
|
30
34
|
PylockRepositoryConfiguration,
|
|
31
|
-
ReposConfiguration,
|
|
32
35
|
ResolverVersion,
|
|
36
|
+
VenvRepositoryConfiguration,
|
|
33
37
|
)
|
|
34
38
|
from pex.result import Error
|
|
35
39
|
from pex.tracer import TRACER
|
|
36
40
|
from pex.typing import TYPE_CHECKING, cast
|
|
41
|
+
from pex.venv.virtualenv import InvalidVirtualenvError, Virtualenv
|
|
37
42
|
|
|
38
43
|
if TYPE_CHECKING:
|
|
39
|
-
from typing import List, Optional, Union
|
|
44
|
+
from typing import DefaultDict, Iterable, List, Mapping, Optional, Tuple, Union
|
|
40
45
|
|
|
41
46
|
|
|
42
|
-
class
|
|
47
|
+
class _HandleTransitiveAction(Action):
|
|
43
48
|
def __init__(self, *args, **kwargs):
|
|
44
|
-
kwargs["nargs"] =
|
|
45
|
-
super(
|
|
49
|
+
kwargs["nargs"] = 0
|
|
50
|
+
super(_HandleTransitiveAction, self).__init__(*args, **kwargs)
|
|
46
51
|
|
|
47
52
|
def __call__(self, parser, namespace, value, option_str=None):
|
|
48
|
-
|
|
49
|
-
setattr(namespace, self.dest, None)
|
|
50
|
-
elif value.startswith("manylinux"):
|
|
51
|
-
setattr(namespace, self.dest, value)
|
|
52
|
-
else:
|
|
53
|
-
raise ArgumentTypeError(
|
|
54
|
-
"Please specify a manylinux standard; ie: --manylinux=manylinux1. "
|
|
55
|
-
"Given {}".format(value)
|
|
56
|
-
)
|
|
53
|
+
setattr(namespace, self.dest, option_str == "--transitive")
|
|
57
54
|
|
|
58
55
|
|
|
59
|
-
class
|
|
56
|
+
class _ResolveVenvAction(Action):
|
|
60
57
|
def __init__(self, *args, **kwargs):
|
|
61
|
-
kwargs["nargs"] =
|
|
62
|
-
super(
|
|
58
|
+
kwargs["nargs"] = "?"
|
|
59
|
+
super(_ResolveVenvAction, self).__init__(*args, default=[], **kwargs)
|
|
63
60
|
|
|
64
61
|
def __call__(self, parser, namespace, value, option_str=None):
|
|
65
|
-
|
|
62
|
+
venvs = getattr(namespace, self.dest)
|
|
63
|
+
if value:
|
|
64
|
+
if not os.path.exists(value):
|
|
65
|
+
raise ArgumentError(
|
|
66
|
+
argument=self,
|
|
67
|
+
message=(
|
|
68
|
+
"The {option} {value} does not point to an existing path.".format(
|
|
69
|
+
option=option_str, value=value
|
|
70
|
+
)
|
|
71
|
+
),
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
venv = None # type: Optional[Virtualenv]
|
|
75
|
+
if is_exe(value):
|
|
76
|
+
venv = Virtualenv.enclosing(value)
|
|
77
|
+
else:
|
|
78
|
+
try:
|
|
79
|
+
venv = Virtualenv(value)
|
|
80
|
+
except InvalidVirtualenvError:
|
|
81
|
+
pass
|
|
82
|
+
if not venv:
|
|
83
|
+
raise ArgumentError(
|
|
84
|
+
argument=self,
|
|
85
|
+
message=(
|
|
86
|
+
"The {option} {value} is not a valid virtual environment interpreter "
|
|
87
|
+
"path.".format(option=option_str, value=value)
|
|
88
|
+
),
|
|
89
|
+
)
|
|
90
|
+
venvs.append(venv)
|
|
91
|
+
else:
|
|
92
|
+
current_venv = Virtualenv.enclosing(python=sys.executable)
|
|
93
|
+
if not current_venv:
|
|
94
|
+
try:
|
|
95
|
+
current_venv = Virtualenv(venv_dir=".")
|
|
96
|
+
except InvalidVirtualenvError:
|
|
97
|
+
raise ArgumentError(
|
|
98
|
+
argument=self,
|
|
99
|
+
message=(
|
|
100
|
+
"The {option} option was requested but Pex is not currently running "
|
|
101
|
+
"from a venv to use as the implicit {option} nor is the current "
|
|
102
|
+
"directory a venv.\n"
|
|
103
|
+
"You'll need to specify the path to a virtual environment directory or "
|
|
104
|
+
"virtual environment interpreter as an argument.".format(
|
|
105
|
+
option=option_str
|
|
106
|
+
)
|
|
107
|
+
),
|
|
108
|
+
)
|
|
109
|
+
venvs.append(current_venv)
|
|
66
110
|
|
|
67
111
|
|
|
68
112
|
def register(
|
|
@@ -71,6 +115,7 @@ def register(
|
|
|
71
115
|
include_pex_lock=False, # type: bool
|
|
72
116
|
include_pylock=False, # type: bool
|
|
73
117
|
include_pre_resolved=False, # type: bool
|
|
118
|
+
include_venv_repository=False, # type: bool
|
|
74
119
|
):
|
|
75
120
|
# type: (...) -> None
|
|
76
121
|
"""Register resolver configuration options with the given parser.
|
|
@@ -81,6 +126,7 @@ def register(
|
|
|
81
126
|
:param include_pylock: Whether to include the `--pylock` / `--pep-751-lock` option.
|
|
82
127
|
:param include_pre_resolved: Whether to include the `--pre-resolved-dist` and
|
|
83
128
|
`--pre-resolved-dists` options.
|
|
129
|
+
:param include_venv_repository: Whether to include the `--venv-repository` option.
|
|
84
130
|
"""
|
|
85
131
|
|
|
86
132
|
default_resolver_configuration = PipConfiguration()
|
|
@@ -191,6 +237,8 @@ def register(
|
|
|
191
237
|
repository_types += 1
|
|
192
238
|
if include_pre_resolved:
|
|
193
239
|
repository_types += 1
|
|
240
|
+
if include_venv_repository:
|
|
241
|
+
repository_types += 1
|
|
194
242
|
|
|
195
243
|
repository_choice = parser.add_mutually_exclusive_group() if repository_types > 1 else parser
|
|
196
244
|
if include_pex_repository:
|
|
@@ -270,6 +318,23 @@ def register(
|
|
|
270
318
|
"default, Pex will ensure the dependencies added form a closure."
|
|
271
319
|
),
|
|
272
320
|
)
|
|
321
|
+
if include_venv_repository:
|
|
322
|
+
repository_choice.add_argument(
|
|
323
|
+
"--venv-repository",
|
|
324
|
+
dest="venv_repositories",
|
|
325
|
+
action=_ResolveVenvAction,
|
|
326
|
+
help=(
|
|
327
|
+
"Resolve requirements from the given virtual environment instead of from "
|
|
328
|
+
"--index servers, --find-links repos or a --lock file. The virtual environment to "
|
|
329
|
+
"resolve from can be specified as the path to the venv or the path of its"
|
|
330
|
+
"interpreter. If no value is specified, the current active venv is used. Multiple "
|
|
331
|
+
"virtual environments may be specified via multiple --venv-repository options and "
|
|
332
|
+
"the resolve will be the combined results. Each virtual environment will be "
|
|
333
|
+
"resolved from individually and must contain the full transitive closure of "
|
|
334
|
+
"requirements. This allows for creating a multi-platform PEX by specifying "
|
|
335
|
+
"multiple virtual environments; say one for Python 3.12 and one for Python 3.13."
|
|
336
|
+
),
|
|
337
|
+
)
|
|
273
338
|
|
|
274
339
|
parser.add_argument(
|
|
275
340
|
"--pre",
|
|
@@ -525,21 +590,64 @@ def register_repos_options(parser):
|
|
|
525
590
|
"-f",
|
|
526
591
|
"--find-links",
|
|
527
592
|
"--repo",
|
|
528
|
-
metavar="PATH/URL",
|
|
593
|
+
metavar="(NAME=)PATH/URL",
|
|
529
594
|
action="append",
|
|
530
595
|
dest="find_links",
|
|
531
596
|
type=str,
|
|
532
|
-
|
|
597
|
+
default=[],
|
|
598
|
+
help=(
|
|
599
|
+
"Additional repository path (directory or URL) to look for requirements. If the "
|
|
600
|
+
"repository should only be used as a source for a subset of distributions, you can "
|
|
601
|
+
"associate a name to refer to it by in `--source` mappings by using "
|
|
602
|
+
"`<name>=<path or url>` syntax, where the name cannot itself contain `=`. For example; "
|
|
603
|
+
"`local=/mnt/share/py/find-links` or `internal=https://dev.corp.internal/py-repo`."
|
|
604
|
+
),
|
|
533
605
|
)
|
|
534
606
|
parser.add_argument(
|
|
535
607
|
"-i",
|
|
536
608
|
"--index",
|
|
537
609
|
"--index-url",
|
|
538
|
-
metavar="URL",
|
|
610
|
+
metavar="(NAME=)URL",
|
|
539
611
|
action="append",
|
|
540
612
|
dest="indexes",
|
|
541
613
|
type=str,
|
|
542
|
-
|
|
614
|
+
default=[],
|
|
615
|
+
help=(
|
|
616
|
+
"Additional cheeseshop indices to use to satisfy requirements. If the index should "
|
|
617
|
+
"only be used as a source for a subset of distributions, you can associate a name to "
|
|
618
|
+
"refer to it by in `--source` mappings by using `<name>=<url>` syntax, where the name "
|
|
619
|
+
"itself cannot contain `=`. For example; internal=https://dev.corp.internal/py-simple`."
|
|
620
|
+
),
|
|
621
|
+
)
|
|
622
|
+
parser.add_argument(
|
|
623
|
+
"--source",
|
|
624
|
+
metavar="NAME=SCOPE",
|
|
625
|
+
action="append",
|
|
626
|
+
dest="repo_scopes",
|
|
627
|
+
type=str,
|
|
628
|
+
default=[],
|
|
629
|
+
help=(
|
|
630
|
+
"Defines a limited scope to use a named find links repo or index in. A source takes "
|
|
631
|
+
"the form `<name>=<scope>` where name is as defined for `--find-links` and `--index`; "
|
|
632
|
+
"namely a string not containing `=`. The scope can be a project name; e.g.: "
|
|
633
|
+
"`internal=torch` to resolve the `torch` project from the `internal` repo, a project "
|
|
634
|
+
"name and marker; e.g.: `internal=torch; sys_platform != 'darwin'` to resolve the "
|
|
635
|
+
"`torch` project from the `internal` repo unless targeting macOS, or just a marker; "
|
|
636
|
+
"e.g.: `piwheels=platform_machine == 'armv7l' to resolve from the `piwheels` repo "
|
|
637
|
+
"whenever 32bit arm machines are being targeted. N.B. wherever you use a project name "
|
|
638
|
+
"in a scope, you can use a regex instead."
|
|
639
|
+
),
|
|
640
|
+
)
|
|
641
|
+
parser.add_argument(
|
|
642
|
+
"--derive-sources-from-requirements-files",
|
|
643
|
+
dest="derive_scopes_from_requirements_files",
|
|
644
|
+
action=HandleBoolAction,
|
|
645
|
+
default=False,
|
|
646
|
+
help=(
|
|
647
|
+
"If any requirements files are specified that contain `-f` / `--find-links`, `-i` / "
|
|
648
|
+
"`--index-url`, or `--extra-index-url` options, automatically map these repos as the "
|
|
649
|
+
"`--source` for the requirements (if any) declared in that same requirements file."
|
|
650
|
+
),
|
|
543
651
|
)
|
|
544
652
|
|
|
545
653
|
|
|
@@ -632,6 +740,7 @@ if TYPE_CHECKING:
|
|
|
632
740
|
PipConfiguration,
|
|
633
741
|
PreResolvedConfiguration,
|
|
634
742
|
PylockRepositoryConfiguration,
|
|
743
|
+
VenvRepositoryConfiguration,
|
|
635
744
|
]
|
|
636
745
|
|
|
637
746
|
|
|
@@ -699,6 +808,18 @@ def configure(
|
|
|
699
808
|
sdists=tuple(sdists), wheels=tuple(wheels), pip_configuration=pip_configuration
|
|
700
809
|
)
|
|
701
810
|
|
|
811
|
+
venvs = getattr(options, "venv_repositories", None)
|
|
812
|
+
if venvs:
|
|
813
|
+
return VenvRepositoryConfiguration(venvs=tuple(venvs), pip_configuration=pip_configuration)
|
|
814
|
+
|
|
815
|
+
if pylock:
|
|
816
|
+
return PylockRepositoryConfiguration(
|
|
817
|
+
lock_file_path=pylock,
|
|
818
|
+
extras=frozenset(options.pylock_extras),
|
|
819
|
+
dependency_groups=frozenset(options.pylock_dependency_groups),
|
|
820
|
+
pip_configuration=pip_configuration,
|
|
821
|
+
)
|
|
822
|
+
|
|
702
823
|
return pip_configuration
|
|
703
824
|
|
|
704
825
|
|
|
@@ -766,17 +887,102 @@ def create_pip_configuration(
|
|
|
766
887
|
)
|
|
767
888
|
|
|
768
889
|
|
|
890
|
+
def _parse_repo_scope(repo_scope):
|
|
891
|
+
# type: (str) -> Tuple[str, Scope]
|
|
892
|
+
|
|
893
|
+
def create_invalid_error(footer=None):
|
|
894
|
+
# type: (Optional[str]) -> Exception
|
|
895
|
+
error_msg_lines = ["Invalid --source value: {source}".format(source=repo_scope)]
|
|
896
|
+
if footer:
|
|
897
|
+
error_msg_lines.append(footer)
|
|
898
|
+
return InvalidConfigurationError(os.linesep.join(error_msg_lines))
|
|
899
|
+
|
|
900
|
+
name, _, scope = repo_scope.partition("=")
|
|
901
|
+
if not scope:
|
|
902
|
+
raise create_invalid_error("A source must be of the form `<name>=<scope>`.")
|
|
903
|
+
try:
|
|
904
|
+
return name, Scope.parse(scope)
|
|
905
|
+
except ValueError as e:
|
|
906
|
+
raise create_invalid_error(str(e))
|
|
907
|
+
|
|
908
|
+
|
|
909
|
+
def _parse_package_repositories(
|
|
910
|
+
package_repository_type, # type: str
|
|
911
|
+
scopes_by_name, # type: Mapping[str, Iterable[Scope]]
|
|
912
|
+
repositories, # type: Iterable[str]
|
|
913
|
+
):
|
|
914
|
+
# type: (...) -> OrderedDict[str, Repo]
|
|
915
|
+
|
|
916
|
+
parsed = OrderedDict() # type: OrderedDict[str, List[str]]
|
|
917
|
+
for repository in repositories:
|
|
918
|
+
name, _, location = repository.partition("=")
|
|
919
|
+
if name in scopes_by_name:
|
|
920
|
+
parsed.setdefault(name, []).append(location)
|
|
921
|
+
else:
|
|
922
|
+
parsed.setdefault("", []).append(repository)
|
|
923
|
+
|
|
924
|
+
duplicate_names = [name for name, repos in parsed.items() if len(repos) > 1]
|
|
925
|
+
if duplicate_names:
|
|
926
|
+
raise InvalidConfigurationError(
|
|
927
|
+
"The following names are being re-used across multiple {package_repositories}: "
|
|
928
|
+
"{duplicate_names}\n"
|
|
929
|
+
"{package_repository} names must be unique.".format(
|
|
930
|
+
package_repositories=pluralize(2, package_repository_type),
|
|
931
|
+
duplicate_names=" ".join(sorted(duplicate_names)),
|
|
932
|
+
package_repository=package_repository_type.capitalize(),
|
|
933
|
+
)
|
|
934
|
+
)
|
|
935
|
+
|
|
936
|
+
package_repositories = OrderedDict() # type: OrderedDict[str, Repo]
|
|
937
|
+
for name, locations in parsed.items():
|
|
938
|
+
if name:
|
|
939
|
+
package_repositories[name] = Repo(locations[0], scopes=tuple(scopes_by_name[name]))
|
|
940
|
+
else:
|
|
941
|
+
package_repositories[""] = Repo(locations[0])
|
|
942
|
+
return package_repositories
|
|
943
|
+
|
|
944
|
+
|
|
769
945
|
def create_repos_configuration(options):
|
|
770
946
|
# type: (Namespace) -> ReposConfiguration
|
|
771
947
|
"""Creates a repos configuration from options registered by `register_repos_options`.
|
|
772
948
|
|
|
773
949
|
:param options: The Pip resolver configuration options.
|
|
774
950
|
"""
|
|
775
|
-
indexes = OrderedSet(
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
951
|
+
indexes = OrderedSet(([Repo(PYPI)] if options.pypi else [])) # type: OrderedSet[Repo]
|
|
952
|
+
scopes_by_name = defaultdict(OrderedSet) # type: DefaultDict[str, OrderedSet[Scope]]
|
|
953
|
+
for repo_scope in options.repo_scopes:
|
|
954
|
+
name, scope = _parse_repo_scope(repo_scope)
|
|
955
|
+
scopes_by_name[name].add(scope)
|
|
956
|
+
|
|
957
|
+
if not scopes_by_name:
|
|
958
|
+
indexes.update(Repo(index) for index in options.indexes)
|
|
959
|
+
return ReposConfiguration.create(
|
|
960
|
+
indexes=tuple(indexes),
|
|
961
|
+
find_links=tuple(Repo(find_links_repo) for find_links_repo in options.find_links),
|
|
962
|
+
derive_scopes_from_requirements_files=options.derive_scopes_from_requirements_files,
|
|
963
|
+
)
|
|
964
|
+
|
|
965
|
+
parsed_indexes = _parse_package_repositories("index", scopes_by_name, options.indexes)
|
|
966
|
+
parsed_find_links = _parse_package_repositories(
|
|
967
|
+
"find links repository", scopes_by_name, options.find_links
|
|
968
|
+
)
|
|
969
|
+
|
|
970
|
+
duplicate_names = set(parsed_indexes).intersection(parsed_find_links)
|
|
971
|
+
if duplicate_names:
|
|
972
|
+
raise InvalidConfigurationError(
|
|
973
|
+
"The following names are being re-used across indexes and find links repos: "
|
|
974
|
+
"{duplicate_names}\n"
|
|
975
|
+
"Package repository names must be unique.".format(
|
|
976
|
+
duplicate_names=" ".join(sorted(duplicate_names))
|
|
977
|
+
)
|
|
978
|
+
)
|
|
979
|
+
|
|
980
|
+
indexes.update(parsed_indexes.values())
|
|
981
|
+
return ReposConfiguration.create(
|
|
982
|
+
indexes=tuple(indexes),
|
|
983
|
+
find_links=tuple(parsed_find_links.values()),
|
|
984
|
+
derive_scopes_from_requirements_files=options.derive_scopes_from_requirements_files,
|
|
985
|
+
)
|
|
780
986
|
|
|
781
987
|
|
|
782
988
|
def create_network_configuration(options):
|
pex/resolve/resolvers.py
CHANGED
|
@@ -16,7 +16,6 @@ from pex.fingerprinted_distribution import FingerprintedDistribution
|
|
|
16
16
|
from pex.pep_427 import InstallableType
|
|
17
17
|
from pex.pep_503 import ProjectName
|
|
18
18
|
from pex.pip.version import PipVersionValue
|
|
19
|
-
from pex.resolve.lockfile.model import Lockfile
|
|
20
19
|
from pex.sorted_tuple import SortedTuple
|
|
21
20
|
from pex.targets import AbbreviatedPlatform, Target, Targets
|
|
22
21
|
from pex.typing import TYPE_CHECKING
|
|
@@ -247,17 +246,6 @@ class Resolver(object):
|
|
|
247
246
|
# type: () -> bool
|
|
248
247
|
raise NotImplementedError()
|
|
249
248
|
|
|
250
|
-
@abstractmethod
|
|
251
|
-
def resolve_lock(
|
|
252
|
-
self,
|
|
253
|
-
lock, # type: Lockfile
|
|
254
|
-
targets=Targets(), # type: Targets
|
|
255
|
-
pip_version=None, # type: Optional[PipVersionValue]
|
|
256
|
-
result_type=InstallableType.INSTALLED_WHEEL_CHROOT, # type: InstallableType.Value
|
|
257
|
-
):
|
|
258
|
-
# type: (...) -> ResolveResult
|
|
259
|
-
raise NotImplementedError()
|
|
260
|
-
|
|
261
249
|
@abstractmethod
|
|
262
250
|
def resolve_requirements(
|
|
263
251
|
self,
|
|
@@ -267,6 +255,9 @@ class Resolver(object):
|
|
|
267
255
|
transitive=None, # type: Optional[bool]
|
|
268
256
|
extra_resolver_requirements=None, # type: Optional[Tuple[Requirement, ...]]
|
|
269
257
|
result_type=InstallableType.INSTALLED_WHEEL_CHROOT, # type: InstallableType.Value
|
|
258
|
+
constraint_files=None, # type: Optional[Iterable[str]]
|
|
259
|
+
compile=False, # type: bool
|
|
260
|
+
ignore_errors=False, # type: bool
|
|
270
261
|
):
|
|
271
262
|
# type: (...) -> ResolveResult
|
|
272
263
|
raise NotImplementedError()
|
pex/resolve/target_options.py
CHANGED
|
@@ -6,7 +6,7 @@ from __future__ import absolute_import
|
|
|
6
6
|
import json
|
|
7
7
|
import os.path
|
|
8
8
|
import sys
|
|
9
|
-
from argparse import ArgumentTypeError, Namespace, _ActionsContainer
|
|
9
|
+
from argparse import Action, ArgumentTypeError, Namespace, _ActionsContainer
|
|
10
10
|
|
|
11
11
|
from pex.argparse import HandleBoolAction
|
|
12
12
|
from pex.interpreter_constraints import InterpreterConstraints
|
|
@@ -16,7 +16,6 @@ from pex.pep_508 import MarkerEnvironment
|
|
|
16
16
|
from pex.platforms import Platform, PlatformSpec
|
|
17
17
|
from pex.resolve import abbreviated_platforms
|
|
18
18
|
from pex.resolve.resolver_configuration import PipConfiguration
|
|
19
|
-
from pex.resolve.resolver_options import _ManylinuxAction
|
|
20
19
|
from pex.resolve.target_configuration import InterpreterConfiguration, TargetConfiguration
|
|
21
20
|
from pex.targets import CompletePlatform
|
|
22
21
|
from pex.typing import TYPE_CHECKING
|
|
@@ -25,6 +24,23 @@ if TYPE_CHECKING:
|
|
|
25
24
|
from typing import Optional
|
|
26
25
|
|
|
27
26
|
|
|
27
|
+
class _ManylinuxAction(Action):
|
|
28
|
+
def __init__(self, *args, **kwargs):
|
|
29
|
+
kwargs["nargs"] = "?"
|
|
30
|
+
super(_ManylinuxAction, self).__init__(*args, **kwargs)
|
|
31
|
+
|
|
32
|
+
def __call__(self, parser, namespace, value, option_str=None):
|
|
33
|
+
if option_str.startswith("--no"):
|
|
34
|
+
setattr(namespace, self.dest, None)
|
|
35
|
+
elif value.startswith("manylinux"):
|
|
36
|
+
setattr(namespace, self.dest, value)
|
|
37
|
+
else:
|
|
38
|
+
raise ArgumentTypeError(
|
|
39
|
+
"Please specify a manylinux standard; ie: --manylinux=manylinux1. "
|
|
40
|
+
"Given {}".format(value)
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
28
44
|
def register(
|
|
29
45
|
parser, # type: _ActionsContainer
|
|
30
46
|
include_platforms=True, # type: bool
|