diff --git a/CHANGELOG.md b/CHANGELOG.md index 47b3f54..74c3ad5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +- Use a validator that corresponds to the input schema draft version (#66) + #### 0.17.4 - 2020-08-26 - fixed string schemas with different `format` keywords (#63) diff --git a/src/hypothesis_jsonschema/_canonicalise.py b/src/hypothesis_jsonschema/_canonicalise.py index 08e3050..b73f169 100644 --- a/src/hypothesis_jsonschema/_canonicalise.py +++ b/src/hypothesis_jsonschema/_canonicalise.py @@ -29,6 +29,12 @@ # (and writing a few steps by hand is a DoS attack on the AST walker in Pytest) JSONType = Union[None, bool, float, str, list, Dict[str, Any]] Schema = Dict[str, JSONType] +JSONSchemaValidator = Union[ + jsonschema.validators.Draft3Validator, + jsonschema.validators.Draft4Validator, + jsonschema.validators.Draft6Validator, + jsonschema.validators.Draft7Validator, +] # Canonical type strings, in order. TYPE_STRINGS = ("null", "boolean", "integer", "number", "string", "array", "object") @@ -66,16 +72,19 @@ def next_down(val: float) -> float: return out -def make_validator( - schema: Schema, -) -> Union[ - jsonschema.validators.Draft3Validator, - jsonschema.validators.Draft4Validator, - jsonschema.validators.Draft6Validator, - jsonschema.validators.Draft7Validator, -]: - validator_cls = jsonschema.validators.validator_for(schema) - return validator_cls(schema) +def _get_validator_class(schema: Schema) -> JSONSchemaValidator: + try: + validator = jsonschema.validators.validator_for(schema) + validator.check_schema(schema) + except jsonschema.exceptions.SchemaError: + validator = jsonschema.Draft4Validator + validator.check_schema(schema) + return validator + + +def make_validator(schema: Schema) -> JSONSchemaValidator: + validator = _get_validator_class(schema) + return validator(schema) class CanonicalisingJsonEncoder(json.JSONEncoder): @@ -888,7 +897,7 @@ def merged(schemas: List[Any]) -> Optional[Schema]: if out == FALSEY: return FALSEY assert isinstance(out, dict) - jsonschema.validators.validator_for(out).check_schema(out) + _get_validator_class(out) return out diff --git a/tests/test_canonicalise.py b/tests/test_canonicalise.py index a79bcc4..0cfecf5 100644 --- a/tests/test_canonicalise.py +++ b/tests/test_canonicalise.py @@ -521,6 +521,21 @@ def test_canonicalise_is_only_valid_for_schemas(): canonicalish("not a schema") +def test_validators_use_proper_draft(): + # See GH-66 + schema = { + "$schema": "http://json-schema.org/draft-04/schema#", + "not": { + "allOf": [ + {"exclusiveMinimum": True, "minimum": 0}, + {"exclusiveMaximum": True, "maximum": 10}, + ] + }, + } + cc = canonicalish(schema) + jsonschema.validators.validator_for(cc).check_schema(cc) + + # Expose fuzz targets in a form that FuzzBuzz can understand (no dotted names) fuzz_canonical_json_encoding = test_canonical_json_encoding.hypothesis.fuzz_one_input fuzz_merge_semantics = test_merge_semantics.hypothesis.fuzz_one_input