Skip to content
This repository was archived by the owner on May 11, 2023. It is now read-only.

Commit f24ee5e

Browse files
committed
python-openapi/openapi-core#296: Implements OpenAPI 3.1 spec validator
1 parent 27ee7cf commit f24ee5e

File tree

12 files changed

+1614
-41
lines changed

12 files changed

+1614
-41
lines changed

.github/workflows/python-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
runs-on: ${{ matrix.os }}
1414
strategy:
1515
matrix:
16-
python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9]
16+
python-version: [3.6, 3.7, 3.8, 3.9]
1717
os: [windows-latest, ubuntu-latest]
1818
fail-fast: false
1919
steps:

openapi_spec_validator/__init__.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
)
55
from openapi_spec_validator.handlers import UrlHandler, FileObjectHandler
66
from openapi_spec_validator.schemas import get_openapi_schema
7-
from openapi_spec_validator.factories import JSONSpecValidatorFactory
7+
from openapi_spec_validator.factories import \
8+
Draft202012JSONSpecValidatorFactory, Draft4JSONSpecValidatorFactory
89
from openapi_spec_validator.validators import SpecValidator
910

1011
__author__ = 'Artur Maciag'
@@ -14,9 +15,15 @@
1415
__license__ = 'Apache License, Version 2.0'
1516

1617
__all__ = [
17-
'openapi_v2_spec_validator', 'openapi_v3_spec_validator',
18-
'validate_v2_spec', 'validate_v3_spec', 'validate_spec',
19-
'validate_v2_spec_url', 'validate_v3_spec_url', 'validate_spec_url',
18+
'openapi_v2_spec_validator',
19+
'openapi_v3_spec_validator',
20+
'openapi_v31_spec_validator',
21+
'validate_v2_spec',
22+
'validate_v3_spec',
23+
'validate_spec',
24+
'validate_v2_spec_url',
25+
'validate_v3_spec_url',
26+
'validate_spec_url',
2027
]
2128

2229
file_object_handler = FileObjectHandler()
@@ -30,7 +37,7 @@
3037

3138
# v2.0 spec
3239
schema_v2, schema_v2_url = get_openapi_schema('2.0')
33-
openapi_v2_validator_factory = JSONSpecValidatorFactory(
40+
openapi_v2_validator_factory = Draft4JSONSpecValidatorFactory(
3441
schema_v2, schema_v2_url,
3542
resolver_handlers=default_handlers,
3643
)
@@ -41,7 +48,7 @@
4148

4249
# v3.0 spec
4350
schema_v3, schema_v3_url = get_openapi_schema('3.0')
44-
openapi_v3_validator_factory = JSONSpecValidatorFactory(
51+
openapi_v3_validator_factory = Draft4JSONSpecValidatorFactory(
4552
schema_v3, schema_v3_url,
4653
resolver_handlers=default_handlers,
4754
)
@@ -50,6 +57,18 @@
5057
resolver_handlers=default_handlers,
5158
)
5259

60+
# v3.1 spec
61+
schema_v31, schema_v31_url = get_openapi_schema('3.1')
62+
openapi_v31_validator_factory = Draft202012JSONSpecValidatorFactory(
63+
schema_v31, schema_v31_url,
64+
resolver_handlers=default_handlers,
65+
)
66+
openapi_v31_spec_validator = SpecValidator(
67+
openapi_v31_validator_factory,
68+
resolver_handlers=default_handlers,
69+
)
70+
71+
5372
# shortcuts
5473
validate_v2_spec = validate_spec_factory(openapi_v2_spec_validator.validate)
5574
validate_v2_spec_url = validate_spec_url_factory(
@@ -59,6 +78,12 @@
5978
validate_v3_spec_url = validate_spec_url_factory(
6079
openapi_v3_spec_validator.validate, default_handlers)
6180

81+
82+
validate_v31_spec = validate_spec_factory(openapi_v31_spec_validator.validate)
83+
validate_v31_spec_url = validate_spec_url_factory(
84+
openapi_v31_spec_validator.validate, default_handlers)
85+
86+
6287
# aliases to the latest version
6388
validate_spec = validate_v3_spec
6489
validate_spec_url = validate_v3_spec_url

openapi_spec_validator/factories.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""OpenAPI spec validator factories module."""
22
from jsonschema import validators
3-
from jsonschema.validators import Draft4Validator, RefResolver
3+
from jsonschema.validators import Draft4Validator, RefResolver, \
4+
Draft202012Validator
45

56
from openapi_spec_validator.generators import (
67
SpecValidatorsGeneratorFactory,
@@ -28,16 +29,15 @@ def _get_spec_validators(cls, spec_resolver):
2829
return dict(list(generator))
2930

3031

31-
class JSONSpecValidatorFactory:
32+
class BaseJSONSpecValidatorFactory:
3233
"""
3334
Json documents validator factory against a json schema.
3435
3536
:param schema: schema for validation.
3637
:param schema_url: schema base uri.
3738
"""
3839

39-
schema_validator_class = Draft4Validator
40-
spec_validator_factory = Draft4ExtendedValidatorFactory
40+
schema_validator_class = None
4141

4242
def __init__(self, schema, schema_url='', resolver_handlers=None):
4343
self.schema = schema
@@ -46,6 +46,17 @@ def __init__(self, schema, schema_url='', resolver_handlers=None):
4646

4747
self.schema_validator_class.check_schema(self.schema)
4848

49+
50+
class Draft4JSONSpecValidatorFactory(BaseJSONSpecValidatorFactory):
51+
"""
52+
Json documents validator factory that uses Draft4Validator
53+
54+
:param schema: schema for validation.
55+
:param schema_url: schema base uri.
56+
"""
57+
schema_validator_class = Draft4Validator
58+
spec_validator_factory = Draft4ExtendedValidatorFactory
59+
4960
@property
5061
def schema_resolver(self):
5162
return self._get_resolver(self.schema_url, self.schema)
@@ -67,3 +78,17 @@ def create(self, spec_resolver):
6778
def _get_resolver(self, base_uri, referrer):
6879
return RefResolver(
6980
base_uri, referrer, handlers=self.resolver_handlers)
81+
82+
83+
class Draft202012JSONSpecValidatorFactory(BaseJSONSpecValidatorFactory):
84+
"""
85+
Json documents validator factory that uses Draft202012Validator
86+
87+
:param schema: schema for validation.
88+
:param schema_url: schema base uri.
89+
"""
90+
91+
schema_validator_class = Draft202012Validator
92+
93+
def create(self, spec_resolver):
94+
return self.schema_validator_class(self.schema)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"$id": "https://spec.openapis.org/oas/3.1/dialect/base",
3+
"$schema": "https://json-schema.org/draft/2020-12/schema",
4+
"$vocabulary": {
5+
"https://json-schema.org/draft/2020-12/vocab/core": true,
6+
"https://json-schema.org/draft/2020-12/vocab/applicator": true,
7+
"https://json-schema.org/draft/2020-12/vocab/unevaluated": true,
8+
"https://json-schema.org/draft/2020-12/vocab/validation": true,
9+
"https://json-schema.org/draft/2020-12/vocab/meta-data": true,
10+
"https://json-schema.org/draft/2020-12/vocab/format-annotation": true,
11+
"https://json-schema.org/draft/2020-12/vocab/content": true,
12+
"https://spec.openapis.org/oas/3.1/vocab/base": false
13+
},
14+
"$dynamicAnchor": "meta",
15+
16+
"title": "OpenAPI 3.1 Schema Object Dialect",
17+
"allOf": [
18+
{ "$ref": "https://json-schema.org/draft/2020-12/schema" },
19+
{ "$ref": "https://spec.openapis.org/oas/3.1/meta/base" }
20+
]
21+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
{
2+
"$id": "https://spec.openapis.org/oas/3.1/meta/base",
3+
"$schema": "https://json-schema.org/draft/2020-12/schema",
4+
"$vocabulary": {
5+
"https://spec.openapis.org/oas/3.1/vocab/base": true
6+
},
7+
"$dynamicAnchor": "meta",
8+
"title": "OAS Base vocabulary",
9+
10+
"type": ["object", "boolean"],
11+
"properties": {
12+
"example": true,
13+
"discriminator": { "$ref": "#/$defs/discriminator" },
14+
"externalDocs": { "$ref": "#/$defs/external-docs" },
15+
"xml": { "$ref": "#/$defs/xml" }
16+
},
17+
"$defs": {
18+
"extensible": {
19+
"patternProperties": {
20+
"^x-": true
21+
}
22+
},
23+
"discriminator": {
24+
"$ref": "#/$defs/extensible",
25+
"type": "object",
26+
"properties": {
27+
"propertyName": {
28+
"type": "string"
29+
},
30+
"mapping": {
31+
"type": "object",
32+
"additionalProperties": {
33+
"type": "string"
34+
}
35+
}
36+
},
37+
"required": ["propertyName"],
38+
"unevaluatedProperties": false
39+
},
40+
"external-docs": {
41+
"$ref": "#/$defs/extensible",
42+
"type": "object",
43+
"properties": {
44+
"url": {
45+
"type": "string",
46+
"format": "uri-reference"
47+
},
48+
"description": {
49+
"type": "string"
50+
}
51+
},
52+
"required": ["url"],
53+
"unevaluatedProperties": false
54+
},
55+
"xml": {
56+
"$ref": "#/$defs/extensible",
57+
"type": "object",
58+
"properties": {
59+
"name": {
60+
"type": "string"
61+
},
62+
"namespace": {
63+
"type": "string",
64+
"format": "uri"
65+
},
66+
"prefix": {
67+
"type": "string"
68+
},
69+
"attribute": {
70+
"type": "boolean"
71+
},
72+
"wrapped": {
73+
"type": "boolean"
74+
}
75+
},
76+
"unevaluatedProperties": false
77+
}
78+
}
79+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"$id": "https://spec.openapis.org/oas/3.1/schema-base/2021-05-20",
3+
"$schema": "https://json-schema.org/draft/2020-12/schema",
4+
"$ref": "https://spec.openapis.org/oas/3.1/schema/2021-05-20",
5+
"properties": {
6+
"jsonSchemaDialect": {
7+
"$ref": "#/$defs/dialect"
8+
}
9+
},
10+
"$defs": {
11+
"dialect": {
12+
"const": "https://spec.openapis.org/oas/3.1/dialect/base"
13+
},
14+
"schema": {
15+
"$dynamicAnchor": "meta",
16+
"$ref": "https://spec.openapis.org/oas/3.1/dialect/base",
17+
"properties": {
18+
"$schema": {
19+
"$ref": "#/$defs/dialect"
20+
}
21+
}
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)