Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
后端镜像
Pdm
提交
ae82fa56
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,发现更多精彩内容 >>
未验证
提交
ae82fa56
编写于
3月 23, 2020
作者:
F
frostming
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
log to file
上级
7f0b755a
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
99 addition
and
90 deletion
+99
-90
pdm/cli/actions.py
pdm/cli/actions.py
+3
-1
pdm/exceptions.py
pdm/exceptions.py
+4
-0
pdm/installers.py
pdm/installers.py
+37
-29
pdm/iostream.py
pdm/iostream.py
+26
-0
pdm/project/core.py
pdm/project/core.py
+4
-1
pdm/resolver/reporters.py
pdm/resolver/reporters.py
+22
-56
pdm/resolver/resolvers.py
pdm/resolver/resolvers.py
+3
-3
未找到文件。
pdm/cli/actions.py
浏览文件 @
ae82fa56
...
...
@@ -49,7 +49,9 @@ def do_lock(
requirements
=
requirements
or
project
.
all_dependencies
# TODO: switch reporter at io level.
with
halo
.
Halo
(
text
=
"Resolving dependencies"
,
spinner
=
"dots"
)
as
spin
:
with
halo
.
Halo
(
text
=
"Resolving dependencies"
,
spinner
=
"dots"
)
as
spin
,
stream
.
logging
(
"lock"
):
reporter
=
project
.
get_reporter
(
requirements
,
tracked_names
,
spin
)
resolver
=
project
.
core
.
resolver_class
(
provider
,
reporter
)
mapping
,
dependencies
,
summaries
=
resolve
(
...
...
pdm/exceptions.py
浏览文件 @
ae82fa56
...
...
@@ -48,6 +48,10 @@ class ProjectError(PdmException):
pass
class
InstallationError
(
PdmException
):
pass
class
NoConfigError
(
PdmException
,
KeyError
):
def
__init__
(
self
,
key
):
super
().
__init__
(
"No such config item: {}"
.
format
(
key
))
...
...
pdm/installers.py
浏览文件 @
ae82fa56
import
contextlib
import
functools
import
importlib
import
os
import
subprocess
import
traceback
from
collections
import
defaultdict
...
...
@@ -15,6 +16,7 @@ from pip._vendor.pkg_resources import Distribution, EggInfoDistribution, safe_na
from
pip_shims
import
shims
from
vistir
import
cd
from
pdm.exceptions
import
InstallationError
from
pdm.iostream
import
stream
from
pdm.models.candidates
import
Candidate
from
pdm.models.environment
import
Environment
...
...
@@ -316,8 +318,8 @@ class Installer: # pragma: no cover
paths
[
"scripts"
],
]
with
self
.
environment
.
activate
(),
cd
(
ireq
.
unpacked_source_directory
):
capture_output
=
stream
.
verbosity
<
stream
.
DETAIL
s
ubprocess
.
run
(
install_args
,
capture_output
=
capture_output
,
check
=
True
)
result
=
subprocess
.
run
(
install_args
,
capture_output
=
True
,
check
=
True
)
s
tream
.
logger
.
debug
(
result
.
stdout
.
decode
(
"utf-8"
)
)
def
uninstall
(
self
,
dist
:
Distribution
)
->
None
:
req
=
parse_requirement
(
dist
.
project_name
)
...
...
@@ -379,7 +381,7 @@ class DummyExecutor:
class
Synchronizer
:
"""Synchronize the working set with given installation candidates"""
BAR_FILLED_CHAR
=
"▉"
BAR_FILLED_CHAR
=
"
="
if
os
.
name
==
"nt"
else
"
▉"
BAR_EMPTY_CHAR
=
" "
RETRY_TIMES
=
1
...
...
@@ -407,7 +409,10 @@ class Synchronizer:
else
:
executor
=
DummyExecutor
()
with
executor
:
yield
bar
,
executor
try
:
yield
bar
,
executor
except
KeyboardInterrupt
:
pass
def
get_installer
(
self
)
->
Installer
:
return
Installer
(
self
.
environment
)
...
...
@@ -474,11 +479,12 @@ class Synchronizer:
def
summarize
(
self
,
result
,
dry_run
=
False
):
added
,
updated
,
removed
=
result
[
"add"
],
result
[
"update"
],
result
[
"remove"
]
if
added
:
stream
.
echo
(
"
\n
"
)
self
.
_print_section_title
(
"installed"
,
len
(
added
),
dry_run
)
for
item
in
sorted
(
added
,
key
=
lambda
x
:
x
.
name
):
stream
.
echo
(
f
" -
{
item
.
format
()
}
"
)
stream
.
echo
()
if
updated
:
stream
.
echo
(
"
\n
"
)
self
.
_print_section_title
(
"updated"
,
len
(
updated
),
dry_run
)
for
old
,
can
in
sorted
(
updated
,
key
=
lambda
x
:
x
[
1
].
name
):
stream
.
echo
(
...
...
@@ -486,8 +492,8 @@ class Synchronizer:
f
"
{
stream
.
yellow
(
old
.
version
)
}
"
f
"->
{
stream
.
yellow
(
can
.
version
)
}
"
)
stream
.
echo
()
if
removed
:
stream
.
echo
(
"
\n
"
)
self
.
_print_section_title
(
"removed"
,
len
(
removed
),
dry_run
)
for
dist
in
sorted
(
removed
,
key
=
lambda
x
:
x
.
key
):
stream
.
echo
(
...
...
@@ -540,29 +546,9 @@ class Synchronizer:
result
[
section
].
append
(
future
.
result
())
bar
.
update
(
1
)
with
self
.
progressbar
(
"Synchronizing:"
,
sum
(
len
(
l
)
for
l
in
to_do
.
values
())
)
as
(
bar
,
pool
):
for
section
in
to_do
:
for
key
in
to_do
[
section
]:
future
=
pool
.
submit
(
handlers
[
section
],
key
)
future
.
add_done_callback
(
functools
.
partial
(
update_progress
,
section
=
section
,
key
=
key
,
bar
=
bar
)
)
# Retry for failed items
for
i
in
range
(
self
.
RETRY_TIMES
):
if
not
any
(
failed
.
values
()):
break
to_do
=
failed
failed
=
defaultdict
(
list
)
errors
.
clear
()
with
stream
.
logging
(
"install"
):
with
self
.
progressbar
(
f
"Retrying (
{
i
+
1
}
/
{
self
.
RETRY_TIMES
}
):"
,
sum
(
len
(
l
)
for
l
in
to_do
.
values
()),
"Synchronizing:"
,
sum
(
len
(
l
)
for
l
in
to_do
.
values
())
)
as
(
bar
,
pool
):
for
section
in
to_do
:
...
...
@@ -573,7 +559,28 @@ class Synchronizer:
update_progress
,
section
=
section
,
key
=
key
,
bar
=
bar
)
)
stream
.
echo
()
# Retry for failed items
for
i
in
range
(
self
.
RETRY_TIMES
):
if
not
any
(
failed
.
values
()):
break
to_do
=
failed
failed
=
defaultdict
(
list
)
errors
.
clear
()
with
self
.
progressbar
(
f
"Retrying (
{
i
+
1
}
/
{
self
.
RETRY_TIMES
}
):"
,
sum
(
len
(
l
)
for
l
in
to_do
.
values
()),
)
as
(
bar
,
pool
):
for
section
in
to_do
:
for
key
in
to_do
[
section
]:
future
=
pool
.
submit
(
handlers
[
section
],
key
)
future
.
add_done_callback
(
functools
.
partial
(
update_progress
,
section
=
section
,
key
=
key
,
bar
=
bar
)
)
# End installation
self
.
summarize
(
result
)
if
not
any
(
failed
.
values
()):
return
...
...
@@ -591,3 +598,4 @@ class Synchronizer:
),
verbosity
=
stream
.
DEBUG
,
)
raise
InstallationError
()
pdm/iostream.py
浏览文件 @
ae82fa56
import
contextlib
import
functools
import
logging
import
os
import
re
from
itertools
import
zip_longest
from
tempfile
import
mktemp
from
typing
import
List
,
Optional
import
click
...
...
@@ -29,6 +32,7 @@ class IOStream:
self
.
verbosity
=
verbosity
self
.
_disable_colors
=
disable_colors
self
.
_indent
=
""
self
.
logger
=
None
for
color
in
COLORS
:
setattr
(
self
,
color
,
functools
.
partial
(
self
.
_style
,
fg
=
color
))
...
...
@@ -80,5 +84,27 @@ class IOStream:
yield
self
.
_indent
=
_indent
@
contextlib
.
contextmanager
def
logging
(
self
,
type_
:
str
=
"install"
):
file_name
=
mktemp
(
".log"
,
f
"pdm-
{
type_
}
-"
)
logger
=
logging
.
getLogger
(
__name__
)
logger
.
setLevel
(
logging
.
DEBUG
)
handler
=
logging
.
FileHandler
(
file_name
,
encoding
=
"utf-8"
)
handler
.
setLevel
(
logging
.
DEBUG
)
logger
.
addHandler
(
handler
)
subprocess_logger
=
logging
.
getLogger
(
"pip.subprocessor"
)
subprocess_logger
.
handlers
[:]
=
[
handler
]
try
:
self
.
logger
=
logger
yield
logger
except
Exception
:
self
.
echo
(
self
.
yellow
(
f
"See
{
file_name
}
for detailed debug log."
))
else
:
try
:
os
.
remove
(
file_name
)
except
OSError
:
pass
stream
=
IOStream
()
pdm/project/core.py
浏览文件 @
ae82fa56
...
...
@@ -249,7 +249,10 @@ class Project:
:param spinner: optional spinner object
:returns: a reporter
"""
return
SpinnerReporter
(
spinner
)
flat_reqs
=
[
req
for
req_set
in
requirements
.
values
()
for
req
in
req_set
.
values
()
]
return
SpinnerReporter
(
spinner
,
flat_reqs
)
def
get_project_metadata
(
self
)
->
Dict
[
str
,
Any
]:
content_hash
=
self
.
get_content_hash
(
"md5"
)
...
...
pdm/resolver/reporters.py
浏览文件 @
ae82fa56
from
__future__
import
annotations
import
time
from
typing
import
TYPE_CHECKING
,
Dict
,
List
,
Optional
import
halo
...
...
@@ -13,27 +12,23 @@ if TYPE_CHECKING:
from
pdm.resolver.resolvers
import
State
def
print_title
(
title
):
print
(
"="
*
20
+
" "
+
title
+
" "
+
"="
*
20
)
class
SimpleReporter
:
def
__init__
(
self
,
requirements
:
List
[
Requirement
])
->
None
:
class
SpinnerReporter
:
def
__init__
(
self
,
spinner
:
halo
.
Halo
,
requirements
:
List
[
Requirement
])
->
None
:
self
.
spinner
=
spinner
self
.
requirements
=
requirements
self
.
start_at
=
None
# type: Optional[float]
self
.
_previous
=
None
# type: Optional[Dict[str, Candidate]]
def
starting_round
(
self
,
index
:
int
)
->
None
:
# self.spinner.hide_and_write(f"Resolving ROUND {index}")
pass
def
starting
(
self
)
->
None
:
"""Called before the resolution actually starts.
"""
self
.
_previous
=
None
print_title
(
"Start resolving requirements..."
)
self
.
start_at
=
time
.
time
()
for
r
in
self
.
requirements
:
print
(
r
.
as_line
())
stream
.
logger
.
info
(
"Start resolving requirements"
)
stream
.
logger
.
info
(
"============================"
)
for
req
in
self
.
requirements
:
stream
.
logger
.
info
(
"
\t
"
+
req
.
as_line
())
def
ending_round
(
self
,
index
:
int
,
state
:
State
)
->
None
:
"""Called before each round of resolution ends.
...
...
@@ -41,8 +36,8 @@ class SimpleReporter:
This is NOT called if the resolution ends at this round. Use `ending`
if you want to report finalization. The index is zero-based.
"""
print_title
(
f
"Ending ROUND
{
index
}
"
)
stream
.
logger
.
info
(
"Ending round {}"
.
format
(
index
)
)
stream
.
logger
.
info
(
"==============="
)
if
not
self
.
_previous
:
added
=
state
.
mapping
.
values
()
changed
=
[]
...
...
@@ -54,62 +49,33 @@ class SimpleReporter:
if
k
in
self
.
_previous
and
self
.
_previous
[
k
]
!=
can
]
if
added
:
print
(
"New pins:"
)
stream
.
logger
.
info
(
"New pins:"
)
for
can
in
added
:
print
(
f
"
\t
{
can
.
name
}
\t
{
can
.
version
}
"
)
stream
.
logger
.
info
(
f
"
\t
{
can
.
name
}
\t
{
can
.
version
}
"
)
if
changed
:
print
(
"Changed pins:"
)
stream
.
logger
.
info
(
"Changed pins:"
)
for
(
old
,
new
)
in
changed
:
print
(
f
"
\t
{
new
.
name
}
\t
{
old
.
version
}
->
{
new
.
version
}
"
)
stream
.
logger
.
info
(
f
"
\t
{
new
.
name
}
\t
{
old
.
version
}
->
{
new
.
version
}
"
)
self
.
_previous
=
state
.
mapping
def
ending
(
self
,
state
:
State
)
->
None
:
"""Called before the resolution ends successfully.
"""
print
(
"End resolving..."
)
print
(
"Stable pins:"
)
for
k
,
can
in
state
.
mapping
.
items
():
print
(
f
"
\t
{
can
.
name
}
\t
{
can
.
version
}
"
)
def
resolve_criteria
(
self
,
name
):
pass
def
pin_candidate
(
self
,
name
,
criterion
,
candidate
,
child_names
):
pass
def
extract_metadata
(
self
):
pass
class
SpinnerReporter
:
def
__init__
(
self
,
spinner
:
halo
.
Halo
)
->
None
:
self
.
spinner
=
spinner
def
starting_round
(
self
,
index
:
int
)
->
None
:
# self.spinner.hide_and_write(f"Resolving ROUND {index}")
pass
def
starting
(
self
)
->
None
:
"""Called before the resolution actually starts.
"""
def
ending_round
(
self
,
index
:
int
,
state
:
State
)
->
None
:
"""Called before each round of resolution ends.
This is NOT called if the resolution ends at this round. Use `ending`
if you want to report finalization. The index is zero-based.
"""
def
ending
(
self
,
state
:
State
)
->
None
:
"""Called before the resolution ends successfully.
"""
self
.
spinner
.
stop_and_persist
(
text
=
"Finish resolving"
)
stream
.
logger
.
info
(
"Resolution Result"
)
stream
.
logger
.
info
(
"================="
)
stream
.
logger
.
info
(
"Stable pins:"
)
for
k
,
can
in
state
.
mapping
.
items
():
stream
.
logger
.
info
(
f
"
\t
{
can
.
name
}
\t
{
can
.
version
}
"
)
def
resolve_criteria
(
self
,
name
):
self
.
spinner
.
text
=
f
"Resolving
{
stream
.
green
(
name
,
bold
=
True
)
}
"
stream
.
logger
.
info
(
f
"
\t
Resolving package
\t
{
name
}
"
)
def
pin_candidate
(
self
,
name
,
criterion
,
candidate
,
child_names
):
self
.
spinner
.
text
=
f
"Resolved:
{
candidate
.
format
()
}
"
stream
.
logger
.
info
(
f
"
\t
Found candidate
\t
{
candidate
.
name
}
\t
{
candidate
.
version
}
"
)
def
extract_metadata
(
self
):
self
.
spinner
.
start
(
"Extracting package metadata"
)
pdm/resolver/resolvers.py
浏览文件 @
ae82fa56
...
...
@@ -15,7 +15,7 @@ if TYPE_CHECKING:
from
pdm.models.candidates
import
Candidate
from
pdm.models.requirements
import
Requirement
from
pdm.resolver.providers
import
BaseProvider
from
pdm.resolver.reporters
import
S
imple
Reporter
from
pdm.resolver.reporters
import
S
pinner
Reporter
RequirementInformation
=
collections
.
namedtuple
(
"RequirementInformation"
,
[
"requirement"
,
"parent"
]
...
...
@@ -86,7 +86,7 @@ class Resolution(object):
the resolution process, and holds the results afterwards.
"""
def
__init__
(
self
,
provider
:
BaseProvider
,
reporter
:
S
imple
Reporter
):
def
__init__
(
self
,
provider
:
BaseProvider
,
reporter
:
S
pinner
Reporter
):
self
.
_p
=
provider
self
.
_r
=
reporter
self
.
_roots
=
[]
# type: List[str]
...
...
@@ -265,7 +265,7 @@ class Resolver(object):
"""The thing that performs the actual resolution work.
"""
def
__init__
(
self
,
provider
:
BaseProvider
,
reporter
:
S
imple
Reporter
)
->
None
:
def
__init__
(
self
,
provider
:
BaseProvider
,
reporter
:
S
pinner
Reporter
)
->
None
:
self
.
provider
=
provider
self
.
reporter
=
reporter
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录