python-openapi/openapi-schema-validator

Unexpected validation error with nullable allOf

linkdd opened this issue · 1 comments

How to reproduce:

from openapi_schema_validator import validate, OAS30Validator, OAS31Validator

schema = {
  "allOf": [
    {"type": "string"},
  ],
  "nullable": True,
}

validate(None, schema, cls=OAS30Validator)
# --> None for not nullable

validate(None, schema, cls=0AS31Validator)
# --> None is not of type 'string'

Seems related to #20

As I understand the codebase, nullable should not be on a schema with only allOf, and that's why the 3.1 OpenAPI spec changed this from 3.0. So it would seem that the schema generated by drf-spectacular (a Django REST Framework extension) is in the wrong here.

I found this workaround though:

from functools import wraps
from copy import deepcopy

from openapi_schema_validator.validators import SPECIFICATIONS
from openapi_schema_validator import OAS30Validator
from jsonschema.validators import create


def _nullable_check_wrapper(func):
    @wraps(func)
    def wrapper(validator, value, instance, schema):
        if instance is None and schema.get("nullable", False):
            return

        yield from func(validator, value, instance, schema)

    return wrapper


def _with_nullable_checks(validators):
    for key in validators:
        if key in ["enum", "allOf", "anyOf", "oneOf", "$ref"]:
            validators[key] = _nullable_check_wrapper(validators[key])

    return validators


FixedOAS30Validator = create(
    meta_schema=SPECIFICATIONS.contents(
        "http://json-schema.org/draft-04/schema#",
    ),
    validators=_with_nullable_checks(deepcopy(OAS30Validator.VALIDATORS)),
    type_checker=OAS30Validator.TYPE_CHECKER,
    format_checker=OAS30Validator.FORMAT_CHECKER,
    id_of=lambda schema: schema.get("id", ""),
)