Coverage for src/dirschema/cli.py: 0%
36 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-12-07 09:34 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-12-07 09:34 +0000
1"""CLI interface of dirschema (see `dirschema --help`)."""
3import sys
4from pathlib import Path
5from typing import Tuple
7import typer
8from ruamel.yaml import YAML
10from .json.handlers import loaded_handlers
11from .log import log_level, logger
12from .validate import DSValidator, MetaConvention
14yaml = YAML()
16app = typer.Typer()
19def _check_rel_prefix(prefix: str):
20 """Validate prefix argument."""
21 valid_protocols = ["http://", "https://", "file://", "cwd://", "local://"]
22 valid_protocols += [f"v#{name}://" for name in loaded_handlers.keys()]
24 if not prefix.find("://") > 0 or prefix.startswith(tuple(valid_protocols)):
25 return prefix
27 msg = "Unsupported URI protocol. "
28 msg += "Supported protocols are: " + ", ".join(valid_protocols)
29 raise typer.BadParameter(msg)
32_def_meta_conv = MetaConvention().to_tuple()
33"""Default metadata convention tuple (used if user provides no override)."""
35_schema_arg = typer.Argument(
36 ...,
37 exists=True,
38 dir_okay=False,
39 readable=True,
40 help="Path of YAML file with the DirSchema to be used for validation.",
41)
43_dir_arg = typer.Argument(
44 ..., exists=True, help="Directory path (or suitable archive file) to be checked."
45)
47_conv_opt = typer.Option(
48 _def_meta_conv,
49 help=(
50 "Used metadata file convention consisting of four strings "
51 "(pathPrefix, pathSuffix, filePrefix, fileSuffix), at least one of which "
52 "must be non-empty"
53 ),
54)
56_local_basedir_opt = typer.Option(
57 None,
58 exists=True,
59 help=(
60 "Base path to resolve local:// URIs "
61 "[default: location of the passed dirschema]"
62 ),
63)
65_rel_prefix_opt = typer.Option(
66 "",
67 help=(
68 "Prefix to add to all relative paths "
69 "(i.e. to paths not starting with a slash or some access protocol)."
70 ),
71 callback=_check_rel_prefix,
72)
74_verbose_opt = typer.Option(0, "--verbose", "-v", min=0, max=3)
77@app.command()
78def run_dirschema(
79 schema: Path = _schema_arg,
80 dir: Path = _dir_arg,
81 conv: Tuple[str, str, str, str] = _conv_opt,
82 local_basedir: Path = _local_basedir_opt,
83 relative_prefix: str = _rel_prefix_opt,
84 verbose: int = _verbose_opt,
85) -> None:
86 """Run dirschema validation of a directory against a schema.
88 Performs validation according to schema and prints all unsatisfied constraints.
89 """
90 logger.setLevel(log_level[verbose])
91 local_basedir = local_basedir or schema.parent
92 dsv = DSValidator(
93 schema,
94 MetaConvention.from_tuple(*conv),
95 local_basedir=local_basedir,
96 relative_prefix=relative_prefix,
97 )
98 if errors := dsv.validate(dir):
99 logger.debug(f"Validation of '{dir}' failed")
100 dsv.format_errors(errors, sys.stdout)
101 raise typer.Exit(code=1)
102 logger.debug(f"Validation of '{dir}' successful")