Skip to content

Instantly share code, notes, and snippets.

@valtron
Created August 18, 2018 05:58
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 valtron/f035fe107a1679cbdc53e133db306414 to your computer and use it in GitHub Desktop.
Save valtron/f035fe107a1679cbdc53e133db306414 to your computer and use it in GitHub Desktop.
import re
import sys
from collections import defaultdict
from pathlib import Path
import inspect
def run(f, argv = None, *, converters = None):
"""
Usage:
```
def main(x: int, c: Path, b: str = '', *l: int, z: int, q: int = 0, **kw: int):
return [x, c, b, l, z, q, kw]
if __name__ == '__main__':
print(funcli.run(main))
```
"""
if argv is None:
argv = sys.argv
if converters is None:
converters = CONVERTERS
args, kwargs = parse_argv(sys.argv)
args, kwargs = convert_args(args, kwargs, f, converters)
return f(*args, **kwargs)
CONVERTERS = defaultdict(lambda: str, {
int: int,
float: float,
bool: lambda s: s == 'True',
Path: Path,
})
def convert_args(args, kwargs, f, converters):
argspec = inspect.getfullargspec(f)
args_converted = []
kwargs_converted = {}
for a, sa in zip(args, argspec.args):
converter = converters[argspec.annotations.get(sa)]
a_converted = converter(a)
args_converted.append(a_converted)
if len(args) > len(argspec.args):
converter = converters[argspec.annotations.get(argspec.varargs)]
for i in range(len(argspec.args), len(args)):
a = args[i]
a_converted = converter(a)
args_converted.append(a_converted)
for k, a in kwargs.items():
if k == argspec.varargs:
raise TypeError("{}() got an unexpected keyword argument '{}'".format(f.__name__, k))
converter = converters[argspec.annotations.get(k or argspec.varkw)]
a_converted = converter(a)
kwargs_converted[k] = a_converted
return args_converted, kwargs_converted
def parse_argv(argv):
args = []
kwargs = {}
for a in argv[1:]:
m = re.match(r'--([^=])=(.*)', a)
if m:
kwargs[m.group(1)] = m.group(2)
else:
if kwargs:
raise SyntaxError("positional argument follows keyword argument")
args.append(a)
return args, kwargs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment