Coverage for obj2cli/_cli.py: 24%
66 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-05 14:23 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-05 14:23 +0000
1import argparse
2import datetime
3import importlib
4import json
5import marshal
6import pickle
7import pprint
8import sys
9from logging import DEBUG, INFO, WARNING, basicConfig, getLogger
11import toml
12import yaml
14from .main import main_func, main_single
15from .version import VERSION
17log = getLogger(__name__)
20def output_bytype(s):
21 if s is None:
22 return
23 elif isinstance(s, (str, int, float, bool)):
24 print(s)
25 else:
26 json.dump(s, sys.stdout, ensure_ascii=False)
29formats = {
30 "json": lambda f: json.dump(f, sys.stdout, ensure_ascii=False),
31 "yaml": lambda f: yaml.dump(f, stream=sys.stdout),
32 "pprint": lambda f: pprint.pprint(f),
33 "print": lambda f: print(f),
34 "log": lambda f: log.info("%s", f),
35 "toml": lambda f: toml.dump(f, f=sys.stdout),
36 "pickle": lambda f: pickle.dump(f, sys.stdout.buffer),
37 "marshal": lambda f: marshal.dump(f, sys.stdout.buffer),
38 "bytype": output_bytype,
39}
41typemap = {
42 "int": int,
43 "str": str,
44 "dict": dict,
45 "datetime": datetime.datetime,
46 "time": datetime.time,
47 "date": datetime.date,
48 "float": float,
49}
52def main():
53 parser = argparse.ArgumentParser(prog="obj2cli")
54 parser.add_argument("--version", action="version", version="%(prog)s " + VERSION)
55 parser.add_argument(
56 "--default-type",
57 type=str,
58 default="str",
59 dest="deftype",
60 choices=typemap.keys(),
61 )
62 parser.add_argument("--module", type=str, required=True)
63 parser.add_argument("--package", type=str, default=None)
64 parser.add_argument("--interface", dest="ifklass", type=str)
65 parser.add_argument("--class", dest="klass", type=str)
66 parser.add_argument("--function", type=str)
67 parser.add_argument("--positional", action="store_true", default=False)
68 parser.add_argument("--noskip", action="store_true")
69 parser.add_argument("--verbose", action="store_true")
70 parser.add_argument("--quiet", action="store_true")
71 parser.add_argument("--format", choices=formats.keys(), default="bytype")
72 parser.add_argument("args", nargs="*")
73 parsed = parser.parse_args()
74 # fmt = '%(asctime)s %(name)s %(levelname)s %(message)s'
75 fmt = "%(asctime)s %(levelname)s %(message)s"
76 if parsed.verbose:
77 basicConfig(level=DEBUG, format=fmt)
78 elif parsed.quiet:
79 basicConfig(level=WARNING, format=fmt)
80 else:
81 basicConfig(level=INFO, format=fmt)
82 log.debug("parsed: %s", parsed)
84 deftype = typemap.get(parsed.deftype, str)
86 log.debug("loading module %s, package=%s", parsed.module, parsed.package)
87 mod = importlib.import_module(name=parsed.module, package=parsed.package)
88 if parsed.ifklass is None:
89 ifclsname = parsed.klass
90 else:
91 ifclsname = parsed.ifklass
92 if ifclsname is not None:
93 ifcls = getattr(mod, ifclsname)
94 cls = getattr(mod, parsed.klass)
95 log.debug("class: %s, if=%s", cls, ifcls)
96 res = main_single(
97 ifcls, cls, parsed.args, deftype=deftype, positional=parsed.positional
98 )
99 log.debug("result: %s", res)
100 formats.get(parsed.format, lambda f: print(f))(res)
101 elif parsed.function is not None:
102 fn = getattr(mod, parsed.function)
103 log.debug("func: %s", fn)
104 res = main_func(
105 fn,
106 parsed.args,
107 noskip=parsed.noskip,
108 deftype=deftype,
109 positional=parsed.positional,
110 )
111 log.debug("result: %s", res)
112 formats.get(parsed.format, lambda f: print(f))(res)
115if __name__ == "__main__": 115 ↛ 116line 115 didn't jump to line 116 because the condition on line 115 was never true
116 main()