Skip to content

Commit e76cba4

Browse files
authored
Merge pull request #143 from p1c2u/anexia-it-master
Implements OpenAPI 3.1 spec validator
2 parents 1298d29 + 3588f6f commit e76cba4

File tree

14 files changed

+1691
-96
lines changed

14 files changed

+1691
-96
lines changed

README.rst

+11-8
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@ About
1919
#####
2020

2121
OpenAPI Spec Validator is a Python library that validates OpenAPI Specs
22-
against the `OpenAPI 2.0 (aka
23-
Swagger) <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md>`__
24-
and `OpenAPI
25-
3.0 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md>`__
26-
specification. The validator aims to check for full compliance with the
27-
Specification.
22+
against the `OpenAPI 2.0 (aka Swagger)
23+
<https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md>`__,
24+
`OpenAPI 3.0 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md>`__
25+
and `OpenAPI 3.1 <https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md>`__
26+
specification. The validator aims to check for full compliance with the Specification.
2827

2928
Installation
3029
############
@@ -73,7 +72,7 @@ or more pythonic way:
7372
Examples
7473
********
7574

76-
By default, OpenAPI v3 syntax is expected. To validate an OpenAPI v3 spec:
75+
By default, OpenAPI v3.1 syntax is expected. To validate an OpenAPI v3.1 spec:
7776

7877
.. code:: python
7978
@@ -91,7 +90,11 @@ By default, OpenAPI v3 syntax is expected. To validate an OpenAPI v3 spec:
9190
...
9291
OpenAPIValidationError: 'openapi' is a required property
9392
94-
In order to validate a Swagger / OpenAPI 2.0 spec file, import ``validate_v2_spec`` instead of ``validate_spec``. You can also explicitly import ``validate_v3_spec`` if you want to disambiguate the expected version.
93+
In order to validate a Swagger / OpenAPI 2.0 spec file, import ``validate_v2_spec`` instead of ``validate_spec``.
94+
In order to validate a OpenAPI 3.0 spec file, import ``validate_v30_spec`` instead of ``validate_spec``.
95+
96+
You can also explicitly import ``validate_v31_spec`` if you want to disambiguate the expected version or
97+
explicitly import ``validate_v3_spec`` which is a shortcut to the latest v3 release.
9598

9699
Add ``spec_url`` to validate spec with relative files:
97100

openapi_spec_validator/__init__.py

+49-13
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,20 @@
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_v30_spec_validator',
21+
'openapi_v31_spec_validator',
22+
'validate_v2_spec',
23+
'validate_v3_spec',
24+
'validate_v30_spec',
25+
'validate_v31_spec',
26+
'validate_spec',
27+
'validate_v2_spec_url',
28+
'validate_v3_spec_url',
29+
'validate_v30_spec_url',
30+
'validate_v31_spec_url',
31+
'validate_spec_url',
2032
]
2133

2234
file_object_handler = FileObjectHandler()
@@ -30,7 +42,7 @@
3042

3143
# v2.0 spec
3244
schema_v2, schema_v2_url = get_openapi_schema('2.0')
33-
openapi_v2_validator_factory = JSONSpecValidatorFactory(
45+
openapi_v2_validator_factory = Draft4JSONSpecValidatorFactory(
3446
schema_v2, schema_v2_url,
3547
resolver_handlers=default_handlers,
3648
)
@@ -40,13 +52,24 @@
4052
)
4153

4254
# v3.0 spec
43-
schema_v3, schema_v3_url = get_openapi_schema('3.0')
44-
openapi_v3_validator_factory = JSONSpecValidatorFactory(
45-
schema_v3, schema_v3_url,
55+
schema_v30, schema_v30_url = get_openapi_schema('3.0')
56+
openapi_v30_validator_factory = Draft4JSONSpecValidatorFactory(
57+
schema_v30, schema_v30_url,
4658
resolver_handlers=default_handlers,
4759
)
48-
openapi_v3_spec_validator = SpecValidator(
49-
openapi_v3_validator_factory,
60+
openapi_v30_spec_validator = SpecValidator(
61+
openapi_v30_validator_factory,
62+
resolver_handlers=default_handlers,
63+
)
64+
65+
# v3.1 spec
66+
schema_v31, schema_v31_url = get_openapi_schema('3.1')
67+
openapi_v31_validator_factory = Draft202012JSONSpecValidatorFactory(
68+
schema_v31, schema_v31_url,
69+
resolver_handlers=default_handlers,
70+
)
71+
openapi_v31_spec_validator = SpecValidator(
72+
openapi_v31_validator_factory,
5073
resolver_handlers=default_handlers,
5174
)
5275

@@ -55,9 +78,22 @@
5578
validate_v2_spec_url = validate_spec_url_factory(
5679
openapi_v2_spec_validator.validate, default_handlers)
5780

58-
validate_v3_spec = validate_spec_factory(openapi_v3_spec_validator.validate)
59-
validate_v3_spec_url = validate_spec_url_factory(
60-
openapi_v3_spec_validator.validate, default_handlers)
81+
validate_v30_spec = validate_spec_factory(openapi_v30_spec_validator.validate)
82+
validate_v30_spec_url = validate_spec_url_factory(
83+
openapi_v30_spec_validator.validate, default_handlers)
84+
85+
86+
validate_v31_spec = validate_spec_factory(openapi_v31_spec_validator.validate)
87+
validate_v31_spec_url = validate_spec_url_factory(
88+
openapi_v31_spec_validator.validate, default_handlers)
89+
90+
# aliases to the latest v3 version
91+
schema_v3 = schema_v31
92+
schema_v3_url = schema_v31_url
93+
openapi_v3_validator_factory = openapi_v31_validator_factory
94+
openapi_v3_spec_validator = openapi_v31_spec_validator
95+
validate_v3_spec = validate_v31_spec
96+
validate_v3_spec_url = validate_v31_spec_url
6197

6298
# aliases to the latest version
6399
validate_spec = validate_v3_spec

openapi_spec_validator/__main__.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
from jsonschema.exceptions import best_match
66

77
from openapi_spec_validator import (
8-
openapi_v2_spec_validator, openapi_v3_spec_validator,
8+
openapi_v2_spec_validator,
9+
openapi_v30_spec_validator,
10+
openapi_v31_spec_validator,
911
)
1012
from openapi_spec_validator.exceptions import ValidationError
1113
from openapi_spec_validator.readers import read_from_stdin, read_from_filename
@@ -50,10 +52,10 @@ def main(args=None):
5052
)
5153
parser.add_argument(
5254
'--schema',
53-
help="OpenAPI schema (default: 3.0.0)",
55+
help="OpenAPI schema (default: 3.1.0)",
5456
type=str,
55-
choices=['2.0', '3.0.0'],
56-
default='3.0.0'
57+
choices=['2.0', '3.0.0', '3.1.0'],
58+
default='3.1.0'
5759
)
5860
args = parser.parse_args(args)
5961

@@ -72,7 +74,8 @@ def main(args=None):
7274
# choose the validator
7375
validators = {
7476
'2.0': openapi_v2_spec_validator,
75-
'3.0.0': openapi_v3_spec_validator,
77+
'3.0.0': openapi_v30_spec_validator,
78+
'3.1.0': openapi_v31_spec_validator,
7679
}
7780
validator = validators[args.schema]
7881

openapi_spec_validator/factories.py

+29-4
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)

0 commit comments

Comments
 (0)