Skip to content

Instantly share code, notes, and snippets.

@devforfu
Last active July 2, 2019 18:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devforfu/2f2019f48b3230c136da529fec8bfc8e to your computer and use it in GitHub Desktop.
Save devforfu/2f2019f48b3230c136da529fec8bfc8e to your computer and use it in GitHub Desktop.
Converting function signature into CLI
import argparse
from pathlib import Path
import signature
def concat(folder: str, output: str = 'concat.txt', include_names: bool = True):
"""Concatenates a list of files from a folder and saves them into a single file."""
p = Path(folder)
files = []
for filename in p.iterdir():
content = filename.open('r').read().strip()
if include_names:
content = f'{filename}\n{content}\n'
files.append(content)
single = '\n'.join(files)
Path(output).open('w').write(single)
def make_cli(func: callable):
"""Takes a Python function and builds ArgumentParser instance using the
function's signature.
The function is called right after the parameters are parsed.
"""
parser = argparse.ArgumentParser()
sig = inspect.signature(func)
empty = inspect._empty
for param in sig.parameters.values():
annot = param.annotation
options = {}
if annot is empty:
ptype = str
elif isinstance(annot, tuple):
ptype, help_msg = annot
if help_msg is not empty:
options['help'] = help_msg
else:
ptype = annot
options['type'] = ptype
if param.default is empty:
options['required'] = True
else:
options['default'] = param.default
if annot is empty:
options['type'] = type(options['default'])
name = param.name.replace('_', '-')
parser.add_argument(f'--{name}', **options)
func(**vars(parser.parse_args()))
if __name__ == '__main__':
make_cli(concat)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment