Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
镜像
Python_Packaging_Authority
pip
提交
6086f71c
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,发现更多精彩内容 >>
未验证
提交
6086f71c
编写于
4月 02, 2020
作者:
P
Paul Moore
提交者:
GitHub
4月 02, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #7960 from uranusjr/requires-python-2
Requires-Python implementation, take 2
上级
c88fa395
557f7670
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
181 addition
and
12 deletion
+181
-12
src/pip/_internal/resolution/resolvelib/candidates.py
src/pip/_internal/resolution/resolvelib/candidates.py
+58
-4
src/pip/_internal/resolution/resolvelib/factory.py
src/pip/_internal/resolution/resolvelib/factory.py
+26
-3
src/pip/_internal/resolution/resolvelib/requirements.py
src/pip/_internal/resolution/resolvelib/requirements.py
+24
-0
src/pip/_internal/resolution/resolvelib/resolver.py
src/pip/_internal/resolution/resolvelib/resolver.py
+2
-0
tests/functional/test_new_resolver.py
tests/functional/test_new_resolver.py
+54
-0
tests/lib/__init__.py
tests/lib/__init__.py
+15
-5
tests/unit/resolution_resolvelib/conftest.py
tests/unit/resolution_resolvelib/conftest.py
+2
-0
未找到文件。
src/pip/_internal/resolution/resolvelib/candidates.py
浏览文件 @
6086f71c
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_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
from
pip._internal.models.link
import
Link
from
typing
import
Any
,
Optional
,
Sequence
,
Set
,
Tuple
from
pip._vendor.packaging.version
import
_BaseVersion
from
pip._vendor.pkg_resources
import
Distribution
from
pip._internal.models.link
import
Link
from
.base
import
Requirement
from
.factory
import
Factory
...
...
@@ -95,12 +100,32 @@ class LinkCandidate(Candidate):
self
.
_version
==
self
.
dist
.
parsed_version
)
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]
return
[
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]
...
...
@@ -179,3 +204,32 @@ class ExtrasCandidate(LinkCandidate):
# 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
))
@
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
src/pip/_internal/resolution/resolvelib/factory.py
浏览文件 @
6086f71c
from
pip._internal.utils.typing
import
MYPY_CHECK_RUNNING
from
.candidates
import
ExtrasCandidate
,
LinkCandidate
from
.requirements
import
ExplicitRequirement
,
SpecifierRequirement
from
.candidates
import
ExtrasCandidate
,
LinkCandidate
,
RequiresPythonCandidate
from
.requirements
import
(
ExplicitRequirement
,
NoMatchRequirement
,
SpecifierRequirement
,
)
if
MYPY_CHECK_RUNNING
:
from
typing
import
Dict
,
Set
from
typing
import
Dict
,
Optional
,
Set
,
Tuple
from
pip._vendor.packaging.specifiers
import
SpecifierSet
from
pip._internal.index.package_finder
import
PackageFinder
from
pip._internal.models.link
import
Link
...
...
@@ -21,10 +27,14 @@ class Factory(object):
finder
,
# type: PackageFinder
preparer
,
# type: RequirementPreparer
make_install_req
,
# type: InstallRequirementProvider
ignore_requires_python
,
# type: bool
py_version_info
=
None
,
# type: Optional[Tuple[int, ...]]
):
# type: (...) -> None
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]
...
...
@@ -56,3 +66,16 @@ class Factory(object):
# type: (str, InstallRequirement) -> Requirement
ireq
=
self
.
_make_install_req_from_spec
(
specifier
,
comes_from
)
return
self
.
make_requirement_from_install_req
(
ireq
)
def
make_requires_python_requirement
(
self
,
specifier
):
# type: (Optional[SpecifierSet]) -> Optional[Requirement]
if
self
.
_ignore_requires_python
or
specifier
is
None
:
return
None
# The logic here is different from SpecifierRequirement, for which we
# "find" candidates matching the specifier. But for Requires-Python,
# there is always exactly one candidate (the one specified with
# py_version_info). Here we decide whether to return that based on
# whether Requires-Python matches that one candidate or not.
if
self
.
_python_candidate
.
version
in
specifier
:
return
ExplicitRequirement
(
self
.
_python_candidate
)
return
NoMatchRequirement
(
self
.
_python_candidate
.
name
)
src/pip/_internal/resolution/resolvelib/requirements.py
浏览文件 @
6086f71c
...
...
@@ -33,6 +33,30 @@ class ExplicitRequirement(Requirement):
return
candidate
==
self
.
candidate
class
NoMatchRequirement
(
Requirement
):
"""A requirement that never matches anything.
Note: Similar to ExplicitRequirement, the caller should handle name
canonicalisation; this class does not perform it.
"""
def
__init__
(
self
,
name
):
# type: (str) -> None
self
.
_name
=
name
@
property
def
name
(
self
):
# type: () -> str
return
self
.
_name
def
find_matches
(
self
):
# type: () -> Sequence[Candidate]
return
[]
def
is_satisfied_by
(
self
,
candidate
):
# type: (Candidate) -> bool
return
False
class
SpecifierRequirement
(
Requirement
):
def
__init__
(
self
,
ireq
,
factory
):
# type: (InstallRequirement, Factory) -> None
...
...
src/pip/_internal/resolution/resolvelib/resolver.py
浏览文件 @
6086f71c
...
...
@@ -43,6 +43,8 @@ class Resolver(BaseResolver):
finder
=
finder
,
preparer
=
preparer
,
make_install_req
=
make_install_req
,
ignore_requires_python
=
ignore_requires_python
,
py_version_info
=
py_version_info
,
)
self
.
ignore_dependencies
=
ignore_dependencies
self
.
_result
=
None
# type: Optional[Result]
...
...
tests/functional/test_new_resolver.py
浏览文件 @
6086f71c
import
json
import
pytest
from
tests.lib
import
create_basic_wheel_for_package
...
...
@@ -137,3 +139,55 @@ def test_new_resolver_installs_extras(script):
assert
"WARNING: Invalid extras specified"
in
result
.
stderr
,
str
(
result
)
assert
": missing"
in
result
.
stderr
,
str
(
result
)
assert_installed
(
script
,
base
=
"0.1.0"
,
dep
=
"0.1.0"
)
@
pytest
.
mark
.
parametrize
(
"requires_python, ignore_requires_python, dep_version"
,
[
# Something impossible to satisfy.
(
"<2"
,
False
,
"0.1.0"
),
(
"<2"
,
True
,
"0.2.0"
),
# Something guaranteed to satisfy.
(
">=2"
,
False
,
"0.2.0"
),
(
">=2"
,
True
,
"0.2.0"
),
],
)
def
test_new_resolver_requires_python
(
script
,
requires_python
,
ignore_requires_python
,
dep_version
,
):
create_basic_wheel_for_package
(
script
,
"base"
,
"0.1.0"
,
depends
=
[
"dep"
],
)
create_basic_wheel_for_package
(
script
,
"dep"
,
"0.1.0"
,
)
create_basic_wheel_for_package
(
script
,
"dep"
,
"0.2.0"
,
requires_python
=
requires_python
,
)
args
=
[
"install"
,
"--unstable-feature=resolver"
,
"--no-cache-dir"
,
"--no-index"
,
"--find-links"
,
script
.
scratch_path
,
]
if
ignore_requires_python
:
args
.
append
(
"--ignore-requires-python"
)
args
.
append
(
"base"
)
script
.
pip
(
*
args
)
assert_installed
(
script
,
base
=
"0.1.0"
,
dep
=
dep_version
)
tests/lib/__init__.py
浏览文件 @
6086f71c
...
...
@@ -979,7 +979,13 @@ def create_really_basic_wheel(name, version):
def
create_basic_wheel_for_package
(
script
,
name
,
version
,
depends
=
None
,
extras
=
None
,
extra_files
=
None
script
,
name
,
version
,
depends
=
None
,
extras
=
None
,
requires_python
=
None
,
extra_files
=
None
,
):
if
depends
is
None
:
depends
=
[]
...
...
@@ -1007,14 +1013,18 @@ def create_basic_wheel_for_package(
for
package
in
packages
]
metadata_updates
=
{
"Provides-Extra"
:
list
(
extras
),
"Requires-Dist"
:
requires_dist
,
}
if
requires_python
is
not
None
:
metadata_updates
[
"Requires-Python"
]
=
requires_python
wheel_builder
=
make_wheel
(
name
=
name
,
version
=
version
,
wheel_metadata_updates
=
{
"Tag"
:
[
"py2-none-any"
,
"py3-none-any"
]},
metadata_updates
=
{
"Provides-Extra"
:
list
(
extras
),
"Requires-Dist"
:
requires_dist
,
},
metadata_updates
=
metadata_updates
,
extra_metadata_files
=
{
"top_level.txt"
:
name
},
extra_files
=
extra_files
,
...
...
tests/unit/resolution_resolvelib/conftest.py
浏览文件 @
6086f71c
...
...
@@ -52,6 +52,8 @@ def factory(finder, preparer):
finder
=
finder
,
preparer
=
preparer
,
make_install_req
=
install_req_from_line
,
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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录