Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: list instead of object give fatal AttributeError #26

Closed
andyceo opened this issue Apr 18, 2018 · 2 comments
Closed

Bug: list instead of object give fatal AttributeError #26

andyceo opened this issue Apr 18, 2018 · 2 comments

Comments

@andyceo
Copy link

andyceo commented Apr 18, 2018

Hi!

Using your great lib, I found very annoying bug: validating wrong response (that does not corresponds to the response given in OpenAPI spec) produce fatal AttributeError and script terminates it's work.

Expected behaviour

Library correctly handle wrong responses, give helpful validation error, and continue to work.

Steps to reproduce

  1. Install openapi-core:

     pip3 install openapi-core
    
  2. Create and save following script as listofobjectscheck.py:

     #!/usr/bin/env python3
     
     # -*- coding: utf-8 -*-
     import json
     import sys
     import yaml
     from openapi_core import create_spec
     from openapi_core.validators import RequestValidator, ResponseValidator
     from openapi_core.wrappers import MockRequest, MockResponse
     
     
     def validate(openapi_file):
         with open(openapi_file, 'r') as myfile:
             spec_dict = yaml.safe_load(myfile)
             spec = create_spec(spec_dict)
     
             openapi_request = MockRequest('localhost', 'get', '/someobjects')
             validator = RequestValidator(spec)
             result = validator.validate(openapi_request)
             request_errors = result.errors
     
             data = json.dumps([
                 {
                     'someint': 123,
                     'somestr': '123'
                 },
                 {
                     'someint': 345,
                     'somestr': '345'
                 }
             ])
     
             openapi_response = MockResponse(data)
             validator = ResponseValidator(spec)
             result = validator.validate(openapi_request, openapi_response)
             response_errors = result.errors
     
             print('Request errors: {} Response errors: {}'.format(request_errors, response_errors))
     
     
     if __name__ == "__main__":
         if len(sys.argv) < 2:
             print("Specify path to openapi.yaml file!")
             exit(1)
         else:
             validate(sys.argv[1])
    
  3. Create and save following specification as listofobjectsfail.yaml, that give us fatal error during validation:

     openapi: "3.0.0"
     
     info:
       version: "0.1"
       title: List of objects
       description: Test for list of objects
     
     components:
       schemas:
         SomeObject:
           type: object
           properties:
             someint:
               description: Some integer
               type: integer
               format: int32
               minimum: 0
               example: 667
             somestr:
               description: Some string
               type: string
     
     paths:
       /someobjects:
         get:
           summary: Get the someobjects list
           operationId: getSomeObjects
           responses:
             '200':
               description: List of someobjects
               content:
                 application/json:
                   schema:
                     $ref: '#/components/schemas/SomeObject'
    
  4. Execute script to validate spec:

     python3 listofobjectscheck.py listofobjectsfail.yaml
    

    This give us fatal error:

     $ python3 listofobjectscheck.py listofobjectsfail.yaml
     Traceback (most recent call last):
       File "listofobjectscheck.py", line 45, in <module>
         validate(sys.argv[1])
       File "listofobjectscheck.py", line 34, in validate
         result = validator.validate(openapi_request, openapi_response)
       File "~/.local/lib/python3.5/site-packages/openapi_core/validators.py", line 201, in validate
         data = media_type.unmarshal(raw_data)
       File "~/.local/lib/python3.5/site-packages/openapi_core/media_types.py", line 19, in unmarshal
         return self.schema.unmarshal(value)
       File "~/.local/lib/python3.5/site-packages/openapi_core/schemas.py", line 104, in unmarshal
         casted = self.cast(value)
       File "~/.local/lib/python3.5/site-packages/openapi_core/schemas.py", line 93, in cast
         return cast_callable(value)
       File "~/.local/lib/python3.5/site-packages/openapi_core/schemas.py", line 126, in _unmarshal_object
         value_keys = value.keys()
     AttributeError: 'list' object has no attribute 'keys'
    
  5. Fix wrong openapi file and save it as listofobjectsok.yaml:

     openapi: "3.0.0"
     
     info:
       version: "0.1"
       title: List of objects
       description: Test for list of objects
     
     components:
       schemas:
         SomeObject:
           type: object
           properties:
             someint:
               description: Some integer
               type: integer
               format: int32
               minimum: 0
               example: 667
             somestr:
               description: Some string
               type: string
     
     paths:
       /someobjects:
         get:
           summary: Get the someobjects list
           operationId: getSomeObjects
           responses:
             '200':
               description: List of someobjects
               content:
                 application/json:
                   schema:
                     type: array
                     items:
                       $ref: '#/components/schemas/SomeObject'
    
  6. Sure that now validation works fine:

     $ python3 listofobjectscheck.py listofobjectsok.yaml 
     Request errors: [] Response errors: []
    
@p1c2u
Copy link
Collaborator

p1c2u commented Apr 23, 2018

@andyceo thank you for the detailed bug report. It is very useful when investigating.

Every error not related to specification itself should be fatal error.

The bug should be fixed with #28 .

@andyceo
Copy link
Author

andyceo commented Apr 24, 2018

Hi @p1c2u !

I edited listofobjectscheck.py in initial report message to pass json string into openapi_response = MockResponse(data) instead of Python list (as we investigated earlier in #27 pull request).

Now everything works fine! Amazing work!

Can confirm this wrong API response now correctly handled without fatals:

$ python3 listofobjectscheck.py listofobjectsfail.yaml
Request errors: [] Response errors: [InvalidMediaTypeValue("Value of [{'somestr': '123', 'someint': 123}, {'somestr': '345', 'someint': 345}] not an object",)]

Closing issue.

@andyceo andyceo closed this as completed Apr 24, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants