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

1"""CLI interface of dirschema (see `dirschema --help`).""" 

2 

3import sys 

4from pathlib import Path 

5from typing import Tuple 

6 

7import typer 

8from ruamel.yaml import YAML 

9 

10from .json.handlers import loaded_handlers 

11from .log import log_level, logger 

12from .validate import DSValidator, MetaConvention 

13 

14yaml = YAML() 

15 

16app = typer.Typer() 

17 

18 

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()] 

23 

24 if not prefix.find("://") > 0 or prefix.startswith(tuple(valid_protocols)): 

25 return prefix 

26 

27 msg = "Unsupported URI protocol. " 

28 msg += "Supported protocols are: " + ", ".join(valid_protocols) 

29 raise typer.BadParameter(msg) 

30 

31 

32_def_meta_conv = MetaConvention().to_tuple() 

33"""Default metadata convention tuple (used if user provides no override).""" 

34 

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) 

42 

43_dir_arg = typer.Argument( 

44 ..., exists=True, help="Directory path (or suitable archive file) to be checked." 

45) 

46 

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) 

55 

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) 

64 

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) 

73 

74_verbose_opt = typer.Option(0, "--verbose", "-v", min=0, max=3) 

75 

76 

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. 

87 

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")