1
1
from __future__ import annotations
2
2
3
- import enum
4
3
import os
5
4
import textwrap
6
5
7
6
import click
8
7
9
- from .catalog import CUSTOM_SCHEMA_NAMES , SCHEMA_CATALOG
10
- from .checker import SchemaChecker
11
- from .formats import FormatOptions , RegexFormatBehavior
12
- from .instance_loader import InstanceLoader
13
- from .parsers import SUPPORTED_FILE_FORMATS
14
- from .reporter import REPORTER_BY_NAME , Reporter
15
- from .schema_loader import (
8
+ from .. catalog import CUSTOM_SCHEMA_NAMES , SCHEMA_CATALOG
9
+ from .. checker import SchemaChecker
10
+ from .. formats import KNOWN_FORMATS , RegexFormatBehavior
11
+ from .. instance_loader import InstanceLoader
12
+ from .. parsers import SUPPORTED_FILE_FORMATS
13
+ from .. reporter import REPORTER_BY_NAME , Reporter
14
+ from .. schema_loader import (
16
15
BuiltinSchemaLoader ,
17
16
MetaSchemaLoader ,
18
17
SchemaLoader ,
19
18
SchemaLoaderBase ,
20
19
)
21
- from .transforms import TRANSFORM_LIBRARY , Transform
20
+ from ..transforms import TRANSFORM_LIBRARY
21
+ from .param_types import CommaDelimitedList
22
+ from .parse_result import ParseResult , SchemaLoadingMode
23
+ from .warnings import deprecation_warning_callback
22
24
23
25
BUILTIN_SCHEMA_NAMES = [f"vendor.{ k } " for k in SCHEMA_CATALOG .keys ()] + [
24
26
f"custom.{ k } " for k in CUSTOM_SCHEMA_NAMES
28
30
)
29
31
30
32
31
- class SchemaLoadingMode (enum .Enum ):
32
- filepath = "filepath"
33
- builtin = "builtin"
34
- metaschema = "metaschema"
35
-
36
-
37
- class ParseResult :
38
- def __init__ (self ) -> None :
39
- # primary options: schema + instances
40
- self .schema_mode : SchemaLoadingMode = SchemaLoadingMode .filepath
41
- self .schema_path : str | None = None
42
- self .instancefiles : tuple [str , ...] = ()
43
- # cache controls
44
- self .disable_cache : bool = False
45
- self .cache_filename : str | None = None
46
- # filetype detection (JSON, YAML, TOML, etc)
47
- self .default_filetype : str = "json"
48
- # data-transform (for Azure Pipelines and potentially future transforms)
49
- self .data_transform : Transform | None = None
50
- # fill default values on instances during validation
51
- self .fill_defaults : bool = False
52
- # regex format options
53
- self .disable_format : bool = False
54
- self .format_regex : RegexFormatBehavior = RegexFormatBehavior .default
55
- # error and output controls
56
- self .verbosity : int = 1
57
- self .traceback_mode : str = "short"
58
- self .output_format : str = "text"
59
-
60
- def set_schema (
61
- self , schemafile : str | None , builtin_schema : str | None , check_metaschema : bool
62
- ) -> None :
63
- mutex_arg_count = sum (
64
- 1 if x else 0 for x in (schemafile , builtin_schema , check_metaschema )
65
- )
66
- if mutex_arg_count == 0 :
67
- raise click .UsageError (
68
- "Either --schemafile, --builtin-schema, or --check-metaschema "
69
- "must be provided"
70
- )
71
- if mutex_arg_count > 1 :
72
- raise click .UsageError (
73
- "--schemafile, --builtin-schema, and --check-metaschema "
74
- "are mutually exclusive"
75
- )
76
-
77
- if schemafile :
78
- self .schema_mode = SchemaLoadingMode .filepath
79
- self .schema_path = schemafile
80
- elif builtin_schema :
81
- self .schema_mode = SchemaLoadingMode .builtin
82
- self .schema_path = builtin_schema
83
- else :
84
- self .schema_mode = SchemaLoadingMode .metaschema
85
-
86
- @property
87
- def format_opts (self ) -> FormatOptions :
88
- return FormatOptions (
89
- enabled = not self .disable_format , regex_behavior = self .format_regex
90
- )
91
-
92
-
93
33
def set_color_mode (ctx : click .Context , param : str , value : str ) -> None :
94
34
if "NO_COLOR" in os .environ :
95
35
ctx .color = False
@@ -101,15 +41,30 @@ def set_color_mode(ctx: click.Context, param: str, value: str) -> None:
101
41
}[value ]
102
42
103
43
44
+ def pretty_helptext_list (values : list [str ] | tuple [str , ...]) -> str :
45
+ return textwrap .indent (
46
+ "\n " .join (
47
+ textwrap .wrap (
48
+ ", " .join (values ),
49
+ width = 75 ,
50
+ break_long_words = False ,
51
+ break_on_hyphens = False ,
52
+ ),
53
+ ),
54
+ " " ,
55
+ )
56
+
57
+
104
58
@click .command (
105
59
"check-jsonschema" ,
106
60
help = """\
107
61
Check JSON and YAML files against a JSON Schema.
108
62
109
63
The schema is specified either with '--schemafile' or with '--builtin-schema'.
110
64
111
- 'check-jsonschema' supports and checks the following formats by default:
112
- date, email, ipv4, regex, uuid
65
+ 'check-jsonschema' supports format checks with appropriate libraries installed,
66
+ including the following formats by default:
67
+ date, email, ipv4, ipv6, regex, uuid
113
68
114
69
\b
115
70
For the "regex" format, there are multiple modes which can be specified with
@@ -121,17 +76,13 @@ def set_color_mode(ctx: click.Context, param: str, value: str) -> None:
121
76
\b
122
77
The '--builtin-schema' flag supports the following schema names:
123
78
"""
124
- + textwrap .indent (
125
- "\n " .join (
126
- textwrap .wrap (
127
- ", " .join (BUILTIN_SCHEMA_NAMES ),
128
- width = 75 ,
129
- break_long_words = False ,
130
- break_on_hyphens = False ,
131
- ),
132
- ),
133
- " " ,
134
- ),
79
+ + pretty_helptext_list (BUILTIN_SCHEMA_NAMES )
80
+ + """\
81
+
82
+ \b
83
+ The '--disable-formats' flag supports the following formats:
84
+ """
85
+ + pretty_helptext_list (KNOWN_FORMATS ),
135
86
)
136
87
@click .help_option ("-h" , "--help" )
137
88
@click .version_option ()
@@ -170,13 +121,29 @@ def set_color_mode(ctx: click.Context, param: str, value: str) -> None:
170
121
),
171
122
)
172
123
@click .option (
173
- "--disable-format" , is_flag = True , help = "Disable all format checks in the schema."
124
+ "--disable-format" ,
125
+ is_flag = True ,
126
+ help = "{deprecated} Disable all format checks in the schema." ,
127
+ callback = deprecation_warning_callback (
128
+ "--disable-format" ,
129
+ is_flag = True ,
130
+ append_message = "Users should now pass '--disable-formats \" *\" ' for "
131
+ "the same functionality." ,
132
+ ),
133
+ )
134
+ @click .option (
135
+ "--disable-formats" ,
136
+ multiple = True ,
137
+ help = "Disable specific format checks in the schema. "
138
+ "Pass '*' to disable all format checks." ,
139
+ type = CommaDelimitedList (choices = ("*" , * KNOWN_FORMATS )),
140
+ metavar = "{*|FORMAT,FORMAT,...}" ,
174
141
)
175
142
@click .option (
176
143
"--format-regex" ,
177
144
help = (
178
145
"Set the mode of format validation for regexes. "
179
- "If ' --disable-format' is used, this option has no effect."
146
+ "If ` --disable-formats regex` is used, this option has no effect."
180
147
),
181
148
default = RegexFormatBehavior .default .value ,
182
149
type = click .Choice ([x .value for x in RegexFormatBehavior ], case_sensitive = False ),
@@ -249,6 +216,7 @@ def main(
249
216
no_cache : bool ,
250
217
cache_filename : str | None ,
251
218
disable_format : bool ,
219
+ disable_formats : tuple [list [str ], ...],
252
220
format_regex : str ,
253
221
default_filetype : str ,
254
222
traceback_mode : str ,
@@ -264,7 +232,13 @@ def main(
264
232
args .set_schema (schemafile , builtin_schema , check_metaschema )
265
233
args .instancefiles = instancefiles
266
234
267
- args .disable_format = disable_format
235
+ normalized_disable_formats : tuple [str , ...] = tuple (
236
+ f for sublist in disable_formats for f in sublist
237
+ )
238
+ if disable_format or "*" in normalized_disable_formats :
239
+ args .disable_all_formats = True
240
+ else :
241
+ args .disable_formats = normalized_disable_formats
268
242
args .format_regex = RegexFormatBehavior (format_regex )
269
243
args .disable_cache = no_cache
270
244
args .default_filetype = default_filetype
0 commit comments