Skip to content

Instantly share code, notes, and snippets.

@podhmo
Created August 15, 2018 14:24
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 podhmo/0cc69b8c1114260ca8ccb72e3892e0e4 to your computer and use it in GitHub Desktop.
Save podhmo/0cc69b8c1114260ca8ccb72e3892e0e4 to your computer and use it in GitHub Desktop.
import sys
class FakeArgumentParser:
def __init__(self, *args, history=None, **kwargs):
self.history = history or [{"name": "__init__", "args": args, "kwargs": kwargs}]
def __getattr__(self, name):
self.history.append({"name": name})
return FakeArgumentParser(history=self.history)
def __call__(self, *args, **kwargs):
latest = self.history[-1]
assert "args" not in latest
latest["args"] = args
latest["kwargs"] = kwargs
def parse_args(self, *args, **kwargs):
self.history.append({"name": "parse_args", "args": args, "kwargs": kwargs})
from prestring.python import Module, LazyArgumentsAndKeywords
def _make_args(history, default=""):
name = history["name"]
if name == "__init__":
name = default
kwargs = {k: repr(v) for k, v in history["kwargs"].items()}
args = [repr(v) for v in history["args"]]
return f"{name}({LazyArgumentsAndKeywords(args, kwargs)})"
m = Module()
with m.def_("Main"):
m.import_("argparse")
m.stmt(f"parser = argparse.ArgumentParser{_make_args(self.history[0])}")
for x in self.history[1:-1]:
m.stmt(f"parser.{_make_args(x)}")
m.stmt(f"args = parser.{_make_args(self.history[-1])}")
m.stmt("main(**vars(args))")
with m.if_("__name__ == '__main__'"):
m.stmt("Main()")
print(m)
sys.exit(0)
def parser(parser):
import logging
parser.add_argument("-c", "--config", required=True)
parser.add_argument("--log-level", default="INFO", choices=tuple(logging._nameToLevel.keys()))
args = parser.parse_args()
run(args)
parser(FakeArgumentParser(help="fake"))
import inspect
import sys
import argparse
def as_command(fn=None, argv=None, level=2):
def call(fn, level=1, argv=argv):
frame = sys._getframe(level)
name = frame.f_globals["__name__"]
if name == "__main__":
argspec = inspect.getfullargspec(fn)
parser = argparse.ArgumentParser()
for k in argspec.kwonlyargs:
parser.add_argument(
f'{"-" if len(k) <= 1 else "--"}{k.replace("_", "-")}', required=True
)
args = parser.parse_args()
return fn(**vars(args))
else:
return fn
if fn is None:
return call
else:
return call(fn, level=level, argv=argv)
@as_command
def run(*, x: int, y: int):
print(f"{x} + {y} = {x + y}")

00 printing onesself

$ python 00*.py
def Main():
    import argparse
    parser = argparse.ArgumentParser(help='fake')
    parser.add_argument('-c', '--config', required=True)
    parser.add_argument('--log-level', choices=('CRITICAL', 'FATAL', 'ERROR', 'WARN', 'WARNING', 'INFO', 'DEBUG', 'NOTSET'), default='INFO')
    args = parser.parse_args()
    main(**vars(args))


if __name__ == '__main__':
    Main()

01 the function as command

$ python 01*.py -h
usage: 01ascommand.py [-h] -x X -y Y

optional arguments:
  -h, --help  show this help message and exit
  -x X
  -y Y

$ python 01*.py -x 10 -y 20
10 + 20 = 1020
default: 00 01
00:
python 00*.py
01:
python 01*.py -h
python 01*.py -x 10 -y 20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment