Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
镜像
Python_Packaging_Authority
pip
提交
14fe337b
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,发现更多精彩内容 >>
提交
14fe337b
编写于
6月 22, 2018
作者:
K
Kexuan Sun
提交者:
Pradyun Gedam
6月 21, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Improve autocompletion function on file name completion (#5125)
上级
bcd9db92
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
199 addition
and
6 deletion
+199
-6
news/4842.feature
news/4842.feature
+2
-0
news/5125.feature
news/5125.feature
+2
-0
src/pip/_internal/__init__.py
src/pip/_internal/__init__.py
+68
-4
tests/data/completion_paths/README.txt
tests/data/completion_paths/README.txt
+0
-0
tests/data/completion_paths/REPLAY/video.mpeg
tests/data/completion_paths/REPLAY/video.mpeg
+0
-0
tests/data/completion_paths/requirements.txt
tests/data/completion_paths/requirements.txt
+0
-0
tests/data/completion_paths/resources/images/icon.png
tests/data/completion_paths/resources/images/icon.png
+0
-0
tests/functional/test_completion.py
tests/functional/test_completion.py
+123
-2
tests/lib/__init__.py
tests/lib/__init__.py
+4
-0
未找到文件。
news/4842.feature
0 → 100644
浏览文件 @
14fe337b
Improve
autocompletion
function
on
file
name
completion
after
options
which
have
``<file>``,
``<dir>``
or
``<path>``
as
metavar.
news/5125.feature
0 → 100644
浏览文件 @
14fe337b
Improve
autocompletion
function
on
file
name
completion
after
options
which
have
``<file>``,
``<dir>``
or
``<path>``
as
metavar.
src/pip/_internal/__init__.py
浏览文件 @
14fe337b
...
@@ -116,6 +116,15 @@ def autocomplete():
...
@@ -116,6 +116,15 @@ def autocomplete():
options
=
[(
x
,
v
)
for
(
x
,
v
)
in
options
if
x
not
in
prev_opts
]
options
=
[(
x
,
v
)
for
(
x
,
v
)
in
options
if
x
not
in
prev_opts
]
# filter options by current input
# filter options by current input
options
=
[(
k
,
v
)
for
k
,
v
in
options
if
k
.
startswith
(
current
)]
options
=
[(
k
,
v
)
for
k
,
v
in
options
if
k
.
startswith
(
current
)]
# get completion type given cwords and available subcommand options
completion_type
=
get_path_completion_type
(
cwords
,
cword
,
subcommand
.
parser
.
option_list_all
,
)
# get completion files and directories if ``completion_type`` is
# ``<file>``, ``<dir>`` or ``<path>``
if
completion_type
:
options
=
auto_complete_paths
(
current
,
completion_type
)
options
=
((
opt
,
0
)
for
opt
in
options
)
for
option
in
options
:
for
option
in
options
:
opt_label
=
option
[
0
]
opt_label
=
option
[
0
]
# append '=' to options which require args
# append '=' to options which require args
...
@@ -124,19 +133,74 @@ def autocomplete():
...
@@ -124,19 +133,74 @@ def autocomplete():
print
(
opt_label
)
print
(
opt_label
)
else
:
else
:
# show main parser options only when necessary
# show main parser options only when necessary
if
current
.
startswith
(
'-'
)
or
current
.
startswith
(
'--'
):
opts
=
[
i
.
option_list
for
i
in
parser
.
option_groups
]
opts
.
append
(
parser
.
option_list
)
opts
=
(
o
for
it
in
opts
for
o
in
it
)
opts
=
[
i
.
option_list
for
i
in
parser
.
option_groups
]
opts
.
append
(
parser
.
option_list
)
opts
=
(
o
for
it
in
opts
for
o
in
it
)
if
current
.
startswith
(
'-'
):
for
opt
in
opts
:
for
opt
in
opts
:
if
opt
.
help
!=
optparse
.
SUPPRESS_HELP
:
if
opt
.
help
!=
optparse
.
SUPPRESS_HELP
:
subcommands
+=
opt
.
_long_opts
+
opt
.
_short_opts
subcommands
+=
opt
.
_long_opts
+
opt
.
_short_opts
else
:
# get completion type given cwords and all available options
completion_type
=
get_path_completion_type
(
cwords
,
cword
,
opts
)
if
completion_type
:
subcommands
=
auto_complete_paths
(
current
,
completion_type
)
print
(
' '
.
join
([
x
for
x
in
subcommands
if
x
.
startswith
(
current
)]))
print
(
' '
.
join
([
x
for
x
in
subcommands
if
x
.
startswith
(
current
)]))
sys
.
exit
(
1
)
sys
.
exit
(
1
)
def
get_path_completion_type
(
cwords
,
cword
,
opts
):
"""Get the type of path completion (``file``, ``dir``, ``path`` or None)
:param cwords: same as the environmental variable ``COMP_WORDS``
:param cword: same as the environmental variable ``COMP_CWORD``
:param opts: The available options to check
:return: path completion type (``file``, ``dir``, ``path`` or None)
"""
if
cword
<
2
or
not
cwords
[
cword
-
2
].
startswith
(
'-'
):
return
for
opt
in
opts
:
if
opt
.
help
==
optparse
.
SUPPRESS_HELP
:
continue
for
o
in
str
(
opt
).
split
(
'/'
):
if
cwords
[
cword
-
2
].
split
(
'='
)[
0
]
==
o
:
if
any
(
x
in
(
'path'
,
'file'
,
'dir'
)
for
x
in
opt
.
metavar
.
split
(
'/'
)):
return
opt
.
metavar
def
auto_complete_paths
(
current
,
completion_type
):
"""If ``completion_type`` is ``file`` or ``path``, list all regular files
and directories starting with ``current``; otherwise only list directories
starting with ``current``.
:param current: The word to be completed
:param completion_type: path completion type(`file`, `path` or `dir`)i
:return: A generator of regular files and/or directories
"""
directory
,
filename
=
os
.
path
.
split
(
current
)
current_path
=
os
.
path
.
abspath
(
directory
)
# Don't complete paths if they can't be accessed
if
not
os
.
access
(
current_path
,
os
.
R_OK
):
return
filename
=
os
.
path
.
normcase
(
filename
)
# list all files that start with ``filename``
file_list
=
(
x
for
x
in
os
.
listdir
(
current_path
)
if
os
.
path
.
normcase
(
x
).
startswith
(
filename
))
for
f
in
file_list
:
opt
=
os
.
path
.
join
(
current_path
,
f
)
comp_file
=
os
.
path
.
normcase
(
os
.
path
.
join
(
directory
,
f
))
# complete regular files when there is not ``<dir>`` after option
# complete directories when there is ``<file>``, ``<path>`` or
# ``<dir>``after option
if
completion_type
!=
'dir'
and
os
.
path
.
isfile
(
opt
):
yield
comp_file
elif
os
.
path
.
isdir
(
opt
):
yield
os
.
path
.
join
(
comp_file
,
''
)
def
create_main_parser
():
def
create_main_parser
():
parser_kw
=
{
parser_kw
=
{
'usage'
:
'
\n
%prog <command> [options]'
,
'usage'
:
'
\n
%prog <command> [options]'
,
...
...
tests/data/completion_paths/README.txt
0 → 100644
浏览文件 @
14fe337b
tests/data/completion_paths/REPLAY/video.mpeg
0 → 100644
浏览文件 @
14fe337b
tests/data/completion_paths/requirements.txt
0 → 100644
浏览文件 @
14fe337b
tests/data/completion_paths/resources/images/icon.png
0 → 100644
浏览文件 @
14fe337b
tests/functional/test_completion.py
浏览文件 @
14fe337b
...
@@ -77,7 +77,7 @@ def test_completion_alone(script):
...
@@ -77,7 +77,7 @@ def test_completion_alone(script):
'completion alone failed -- '
+
result
.
stderr
'completion alone failed -- '
+
result
.
stderr
def
setup_completion
(
script
,
words
,
cword
):
def
setup_completion
(
script
,
words
,
cword
,
cwd
=
None
):
script
.
environ
=
os
.
environ
.
copy
()
script
.
environ
=
os
.
environ
.
copy
()
script
.
environ
[
'PIP_AUTO_COMPLETE'
]
=
'1'
script
.
environ
[
'PIP_AUTO_COMPLETE'
]
=
'1'
script
.
environ
[
'COMP_WORDS'
]
=
words
script
.
environ
[
'COMP_WORDS'
]
=
words
...
@@ -87,6 +87,7 @@ def setup_completion(script, words, cword):
...
@@ -87,6 +87,7 @@ def setup_completion(script, words, cword):
result
=
script
.
run
(
result
=
script
.
run
(
'python'
,
'-c'
,
'import pip._internal;pip._internal.autocomplete()'
,
'python'
,
'-c'
,
'import pip._internal;pip._internal.autocomplete()'
,
expect_error
=
True
,
expect_error
=
True
,
cwd
=
cwd
,
)
)
return
result
,
script
return
result
,
script
...
@@ -113,7 +114,7 @@ def test_completion_for_default_parameters(script):
...
@@ -113,7 +114,7 @@ def test_completion_for_default_parameters(script):
def
test_completion_option_for_command
(
script
):
def
test_completion_option_for_command
(
script
):
"""
"""
Test getting completion for ``--`` in command (e
g. pip search --
)
Test getting completion for ``--`` in command (e
.g. ``pip search --``
)
"""
"""
res
,
env
=
setup_completion
(
script
,
'pip search --'
,
'2'
)
res
,
env
=
setup_completion
(
script
,
'pip search --'
,
'2'
)
...
@@ -144,6 +145,126 @@ def test_completion_short_option_for_command(script):
...
@@ -144,6 +145,126 @@ def test_completion_short_option_for_command(script):
"autocomplete function could not complete short options after ``-``"
"autocomplete function could not complete short options after ``-``"
def
test_completion_files_after_option
(
script
,
data
):
"""
Test getting completion for <file> or <dir> after options in command
(e.g. ``pip install -r``)
"""
res
,
env
=
setup_completion
(
script
=
script
,
words
=
(
'pip install -r r'
),
cword
=
'3'
,
cwd
=
data
.
completion_paths
,
)
assert
'requirements.txt'
in
res
.
stdout
,
(
"autocomplete function could not complete <file> "
"after options in command"
)
assert
os
.
path
.
join
(
'resources'
,
''
)
in
res
.
stdout
,
(
"autocomplete function could not complete <dir> "
"after options in command"
)
assert
not
any
(
out
in
res
.
stdout
for
out
in
(
os
.
path
.
join
(
'REPLAY'
,
''
),
'README.txt'
)),
(
"autocomplete function completed <file> or <dir> that "
"should not be completed"
)
if
sys
.
platform
!=
'win32'
:
return
assert
'readme.txt'
in
res
.
stdout
,
(
"autocomplete function could not complete <file> "
"after options in command"
)
assert
os
.
path
.
join
(
'replay'
,
''
)
in
res
.
stdout
,
(
"autocomplete function could not complete <dir> "
"after options in command"
)
def
test_completion_not_files_after_option
(
script
,
data
):
"""
Test not getting completion files after options which not applicable
(e.g. ``pip install``)
"""
res
,
env
=
setup_completion
(
script
=
script
,
words
=
(
'pip install r'
),
cword
=
'2'
,
cwd
=
data
.
completion_paths
,
)
assert
not
any
(
out
in
res
.
stdout
for
out
in
(
'requirements.txt'
,
'readme.txt'
,)),
(
"autocomplete function completed <file> when "
"it should not complete"
)
assert
not
any
(
os
.
path
.
join
(
out
,
''
)
in
res
.
stdout
for
out
in
(
'replay'
,
'resources'
)),
(
"autocomplete function completed <dir> when "
"it should not complete"
)
def
test_completion_directories_after_option
(
script
,
data
):
"""
Test getting completion <dir> after options in command
(e.g. ``pip --cache-dir``)
"""
res
,
env
=
setup_completion
(
script
=
script
,
words
=
(
'pip --cache-dir r'
),
cword
=
'2'
,
cwd
=
data
.
completion_paths
,
)
assert
os
.
path
.
join
(
'resources'
,
''
)
in
res
.
stdout
,
(
"autocomplete function could not complete <dir> after options"
)
assert
not
any
(
out
in
res
.
stdout
for
out
in
(
'requirements.txt'
,
'README.txt'
,
os
.
path
.
join
(
'REPLAY'
,
''
))),
(
"autocomplete function completed <dir> when "
"it should not complete"
)
if
sys
.
platform
==
'win32'
:
assert
os
.
path
.
join
(
'replay'
,
''
)
in
res
.
stdout
,
(
"autocomplete function could not complete <dir> after options"
)
def
test_completion_subdirectories_after_option
(
script
,
data
):
"""
Test getting completion <dir> after options in command
given path of a directory
"""
res
,
env
=
setup_completion
(
script
=
script
,
words
=
(
'pip --cache-dir '
+
os
.
path
.
join
(
'resources'
,
''
)),
cword
=
'2'
,
cwd
=
data
.
completion_paths
,
)
assert
os
.
path
.
join
(
'resources'
,
os
.
path
.
join
(
'images'
,
''
))
in
res
.
stdout
,
(
"autocomplete function could not complete <dir> "
"given path of a directory after options"
)
def
test_completion_path_after_option
(
script
,
data
):
"""
Test getting completion <path> after options in command
given absolute path
"""
res
,
env
=
setup_completion
(
script
=
script
,
words
=
(
'pip install -e '
+
os
.
path
.
join
(
data
.
completion_paths
,
'R'
)),
cword
=
'3'
,
)
assert
all
(
os
.
path
.
normcase
(
os
.
path
.
join
(
data
.
completion_paths
,
out
))
in
res
.
stdout
for
out
in
(
'README.txt'
,
os
.
path
.
join
(
'REPLAY'
,
''
))),
(
"autocomplete function could not complete <path> "
"after options in command given absolute path"
)
@
pytest
.
mark
.
parametrize
(
'flag'
,
[
'--bash'
,
'--zsh'
,
'--fish'
])
@
pytest
.
mark
.
parametrize
(
'flag'
,
[
'--bash'
,
'--zsh'
,
'--fish'
])
def
test_completion_uses_same_executable_name
(
script
,
flag
):
def
test_completion_uses_same_executable_name
(
script
,
flag
):
expect_stderr
=
sys
.
version_info
[:
2
]
==
(
3
,
3
)
expect_stderr
=
sys
.
version_info
[:
2
]
==
(
3
,
3
)
...
...
tests/lib/__init__.py
浏览文件 @
14fe337b
...
@@ -116,6 +116,10 @@ class TestData(object):
...
@@ -116,6 +116,10 @@ class TestData(object):
def
reqfiles
(
self
):
def
reqfiles
(
self
):
return
self
.
root
.
join
(
"reqfiles"
)
return
self
.
root
.
join
(
"reqfiles"
)
@
property
def
completion_paths
(
self
):
return
self
.
root
.
join
(
"completion_paths"
)
@
property
@
property
def
find_links
(
self
):
def
find_links
(
self
):
return
path_to_url
(
self
.
packages
)
return
path_to_url
(
self
.
packages
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录