4
4
from __future__ import annotations
5
5
6
6
from collections import deque
7
- from collections .abc import Mapping , Sequence
7
+ from collections .abc import Iterable , Mapping , Sequence
8
8
from functools import lru_cache
9
9
from operator import methodcaller
10
10
from urllib .parse import unquote , urldefrag , urljoin , urlsplit
15
15
import reprlib
16
16
import warnings
17
17
18
+ from attrs import define , field , fields
18
19
from jsonschema_specifications import REGISTRY as SPECIFICATIONS
19
20
from referencing import Specification
20
21
from rpds import HashTrieMap
21
- import attr
22
22
import referencing .jsonschema
23
23
24
24
from jsonschema import (
25
25
_format ,
26
26
_legacy_validators ,
27
27
_types ,
28
+ _typing ,
28
29
_utils ,
29
30
_validators ,
30
31
exceptions ,
@@ -102,24 +103,29 @@ def _validates(cls):
102
103
103
104
104
105
def create (
105
- meta_schema ,
106
- validators = (),
107
- version = None ,
108
- type_checker = _types .draft202012_type_checker ,
109
- format_checker = _format .draft202012_format_checker ,
110
- id_of = referencing .jsonschema .DRAFT202012 .id_of ,
111
- applicable_validators = methodcaller ("items" ),
106
+ meta_schema : referencing .jsonschema .ObjectSchema ,
107
+ validators : (
108
+ Mapping [str , _typing .SchemaKeywordValidator ]
109
+ | Iterable [tuple [str , _typing .SchemaKeywordValidator ]]
110
+ ) = (),
111
+ version : str | None = None ,
112
+ type_checker : _types .TypeChecker = _types .draft202012_type_checker ,
113
+ format_checker : _format .FormatChecker = _format .draft202012_format_checker ,
114
+ id_of : _typing .id_of = referencing .jsonschema .DRAFT202012 .id_of ,
115
+ applicable_validators : _typing .ApplicableValidators = methodcaller (
116
+ "items" ,
117
+ ),
112
118
):
113
119
"""
114
120
Create a new validator class.
115
121
116
122
Arguments:
117
123
118
- meta_schema (collections.abc.Mapping) :
124
+ meta_schema:
119
125
120
126
the meta schema for the new validator class
121
127
122
- validators (collections.abc.Mapping) :
128
+ validators:
123
129
124
130
a mapping from names to callables, where each callable will
125
131
validate the schema property with the given name.
@@ -132,37 +138,42 @@ def create(
132
138
3. the instance
133
139
4. the schema
134
140
135
- version (str) :
141
+ version:
136
142
137
143
an identifier for the version that this validator class will
138
144
validate. If provided, the returned validator class will
139
145
have its ``__name__`` set to include the version, and also
140
146
will have `jsonschema.validators.validates` automatically
141
147
called for the given version.
142
148
143
- type_checker (jsonschema.TypeChecker) :
149
+ type_checker:
144
150
145
151
a type checker, used when applying the :kw:`type` keyword.
146
152
147
153
If unprovided, a `jsonschema.TypeChecker` will be created
148
154
with a set of default types typical of JSON Schema drafts.
149
155
150
- format_checker (jsonschema.FormatChecker) :
156
+ format_checker:
151
157
152
158
a format checker, used when applying the :kw:`format` keyword.
153
159
154
160
If unprovided, a `jsonschema.FormatChecker` will be created
155
161
with a set of default formats typical of JSON Schema drafts.
156
162
157
- id_of (collections.abc.Callable) :
163
+ id_of:
158
164
159
165
A function that given a schema, returns its ID.
160
166
161
- applicable_validators (collections.abc.Callable) :
167
+ applicable_validators:
162
168
163
- A function that given a schema, returns the list of
164
- applicable validators (validation keywords and callables)
169
+ A function that, given a schema, returns the list of
170
+ applicable schema keywords and associated values
165
171
which will be used to validate the instance.
172
+ This is mostly used to support pre-draft 7 versions of JSON Schema
173
+ which specified behavior around ignoring keywords if they were
174
+ siblings of a ``$ref`` keyword. If you're not attempting to
175
+ implement similar behavior, you can typically ignore this argument
176
+ and leave it at its default.
166
177
167
178
Returns:
168
179
@@ -176,7 +187,7 @@ def create(
176
187
default = Specification .OPAQUE ,
177
188
)
178
189
179
- @attr . s
190
+ @define
180
191
class Validator :
181
192
182
193
VALIDATORS = dict (validators )
@@ -185,17 +196,17 @@ class Validator:
185
196
FORMAT_CHECKER = format_checker_arg
186
197
ID_OF = staticmethod (id_of )
187
198
188
- schema = attr . ib (repr = reprlib .repr )
189
- _ref_resolver = attr . ib (default = None , repr = False , alias = "resolver" )
190
- format_checker = attr . ib (default = None )
199
+ schema : referencing . jsonschema . Schema = field (repr = reprlib .repr )
200
+ _ref_resolver = field (default = None , repr = False , alias = "resolver" )
201
+ format_checker : _format . FormatChecker | None = field (default = None )
191
202
# TODO: include new meta-schemas added at runtime
192
- _registry = attr . ib (
203
+ _registry : referencing . jsonschema . SchemaRegistry = field (
193
204
default = SPECIFICATIONS ,
194
205
converter = SPECIFICATIONS .combine , # type: ignore[misc]
195
206
kw_only = True ,
196
207
repr = False ,
197
208
)
198
- _resolver = attr . ib (
209
+ _resolver = field (
199
210
alias = "_resolver" ,
200
211
default = None ,
201
212
kw_only = True ,
@@ -222,7 +233,7 @@ def evolve(self, **changes):
222
233
schema = changes .setdefault ("schema" , self .schema )
223
234
NewValidator = validator_for (schema , default = cls )
224
235
225
- for field in attr . fields (cls ):
236
+ for field in fields (cls ): # noqa: F402
226
237
if not field .init :
227
238
continue
228
239
attr_name = field .name
@@ -429,14 +440,14 @@ def is_valid(self, instance, _schema=None):
429
440
430
441
evolve_fields = [
431
442
(field .name , field .alias )
432
- for field in attr . fields (Validator )
443
+ for field in fields (Validator )
433
444
if field .init
434
445
]
435
446
436
447
if version is not None :
437
448
safe = version .title ().replace (" " , "" ).replace ("-" , "" )
438
449
Validator .__name__ = Validator .__qualname__ = f"{ safe } Validator"
439
- Validator = validates (version )(Validator )
450
+ Validator = validates (version )(Validator ) # type: ignore[misc]
440
451
441
452
return Validator
442
453
0 commit comments