Yelp / bravado-core

Other
109 stars 98 forks source link

Validation fails for x-nullable objects that happen to have discriminator #359

Closed xaralis closed 4 years ago

xaralis commented 4 years ago

Where a thing is defined as x-nullable and has a discriminator at the same time, bravado-core@5.14.0 validation fails with a TypeError in case the instance resolves to None:

Traceback (most recent call last):
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/falcon/api.py", line 286, in __call__
    process_response(req, resp, resource, req_succeeded)
  File "/Users/myself/project/.venv/kw/misc/openapi/validator.py", line 141, in process_response
    validate_response(resp_spec, operation, bravado_response)
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/bravado_core/response.py", line 175, in validate_response
    validate_response_body(op, response_spec, response)
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/bravado_core/response.py", line 214, in validate_response_body
    op.swagger_spec, response_body_spec, response_value,
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/bravado_core/validate.py", line 59, in validate_schema_object
    validate_object(swagger_spec, schema_object_spec, value)
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/bravado_core/validate.py", line 25, in scrubbed
    return func(*args, **kwargs)
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/bravado_core/validate.py", line 109, in validate_object
    ).validate(value)
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/jsonschema/validators.py", line 347, in validate
    for error in self.iter_errors(*args, **kwargs):
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/jsonschema/validators.py", line 323, in iter_errors
    for error in errors:
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/jsonschema/_validators.py", line 315, in allOf
    for error in validator.descend(instance, subschema, schema_path=index):
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/jsonschema/validators.py", line 339, in descend
    for error in self.iter_errors(instance, schema):
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/jsonschema/validators.py", line 323, in iter_errors
    for error in errors:
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/bravado_core/swagger20_validator.py", line 234, in ref_validator
    for error in validator.descend(instance, resolved):
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/jsonschema/validators.py", line 339, in descend
    for error in self.iter_errors(instance, schema):
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/jsonschema/validators.py", line 323, in iter_errors
    for error in errors:
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/jsonschema/_validators.py", line 286, in properties
    schema_path=property,
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/jsonschema/validators.py", line 339, in descend
    for error in self.iter_errors(instance, schema):
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/jsonschema/validators.py", line 323, in iter_errors
    for error in errors:
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/bravado_core/swagger20_validator.py", line 234, in ref_validator
    for error in validator.descend(instance, resolved):
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/jsonschema/validators.py", line 339, in descend
    for error in self.iter_errors(instance, schema):
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/jsonschema/validators.py", line 322, in iter_errors
    errors = validator(self, v, instance, _schema) or ()
  File "/Users/myself/project/.venv/.venv/lib/python3.7/site-packages/bravado_core/swagger20_validator.py", line 157, in discriminator_validator
    discriminator_value = instance[discriminator_attribute]
TypeError: 'NoneType' object is not subscriptable

This definitely should error out and instead validate A-OK in fact.

macisamuele commented 4 years ago

@xaralis sorry for the huge reply delay. I totally missed this 😞

Do you have a simple spec example and interaction that is able to reproduce it?

macisamuele commented 4 years ago

I was able to identify a minimal test case that is able to reproduce the issue

def test_issue_359(polymorphic_abspath, polymorphic_dict):
    polymorphic_dict['definitions']['GenericPet']['x-nullable'] = True
    polymorphic_spec = Spec.from_dict(polymorphic_dict)

    unmarshal_response(
        response=mock.Mock(
            spec=IncomingResponse,
            status_code=200,
            headers={'content-type': APP_JSON},
            json=mock.Mock(
                return_value={
                    'number_of_pets': 1,
                    'list': [None],
                },
            ),
        ),
        op=polymorphic_spec.resources['pets'].operations['get_pets'],
    )

Definitely the report looks like a bug.

@xaralis : thanks for opening it