Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
镜像
Python_Packaging_Authority
pip
提交
87aaae0e
P
pip
项目概览
镜像
/
Python_Packaging_Authority
/
pip
12 个月 前同步成功
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
pip
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
87aaae0e
编写于
4月 02, 2020
作者:
P
Paul Moore
提交者:
GitHub
4月 02, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #7942 from uranusjr/installed-candidate
New resolver: Installed candidate
上级
6086f71c
7511737e
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
206 addition
and
17 deletion
+206
-17
src/pip/_internal/resolution/resolvelib/candidates.py
src/pip/_internal/resolution/resolvelib/candidates.py
+71
-5
src/pip/_internal/resolution/resolvelib/factory.py
src/pip/_internal/resolution/resolvelib/factory.py
+69
-10
src/pip/_internal/resolution/resolvelib/requirements.py
src/pip/_internal/resolution/resolvelib/requirements.py
+2
-2
src/pip/_internal/resolution/resolvelib/resolver.py
src/pip/_internal/resolution/resolvelib/resolver.py
+1
-0
tests/functional/test_new_resolver.py
tests/functional/test_new_resolver.py
+62
-0
tests/unit/resolution_resolvelib/conftest.py
tests/unit/resolution_resolvelib/conftest.py
+1
-0
未找到文件。
src/pip/_internal/resolution/resolvelib/candidates.py
浏览文件 @
87aaae0e
...
...
@@ -14,7 +14,7 @@ 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
from
typing
import
Any
,
Optional
,
Sequence
,
Set
,
Tuple
,
Union
from
pip._vendor.packaging.version
import
_BaseVersion
from
pip._vendor.pkg_resources
import
Distribution
...
...
@@ -45,6 +45,28 @@ def make_install_req_from_link(link, parent):
)
def
make_install_req_from_dist
(
dist
,
parent
):
# type: (Distribution, InstallRequirement) -> InstallRequirement
# TODO: Do we need to support editables?
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
LinkCandidate
(
Candidate
):
def
__init__
(
self
,
link
,
parent
,
factory
):
# type: (Link, InstallRequirement, Factory) -> None
...
...
@@ -132,7 +154,48 @@ class LinkCandidate(Candidate):
return
self
.
_ireq
class
ExtrasCandidate
(
LinkCandidate
):
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
)
@
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
...
...
@@ -156,11 +219,14 @@ class ExtrasCandidate(LinkCandidate):
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
,
extras
):
# type: (LinkCandidate, Set[str]) -> None
def
__init__
(
self
,
base
,
# type: Union[AlreadyInstalledCandidate, LinkCandidate]
extras
,
# type: Set[str]
):
# type: (...) -> None
self
.
base
=
base
self
.
extras
=
extras
self
.
link
=
base
.
link
@
property
def
name
(
self
):
...
...
src/pip/_internal/resolution/resolvelib/factory.py
浏览文件 @
87aaae0e
from
pip._vendor.pkg_resources
import
(
DistributionNotFound
,
VersionConflict
,
get_distribution
,
)
from
pip._internal.utils.typing
import
MYPY_CHECK_RUNNING
from
.candidates
import
ExtrasCandidate
,
LinkCandidate
,
RequiresPythonCandidate
from
.candidates
import
(
AlreadyInstalledCandidate
,
ExtrasCandidate
,
LinkCandidate
,
RequiresPythonCandidate
,
)
from
.requirements
import
(
ExplicitRequirement
,
NoMatchRequirement
,
...
...
@@ -11,8 +22,10 @@ if MYPY_CHECK_RUNNING:
from
typing
import
Dict
,
Optional
,
Set
,
Tuple
from
pip._vendor.packaging.specifiers
import
SpecifierSet
from
pip._vendor.pkg_resources
import
Distribution
from
pip._internal.index.package_finder
import
PackageFinder
from
pip._internal.models.candidate
import
InstallationCandidate
from
pip._internal.models.link
import
Link
from
pip._internal.operations.prepare
import
RequirementPreparer
from
pip._internal.req.req_install
import
InstallRequirement
...
...
@@ -27,6 +40,7 @@ class Factory(object):
finder
,
# type: PackageFinder
preparer
,
# type: RequirementPreparer
make_install_req
,
# type: InstallRequirementProvider
ignore_installed
,
# type: bool
ignore_requires_python
,
# type: bool
py_version_info
=
None
,
# type: Optional[Tuple[int, ...]]
):
...
...
@@ -34,33 +48,78 @@ class Factory(object):
self
.
finder
=
finder
self
.
preparer
=
preparer
self
.
_python_candidate
=
RequiresPythonCandidate
(
py_version_info
)
self
.
_ignore_requires_python
=
ignore_requires_python
self
.
_make_install_req_from_spec
=
make_install_req
self
.
_candidate_cache
=
{}
# type: Dict[Link, LinkCandidate]
self
.
_ignore_installed
=
ignore_installed
self
.
_ignore_requires_python
=
ignore_requires_python
self
.
_link_candidate_cache
=
{}
# type: Dict[Link, LinkCandidate]
def
make_candidate
(
def
_make_candidate_from_dist
(
self
,
dist
,
# type: Distribution
extras
,
# type: Set[str]
parent
,
# type: InstallRequirement
):
# type: (...) -> Candidate
base
=
AlreadyInstalledCandidate
(
dist
,
parent
,
factory
=
self
)
if
extras
:
return
ExtrasCandidate
(
base
,
extras
)
return
base
def
_make_candidate_from_link
(
self
,
link
,
# type: Link
extras
,
# type: Set[str]
parent
,
# type: InstallRequirement
):
# type: (...) -> Candidate
if
link
not
in
self
.
_candidate_cache
:
self
.
_candidate_cache
[
link
]
=
LinkCandidate
(
if
link
not
in
self
.
_
link_
candidate_cache
:
self
.
_
link_
candidate_cache
[
link
]
=
LinkCandidate
(
link
,
parent
,
factory
=
self
,
)
base
=
self
.
_candidate_cache
[
link
]
base
=
self
.
_
link_
candidate_cache
[
link
]
if
extras
:
return
ExtrasCandidate
(
base
,
extras
)
return
base
def
_get_installed_distribution
(
self
,
name
,
version
):
# type: (str, str) -> Optional[Distribution]
if
self
.
_ignore_installed
:
return
None
specifier
=
"{}=={}"
.
format
(
name
,
version
)
try
:
dist
=
get_distribution
(
specifier
)
except
(
DistributionNotFound
,
VersionConflict
):
return
None
return
dist
def
make_candidate_from_ican
(
self
,
ican
,
# type: InstallationCandidate
extras
,
# type: Set[str]
parent
,
# type: InstallRequirement
):
# type: (...) -> Candidate
dist
=
self
.
_get_installed_distribution
(
ican
.
name
,
ican
.
version
)
if
dist
is
None
:
return
self
.
_make_candidate_from_link
(
link
=
ican
.
link
,
extras
=
extras
,
parent
=
parent
,
)
return
self
.
_make_candidate_from_dist
(
dist
=
dist
,
extras
=
extras
,
parent
=
parent
,
)
def
make_requirement_from_install_req
(
self
,
ireq
):
# type: (InstallRequirement) -> Requirement
if
ireq
.
link
:
cand
=
self
.
make_candidate
(
ireq
.
link
,
extras
=
set
(),
parent
=
ireq
)
cand
=
self
.
_make_candidate_from_link
(
ireq
.
link
,
extras
=
set
(),
parent
=
ireq
,
)
return
ExplicitRequirement
(
cand
)
else
:
return
SpecifierRequirement
(
ireq
,
factory
=
self
)
return
SpecifierRequirement
(
ireq
,
factory
=
self
)
def
make_requirement_from_spec
(
self
,
specifier
,
comes_from
):
# type: (str, InstallRequirement) -> Requirement
...
...
src/pip/_internal/resolution/resolvelib/requirements.py
浏览文件 @
87aaae0e
...
...
@@ -79,8 +79,8 @@ class SpecifierRequirement(Requirement):
hashes
=
self
.
_ireq
.
hashes
(
trust_internet
=
False
),
)
return
[
self
.
_factory
.
make_candidate
(
link
=
ican
.
link
,
self
.
_factory
.
make_candidate
_from_ican
(
ican
=
ican
,
extras
=
self
.
extras
,
parent
=
self
.
_ireq
,
)
...
...
src/pip/_internal/resolution/resolvelib/resolver.py
浏览文件 @
87aaae0e
...
...
@@ -43,6 +43,7 @@ class Resolver(BaseResolver):
finder
=
finder
,
preparer
=
preparer
,
make_install_req
=
make_install_req
,
ignore_installed
=
ignore_installed
,
ignore_requires_python
=
ignore_requires_python
,
py_version_info
=
py_version_info
,
)
...
...
tests/functional/test_new_resolver.py
浏览文件 @
87aaae0e
...
...
@@ -191,3 +191,65 @@ def test_new_resolver_requires_python(
script
.
pip
(
*
args
)
assert_installed
(
script
,
base
=
"0.1.0"
,
dep
=
dep_version
)
def
test_new_resolver_installed
(
script
):
create_basic_wheel_for_package
(
script
,
"base"
,
"0.1.0"
,
depends
=
[
"dep"
],
)
create_basic_wheel_for_package
(
script
,
"dep"
,
"0.1.0"
,
)
satisfied_output
=
"Requirement already satisfied: base==0.1.0 in"
result
=
script
.
pip
(
"install"
,
"--unstable-feature=resolver"
,
"--no-cache-dir"
,
"--no-index"
,
"--find-links"
,
script
.
scratch_path
,
"base"
,
)
assert
satisfied_output
not
in
result
.
stdout
,
str
(
result
)
result
=
script
.
pip
(
"install"
,
"--unstable-feature=resolver"
,
"--no-cache-dir"
,
"--no-index"
,
"--find-links"
,
script
.
scratch_path
,
"base"
,
)
assert
satisfied_output
in
result
.
stdout
,
str
(
result
)
assert
script
.
site_packages
/
"base"
not
in
result
.
files_updated
,
(
"base 0.1.0 reinstalled"
)
def
test_new_resolver_ignore_installed
(
script
):
create_basic_wheel_for_package
(
script
,
"base"
,
"0.1.0"
,
)
satisfied_output
=
"Requirement already satisfied: base==0.1.0 in"
result
=
script
.
pip
(
"install"
,
"--unstable-feature=resolver"
,
"--no-cache-dir"
,
"--no-index"
,
"--find-links"
,
script
.
scratch_path
,
"base"
,
)
assert
satisfied_output
not
in
result
.
stdout
,
str
(
result
)
result
=
script
.
pip
(
"install"
,
"--unstable-feature=resolver"
,
"--no-cache-dir"
,
"--no-index"
,
"--ignore-installed"
,
"--find-links"
,
script
.
scratch_path
,
"base"
,
)
assert
satisfied_output
not
in
result
.
stdout
,
str
(
result
)
assert
script
.
site_packages
/
"base"
in
result
.
files_updated
,
(
"base 0.1.0 not reinstalled"
)
tests/unit/resolution_resolvelib/conftest.py
浏览文件 @
87aaae0e
...
...
@@ -52,6 +52,7 @@ def factory(finder, preparer):
finder
=
finder
,
preparer
=
preparer
,
make_install_req
=
install_req_from_line
,
ignore_installed
=
False
,
ignore_requires_python
=
False
,
py_version_info
=
None
,
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录