summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarald Nezbeda <hn@nezhar.com>2021-06-28 14:43:38 +0200
committerHarald Nezbeda <hn@nezhar.com>2021-07-20 17:08:48 +0200
commitbede403b64d5044396af891a40e9670d0d3bb549 (patch)
tree81a84036482d8155f786f700f6c1758717140d7d
parentc380b09ea9aeb9eb3a5c8ac92f0245843b113aa7 (diff)
downloadjsonschema-bede403b64d5044396af891a40e9670d0d3bb549.tar.gz
Julian/jsonschema#782: Resolve meta schema vocabularies from local cache
-rw-r--r--jsonschema/_utils.py16
-rw-r--r--jsonschema/schemas/draft2020-12/applicator.json48
-rw-r--r--jsonschema/schemas/draft2020-12/content.json17
-rw-r--r--jsonschema/schemas/draft2020-12/core.json51
-rw-r--r--jsonschema/schemas/draft2020-12/format-annotation.json14
-rw-r--r--jsonschema/schemas/draft2020-12/meta-data.json37
-rw-r--r--jsonschema/schemas/draft2020-12/unevaluated.json15
-rw-r--r--jsonschema/schemas/draft2020-12/validation.json98
-rw-r--r--jsonschema/validators.py24
-rw-r--r--setup.cfg2
10 files changed, 317 insertions, 5 deletions
diff --git a/jsonschema/_utils.py b/jsonschema/_utils.py
index fa928e6..e963e39 100644
--- a/jsonschema/_utils.py
+++ b/jsonschema/_utils.py
@@ -1,9 +1,12 @@
from collections.abc import Mapping, MutableMapping, Sequence
+from pathlib import Path
from urllib.parse import urlsplit
import itertools
import json
+import os
import pkgutil
import re
+import sys
class URIDict(MutableMapping):
@@ -55,6 +58,19 @@ def load_schema(name):
return json.loads(data.decode("utf-8"))
+def load_vocabulary(name):
+ """
+ Load all schema files from ./schemas/``name`` and return them as a list.
+ """
+ vocabulary = []
+ base_path = os.path.dirname(sys.modules["jsonschema"].__file__)
+ pathlist = Path(os.path.join(base_path, 'schemas', name)).glob('*.json')
+ for path in pathlist:
+ with open(path) as data:
+ vocabulary.append(json.load(data))
+ return vocabulary
+
+
def format_as_index(indices):
"""
Construct a single string containing indexing operations for the indices.
diff --git a/jsonschema/schemas/draft2020-12/applicator.json b/jsonschema/schemas/draft2020-12/applicator.json
new file mode 100644
index 0000000..ca69923
--- /dev/null
+++ b/jsonschema/schemas/draft2020-12/applicator.json
@@ -0,0 +1,48 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://json-schema.org/draft/2020-12/meta/applicator",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2020-12/vocab/applicator": true
+ },
+ "$dynamicAnchor": "meta",
+
+ "title": "Applicator vocabulary meta-schema",
+ "type": ["object", "boolean"],
+ "properties": {
+ "prefixItems": { "$ref": "#/$defs/schemaArray" },
+ "items": { "$dynamicRef": "#meta" },
+ "contains": { "$dynamicRef": "#meta" },
+ "additionalProperties": { "$dynamicRef": "#meta" },
+ "properties": {
+ "type": "object",
+ "additionalProperties": { "$dynamicRef": "#meta" },
+ "default": {}
+ },
+ "patternProperties": {
+ "type": "object",
+ "additionalProperties": { "$dynamicRef": "#meta" },
+ "propertyNames": { "format": "regex" },
+ "default": {}
+ },
+ "dependentSchemas": {
+ "type": "object",
+ "additionalProperties": { "$dynamicRef": "#meta" },
+ "default": {}
+ },
+ "propertyNames": { "$dynamicRef": "#meta" },
+ "if": { "$dynamicRef": "#meta" },
+ "then": { "$dynamicRef": "#meta" },
+ "else": { "$dynamicRef": "#meta" },
+ "allOf": { "$ref": "#/$defs/schemaArray" },
+ "anyOf": { "$ref": "#/$defs/schemaArray" },
+ "oneOf": { "$ref": "#/$defs/schemaArray" },
+ "not": { "$dynamicRef": "#meta" }
+ },
+ "$defs": {
+ "schemaArray": {
+ "type": "array",
+ "minItems": 1,
+ "items": { "$dynamicRef": "#meta" }
+ }
+ }
+}
diff --git a/jsonschema/schemas/draft2020-12/content.json b/jsonschema/schemas/draft2020-12/content.json
new file mode 100644
index 0000000..2f6e056
--- /dev/null
+++ b/jsonschema/schemas/draft2020-12/content.json
@@ -0,0 +1,17 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://json-schema.org/draft/2020-12/meta/content",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2020-12/vocab/content": true
+ },
+ "$dynamicAnchor": "meta",
+
+ "title": "Content vocabulary meta-schema",
+
+ "type": ["object", "boolean"],
+ "properties": {
+ "contentEncoding": { "type": "string" },
+ "contentMediaType": { "type": "string" },
+ "contentSchema": { "$dynamicRef": "#meta" }
+ }
+}
diff --git a/jsonschema/schemas/draft2020-12/core.json b/jsonschema/schemas/draft2020-12/core.json
new file mode 100644
index 0000000..dfc092d
--- /dev/null
+++ b/jsonschema/schemas/draft2020-12/core.json
@@ -0,0 +1,51 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://json-schema.org/draft/2020-12/meta/core",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2020-12/vocab/core": true
+ },
+ "$dynamicAnchor": "meta",
+
+ "title": "Core vocabulary meta-schema",
+ "type": ["object", "boolean"],
+ "properties": {
+ "$id": {
+ "$ref": "#/$defs/uriReferenceString",
+ "$comment": "Non-empty fragments not allowed.",
+ "pattern": "^[^#]*#?$"
+ },
+ "$schema": { "$ref": "#/$defs/uriString" },
+ "$ref": { "$ref": "#/$defs/uriReferenceString" },
+ "$anchor": { "$ref": "#/$defs/anchorString" },
+ "$dynamicRef": { "$ref": "#/$defs/uriReferenceString" },
+ "$dynamicAnchor": { "$ref": "#/$defs/anchorString" },
+ "$vocabulary": {
+ "type": "object",
+ "propertyNames": { "$ref": "#/$defs/uriString" },
+ "additionalProperties": {
+ "type": "boolean"
+ }
+ },
+ "$comment": {
+ "type": "string"
+ },
+ "$defs": {
+ "type": "object",
+ "additionalProperties": { "$dynamicRef": "#meta" }
+ }
+ },
+ "$defs": {
+ "anchorString": {
+ "type": "string",
+ "pattern": "^[A-Za-z_][-A-Za-z0-9._]*$"
+ },
+ "uriString": {
+ "type": "string",
+ "format": "uri"
+ },
+ "uriReferenceString": {
+ "type": "string",
+ "format": "uri-reference"
+ }
+ }
+}
diff --git a/jsonschema/schemas/draft2020-12/format-annotation.json b/jsonschema/schemas/draft2020-12/format-annotation.json
new file mode 100644
index 0000000..51ef7ea
--- /dev/null
+++ b/jsonschema/schemas/draft2020-12/format-annotation.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://json-schema.org/draft/2020-12/meta/format-annotation",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2020-12/vocab/format-annotation": true
+ },
+ "$dynamicAnchor": "meta",
+
+ "title": "Format vocabulary meta-schema for annotation results",
+ "type": ["object", "boolean"],
+ "properties": {
+ "format": { "type": "string" }
+ }
+}
diff --git a/jsonschema/schemas/draft2020-12/meta-data.json b/jsonschema/schemas/draft2020-12/meta-data.json
new file mode 100644
index 0000000..05cbc22
--- /dev/null
+++ b/jsonschema/schemas/draft2020-12/meta-data.json
@@ -0,0 +1,37 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://json-schema.org/draft/2020-12/meta/meta-data",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2020-12/vocab/meta-data": true
+ },
+ "$dynamicAnchor": "meta",
+
+ "title": "Meta-data vocabulary meta-schema",
+
+ "type": ["object", "boolean"],
+ "properties": {
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": true,
+ "deprecated": {
+ "type": "boolean",
+ "default": false
+ },
+ "readOnly": {
+ "type": "boolean",
+ "default": false
+ },
+ "writeOnly": {
+ "type": "boolean",
+ "default": false
+ },
+ "examples": {
+ "type": "array",
+ "items": true
+ }
+ }
+}
diff --git a/jsonschema/schemas/draft2020-12/unevaluated.json b/jsonschema/schemas/draft2020-12/unevaluated.json
new file mode 100644
index 0000000..5f62a3f
--- /dev/null
+++ b/jsonschema/schemas/draft2020-12/unevaluated.json
@@ -0,0 +1,15 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://json-schema.org/draft/2020-12/meta/unevaluated",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2020-12/vocab/unevaluated": true
+ },
+ "$dynamicAnchor": "meta",
+
+ "title": "Unevaluated applicator vocabulary meta-schema",
+ "type": ["object", "boolean"],
+ "properties": {
+ "unevaluatedItems": { "$dynamicRef": "#meta" },
+ "unevaluatedProperties": { "$dynamicRef": "#meta" }
+ }
+}
diff --git a/jsonschema/schemas/draft2020-12/validation.json b/jsonschema/schemas/draft2020-12/validation.json
new file mode 100644
index 0000000..606b87b
--- /dev/null
+++ b/jsonschema/schemas/draft2020-12/validation.json
@@ -0,0 +1,98 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://json-schema.org/draft/2020-12/meta/validation",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2020-12/vocab/validation": true
+ },
+ "$dynamicAnchor": "meta",
+
+ "title": "Validation vocabulary meta-schema",
+ "type": ["object", "boolean"],
+ "properties": {
+ "type": {
+ "anyOf": [
+ { "$ref": "#/$defs/simpleTypes" },
+ {
+ "type": "array",
+ "items": { "$ref": "#/$defs/simpleTypes" },
+ "minItems": 1,
+ "uniqueItems": true
+ }
+ ]
+ },
+ "const": true,
+ "enum": {
+ "type": "array",
+ "items": true
+ },
+ "multipleOf": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "maximum": {
+ "type": "number"
+ },
+ "exclusiveMaximum": {
+ "type": "number"
+ },
+ "minimum": {
+ "type": "number"
+ },
+ "exclusiveMinimum": {
+ "type": "number"
+ },
+ "maxLength": { "$ref": "#/$defs/nonNegativeInteger" },
+ "minLength": { "$ref": "#/$defs/nonNegativeIntegerDefault0" },
+ "pattern": {
+ "type": "string",
+ "format": "regex"
+ },
+ "maxItems": { "$ref": "#/$defs/nonNegativeInteger" },
+ "minItems": { "$ref": "#/$defs/nonNegativeIntegerDefault0" },
+ "uniqueItems": {
+ "type": "boolean",
+ "default": false
+ },
+ "maxContains": { "$ref": "#/$defs/nonNegativeInteger" },
+ "minContains": {
+ "$ref": "#/$defs/nonNegativeInteger",
+ "default": 1
+ },
+ "maxProperties": { "$ref": "#/$defs/nonNegativeInteger" },
+ "minProperties": { "$ref": "#/$defs/nonNegativeIntegerDefault0" },
+ "required": { "$ref": "#/$defs/stringArray" },
+ "dependentRequired": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/$defs/stringArray"
+ }
+ }
+ },
+ "$defs": {
+ "nonNegativeInteger": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "nonNegativeIntegerDefault0": {
+ "$ref": "#/$defs/nonNegativeInteger",
+ "default": 0
+ },
+ "simpleTypes": {
+ "enum": [
+ "array",
+ "boolean",
+ "integer",
+ "null",
+ "number",
+ "object",
+ "string"
+ ]
+ },
+ "stringArray": {
+ "type": "array",
+ "items": { "type": "string" },
+ "uniqueItems": true,
+ "default": []
+ }
+ }
+}
diff --git a/jsonschema/validators.py b/jsonschema/validators.py
index 328f6bc..3da5091 100644
--- a/jsonschema/validators.py
+++ b/jsonschema/validators.py
@@ -26,6 +26,7 @@ ErrorTree
validators = {}
meta_schemas = _utils.URIDict()
+vocabulary_schemas = _utils.URIDict()
def validates(version):
@@ -53,6 +54,12 @@ def validates(version):
meta_schema_id = cls.ID_OF(cls.META_SCHEMA)
if meta_schema_id:
meta_schemas[meta_schema_id] = cls
+
+ for vocabulary in cls.VOCABULARY_SCHEMAS:
+ vocabulary_id = cls.ID_OF(vocabulary)
+ if vocabulary_id:
+ vocabulary_schemas[vocabulary_id] = vocabulary
+
return cls
return _validates
@@ -63,8 +70,18 @@ def _id_of(schema):
return schema.get(u"$id", u"")
+def _store_schema_list():
+ return [
+ (id, validator.META_SCHEMA)
+ for id, validator in meta_schemas.items()
+ ] + [
+ (id, schema) for id, schema in vocabulary_schemas.items()
+ ]
+
+
def create(
meta_schema,
+ vocabulary_schemas=(),
validators=(),
version=None,
type_checker=_types.draft7_type_checker,
@@ -120,6 +137,7 @@ def create(
VALIDATORS = dict(validators)
META_SCHEMA = dict(meta_schema)
+ VOCABULARY_SCHEMAS = list(vocabulary_schemas)
TYPE_CHECKER = type_checker
ID_OF = staticmethod(id_of)
@@ -434,6 +452,7 @@ Draft7Validator = create(
Draft202012Validator = create(
meta_schema=_utils.load_schema("draft2020-12"),
+ vocabulary_schemas=_utils.load_vocabulary("draft2020-12"),
validators={
u"$ref": _validators.ref,
u"$defs": _validators.defs,
@@ -545,10 +564,7 @@ class RefResolver(object):
self.handlers = dict(handlers)
self._scopes_stack = [base_uri]
- self.store = _utils.URIDict(
- (id, validator.META_SCHEMA)
- for id, validator in meta_schemas.items()
- )
+ self.store = _utils.URIDict(_store_schema_list())
self.store.update(store)
self.store[base_uri] = referrer
diff --git a/setup.cfg b/setup.cfg
index a53aea0..a4c1fb4 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -55,7 +55,7 @@ console_scripts =
jsonschema = jsonschema.cli:main
[options.package_data]
-jsonschema = schemas/*.json
+jsonschema = schemas/*.json, schemas/draft2020-12/*.json
[bdist_wheel]
universal = 1