Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Use this as the default operating playbook when making changes.
## Source Layout

- `openapi_schema_validator/__init__.py`: public exports + package metadata.
- `openapi_schema_validator/validators.py`: validator class setup for OAS 3.0/3.1.
- `openapi_schema_validator/validators.py`: validator class setup for OAS 3.0/3.1/3.2.
- `openapi_schema_validator/_keywords.py`: custom keyword handlers and ValidationError generation.
- `openapi_schema_validator/_format.py`: format checker functions and registrations.
- `openapi_schema_validator/_types.py`: custom type checker setup.
Expand Down Expand Up @@ -128,7 +128,7 @@ Run commands from repository root.
### Behavioral constraints to preserve

- Do not mutate incoming schema objects in helper APIs.
- Maintain compatibility for both OAS 3.0 and OAS 3.1 validators.
- Maintain compatibility for OAS 3.0, OAS 3.1, and OAS 3.2 validators.
- Keep existing read/write behavior around `readOnly` and `writeOnly`.
- Keep format and type checker semantics aligned with current tests.

Expand Down
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Openapi-schema-validator is a Python library that validates schema against:

* `OpenAPI Schema Specification v3.0 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject>`__ which is an extended subset of the `JSON Schema Specification Wright Draft 00 <http://json-schema.org/>`__.
* `OpenAPI Schema Specification v3.1 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#schemaObject>`__ which is an extended superset of the `JSON Schema Specification Draft 2020-12 <http://json-schema.org/>`__.
* `OpenAPI Schema Specification v3.2 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.2.0.md#schemaObject>`__ which uses the same JSON Schema dialect as v3.1.


Documentation
Expand Down
2 changes: 2 additions & 0 deletions docs/format.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ You can check format for predefined OAS primitive types
Traceback (most recent call last):
...
ValidationError: '-12' is not a 'date'

For OpenAPI 3.2, use ``oas32_format_checker`` (behaves identically to ``oas31_format_checker``, since 3.2 uses the same JSON Schema dialect).
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Openapi-schema-validator is a Python library that validates schema against:

* `OpenAPI Schema Specification v3.0 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject>`__ which is an extended subset of the `JSON Schema Specification Wright Draft 00 <http://json-schema.org/>`__.
* `OpenAPI Schema Specification v3.1 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#schemaObject>`__ which is an extended superset of the `JSON Schema Specification Draft 2020-12 <http://json-schema.org/>`__.
* `OpenAPI Schema Specification v3.2 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.2.0.md#schemaObject>`__ which uses the same JSON Schema dialect as v3.1.

Installation
------------
Expand Down
2 changes: 2 additions & 0 deletions docs/validation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ if you want to disambiguate the expected schema version, import and use ``OAS31V

validate({"name": "John", "age": 23}, schema, cls=OAS31Validator)

For OpenAPI 3.2, use ``OAS32Validator`` (behaves identically to ``OAS31Validator``, since 3.2 uses the same JSON Schema dialect).

In order to validate OpenAPI 3.0 schema, import and use ``OAS30Validator`` instead of ``OAS31Validator``.

.. code-block:: python
Expand Down
4 changes: 4 additions & 0 deletions openapi_schema_validator/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from openapi_schema_validator._format import oas30_format_checker
from openapi_schema_validator._format import oas30_strict_format_checker
from openapi_schema_validator._format import oas31_format_checker
from openapi_schema_validator._format import oas32_format_checker
from openapi_schema_validator.shortcuts import validate
from openapi_schema_validator.validators import OAS30ReadValidator
from openapi_schema_validator.validators import OAS30StrictValidator
from openapi_schema_validator.validators import OAS30Validator
from openapi_schema_validator.validators import OAS30WriteValidator
from openapi_schema_validator.validators import OAS31Validator
from openapi_schema_validator.validators import OAS32Validator

__author__ = "Artur Maciag"
__email__ = "maciag.artur@gmail.com"
Expand All @@ -24,4 +26,6 @@
"oas30_strict_format_checker",
"OAS31Validator",
"oas31_format_checker",
"OAS32Validator",
"oas32_format_checker",
]
8 changes: 8 additions & 0 deletions openapi_schema_validator/_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,11 @@ def is_password(instance: object) -> bool:
oas31_format_checker.checks("float")(is_float)
oas31_format_checker.checks("double")(is_double)
oas31_format_checker.checks("password")(is_password)

# OAS 3.2 uses the same format checks as OAS 3.1
oas32_format_checker = FormatChecker()
oas32_format_checker.checks("int32")(is_int32)
oas32_format_checker.checks("int64")(is_int64)
oas32_format_checker.checks("float")(is_float)
oas32_format_checker.checks("double")(is_double)
oas32_format_checker.checks("password")(is_password)
10 changes: 10 additions & 0 deletions openapi_schema_validator/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,13 @@ def _oas30_id_of(schema: Any) -> str:
type_checker=oas31_type_checker,
format_checker=oas_format.oas31_format_checker,
)

# OAS 3.2 uses JSON Schema Draft 2020-12 as its base dialect, same as
# OAS 3.1. The OAS-specific vocabulary differs slightly (e.g. xml keyword
# changes), but since xml is not_implemented in the current validators,
# the behavior is equivalent.
OAS32Validator = extend(
OAS31Validator,
{},
format_checker=oas_format.oas32_format_checker,
)
62 changes: 62 additions & 0 deletions tests/integration/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
from openapi_schema_validator import OAS30Validator
from openapi_schema_validator import OAS30WriteValidator
from openapi_schema_validator import OAS31Validator
from openapi_schema_validator import OAS32Validator
from openapi_schema_validator import oas30_format_checker
from openapi_schema_validator import oas30_strict_format_checker
from openapi_schema_validator import oas31_format_checker
from openapi_schema_validator import oas32_format_checker


class TestOAS30ValidatorFormatChecker:
Expand Down Expand Up @@ -1003,6 +1005,66 @@ def test_array_prefixitems_invalid(self, validator_class, value):
assert any(error in str(excinfo.value) for error in errors)


class TestOAS32ValidatorValidate(TestOAS31ValidatorValidate):
"""OAS 3.2 uses the same JSON Schema dialect as 3.1."""

@pytest.fixture
def validator_class(self):
return OAS32Validator

@pytest.fixture
def format_checker(self):
return oas32_format_checker

def test_validator_is_distinct_from_oas31(self):
assert OAS32Validator is not OAS31Validator

def test_format_checker_is_distinct_from_oas31(self):
assert oas32_format_checker is not oas31_format_checker

def test_validator_shares_oas31_behavior(self):
assert OAS32Validator.VALIDATORS == OAS31Validator.VALIDATORS

def test_format_validation_int32(self, validator_class):
schema = {"type": "integer", "format": "int32"}
validator = validator_class(
schema, format_checker=oas32_format_checker
)

result = validator.validate(42)
assert result is None

with pytest.raises(ValidationError):
validator.validate(9999999999)

def test_format_validation_date(self, validator_class):
schema = {"type": "string", "format": "date"}
validator = validator_class(
schema, format_checker=oas32_format_checker
)

result = validator.validate("2024-01-15")
assert result is None

with pytest.raises(ValidationError):
validator.validate("not-a-date")

def test_schema_with_allof(self, validator_class):
schema = {
"allOf": [
{"type": "object", "properties": {"id": {"type": "integer"}}},
{"type": "object", "properties": {"name": {"type": "string"}}},
]
}
validator = validator_class(schema)

result = validator.validate({"id": 1, "name": "test"})
assert result is None

with pytest.raises(ValidationError):
validator.validate({"id": "not-an-integer"})


class TestOAS30StrictValidator:
"""
Tests for OAS30StrictValidator which follows OAS spec strictly:
Expand Down
Loading