Coverage for visailu/cli.py: 96.00%
66 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-05 19:49:28 +00:00
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-05 19:49:28 +00:00
1"""Command line interface for quiz (Finnish: visailu) data operations."""
3import logging
4import pathlib
6import typer
8from visailu import APP_NAME, QUIET, __version__ as APP_VERSION, log
9from visailu.publish import publish_path
10from visailu.validate import validate_path
11from visailu.verify import verify_path
13app = typer.Typer(
14 add_completion=False,
15 context_settings={'help_option_names': ['-h', '--help']},
16 no_args_is_help=True,
17)
19DocumentPath = typer.Option(
20 '',
21 '-f',
22 '--file',
23 help='File path to read model from',
24)
25Verbosity = typer.Option(
26 False,
27 '-v',
28 '--verbose',
29 help='Verbose output (default is False)',
30)
31Strictness = typer.Option(
32 False,
33 '-s',
34 '--strict',
35 help='Ouput noisy warnings on console (default is False)',
36)
37OutputPath = typer.Option(
38 '',
39 '-o',
40 '--output-path',
41 help='Path to output unambiguous content to - like when ejecting a template',
42)
45@app.callback(invoke_without_command=True)
46def callback(
47 version: bool = typer.Option(
48 False,
49 '-V',
50 '--version',
51 help='Display the application version and exit',
52 is_eager=True,
53 )
54) -> None:
55 """
56 Quiz (Finnish: visailu) data operations.
57 """
58 if version:
59 typer.echo(f'{APP_NAME} version {APP_VERSION}')
60 raise typer.Exit()
63def _verify_call_vector(
64 doc_path: str, doc_path_pos: str, verbose: bool, strict: bool
65) -> tuple[int, str, str, dict[str, bool]]:
66 """DRY"""
67 doc = doc_path.strip()
68 if not doc and doc_path_pos:
69 doc = doc_path_pos
70 if not doc:
71 return 2, 'Document path required', '', {}
73 doc_path_path = pathlib.Path(doc)
74 if doc_path_path.exists():
75 if not doc_path_path.is_file(): 75 ↛ 76line 75 didn't jump to line 76, because the condition on line 75 was never true
76 return 2, f'requested model file path at ({doc}) is not a file', '', {}
77 else:
78 return 2, f'requested model file path at ({doc}) does not exist', '', {}
80 options = {
81 'quiet': QUIET and not verbose and not strict,
82 'strict': strict,
83 'verbose': verbose,
84 }
85 if verbose: 85 ↛ 86line 85 didn't jump to line 86, because the condition on line 85 was never true
86 logging.getLogger().setLevel(logging.DEBUG)
87 return 0, '', doc, options
90@app.command('verify')
91def verify_cmd( # noqa
92 doc_path_pos: str = typer.Argument(''),
93 doc_path: str = DocumentPath,
94 verbose: bool = Verbosity,
95 strict: bool = Strictness,
96) -> int:
97 """
98 Verify the model data against YAML syntax.
99 """
100 code, message, path, options = _verify_call_vector(doc_path, doc_path_pos, verbose, strict)
101 if code:
102 log.error(message)
103 raise typer.Exit(code=code)
105 code, message, data = verify_path(path, options=options)
106 if code != 0:
107 log.error(message)
109 raise typer.Exit(code=code)
112@app.command('validate')
113def validate_cmd( # noqa
114 doc_path_pos: str = typer.Argument(''),
115 doc_path: str = DocumentPath,
116 verbose: bool = Verbosity,
117 strict: bool = Strictness,
118) -> int:
119 """
120 Validate the YAML data against the model.
121 """
122 code, message, path, options = _verify_call_vector(doc_path, doc_path_pos, verbose, strict)
123 if code:
124 log.error(message)
125 raise typer.Exit(code=code)
127 code, message, data = validate_path(path, options=options)
128 if code != 0:
129 log.error(f'path {path} {message}')
131 raise typer.Exit(code=code)
134@app.command('publish')
135def publish_cmd( # noqa
136 doc_path_pos: str = typer.Argument(''),
137 doc_path: str = DocumentPath,
138 verbose: bool = Verbosity,
139 strict: bool = Strictness,
140) -> int:
141 """
142 Publish the model data in simplified JSON syntax.
143 """
144 code, message, path, options = _verify_call_vector(doc_path, doc_path_pos, verbose, strict)
145 if code:
146 log.error(message)
147 raise typer.Exit(code=code)
149 code, message, data = publish_path(path, options=options)
150 if code != 0:
151 log.error(f'path {path} {message}')
152 else:
153 log.info(message)
155 raise typer.Exit(code=code)
158@app.command('version')
159def app_version() -> None:
160 """
161 Display the application version and exit.
162 """
163 callback(True)