Skip to content

Commit

Permalink
First step on Draft7 support.
Browse files Browse the repository at this point in the history
Add everything that's the same in Draft6, which appears to just leave
out if/then/else.
  • Loading branch information
Julian committed Sep 30, 2018
1 parent e0add0e commit 7c16622
Show file tree
Hide file tree
Showing 13 changed files with 298 additions and 21 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
v3.0.0
------

* Support for Draft 6
* Draft 6 is now the default
* Support for Draft 6 and Draft 7
* Draft 7 is now the default
* New ``TypeChecker`` object for more complex type definitions (and overrides)
* Falling back to isodate for the date-time format checker is no longer
attempted, in accordance with the specification
Expand Down
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Features
--------

* Full support for
`Draft 7 <https://python-jsonschema.readthedocs.io/en/latest/validate/#jsonschema.Draft7Validator>`_,
`Draft 6 <https://python-jsonschema.readthedocs.io/en/latest/validate/#jsonschema.Draft6Validator>`_,
`Draft 4 <https://python-jsonschema.readthedocs.io/en/latest/validate/#jsonschema.Draft4Validator>`_
and
Expand Down
8 changes: 4 additions & 4 deletions docs/errors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ These attributes can be clarified with a short example:
}
}
instance = [{}, 3, "foo"]
v = Draft6Validator(schema)
v = Draft7Validator(schema)
errors = sorted(v.iter_errors(instance), key=lambda e: e.path)

The error messages in this situation are not very helpful on their own.
Expand Down Expand Up @@ -347,14 +347,14 @@ to guess the most relevant error in a given bunch.

.. doctest::

>>> from jsonschema import Draft6Validator
>>> from jsonschema import Draft7Validator
>>> from jsonschema.exceptions import best_match

>>> schema = {
... "type": "array",
... "minItems": 3,
... }
>>> print(best_match(Draft6Validator(schema).iter_errors(11)).message)
>>> print(best_match(Draft7Validator(schema).iter_errors(11)).message)
11 is not of type 'array'


Expand Down Expand Up @@ -423,7 +423,7 @@ to guess the most relevant error in a given bunch.
... },
... }
>>> instance = {"name": 123, "phones": {"home": [123]}}
>>> errors = Draft6Validator(schema).iter_errors(instance)
>>> errors = Draft7Validator(schema).iter_errors(instance)
>>> [
... e.path[-1]
... for e in sorted(errors, key=exceptions.relevance)
Expand Down
14 changes: 7 additions & 7 deletions docs/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ themselves will need to be valid under the schema.)

.. code-block:: python
from jsonschema import Draft6Validator, validators
from jsonschema import Draft7Validator, validators
def extend_with_default(validator_class):
Expand All @@ -46,21 +46,21 @@ themselves will need to be valid under the schema.)
)
DefaultValidatingDraft6Validator = extend_with_default(Draft6Validator)
DefaultValidatingDraft7Validator = extend_with_default(Draft7Validator)
# Example usage:
obj = {}
schema = {'properties': {'foo': {'default': 'bar'}}}
# Note jsonschem.validate(obj, schema, cls=DefaultValidatingDraft6Validator)
# Note jsonschem.validate(obj, schema, cls=DefaultValidatingDraft7Validator)
# will not work because the metaschema contains `default` directives.
DefaultValidatingDraft6Validator(schema).validate(obj)
DefaultValidatingDraft7Validator(schema).validate(obj)
assert obj == {'foo': 'bar'}
See the above-linked document for more info on how this works, but
basically, it just extends the :validator:`properties` validator on a
`jsonschema.Draft6Validator` to then go ahead and update all the
`jsonschema.Draft7Validator` to then go ahead and update all the
defaults.

.. note::
Expand Down Expand Up @@ -95,7 +95,7 @@ defaults.
}
obj = {}
DefaultValidatingDraft6Validator(schema).validate(obj)
DefaultValidatingDraft7Validator(schema).validate(obj)
assert obj == {'outer-object': {'inner-object': 'INNER-DEFAULT'}}
...but if you don't provide a default value for your object,
Expand All @@ -105,7 +105,7 @@ defaults.
del schema["properties"]["outer-object"]["default"]
obj2 = {}
DefaultValidatingDraft6Validator(schema).validate(obj2)
DefaultValidatingDraft7Validator(schema).validate(obj2)
assert obj2 == {} # whoops
Expand Down
2 changes: 2 additions & 0 deletions docs/validate.rst
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ the JSON Schema specification. For details on the methods and attributes
that each validator class provides see the `IValidator` interface,
which each included validator class implements.

.. autoclass:: Draft7Validator

.. autoclass:: Draft6Validator

.. autoclass:: Draft4Validator
Expand Down
2 changes: 2 additions & 0 deletions jsonschema/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
draft3_format_checker,
draft4_format_checker,
draft6_format_checker,
draft7_format_checker,
)
from jsonschema._types import TypeChecker
from jsonschema.validators import (
Draft3Validator,
Draft4Validator,
Draft6Validator,
Draft7Validator,
RefResolver,
validate,
)
Expand Down
8 changes: 7 additions & 1 deletion jsonschema/_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,19 +129,21 @@ def conforms(self, instance, format):
return True


_draft_checkers = {"draft3": [], "draft4": [], "draft6": []}
_draft_checkers = {"draft3": [], "draft4": [], "draft6": [], "draft7": []}


def _checks_drafts(
name=None,
draft3=None,
draft4=None,
draft6=None,
draft7=None,
raises=(),
):
draft3 = draft3 or name
draft4 = draft4 or name
draft6 = draft6 or name
draft7 = draft7 or name

def wrap(func):
if draft3:
Expand All @@ -153,6 +155,9 @@ def wrap(func):
if draft6:
_draft_checkers["draft6"].append(draft6)
func = FormatChecker.cls_checks(draft6, raises)(func)
if draft7:
_draft_checkers["draft7"].append(draft7)
func = FormatChecker.cls_checks(draft7, raises)(func)
return func
return wrap

Expand Down Expand Up @@ -307,3 +312,4 @@ def is_uri_template(
draft3_format_checker = FormatChecker(_draft_checkers["draft3"])
draft4_format_checker = FormatChecker(_draft_checkers["draft4"])
draft6_format_checker = FormatChecker(_draft_checkers["draft6"])
draft7_format_checker = FormatChecker(_draft_checkers["draft7"])
1 change: 1 addition & 0 deletions jsonschema/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,4 @@ def remove(self, *types):
isinstance(instance, float) and instance.is_integer()
),
)
draft7_type_checker = draft6_type_checker
2 changes: 1 addition & 1 deletion jsonschema/benchmarks/issue232.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
path=FilePath(__file__).sibling("issue232"),
remotes=m(),
name="issue232",
validator=jsonschema.Draft6Validator,
validator=jsonschema.Draft7Validator,
)


Expand Down
168 changes: 168 additions & 0 deletions jsonschema/schemas/draft7.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://json-schema.org/draft-07/schema#",
"title": "Core schema meta-schema",
"definitions": {
"schemaArray": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#" }
},
"nonNegativeInteger": {
"type": "integer",
"minimum": 0
},
"nonNegativeIntegerDefault0": {
"allOf": [
{ "$ref": "#/definitions/nonNegativeInteger" },
{ "default": 0 }
]
},
"simpleTypes": {
"enum": [
"array",
"boolean",
"integer",
"null",
"number",
"object",
"string"
]
},
"stringArray": {
"type": "array",
"items": { "type": "string" },
"uniqueItems": true,
"default": []
}
},
"type": ["object", "boolean"],
"properties": {
"$id": {
"type": "string",
"format": "uri-reference"
},
"$schema": {
"type": "string",
"format": "uri"
},
"$ref": {
"type": "string",
"format": "uri-reference"
},
"$comment": {
"type": "string"
},
"title": {
"type": "string"
},
"description": {
"type": "string"
},
"default": true,
"readOnly": {
"type": "boolean",
"default": false
},
"examples": {
"type": "array",
"items": true
},
"multipleOf": {
"type": "number",
"exclusiveMinimum": 0
},
"maximum": {
"type": "number"
},
"exclusiveMaximum": {
"type": "number"
},
"minimum": {
"type": "number"
},
"exclusiveMinimum": {
"type": "number"
},
"maxLength": { "$ref": "#/definitions/nonNegativeInteger" },
"minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" },
"pattern": {
"type": "string",
"format": "regex"
},
"additionalItems": { "$ref": "#" },
"items": {
"anyOf": [
{ "$ref": "#" },
{ "$ref": "#/definitions/schemaArray" }
],
"default": true
},
"maxItems": { "$ref": "#/definitions/nonNegativeInteger" },
"minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" },
"uniqueItems": {
"type": "boolean",
"default": false
},
"contains": { "$ref": "#" },
"maxProperties": { "$ref": "#/definitions/nonNegativeInteger" },
"minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" },
"required": { "$ref": "#/definitions/stringArray" },
"additionalProperties": { "$ref": "#" },
"definitions": {
"type": "object",
"additionalProperties": { "$ref": "#" },
"default": {}
},
"properties": {
"type": "object",
"additionalProperties": { "$ref": "#" },
"default": {}
},
"patternProperties": {
"type": "object",
"additionalProperties": { "$ref": "#" },
"propertyNames": { "format": "regex" },
"default": {}
},
"dependencies": {
"type": "object",
"additionalProperties": {
"anyOf": [
{ "$ref": "#" },
{ "$ref": "#/definitions/stringArray" }
]
}
},
"propertyNames": { "$ref": "#" },
"const": true,
"enum": {
"type": "array",
"items": true,
"minItems": 1,
"uniqueItems": true
},
"type": {
"anyOf": [
{ "$ref": "#/definitions/simpleTypes" },
{
"type": "array",
"items": { "$ref": "#/definitions/simpleTypes" },
"minItems": 1,
"uniqueItems": true
}
]
},
"format": { "type": "string" },
"contentMediaType": { "type": "string" },
"contentEncoding": { "type": "string" },
"if": {"$ref": "#"},
"then": {"$ref": "#"},
"else": {"$ref": "#"},
"allOf": { "$ref": "#/definitions/schemaArray" },
"anyOf": { "$ref": "#/definitions/schemaArray" },
"oneOf": { "$ref": "#/definitions/schemaArray" },
"not": { "$ref": "#" }
},
"default": true
}
Loading

0 comments on commit 7c16622

Please sign in to comment.