Coverage for obj2cli/_cli.py: 24%

66 statements  

« 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 

10 

11import toml 

12import yaml 

13 

14from .main import main_func, main_single 

15from .version import VERSION 

16 

17log = getLogger(__name__) 

18 

19 

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) 

27 

28 

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} 

40 

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} 

50 

51 

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) 

83 

84 deftype = typemap.get(parsed.deftype, str) 

85 

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) 

113 

114 

115if __name__ == "__main__": 115 ↛ 116line 115 didn't jump to line 116 because the condition on line 115 was never true

116 main()