From 0d251ba8b5438bd9700fc43bcb240e7daa5bd339 Mon Sep 17 00:00:00 2001 From: Dmitry Dygalo Date: Tue, 1 Sep 2020 23:35:29 +0200 Subject: [PATCH] Use a validator that corresponds to the input schema draft version --- CHANGELOG.md | 2 ++ src/hypothesis_jsonschema/_canonicalise.py | 31 ++++++++++++++-------- src/hypothesis_jsonschema/_from_schema.py | 2 +- tests/test_canonicalise.py | 15 +++++++++++ 4 files changed, 38 insertions(+), 12 deletions(-) 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/src/hypothesis_jsonschema/_from_schema.py b/src/hypothesis_jsonschema/_from_schema.py index 5584104..1a2827d 100644 --- a/src/hypothesis_jsonschema/_from_schema.py +++ b/src/hypothesis_jsonschema/_from_schema.py @@ -306,7 +306,7 @@ def regex_patterns(draw: Any) -> str: assert isinstance(result, str) try: re.compile(result) - except (re.error, FutureWarning): + except re.error: assume(False) return result 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