Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
镜像
Python_Packaging_Authority
pip
提交
fc7ca264
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,发现更多精彩内容 >>
提交
fc7ca264
编写于
10月 02, 2017
作者:
P
Pradyun Gedam
提交者:
Paul Moore
10月 02, 2017
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Warn user when installing scripts outside PATH (#4553)
上级
3e56733d
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
195 addition
and
7 deletion
+195
-7
news/4553.feature
news/4553.feature
+1
-0
src/pip/_internal/commands/install.py
src/pip/_internal/commands/install.py
+9
-0
src/pip/_internal/req/req_install.py
src/pip/_internal/req/req_install.py
+8
-3
src/pip/_internal/wheel.py
src/pip/_internal/wheel.py
+71
-3
tests/functional/test_install.py
tests/functional/test_install.py
+23
-0
tests/unit/test_wheel.py
tests/unit/test_wheel.py
+83
-1
未找到文件。
news/4553.feature
0 → 100644
浏览文件 @
fc7ca264
pip
now
displays
a
warning when it installs scripts from a wheel outside the PATH. These warnings can be suppressed using a new --no-warn-script-location option.
src/pip/_internal/commands/install.py
浏览文件 @
fc7ca264
...
...
@@ -158,6 +158,14 @@ class InstallCommand(RequirementCommand):
help
=
"Do not compile Python source files to bytecode"
,
)
cmd_opts
.
add_option
(
"--no-warn-script-location"
,
action
=
"store_false"
,
dest
=
"warn_script_location"
,
default
=
True
,
help
=
"Do not warn when installing scripts outside PATH"
,
)
cmd_opts
.
add_option
(
cmdoptions
.
no_binary
())
cmd_opts
.
add_option
(
cmdoptions
.
only_binary
())
cmd_opts
.
add_option
(
cmdoptions
.
no_clean
())
...
...
@@ -290,6 +298,7 @@ class InstallCommand(RequirementCommand):
global_options
,
root
=
options
.
root_path
,
prefix
=
options
.
prefix_path
,
warn_script_location
=
options
.
warn_script_location
,
)
possible_lib_locations
=
get_lib_location_guesses
(
...
...
src/pip/_internal/req/req_install.py
浏览文件 @
fc7ca264
...
...
@@ -725,7 +725,7 @@ class InstallRequirement(object):
return
True
def
install
(
self
,
install_options
,
global_options
=
None
,
root
=
None
,
prefix
=
None
):
prefix
=
None
,
warn_script_location
=
True
):
global_options
=
global_options
if
global_options
is
not
None
else
[]
if
self
.
editable
:
self
.
install_editable
(
...
...
@@ -735,7 +735,10 @@ class InstallRequirement(object):
version
=
wheel
.
wheel_version
(
self
.
source_dir
)
wheel
.
check_compatibility
(
version
,
self
.
name
)
self
.
move_wheel_files
(
self
.
source_dir
,
root
=
root
,
prefix
=
prefix
)
self
.
move_wheel_files
(
self
.
source_dir
,
root
=
root
,
prefix
=
prefix
,
warn_script_location
=
warn_script_location
,
)
self
.
install_succeeded
=
True
return
...
...
@@ -927,7 +930,8 @@ class InstallRequirement(object):
def
is_wheel
(
self
):
return
self
.
link
and
self
.
link
.
is_wheel
def
move_wheel_files
(
self
,
wheeldir
,
root
=
None
,
prefix
=
None
):
def
move_wheel_files
(
self
,
wheeldir
,
root
=
None
,
prefix
=
None
,
warn_script_location
=
True
):
move_wheel_files
(
self
.
name
,
self
.
req
,
wheeldir
,
user
=
self
.
use_user_site
,
...
...
@@ -936,6 +940,7 @@ class InstallRequirement(object):
prefix
=
prefix
,
pycompile
=
self
.
pycompile
,
isolated
=
self
.
isolated
,
warn_script_location
=
warn_script_location
,
)
def
get_dist
(
self
):
...
...
src/pip/_internal/wheel.py
浏览文件 @
fc7ca264
...
...
@@ -3,6 +3,7 @@ Support for installing and building the "wheel" binary package format.
"""
from
__future__
import
absolute_import
import
collections
import
compileall
import
copy
import
csv
...
...
@@ -37,8 +38,12 @@ from pip._internal.utils.misc import (
)
from
pip._internal.utils.setuptools_build
import
SETUPTOOLS_SHIM
from
pip._internal.utils.temp_dir
import
TempDirectory
from
pip._internal.utils.typing
import
MYPY_CHECK_RUNNING
from
pip._internal.utils.ui
import
open_spinner
if
MYPY_CHECK_RUNNING
:
from
typing
import
Dict
,
List
,
Optional
wheel_ext
=
'.whl'
VERSION_COMPATIBLE
=
(
1
,
0
)
...
...
@@ -140,8 +145,64 @@ def get_entrypoints(filename):
return
console
,
gui
def
message_about_scripts_not_on_PATH
(
scripts
):
# type: (List[str]) -> Optional[str]
"""Determine if any scripts are not on PATH and format a warning.
Returns a warning message if one or more scripts are not on PATH,
otherwise None.
"""
if
not
scripts
:
return
None
# Group scripts by the path they were installed in
grouped_by_dir
=
collections
.
defaultdict
(
set
)
# type: Dict[str, set]
for
destfile
in
scripts
:
parent_dir
=
os
.
path
.
dirname
(
destfile
)
script_name
=
os
.
path
.
basename
(
destfile
)
grouped_by_dir
[
parent_dir
].
add
(
script_name
)
path_env_var_parts
=
os
.
environ
[
"PATH"
].
split
(
os
.
pathsep
)
# Warn only for directories that are not on PATH
warn_for
=
{
parent_dir
:
scripts
for
parent_dir
,
scripts
in
grouped_by_dir
.
items
()
if
parent_dir
not
in
path_env_var_parts
}
if
not
warn_for
:
return
None
# Format a message
msg_lines
=
[]
for
parent_dir
,
scripts
in
warn_for
.
items
():
scripts
=
sorted
(
scripts
)
if
len
(
scripts
)
==
1
:
start_text
=
"script {} is"
.
format
(
scripts
[
0
])
else
:
start_text
=
"scripts {} are"
.
format
(
", "
.
join
(
scripts
[:
-
1
])
+
" and "
+
scripts
[
-
1
]
)
msg_lines
.
append
(
"The {} installed in '{}' which is not on PATH."
.
format
(
start_text
,
parent_dir
)
)
last_line_fmt
=
(
"Consider adding {} to PATH or, if you prefer "
"to suppress this warning, use --no-warn-script-location."
)
if
len
(
msg_lines
)
==
1
:
msg_lines
.
append
(
last_line_fmt
.
format
(
"this directory"
))
else
:
msg_lines
.
append
(
last_line_fmt
.
format
(
"these directories"
))
# Returns the formatted multiline message
return
"
\n
"
.
join
(
msg_lines
)
def
move_wheel_files
(
name
,
req
,
wheeldir
,
user
=
False
,
home
=
None
,
root
=
None
,
pycompile
=
True
,
scheme
=
None
,
isolated
=
False
,
prefix
=
None
):
pycompile
=
True
,
scheme
=
None
,
isolated
=
False
,
prefix
=
None
,
warn_script_location
=
True
):
"""Install a wheel"""
if
not
scheme
:
...
...
@@ -391,9 +452,16 @@ if __name__ == '__main__':
# Generate the console and GUI entry points specified in the wheel
if
len
(
console
)
>
0
:
generated
.
extend
(
maker
.
make_multiple
([
'%s = %s'
%
kv
for
kv
in
console
.
items
()])
generated
_console_scripts
=
maker
.
make_multiple
(
[
'%s = %s'
%
kv
for
kv
in
console
.
items
()]
)
generated
.
extend
(
generated_console_scripts
)
if
warn_script_location
:
msg
=
message_about_scripts_not_on_PATH
(
generated_console_scripts
)
if
msg
is
not
None
:
logger
.
warn
(
msg
)
if
len
(
gui
)
>
0
:
generated
.
extend
(
maker
.
make_multiple
(
...
...
tests/functional/test_install.py
浏览文件 @
fc7ca264
...
...
@@ -1224,3 +1224,26 @@ def test_install_pep508_with_url_in_install_requires(script):
res
=
script
.
pip
(
'install'
,
pkga_path
,
expect_error
=
True
)
assert
"Direct url requirement "
in
res
.
stderr
,
str
(
res
)
assert
"are not allowed for dependencies"
in
res
.
stderr
,
str
(
res
)
def
test_installing_scripts_outside_path_prints_warning
(
script
):
result
=
script
.
pip_install_local
(
"--prefix"
,
script
.
scratch_path
,
"script_wheel1"
,
expect_error
=
True
)
assert
"Successfully installed script-wheel1"
in
result
.
stdout
,
str
(
result
)
assert
"--no-warn-script-location"
in
result
.
stderr
def
test_installing_scripts_outside_path_can_suppress_warning
(
script
):
result
=
script
.
pip_install_local
(
"--prefix"
,
script
.
scratch_path
,
"--no-warn-script-location"
,
"script_wheel1"
)
assert
"Successfully installed script-wheel1"
in
result
.
stdout
,
str
(
result
)
assert
"--no-warn-script-location"
not
in
result
.
stderr
def
test_installing_scripts_on_path_does_not_print_warning
(
script
):
result
=
script
.
pip_install_local
(
"script_wheel1"
)
assert
"Successfully installed script-wheel1"
in
result
.
stdout
,
str
(
result
)
assert
"--no-warn-script-location"
not
in
result
.
stderr
tests/unit/test_wheel.py
浏览文件 @
fc7ca264
...
...
@@ -9,7 +9,6 @@ from pip._internal import pep425tags, wheel
from
pip._internal.compat
import
WINDOWS
from
pip._internal.exceptions
import
InvalidWheelFilename
,
UnsupportedWheel
from
pip._internal.utils.misc
import
unpack_file
from
tests.lib
import
DATA_DIR
...
...
@@ -371,3 +370,86 @@ class TestWheelBuilder(object):
wb
.
build
(
Mock
())
assert
"due to already being wheel"
in
caplog
.
text
assert
mock_build_one
.
mock_calls
==
[]
class
TestMessageAboutScriptsNotOnPATH
(
object
):
def
_template
(
self
,
paths
,
scripts
):
with
patch
.
dict
(
'os.environ'
,
{
'PATH'
:
os
.
pathsep
.
join
(
paths
)}):
return
wheel
.
message_about_scripts_not_on_PATH
(
scripts
)
def
test_no_script
(
self
):
retval
=
self
.
_template
(
paths
=
[
'/a/b'
,
'/c/d/bin'
],
scripts
=
[]
)
assert
retval
is
None
def
test_single_script__single_dir_not_on_PATH
(
self
):
retval
=
self
.
_template
(
paths
=
[
'/a/b'
,
'/c/d/bin'
],
scripts
=
[
'/c/d/foo'
]
)
assert
retval
is
not
None
assert
"--no-warn-script-location"
in
retval
assert
"foo is installed in '/c/d'"
in
retval
def
test_two_script__single_dir_not_on_PATH
(
self
):
retval
=
self
.
_template
(
paths
=
[
'/a/b'
,
'/c/d/bin'
],
scripts
=
[
'/c/d/foo'
,
'/c/d/baz'
]
)
assert
retval
is
not
None
assert
"--no-warn-script-location"
in
retval
assert
"baz and foo are installed in '/c/d'"
in
retval
def
test_multi_script__multi_dir_not_on_PATH
(
self
):
retval
=
self
.
_template
(
paths
=
[
'/a/b'
,
'/c/d/bin'
],
scripts
=
[
'/c/d/foo'
,
'/c/d/bar'
,
'/c/d/baz'
,
'/a/b/c/spam'
]
)
assert
retval
is
not
None
assert
"--no-warn-script-location"
in
retval
assert
"bar, baz and foo are installed in '/c/d'"
in
retval
assert
"spam is installed in '/a/b/c'"
in
retval
def
test_multi_script_all__multi_dir_not_on_PATH
(
self
):
retval
=
self
.
_template
(
paths
=
[
'/a/b'
,
'/c/d/bin'
],
scripts
=
[
'/c/d/foo'
,
'/c/d/bar'
,
'/c/d/baz'
,
'/a/b/c/spam'
,
'/a/b/c/eggs'
]
)
assert
retval
is
not
None
assert
"--no-warn-script-location"
in
retval
assert
"bar, baz and foo are installed in '/c/d'"
in
retval
assert
"eggs and spam are installed in '/a/b/c'"
in
retval
def
test_two_script__single_dir_on_PATH
(
self
):
retval
=
self
.
_template
(
paths
=
[
'/a/b'
,
'/c/d/bin'
],
scripts
=
[
'/a/b/foo'
,
'/a/b/baz'
]
)
assert
retval
is
None
def
test_multi_script__multi_dir_on_PATH
(
self
):
retval
=
self
.
_template
(
paths
=
[
'/a/b'
,
'/c/d/bin'
],
scripts
=
[
'/a/b/foo'
,
'/a/b/bar'
,
'/a/b/baz'
,
'/c/d/bin/spam'
]
)
assert
retval
is
None
def
test_multi_script__single_dir_on_PATH
(
self
):
retval
=
self
.
_template
(
paths
=
[
'/a/b'
,
'/c/d/bin'
],
scripts
=
[
'/a/b/foo'
,
'/a/b/bar'
,
'/a/b/baz'
]
)
assert
retval
is
None
def
test_single_script__single_dir_on_PATH
(
self
):
retval
=
self
.
_template
(
paths
=
[
'/a/b'
,
'/c/d/bin'
],
scripts
=
[
'/a/b/foo'
]
)
assert
retval
is
None
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录