Skip to content

Commit

Permalink
bump version, merge pull request #10 from iterative/devel
Browse files Browse the repository at this point in the history
  • Loading branch information
casperdcl authored Jul 1, 2020
2 parents 94af05f + 52ddf91 commit 3002441
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 82 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/comment-bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ jobs:
})
- name: Tag Commit
run: |
git config user.name tag-bot
git config user.email [email protected]
git tag $(echo "$BODY" | awk '{print $2" "$3}')
git push --tags
git clone https://${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY} repo
git -C repo tag $(echo "$BODY" | awk '{print $2" "$3}')
git -C repo push --tags
rm -rf repo
env:
BODY: ${{ github.event.comment.body }}
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
- name: React Success
uses: actions/github-script@v2
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
run: |
echo "::set-output name=asset_path::$(ls dist/*.whl)"
echo "::set-output name=asset_name::$(basename dist/*.whl)"
git fetch --tags
git fetch --unshallow
changes="$(git log --format='format:%d %B %N' $(git tag --sort=v:refname | tail -n2 | xargs | awk '{print $1".."$2}'))"
changes="${changes//'%'/'%25'}"
changes="${changes//$'\n'/'%0A'}"
Expand Down
20 changes: 9 additions & 11 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -223,28 +223,26 @@ Add direct support to scripts for a little more configurability:
def get_main_parser():
parser = argparse.ArgumentParser(prog="pathcomplete")
parser.add_argument(
"-s", "--print-completion-shell", choices=["bash", "zsh"]
)
parser.add_argument(
"--file",
choices=shtab.Optional.FILE, # file tab completion, can be blank
)
parser.add_argument(
"--dir",
choices=shtab.Required.DIRECTORY, # directory tab completion
default=".",
"-s",
"--print-completion-shell",
choices=["bash", "zsh"],
help="prints completion script",
)
# file & directory tab complete
parser.add_argument("file", nargs="?").complete = shtab.FILE
parser.add_argument("--dir", default=".").complete = shtab.DIRECTORY
return parser
if __name__ == "__main__":
parser = get_main_parser()
args = parser.parse_args()
print("received --file='%s' --dir='%s'" % (args.file, args.dir))
# completion magic
shell = args.print_completion_shell
if shell:
print(shtab.complete(parser, shell=shell))
else:
print("received <file>=%r --dir=%r" % (args.file, args.dir))
docopt
~~~~~~
Expand Down
46 changes: 20 additions & 26 deletions examples/customcomplete.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

import shtab # for completion magic

CHOICE_FUNCTIONS = {
"bash": {"*.txt": "_shtab_greeter_compgen_TXTFiles"},
"zsh": {"*.txt": "_files -g '(*.txt|*.TXT)'"},
TXT_FILE = {
"bash": "_shtab_greeter_compgen_TXTFiles",
"zsh": "_files -g '(*.txt|*.TXT)'",
}
PREAMBLE = {
"bash": """
Expand All @@ -25,27 +25,26 @@
}


class Optional(shtab.Required):
TXT_FILE = [shtab.Choice("*.txt", required=False)]


class Required(shtab.Required):
TXT_FILE = [shtab.Choice("*.txt", required=True)]


def get_main_parser():
parser = argparse.ArgumentParser(prog="customcomplete")
parser.add_argument(
"-s", "--print-completion-shell", choices=["bash", "zsh"]
"-s",
"--print-completion-shell",
choices=["bash", "zsh"],
help="prints completion script",
)
# `*.txt` file tab completion
parser.add_argument("input_txt", nargs="?").complete = TXT_FILE
# file tab completion builtin shortcut
parser.add_argument("-i", "--input-file").complete = shtab.FILE
parser.add_argument(
"-o",
"--output-txt",
choices=Optional.TXT_FILE, # *.txt file tab completion, can be blank
)
parser.add_argument(
"input_txt", choices=Required.TXT_FILE, # cannot be blank
)
"--output-name",
help=(
"output file name. Completes directory names to avoid users"
" accidentally overwriting existing files."
),
).complete = shtab.DIRECTORY # directory tab completion builtin shortcut
return parser


Expand All @@ -56,15 +55,10 @@ def get_main_parser():
# completion magic
shell = args.print_completion_shell
if shell:
script = shtab.complete(
parser,
shell=shell,
preamble=PREAMBLE[shell],
choice_functions=CHOICE_FUNCTIONS[shell],
)
script = shtab.complete(parser, shell=shell, preamble=PREAMBLE)
print(script)
else:
print(
"received input_txt='%s' --output-txt='%s'"
% (args.input_txt, args.output_txt)
"received <input_txt>=%r --output-dir=%r --output-name=%r"
% (args.input_txt, args.output_dir, args.output_name)
)
22 changes: 9 additions & 13 deletions examples/pathcomplete.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#!/usr/bin/env python
"""
`argparse`-based CLI app using
`add_argument(choices=shtab.(Optional|Required).(FILE|DIR)`
for file/directory completion.
`add_argument().complete = shtab.(FILE|DIR)` for file/dir tab completion.
See `customcomplete.py` for a more advanced version.
"""
Expand All @@ -14,17 +13,14 @@
def get_main_parser():
parser = argparse.ArgumentParser(prog="pathcomplete")
parser.add_argument(
"-s", "--print-completion-shell", choices=["bash", "zsh"]
)
parser.add_argument(
"--file",
choices=shtab.Optional.FILE, # file tab completion, can be blank
)
parser.add_argument(
"--dir",
choices=shtab.Required.DIRECTORY, # directory tab completion
default=".",
"-s",
"--print-completion-shell",
choices=["bash", "zsh"],
help="prints completion script",
)
# file & directory tab complete
parser.add_argument("file", nargs="?").complete = shtab.FILE
parser.add_argument("--dir", default=".").complete = shtab.DIRECTORY
return parser


Expand All @@ -37,4 +33,4 @@ def get_main_parser():
if shell:
print(shtab.complete(parser, shell=shell))
else:
print("received --file='%s' --dir='%s'" % (args.file, args.dir))
print("received <file>=%r --dir=%r" % (args.file, args.dir))
78 changes: 51 additions & 27 deletions shtab/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,12 @@ def get_version_dist(name=__name__):
__all__ = ["Optional", "Required", "Choice", "complete"]
log = logging.getLogger(__name__)

CHOICE_FUNCTIONS_BASH = {
"file": "_shtab_compgen_files",
"directory": "_shtab_compgen_dirs",
}
CHOICE_FUNCTIONS_ZSH = {
"file": "_files",
"directory": "_files -/",
CHOICE_FUNCTIONS = {
"file": {"bash": "_shtab_compgen_files", "zsh": "_files"},
"directory": {"bash": "_shtab_compgen_dirs", "zsh": "_files -/"},
}
FILE = CHOICE_FUNCTIONS["file"]
DIRECTORY = DIR = CHOICE_FUNCTIONS["directory"]
FLAG_OPTION = (
_StoreConstAction,
_HelpAction,
Expand Down Expand Up @@ -109,25 +107,21 @@ class Required(object):
DIR = DIRECTORY = [Choice("directory", True)]


def complete2pattern(opt_complete, shell, choice_type2fn):
return (
opt_complete.get(shell, "")
if isinstance(opt_complete, dict)
else choice_type2fn[opt_complete]
)


def replace_format(string, **fmt):
"""Similar to `string.format(**fmt)` but ignores unknown `{key}`s."""
for k, v in fmt.items():
string = string.replace("{" + k + "}", v)
return string


def get_optional_actions(parser):
"""Flattened list of all `parser`'s optional actions."""
return sum(
(
opt.option_strings
for opt in parser._get_optional_actions()
if opt.help != SUPPRESS
),
[],
)


def get_bash_commands(root_parser, root_prefix, choice_functions=None):
"""
Recursive subcommand parser traversal, printing bash helper syntax.
Expand All @@ -145,13 +139,24 @@ def get_bash_commands(root_parser, root_prefix, choice_functions=None):
# `add_argument('subcommand', choices=shtab.Required.FILE)`)
_{root_parser.prog}_{subcommand}_COMPGEN=_shtab_compgen_files
"""
choice_type2fn = dict(CHOICE_FUNCTIONS_BASH)
choice_type2fn = {k: v["bash"] for k, v in CHOICE_FUNCTIONS.items()}
if choice_functions:
choice_type2fn.update(choice_functions)

fd = io.StringIO()
root_options = []

def get_optional_actions(parser):
"""Flattened list of all `parser`'s optional actions."""
return sum(
(
opt.option_strings
for opt in parser._get_optional_actions()
if opt.help != SUPPRESS
),
[],
)

def recurse(parser, prefix):
positionals = parser._get_positional_actions()
commands = []
Expand All @@ -176,6 +181,16 @@ def recurse(parser, prefix):
for sub in positionals:
if sub.choices:
log.debug("choices:{}:{}".format(prefix, sorted(sub.choices)))
if hasattr(sub, "complete"):
print(
"{}_COMPGEN={}".format(
prefix,
complete2pattern(
sub.complete, "bash", choice_type2fn
),
),
file=fd,
)
for cmd in sorted(sub.choices):
if isinstance(cmd, Choice):
log.debug(
Expand Down Expand Up @@ -342,7 +357,7 @@ def complete_zsh(parser, root_prefix=None, preamble="", choice_functions=None):
root_arguments = []
subcommands = {} # {cmd: {"help": help, "arguments": [arguments]}}

choice_type2fn = dict(CHOICE_FUNCTIONS_ZSH)
choice_type2fn = {k: v["zsh"] for k, v in CHOICE_FUNCTIONS.items()}
if choice_functions:
choice_type2fn.update(choice_functions)

Expand All @@ -368,7 +383,9 @@ def format_optional(opt):
),
help=escape_zsh(opt.help or ""),
dest=opt.dest,
pattern=(
pattern=complete2pattern(opt.complete, "zsh", choice_type2fn)
if hasattr(opt, "complete")
else (
choice_type2fn[opt.choices[0].type]
if isinstance(opt.choices[0], Choice)
else "({})".format(" ".join(opt.choices))
Expand All @@ -380,10 +397,12 @@ def format_optional(opt):
)

def format_positional(opt):
return '"{nargs}:{help}:{choices}"'.format(
return '"{nargs}:{help}:{pattern}"'.format(
nargs={"+": "*", "*": "*"}.get(opt.nargs, ""),
help=escape_zsh((opt.help or opt.dest).strip().split("\n")[0]),
choices=(
pattern=complete2pattern(opt.complete, "zsh", choice_type2fn)
if hasattr(opt, "complete")
else (
choice_type2fn[opt.choices[0].type]
if isinstance(opt.choices[0], Choice)
else "({})".format(" ".join(opt.choices))
Expand Down Expand Up @@ -529,10 +548,15 @@ def complete(
shell : str (bash/zsh)
root_prefix : str, prefix for shell functions to avoid clashes
(default: "_{parser.prog}")
preamble : str, prepended to generated script
choice_functions : dict, maps custom `shtab.Choice.type`s to
completion functions (possibly defined in `preamble`)
preamble : dict, mapping shell to text to prepend to generated script
(e.g. `{"bash": "_myprog_custom_function(){ echo hello }"}`)
choice_functions : deprecated.
N.B. `parser.add_argument().complete = ...` can be used to define custom
completions (e.g. filenames). See <../examples/pathcomplete.py>.
"""
if isinstance(preamble, dict):
preamble = preamble.get(shell, "")
if shell == "bash":
return complete_bash(
parser,
Expand Down

0 comments on commit 3002441

Please sign in to comment.