Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
news
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Sartika Aritonang
news
Commits
c8536afc
Commit
c8536afc
authored
May 29, 2020
by
Sartika Aritonang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Upload New File
parent
d88c8e75
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
450 additions
and
0 deletions
+450
-0
candidates.py
...ackages/pip/_internal/resolution/resolvelib/candidates.py
+450
-0
No files found.
stbi/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py
0 → 100644
View file @
c8536afc
import
logging
import
sys
from
pip._vendor.packaging.specifiers
import
InvalidSpecifier
,
SpecifierSet
from
pip._vendor.packaging.utils
import
canonicalize_name
from
pip._vendor.packaging.version
import
Version
from
pip._internal.req.constructors
import
(
install_req_from_editable
,
install_req_from_line
,
)
from
pip._internal.req.req_install
import
InstallRequirement
from
pip._internal.utils.misc
import
normalize_version_info
from
pip._internal.utils.packaging
import
get_requires_python
from
pip._internal.utils.typing
import
MYPY_CHECK_RUNNING
from
.base
import
Candidate
,
format_name
if
MYPY_CHECK_RUNNING
:
from
typing
import
Any
,
Optional
,
Sequence
,
Set
,
Tuple
,
Union
from
pip._vendor.packaging.version
import
_BaseVersion
from
pip._vendor.pkg_resources
import
Distribution
from
pip._internal.distributions
import
AbstractDistribution
from
pip._internal.models.link
import
Link
from
.base
import
Requirement
from
.factory
import
Factory
BaseCandidate
=
Union
[
"AlreadyInstalledCandidate"
,
"EditableCandidate"
,
"LinkCandidate"
,
]
logger
=
logging
.
getLogger
(
__name__
)
def
make_install_req_from_link
(
link
,
parent
):
# type: (Link, InstallRequirement) -> InstallRequirement
assert
not
parent
.
editable
,
"parent is editable"
return
install_req_from_line
(
link
.
url
,
comes_from
=
parent
.
comes_from
,
use_pep517
=
parent
.
use_pep517
,
isolated
=
parent
.
isolated
,
constraint
=
parent
.
constraint
,
options
=
dict
(
install_options
=
parent
.
install_options
,
global_options
=
parent
.
global_options
,
hashes
=
parent
.
hash_options
),
)
def
make_install_req_from_editable
(
link
,
parent
):
# type: (Link, InstallRequirement) -> InstallRequirement
assert
parent
.
editable
,
"parent not editable"
return
install_req_from_editable
(
link
.
url
,
comes_from
=
parent
.
comes_from
,
use_pep517
=
parent
.
use_pep517
,
isolated
=
parent
.
isolated
,
constraint
=
parent
.
constraint
,
options
=
dict
(
install_options
=
parent
.
install_options
,
global_options
=
parent
.
global_options
,
hashes
=
parent
.
hash_options
),
)
def
make_install_req_from_dist
(
dist
,
parent
):
# type: (Distribution, InstallRequirement) -> InstallRequirement
ireq
=
install_req_from_line
(
"{}=={}"
.
format
(
canonicalize_name
(
dist
.
project_name
),
dist
.
parsed_version
,
),
comes_from
=
parent
.
comes_from
,
use_pep517
=
parent
.
use_pep517
,
isolated
=
parent
.
isolated
,
constraint
=
parent
.
constraint
,
options
=
dict
(
install_options
=
parent
.
install_options
,
global_options
=
parent
.
global_options
,
hashes
=
parent
.
hash_options
),
)
ireq
.
satisfied_by
=
dist
return
ireq
class
_InstallRequirementBackedCandidate
(
Candidate
):
def
__init__
(
self
,
link
,
# type: Link
ireq
,
# type: InstallRequirement
factory
,
# type: Factory
name
=
None
,
# type: Optional[str]
version
=
None
,
# type: Optional[_BaseVersion]
):
# type: (...) -> None
self
.
link
=
link
self
.
_factory
=
factory
self
.
_ireq
=
ireq
self
.
_name
=
name
self
.
_version
=
version
self
.
_dist
=
None
# type: Optional[Distribution]
def
__repr__
(
self
):
# type: () -> str
return
"{class_name}({link!r})"
.
format
(
class_name
=
self
.
__class__
.
__name__
,
link
=
str
(
self
.
link
),
)
def
__eq__
(
self
,
other
):
# type: (Any) -> bool
if
isinstance
(
other
,
self
.
__class__
):
return
self
.
link
==
other
.
link
return
False
# Needed for Python 2, which does not implement this by default
def
__ne__
(
self
,
other
):
# type: (Any) -> bool
return
not
self
.
__eq__
(
other
)
@property
def
name
(
self
):
# type: () -> str
"""The normalised name of the project the candidate refers to"""
if
self
.
_name
is
None
:
self
.
_name
=
canonicalize_name
(
self
.
dist
.
project_name
)
return
self
.
_name
@property
def
version
(
self
):
# type: () -> _BaseVersion
if
self
.
_version
is
None
:
self
.
_version
=
self
.
dist
.
parsed_version
return
self
.
_version
def
_prepare_abstract_distribution
(
self
):
# type: () -> AbstractDistribution
raise
NotImplementedError
(
"Override in subclass"
)
def
_prepare
(
self
):
# type: () -> None
if
self
.
_dist
is
not
None
:
return
abstract_dist
=
self
.
_prepare_abstract_distribution
()
self
.
_dist
=
abstract_dist
.
get_pkg_resources_distribution
()
assert
self
.
_dist
is
not
None
,
"Distribution already installed"
# TODO: Abort cleanly here, as the resolution has been
# based on the wrong name/version until now, and
# so is wrong.
# TODO: (Longer term) Rather than abort, reject this candidate
# and backtrack. This would need resolvelib support.
# These should be "proper" errors, not just asserts, as they
# can result from user errors like a requirement "foo @ URL"
# when the project at URL has a name of "bar" in its metadata.
assert
(
self
.
_name
is
None
or
self
.
_name
==
canonicalize_name
(
self
.
_dist
.
project_name
)
),
"Name mismatch: {!r} vs {!r}"
.
format
(
self
.
_name
,
canonicalize_name
(
self
.
_dist
.
project_name
),
)
assert
(
self
.
_version
is
None
or
self
.
_version
==
self
.
_dist
.
parsed_version
),
"Version mismatch: {!r} vs {!r}"
.
format
(
self
.
_version
,
self
.
_dist
.
parsed_version
,
)
@property
def
dist
(
self
):
# type: () -> Distribution
self
.
_prepare
()
return
self
.
_dist
def
_get_requires_python_specifier
(
self
):
# type: () -> Optional[SpecifierSet]
requires_python
=
get_requires_python
(
self
.
dist
)
if
requires_python
is
None
:
return
None
try
:
spec
=
SpecifierSet
(
requires_python
)
except
InvalidSpecifier
as
e
:
logger
.
warning
(
"Package
%
r has an invalid Requires-Python:
%
s"
,
self
.
name
,
e
,
)
return
None
return
spec
def
get_dependencies
(
self
):
# type: () -> Sequence[Requirement]
deps
=
[
self
.
_factory
.
make_requirement_from_spec
(
str
(
r
),
self
.
_ireq
)
for
r
in
self
.
dist
.
requires
()
]
python_dep
=
self
.
_factory
.
make_requires_python_requirement
(
self
.
_get_requires_python_specifier
(),
)
if
python_dep
:
deps
.
append
(
python_dep
)
return
deps
def
get_install_requirement
(
self
):
# type: () -> Optional[InstallRequirement]
self
.
_prepare
()
return
self
.
_ireq
class
LinkCandidate
(
_InstallRequirementBackedCandidate
):
def
__init__
(
self
,
link
,
# type: Link
parent
,
# type: InstallRequirement
factory
,
# type: Factory
name
=
None
,
# type: Optional[str]
version
=
None
,
# type: Optional[_BaseVersion]
):
# type: (...) -> None
super
(
LinkCandidate
,
self
)
.
__init__
(
link
=
link
,
ireq
=
make_install_req_from_link
(
link
,
parent
),
factory
=
factory
,
name
=
name
,
version
=
version
,
)
def
_prepare_abstract_distribution
(
self
):
# type: () -> AbstractDistribution
return
self
.
_factory
.
preparer
.
prepare_linked_requirement
(
self
.
_ireq
)
class
EditableCandidate
(
_InstallRequirementBackedCandidate
):
def
__init__
(
self
,
link
,
# type: Link
parent
,
# type: InstallRequirement
factory
,
# type: Factory
name
=
None
,
# type: Optional[str]
version
=
None
,
# type: Optional[_BaseVersion]
):
# type: (...) -> None
super
(
EditableCandidate
,
self
)
.
__init__
(
link
=
link
,
ireq
=
make_install_req_from_editable
(
link
,
parent
),
factory
=
factory
,
name
=
name
,
version
=
version
,
)
def
_prepare_abstract_distribution
(
self
):
# type: () -> AbstractDistribution
return
self
.
_factory
.
preparer
.
prepare_editable_requirement
(
self
.
_ireq
)
class
AlreadyInstalledCandidate
(
Candidate
):
def
__init__
(
self
,
dist
,
# type: Distribution
parent
,
# type: InstallRequirement
factory
,
# type: Factory
):
# type: (...) -> None
self
.
dist
=
dist
self
.
_ireq
=
make_install_req_from_dist
(
dist
,
parent
)
self
.
_factory
=
factory
# This is just logging some messages, so we can do it eagerly.
# The returned dist would be exactly the same as self.dist because we
# set satisfied_by in make_install_req_from_dist.
# TODO: Supply reason based on force_reinstall and upgrade_strategy.
skip_reason
=
"already satisfied"
factory
.
preparer
.
prepare_installed_requirement
(
self
.
_ireq
,
skip_reason
)
def
__repr__
(
self
):
# type: () -> str
return
"{class_name}({distribution!r})"
.
format
(
class_name
=
self
.
__class__
.
__name__
,
distribution
=
self
.
dist
,
)
def
__eq__
(
self
,
other
):
# type: (Any) -> bool
if
isinstance
(
other
,
self
.
__class__
):
return
self
.
name
==
other
.
name
and
self
.
version
==
other
.
version
return
False
# Needed for Python 2, which does not implement this by default
def
__ne__
(
self
,
other
):
# type: (Any) -> bool
return
not
self
.
__eq__
(
other
)
@property
def
name
(
self
):
# type: () -> str
return
canonicalize_name
(
self
.
dist
.
project_name
)
@property
def
version
(
self
):
# type: () -> _BaseVersion
return
self
.
dist
.
parsed_version
def
get_dependencies
(
self
):
# type: () -> Sequence[Requirement]
return
[
self
.
_factory
.
make_requirement_from_spec
(
str
(
r
),
self
.
_ireq
)
for
r
in
self
.
dist
.
requires
()
]
def
get_install_requirement
(
self
):
# type: () -> Optional[InstallRequirement]
return
None
class
ExtrasCandidate
(
Candidate
):
"""A candidate that has 'extras', indicating additional dependencies.
Requirements can be for a project with dependencies, something like
foo[extra]. The extras don't affect the project/version being installed
directly, but indicate that we need additional dependencies. We model that
by having an artificial ExtrasCandidate that wraps the "base" candidate.
The ExtrasCandidate differs from the base in the following ways:
1. It has a unique name, of the form foo[extra]. This causes the resolver
to treat it as a separate node in the dependency graph.
2. When we're getting the candidate's dependencies,
a) We specify that we want the extra dependencies as well.
b) We add a dependency on the base candidate (matching the name and
version). See below for why this is needed.
3. We return None for the underlying InstallRequirement, as the base
candidate will provide it, and we don't want to end up with duplicates.
The dependency on the base candidate is needed so that the resolver can't
decide that it should recommend foo[extra1] version 1.0 and foo[extra2]
version 2.0. Having those candidates depend on foo=1.0 and foo=2.0
respectively forces the resolver to recognise that this is a conflict.
"""
def
__init__
(
self
,
base
,
# type: BaseCandidate
extras
,
# type: Set[str]
):
# type: (...) -> None
self
.
base
=
base
self
.
extras
=
extras
def
__repr__
(
self
):
# type: () -> str
return
"{class_name}(base={base!r}, extras={extras!r})"
.
format
(
class_name
=
self
.
__class__
.
__name__
,
base
=
self
.
base
,
extras
=
self
.
extras
,
)
def
__eq__
(
self
,
other
):
# type: (Any) -> bool
if
isinstance
(
other
,
self
.
__class__
):
return
self
.
base
==
other
.
base
and
self
.
extras
==
other
.
extras
return
False
# Needed for Python 2, which does not implement this by default
def
__ne__
(
self
,
other
):
# type: (Any) -> bool
return
not
self
.
__eq__
(
other
)
@property
def
name
(
self
):
# type: () -> str
"""The normalised name of the project the candidate refers to"""
return
format_name
(
self
.
base
.
name
,
self
.
extras
)
@property
def
version
(
self
):
# type: () -> _BaseVersion
return
self
.
base
.
version
def
get_dependencies
(
self
):
# type: () -> Sequence[Requirement]
factory
=
self
.
base
.
_factory
# The user may have specified extras that the candidate doesn't
# support. We ignore any unsupported extras here.
valid_extras
=
self
.
extras
.
intersection
(
self
.
base
.
dist
.
extras
)
invalid_extras
=
self
.
extras
.
difference
(
self
.
base
.
dist
.
extras
)
if
invalid_extras
:
logger
.
warning
(
"Invalid extras specified in
%
s:
%
s"
,
self
.
name
,
','
.
join
(
sorted
(
invalid_extras
))
)
deps
=
[
factory
.
make_requirement_from_spec
(
str
(
r
),
self
.
base
.
_ireq
)
for
r
in
self
.
base
.
dist
.
requires
(
valid_extras
)
]
# Add a dependency on the exact base.
# (See note 2b in the class docstring)
spec
=
"{}=={}"
.
format
(
self
.
base
.
name
,
self
.
base
.
version
)
deps
.
append
(
factory
.
make_requirement_from_spec
(
spec
,
self
.
base
.
_ireq
))
return
deps
def
get_install_requirement
(
self
):
# type: () -> Optional[InstallRequirement]
# We don't return anything here, because we always
# depend on the base candidate, and we'll get the
# install requirement from that.
return
None
class
RequiresPythonCandidate
(
Candidate
):
def
__init__
(
self
,
py_version_info
):
# type: (Optional[Tuple[int, ...]]) -> None
if
py_version_info
is
not
None
:
version_info
=
normalize_version_info
(
py_version_info
)
else
:
version_info
=
sys
.
version_info
[:
3
]
self
.
_version
=
Version
(
"."
.
join
(
str
(
c
)
for
c
in
version_info
))
# We don't need to implement __eq__() and __ne__() since there is always
# only one RequiresPythonCandidate in a resolution, i.e. the host Python.
# The built-in object.__eq__() and object.__ne__() do exactly what we want.
@property
def
name
(
self
):
# type: () -> str
# Avoid conflicting with the PyPI package "Python".
return
"<Python fom Requires-Python>"
@property
def
version
(
self
):
# type: () -> _BaseVersion
return
self
.
_version
def
get_dependencies
(
self
):
# type: () -> Sequence[Requirement]
return
[]
def
get_install_requirement
(
self
):
# type: () -> Optional[InstallRequirement]
return
None
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment