Coverage for etiketti / cli.py: 91.94%
44 statements
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-03 22:57:11 +00:00
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-03 22:57:11 +00:00
1"""Command line interface for labeling."""
3import argparse
4import pathlib
5import sys
7import etiketti.implementation as impl
8from etiketti import (
9 APP_ALIAS,
10 APP_NAME,
11 APP_VERSION,
12 CONFIG_PATH_STRING,
13 SOURCE_NAME_PATH_STRING,
14 TARGET_NAME_PATH_STRING,
15 parse_key_value_pair_csl,
16)
19def parse_request(argv: list[str]) -> int | argparse.Namespace:
20 """DRY."""
21 parser = argparse.ArgumentParser(
22 prog=APP_ALIAS, description=APP_NAME, formatter_class=argparse.RawTextHelpFormatter
23 )
24 parser.add_argument(
25 '--in-path',
26 '-i',
27 dest='in_pdf',
28 default='',
29 help='input file path to pdf file to label',
30 required=False,
31 )
32 parser.add_argument(
33 'in_pdf_pos',
34 nargs='?',
35 default=SOURCE_NAME_PATH_STRING,
36 help='input file path to pdf file to label',
37 )
38 parser.add_argument(
39 '--out-path',
40 '-o',
41 dest='out_pdf',
42 default=TARGET_NAME_PATH_STRING,
43 help='output path for resulting labeled pdf file',
44 required=False,
45 )
46 parser.add_argument(
47 '--config',
48 '-c',
49 dest='cfg_path',
50 default=CONFIG_PATH_STRING,
51 help='configuration file for label context data',
52 required=False,
53 )
54 parser.add_argument(
55 '--enforce',
56 '-e',
57 dest='enforce',
58 default=False,
59 action='store_true',
60 help='enforce labels by overwriting the source file',
61 required=False,
62 )
63 parser.add_argument(
64 '--version',
65 '-V',
66 dest='version_request',
67 default=False,
68 action='store_true',
69 help='show version of the app and exit',
70 required=False,
71 )
72 parser.add_argument(
73 '--key-value-pairs',
74 '-k',
75 dest='key_value_pair_csl',
76 default='',
77 help='key value pairs as comma separated list of key=value pairs (default: empty string)',
78 )
80 if not argv:
81 print(f'{APP_NAME} version {APP_VERSION}')
82 parser.print_help()
83 return 0
85 options = parser.parse_args(argv)
87 if options.version_request: 87 ↛ 88line 87 didn't jump to line 88 because the condition on line 87 was never true
88 print(f'{APP_NAME} version {APP_VERSION}')
89 return 0
91 if not options.in_pdf:
92 if options.in_pdf_pos: 92 ↛ 95line 92 didn't jump to line 95 because the condition on line 92 was always true
93 options.in_pdf = options.in_pdf_pos
94 else:
95 options.in_pdf = SOURCE_NAME_PATH_STRING
97 options.kv_pairs = parse_key_value_pair_csl(options.key_value_pair_csl)
99 in_pdf = pathlib.Path(options.in_pdf)
100 if in_pdf.exists():
101 if in_pdf.is_file():
102 cfg_path = pathlib.Path(options.cfg_path)
103 if cfg_path.exists():
104 if cfg_path.is_file():
105 return options
106 parser.error(f'configuration path ({cfg_path}) is not a file')
107 parser.error(f'configuration path ({cfg_path}) does not exist')
108 parser.error(f'requested pdf at ({in_pdf}) is not a file')
109 parser.error(f'requested pdf at ({in_pdf}) does not exist')
112def app(argv: list[str] | None = None) -> int:
113 """Delegate processing to functional module."""
114 argv = sys.argv[1:] if argv is None else argv
115 options = parse_request(argv)
116 if isinstance(options, int):
117 return 0
118 return impl.patch(options)