argcomplete 3.6.2__tar.gz → 3.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {argcomplete-3.6.2 → argcomplete-3.7.0}/.github/workflows/ci.yml +10 -10
- {argcomplete-3.6.2 → argcomplete-3.7.0}/Changes.rst +20 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/PKG-INFO +3 -3
- {argcomplete-3.6.2 → argcomplete-3.7.0}/README.rst +1 -1
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/bash_completion.d/_python-argcomplete +3 -5
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/completers.py +7 -4
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/finders.py +14 -4
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/packages/_argparse.py +16 -8
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/scripts/activate_global_python_argcomplete.py +3 -1
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/shell_integration.py +9 -9
- {argcomplete-3.6.2 → argcomplete-3.7.0}/contrib/README.rst +8 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/pyproject.toml +1 -2
- {argcomplete-3.6.2 → argcomplete-3.7.0}/test/test.py +14 -0
- argcomplete-3.6.2/argcomplete/scripts/python_argcomplete_check_easy_install_script.py +0 -84
- {argcomplete-3.6.2 → argcomplete-3.7.0}/.github/FUNDING.yml +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/.github/workflows/release.yml +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/.gitignore +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/Authors.rst +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/LICENSE.rst +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/MANIFEST.in +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/Makefile +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/NOTICE +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/SECURITY.md +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/__init__.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/_check_console_script.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/_check_module.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/exceptions.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/io.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/lexers.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/packages/__init__.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/packages/_shlex.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/py.typed +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/scripts/__init__.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/scripts/register_python_argcomplete.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/common.mk +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/docs/changelog.rst +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/docs/conf.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/docs/examples/describe_github_user.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/docs/fish_help_string.png +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/docs/index.rst +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/docs/toc.html +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/setup.cfg +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/test/__init__.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/test/inputrc +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/test/prog +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/test/stuck +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/test/test_contrib_shells.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/test/test_package/__init__.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/test/test_package/setup.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/test/test_package/test_module.py +0 -0
- {argcomplete-3.6.2 → argcomplete-3.7.0}/test/test_package/test_package/__init__.py +0 -0
|
@@ -3,17 +3,17 @@ name: Python package
|
|
|
3
3
|
on: [push, pull_request]
|
|
4
4
|
|
|
5
5
|
jobs:
|
|
6
|
-
|
|
6
|
+
ci:
|
|
7
7
|
runs-on: ${{matrix.os}}
|
|
8
8
|
strategy:
|
|
9
9
|
fail-fast: false
|
|
10
10
|
matrix:
|
|
11
|
-
os: [ubuntu-
|
|
12
|
-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
11
|
+
os: [ubuntu-22.04, ubuntu-latest, macos-14, macos-latest]
|
|
12
|
+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "3.15"]
|
|
13
13
|
|
|
14
14
|
steps:
|
|
15
|
-
- uses: actions/checkout@
|
|
16
|
-
- uses: actions/setup-python@
|
|
15
|
+
- uses: actions/checkout@v7
|
|
16
|
+
- uses: actions/setup-python@v6
|
|
17
17
|
with:
|
|
18
18
|
python-version: ${{matrix.python-version}}
|
|
19
19
|
allow-prereleases: true
|
|
@@ -31,15 +31,15 @@ jobs:
|
|
|
31
31
|
- uses: codecov/codecov-action@v5
|
|
32
32
|
if: ${{matrix.python-version == '3.12' && matrix.os == 'ubuntu-22.04'}}
|
|
33
33
|
isort:
|
|
34
|
-
runs-on: ubuntu-
|
|
34
|
+
runs-on: ubuntu-24.04
|
|
35
35
|
steps:
|
|
36
|
-
- uses: actions/checkout@
|
|
36
|
+
- uses: actions/checkout@v7
|
|
37
37
|
- uses: isort/isort-action@v1.1.0
|
|
38
38
|
ruff:
|
|
39
39
|
runs-on: ubuntu-latest
|
|
40
40
|
steps:
|
|
41
|
-
- uses: actions/checkout@
|
|
42
|
-
- uses: astral-sh/ruff-action@
|
|
43
|
-
- uses: astral-sh/ruff-action@
|
|
41
|
+
- uses: actions/checkout@v7
|
|
42
|
+
- uses: astral-sh/ruff-action@v4.0.0
|
|
43
|
+
- uses: astral-sh/ruff-action@v4.0.0
|
|
44
44
|
with:
|
|
45
45
|
args: "format --check"
|
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
Changes for v3.7.0 (2026-06-30)
|
|
2
|
+
===============================
|
|
3
|
+
|
|
4
|
+
- Escape glob and brace metacharacters in quote_completions (#552)
|
|
5
|
+
- Quote prefix passed to compgen in FilesCompleter (#551)
|
|
6
|
+
- Remove deprecated easy_install script detection
|
|
7
|
+
- Type hinting improvements
|
|
8
|
+
|
|
9
|
+
Changes for v3.6.3 (2025-10-19)
|
|
10
|
+
===============================
|
|
11
|
+
|
|
12
|
+
- Make RE PCRE compatible. Fixes #539
|
|
13
|
+
|
|
14
|
+
- Only execute Python interpreters (#536)
|
|
15
|
+
|
|
16
|
+
- fish: set variable scope to local to avoid clobbering global or
|
|
17
|
+
universal variables (#534)
|
|
18
|
+
|
|
19
|
+
- Documentation and help improvements
|
|
20
|
+
|
|
1
21
|
Changes for v3.6.2 (2025-04-02)
|
|
2
22
|
===============================
|
|
3
23
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: argcomplete
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.7.0
|
|
4
4
|
Summary: Bash tab completion for argparse
|
|
5
5
|
Project-URL: Homepage, https://github.com/kislyuk/argcomplete
|
|
6
6
|
Project-URL: Documentation, https://kislyuk.github.io/argcomplete
|
|
@@ -22,12 +22,12 @@ Classifier: Operating System :: MacOS :: MacOS X
|
|
|
22
22
|
Classifier: Operating System :: POSIX
|
|
23
23
|
Classifier: Programming Language :: Python
|
|
24
24
|
Classifier: Programming Language :: Python :: 3
|
|
25
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
26
25
|
Classifier: Programming Language :: Python :: 3.9
|
|
27
26
|
Classifier: Programming Language :: Python :: 3.10
|
|
28
27
|
Classifier: Programming Language :: Python :: 3.11
|
|
29
28
|
Classifier: Programming Language :: Python :: 3.12
|
|
30
29
|
Classifier: Programming Language :: Python :: 3.13
|
|
30
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
31
31
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
32
32
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
33
33
|
Classifier: Topic :: Software Development
|
|
@@ -51,7 +51,7 @@ Argcomplete provides easy, extensible command line tab completion of arguments f
|
|
|
51
51
|
|
|
52
52
|
It makes two assumptions:
|
|
53
53
|
|
|
54
|
-
* You're using bash or zsh as your shell
|
|
54
|
+
* You're using bash or zsh as your shell (limited support exists for other shells - see below)
|
|
55
55
|
* You're using `argparse <http://docs.python.org/3/library/argparse.html>`_ to manage your command line arguments/options
|
|
56
56
|
|
|
57
57
|
Argcomplete is particularly useful if your program has lots of options or subparsers, and if your program can
|
|
@@ -6,7 +6,7 @@ Argcomplete provides easy, extensible command line tab completion of arguments f
|
|
|
6
6
|
|
|
7
7
|
It makes two assumptions:
|
|
8
8
|
|
|
9
|
-
* You're using bash or zsh as your shell
|
|
9
|
+
* You're using bash or zsh as your shell (limited support exists for other shells - see below)
|
|
10
10
|
* You're using `argparse <http://docs.python.org/3/library/argparse.html>`_ to manage your command line arguments/options
|
|
11
11
|
|
|
12
12
|
Argcomplete is particularly useful if your program has lots of options or subparsers, and if your program can
|
|
@@ -190,10 +190,8 @@ _python_argcomplete_global() {
|
|
|
190
190
|
interpreter=($interpreter)
|
|
191
191
|
fi
|
|
192
192
|
|
|
193
|
-
if (
|
|
194
|
-
&& "${interpreter[@]}"
|
|
195
|
-
ARGCOMPLETE=1
|
|
196
|
-
elif __python_argcomplete_run "${interpreter[@]}" -m argcomplete._check_console_script "$SCRIPT_NAME"; then
|
|
193
|
+
if ([[ "${interpreter[@]}" == *python* ]] || [[ "${interpreter[@]}" == *pypy* ]])\
|
|
194
|
+
&& __python_argcomplete_run "${interpreter[@]}" -m argcomplete._check_console_script "$SCRIPT_NAME"; then
|
|
197
195
|
ARGCOMPLETE=1
|
|
198
196
|
fi
|
|
199
197
|
fi
|
|
@@ -215,7 +213,7 @@ _python_argcomplete_global() {
|
|
|
215
213
|
if is-at-least 5.8; then
|
|
216
214
|
nosort=(-o nosort)
|
|
217
215
|
fi
|
|
218
|
-
if [[ "${completions-}" =~ ([
|
|
216
|
+
if [[ "${completions-}" =~ ([^\\\\]): && "${BASH_REMATCH[2]}" =~ [=/:] ]]; then
|
|
219
217
|
nospace=(-S '')
|
|
220
218
|
fi
|
|
221
219
|
_describe "$executable" completions "${nosort[@]}" "${nospace[@]}"
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import argparse
|
|
5
5
|
import os
|
|
6
6
|
import subprocess
|
|
7
|
+
from shlex import quote
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
def _call(*args, **kwargs):
|
|
@@ -64,20 +65,22 @@ class FilesCompleter(BaseCompleter):
|
|
|
64
65
|
# correctly in older versions and calling bind makes them available. For details, see
|
|
65
66
|
# https://savannah.gnu.org/support/index.php?111125
|
|
66
67
|
files = _call(
|
|
67
|
-
["bash", "-c", "bind; compgen -A directory --
|
|
68
|
+
["bash", "-c", "bind; compgen -A directory -- {p}".format(p=quote(prefix))],
|
|
69
|
+
stderr=subprocess.DEVNULL,
|
|
68
70
|
)
|
|
69
71
|
completion += [f + "/" for f in files]
|
|
70
72
|
for x in self.allowednames:
|
|
71
73
|
completion += _call(
|
|
72
|
-
["bash", "-c", "bind; compgen -A file -X '!*.{0}' --
|
|
74
|
+
["bash", "-c", "bind; compgen -A file -X '!*.{0}' -- {p}".format(x, p=quote(prefix))],
|
|
73
75
|
stderr=subprocess.DEVNULL,
|
|
74
76
|
)
|
|
75
77
|
else:
|
|
76
78
|
completion += _call(
|
|
77
|
-
["bash", "-c", "bind; compgen -A file --
|
|
79
|
+
["bash", "-c", "bind; compgen -A file -- {p}".format(p=quote(prefix))], stderr=subprocess.DEVNULL
|
|
78
80
|
)
|
|
79
81
|
anticomp = _call(
|
|
80
|
-
["bash", "-c", "bind; compgen -A directory --
|
|
82
|
+
["bash", "-c", "bind; compgen -A directory -- {p}".format(p=quote(prefix))],
|
|
83
|
+
stderr=subprocess.DEVNULL,
|
|
81
84
|
)
|
|
82
85
|
completion = list(set(completion) - set(anticomp))
|
|
83
86
|
|
|
@@ -48,6 +48,7 @@ class CompletionFinder(object):
|
|
|
48
48
|
append_space=None,
|
|
49
49
|
):
|
|
50
50
|
self._parser = argument_parser
|
|
51
|
+
self._formatter = None
|
|
51
52
|
self.always_complete_options = always_complete_options
|
|
52
53
|
self.exclude = exclude
|
|
53
54
|
if validator is None:
|
|
@@ -283,6 +284,15 @@ class CompletionFinder(object):
|
|
|
283
284
|
|
|
284
285
|
return self.active_parsers
|
|
285
286
|
|
|
287
|
+
def _get_action_help(self, action):
|
|
288
|
+
if action.help is None:
|
|
289
|
+
return ""
|
|
290
|
+
if "%" not in action.help:
|
|
291
|
+
return action.help
|
|
292
|
+
if self._formatter is None:
|
|
293
|
+
self._formatter = self._parser.formatter_class(prog=self._parser.prog)
|
|
294
|
+
return self._formatter._expand_help(action)
|
|
295
|
+
|
|
286
296
|
def _get_subparser_completions(self, parser, cword_prefix):
|
|
287
297
|
aliases_by_parser: Dict[argparse.ArgumentParser, List[str]] = {}
|
|
288
298
|
for key in parser.choices.keys():
|
|
@@ -292,7 +302,7 @@ class CompletionFinder(object):
|
|
|
292
302
|
for action in parser._get_subactions():
|
|
293
303
|
for alias in aliases_by_parser[parser.choices[action.dest]]:
|
|
294
304
|
if alias.startswith(cword_prefix):
|
|
295
|
-
self._display_completions[alias] = action
|
|
305
|
+
self._display_completions[alias] = self._get_action_help(action)
|
|
296
306
|
|
|
297
307
|
completions = [subcmd for subcmd in parser.choices.keys() if subcmd.startswith(cword_prefix)]
|
|
298
308
|
return completions
|
|
@@ -313,7 +323,7 @@ class CompletionFinder(object):
|
|
|
313
323
|
if action.option_strings:
|
|
314
324
|
for option_string in action.option_strings:
|
|
315
325
|
if option_string.startswith(cword_prefix):
|
|
316
|
-
self._display_completions[option_string] = action
|
|
326
|
+
self._display_completions[option_string] = self._get_action_help(action)
|
|
317
327
|
|
|
318
328
|
option_completions = []
|
|
319
329
|
for action in parser._actions:
|
|
@@ -405,7 +415,7 @@ class CompletionFinder(object):
|
|
|
405
415
|
if self.validator(completion, cword_prefix):
|
|
406
416
|
completions.append(completion)
|
|
407
417
|
if isinstance(completer, ChoicesCompleter):
|
|
408
|
-
self._display_completions[completion] = active_action
|
|
418
|
+
self._display_completions[completion] = self._get_action_help(active_action)
|
|
409
419
|
else:
|
|
410
420
|
self._display_completions[completion] = ""
|
|
411
421
|
else:
|
|
@@ -517,7 +527,7 @@ class CompletionFinder(object):
|
|
|
517
527
|
# (extended to characters other than the colon).
|
|
518
528
|
if last_wordbreak_pos is not None:
|
|
519
529
|
completions = [c[last_wordbreak_pos + 1 :] for c in completions]
|
|
520
|
-
special_chars += "()
|
|
530
|
+
special_chars += "();<>|&!`$*?[]{} \t\n\"'"
|
|
521
531
|
elif cword_prequote == '"':
|
|
522
532
|
special_chars += '"`$!'
|
|
523
533
|
|
|
@@ -19,7 +19,13 @@ from argparse import (
|
|
|
19
19
|
_SubParsersAction,
|
|
20
20
|
)
|
|
21
21
|
from gettext import gettext
|
|
22
|
-
from typing import Dict, List, Set, Tuple
|
|
22
|
+
from typing import Dict, List, Optional, Set, Tuple, Union, cast
|
|
23
|
+
|
|
24
|
+
_OptionTuple = Union[
|
|
25
|
+
Tuple[Optional[Action], str, Optional[str]],
|
|
26
|
+
Tuple[Optional[Action], str, Optional[str], Optional[str]],
|
|
27
|
+
]
|
|
28
|
+
_OptionTupleEntry = Union[_OptionTuple, List[_OptionTuple]]
|
|
23
29
|
|
|
24
30
|
_num_consumed_args: Dict[Action, int] = {}
|
|
25
31
|
|
|
@@ -97,7 +103,7 @@ class IntrospectiveArgumentParser(ArgumentParser):
|
|
|
97
103
|
# find all option indices, and determine the arg_string_pattern
|
|
98
104
|
# which has an 'O' if there is an option at an index,
|
|
99
105
|
# an 'A' if there is an argument, or a '-' if there is a '--'
|
|
100
|
-
option_string_indices = {}
|
|
106
|
+
option_string_indices: Dict[int, _OptionTupleEntry] = {}
|
|
101
107
|
arg_string_pattern_parts = []
|
|
102
108
|
arg_strings_iter = iter(arg_strings)
|
|
103
109
|
for i, arg_string in enumerate(arg_strings_iter):
|
|
@@ -114,7 +120,7 @@ class IntrospectiveArgumentParser(ArgumentParser):
|
|
|
114
120
|
if option_tuple is None:
|
|
115
121
|
pattern = 'A'
|
|
116
122
|
else:
|
|
117
|
-
option_string_indices[i] = option_tuple
|
|
123
|
+
option_string_indices[i] = cast(_OptionTupleEntry, option_tuple)
|
|
118
124
|
pattern = 'O'
|
|
119
125
|
arg_string_pattern_parts.append(pattern)
|
|
120
126
|
|
|
@@ -161,9 +167,11 @@ class IntrospectiveArgumentParser(ArgumentParser):
|
|
|
161
167
|
# function to convert arg_strings into an optional action
|
|
162
168
|
def consume_optional(start_index):
|
|
163
169
|
# get the optional identified at this index
|
|
164
|
-
|
|
165
|
-
if isinstance(
|
|
166
|
-
option_tuple =
|
|
170
|
+
raw_option_tuple = option_string_indices[start_index]
|
|
171
|
+
if isinstance(raw_option_tuple, list): # Python 3.12.7+
|
|
172
|
+
option_tuple = raw_option_tuple[0]
|
|
173
|
+
else:
|
|
174
|
+
option_tuple = raw_option_tuple
|
|
167
175
|
if len(option_tuple) == 3:
|
|
168
176
|
action, option_string, explicit_arg = option_tuple
|
|
169
177
|
else: # Python 3.11.9+, 3.12.3+, 3.13+
|
|
@@ -241,8 +249,8 @@ class IntrospectiveArgumentParser(ArgumentParser):
|
|
|
241
249
|
# add the Optional to the list and return the index at which
|
|
242
250
|
# the Optional's string args stopped
|
|
243
251
|
assert action_tuples
|
|
244
|
-
for
|
|
245
|
-
take_action(
|
|
252
|
+
for optional_action, args, option_string in action_tuples:
|
|
253
|
+
take_action(optional_action, args, option_string)
|
|
246
254
|
return stop
|
|
247
255
|
|
|
248
256
|
# the list of Positionals left to be parsed; this is modified
|
{argcomplete-3.6.2 → argcomplete-3.7.0}/argcomplete/scripts/activate_global_python_argcomplete.py
RENAMED
|
@@ -79,7 +79,9 @@ def install_to_destination(dest):
|
|
|
79
79
|
try:
|
|
80
80
|
os.makedirs(destdir, exist_ok=True)
|
|
81
81
|
except Exception as e:
|
|
82
|
-
parser.error(
|
|
82
|
+
parser.error(
|
|
83
|
+
f"path {destdir} does not exist and could not be created: {e}. Please run this command using sudo, or see --help for more options."
|
|
84
|
+
)
|
|
83
85
|
try:
|
|
84
86
|
print(f"Installing {activator} to {dest}...", file=sys.stderr)
|
|
85
87
|
shutil.copy(activator, dest)
|
|
@@ -47,7 +47,7 @@ _python_argcomplete%(function_suffix)s() {
|
|
|
47
47
|
if is-at-least 5.8; then
|
|
48
48
|
nosort=(-o nosort)
|
|
49
49
|
fi
|
|
50
|
-
if [[ "${completions-}" =~ ([
|
|
50
|
+
if [[ "${completions-}" =~ ([^\\\\]): && "${match[1]}" =~ [=/:] ]]; then
|
|
51
51
|
nospace=(-S '')
|
|
52
52
|
fi
|
|
53
53
|
_describe "${words[1]}" completions "${nosort[@]}" "${nospace[@]}"
|
|
@@ -94,14 +94,14 @@ complete "%(executable)s" 'p@*@`python-argcomplete-tcsh "%(argcomplete_script)s"
|
|
|
94
94
|
|
|
95
95
|
fishcode = r"""
|
|
96
96
|
function __fish_%(function_name)s_complete
|
|
97
|
-
set -
|
|
98
|
-
set -
|
|
99
|
-
set -
|
|
100
|
-
set -
|
|
101
|
-
set -
|
|
102
|
-
set -
|
|
103
|
-
set -
|
|
104
|
-
set -
|
|
97
|
+
set -lx _ARGCOMPLETE 1
|
|
98
|
+
set -lx _ARGCOMPLETE_DFS \t
|
|
99
|
+
set -lx _ARGCOMPLETE_IFS \n
|
|
100
|
+
set -lx _ARGCOMPLETE_SUPPRESS_SPACE 1
|
|
101
|
+
set -lx _ARGCOMPLETE_SHELL fish
|
|
102
|
+
set -lx COMP_LINE (commandline -p)
|
|
103
|
+
set -lx COMP_POINT (string length (commandline -cp))
|
|
104
|
+
set -lx COMP_TYPE
|
|
105
105
|
if set -q _ARC_DEBUG
|
|
106
106
|
%(argcomplete_script)s 8>&1 9>&2 1>&9 2>&1
|
|
107
107
|
else
|
|
@@ -16,6 +16,14 @@ or create new completion file, e.g::
|
|
|
16
16
|
|
|
17
17
|
register-python-argcomplete --shell fish my-awesome-script > ~/.config/fish/completions/my-awesome-script.fish
|
|
18
18
|
|
|
19
|
+
If the script is called using a path, such as ``./my-awesome-script``, it must be registered using the absolute path to the script. ::
|
|
20
|
+
|
|
21
|
+
register-python-argcomplete --shell fish $(realpath ./my-awesome-script) > ~/.config/fish/completions/my-awesome-script.fish
|
|
22
|
+
|
|
23
|
+
The completions using a path will not be automatically loaded since the command name does not match the file name. To load the completions, ``source`` them. ::
|
|
24
|
+
|
|
25
|
+
source ~/.config/fish/completions/my-awesome-script.fish
|
|
26
|
+
|
|
19
27
|
Completion Description For Fish
|
|
20
28
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
21
29
|
By default help string is added as completion description.
|
|
@@ -15,12 +15,12 @@ classifiers = [
|
|
|
15
15
|
"Operating System :: POSIX",
|
|
16
16
|
"Programming Language :: Python",
|
|
17
17
|
"Programming Language :: Python :: 3",
|
|
18
|
-
"Programming Language :: Python :: 3.8",
|
|
19
18
|
"Programming Language :: Python :: 3.9",
|
|
20
19
|
"Programming Language :: Python :: 3.10",
|
|
21
20
|
"Programming Language :: Python :: 3.11",
|
|
22
21
|
"Programming Language :: Python :: 3.12",
|
|
23
22
|
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Programming Language :: Python :: 3.14",
|
|
24
24
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
25
25
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
26
26
|
"Development Status :: 5 - Production/Stable",
|
|
@@ -32,7 +32,6 @@ classifiers = [
|
|
|
32
32
|
|
|
33
33
|
[project.scripts]
|
|
34
34
|
activate-global-python-argcomplete = "argcomplete.scripts.activate_global_python_argcomplete:main"
|
|
35
|
-
python-argcomplete-check-easy-install-script = "argcomplete.scripts.python_argcomplete_check_easy_install_script:main"
|
|
36
35
|
register-python-argcomplete = "argcomplete.scripts.register_python_argcomplete:main"
|
|
37
36
|
|
|
38
37
|
[project.optional-dependencies]
|
|
@@ -356,6 +356,15 @@ class TestArgcomplete(unittest.TestCase):
|
|
|
356
356
|
fp.write("test")
|
|
357
357
|
self.assertEqual(set(fc("a")), set(["abcdefж/", "abcaha/", "abcxyz"]))
|
|
358
358
|
|
|
359
|
+
def test_file_completion_quotes_prefix(self):
|
|
360
|
+
with TempDir(prefix="test_dir_fc_quote", dir="."):
|
|
361
|
+
marker = "should_not_exist"
|
|
362
|
+
prefix = "'; touch {0}; echo '".format(marker)
|
|
363
|
+
|
|
364
|
+
self.assertFalse(os.path.exists(marker))
|
|
365
|
+
self.assertEqual(FilesCompleter()(prefix), [])
|
|
366
|
+
self.assertFalse(os.path.exists(marker))
|
|
367
|
+
|
|
359
368
|
def test_filescompleter_filetype_integration(self):
|
|
360
369
|
def make_parser():
|
|
361
370
|
parser = ArgumentParser()
|
|
@@ -828,6 +837,7 @@ class TestArgcomplete(unittest.TestCase):
|
|
|
828
837
|
parser.add_argument("-1", choices=["bar<$>baz"])
|
|
829
838
|
parser.add_argument("-2", choices=[r"\* "])
|
|
830
839
|
parser.add_argument("-3", choices=["\"'"])
|
|
840
|
+
parser.add_argument("-4", choices=["data?", "file[1]", "{x,--flag}"])
|
|
831
841
|
return parser
|
|
832
842
|
|
|
833
843
|
self.assertEqual(set(self.run_completer(make_parser(), "prog -1 ")), {r"bar\<\$\>baz "})
|
|
@@ -835,6 +845,10 @@ class TestArgcomplete(unittest.TestCase):
|
|
|
835
845
|
self.assertEqual(set(self.run_completer(make_parser(), "prog -3 ")), {r"\"\' "})
|
|
836
846
|
self.assertEqual(set(self.run_completer(make_parser(), 'prog -3 "')), {r"\"'"})
|
|
837
847
|
self.assertEqual(set(self.run_completer(make_parser(), "prog -3 '")), {"\"'\\''"})
|
|
848
|
+
self.assertEqual(
|
|
849
|
+
set(self.run_completer(make_parser(), "prog -4 ")),
|
|
850
|
+
{r"data\?", r"file\[1\]", r"\{x,--flag\}"},
|
|
851
|
+
)
|
|
838
852
|
|
|
839
853
|
self.assertEqual(set(self.run_completer(make_parser(), "prog -1 ", shell="tcsh")), {"bar<$>baz "})
|
|
840
854
|
# The trailing space won't actually work correctly in tcsh.
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
# Copyright 2012-2023, Andrey Kislyuk and argcomplete contributors.
|
|
4
|
-
# Licensed under the Apache License. See https://github.com/kislyuk/argcomplete for more info.
|
|
5
|
-
|
|
6
|
-
"""
|
|
7
|
-
This script is part of the Python argcomplete package (https://github.com/kislyuk/argcomplete).
|
|
8
|
-
It is used to check if an EASY-INSTALL-SCRIPT wrapper redirects to a script that contains the string
|
|
9
|
-
"PYTHON_ARGCOMPLETE_OK". If you have enabled global completion in argcomplete, the completion hook will run it every
|
|
10
|
-
time you press <TAB> in your shell.
|
|
11
|
-
|
|
12
|
-
Usage:
|
|
13
|
-
python-argcomplete-check-easy-install-script <input executable file>
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
import sys
|
|
17
|
-
|
|
18
|
-
# PEP 366
|
|
19
|
-
__package__ = "argcomplete.scripts"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def main():
|
|
23
|
-
if len(sys.argv) != 2:
|
|
24
|
-
sys.exit(__doc__)
|
|
25
|
-
|
|
26
|
-
sys.tracebacklimit = 0
|
|
27
|
-
|
|
28
|
-
with open(sys.argv[1]) as fh:
|
|
29
|
-
line1, head = fh.read(1024).split("\n", 1)[:2]
|
|
30
|
-
if line1.startswith("#") and ("py" in line1 or "Py" in line1):
|
|
31
|
-
import re
|
|
32
|
-
|
|
33
|
-
lines = head.split("\n", 12)
|
|
34
|
-
for line in lines:
|
|
35
|
-
if line.startswith("# EASY-INSTALL-SCRIPT"):
|
|
36
|
-
import pkg_resources # type: ignore
|
|
37
|
-
|
|
38
|
-
re_match = re.match("# EASY-INSTALL-SCRIPT: '(.+)','(.+)'", line)
|
|
39
|
-
assert re_match is not None
|
|
40
|
-
dist, script = re_match.groups()
|
|
41
|
-
if "PYTHON_ARGCOMPLETE_OK" in pkg_resources.get_distribution(dist).get_metadata(
|
|
42
|
-
"scripts/" + script
|
|
43
|
-
):
|
|
44
|
-
return 0
|
|
45
|
-
elif line.startswith("# EASY-INSTALL-ENTRY-SCRIPT"):
|
|
46
|
-
re_match = re.match("# EASY-INSTALL-ENTRY-SCRIPT: '(.+)','(.+)','(.+)'", line)
|
|
47
|
-
assert re_match is not None
|
|
48
|
-
dist, group, name = re_match.groups()
|
|
49
|
-
import pkgutil
|
|
50
|
-
|
|
51
|
-
import pkg_resources # type: ignore
|
|
52
|
-
|
|
53
|
-
entry_point_info = pkg_resources.get_distribution(dist).get_entry_info(group, name)
|
|
54
|
-
assert entry_point_info is not None
|
|
55
|
-
module_name = entry_point_info.module_name
|
|
56
|
-
with open(pkgutil.get_loader(module_name).get_filename()) as mod_fh: # type: ignore
|
|
57
|
-
if "PYTHON_ARGCOMPLETE_OK" in mod_fh.read(1024):
|
|
58
|
-
return 0
|
|
59
|
-
elif line.startswith("# EASY-INSTALL-DEV-SCRIPT"):
|
|
60
|
-
for line2 in lines:
|
|
61
|
-
if line2.startswith("__file__"):
|
|
62
|
-
re_match = re.match("__file__ = '(.+)'", line2)
|
|
63
|
-
assert re_match is not None
|
|
64
|
-
filename = re_match.group(1)
|
|
65
|
-
with open(filename) as mod_fh:
|
|
66
|
-
if "PYTHON_ARGCOMPLETE_OK" in mod_fh.read(1024):
|
|
67
|
-
return 0
|
|
68
|
-
elif line.startswith("# PBR Generated"):
|
|
69
|
-
re_match = re.search("from (.*) import", head)
|
|
70
|
-
assert re_match is not None
|
|
71
|
-
module = re_match.groups()[0]
|
|
72
|
-
import pkgutil
|
|
73
|
-
|
|
74
|
-
import pkg_resources # type: ignore
|
|
75
|
-
|
|
76
|
-
with open(pkgutil.get_loader(module).get_filename()) as mod_fh: # type: ignore
|
|
77
|
-
if "PYTHON_ARGCOMPLETE_OK" in mod_fh.read(1024):
|
|
78
|
-
return 0
|
|
79
|
-
|
|
80
|
-
return 1
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if __name__ == "__main__":
|
|
84
|
-
sys.exit(main())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|