Skip to content

Commit

Permalink
Support validator classes whose metaschema uses a different dialect.
Browse files Browse the repository at this point in the history
In other words, one may author validator classes (via
jsonschema.validators.create or extend) whose meta schema defines schema
behavior using JSON Schema draft2020-12 but whose schemas are in its own
dialect.

Said again differently, the set of valid schemas for a validator class
may be governed by one draft, while the schema behavior itself is
governed by another.
  • Loading branch information
Julian committed Aug 19, 2022
1 parent edaf2a1 commit a60a087
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
10 changes: 10 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
v4.13.0
=======

* Add support for creating validator classes whose metaschema uses a different
dialect than its schemas. In other words, they may use draft2020-12 to define
which schemas are valid, but the schemas themselves use draft7 (or a custom
dialect, etc.) to define which *instances* are valid. Doing this is likely
not something most users, even metaschema authors, may need, but occasionally
will be useful for advanced use cases.

v4.12.1
=======

Expand Down
32 changes: 32 additions & 0 deletions jsonschema/tests/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,38 @@ def test_create_default_types(self):
),
)

def test_check_schema_with_different_metaschema(self):
"""
One can create a validator class whose metaschema uses a different
dialect than itself.
"""

NoEmptySchemasValidator = validators.create(
meta_schema={
"$schema": validators.Draft202012Validator.META_SCHEMA["$id"],
"not": {"const": {}},
},
)
NoEmptySchemasValidator.check_schema({"foo": "bar"})

with self.assertRaises(exceptions.SchemaError):
NoEmptySchemasValidator.check_schema({})

NoEmptySchemasValidator({"foo": "bar"}).validate("foo")

def test_check_schema_with_different_metaschema_defaults_to_self(self):
"""
A validator whose metaschema doesn't declare $schema defaults to its
own validation behavior, not the latest "normal" specification.
"""

NoEmptySchemasValidator = validators.create(
meta_schema={"fail": [{"message": "Meta schema whoops!"}]},
validators={"fail": fail},
)
with self.assertRaises(exceptions.SchemaError):
NoEmptySchemasValidator.check_schema({})

def test_extend(self):
original = dict(self.Validator.VALIDATORS)
new = object()
Expand Down
3 changes: 2 additions & 1 deletion jsonschema/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ def __attrs_post_init__(self):

@classmethod
def check_schema(cls, schema):
for error in cls(cls.META_SCHEMA).iter_errors(schema):
Validator = validator_for(cls.META_SCHEMA, default=cls)
for error in Validator(cls.META_SCHEMA).iter_errors(schema):
raise exceptions.SchemaError.create_from(error)

def evolve(self, **changes):
Expand Down

0 comments on commit a60a087

Please sign in to comment.