From bce4cb8dc0b57b2613a4d7239119f8c34ffdbb23 Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Thu, 20 Jul 2023 15:12:17 +0200 Subject: [PATCH] WIP --- jsonschema/_legacy_validators.py | 4 ++-- jsonschema/_validators.py | 4 +++- .../{exceptions.py => exceptions/__init__.py} | 0 jsonschema/exceptions/keywords.py | 11 +++++++++++ jsonschema/tests/test_validators.py | 13 +++++++++++++ 5 files changed, 29 insertions(+), 3 deletions(-) rename jsonschema/{exceptions.py => exceptions/__init__.py} (100%) create mode 100644 jsonschema/exceptions/keywords.py diff --git a/jsonschema/_legacy_validators.py b/jsonschema/_legacy_validators.py index 141f15a09..5cb614851 100644 --- a/jsonschema/_legacy_validators.py +++ b/jsonschema/_legacy_validators.py @@ -1,7 +1,7 @@ from referencing.jsonschema import lookup_recursive_ref from jsonschema import _utils -from jsonschema.exceptions import ValidationError +from jsonschema.exceptions import ValidationError, keywords def ignore_ref_siblings(schema): @@ -160,7 +160,7 @@ def properties_draft3(validator, properties, instance, schema): schema_path=property, ) elif subschema.get("required", False): - error = ValidationError(f"{property!r} is a required property") + error = keywords.Required(property_name=property) error._set( validator="required", validator_value=subschema["required"], diff --git a/jsonschema/_validators.py b/jsonschema/_validators.py index 45b53c9c4..820a79c5b 100644 --- a/jsonschema/_validators.py +++ b/jsonschema/_validators.py @@ -1,6 +1,7 @@ from fractions import Fraction import re +from jsonschema import exceptions from jsonschema._utils import ( ensure_list, equal, @@ -12,6 +13,7 @@ uniq, ) from jsonschema.exceptions import FormatError, ValidationError +import jsonschema.exceptions.keywords # noqa: F401 def patternProperties(validator, patternProperties, instance, schema): @@ -315,7 +317,7 @@ def required(validator, required, instance, schema): return for property in required: if property not in instance: - yield ValidationError(f"{property!r} is a required property") + yield exceptions.keywords.Required(property_name=property) def minProperties(validator, mP, instance, schema): diff --git a/jsonschema/exceptions.py b/jsonschema/exceptions/__init__.py similarity index 100% rename from jsonschema/exceptions.py rename to jsonschema/exceptions/__init__.py diff --git a/jsonschema/exceptions/keywords.py b/jsonschema/exceptions/keywords.py new file mode 100644 index 000000000..9cb37f698 --- /dev/null +++ b/jsonschema/exceptions/keywords.py @@ -0,0 +1,11 @@ +from jsonschema.exceptions import ValidationError + + +class Required(ValidationError): + def __init__(self, property_name): + ValidationError.__init__( + self, + message=f"{property_name!r} is a required property", + ) + + self.property_name = property_name diff --git a/jsonschema/tests/test_validators.py b/jsonschema/tests/test_validators.py index 940a86da4..f638b952d 100644 --- a/jsonschema/tests/test_validators.py +++ b/jsonschema/tests/test_validators.py @@ -24,6 +24,7 @@ protocols, validators, ) +import jsonschema.exceptions.keywords def fail(validator, errors, instance, schema): @@ -1760,6 +1761,18 @@ def test_check_redefined_sequence(self): with self.assertRaises(exceptions.ValidationError): validator.validate(instance) + def test_required_missing(self): + if self.Validator is not validators.Draft3Validator: + schema = {"required": ["a", "b"]} + else: + required = dict(required=True) + schema = {"properties": dict(a=required, b=required)} + validator = self.Validator(schema) + + with self.assertRaises(exceptions.keywords.Required) as e: + validator.validate({"a": 37}) + self.assertEqual(e.exception.property_name, "b") + def test_it_creates_a_ref_resolver_if_not_provided(self): with self.assertWarns(DeprecationWarning): resolver = self.Validator({}).resolver