pgjones / quart-schema

Quart-Schema is a Quart extension that provides schema validation and auto-generated API documentation.
MIT License
76 stars 24 forks source link

Now returns the decorated function #38

Closed tgaspar closed 1 year ago

tgaspar commented 1 year ago

I think I found a small bug in both the document and validate method. Both methods override the func object with the output of the decorator, which is a callable. I believe the desired behavior should be like the one proposed in my fix.

The consequence of this bug is that the following code:

from quart import Quart
from quart_schema import QuartSchema, document
from dataclasses import dataclass
from quart_schema.extension import _build_openapi_schema
import numpy
import json

@dataclass
class Message:
    message: str

app = Quart(__name__)
schema = QuartSchema(app)

@app.route('/api/something/info', methods=['GET'])
@document(
    request=Message,
    headers=Message,
    responses={200: (Message, None)},
    )
async def dummy_get_parsing_method():
    """
    Parses a GET request and returns a message.
    This is a dummy method to test the parsing of the GET request.

    """
    try:
        rand = numpy.random.rand()
        if rand > 0.5:
            return Message(message="GET was successful"), 200
        else:
            if rand > 0.9:
                raise Exception("Random error")
            return Message(message="GET was unsuccessful"), 500
    except Exception as e:
        return Message(message=str(e)), 500

print(json.dumps(_build_openapi_schema(app, schema), indent=4, sort_keys=True))

produces the following OpenAPI JSON, where the responses field is empty:

{
    "components": {
        "schemas": {}
    },
    "info": {
        "title": "__main__",
        "version": "0.1.0"
    },
    "openapi": "3.0.3",
    "paths": {
        "/api/something/info": {
            "get": {
                "parameters": [],
                "responses": {}
            }
        }
    }
}

With my fix applied, the output JSON is the following (which I think is correct):

{
    "components": {
        "schemas": {}
    },
    "info": {
        "title": "__main__",
        "version": "0.1.0"
    },
    "openapi": "3.0.3",
    "paths": {
        "/api/something/info": {
            "get": {
                "description": "This is a dummy method to test the parsing of the GET request.",
                "parameters": [
                    {
                        "in": "header",
                        "name": "message",
                        "schema": {
                            "title": "Message",
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "description": "Message(message: str)",
                                "properties": {
                                    "message": {
                                        "title": "Message",
                                        "type": "string"
                                    }
                                },
                                "required": [
                                    "message"
                                ],
                                "title": "Message",
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "description": "Message(message: str)",
                                    "properties": {
                                        "message": {
                                            "title": "Message",
                                            "type": "string"
                                        }
                                    },
                                    "required": [
                                        "message"
                                    ],
                                    "title": "Message",
                                    "type": "object"
                                }
                            }
                        },
                        "description": "Message(message: str)"
                    }
                },
                "summary": "Parses a GET request and returns a message."
            }
        }
    }
}
pgjones commented 1 year ago

Thanks