Coverage for etiketti/cli.py: 92.06%

45 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-02-04 17:54:24 +00:00

1"""Command line interface for labeling.""" 

2 

3import argparse 

4import pathlib 

5import sys 

6from typing import Union 

7 

8import etiketti.implementation as impl 

9from etiketti import ( 

10 APP_ALIAS, 

11 APP_NAME, 

12 APP_VERSION, 

13 CONFIG_PATH_STRING, 

14 SOURCE_NAME_PATH_STRING, 

15 TARGET_NAME_PATH_STRING, 

16 parse_key_value_pair_csl, 

17) 

18 

19 

20def parse_request(argv: list[str]) -> Union[int, argparse.Namespace]: 

21 """DRY.""" 

22 parser = argparse.ArgumentParser( 

23 prog=APP_ALIAS, description=APP_NAME, formatter_class=argparse.RawTextHelpFormatter 

24 ) 

25 parser.add_argument( 

26 '--in-path', 

27 '-i', 

28 dest='in_pdf', 

29 default='', 

30 help='input file path to pdf file to label', 

31 required=False, 

32 ) 

33 parser.add_argument( 

34 'in_pdf_pos', 

35 nargs='?', 

36 default=SOURCE_NAME_PATH_STRING, 

37 help='input file path to pdf file to label', 

38 ) 

39 parser.add_argument( 

40 '--out-path', 

41 '-o', 

42 dest='out_pdf', 

43 default=TARGET_NAME_PATH_STRING, 

44 help='output path for resulting labeled pdf file', 

45 required=False, 

46 ) 

47 parser.add_argument( 

48 '--config', 

49 '-c', 

50 dest='cfg_path', 

51 default=CONFIG_PATH_STRING, 

52 help='configuration file for label context data', 

53 required=False, 

54 ) 

55 parser.add_argument( 

56 '--enforce', 

57 '-e', 

58 dest='enforce', 

59 default=False, 

60 action='store_true', 

61 help='enforce labels by overwriting the source file', 

62 required=False, 

63 ) 

64 parser.add_argument( 

65 '--version', 

66 '-V', 

67 dest='version_request', 

68 default=False, 

69 action='store_true', 

70 help='show version of the app and exit', 

71 required=False, 

72 ) 

73 parser.add_argument( 

74 '--key-value-pairs', 

75 '-k', 

76 dest='key_value_pair_csl', 

77 default='', 

78 help='key value pairs as comma separated list of key=value pairs (default: empty string)', 

79 ) 

80 

81 if not argv: 

82 print(f'{APP_NAME} version {APP_VERSION}') 

83 parser.print_help() 

84 return 0 

85 

86 options = parser.parse_args(argv) 

87 

88 if options.version_request: 88 ↛ 89line 88 didn't jump to line 89, because the condition on line 88 was never true

89 print(f'{APP_NAME} version {APP_VERSION}') 

90 return 0 

91 

92 if not options.in_pdf: 

93 if options.in_pdf_pos: 93 ↛ 96line 93 didn't jump to line 96, because the condition on line 93 was never false

94 options.in_pdf = options.in_pdf_pos 

95 else: 

96 options.in_pdf = SOURCE_NAME_PATH_STRING 

97 

98 options.kv_pairs = parse_key_value_pair_csl(options.key_value_pair_csl) 

99 

100 in_pdf = pathlib.Path(options.in_pdf) 

101 if in_pdf.exists(): 

102 if in_pdf.is_file(): 

103 cfg_path = pathlib.Path(options.cfg_path) 

104 if cfg_path.exists(): 

105 if cfg_path.is_file(): 

106 return options 

107 parser.error(f'configuration path ({cfg_path}) is not a file') 

108 parser.error(f'configuration path ({cfg_path}) does not exist') 

109 parser.error(f'requested pdf at ({in_pdf}) is not a file') 

110 parser.error(f'requested pdf at ({in_pdf}) does not exist') 

111 

112 

113def app(argv: list[str] | None = None) -> int: 

114 """Delegate processing to functional module.""" 

115 argv = sys.argv[1:] if argv is None else argv 

116 options = parse_request(argv) 

117 if isinstance(options, int): 

118 return 0 

119 return impl.patch(options)