Skip to content

Commit 3002441

Browse files
authored
bump version, merge pull request #10 from iterative/devel
2 parents 94af05f + 52ddf91 commit 3002441

File tree

6 files changed

+95
-82
lines changed

6 files changed

+95
-82
lines changed

.github/workflows/comment-bot.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ jobs:
2424
})
2525
- name: Tag Commit
2626
run: |
27-
git config user.name tag-bot
28-
git config user.email [email protected]
29-
git tag $(echo "$BODY" | awk '{print $2" "$3}')
30-
git push --tags
27+
git clone https://${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY} repo
28+
git -C repo tag $(echo "$BODY" | awk '{print $2" "$3}')
29+
git -C repo push --tags
30+
rm -rf repo
3131
env:
3232
BODY: ${{ github.event.comment.body }}
33+
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
3334
- name: React Success
3435
uses: actions/github-script@v2
3536
with:

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ jobs:
4444
run: |
4545
echo "::set-output name=asset_path::$(ls dist/*.whl)"
4646
echo "::set-output name=asset_name::$(basename dist/*.whl)"
47-
git fetch --tags
47+
git fetch --unshallow
4848
changes="$(git log --format='format:%d %B %N' $(git tag --sort=v:refname | tail -n2 | xargs | awk '{print $1".."$2}'))"
4949
changes="${changes//'%'/'%25'}"
5050
changes="${changes//$'\n'/'%0A'}"

README.rst

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -223,28 +223,26 @@ Add direct support to scripts for a little more configurability:
223223
def get_main_parser():
224224
parser = argparse.ArgumentParser(prog="pathcomplete")
225225
parser.add_argument(
226-
"-s", "--print-completion-shell", choices=["bash", "zsh"]
227-
)
228-
parser.add_argument(
229-
"--file",
230-
choices=shtab.Optional.FILE, # file tab completion, can be blank
231-
)
232-
parser.add_argument(
233-
"--dir",
234-
choices=shtab.Required.DIRECTORY, # directory tab completion
235-
default=".",
226+
"-s",
227+
"--print-completion-shell",
228+
choices=["bash", "zsh"],
229+
help="prints completion script",
236230
)
231+
# file & directory tab complete
232+
parser.add_argument("file", nargs="?").complete = shtab.FILE
233+
parser.add_argument("--dir", default=".").complete = shtab.DIRECTORY
237234
return parser
238235
239236
if __name__ == "__main__":
240237
parser = get_main_parser()
241238
args = parser.parse_args()
242-
print("received --file='%s' --dir='%s'" % (args.file, args.dir))
243239
244240
# completion magic
245241
shell = args.print_completion_shell
246242
if shell:
247243
print(shtab.complete(parser, shell=shell))
244+
else:
245+
print("received <file>=%r --dir=%r" % (args.file, args.dir))
248246
249247
docopt
250248
~~~~~~

examples/customcomplete.py

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88

99
import shtab # for completion magic
1010

11-
CHOICE_FUNCTIONS = {
12-
"bash": {"*.txt": "_shtab_greeter_compgen_TXTFiles"},
13-
"zsh": {"*.txt": "_files -g '(*.txt|*.TXT)'"},
11+
TXT_FILE = {
12+
"bash": "_shtab_greeter_compgen_TXTFiles",
13+
"zsh": "_files -g '(*.txt|*.TXT)'",
1414
}
1515
PREAMBLE = {
1616
"bash": """
@@ -25,27 +25,26 @@
2525
}
2626

2727

28-
class Optional(shtab.Required):
29-
TXT_FILE = [shtab.Choice("*.txt", required=False)]
30-
31-
32-
class Required(shtab.Required):
33-
TXT_FILE = [shtab.Choice("*.txt", required=True)]
34-
35-
3628
def get_main_parser():
3729
parser = argparse.ArgumentParser(prog="customcomplete")
3830
parser.add_argument(
39-
"-s", "--print-completion-shell", choices=["bash", "zsh"]
31+
"-s",
32+
"--print-completion-shell",
33+
choices=["bash", "zsh"],
34+
help="prints completion script",
4035
)
36+
# `*.txt` file tab completion
37+
parser.add_argument("input_txt", nargs="?").complete = TXT_FILE
38+
# file tab completion builtin shortcut
39+
parser.add_argument("-i", "--input-file").complete = shtab.FILE
4140
parser.add_argument(
4241
"-o",
43-
"--output-txt",
44-
choices=Optional.TXT_FILE, # *.txt file tab completion, can be blank
45-
)
46-
parser.add_argument(
47-
"input_txt", choices=Required.TXT_FILE, # cannot be blank
48-
)
42+
"--output-name",
43+
help=(
44+
"output file name. Completes directory names to avoid users"
45+
" accidentally overwriting existing files."
46+
),
47+
).complete = shtab.DIRECTORY # directory tab completion builtin shortcut
4948
return parser
5049

5150

@@ -56,15 +55,10 @@ def get_main_parser():
5655
# completion magic
5756
shell = args.print_completion_shell
5857
if shell:
59-
script = shtab.complete(
60-
parser,
61-
shell=shell,
62-
preamble=PREAMBLE[shell],
63-
choice_functions=CHOICE_FUNCTIONS[shell],
64-
)
58+
script = shtab.complete(parser, shell=shell, preamble=PREAMBLE)
6559
print(script)
6660
else:
6761
print(
68-
"received input_txt='%s' --output-txt='%s'"
69-
% (args.input_txt, args.output_txt)
62+
"received <input_txt>=%r --output-dir=%r --output-name=%r"
63+
% (args.input_txt, args.output_dir, args.output_name)
7064
)

examples/pathcomplete.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
#!/usr/bin/env python
22
"""
33
`argparse`-based CLI app using
4-
`add_argument(choices=shtab.(Optional|Required).(FILE|DIR)`
5-
for file/directory completion.
4+
`add_argument().complete = shtab.(FILE|DIR)` for file/dir tab completion.
65
76
See `customcomplete.py` for a more advanced version.
87
"""
@@ -14,17 +13,14 @@
1413
def get_main_parser():
1514
parser = argparse.ArgumentParser(prog="pathcomplete")
1615
parser.add_argument(
17-
"-s", "--print-completion-shell", choices=["bash", "zsh"]
18-
)
19-
parser.add_argument(
20-
"--file",
21-
choices=shtab.Optional.FILE, # file tab completion, can be blank
22-
)
23-
parser.add_argument(
24-
"--dir",
25-
choices=shtab.Required.DIRECTORY, # directory tab completion
26-
default=".",
16+
"-s",
17+
"--print-completion-shell",
18+
choices=["bash", "zsh"],
19+
help="prints completion script",
2720
)
21+
# file & directory tab complete
22+
parser.add_argument("file", nargs="?").complete = shtab.FILE
23+
parser.add_argument("--dir", default=".").complete = shtab.DIRECTORY
2824
return parser
2925

3026

@@ -37,4 +33,4 @@ def get_main_parser():
3733
if shell:
3834
print(shtab.complete(parser, shell=shell))
3935
else:
40-
print("received --file='%s' --dir='%s'" % (args.file, args.dir))
36+
print("received <file>=%r --dir=%r" % (args.file, args.dir))

shtab/__init__.py

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,12 @@ def get_version_dist(name=__name__):
4242
__all__ = ["Optional", "Required", "Choice", "complete"]
4343
log = logging.getLogger(__name__)
4444

45-
CHOICE_FUNCTIONS_BASH = {
46-
"file": "_shtab_compgen_files",
47-
"directory": "_shtab_compgen_dirs",
48-
}
49-
CHOICE_FUNCTIONS_ZSH = {
50-
"file": "_files",
51-
"directory": "_files -/",
45+
CHOICE_FUNCTIONS = {
46+
"file": {"bash": "_shtab_compgen_files", "zsh": "_files"},
47+
"directory": {"bash": "_shtab_compgen_dirs", "zsh": "_files -/"},
5248
}
49+
FILE = CHOICE_FUNCTIONS["file"]
50+
DIRECTORY = DIR = CHOICE_FUNCTIONS["directory"]
5351
FLAG_OPTION = (
5452
_StoreConstAction,
5553
_HelpAction,
@@ -109,25 +107,21 @@ class Required(object):
109107
DIR = DIRECTORY = [Choice("directory", True)]
110108

111109

110+
def complete2pattern(opt_complete, shell, choice_type2fn):
111+
return (
112+
opt_complete.get(shell, "")
113+
if isinstance(opt_complete, dict)
114+
else choice_type2fn[opt_complete]
115+
)
116+
117+
112118
def replace_format(string, **fmt):
113119
"""Similar to `string.format(**fmt)` but ignores unknown `{key}`s."""
114120
for k, v in fmt.items():
115121
string = string.replace("{" + k + "}", v)
116122
return string
117123

118124

119-
def get_optional_actions(parser):
120-
"""Flattened list of all `parser`'s optional actions."""
121-
return sum(
122-
(
123-
opt.option_strings
124-
for opt in parser._get_optional_actions()
125-
if opt.help != SUPPRESS
126-
),
127-
[],
128-
)
129-
130-
131125
def get_bash_commands(root_parser, root_prefix, choice_functions=None):
132126
"""
133127
Recursive subcommand parser traversal, printing bash helper syntax.
@@ -145,13 +139,24 @@ def get_bash_commands(root_parser, root_prefix, choice_functions=None):
145139
# `add_argument('subcommand', choices=shtab.Required.FILE)`)
146140
_{root_parser.prog}_{subcommand}_COMPGEN=_shtab_compgen_files
147141
"""
148-
choice_type2fn = dict(CHOICE_FUNCTIONS_BASH)
142+
choice_type2fn = {k: v["bash"] for k, v in CHOICE_FUNCTIONS.items()}
149143
if choice_functions:
150144
choice_type2fn.update(choice_functions)
151145

152146
fd = io.StringIO()
153147
root_options = []
154148

149+
def get_optional_actions(parser):
150+
"""Flattened list of all `parser`'s optional actions."""
151+
return sum(
152+
(
153+
opt.option_strings
154+
for opt in parser._get_optional_actions()
155+
if opt.help != SUPPRESS
156+
),
157+
[],
158+
)
159+
155160
def recurse(parser, prefix):
156161
positionals = parser._get_positional_actions()
157162
commands = []
@@ -176,6 +181,16 @@ def recurse(parser, prefix):
176181
for sub in positionals:
177182
if sub.choices:
178183
log.debug("choices:{}:{}".format(prefix, sorted(sub.choices)))
184+
if hasattr(sub, "complete"):
185+
print(
186+
"{}_COMPGEN={}".format(
187+
prefix,
188+
complete2pattern(
189+
sub.complete, "bash", choice_type2fn
190+
),
191+
),
192+
file=fd,
193+
)
179194
for cmd in sorted(sub.choices):
180195
if isinstance(cmd, Choice):
181196
log.debug(
@@ -342,7 +357,7 @@ def complete_zsh(parser, root_prefix=None, preamble="", choice_functions=None):
342357
root_arguments = []
343358
subcommands = {} # {cmd: {"help": help, "arguments": [arguments]}}
344359

345-
choice_type2fn = dict(CHOICE_FUNCTIONS_ZSH)
360+
choice_type2fn = {k: v["zsh"] for k, v in CHOICE_FUNCTIONS.items()}
346361
if choice_functions:
347362
choice_type2fn.update(choice_functions)
348363

@@ -368,7 +383,9 @@ def format_optional(opt):
368383
),
369384
help=escape_zsh(opt.help or ""),
370385
dest=opt.dest,
371-
pattern=(
386+
pattern=complete2pattern(opt.complete, "zsh", choice_type2fn)
387+
if hasattr(opt, "complete")
388+
else (
372389
choice_type2fn[opt.choices[0].type]
373390
if isinstance(opt.choices[0], Choice)
374391
else "({})".format(" ".join(opt.choices))
@@ -380,10 +397,12 @@ def format_optional(opt):
380397
)
381398

382399
def format_positional(opt):
383-
return '"{nargs}:{help}:{choices}"'.format(
400+
return '"{nargs}:{help}:{pattern}"'.format(
384401
nargs={"+": "*", "*": "*"}.get(opt.nargs, ""),
385402
help=escape_zsh((opt.help or opt.dest).strip().split("\n")[0]),
386-
choices=(
403+
pattern=complete2pattern(opt.complete, "zsh", choice_type2fn)
404+
if hasattr(opt, "complete")
405+
else (
387406
choice_type2fn[opt.choices[0].type]
388407
if isinstance(opt.choices[0], Choice)
389408
else "({})".format(" ".join(opt.choices))
@@ -529,10 +548,15 @@ def complete(
529548
shell : str (bash/zsh)
530549
root_prefix : str, prefix for shell functions to avoid clashes
531550
(default: "_{parser.prog}")
532-
preamble : str, prepended to generated script
533-
choice_functions : dict, maps custom `shtab.Choice.type`s to
534-
completion functions (possibly defined in `preamble`)
551+
preamble : dict, mapping shell to text to prepend to generated script
552+
(e.g. `{"bash": "_myprog_custom_function(){ echo hello }"}`)
553+
choice_functions : deprecated.
554+
555+
N.B. `parser.add_argument().complete = ...` can be used to define custom
556+
completions (e.g. filenames). See <../examples/pathcomplete.py>.
535557
"""
558+
if isinstance(preamble, dict):
559+
preamble = preamble.get(shell, "")
536560
if shell == "bash":
537561
return complete_bash(
538562
parser,

0 commit comments

Comments
 (0)