summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Berman <Julian@GrayVines.com>2020-03-04 17:12:02 +0200
committerJulian Berman <Julian@GrayVines.com>2020-11-22 21:01:02 -0500
commit521a02ca42b3c970531ac47ac524141949d42f25 (patch)
treef5dfd0965d264e56cecd6c84a3dd725cd891b2d0
parente5b0127d2c48ae4712b1baa27c077cd5147778b6 (diff)
downloadjsonschema-draft2019-09.tar.gz
-rw-r--r--README.rst1
-rw-r--r--docs/errors.rst8
-rw-r--r--docs/faq.rst14
-rw-r--r--docs/validate.rst4
-rw-r--r--jsonschema/__init__.py2
-rw-r--r--jsonschema/_format.py14
-rw-r--r--jsonschema/_types.py2
-rw-r--r--jsonschema/schemas/draft2019-09.json42
-rw-r--r--jsonschema/tests/test_jsonschema_test_suite.py71
-rw-r--r--jsonschema/validators.py44
10 files changed, 185 insertions, 17 deletions
diff --git a/README.rst b/README.rst
index 2ad096e..6d3a129 100644
--- a/README.rst
+++ b/README.rst
@@ -57,6 +57,7 @@ Features
--------
* Full support for
+ `Draft 2019-09 <https://python-jsonschema.readthedocs.io/en/latest/validate/#jsonschema.Draft201909Validator>`_,
`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>`_
diff --git a/docs/errors.rst b/docs/errors.rst
index 2b2f485..dbcecc0 100644
--- a/docs/errors.rst
+++ b/docs/errors.rst
@@ -140,7 +140,7 @@ These attributes can be clarified with a short example:
}
}
instance = [{}, 3, "foo"]
- v = Draft7Validator(schema)
+ v = Draft201909Validator(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.
@@ -350,14 +350,14 @@ to guess the most relevant error in a given bunch.
.. doctest::
- >>> from jsonschema import Draft7Validator
+ >>> from jsonschema import Draft201909Validator
>>> from jsonschema.exceptions import best_match
>>> schema = {
... "type": "array",
... "minItems": 3,
... }
- >>> print(best_match(Draft7Validator(schema).iter_errors(11)).message)
+ >>> print(best_match(Draft201909Validator(schema).iter_errors(11)).message)
11 is not of type 'array'
@@ -395,7 +395,7 @@ to guess the most relevant error in a given bunch.
... },
... }
>>> instance = {"name": 123, "phones": {"home": [123]}}
- >>> errors = Draft7Validator(schema).iter_errors(instance)
+ >>> errors = Draft201909Validator(schema).iter_errors(instance)
>>> [
... e.path[-1]
... for e in sorted(errors, key=exceptions.relevance)
diff --git a/docs/faq.rst b/docs/faq.rst
index 154ed90..b4093a5 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -98,7 +98,7 @@ be valid under the schema.)
.. code-block:: python
- from jsonschema import Draft7Validator, validators
+ from jsonschema import Draft201909Validator, validators
def extend_with_default(validator_class):
@@ -119,7 +119,9 @@ be valid under the schema.)
)
- DefaultValidatingDraft7Validator = extend_with_default(Draft7Validator)
+ DefaultValidatingDraft201909Validator = extend_with_default(
+ Draft201909Validator,
+ )
# Example usage:
@@ -127,13 +129,13 @@ be valid under the schema.)
schema = {'properties': {'foo': {'default': 'bar'}}}
# Note jsonschem.validate(obj, schema, cls=DefaultValidatingDraft7Validator)
# will not work because the metaschema contains `default` directives.
- DefaultValidatingDraft7Validator(schema).validate(obj)
+ DefaultValidatingDraft201909Validator(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.Draft7Validator` to then go ahead and update all the
+a `jsonschema.Draft201909Validator` to then go ahead and update all the
defaults.
.. note::
@@ -170,7 +172,7 @@ defaults.
}
obj = {}
- DefaultValidatingDraft7Validator(schema).validate(obj)
+ DefaultValidatingDraft201909Validator(schema).validate(obj)
assert obj == {'outer-object': {'inner-object': 'INNER-DEFAULT'}}
...but if you don't provide a default value for your object, then
@@ -181,7 +183,7 @@ defaults.
del schema["properties"]["outer-object"]["default"]
obj2 = {}
- DefaultValidatingDraft7Validator(schema).validate(obj2)
+ DefaultValidatingDraft201909Validator(schema).validate(obj2)
assert obj2 == {} # whoops
diff --git a/docs/validate.rst b/docs/validate.rst
index dc46017..612c2bd 100644
--- a/docs/validate.rst
+++ b/docs/validate.rst
@@ -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:: Draft201909Validator
+
.. autoclass:: Draft7Validator
.. autoclass:: Draft6Validator
@@ -281,7 +283,7 @@ validation can be enabled by hooking in a format-checking object into an
>>> validate(
... instance="-12",
... schema={"format" : "ipv4"},
- ... format_checker=draft7_format_checker,
+ ... format_checker=draft201909_format_checker,
... )
Traceback (most recent call last):
...
diff --git a/jsonschema/__init__.py b/jsonschema/__init__.py
index 619a7ea..6fa7a83 100644
--- a/jsonschema/__init__.py
+++ b/jsonschema/__init__.py
@@ -14,6 +14,7 @@ from jsonschema._format import (
draft4_format_checker,
draft6_format_checker,
draft7_format_checker,
+ draft201909_format_checker,
)
from jsonschema._types import TypeChecker
from jsonschema.exceptions import (
@@ -28,6 +29,7 @@ from jsonschema.validators import (
Draft4Validator,
Draft6Validator,
Draft7Validator,
+ Draft201909Validator,
RefResolver,
validate,
)
diff --git a/jsonschema/_format.py b/jsonschema/_format.py
index 6d9be51..be5afc5 100644
--- a/jsonschema/_format.py
+++ b/jsonschema/_format.py
@@ -131,6 +131,7 @@ draft3_format_checker = FormatChecker()
draft4_format_checker = FormatChecker()
draft6_format_checker = FormatChecker()
draft7_format_checker = FormatChecker()
+draft201909_format_checker = FormatChecker()
_draft_checkers = dict(
@@ -138,6 +139,7 @@ _draft_checkers = dict(
draft4=draft4_format_checker,
draft6=draft6_format_checker,
draft7=draft7_format_checker,
+ draft201909=draft7_format_checker,
)
@@ -147,12 +149,14 @@ def _checks_drafts(
draft4=None,
draft6=None,
draft7=None,
+ draft201909=None,
raises=(),
):
draft3 = draft3 or name
draft4 = draft4 or name
draft6 = draft6 or name
draft7 = draft7 or name
+ draft201909 = draft201909 or name
def wrap(func):
if draft3:
@@ -163,13 +167,17 @@ def _checks_drafts(
func = _draft_checkers["draft6"].checks(draft6, raises)(func)
if draft7:
func = _draft_checkers["draft7"].checks(draft7, raises)(func)
+ if draft201909:
+ func = _draft_checkers["draft201909"].checks(draft201909, raises)(
+ func,
+ )
# Oy. This is bad global state, but relied upon for now, until
# deprecation. See https://github.com/Julian/jsonschema/issues/519
# and test_format_checkers_come_with_defaults
- FormatChecker.cls_checks(draft7 or draft6 or draft4 or draft3, raises)(
- func,
- )
+ FormatChecker.cls_checks(
+ draft201909 or draft7 or draft6 or draft4 or draft3, raises,
+ )(func)
return func
return wrap
diff --git a/jsonschema/_types.py b/jsonschema/_types.py
index 50bcf99..5473023 100644
--- a/jsonschema/_types.py
+++ b/jsonschema/_types.py
@@ -184,4 +184,4 @@ draft6_type_checker = draft4_type_checker.redefine(
isinstance(instance, float) and instance.is_integer()
),
)
-draft7_type_checker = draft6_type_checker
+draft201909_type_checker = draft7_type_checker = draft6_type_checker
diff --git a/jsonschema/schemas/draft2019-09.json b/jsonschema/schemas/draft2019-09.json
new file mode 100644
index 0000000..2248a0c
--- /dev/null
+++ b/jsonschema/schemas/draft2019-09.json
@@ -0,0 +1,42 @@
+{
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "https://json-schema.org/draft/2019-09/schema",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2019-09/vocab/core": true,
+ "https://json-schema.org/draft/2019-09/vocab/applicator": true,
+ "https://json-schema.org/draft/2019-09/vocab/validation": true,
+ "https://json-schema.org/draft/2019-09/vocab/meta-data": true,
+ "https://json-schema.org/draft/2019-09/vocab/format": false,
+ "https://json-schema.org/draft/2019-09/vocab/content": true
+ },
+ "$recursiveAnchor": true,
+
+ "title": "Core and Validation specifications meta-schema",
+ "allOf": [
+ {"$ref": "meta/core"},
+ {"$ref": "meta/applicator"},
+ {"$ref": "meta/validation"},
+ {"$ref": "meta/meta-data"},
+ {"$ref": "meta/format"},
+ {"$ref": "meta/content"}
+ ],
+ "type": ["object", "boolean"],
+ "properties": {
+ "definitions": {
+ "$comment": "While no longer an official keyword as it is replaced by $defs, this keyword is retained in the meta-schema to prevent incompatible extensions as it remains in common use.",
+ "type": "object",
+ "additionalProperties": { "$recursiveRef": "#" },
+ "default": {}
+ },
+ "dependencies": {
+ "$comment": "\"dependencies\" is no longer a keyword, but schema authors should avoid redefining it to facilitate a smooth transition to \"dependentSchemas\" and \"dependentRequired\"",
+ "type": "object",
+ "additionalProperties": {
+ "anyOf": [
+ { "$recursiveRef": "#" },
+ { "$ref": "meta/validation#/$defs/stringArray" }
+ ]
+ }
+ }
+ }
+}
diff --git a/jsonschema/tests/test_jsonschema_test_suite.py b/jsonschema/tests/test_jsonschema_test_suite.py
index 26e4345..2bce015 100644
--- a/jsonschema/tests/test_jsonschema_test_suite.py
+++ b/jsonschema/tests/test_jsonschema_test_suite.py
@@ -14,10 +14,12 @@ from jsonschema import (
Draft4Validator,
Draft6Validator,
Draft7Validator,
+ Draft201909Validator,
draft3_format_checker,
draft4_format_checker,
draft6_format_checker,
draft7_format_checker,
+ draft201909_format_checker,
)
from jsonschema.tests._helpers import bug
from jsonschema.tests._suite import Suite
@@ -28,6 +30,7 @@ DRAFT3 = SUITE.version(name="draft3")
DRAFT4 = SUITE.version(name="draft4")
DRAFT6 = SUITE.version(name="draft6")
DRAFT7 = SUITE.version(name="draft7")
+DRAFT201909 = SUITE.version(name="draft2019-09")
def skip(message, **kwargs):
@@ -446,6 +449,74 @@ TestDraft7 = DRAFT7.to_unittest_testcase(
)
+TestDraft201909 = DRAFT201909.to_unittest_testcase(
+ DRAFT201909.tests(),
+ DRAFT201909.format_tests(),
+ DRAFT201909.optional_tests_of(name="bignum"),
+ DRAFT201909.optional_tests_of(name="content"),
+ DRAFT201909.optional_tests_of(name="zeroTerminatedFloats"),
+ Validator=Draft201909Validator,
+ format_checker=draft201909_format_checker,
+ # skip=lambda test: (
+ # narrow_unicode_build(test)
+ # or missing_format(draft201909_format_checker)(test)
+ # or skip(
+ # message=bug(),
+ # subject="ref",
+ # case_description="Recursive references between schemas",
+ # )(test)
+ # or skip(
+ # message=bug(32019091),
+ # subject="ref",
+ # case_description="Location-independent identifier",
+ # )(test)
+ # or skip(
+ # message=bug(32019091),
+ # subject="ref",
+ # case_description=(
+ # "Location-independent identifier with absolute URI"
+ # ),
+ # )(test)
+ # or skip(
+ # message=bug(32019091),
+ # subject="ref",
+ # case_description=(
+ # "Location-independent identifier with base URI change in subschema"
+ # ),
+ # )(test)
+ # or skip(
+ # message=bug(),
+ # subject="refRemote",
+ # case_description="base URI change - change folder in subschema",
+ # )(test)
+ # or skip(
+ # message="Upstream bug in strict_rfc3339",
+ # subject="date-time",
+ # description="case-insensitive T and Z",
+ # )(test)
+ # or skip(
+ # message=bug(593),
+ # subject="content",
+ # case_description=(
+ # "validation of string-encoded content based on media type"
+ # ),
+ # )(test)
+ # or skip(
+ # message=bug(593),
+ # subject="content",
+ # case_description="validation of binary string-encoding",
+ # )(test)
+ # or skip(
+ # message=bug(593),
+ # subject="content",
+ # case_description=(
+ # "validation of binary-encoded media type documents"
+ # ),
+ # )(test)
+ # ),
+)
+
+
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
diff --git a/jsonschema/validators.py b/jsonschema/validators.py
index d6e0a0c..c6f1e56 100644
--- a/jsonschema/validators.py
+++ b/jsonschema/validators.py
@@ -573,7 +573,47 @@ Draft7Validator = create(
version="draft7",
)
-_LATEST_VERSION = Draft7Validator
+Draft201909Validator = create(
+ meta_schema=_utils.load_schema("draft2019-09"),
+ type_checker=_types.draft201909_type_checker,
+ version="draft2019-09",
+ validators={
+ u"$ref": _validators.ref,
+ u"additionalItems": _validators.additionalItems,
+ u"additionalProperties": _validators.additionalProperties,
+ u"allOf": _validators.allOf,
+ u"anyOf": _validators.anyOf,
+ u"const": _validators.const,
+ u"contains": _validators.contains,
+ u"dependencies": _validators.dependencies,
+ u"enum": _validators.enum,
+ u"exclusiveMaximum": _validators.exclusiveMaximum,
+ u"exclusiveMinimum": _validators.exclusiveMinimum,
+ u"format": _validators.format,
+ u"if": _validators.if_,
+ u"items": _validators.items,
+ u"maxItems": _validators.maxItems,
+ u"maxLength": _validators.maxLength,
+ u"maxProperties": _validators.maxProperties,
+ u"maximum": _validators.maximum,
+ u"minItems": _validators.minItems,
+ u"minLength": _validators.minLength,
+ u"minProperties": _validators.minProperties,
+ u"minimum": _validators.minimum,
+ u"multipleOf": _validators.multipleOf,
+ u"oneOf": _validators.oneOf,
+ u"not": _validators.not_,
+ u"pattern": _validators.pattern,
+ u"patternProperties": _validators.patternProperties,
+ u"properties": _validators.properties,
+ u"propertyNames": _validators.propertyNames,
+ u"required": _validators.required,
+ u"type": _validators.type,
+ u"uniqueItems": _validators.uniqueItems,
+ },
+)
+
+_LATEST_VERSION = Draft201909Validator
class RefResolver(object):
@@ -871,7 +911,7 @@ def validate(instance, schema, cls=None, *args, **kwargs):
If you know you have a valid schema already, especially if you
intend to validate multiple instances with the same schema, you
likely would prefer using the `IValidator.validate` method directly
- on a specific validator (e.g. ``Draft7Validator.validate``).
+ on a specific validator (e.g. ``Draft201909Validator.validate``).
Arguments: