Git Product home page Git Product logo

openapi-schema-validator's Introduction

openapi-schema-validator

image

image

image

image

image

image

About

Openapi-schema-validator is a Python library that validates schema against:

Documentation

Check documentation to see more details about the features. All documentation is in the "docs" directory and online at openapi-schema-validator.readthedocs.io

Installation

Recommended way (via pip):

pip install openapi-schema-validator

Alternatively you can download the code and install from the repository:

pip install -e git+https://github.com/python-openapi/openapi-schema-validator.git#egg=openapi_schema_validator

Usage

To validate an OpenAPI v3.1 schema:

from openapi_schema_validator import validate

# A sample schema
schema = {
    "type": "object",
    "required": [
       "name"
    ],
    "properties": {
        "name": {
            "type": "string"
        },
        "age": {
            "type": ["integer", "null"],
            "format": "int32",
            "minimum": 0,
        },
        "birth-date": {
            "type": "string",
            "format": "date",
        },
        "address": {
             "type": 'array',
             "prefixItems": [
                 { "type": "number" },
                 { "type": "string" },
                 { "enum": ["Street", "Avenue", "Boulevard"] },
                 { "enum": ["NW", "NE", "SW", "SE"] }
             ],
             "items": False,
         }
    },
    "additionalProperties": False,
}

# If no exception is raised by validate(), the instance is valid.
validate({"name": "John", "age": 23, "address": [1600, "Pennsylvania", "Avenue"]}, schema)

validate({"name": "John", "city": "London"}, schema)

Traceback (most recent call last):
    ...
ValidationError: Additional properties are not allowed ('city' was unexpected)

By default, the latest OpenAPI schema syntax is expected.

For more details read about Validation.

  • openapi-core

    Python library that adds client-side and server-side support for the OpenAPI.

  • openapi-spec-validator

    Python library that validates OpenAPI Specs against the OpenAPI 2.0 (aka Swagger) and OpenAPI 3.0 specification

openapi-schema-validator's People

Contributors

daniilglazkotr avatar dependabot[bot] avatar ecederstrand avatar felixonmars avatar fpgmaas avatar gberaudo avatar jparise avatar larox avatar lyang avatar miketheman avatar mirumirumi avatar nezhar avatar p1c2u avatar sebastianmika avatar stanislavlevin avatar timsilvers avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

openapi-schema-validator's Issues

minLength error message is missing the path/field that is in error.

Given the following OpenAPI schema:

model:
      required:
        - email
      type: object
      properties:
        email:
          type: string
          description: Email address of the user
          example: [email protected]
          minLength: 1

And given the following input payload to validate against:

{"email": ""}

The message returned in the ValidationError looks like:

"'' is too short"

As you can see, it is missing the field or path that is in error.

P.S.: Thank you for the work on this package. It is very helpful. Any chance we can get multiple errors returned at the same time? :)

Thank you again.

ERROR in validation: ... validation error: '2023-03-23 13:35:45' is not a 'date-time' - 'timestamp'

Hello guys,

we just upgraded
openapi-schema-validator | 0.4.0 | 0.4.4
openapi-spec-validator | 0.3.0 | 0.5.6

and now in certain situations we get the following error:

[2023-04-12 10:55:55,777] ERROR in validation: http://127.0.0.1:9081/xrfapi/xrfDetectorCalibration/import validation error: '2023-03-23 13:35:45' is not a 'date-time' - 'timestamp'

when processing JSON data that looks like this:

{
  "uuid": "eea1804b-542f-4d6c-b88b-b2f2c0dc5915",
  ...
  "timestamp": "2023-03-23 13:35:45",
  ...
}

The identical json worked without issues before. Any troubleshooting hints?
It is possible that the upgrade pulled other upgrades that cause this effect or that it did not pull other upgrades it should have pulled -- anything to watch out for?

Schema used is mutating inside validation process

Hi all! First of all thanks for providing this tool. It has helped my projects a lot.

I find an issue related to the schema used for the validation. There is an _schema.update(...) in https://github.com/p1c2u/openapi-schema-validator/blob/ab7222af0597ebc672f93cc7f7e089897aba1bec/openapi_schema_validator/validators.py#L68-L72 that is mutating the schema adding nullable: False property in all the fields that doesn't have it.

This schema mutation is generating some issues at the time of using the schema in other features like generating default values and in tests that are expecting the schema without changes.

I'll be happy to work on this and submit a PR.

Steps to reproduce

  • Create a schema that doesn't have the nullable property
  • Use validate(...) function with the instance and the schema
  • Now the schema contains the nullable property

Expected Behaviour

  • The schema shouldn't have changed

Code used as an example for showing the issue

from openapi_schema_validator import validate
schema = {
    "type": "object",
    'properties': {
        'email': {
            'type': 'string'
        },
        'enabled': {
            'type': 'boolean',
        }
    },
    'example': {'enabled': False, 'email': "[email protected]"}
}

validate({"email": "[email protected]"}, schema)
# schema after the validation
{
    'type': 'object',
    'properties': {
        'email': {
            'type': 'string',
+           'nullable': False
        },
        'enabled': {
            'type': 'boolean',
        }
    },
    'example': {
        'enabled': False,
        'email': "[email protected]"
    },
+   'nullable': False
}

readOnly and writeOnly with jsonschema4 doesn't work

Given schema and validator:

schema = {
    "type": "object",
    "properties": {
        "some_prop": {
            "type": "string",
            "readOnly": True
        }
    },
    "required": ["some_prop"]
}
validator = OAS30Validator(schema, format_checker=oas30_format_checker, write=True)

For the following instance:

validator.validate({"some_prop": "hello"})

in jsonschem3 we get error (correct):

Tried to write read-only property with hello

In jsonschem4 we get no errors (incorrect)

The issue exists in all versions <0.3.0

`TypeError: unhashable type: 'dict'` validating K8S v1.18 openapi.json

File being validated is https://raw.githubusercontent.com/kubernetes/kubernetes/release-1.18/api/openapi-spec/swagger.json

Failure occurs with ref being {'type': 'string'}.

Example of the portion of the schema that won't validate:

...
    "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1.JSONSchemaProps": {
      "description": "JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/).",
      "properties": {
        "$ref": {
          "type": "string"
        },
        "$schema": {
          "type": "string"
        },
        "additionalItems": {
          "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1.JSONSchemaPropsOrBool"
        },
        "additionalProperties": {
          "$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1.JSONSchemaPropsOrBool"
        },
...
Traceback (most recent call last):
  File "/snipped-path/src/main/python/project/app.py", line 387, in main
    app.run()
  File "/snipped-path/src/main/python/project/app.py", line 241, in run
    self._run_handlers(KtorPlugin.handle_start, False, context)
  File "/snipped-path/src/main/python/project/app.py", line 274, in _run_handlers
    h_f(*args, **kwargs)
  File "/snipped-path/src/main/python/project/k8s/__init__.py", line 44, in handle_start
    validate_v2_spec(p_json, p_uri)
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/shortcuts.py", line 7, in validate
    return validator_callable(spec, spec_url=spec_url)
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/validators.py", line 47, in validate
    for err in self.iter_errors(spec, spec_url=spec_url):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 58, in wrapper
    for err in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/validators.py", line 56, in iter_errors
    for err in validator.iter_errors(spec):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 282, in properties
    for error in validator.descend(
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 263, in ref
    for error in validator.descend(instance, resolved):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 23, in patternProperties
    for error in validator.descend(
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 263, in ref
    for error in validator.descend(instance, resolved):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 282, in properties
    for error in validator.descend(
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 263, in ref
    for error in validator.descend(instance, resolved):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 282, in properties
    for error in validator.descend(
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 263, in ref
    for error in validator.descend(instance, resolved):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 23, in patternProperties
    for error in validator.descend(
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 263, in ref
    for error in validator.descend(instance, resolved):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 337, in oneOf
    errs = list(validator.descend(instance, subschema, schema_path=index))
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 263, in ref
    for error in validator.descend(instance, resolved):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 282, in properties
    for error in validator.descend(
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 35, in wrapped
    for res in func(validator, schema_element, target, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 337, in oneOf
    errs = list(validator.descend(instance, subschema, schema_path=index))
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 263, in ref
    for error in validator.descend(instance, resolved):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 282, in properties
    for error in validator.descend(
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 49, in additionalProperties
    for error in validator.descend(instance[extra], aP, path=extra):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 263, in ref
    for error in validator.descend(instance, resolved):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 282, in properties
    for error in validator.descend(
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 35, in wrapped
    for res in func(validator, schema_element, target, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 322, in anyOf
    errs = list(validator.descend(instance, subschema, schema_path=index))
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 263, in ref
    for error in validator.descend(instance, resolved):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 282, in properties
    for error in validator.descend(
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 49, in additionalProperties
    for error in validator.descend(instance[extra], aP, path=extra):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 35, in wrapped
    for res in func(validator, schema_element, target, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 263, in ref
    for error in validator.descend(instance, resolved):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 282, in properties
    for error in validator.descend(
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 49, in additionalProperties
    for error in validator.descend(instance[extra], aP, path=extra):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 263, in ref
    for error in validator.descend(instance, resolved):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 282, in properties
    for error in validator.descend(
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 35, in wrapped
    for res in func(validator, schema_element, target, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 322, in anyOf
    errs = list(validator.descend(instance, subschema, schema_path=index))
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 263, in ref
    for error in validator.descend(instance, resolved):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 282, in properties
    for error in validator.descend(
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 49, in additionalProperties
    for error in validator.descend(instance[extra], aP, path=extra):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 35, in wrapped
    for res in func(validator, schema_element, target, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 263, in ref
    for error in validator.descend(instance, resolved):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 282, in properties
    for error in validator.descend(
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 49, in additionalProperties
    for error in validator.descend(instance[extra], aP, path=extra):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 35, in wrapped
    for res in func(validator, schema_element, target, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 263, in ref
    for error in validator.descend(instance, resolved):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 22, in wrapped
    for res in func(validator, schema_element, instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/_validators.py", line 282, in properties
    for error in validator.descend(
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 344, in descend
    for error in self.iter_errors(instance, schema):
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
    for error in errors:
  File "/home/arcivanov/.pyenv/versions/project/lib/python3.9/site-packages/openapi_spec_validator/decorators.py", line 29, in wrapped
    if ref in self.visiting:
TypeError: unhashable type: 'dict'

image

image

0.4.2 test failures: tests/integration/test_validators.py::TestOAS{30,31}Validator::test_format_checkers

When running the test suite in 0.4.2, I get the following failures:

========================================================= test session starts =========================================================
platform linux -- Python 3.10.9, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 -- /tmp/openapi-schema-validator/.venv/bin/python
cachedir: .pytest_cache
rootdir: /tmp/openapi-schema-validator, configfile: pyproject.toml
plugins: flake8-1.1.0, cov-3.0.0
collected 58 items                                                                                                                    

tests/integration/test_validators.py::TestOAS30Validator::test_format_checkers FAILED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_null[boolean] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_null[array] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_null[integer] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_null[number] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_null[string] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable_untyped[True] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable_untyped[False] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable[boolean] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable[array] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable[integer] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable[number] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable[string] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable_enum_without_none PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable_enum_with_none PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_string_format_byte_valid[c3RyaW5n0] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_string_format_byte_valid[c3RyaW5n1] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_string_format_byte_invalid[string0] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_string_format_byte_invalid[string1] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_allof_required PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_required PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_read_only PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_write_only PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_required_read_only PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_required_write_only PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_oneof_required PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_oneof_discriminator[oneOf] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_oneof_discriminator[anyOf] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_oneof_discriminator[allOf] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable_ref[True] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable_ref[False] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable_schema_combos[True-oneOf-None is not valid under any of the given schemas] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable_schema_combos[True-anyOf-None is not valid under any of the given schemas] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable_schema_combos[True-allOf-None for not nullable] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable_schema_combos[False-oneOf-None is not valid under any of the given schemas] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable_schema_combos[False-anyOf-None is not valid under any of the given schemas] PASSED
tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_nullable_schema_combos[False-allOf-None for not nullable] PASSED
tests/integration/test_validators.py::TestOAS31Validator::test_format_checkers FAILED
tests/integration/test_validators.py::TestOAS30ReadWriteValidatorValidate::test_read_only PASSED
tests/integration/test_validators.py::TestOAS30ReadWriteValidatorValidate::test_write_only PASSED
tests/integration/test_validators.py::TestOAS30ReadWriteValidatorValidate::test_required_read_only PASSED
tests/integration/test_validators.py::TestOAS30ReadWriteValidatorValidate::test_required_write_only PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_null[boolean] PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_null[array] PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_null[integer] PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_null[number] PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_null[string] PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_nullable[boolean] PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_nullable[array] PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_nullable[integer] PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_nullable[number] PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_nullable[string] PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_schema_validation PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_schema_ref PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_array_prefixitems[value0] PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_array_prefixitems[value1] PASSED
tests/integration/test_validators.py::TestOAS31ValidatorValidate::test_array_prefixitems_invalid[value0] PASSED
tests/unit/test_shortcut.py::ValidateTest::test_validate_does_not_mutate_schema_adding_nullable_key PASSED

============================================================== FAILURES ===============================================================
_______________________________________________ TestOAS30Validator.test_format_checkers _______________________________________________

self = <test_validators.TestOAS30Validator object at 0x7f0996aea470>

    def test_format_checkers(self):
>       assert set(OAS30Validator.FORMAT_CHECKER.checkers.keys()) == set([
            # standard formats
            "int32", "int64", "float", "double", "byte", "binary",
            "date", "date-time", "password",
            # extra formats
            "uuid", "regex",
            "ipv4", "ipv6", "email", "idn-email", "time"
        ])
E       AssertionError: assert {'binary',\n 'byte',\n 'date',\n 'double',\n 'email',\n 'float',\n 'idn-email',\n 'idn-hostname',\n 'int32',\n 'int64',\n 'ipv4',\n 'ipv6',\n 'password',\n 'regex',\n 'time',\n 'uuid'} == {'binary',\n 'byte',\n 'date',\n 'date-time',\n 'double',\n 'email',\n 'float',\n 'idn-email',\n 'int32',\n 'int64',\n 'ipv4',\n 'ipv6',\n 'password',\n 'regex',\n 'time',\n 'uuid'}
E         Extra items in the left set:
E         'idn-hostname'
E         Extra items in the right set:
E         'date-time'
E         Full diff:
E           {
E            'binary',
E            'byte',
E            'date',
E         -  'date-time',
E            'double',
E            'email',
E            'float',
E            'idn-email',
E         +  'idn-hostname',
E            'int32',
E            'int64',
E            'ipv4',
E            'ipv6',
E            'password',
E            'regex',
E            'time',
E            'uuid',
E           }

self       = <test_validators.TestOAS30Validator object at 0x7f0996aea470>

tests/integration/test_validators.py:17: AssertionError
_______________________________________________ TestOAS31Validator.test_format_checkers _______________________________________________

self = <test_validators.TestOAS31Validator object at 0x7f09969c2920>

    def test_format_checkers(self):
>       assert set(OAS31Validator.FORMAT_CHECKER.checkers.keys()) == set([
            # standard formats
            "int32", "int64", "float", "double", "password",
            # extra formats
            "date", "date-time", "uuid", "regex",
            "ipv4", "ipv6", "email", "idn-email", "time"
        ])
E       AssertionError: assert {'date',\n 'double',\n 'email',\n 'float',\n 'idn-email',\n 'idn-hostname',\n 'int32',\n 'int64',\n 'ipv4',\n 'ipv6',\n 'password',\n 'regex',\n 'time',\n 'uuid'} == {'date',\n 'date-time',\n 'double',\n 'email',\n 'float',\n 'idn-email',\n 'int32',\n 'int64',\n 'ipv4',\n 'ipv6',\n 'password',\n 'regex',\n 'time',\n 'uuid'}
E         Extra items in the left set:
E         'idn-hostname'
E         Extra items in the right set:
E         'date-time'
E         Full diff:
E           {
E            'date',
E         -  'date-time',
E            'double',
E            'email',
E            'float',
E            'idn-email',
E         +  'idn-hostname',
E            'int32',
E            'int64',
E            'ipv4',
E            'ipv6',
E            'password',
E            'regex',
E            'time',
E            'uuid',
E           }

self       = <test_validators.TestOAS31Validator object at 0x7f09969c2920>

tests/integration/test_validators.py:474: AssertionError
--------------------------------- generated xml file: /tmp/openapi-schema-validator/reports/junit.xml ---------------------------------

---------- coverage: platform linux, python 3.10.9-final-0 -----------
Name                                      Stmts   Miss Branch BrPart  Cover   Missing
-------------------------------------------------------------------------------------
openapi_schema_validator/__init__.py         13      0      0      0   100%
openapi_schema_validator/_format.py          41      7      6      1    79%   19, 25, 29, 36, 43-46
openapi_schema_validator/_types.py           12      0      0      0   100%
openapi_schema_validator/_validators.py     125     25     72     10    73%   37, 47-53, 62, 131, 133->exit, 146-150, 160, 184, 186->185, 188->195, 205, 207->206, 209->213, 222-237
openapi_schema_validator/shortcuts.py        13      1      2      1    87%   23
openapi_schema_validator/validators.py       37      0      6      0   100%
-------------------------------------------------------------------------------------
TOTAL                                       241     33     86     12    80%
Coverage XML written to file reports/coverage.xml

======================================================= short test summary info =======================================================
FAILED tests/integration/test_validators.py::TestOAS30Validator::test_format_checkers - AssertionError: assert {'binary',\n 'byte',\...
FAILED tests/integration/test_validators.py::TestOAS31Validator::test_format_checkers - AssertionError: assert {'date',\n 'double',\...
==================================================== 2 failed, 56 passed in 0.55s =====================================================

I can reproduce it reliably in a venv via:

git clone https://github.com/p1c2u/openapi-schema-validator/
cd openapi-schema-validator/
git checkout 0.4.2
poetry install
pytest -vv

On a production system, I get even more mismatches:

_______________________________________________ TestOAS30Validator.test_format_checkers _______________________________________________

self = <test_validators.TestOAS30Validator object at 0x7f6ee63cceb0>

    def test_format_checkers(self):
>       assert set(OAS30Validator.FORMAT_CHECKER.checkers.keys()) == set([
            # standard formats
            "int32", "int64", "float", "double", "byte", "binary",
            "date", "date-time", "password",
            # extra formats
            "uuid", "regex",
            "ipv4", "ipv6", "email", "idn-email", "time"
        ])
E       AssertionError: assert {'color', 'byte', 'idn-hostname', 'email', 'hostname', 'float', 'ipv6', 'idn-email', 'time', 'double', 'uri-template', 'password', 'uri-reference', 'duration', 'regex', 'uri', 'date', 'ipv4', 'int32', 'iri-reference', 'date-time', 'relative-json-pointer', 'iri', 'binary', 'uuid', 'json-pointer', 'int64'} == {'byte', 'time', 'ipv6', 'date', 'regex', 'double', 'email', 'float', 'int32', 'binary', 'password', 'uuid', 'ipv4', 'date-time', 'in
t64', 'idn-email'}
E         Extra items in the left set:
E         'color'
E         'uri'
E         'relative-json-pointer'
E         'idn-hostname'
E         'hostname'
E         'iri'
E         'uri-template'
E         'uri-reference'
E         'iri-reference'
E         'duration'
E         'json-pointer'
E         Full diff:
E           {
E            'binary',
E            'byte',
E         +  'color',
E            'date',
E            'date-time',
E            'double',
E         +  'duration',
E            'email',
E            'float',
E         +  'hostname',
E            'idn-email',
E         +  'idn-hostname',
E            'int32',
E            'int64',
E            'ipv4',
E            'ipv6',
E         +  'iri',
E         +  'iri-reference',
E         +  'json-pointer',
E            'password',
E            'regex',
E         +  'relative-json-pointer',
E            'time',
E         +  'uri',
E         +  'uri-reference',
E         +  'uri-template',
E            'uuid',
E           }

self       = <test_validators.TestOAS30Validator object at 0x7f6ee63cceb0>

tests/integration/test_validators.py:17: AssertionError
_______________________________________________ TestOAS31Validator.test_format_checkers _______________________________________________

self = <test_validators.TestOAS31Validator object at 0x7f6ee642d6f0>

    def test_format_checkers(self):
>       assert set(OAS31Validator.FORMAT_CHECKER.checkers.keys()) == set([
            # standard formats
            "int32", "int64", "float", "double", "password",
            # extra formats
            "date", "date-time", "uuid", "regex",
            "ipv4", "ipv6", "email", "idn-email", "time"
        ])
E       AssertionError: assert {'color', 'idn-hostname', 'email', 'hostname', 'float', 'ipv6', 'idn-email', 'time', 'double', 'uri-template', 'password', 'uri-reference', 'duration', 'regex', 'uri', 'date', 'ipv4', 'int32', 'iri-reference', 'date-time', 'relative-json-pointer', 'iri', 'uuid', 'json-pointer', 'int64'} == {'time', 'ipv6', 'date', 'regex', 'double', 'email', 'float', 'password', 'int32', 'uuid', 'ipv4', 'date-time', 'int64', 'idn-email'}
E         Extra items in the left set:
E         'color'
E         'uri'
E         'relative-json-pointer'
E         'idn-hostname'
E         'hostname'
E         'iri'
E         'uri-template'
E         'uri-reference'
E         'iri-reference'
E         'duration'
E         'json-pointer'
E         Full diff:
E           {
E         +  'color',
E            'date',
E            'date-time',
E            'double',
E         +  'duration',
E            'email',
E            'float',
E         +  'hostname',
E            'idn-email',
E         +  'idn-hostname',
E            'int32',
E            'int64',
E            'ipv4',
E            'ipv6',
E         +  'iri',
E         +  'iri-reference',
E         +  'json-pointer',
E            'password',
E            'regex',
E         +  'relative-json-pointer',
E            'time',
E         +  'uri',
E         +  'uri-reference',
E         +  'uri-template',
E            'uuid',
E           }

self       = <test_validators.TestOAS31Validator object at 0x7f6ee642d6f0>

tests/integration/test_validators.py:474: AssertionError
-- generated xml file: /tmp/portage/dev-python/openapi-schema-validator-0.4.2/work/openapi-schema-validator-0.4.2/reports/junit.xml ---
======================================================= short test summary info =======================================================

test_array_prefixitems_invalid[value0] failing on 0.6.2

Hi, we're seeing the following test fail. Our environment is

  • Python 3.11.6
  • jsonschema 4.20.0
  • jsonschema-specifications 2023.11.2
  • rfc3339-validator 0.1.4
openapi-schema-validator> ______ TestOAS31ValidatorValidate.test_array_prefixitems_invalid[value0] _______
openapi-schema-validator> 
openapi-schema-validator> self = <test_validators.TestOAS31ValidatorValidate object at 0x7ffff5d0f710>
openapi-schema-validator> validator_class = <class 'jsonschema.validators.create.<locals>.Validator'>
openapi-schema-validator> value = [1600, 'Pennsylvania', 'Avenue', 'NW', 'Washington']
openapi-schema-validator> 
openapi-schema-validator>     @pytest.mark.parametrize(
openapi-schema-validator>         "value",
openapi-schema-validator>         [
openapi-schema-validator>             [1600, "Pennsylvania", "Avenue", "NW", "Washington"],
openapi-schema-validator>         ],
openapi-schema-validator>     )
openapi-schema-validator>     def test_array_prefixitems_invalid(self, validator_class, value):
openapi-schema-validator>         schema = {
openapi-schema-validator>             "type": "array",
openapi-schema-validator>             "prefixItems": [
openapi-schema-validator>                 {"type": "number"},
openapi-schema-validator>                 {"type": "string"},
openapi-schema-validator>                 {"enum": ["Street", "Avenue", "Boulevard"]},
openapi-schema-validator>                 {"enum": ["NW", "NE", "SW", "SE"]},
openapi-schema-validator>             ],
openapi-schema-validator>             "items": False,
openapi-schema-validator>         }
openapi-schema-validator>         validator = validator_class(
openapi-schema-validator>             schema,
openapi-schema-validator>             format_checker=oas31_format_checker,
openapi-schema-validator>         )
openapi-schema-validator>     
openapi-schema-validator>         with pytest.raises(ValidationError) as excinfo:
openapi-schema-validator>             validator.validate(value)
openapi-schema-validator>     
openapi-schema-validator>         error = "Expected at most 4 items, but found 5"
openapi-schema-validator> >       assert error in str(excinfo.value)
openapi-schema-validator> E       assert 'Expected at most 4 items, but found 5' in "Expected at most 4 items but found 1 extra: 'Washington'\n\nFailed validating 'items' in schema:\n    {'items': False,\n     'prefixItems': [{'type': 'number'},\n                     {'type': 'string'},\n                     {'enum': ['Street', 'Avenue', 'Boulevard']},\n                     {'enum': ['NW', 'NE', 'SW', 'SE']}],\n     'type': 'array'}\n\nOn instance:\n    [1600, 'Pennsylvania', 'Avenue', 'NW', 'Washington']"
openapi-schema-validator> E        +  where "Expected at most 4 items but found 1 extra: 'Washington'\n\nFailed validating 'items' in schema:\n    {'items': False,\n     'prefixItems': [{'type': 'number'},\n                     {'type': 'string'},\n                     {'enum': ['Street', 'Avenue', 'Boulevard']},\n                     {'enum': ['NW', 'NE', 'SW', 'SE']}],\n     'type': 'array'}\n\nOn instance:\n    [1600, 'Pennsylvania', 'Avenue', 'NW', 'Washington']" = str(<ValidationError: "Expected at most 4 items but found 1 extra: 'Washington'">)
openapi-schema-validator> E        +    where <ValidationError: "Expected at most 4 items but found 1 extra: 'Washington'"> = <ExceptionInfo <ValidationError: "Expected at most 4 items but found 1 extra: 'Washington'"> tblen=2>.value
openapi-schema-validator> 
openapi-schema-validator> error      = 'Expected at most 4 items, but found 5'
openapi-schema-validator> excinfo    = <ExceptionInfo <ValidationError: "Expected at most 4 items but found 1 extra: 'Washington'"> tblen=2>
openapi-schema-validator> schema     = {'items': False,
openapi-schema-validator>  'prefixItems': [{'type': 'number'},
openapi-schema-validator>                  {'type': 'string'},
openapi-schema-validator>                  {'enum': ['Street', 'Avenue', 'Boulevard']},
openapi-schema-validator>                  {'enum': ['NW', 'NE', 'SW', 'SE']}],
openapi-schema-validator>  'type': 'array'}
openapi-schema-validator> self       = <test_validators.TestOAS31ValidatorValidate object at 0x7ffff5d0f710>
openapi-schema-validator> validator  = Validator(schema={'items': False, 'prefixItems': [{'type': 'number'}, {'type': 'string'}, {'enum': ['Street', 'Avenue', 'Boulevard']}, {'enum': ['NW', 'NE', 'SW', 'SE']}], 'type': 'array'}, format_checker=<FormatChecker checkers=['date', 'date-time', 'double', 'email', 'float', 'idn-email', 'int32', 'int64', 'ipv4', 'ipv6', 'password', 'regex', 'time', 'uuid']>)
openapi-schema-validator> validator_class = <class 'jsonschema.validators.create.<locals>.Validator'>
openapi-schema-validator> value      = [1600, 'Pennsylvania', 'Avenue', 'NW', 'Washington']
openapi-schema-validator> 
openapi-schema-validator> tests/integration/test_validators.py:867: AssertionError

Failure to correctly validate required in allOf

Having one spec with optional properties and creating a derived spec using allOf that makes a property required fails. This should be supported according to json schema itself (e.g. here)

To reproduce (with 0.1.5):

from openapi_schema_validator import validate


schema = {
    "allOf": [
        {"type": "object", "properties": {"some_prop": {"type": "string"}}},
        {"type": "object", "required": ["some_prop"]},
    ]
}

validate({"another_prop": "bla"}, schema)

Expected behaviour: an error that the required property some_prop is missing. The code actually correctly figures that out, but when it tries to check whether it is ok to have that property missing because it is e.g. a readOnly missing in a write operation a "runtime" error is produced instead of a validation exception:

~/venvs/py39/lib/python3.9/site-packages/openapi_schema_validator/_validators.py in required(validator, required, instance, schema)
     41     for property in required:
     42         if property not in instance:
---> 43             prop_schema = schema['properties'][property]
     44             read_only = prop_schema.get('readOnly', False)
     45             write_only = prop_schema.get('writeOnly', False)

KeyError: 'properties'

The problem is that here schema is only the second schema with the required - but the property can come from any schema in the allOf.

Pattern validation: error: bad escape \z

I've got an issue with validation Django User model schema generated by django-rest-framework

error: bad escape \z

image

To mimic other engines drf changes python '\Z' to '\z` that cause problem with validation on python>3.6

Probably the same problem could happens with any other scheme, came from not-python backend.

jsonschema iter_errors deprecation warnings

jsonschema>=4.0.0 has deprecated passing a second-argument schema to Validator.iter_errors

DeprecationWarning: Passing a schema to Validator.iter_errors is deprecated and will be removed in a future release. Call validator.evolve(schema=new_schema).iter_errors(...) instead.

Formats raise error for other types

Given:

schema = {"format": "byte"}

or

schema = {"format": "binary"}

Then:

from openapi_schema_validator import validate
from openapi_schema_validator import OAS30Validator

validate(1.23, schema, cls=OAS30Validator, format_checker=OAS30Validator.FORMAT_CHECKER)

Result:

ValidationError: 1.23 is not a 'byte'

Expected:
It should ignore other types and pass

How to resolve local references with jsonschema/referencing

Hi, so I'm sorry for the probably dumb question, but I've been banging my head against this and am getting nowhere.

I have an openapi spec like this

components:
  schemas:
    something:
      type: array
      items:
        "$ref": "#/components/schemas/uuid"
    uuid:
      pattern: "^((\\{urn:uuid:)?([a-f0-9]{8})\\}?)$"
      type: string

Previously I could do validation like so:

schema = yaml.safe_load(open('openapi.yaml').read())
resolver = jsonschema.validators.RefResolver.from_schema(schema)
openapi_schema_validator.validate(
    ['{urn:uuid:deadbeef}'], 
    schema=schema['components']['schemas']['something'], 
    resolver=resolver)

But after the API switch to referencing, I'm stumped on how to create a Registry that "just" resolves these local pointers. I've tried following the guide in https://openapi-schema-validator.readthedocs.io/en/latest/references.html, like so

schema = yaml.safe_load(open('openapi.yaml').read())
definitions = schema['components']['schemas']
registry = referencing.Registry().with_resources([
    (f'urn:{k}-schema', referencing.Resource.from_contents(
        v, default_specification=DRAFT202012))
    for k, v in definitions.items()
])
openapi_schema_validator.validate(
    ['{urn:uuid:deadbeef}'],
    schema=schema['components']['schemas']['something'],
    registry=registry)

but that raises PointerToNowhere: '/components/schemas/uuid' does not exist within {'type': 'array', 'items': {'$ref': '#/components/schemas/uuid'}}

Thanks for your help!

Exception when validating schema with required in oneOf

Code:

from openapi_schema_validator import validate
instance = {
    'n3IwfId': 'string',
}
schema = {
    "type": "object",
    "properties": {
        "n3IwfId": {"type": "string"},
        "wagfId": {"type": "string"},
    },
    "oneOf": [
        {"required": ["n3IwfId"]},
        {"required": ["wagfId"]},
    ],
}
validate(instance, schema)

Exception:
File "/usr/local/lib/python3.9/site-packages/jsonschema/validators.py", line 328, in iter_errors
for error in errors:
File "/usr/local/lib/python3.9/site-packages/openapi_schema_validator/_validators.py", line 43, in required
prop_schema = schema['properties'][property]
KeyError: 'properties'

0.2.0: pytest is failing

I'm trying to package your module as an rpm package. So I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.

  • python3 -sBm build -w --no-isolation
  • because I'm calling build with --no-isolation I'm using during all processes only locally installed modules
  • install .whl file in </install/prefix>
  • run pytest with PYTHONPATH pointing to sitearch and sitelib inside </install/prefix>

Here is pytest output:

+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-openapi-schema-validator-0.2.0-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-openapi-schema-validator-0.2.0-2.fc35.x86_64/usr/lib/python3.8/site-packages
+ /usr/bin/pytest -ra -q
=========================================================================== test session starts ============================================================================
platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /home/tkloczko/rpmbuild/BUILD/openapi-schema-validator-0.2.0, configfile: pyproject.toml
plugins: cov-3.0.0
collected 26 items

tests/integration/test_validators.py ............FF..FF.......
tests/unit/test_shortcut.py ./usr/lib64/python3.8/site-packages/coverage/control.py:768: CoverageWarning: No data was collected. (no-data-collected)
  self._warn("No data was collected.", slug="no-data-collected")


================================================================================= FAILURES =================================================================================
______________________________________ TestOAS30ValidatorValidate.test_string_format_datetime_rfc3339_validator[1989-01-02T00:00:00Z] ______________________________________

self = <test_validators.TestOAS30ValidatorValidate object at 0x7fe3212191f0>, value = '1989-01-02T00:00:00Z'

    @pytest.mark.parametrize('value', [
        u'1989-01-02T00:00:00Z',
        u'2018-01-02T23:59:59Z',
    ])
    @mock.patch(
        'openapi_schema_validator._format.'
        'DATETIME_HAS_RFC3339_VALIDATOR', True
    )
    @mock.patch(
        'openapi_schema_validator._format.'
        'DATETIME_HAS_STRICT_RFC3339', False
    )
    @mock.patch(
        'openapi_schema_validator._format.'
        'DATETIME_HAS_ISODATE', False
    )
    def test_string_format_datetime_rfc3339_validator(self, value):
        schema = {"type": 'string', "format": 'date-time'}
        validator = OAS30Validator(
            schema, format_checker=oas30_format_checker)

>       result = validator.validate(value)

schema     = {'format': 'date-time', 'type': 'string'}
self       = <test_validators.TestOAS30ValidatorValidate object at 0x7fe3212191f0>
validator  = OAS30Validator(schema={'format': 'date-time', 'type': 'string'}, format_checker=<FormatChecker checkers=['binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
value      = '1989-01-02T00:00:00Z'

tests/integration/test_validators.py:83:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.8/site-packages/jsonschema/validators.py:253: in validate
    for error in self.iter_errors(*args, **kwargs):
        args       = ('1989-01-02T00:00:00Z',)
        kwargs     = {}
        self       = OAS30Validator(schema={'format': 'date-time', 'type': 'string'}, format_checker=<FormatChecker checkers=['binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
/usr/lib/python3.8/site-packages/jsonschema/validators.py:229: in iter_errors
    for error in errors:
        _schema    = {'format': 'date-time', 'nullable': False, 'type': 'string'}
        applicable_validators = <function <lambda> at 0x7fe32157b670>
        errors     = <generator object format at 0x7fe3224d8e40>
        id_of      = <function <lambda> at 0x7fe321546ee0>
        instance   = '1989-01-02T00:00:00Z'
        k          = 'format'
        scope      = ''
        self       = OAS30Validator(schema={'format': 'date-time', 'nullable': False, 'type': 'string'}, format_checker=<FormatChecker chec...binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
        v          = 'date-time'
        validator  = <function format at 0x7fe321546a60>
../../BUILDROOT/python-openapi-schema-validator-0.2.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/openapi_schema_validator/_validators.py:19: in format
    validator.format_checker.check(instance, format)
        format     = 'date-time'
        instance   = '1989-01-02T00:00:00Z'
        schema     = {'format': 'date-time', 'nullable': False, 'type': 'string'}
        validator  = OAS30Validator(schema={'format': 'date-time', 'nullable': False, 'type': 'string'}, format_checker=<FormatChecker chec...binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
../../BUILDROOT/python-openapi-schema-validator-0.2.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/openapi_schema_validator/_format.py:135: in check
    result = func(instance)
        cause      = None
        format     = 'date-time'
        func       = <function is_datetime at 0x7fe3215464c0>
        instance   = '1989-01-02T00:00:00Z'
        raises     = (<class 'ValueError'>, <class 'TypeError'>)
        result     = None
        self       = <FormatChecker checkers=['binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

instance = '1989-01-02T00:00:00Z'

    def is_datetime(instance):
        if not isinstance(instance, (bytes, str)):
            return False

        if DATETIME_HAS_RFC3339_VALIDATOR:
>           return validate_rfc3339(instance)
E           NameError: name 'validate_rfc3339' is not defined

instance   = '1989-01-02T00:00:00Z'

../../BUILDROOT/python-openapi-schema-validator-0.2.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/openapi_schema_validator/_format.py:76: NameError
______________________________________ TestOAS30ValidatorValidate.test_string_format_datetime_rfc3339_validator[2018-01-02T23:59:59Z] ______________________________________

self = <test_validators.TestOAS30ValidatorValidate object at 0x7fe32113c4f0>, value = '2018-01-02T23:59:59Z'

    @pytest.mark.parametrize('value', [
        u'1989-01-02T00:00:00Z',
        u'2018-01-02T23:59:59Z',
    ])
    @mock.patch(
        'openapi_schema_validator._format.'
        'DATETIME_HAS_RFC3339_VALIDATOR', True
    )
    @mock.patch(
        'openapi_schema_validator._format.'
        'DATETIME_HAS_STRICT_RFC3339', False
    )
    @mock.patch(
        'openapi_schema_validator._format.'
        'DATETIME_HAS_ISODATE', False
    )
    def test_string_format_datetime_rfc3339_validator(self, value):
        schema = {"type": 'string', "format": 'date-time'}
        validator = OAS30Validator(
            schema, format_checker=oas30_format_checker)

>       result = validator.validate(value)

schema     = {'format': 'date-time', 'type': 'string'}
self       = <test_validators.TestOAS30ValidatorValidate object at 0x7fe32113c4f0>
validator  = OAS30Validator(schema={'format': 'date-time', 'type': 'string'}, format_checker=<FormatChecker checkers=['binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
value      = '2018-01-02T23:59:59Z'

tests/integration/test_validators.py:83:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.8/site-packages/jsonschema/validators.py:253: in validate
    for error in self.iter_errors(*args, **kwargs):
        args       = ('2018-01-02T23:59:59Z',)
        kwargs     = {}
        self       = OAS30Validator(schema={'format': 'date-time', 'type': 'string'}, format_checker=<FormatChecker checkers=['binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
/usr/lib/python3.8/site-packages/jsonschema/validators.py:229: in iter_errors
    for error in errors:
        _schema    = {'format': 'date-time', 'nullable': False, 'type': 'string'}
        applicable_validators = <function <lambda> at 0x7fe32157b670>
        errors     = <generator object format at 0x7fe3211ce0b0>
        id_of      = <function <lambda> at 0x7fe321546ee0>
        instance   = '2018-01-02T23:59:59Z'
        k          = 'format'
        scope      = ''
        self       = OAS30Validator(schema={'format': 'date-time', 'nullable': False, 'type': 'string'}, format_checker=<FormatChecker chec...binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
        v          = 'date-time'
        validator  = <function format at 0x7fe321546a60>
../../BUILDROOT/python-openapi-schema-validator-0.2.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/openapi_schema_validator/_validators.py:19: in format
    validator.format_checker.check(instance, format)
        format     = 'date-time'
        instance   = '2018-01-02T23:59:59Z'
        schema     = {'format': 'date-time', 'nullable': False, 'type': 'string'}
        validator  = OAS30Validator(schema={'format': 'date-time', 'nullable': False, 'type': 'string'}, format_checker=<FormatChecker chec...binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
../../BUILDROOT/python-openapi-schema-validator-0.2.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/openapi_schema_validator/_format.py:135: in check
    result = func(instance)
        cause      = None
        format     = 'date-time'
        func       = <function is_datetime at 0x7fe3215464c0>
        instance   = '2018-01-02T23:59:59Z'
        raises     = (<class 'ValueError'>, <class 'TypeError'>)
        result     = None
        self       = <FormatChecker checkers=['binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

instance = '2018-01-02T23:59:59Z'

    def is_datetime(instance):
        if not isinstance(instance, (bytes, str)):
            return False

        if DATETIME_HAS_RFC3339_VALIDATOR:
>           return validate_rfc3339(instance)
E           NameError: name 'validate_rfc3339' is not defined

instance   = '2018-01-02T23:59:59Z'

../../BUILDROOT/python-openapi-schema-validator-0.2.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/openapi_schema_validator/_format.py:76: NameError
___________________________________________ TestOAS30ValidatorValidate.test_string_format_datetime_isodate[1989-01-02T00:00:00Z] ___________________________________________

self = <test_validators.TestOAS30ValidatorValidate object at 0x7fe3212424f0>, value = '1989-01-02T00:00:00Z'

    @pytest.mark.parametrize('value', [
        u'1989-01-02T00:00:00Z',
        u'2018-01-02T23:59:59Z',
    ])
    @mock.patch(
        'openapi_schema_validator._format.'
        'DATETIME_HAS_RFC3339_VALIDATOR', False
    )
    @mock.patch(
        'openapi_schema_validator._format.'
        'DATETIME_HAS_STRICT_RFC3339', False
    )
    @mock.patch(
        'openapi_schema_validator._format.'
        'DATETIME_HAS_ISODATE', True
    )
    def test_string_format_datetime_isodate(self, value):
        schema = {"type": 'string', "format": 'date-time'}
        validator = OAS30Validator(
            schema, format_checker=oas30_format_checker)

>       result = validator.validate(value)

schema     = {'format': 'date-time', 'type': 'string'}
self       = <test_validators.TestOAS30ValidatorValidate object at 0x7fe3212424f0>
validator  = OAS30Validator(schema={'format': 'date-time', 'type': 'string'}, format_checker=<FormatChecker checkers=['binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
value      = '1989-01-02T00:00:00Z'

tests/integration/test_validators.py:133:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.8/site-packages/jsonschema/validators.py:253: in validate
    for error in self.iter_errors(*args, **kwargs):
        args       = ('1989-01-02T00:00:00Z',)
        kwargs     = {}
        self       = OAS30Validator(schema={'format': 'date-time', 'type': 'string'}, format_checker=<FormatChecker checkers=['binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
/usr/lib/python3.8/site-packages/jsonschema/validators.py:229: in iter_errors
    for error in errors:
        _schema    = {'format': 'date-time', 'nullable': False, 'type': 'string'}
        applicable_validators = <function <lambda> at 0x7fe32157b670>
        errors     = <generator object format at 0x7fe3211ce660>
        id_of      = <function <lambda> at 0x7fe321546ee0>
        instance   = '1989-01-02T00:00:00Z'
        k          = 'format'
        scope      = ''
        self       = OAS30Validator(schema={'format': 'date-time', 'nullable': False, 'type': 'string'}, format_checker=<FormatChecker chec...binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
        v          = 'date-time'
        validator  = <function format at 0x7fe321546a60>
../../BUILDROOT/python-openapi-schema-validator-0.2.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/openapi_schema_validator/_validators.py:19: in format
    validator.format_checker.check(instance, format)
        format     = 'date-time'
        instance   = '1989-01-02T00:00:00Z'
        schema     = {'format': 'date-time', 'nullable': False, 'type': 'string'}
        validator  = OAS30Validator(schema={'format': 'date-time', 'nullable': False, 'type': 'string'}, format_checker=<FormatChecker chec...binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
../../BUILDROOT/python-openapi-schema-validator-0.2.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/openapi_schema_validator/_format.py:135: in check
    result = func(instance)
        cause      = None
        format     = 'date-time'
        func       = <function is_datetime at 0x7fe3215464c0>
        instance   = '1989-01-02T00:00:00Z'
        raises     = (<class 'ValueError'>, <class 'TypeError'>)
        result     = None
        self       = <FormatChecker checkers=['binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

instance = '1989-01-02T00:00:00Z'

    def is_datetime(instance):
        if not isinstance(instance, (bytes, str)):
            return False

        if DATETIME_HAS_RFC3339_VALIDATOR:
            return validate_rfc3339(instance)

        if DATETIME_HAS_STRICT_RFC3339:
            return strict_rfc3339.validate_rfc3339(instance)

        if DATETIME_HAS_ISODATE:
>           return isodate.parse_datetime(instance)
E           NameError: name 'isodate' is not defined

instance   = '1989-01-02T00:00:00Z'

../../BUILDROOT/python-openapi-schema-validator-0.2.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/openapi_schema_validator/_format.py:82: NameError
___________________________________________ TestOAS30ValidatorValidate.test_string_format_datetime_isodate[2018-01-02T23:59:59Z] ___________________________________________

self = <test_validators.TestOAS30ValidatorValidate object at 0x7fe3211dc4c0>, value = '2018-01-02T23:59:59Z'

    @pytest.mark.parametrize('value', [
        u'1989-01-02T00:00:00Z',
        u'2018-01-02T23:59:59Z',
    ])
    @mock.patch(
        'openapi_schema_validator._format.'
        'DATETIME_HAS_RFC3339_VALIDATOR', False
    )
    @mock.patch(
        'openapi_schema_validator._format.'
        'DATETIME_HAS_STRICT_RFC3339', False
    )
    @mock.patch(
        'openapi_schema_validator._format.'
        'DATETIME_HAS_ISODATE', True
    )
    def test_string_format_datetime_isodate(self, value):
        schema = {"type": 'string', "format": 'date-time'}
        validator = OAS30Validator(
            schema, format_checker=oas30_format_checker)

>       result = validator.validate(value)

schema     = {'format': 'date-time', 'type': 'string'}
self       = <test_validators.TestOAS30ValidatorValidate object at 0x7fe3211dc4c0>
validator  = OAS30Validator(schema={'format': 'date-time', 'type': 'string'}, format_checker=<FormatChecker checkers=['binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
value      = '2018-01-02T23:59:59Z'

tests/integration/test_validators.py:133:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.8/site-packages/jsonschema/validators.py:253: in validate
    for error in self.iter_errors(*args, **kwargs):
        args       = ('2018-01-02T23:59:59Z',)
        kwargs     = {}
        self       = OAS30Validator(schema={'format': 'date-time', 'type': 'string'}, format_checker=<FormatChecker checkers=['binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
/usr/lib/python3.8/site-packages/jsonschema/validators.py:229: in iter_errors
    for error in errors:
        _schema    = {'format': 'date-time', 'nullable': False, 'type': 'string'}
        applicable_validators = <function <lambda> at 0x7fe32157b670>
        errors     = <generator object format at 0x7fe32119d350>
        id_of      = <function <lambda> at 0x7fe321546ee0>
        instance   = '2018-01-02T23:59:59Z'
        k          = 'format'
        scope      = ''
        self       = OAS30Validator(schema={'format': 'date-time', 'nullable': False, 'type': 'string'}, format_checker=<FormatChecker chec...binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
        v          = 'date-time'
        validator  = <function format at 0x7fe321546a60>
../../BUILDROOT/python-openapi-schema-validator-0.2.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/openapi_schema_validator/_validators.py:19: in format
    validator.format_checker.check(instance, format)
        format     = 'date-time'
        instance   = '2018-01-02T23:59:59Z'
        schema     = {'format': 'date-time', 'nullable': False, 'type': 'string'}
        validator  = OAS30Validator(schema={'format': 'date-time', 'nullable': False, 'type': 'string'}, format_checker=<FormatChecker chec...binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>, read=None, write=None)
../../BUILDROOT/python-openapi-schema-validator-0.2.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/openapi_schema_validator/_format.py:135: in check
    result = func(instance)
        cause      = None
        format     = 'date-time'
        func       = <function is_datetime at 0x7fe3215464c0>
        instance   = '2018-01-02T23:59:59Z'
        raises     = (<class 'ValueError'>, <class 'TypeError'>)
        result     = None
        self       = <FormatChecker checkers=['binary', 'byte', 'date', 'date-time', 'double', 'float', 'int32', 'int64', 'password', 'uuid']>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

instance = '2018-01-02T23:59:59Z'

    def is_datetime(instance):
        if not isinstance(instance, (bytes, str)):
            return False

        if DATETIME_HAS_RFC3339_VALIDATOR:
            return validate_rfc3339(instance)

        if DATETIME_HAS_STRICT_RFC3339:
            return strict_rfc3339.validate_rfc3339(instance)

        if DATETIME_HAS_ISODATE:
>           return isodate.parse_datetime(instance)
E           NameError: name 'isodate' is not defined

instance   = '2018-01-02T23:59:59Z'

../../BUILDROOT/python-openapi-schema-validator-0.2.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/openapi_schema_validator/_format.py:82: NameError
------------------------------------ generated xml file: /home/tkloczko/rpmbuild/BUILD/openapi-schema-validator-0.2.0/reports/junit.xml ------------------------------------

---------- coverage: platform linux, python 3.8.12-final-0 -----------
Name                                      Stmts   Miss  Cover   Missing
-----------------------------------------------------------------------
openapi_schema_validator/__init__.py          9      9     0%   2-12
openapi_schema_validator/_format.py          84     84     0%   1-146
openapi_schema_validator/_types.py            4      4     0%   1-11
openapi_schema_validator/_validators.py      60     60     0%   1-90
openapi_schema_validator/shortcuts.py         8      8     0%   1-11
openapi_schema_validator/validators.py       18     18     0%   1-78
-----------------------------------------------------------------------
TOTAL                                       183    183     0%
Coverage XML written to file reports/coverage.xml

========================================================================= short test summary info ==========================================================================
FAILED tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_string_format_datetime_rfc3339_validator[1989-01-02T00:00:00Z] - NameError: name 'validate_...
FAILED tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_string_format_datetime_rfc3339_validator[2018-01-02T23:59:59Z] - NameError: name 'validate_...
FAILED tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_string_format_datetime_isodate[1989-01-02T00:00:00Z] - NameError: name 'isodate' is not def...
FAILED tests/integration/test_validators.py::TestOAS30ValidatorValidate::test_string_format_datetime_isodate[2018-01-02T23:59:59Z] - NameError: name 'isodate' is not def...
======================================================================= 4 failed, 22 passed in 0.64s =======================================================================

Nullable Strings are not recognized, incorrect check for None if type is string

I was digging through the code and it seems for string type None validation there is no check for nullable. It is in the code but validate from shortcuts pulls directly the jsonschema type validator which ignores nullables alltoghether.

I am looking for a possibility for it wo work.
Can be easily replicated by adding to the examle on README a nullable string and put it in the content.

Validate doesnt seem to match schema correctly?

I am using validate against API responses.

 validate(openapi_schema_path, response.json())

seems to work on many of the apis. But when the api returns something like:

{"items":[4,5,6,1,2]}

which is an object with items property and an array of integers or objects in other cases. The validate throws

validation failed:
[6, 1, 2, 4, 5] is not of type 'object', 'boolean'

Failed validating 'type' in metaschema['allOf'][1]['properties']['items']['$dynamicRef']['allOf'][0]:
    {'$defs': {'anchorString': {'pattern': '^[A-Za-z_][-A-Za-z0-9._]*$',
                                'type': 'string'},
               'uriReferenceString': {'format': 'uri-reference',
                                      'type': 'string'},
               'uriString': {'format': 'uri', 'type': 'string'}},
     '$dynamicAnchor': 'meta',
     '$id': 'https://json-schema.org/draft/2020-12/meta/core',
     '$schema': 'https://json-schema.org/draft/2020-12/schema',
     '$vocabulary': {'https://json-schema.org/draft/2020-12/vocab/core': True},
     'properties': {'$anchor': {'$ref': '#/$defs/anchorString'},
                    '$comment': {'type': 'string'},
                    '$defs': {'additionalProperties': {'$dynamicRef': '#meta'},
                              'type': 'object'},
                    '$dynamicAnchor': {'$ref': '#/$defs/anchorString'},
                    '$dynamicRef': {'$ref': '#/$defs/uriReferenceString'},
                    '$id': {'$comment': 'Non-empty fragments not allowed.',
                            '$ref': '#/$defs/uriReferenceString',
                            'pattern': '^[^#]*#?$'},
                    '$ref': {'$ref': '#/$defs/uriReferenceString'},
                    '$schema': {'$ref': '#/$defs/uriString'},
                    '$vocabulary': {'additionalProperties': {'type': 'boolean'},
                                    'propertyNames': {'$ref': '#/$defs/uriString'},
                                    'type': 'object'}},
     'title': 'Core vocabulary meta-schema',
     'type': ['object', 'boolean']}

On schema['items']:
    [6, 1, 2, 4, 5]

the schema is defined as

methods:
      type: object
      properties:
        items:
          type: array
          items:
            type: integer

which matches the actual response.

Am i doing something wrong with validate?

Add support for discriminator

It would be nice to have support for the discriminator object so that anyOf or oneOf schemas can return good validation errors.

Exemple schema:

{
    "$ref": "#/$defs/Route",
    "$defs": {
        "MountainHiking": {
            "type": "object",
            "properties": {
                "discipline": {
                    "type": "string",
                    "enum": ["mountain_hiking"]
                },
                "length": {
                    "type": "integer",
                }
            },
            "required": ["discipline", "length"]
        },
        "AlpineClimbing": {
            "type": "object",
            "properties": {
                "discipline": {
                    "type": "string",
                    "enum": ["alpine_climbing"]
                },
                "height": {
                    "type": "integer",
                },
            },
            "required": ["discipline", "height"]
        },
        "Route": {
          "discriminator": {
              "propertyName": "discipline",
              "mapping": {
                  "mountain_hiking": {"$ref": "#/$defs/MountainHiking"},
                  "alpine_climbing": {"$ref": "#/$defs/AlpineClimbing"},
              }
          },
            "oneOf": [
                {"$ref": "#/$defs/MountainHiking"},
                {"$ref": "#/$defs/AlpineClimbing"},
            ]
        }
    }
}

Example instance:

{
    "discipline": "mountain_hiking",
    "length": "bad_string"
}

Current error:

....is not valid under any of the given schemas...

Expected error:

...'bad_string' is not of type integer...

Validating schema using yaml file

Hi, I have developed an openapi.yaml file which contains the schema that my API requests should follow. The schema is not small so I wouldn't like to hardcode it in JSON in my Python schema-validation application. Can I use that yaml file as reference in this schema validator?

Version 0.2.0 introduces breaking change due to version upgrade

Hi @p1c2u

Version 0.2.0 introduces a breaking change due to the upgrade of the lower bound for the jsonschema dependency.
You can see this downstream in these packages:

Restricting the version range of a dependency should be done as a major version update. The iter_errors change (#25) and accompanying version range restriction also should not have been needed yet for jsonschema 4.0.0, as it only provides a deprecation warning for future versions. The current approach leads to a very narrow range of compatibility with jsonschema and other dependent packages.

My proposal would be to release a patch version 0.2.1 reverting #25 and fixing the upper version of jsonschema to 5.0.0. When jsonschema 5.0.0 is released and the old behavior of iter_errors removed, #25 can be applied again, and the version range updated to support both 4.X.X and 5.X.X versions.

Validating schema with external references

Greetings,
I am attempting to use openapi-schema-validator to validate a bare JSON object against a specific OpenAPI Model. This JSON is received by my application by GET from a remote API, similar to the case in python-openapi/openapi-core#154 .

However, the wrinkle is that the model I am trying to validate against has external refs. OpenAPI-Core itself (given a spec_url) is able to resolve these external refs, but I am struggling to find a method to validate bare models that doesn't involve making a fake request and path, as described in 154.

Is there a way to provide OpenAPI-Schema-Valdiator with a resolver that's capable of resolving external refs (filenames)?

Alternatively, is there a way to retrieve a fully-flattened model definition (with $refs expanded) from an existing OpenAPI spec? openapi_spec.get_schema('Modelname') returns the original model with refs in place.

Thanks in advance for any guidance.

Failure to validate exclusiveMinimum for OpenAPI 3.0

The following code throws an error when validating:

from openapi_schema_validator import oas30_format_checker
from openapi_schema_validator import validate

# A sample schema
schema = {
    "type": "object",
    "required": [
        "duration"
    ],
    "properties": {
        "duration": {
            "type": "number",
            "exclusiveMinimum": True,
            "minimum": 0
        }
    },
    "additionalProperties": False,
}
validate({"duration": 10}, schema, format_checker=oas30_format_checker)

Failed validating 'type' in metaschema['allOf'][1]['properties']['properties']['additionalProperties']['$dynamicRef']['allOf'][3]['properties']['exclusiveMinimum']:
    {'type': 'number'}

On schema['properties']['duration']['exclusiveMinimum']:
    True

This is valid OpenAPI 3.0 syntax since it follows the Draft 5 JSON schema synatx:

https://swagger.io/specification/#schema-object
https://datatracker.ietf.org/doc/html/draft-wright-json-schema-validation-00#section-5.5

This would be an error in 3.0 if it was a number.

`readOnly` / `writeOnly` support for OpenAPI 3.1

Seems like read/write context-aware validators are only implemented for OpenAPI 3.0. Any reason not to implement a similar interface for 3.1?

For some context, I'm leveraging the openapi-core library and noticing that readOnly and writeOnly work great when validating against 3.0 specs, but do nothing with 3.1 specs.

Cannot import _legacy_validators

jsonschema released 2 hours ago comes with a change

2023-09-20_17-20

packages/openapi_schema_validator/validators.py:5: in <module>
    from jsonschema import _legacy_validators
E   ImportError: cannot import name '_legacy_validators' from 'jsonschema' (/tmp/gng_testing/lib64/python3.11/site-

suggestion

Do a conditional import on validators.py

try:
    from jsonschema import _legacy_validators
except ImportError:
    from jsonschema import _legacy_keywords as _legacy_validators

Support for scientific notation

This schema with scientific notation maximum: 1e2

openapi: 3.0.3
info:
  title: scientific notation
  description: ...
  version: 1.0.0
paths:
  /pet:
    put:
      tags:
        - pet
      summary: ...
      description: ...
      operationId: updatePet
      requestBody:
        description: ...
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Pet'
      responses:
        '200':
          description: Successful operation
components:
  schemas:
    Pet:
      type: object
      properties:
        id:
          type: integer
          format: int64
          maximum: 1e2
          example: 10

results in this unexpected failure

# Validation Error

{'description': '...', 'content': {'application/json': {'schema': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'maximum': '1e2', 'example': 10}}}}}} is not valid under any of the given schemas

Failed validating 'oneOf' in schema['properties']['paths']['patternProperties']['^\\/']['patternProperties']['^(get|put|post|delete|options|head|patch|trace)$']['properties']['requestBody']:
    {'oneOf': [{'$ref': '#/definitions/RequestBody'},
               {'$ref': '#/definitions/Reference'}]}

On instance['paths']['/pet']['put']['requestBody']:
    {'content': {'application/json': {'schema': {'properties': {'id': {'example': 10,
                                                                       'format': 'int64',
                                                                       'maximum': '1e2',
                                                                       'type': 'integer'}},
                                                 'type': 'object'}}},
     'description': '...'}


# Due to one of those errors

## {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'maximum': '1e2', 'example': 10}}} is not valid under any of the given schemas

Failed validating 'oneOf' in schema[0]['properties']['content']['additionalProperties']['properties']['schema']:
    {'oneOf': [{'$ref': '#/definitions/Schema'},
               {'$ref': '#/definitions/Reference'}]}

On instance['content']['application/json']['schema']:
    {'properties': {'id': {'example': 10,
                           'format': 'int64',
                           'maximum': '1e2',
                           'type': 'integer'}},
     'type': 'object'}


## '$ref' is a required property

Failed validating 'required' in schema[1]:
    {'patternProperties': {'^\\$ref$': {'format': 'uri-reference',
                                        'type': 'string'}},
     'required': ['$ref'],
     'type': 'object'}

On instance:
    {'content': {'application/json': {'schema': {'properties': {'id': {'example': 10,
                                                                       'format': 'int64',
                                                                       'maximum': '1e2',
                                                                       'type': 'integer'}},
                                                 'type': 'object'}}},
     'description': '...'}
...

If I change maximum: 1e2 to maximum: 100, it validates without error.

Inner any of type mismatch not raising error

If we have stacked any of and on the second level send strring, not an object, validator doesn't react.
If we do so on the top any of validator will find error as intended.
python 3.11.2
openapi_schema_validator 0.6.0

Expect error on validation, but there was not.

Object:

        {
            "animals_top_any_of": {
                "milk_product_additional_field": {
                    "product_spec_inner_any_of": "string_not_object_under_any_of_expect_error_but_there_is_not"
                }
            }
        }

Schema:

{
  "type": "object",
  "title": "Farm - top level",
  "allOf": [
    {
      "$ref": "#/components/schemas/Schema"
    }
  ],
  "components":{
    "schemas": {
      "Schema": {
        "properties":{
          "animals_top_any_of": {
            "type": "object",
            "description": "Animals top any Of",
            "anyOf": [
              {
                "$ref": "#/components/schemas/Mammal"
              },
              {
                "$ref": "#/components/schemas/Bird"
              }
            ]
          }
        },
        "required":[
          "animals_top_any_of"
        ]
      },
      "Mammal": {
        "title": "mammal - under to animals_top_any_of",
        "type": "object",
        "properties": {
          "milk_product_additional_field": {
            "$ref": "#/components/schemas/Dairy"
          }
        }
      },
      "Bird": {
        "title": "under animals_top_any_of",
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          }
        }
      },
      "Dairy": {
        "properties": {
          "product_spec_inner_any_of": {
            "type": "object",
            "description": "inner any of",
            "anyOf": [
              {
                "$ref": "#/components/schemas/Milk"
              },
              {
                "$ref": "#/components/schemas/Cream"
              }
            ]
          }
        },
        "required":[
          "product_spec_inner_any_of"
        ]
      },
      "Milk": {
        "title": "milk element inner any of",
        "type": "object",
        "properties": {
          "fat_percentage_int": {
            "type": "integer"
          }
        }
      },
      "Cream": {
        "title": "cream element inner any of",
        "type": "object",
        "properties": {
          "cream_only_viscosity_int": {
            "type": "integer"
          }
        }
      }
    }
  }
}


Top level any of type missmatch works as intended:
object:

            {
                "animals_top_any_of": "string_not_object_under_any_of_correctly_finds_error"
            }

Bug when a schema has a nullable AllOf ref

Hey! I have a weird issue that happens with refs that are nullable. I have the following schema:

"GroupWithRecentMessage": {
                "type": "object",
                "properties": {
                    "uid": {
                        "type": "string",
                        "format": "uuid",
                        "readOnly": true
                    },
                    "recent_message": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Message"
                            }
                        ],
                        "readOnly": true,
                        "nullable": true
                    }
                }
            }

Essentially what I try to express is that recent_message can be either null or an object of type Message.

When I run a validator it raises an exception:

openapi_core.unmarshalling.schemas.exceptions.InvalidSchemaValue: Value {
'results': [{'uid': '018a8f79-5098-478b-a77e-2adb685a1ea5', 'recent_message': None}]
} not valid for schema of type object: (<ValidationError: 'None for not nullable'>

After debugging the issue I have been able to find the root cause. I think the main reason why it happens is that openapi-schema-validator adds a "nullable": false to each ref. So the actual schema that ends being used is the following:

{'nullable': False,
 'properties': {'recent_message': {'allOf': [{'$ref': '#/components/schemas/Message',
                                              'nullable': False, # <---- this is what triggers the wrong error
                                              'x-scope': ['',
                                                          '#/components/schemas/GroupWithRecentMessage']}],
                                   'nullable': True,
                                   'readOnly': True},
                'uid': {'format': 'uuid',
                        'nullable': False,
                        'readOnly': True,
                        'type': 'string'}},
 'required': ['recent_message',
              'uid'],
 'type': 'object'}

How can I fix this issue?

Thanks!

Subclassing JSONSchema validator class with OAS30Validator

OAS 3.0 is incompatible with JSON Schema because it assumes context-sensitive validation (readOnly and writeOnly for request and response), which JSON Schema doesn't support.

Subclassing jsonschema validator classes is not intended to be part of their public API but it's the only way to add context-sensitive validation support.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.