Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
后端镜像
Pdm
提交
57068eac
P
Pdm
项目概览
后端镜像
/
Pdm
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Pdm
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
57068eac
编写于
1月 19, 2020
作者:
F
frostming
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix code styles
上级
8e7e6b53
变更
20
隐藏空白更改
内联
并排
Showing
20 changed file
with
237 addition
and
168 deletion
+237
-168
.pre-commit-config.yaml
.pre-commit-config.yaml
+4
-7
pdm/__main__.py
pdm/__main__.py
+1
-1
pdm/cli/actions.py
pdm/cli/actions.py
+38
-16
pdm/cli/commands.py
pdm/cli/commands.py
+37
-18
pdm/cli/options.py
pdm/cli/options.py
+44
-20
pdm/context.py
pdm/context.py
+1
-1
pdm/installers.py
pdm/installers.py
+9
-7
pdm/models/environment.py
pdm/models/environment.py
+8
-7
pdm/models/markers.py
pdm/models/markers.py
+2
-3
pdm/models/repositories.py
pdm/models/repositories.py
+7
-2
pdm/models/requirements.py
pdm/models/requirements.py
+7
-3
pdm/project/__init__.py
pdm/project/__init__.py
+6
-8
pdm/project/config.py
pdm/project/config.py
+1
-1
pdm/resolver/__init__.py
pdm/resolver/__init__.py
+6
-2
pdm/resolver/providers.py
pdm/resolver/providers.py
+6
-12
pdm/resolver/reporters.py
pdm/resolver/reporters.py
+2
-1
pdm/resolver/resolvers.py
pdm/resolver/resolvers.py
+31
-31
pdm/resolver/structs.py
pdm/resolver/structs.py
+4
-3
pdm/utils.py
pdm/utils.py
+21
-25
pyproject.toml
pyproject.toml
+2
-0
未找到文件。
.pre-commit-config.yaml
浏览文件 @
57068eac
repos
:
-
repo
:
https://github.com/psf/black
rev
:
stable
hooks
:
-
id
:
black
-
repo
:
https://gitlab.com/pycqa/flake8
rev
:
3.7.8
hooks
:
-
id
:
flake8
-
repo
:
https://github.com/pre-commit/mirrors-isort
rev
:
v4.3.21
hooks
:
-
id
:
isort
additional_dependencies
:
[
toml
]
exclude
:
^.*/?setup\.py$
pdm/__main__.py
浏览文件 @
57068eac
from
pdm.cli.commands
import
cli
if
__name__
==
'__main__'
:
if
__name__
==
"__main__"
:
cli
.
main
()
pdm/cli/actions.py
浏览文件 @
57068eac
...
...
@@ -9,7 +9,13 @@ from pdm.models.candidates import Candidate, identify
from
pdm.models.requirements
import
parse_requirement
from
pdm.models.specifiers
import
bump_version
,
get_specifier
from
pdm.project
import
Project
from
pdm.resolver
import
BaseProvider
,
EagerUpdateProvider
,
ReusePinProvider
,
SimpleReporter
,
resolve
from
pdm.resolver
import
(
BaseProvider
,
EagerUpdateProvider
,
ReusePinProvider
,
SimpleReporter
,
resolve
,
)
def
format_lockfile
(
mapping
,
fetched_dependencies
,
summary_collection
):
...
...
@@ -47,9 +53,10 @@ def format_lockfile(mapping, fetched_dependencies, summary_collection):
def
do_lock
(
project
:
Project
,
strategy
:
str
=
"reuse"
,
project
:
Project
,
strategy
:
str
=
"reuse"
,
preferred_pins
:
Optional
[
Dict
[
str
,
Candidate
]]
=
None
,
tracked_names
:
Optional
[
Iterable
[
str
]]
=
None
tracked_names
:
Optional
[
Iterable
[
str
]]
=
None
,
)
->
Dict
[
str
,
Candidate
]:
"""Performs the locking process and update lockfile.
...
...
@@ -70,8 +77,11 @@ def do_lock(
ReusePinProvider
if
strategy
==
"reuse"
else
EagerUpdateProvider
)
provider
=
provider_class
(
preferred_pins
,
tracked_names
or
(),
repository
,
requires_python
,
allow_prereleases
preferred_pins
,
tracked_names
or
(),
repository
,
requires_python
,
allow_prereleases
,
)
flat_reqs
=
list
(
itertools
.
chain
(
*
[
deps
.
values
()
for
_
,
deps
in
requirements
.
items
()])
...
...
@@ -89,8 +99,12 @@ def do_lock(
def
do_sync
(
project
:
Project
,
sections
:
Tuple
[
str
,
...]
=
(),
dev
:
bool
=
False
,
default
:
bool
=
True
,
dry_run
:
bool
=
False
,
clean
:
Optional
[
bool
]
=
None
project
:
Project
,
sections
:
Tuple
[
str
,
...]
=
(),
dev
:
bool
=
False
,
default
:
bool
=
True
,
dry_run
:
bool
=
False
,
clean
:
Optional
[
bool
]
=
None
,
)
->
None
:
"""Synchronize project
...
...
@@ -114,9 +128,14 @@ def do_sync(
def
do_add
(
project
:
Project
,
dev
:
bool
=
False
,
section
:
Optional
[
str
]
=
None
,
install
:
bool
=
True
,
save
:
str
=
"compatible"
,
strategy
:
str
=
"reuse"
,
editables
:
Iterable
[
str
]
=
(),
packages
:
Iterable
[
str
]
=
()
project
:
Project
,
dev
:
bool
=
False
,
section
:
Optional
[
str
]
=
None
,
install
:
bool
=
True
,
save
:
str
=
"compatible"
,
strategy
:
str
=
"reuse"
,
editables
:
Iterable
[
str
]
=
(),
packages
:
Iterable
[
str
]
=
(),
)
->
None
:
"""Add packages and install
...
...
@@ -135,10 +154,9 @@ def do_add(
section
=
"dev"
tracked_names
=
set
()
requirements
=
{}
for
r
in
(
[
parse_requirement
(
line
,
True
)
for
line
in
editables
]
+
[
parse_requirement
(
line
)
for
line
in
packages
]
):
for
r
in
[
parse_requirement
(
line
,
True
)
for
line
in
editables
]
+
[
parse_requirement
(
line
)
for
line
in
packages
]:
key
=
identify
(
r
)
r
.
from_section
=
section
or
"default"
tracked_names
.
add
(
key
)
...
...
@@ -166,6 +184,10 @@ def do_add(
if
install
:
do_sync
(
project
,
sections
=
(
section
,),
dev
=
False
,
default
=
False
,
dry_run
=
False
,
clean
=
False
project
,
sections
=
(
section
,),
dev
=
False
,
default
=
False
,
dry_run
=
False
,
clean
=
False
,
)
pdm/cli/commands.py
浏览文件 @
57068eac
...
...
@@ -4,15 +4,17 @@ import subprocess
import
click
from
pdm.cli
import
actions
from
pdm.cli.options
import
dry_run_option
,
save_strategy_option
,
sections_option
,
update_strategy_option
from
pdm.cli.options
import
(
dry_run_option
,
save_strategy_option
,
sections_option
,
update_strategy_option
,
)
from
pdm.exceptions
import
CommandNotFound
from
pdm.project
import
Project
pass_project
=
click
.
make_pass_decorator
(
Project
,
ensure
=
True
)
context_settings
=
{
"ignore_unknown_options"
:
True
,
"allow_extra_args"
:
True
}
context_settings
=
{
"ignore_unknown_options"
:
True
,
"allow_extra_args"
:
True
}
@
click
.
group
(
help
=
"PDM - Python Development Master"
)
...
...
@@ -30,8 +32,11 @@ def lock(project):
@
cli
.
command
(
help
=
"Install dependencies from lock file."
)
@
sections_option
@
click
.
option
(
"--no-lock"
,
"lock"
,
flag_value
=
False
,
default
=
True
,
help
=
"Don't do lock if lockfile is not found or outdated."
"--no-lock"
,
"lock"
,
flag_value
=
False
,
default
=
True
,
help
=
"Don't do lock if lockfile is not found or outdated."
,
)
@
pass_project
def
install
(
project
,
sections
,
dev
,
default
,
lock
):
...
...
@@ -44,7 +49,7 @@ def install(project, sections, dev, default, lock):
@
cli
.
command
(
help
=
"Run commands or scripts with local packages loaded."
,
context_settings
=
context_settings
context_settings
=
context_settings
,
)
@
click
.
argument
(
"command"
)
@
click
.
argument
(
"args"
,
nargs
=-
1
)
...
...
@@ -61,8 +66,10 @@ def run(project, command, args):
@
sections_option
@
dry_run_option
@
click
.
option
(
"--clean/--no-clean"
,
"clean"
,
default
=
None
,
help
=
"Whether to remove unneeded packages from working set."
"--clean/--no-clean"
,
"clean"
,
default
=
None
,
help
=
"Whether to remove unneeded packages from working set."
,
)
@
pass_project
def
sync
(
project
,
sections
,
dev
,
default
,
dry_run
,
clean
):
...
...
@@ -71,13 +78,19 @@ def sync(project, sections, dev, default, dry_run, clean):
@
cli
.
command
(
help
=
"Add packages to pyproject.toml and install them."
)
@
click
.
option
(
"-d"
,
"--dev"
,
default
=
False
,
is_flag
=
True
,
help
=
"Add packages into dev dependencies."
"-d"
,
"--dev"
,
default
=
False
,
is_flag
=
True
,
help
=
"Add packages into dev dependencies."
,
)
@
click
.
option
(
"-s"
,
"--section"
,
help
=
"Specify target section to add into."
)
@
click
.
option
(
"--no-install"
,
"install"
,
flag_value
=
False
,
default
=
True
,
help
=
"Only write pyproject.toml and do not install packages."
"--no-install"
,
"install"
,
flag_value
=
False
,
default
=
True
,
help
=
"Only write pyproject.toml and do not install packages."
,
)
@
save_strategy_option
@
update_strategy_option
...
...
@@ -100,13 +113,19 @@ def update(project, dev, sections, default, save, strategy, packages):
@
cli
.
command
(
help
=
"Remove packages from pyproject.toml"
)
@
click
.
option
(
"-d"
,
"--dev"
,
default
=
False
,
is_flag
=
True
,
help
=
"Remove packages from dev dependencies."
"-d"
,
"--dev"
,
default
=
False
,
is_flag
=
True
,
help
=
"Remove packages from dev dependencies."
,
)
@
click
.
option
(
"-s"
,
"--section"
,
help
=
"Specify target section the package belongs to"
)
@
click
.
option
(
"--no-install"
,
"install"
,
flag_value
=
False
,
default
=
True
,
help
=
"Only write pyproject.toml and do not uninstall packages."
"--no-install"
,
"install"
,
flag_value
=
False
,
default
=
True
,
help
=
"Only write pyproject.toml and do not uninstall packages."
,
)
@
click
.
argument
(
"packages"
,
nargs
=-
1
)
@
pass_project
...
...
pdm/cli/options.py
浏览文件 @
57068eac
...
...
@@ -3,8 +3,10 @@ import click
def
dry_run_option
(
f
):
return
click
.
option
(
"--dry-run"
,
is_flag
=
True
,
default
=
False
,
help
=
"Only prints actions without actually running them."
"--dry-run"
,
is_flag
=
True
,
default
=
False
,
help
=
"Only prints actions without actually running them."
,
)(
f
)
...
...
@@ -12,42 +14,64 @@ def sections_option(f):
name
=
f
.
__name__
f
=
click
.
option
(
"-s"
,
"--section"
,
"sections"
,
multiple
=
True
,
help
=
f
"Specify section(s) to
{
name
}
."
"-s"
,
"--section"
,
"sections"
,
multiple
=
True
,
help
=
f
"Specify section(s) to
{
name
}
."
,
)(
f
)
f
=
click
.
option
(
"-d"
,
"--dev"
,
default
=
False
,
is_flag
=
True
,
help
=
f
"Also
{
name
}
dev dependencies."
"-d"
,
"--dev"
,
default
=
False
,
is_flag
=
True
,
help
=
f
"Also
{
name
}
dev dependencies."
,
)(
f
)
f
=
click
.
option
(
"--no-default"
,
"default"
,
flag_value
=
False
,
default
=
True
,
help
=
f
"Don't
{
name
}
dependencies from default seciton."
"--no-default"
,
"default"
,
flag_value
=
False
,
default
=
True
,
help
=
f
"Don't
{
name
}
dependencies from default seciton."
,
)(
f
)
return
f
def
save_strategy_option
(
f
):
f
=
click
.
option
(
"--save-compatible"
,
"save"
,
flag_value
=
"compatible"
,
help
=
"Save compatible version specifiers."
,
default
=
True
"--save-compatible"
,
"save"
,
flag_value
=
"compatible"
,
help
=
"Save compatible version specifiers."
,
default
=
True
,
)(
f
)
f
=
click
.
option
(
"--save-exact"
,
"save"
,
flag_value
=
"exact"
,
help
=
"Save exactly pinned version specifiers."
"--save-exact"
,
"save"
,
flag_value
=
"exact"
,
help
=
"Save exactly pinned version specifiers."
,
)(
f
)
f
=
click
.
option
(
"--save-wildcard"
,
"save"
,
flag_value
=
"wildcard"
,
help
=
"Save wildcard unpinned version specifiers."
"--save-wildcard"
,
"save"
,
flag_value
=
"wildcard"
,
help
=
"Save wildcard unpinned version specifiers."
,
)(
f
)
return
f
def
update_strategy_option
(
f
):
f
=
click
.
option
(
"--update-reuse"
,
"strategy"
,
flag_value
=
"reuse"
,
help
=
"Reuse pinned versions already present in lock file if possible."
)(
click
.
option
(
"--update-eager"
,
"strategy"
,
flag_value
=
"eager"
,
help
=
"Try to update the packages and their dependencies recursively."
)(
f
))
"--update-reuse"
,
"strategy"
,
flag_value
=
"reuse"
,
help
=
"Reuse pinned versions already present in lock file if possible."
,
)(
click
.
option
(
"--update-eager"
,
"strategy"
,
flag_value
=
"eager"
,
help
=
"Try to update the packages and their dependencies recursively."
,
)(
f
)
)
return
f
pdm/context.py
浏览文件 @
57068eac
...
...
@@ -50,7 +50,7 @@ class Context:
@
require_initialize
def
make_wheel_cache
(
self
)
->
shims
.
WheelCache
:
return
shims
.
WheelCache
(
self
.
cache_dir
.
as_posix
(),
shims
.
FormatControl
(
set
(),
set
())
,
self
.
cache_dir
.
as_posix
(),
shims
.
FormatControl
(
set
(),
set
())
)
@
require_initialize
...
...
pdm/installers.py
浏览文件 @
57068eac
...
...
@@ -55,7 +55,7 @@ class Installer:
scripts
.
executable
=
self
.
environment
.
python_executable
scripts
.
script_template
=
scripts
.
script_template
.
replace
(
"import sys"
,
"import sys; sys.path.insert(0, {!r})"
.
format
(
paths
[
"platlib"
])
"import sys; sys.path.insert(0, {!r})"
.
format
(
paths
[
"platlib"
])
,
)
wheel
.
install
(
paths
,
scripts
)
...
...
@@ -64,12 +64,16 @@ class Installer:
paths
=
self
.
environment
.
get_paths
()
old_pwd
=
os
.
getcwd
()
install_args
=
[
self
.
environment
.
python_executable
,
"-u"
,
"-c"
,
self
.
environment
.
python_executable
,
"-u"
,
"-c"
,
SETUPTOOLS_SHIM
%
setup_path
,
"develop"
,
"--install-dir={}"
.
format
(
paths
[
"platlib"
]),
"--no-deps"
,
"develop"
,
"--install-dir={}"
.
format
(
paths
[
"platlib"
]),
"--no-deps"
,
"--prefix={}"
.
format
(
paths
[
"prefix"
]),
"--script-dir={}"
.
format
(
paths
[
"scripts"
]),
"--site-dirs={}"
.
format
(
paths
[
"platlib"
])
"--site-dirs={}"
.
format
(
paths
[
"platlib"
])
,
]
os
.
chdir
(
ireq
.
source_dir
)
try
:
...
...
@@ -93,9 +97,7 @@ class Synchronizer:
"""Synchronize the working set with given installation candidates"""
def
__init__
(
self
,
candidates
:
Dict
[
str
,
Candidate
],
environment
:
Environment
,
self
,
candidates
:
Dict
[
str
,
Candidate
],
environment
:
Environment
)
->
None
:
self
.
candidates
=
candidates
self
.
environment
=
environment
...
...
pdm/models/environment.py
浏览文件 @
57068eac
...
...
@@ -16,7 +16,12 @@ from distlib.wheel import Wheel
from
pdm.context
import
context
from
pdm.exceptions
import
NoPythonVersion
,
WheelBuildError
from
pdm.utils
import
(
_allow_all_wheels
,
cached_property
,
convert_hashes
,
create_tracked_tempdir
,
get_finder
,
get_python_version
,
_allow_all_wheels
,
cached_property
,
convert_hashes
,
create_tracked_tempdir
,
get_finder
,
get_python_version
,
)
from
pythonfinder
import
Finder
from
vistir.contextmanagers
import
temp_environ
...
...
@@ -157,9 +162,7 @@ class Environment:
finder
.
session
.
close
()
def
build_wheel
(
self
,
ireq
:
shims
.
InstallRequirement
,
hashes
:
Optional
[
Dict
[
str
,
str
]]
=
None
self
,
ireq
:
shims
.
InstallRequirement
,
hashes
:
Optional
[
Dict
[
str
,
str
]]
=
None
)
->
Optional
[
Wheel
]:
"""A local candidate has already everything in local, no need to download."""
kwargs
=
self
.
_make_pip_wheel_args
(
ireq
)
...
...
@@ -188,9 +191,7 @@ class Environment:
)
if
ireq
.
link
.
is_wheel
:
return
Wheel
(
(
context
.
cache
(
"wheels"
)
/
ireq
.
link
.
filename
).
as_posix
()
)
return
Wheel
((
context
.
cache
(
"wheels"
)
/
ireq
.
link
.
filename
).
as_posix
())
# VCS url is unpacked, now build the egg-info
if
ireq
.
editable
and
ireq
.
req
.
is_vcs
:
ireq
.
prepare_metadata
()
...
...
pdm/models/markers.py
浏览文件 @
57068eac
...
...
@@ -121,10 +121,9 @@ def _only_contains_python_keys(markers):
def
_build_pyspec_from_marker
(
markers
):
def
split_version
(
version
):
if
','
in
version
:
return
[
v
.
strip
()
for
v
in
version
.
split
(
','
)]
if
","
in
version
:
return
[
v
.
strip
()
for
v
in
version
.
split
(
","
)]
return
version
.
split
()
groups
=
[
PySpecSet
()]
...
...
pdm/models/repositories.py
浏览文件 @
57068eac
...
...
@@ -7,7 +7,11 @@ from typing import TYPE_CHECKING, Callable, Dict, Iterable, List, Optional, Tupl
from
pdm.context
import
context
from
pdm.exceptions
import
CandidateInfoNotFound
,
CorruptedCacheError
from
pdm.models.candidates
import
Candidate
from
pdm.models.requirements
import
Requirement
,
filter_requirements_with_extras
,
parse_requirement
from
pdm.models.requirements
import
(
Requirement
,
filter_requirements_with_extras
,
parse_requirement
,
)
from
pdm.models.specifiers
import
PySpecSet
,
SpecifierSet
from
pdm.types
import
CandidateInfo
,
Source
from
pdm.utils
import
_allow_all_wheels
...
...
@@ -113,7 +117,8 @@ class BaseRepository:
if
(
candidate
.
hashes
or
candidate
.
req
.
is_vcs
or
candidate
.
req
.
is_file_or_url
and
candidate
.
req
.
is_local_dir
or
candidate
.
req
.
is_file_or_url
and
candidate
.
req
.
is_local_dir
):
return
req
=
candidate
.
req
.
copy
()
...
...
pdm/models/requirements.py
浏览文件 @
57068eac
...
...
@@ -16,7 +16,11 @@ from pdm.models.markers import Marker, get_marker, split_marker_element
from
pdm.models.readers
import
SetupReader
from
pdm.models.specifiers
import
PySpecSet
,
get_specifier
from
pdm.types
import
RequirementDict
from
pdm.utils
import
is_readonly_property
,
parse_name_version_from_wheel
,
url_without_fragments
from
pdm.utils
import
(
is_readonly_property
,
parse_name_version_from_wheel
,
url_without_fragments
,
)
VCS_SCHEMA
=
(
"git"
,
"hg"
,
"svn"
,
"bzr"
)
VCS_REQ
=
re
.
compile
(
...
...
@@ -220,7 +224,7 @@ class FileRequirement(Requirement):
@
classmethod
def
parse
(
cls
,
line
:
str
,
parsed
:
Dict
[
str
,
str
])
->
"FileRequirement"
:
r
=
cls
(
url
=
parsed
.
get
(
"url"
),
path
=
parsed
.
get
(
"path"
),
marker
=
parsed
.
get
(
"marker"
)
,
url
=
parsed
.
get
(
"url"
),
path
=
parsed
.
get
(
"path"
),
marker
=
parsed
.
get
(
"marker"
)
)
return
r
...
...
@@ -313,7 +317,7 @@ class VcsRequirement(FileRequirement):
@
classmethod
def
parse
(
cls
,
line
:
str
,
parsed
:
Dict
[
str
,
str
])
->
"VcsRequirement"
:
r
=
cls
(
url
=
parsed
.
get
(
"url"
),
vcs
=
parsed
.
get
(
"vcs"
),
marker
=
parsed
.
get
(
"marker"
)
,
url
=
parsed
.
get
(
"url"
),
vcs
=
parsed
.
get
(
"vcs"
),
marker
=
parsed
.
get
(
"marker"
)
)
return
r
...
...
pdm/project/__init__.py
浏览文件 @
57068eac
...
...
@@ -58,7 +58,7 @@ class Project:
def
__init__
(
self
,
root_path
:
Optional
[
str
]
=
None
)
->
None
:
if
root_path
is
None
:
root_path
=
find_project_root
()
or
''
root_path
=
find_project_root
()
or
""
self
.
root
=
Path
(
root_path
).
absolute
()
self
.
pyproject_file
=
self
.
root
/
self
.
PYPROJECT_FILENAME
self
.
lockfile_file
=
self
.
root
/
"pdm.lock"
...
...
@@ -192,9 +192,7 @@ class Project:
package
[
"version"
]
=
f
"==
{
version
}
"
package_name
=
package
.
pop
(
"name"
)
req
=
Requirement
.
from_req_dict
(
package_name
,
dict
(
package
))
can
=
Candidate
(
req
,
self
.
environment
,
name
=
package_name
,
version
=
version
)
can
=
Candidate
(
req
,
self
.
environment
,
name
=
package_name
,
version
=
version
)
can
.
hashes
=
{
item
[
"file"
]:
item
[
"hash"
]
for
item
in
self
.
lockfile
[
"metadata"
].
get
(
...
...
@@ -232,9 +230,9 @@ class Project:
matched_name
=
next
(
filter
(
lambda
k
:
strip_extras
(
name
)[
0
]
==
safe_name
(
k
).
lower
(),
deps
.
keys
()
),
None
lambda
k
:
strip_extras
(
name
)[
0
]
==
safe_name
(
k
).
lower
(),
deps
.
keys
()
),
None
,
)
name_to_save
=
dep
.
name
if
matched_name
is
None
else
matched_name
_
,
req_dict
=
dep
.
as_req_dict
()
...
...
@@ -265,6 +263,6 @@ class Project:
def
init_pyproject
(
self
)
->
None
:
self
.
_pyproject
=
{
"dependencies"
:
tomlkit
.
table
(),
"dev-dependencies"
:
tomlkit
.
table
()
"dev-dependencies"
:
tomlkit
.
table
()
,
}
self
.
write_pyproject
()
pdm/project/config.py
浏览文件 @
57068eac
...
...
@@ -11,7 +11,7 @@ class Config(MutableMapping):
DEFAULT_CONFIG
=
{
"cache_dir"
:
appdirs
.
user_cache_dir
(
"pdm"
),
"python"
:
None
,
"packages_path"
:
None
"packages_path"
:
None
,
}
def
__init__
(
self
,
project_root
:
Path
):
...
...
pdm/resolver/__init__.py
浏览文件 @
57068eac
import
copy
from
pdm.models.markers
import
PySpecSet
,
join_metaset
from
pdm.resolver.providers
import
BaseProvider
,
EagerUpdateProvider
,
ReusePinProvider
# noqa
from
pdm.resolver.providers
import
(
# noqa
BaseProvider
,
EagerUpdateProvider
,
ReusePinProvider
,
)
from
pdm.resolver.reporters
import
SimpleReporter
# noqa
from
pdm.resolver.resolvers
import
Resolver
...
...
@@ -88,7 +92,7 @@ def _calculate_markers_and_pyspecs(traces, dependencies, pythons):
for
key
,
trace
in
traces
.
items
():
assert
key
not
in
all_metasets
,
key
# Sanity check for debug.
metasets
=
_build_marker_and_pyspec
(
dependencies
,
pythons
,
key
,
trace
,
all_metasets
,
dependencies
,
pythons
,
key
,
trace
,
all_metasets
)
if
metasets
is
None
:
continue
...
...
pdm/resolver/providers.py
浏览文件 @
57068eac
...
...
@@ -21,9 +21,7 @@ class BaseProvider:
None
:
requires_python
}
# type: Dict[Optional[str], PySpecSet]
self
.
summary_collection
=
{}
# type: Dict[str, str]
self
.
fetched_dependencies
=
(
{}
)
# type: Dict[str, Dict[str, List[Requirement]]]
self
.
fetched_dependencies
=
{}
# type: Dict[str, Dict[str, List[Requirement]]]
def
identify
(
self
,
req
:
Union
[
Requirement
,
Candidate
])
->
Optional
[
str
]:
return
identify
(
req
)
...
...
@@ -79,6 +77,7 @@ class ReusePinProvider(BaseProvider):
This is used to implement "add", "remove", and "reuse upgrade",
where already-pinned candidates in lockfile should be preferred.
"""
def
__init__
(
self
,
preferred_pins
:
Dict
[
str
,
Candidate
],
tracked_names
:
Iterable
[
str
],
*
args
):
...
...
@@ -91,9 +90,7 @@ class ReusePinProvider(BaseProvider):
# preferred pin, and into a "normal" candidate selection process.
if
getattr
(
candidate
,
"_preferred"
,
False
):
return
True
return
super
().
is_satisfied_by
(
requirement
,
candidate
,
)
return
super
().
is_satisfied_by
(
requirement
,
candidate
)
def
find_matches
(
self
,
requirement
:
Requirement
)
->
List
[
Candidate
]:
result
=
super
().
find_matches
(
requirement
)
...
...
@@ -120,14 +117,11 @@ class EagerUpdateProvider(ReusePinProvider):
def
is_satisfied_by
(
self
,
requirement
,
candidate
):
# If this is a tracking package, tell the resolver out of using the
# preferred pin, and into a "normal" candidate selection process.
if
(
self
.
identify
(
requirement
)
in
self
.
tracked_names
and
getattr
(
candidate
,
"_preferred"
,
False
)
if
self
.
identify
(
requirement
)
in
self
.
tracked_names
and
getattr
(
candidate
,
"_preferred"
,
False
):
return
False
return
super
().
is_satisfied_by
(
requirement
,
candidate
,
)
return
super
().
is_satisfied_by
(
requirement
,
candidate
)
def
get_dependencies
(
self
,
candidate
):
# If this package is being tracked for upgrade, remove pins of its
...
...
pdm/resolver/reporters.py
浏览文件 @
57068eac
...
...
@@ -45,7 +45,8 @@ class SimpleReporter:
else
:
added
=
[
can
for
k
,
can
in
state
.
mapping
.
items
()
if
k
not
in
self
.
_previous
]
changed
=
[
(
self
.
_previous
[
k
],
can
)
for
k
,
can
in
state
.
mapping
.
items
()
(
self
.
_previous
[
k
],
can
)
for
k
,
can
in
state
.
mapping
.
items
()
if
k
in
self
.
_previous
and
self
.
_previous
[
k
]
!=
can
]
if
added
:
...
...
pdm/resolver/resolvers.py
浏览文件 @
57068eac
...
...
@@ -3,7 +3,12 @@ from __future__ import annotations
import
collections
from
typing
import
TYPE_CHECKING
,
Dict
,
Iterable
,
List
,
Optional
,
Set
,
Tuple
,
Union
from
pdm.exceptions
import
NoVersionsAvailable
,
RequirementsConflicted
,
ResolutionImpossible
,
ResolutionTooDeep
from
pdm.exceptions
import
(
NoVersionsAvailable
,
RequirementsConflicted
,
ResolutionImpossible
,
ResolutionTooDeep
,
)
from
pdm.resolver.structs
import
DirectedGraph
if
TYPE_CHECKING
:
...
...
@@ -12,9 +17,9 @@ if TYPE_CHECKING:
from
pdm.resolver.providers
import
BaseProvider
from
pdm.resolver.reporters
import
SimpleReporter
RequirementInformation
=
collections
.
namedtuple
(
'RequirementInformation'
,
[
'requirement'
,
'parent'
,
]
)
RequirementInformation
=
collections
.
namedtuple
(
"RequirementInformation"
,
[
"requirement"
,
"parent"
]
)
class
Criterion
(
object
):
...
...
@@ -30,19 +35,14 @@ class Criterion(object):
"""
def
__init__
(
self
,
candidates
:
List
[
Candidate
],
information
:
List
[
RequirementInformation
]
self
,
candidates
:
List
[
Candidate
],
information
:
List
[
RequirementInformation
]
)
->
None
:
self
.
candidates
=
candidates
self
.
information
=
information
@
classmethod
def
from_requirement
(
cls
,
provider
:
BaseProvider
,
requirement
:
Requirement
,
parent
:
Candidate
cls
,
provider
:
BaseProvider
,
requirement
:
Requirement
,
parent
:
Candidate
)
->
"Criterion"
:
"""Build an instance from a requirement.
"""
...
...
@@ -61,18 +61,14 @@ class Criterion(object):
return
(
i
.
parent
for
i
in
self
.
information
)
def
merged_with
(
self
,
provider
:
BaseProvider
,
requirement
:
Requirement
,
parent
:
Candidate
self
,
provider
:
BaseProvider
,
requirement
:
Requirement
,
parent
:
Candidate
)
->
"Criterion"
:
"""Build a new instance from this and a new requirement.
"""
infos
=
list
(
self
.
information
)
infos
.
append
(
RequirementInformation
(
requirement
,
parent
))
candidates
=
[
c
for
c
in
self
.
candidates
if
provider
.
is_satisfied_by
(
requirement
,
c
)
c
for
c
in
self
.
candidates
if
provider
.
is_satisfied_by
(
requirement
,
c
)
]
if
not
candidates
:
raise
RequirementsConflicted
([
info
.
requirement
for
info
in
infos
])
...
...
@@ -80,7 +76,7 @@ class Criterion(object):
# Resolution state in a round.
State
=
collections
.
namedtuple
(
'State'
,
'mapping graph'
)
State
=
collections
.
namedtuple
(
"State"
,
"mapping graph"
)
class
Resolution
(
object
):
...
...
@@ -102,7 +98,7 @@ class Resolution(object):
try
:
return
self
.
_states
[
-
1
]
except
IndexError
:
raise
AttributeError
(
'state'
)
raise
AttributeError
(
"state"
)
def
_push_new_state
(
self
)
->
None
:
"""Push a new state into history.
...
...
@@ -118,10 +114,7 @@ class Resolution(object):
graph
.
add
(
root
)
# Sentinel as root dependencies' parent.
state
=
State
(
mapping
=
{},
graph
=
graph
)
else
:
state
=
State
(
mapping
=
base
.
mapping
.
copy
(),
graph
=
base
.
graph
.
copy
(),
)
state
=
State
(
mapping
=
base
.
mapping
.
copy
(),
graph
=
base
.
graph
.
copy
())
self
.
_states
.
append
(
state
)
def
_contribute_to_criteria
(
...
...
@@ -141,7 +134,7 @@ class Resolution(object):
except
(
IndexError
,
KeyError
):
pinned
=
None
return
self
.
_p
.
get_preference
(
pinned
,
criterion
.
candidates
,
criterion
.
information
,
pinned
,
criterion
.
candidates
,
criterion
.
information
)
def
_is_current_pin_satisfying
(
self
,
name
:
str
,
criterion
:
Criterion
)
->
bool
:
...
...
@@ -169,8 +162,13 @@ class Resolution(object):
return
None
return
contributed
def
_pin_candidate
(
self
,
name
:
str
,
criterion
:
Criterion
,
candidate
:
Candidate
,
child_names
:
Iterable
[
str
])
->
None
:
def
_pin_candidate
(
self
,
name
:
str
,
criterion
:
Criterion
,
candidate
:
Candidate
,
child_names
:
Iterable
[
str
],
)
->
None
:
try
:
self
.
state
.
graph
.
remove
(
name
)
except
KeyError
:
...
...
@@ -196,10 +194,12 @@ class Resolution(object):
pass
def
_pin_criteria
(
self
)
->
None
:
criterion_names
=
[
name
for
name
,
_
in
sorted
(
self
.
_criteria
.
items
(),
key
=
self
.
_get_criterion_item_preference
,
)]
criterion_names
=
[
name
for
name
,
_
in
sorted
(
self
.
_criteria
.
items
(),
key
=
self
.
_get_criterion_item_preference
)
]
for
name
in
criterion_names
:
# Any pin may modify any criterion during the loop. Criteria are
# replaced, not updated in-place, so we need to read this value
...
...
@@ -225,7 +225,7 @@ class Resolution(object):
self
,
requirements
:
Dict
[
str
,
Iterable
[
Requirement
]],
max_rounds
:
int
)
->
None
:
if
self
.
_states
:
raise
RuntimeError
(
'already resolved'
)
raise
RuntimeError
(
"already resolved"
)
self
.
_roots
=
[]
for
key
,
reqs
in
requirements
.
items
():
self
.
_roots
.
append
(
f
"__
{
key
}
__"
)
...
...
pdm/resolver/structs.py
浏览文件 @
57068eac
class
DirectedGraph
(
object
):
"""A graph structure with directed edges.
"""
def
__init__
(
self
):
self
.
_vertices
=
set
()
self
.
_forwards
=
{}
# <key> -> Set[<key>]
self
.
_backwards
=
{}
# <key> -> Set[<key>]
self
.
_forwards
=
{}
# <key> -> Set[<key>]
self
.
_backwards
=
{}
# <key> -> Set[<key>]
def
__iter__
(
self
):
return
iter
(
self
.
_vertices
)
...
...
@@ -28,7 +29,7 @@ class DirectedGraph(object):
"""Add a new vertex to the graph.
"""
if
key
in
self
.
_vertices
:
raise
ValueError
(
'vertex exists'
)
raise
ValueError
(
"vertex exists"
)
self
.
_vertices
.
add
(
key
)
self
.
_forwards
[
key
]
=
set
()
self
.
_backwards
[
key
]
=
set
()
...
...
pdm/utils.py
浏览文件 @
57068eac
...
...
@@ -23,13 +23,7 @@ from distlib.wheel import Wheel
from
pdm.types
import
Source
if
TYPE_CHECKING
:
from
pip_shims.backports
import
(
TCommand
,
TShimmedFunc
,
Values
,
TSession
,
TFinder
,
)
from
pip_shims.backports
import
TCommand
,
TShimmedFunc
,
Values
,
TSession
,
TFinder
try
:
from
functools
import
cached_property
...
...
@@ -57,33 +51,35 @@ def _get_abi_tag(python_version):
"""
from
pip._internal.pep425tags
import
get_config_var
,
get_abbr_impl
,
get_flag
soabi
=
get_config_var
(
'SOABI'
)
soabi
=
get_config_var
(
"SOABI"
)
impl
=
get_abbr_impl
()
abi
=
None
# type: Optional[str]
if
not
soabi
and
impl
in
{
'cp'
,
'pp'
}
and
hasattr
(
sys
,
'maxunicode'
):
d
=
''
m
=
''
u
=
''
is_cpython
=
(
impl
==
'cp'
)
if
not
soabi
and
impl
in
{
"cp"
,
"pp"
}
and
hasattr
(
sys
,
"maxunicode"
):
d
=
""
m
=
""
u
=
""
is_cpython
=
impl
==
"cp"
if
get_flag
(
'Py_DEBUG'
,
lambda
:
hasattr
(
sys
,
'gettotalrefcount'
),
warn
=
is_cpython
"Py_DEBUG"
,
lambda
:
hasattr
(
sys
,
"gettotalrefcount"
),
warn
=
is_cpython
):
d
=
'd'
d
=
"d"
if
python_version
<
(
3
,
8
)
and
get_flag
(
'WITH_PYMALLOC'
,
lambda
:
is_cpython
,
warn
=
is_cpython
"WITH_PYMALLOC"
,
lambda
:
is_cpython
,
warn
=
is_cpython
):
m
=
'm'
m
=
"m"
if
python_version
<
(
3
,
3
)
and
get_flag
(
'Py_UNICODE_SIZE'
,
lambda
:
sys
.
maxunicode
==
0x10ffff
,
expected
=
4
,
warn
=
is_cpython
"Py_UNICODE_SIZE"
,
lambda
:
sys
.
maxunicode
==
0x10FFFF
,
expected
=
4
,
warn
=
is_cpython
,
):
u
=
'u'
abi
=
'%s%s%s%s%s'
%
(
impl
,
""
.
join
(
map
(
str
,
python_version
)),
d
,
m
,
u
)
elif
soabi
and
soabi
.
startswith
(
'cpython-'
):
abi
=
'cp'
+
soabi
.
split
(
'-'
)[
1
]
u
=
"u"
abi
=
"%s%s%s%s%s"
%
(
impl
,
""
.
join
(
map
(
str
,
python_version
)),
d
,
m
,
u
)
elif
soabi
and
soabi
.
startswith
(
"cpython-"
):
abi
=
"cp"
+
soabi
.
split
(
"-"
)[
1
]
elif
soabi
:
abi
=
soabi
.
replace
(
'.'
,
'_'
).
replace
(
'-'
,
'_'
)
abi
=
soabi
.
replace
(
"."
,
"_"
).
replace
(
"-"
,
"_"
)
return
abi
...
...
@@ -319,7 +315,7 @@ def get_python_version(executable) -> Tuple[Union[str, int], ...]:
args
=
[
executable
,
"-c"
,
"import sys,json;print(json.dumps(tuple(sys.version_info[:3])))"
"import sys,json;print(json.dumps(tuple(sys.version_info[:3])))"
,
]
return
tuple
(
json
.
loads
(
subprocess
.
check_output
(
args
)))
...
...
pyproject.toml
浏览文件 @
57068eac
...
...
@@ -21,6 +21,8 @@ line_length = 88
multi_line_output
=
3
include_trailing_comma
=
true
use_parentheses
=
true
force_grid_wrap
=
0
atomic
=
true
not_skip
=
"__init__.py"
skip_glob
=
["*/setup.py"]
filter_files
=
true
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录