Coverage for laskea/cli.py: 60.22%
71 statements
« prev ^ index » next coverage.py v7.3.0, created at 2023-08-17 13:24:57 +00:00
« prev ^ index » next coverage.py v7.3.0, created at 2023-08-17 13:24:57 +00:00
1#! /usr/bin/env python3
2# -*- coding: utf-8 -*-
3"""Commandline API gateway for laskea."""
4import sys
5from typing import List
7import requests_cache
8import typer
10import laskea
11import laskea.config as cfg
12import laskea.laskea as fill
13from laskea import env
15app = typer.Typer(
16 add_completion=False,
17 context_settings={'help_option_names': ['-h', '--help']},
18 no_args_is_help=True,
19)
22@app.callback(invoke_without_command=True)
23def callback(
24 version: bool = typer.Option(
25 False,
26 '-V',
27 '--version',
28 help='Display the laskea version and exit',
29 is_eager=True,
30 )
31) -> None:
32 """
33 Calculate (Finnish: laskea) some parts.
34 """
35 if version:
36 typer.echo(f'{laskea.APP_NAME} version {laskea.__version__}')
37 raise typer.Exit()
40@app.command('template')
41def app_template() -> int:
42 """
43 Write a template of a well-formed JSON configuration to standard out and exit
45 The strategy for looking up configurations is to start at the current working
46 directory trying to read a file with the name `.laskea.json` else try to read
47 same named file in the user folder (home).
49 In case an explicit path is given to the config option of commands that offer
50 it, only that path is considered.
51 """
52 sys.stdout.write(cfg.generate_template())
53 return sys.exit(0)
56@app.command('report')
57def report(
58 shallow: bool = typer.Option(
59 False,
60 '-s',
61 '--shallow',
62 help='Shallow reporting - no setuptools required (default is False)',
63 ),
64) -> int:
65 """Output either text options for the user to report her env or the report of the environment for support."""
66 sys.stdout.write(env.report(shallow))
67 return sys.exit(0)
70@app.command('update')
71def update( # noqa
72 source: List[str],
73 inp: str = typer.Option(
74 '',
75 '-i',
76 '--input',
77 help='Path to input file',
78 metavar='<sourcepath>',
79 ),
80 conf: str = typer.Option(
81 '',
82 '-c',
83 '--config',
84 help=f'Path to config file (default is $HOME/{laskea.DEFAULT_CONFIG_NAME})',
85 metavar='<configpath>',
86 ),
87 verify: bool = typer.Option(
88 False,
89 '-n',
90 '--dry-run',
91 help='Dry run (default is False)',
92 ),
93 verbose: bool = typer.Option(
94 False,
95 '-v',
96 '--verbose',
97 help='Verbose output (default is False)',
98 ),
99 quiet: bool = typer.Option(
100 False,
101 '-q',
102 '--quiet',
103 help='Minimal output (default is False)',
104 ),
105 strict: bool = typer.Option(
106 False,
107 '-s',
108 '--strict',
109 help='Ouput noisy warnings on console and in the processed document (default is False)',
110 ),
111 expires: int = typer.Option(
112 180,
113 '-x',
114 '--cache-expiry-seconds',
115 help='Request cache expiry in seconds',
116 ),
117) -> int:
118 """
119 Fill in some parts of the input document.
121 You can set some options per evironment variables:
123 \b
124 * LASKEA_USER='remote-user'
125 * LASKEA_TOKEN='remote-secret'
126 * LASKEA_BASE_URL='https://remote-jira-instance.example.com/'
127 * LASKEA_CACHE_EXPIRY_SECONDS=180
128 * LASKEA_COL_FIELDS: '["Key", "Summary", "Custom Field Name"]'
129 * LASKEA_COL_MAPS='{"key": ["key", "key"], "summary": ["summary", "fields.summary"],
130 "custom field name": ["customfield_123", "fields.customfield_123"]}'
131 * LASKEA_JOIN_STRING=' <br>'
132 * LASKEA_LF_ONLY='AnythingTruthy'
133 * LASKEA_IS_CLOUD='WhenNotConnectingToJiraServerButJiraCloud'
134 * LASKEA_MARKERS='[[[fill ]]] [[[end]]]'
135 * LASKEA_DEBUG='AnythingTruthy'
136 * LASKEA_VERBOSE='AnythingTruthy'
137 * LASKEA_STRICT='AnythingTruthy'
139 The quiet option (if given) disables any conflicting verbosity setting.
140 """
141 command = 'update'
142 transaction_mode = 'commit' if not verify else 'dry-run'
143 if quiet: 143 ↛ 144line 143 didn't jump to line 144, because the condition on line 143 was never true
144 laskea.QUIET = True
145 laskea.DEBUG = False
146 laskea.VERBOSE = False
147 elif verbose: 147 ↛ 148line 147 didn't jump to line 148, because the condition on line 147 was never true
148 laskea.VERBOSE = True
150 if strict: 150 ↛ 151line 150 didn't jump to line 151, because the condition on line 150 was never true
151 laskea.STRICT = True
153 if transaction_mode == 'dry-run': 153 ↛ 154line 153 didn't jump to line 154, because the condition on line 153 was never true
154 laskea.DRY_RUN = True
156 requests_cache.install_cache(cache_name='.laskea_cache', backend='sqlite', expire_after=expires)
157 laskea.CACHE_EXPIRY_SECONDS = expires
158 options = {
159 'quiet': quiet,
160 'strict': strict,
161 'verbose': verbose,
162 }
163 cfg.process(conf, options)
165 paths = (inp,) if inp else tuple(source)
166 return sys.exit(fill.process(command, transaction_mode, paths, options))
169@app.command('csv')
170def svl_cmd( # noqa
171 query: str = typer.Argument(''),
172 jql_query: str = typer.Option(
173 '',
174 '-j',
175 '--jql-query',
176 help=(
177 'The query in JQL format.'
178 '\nFor example given a project YES and two issues 123 and 124:'
179 "\n'project = YES and key in (YES-123, YES-124) order by created DESC'"
180 ),
181 metavar='<jql-query>',
182 ),
183 conf: str = typer.Option(
184 '',
185 '-c',
186 '--config',
187 help=f'Path to config file (default is $HOME/{laskea.DEFAULT_CONFIG_NAME})',
188 metavar='<configpath>',
189 ),
190 key_magic: bool = typer.Option(
191 False,
192 '-k',
193 '--key-magic',
194 help='Apply magic to key by replacing with markdown like link (default is False)',
195 ),
196 field_sep: str = typer.Option(
197 laskea.PIPE,
198 '-d',
199 '--delimiter',
200 help=(
201 'Delimiter / field separator'
202 '\nOn output, header and data cell values will have any occurences'
203 '\nof the field separator replaced with the replacement string'
204 ),
205 metavar='<field-separator>',
206 ),
207 replacement: str = typer.Option(
208 laskea.FS_SLUG,
209 '-r',
210 '--replacement',
211 help=(
212 'Replacement string for occurences of FS in text\n'
213 '\nOn output, header and data cell values will have any occurences'
214 '\nof the field separator replaced with the replacement string'
215 ),
216 metavar='<replacement-text>',
217 ),
218 verify: bool = typer.Option(
219 False,
220 '-n',
221 '--dry-run',
222 help='Dry run (default is False)',
223 ),
224 verbose: bool = typer.Option(
225 False,
226 '-v',
227 '--verbose',
228 help='Verbose output (default is False)',
229 ),
230 strict: bool = typer.Option(
231 False,
232 '-s',
233 '--strict',
234 help='Ouput noisy warnings on console and in the processed document (default is False)',
235 ),
236 expires: int = typer.Option(
237 180,
238 '-x',
239 '--cache-expiry-seconds',
240 help='Request cache expiry in seconds',
241 ),
242) -> int:
243 """
244 Export query result as separated values list.
246 You can set some options per evironment variables:
248 \b
249 * LASKEA_USER='remote-user'
250 * LASKEA_TOKEN='remote-secret'
251 * LASKEA_BASE_URL='https://remote-jira-instance.example.com/'
252 * LASKEA_CACHE_EXPIRY_SECONDS=180
253 * LASKEA_COL_FIELDS: '["Key", "Summary", "Custom Field Name"]'
254 * LASKEA_COL_MAPS='{"key": ["key", "key"], "summary": ["summary", "fields.summary"],
255 "custom field name": ["customfield_123", "fields.customfield_123"]}'
256 * LASKEA_JOIN_STRING=' <br>'
257 * LASKEA_LF_ONLY='AnythingTruthy'
258 * LASKEA_IS_CLOUD='WhenNotConnectingToJiraServerButJiraCloud'
259 * LASKEA_MARKERS='[[[fill ]]] [[[end]]]'
260 * LASKEA_DEBUG='AnythingTruthy'
261 * LASKEA_VERBOSE='AnythingTruthy'
262 * LASKEA_STRICT='AnythingTruthy'
264 The quiet option (if given) disables any conflicting verbosity setting.
265 """
266 transaction_mode = 'commit' if not verify else 'dry-run'
267 jql = jql_query.strip()
268 if not jql and query: 268 ↛ 269line 268 didn't jump to line 269, because the condition on line 268 was never true
269 jql = query
270 if not jql: 270 ↛ 273line 270 didn't jump to line 273, because the condition on line 270 was never false
271 print('JQL query required.', file=sys.stderr)
272 return sys.exit(2)
273 quiet = True
274 laskea.QUIET = True
275 laskea.DEBUG = False
276 laskea.VERBOSE = False
277 if verbose:
278 laskea.VERBOSE = True
280 if strict:
281 laskea.STRICT = True
283 if transaction_mode == 'dry-run':
284 laskea.DRY_RUN = True
286 requests_cache.install_cache(cache_name='.laskea_cache', backend='sqlite', expire_after=expires)
287 laskea.CACHE_EXPIRY_SECONDS = expires
288 options = {
289 'quiet': quiet,
290 'strict': strict,
291 'verbose': verbose,
292 }
293 if conf:
294 cfg.process(conf, options)
296 return sys.exit(laskea.svl(jql, key_magic=key_magic, field_sep=field_sep, replacement=replacement))
299@app.command('version')
300def app_version() -> None:
301 """
302 Display the laskea version and exit.
303 """
304 callback(True)