Skip to content

Commit

Permalink
Update tests and openapi responses doc
Browse files Browse the repository at this point in the history
  • Loading branch information
tarsil committed Jul 14, 2023
1 parent be724a4 commit b352a8f
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 5 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -507,9 +507,12 @@ To access the OpenAPI, simply start your local development and access:
* **Swagger** - `/docs/swagger`.
* **Redoc** - `/docs/redoc`.

There are more details about [how to configure the OpenAPIConfig](https://esmerald.dev/configurations/openapi/config.md)
There are more details about [how to configure the OpenAPIConfig](https://esmerald.dev/configurations/openapi/config)
within the documentation.

There is also a good explanation on how to use the [OpenAPIResponse](https://esmerald.dev/responses#openapi-responses)
as well.

## Notes

This is just a very high-level demonstration of how to start quickly and what Esmerald can do.
Expand Down
3 changes: 3 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,9 @@ To access the OpenAPI, simply start your local development and access:
There are more details about [how to configure the OpenAPIConfig](./configurations/openapi/config.md)
within this documentation.

There is also a good explanation on how to use the [OpenAPIResponse](./responses.md#openapi-responses)
as well.

## Notes

This is just a very high-level demonstration of how to start quickly and what Esmerald can do.
Expand Down
11 changes: 10 additions & 1 deletion docs/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Release Notes

## 2.0.1

This is a small fix into the parser of lists for the OpenAPI specification.

### Fixed

- [OpenAPIResponse](https://esmerald.dev/responses#openapi-responses) now allows proper parse of
lists as definition. [More details](http://esmerald.dev/responses/#lists).

## 2.0.0

!!! Warning
Expand Down Expand Up @@ -166,7 +175,7 @@ across main application and children.
- Brand new support for [Saffier](https://saffier.tarsild.io). A brand new ORM running
on the top of SQLAlchemy in an async fashion.
- New `base_user` and `middleware` support for Saffier with Esmerald.
- New docs regarding the [Saffier](https://esmerald.dymmond.com/databases/saffier/motivation/) integration.
- New docs regarding the [Saffier](https://esmerald.dev/databases/saffier/motivation/) integration.
Those include also an example how to use it.

### Changed
Expand Down
13 changes: 13 additions & 0 deletions docs/responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,19 @@ async def get_items() -> Union[None, UserOut]:
As you could notice, we simply added `[]` in the model to reflect a list in the OpenAPI
specification. That simple.

#### Errors

A `ValueError` is raised in the following scenarios:

* You try to pass a model than one pydantic model into a list. The OpenAPIResponse is a mere
representation of a response, so be compliant.
* You try to pass a model that is not a subclass of a Pydantic `BaseModel`.
* You try to pass a list of non Pydantic `BaseModels`.

When one of these scenarios occur, the following error will be raised.

> The representation of a list of models in OpenAPI can only be a total of one. Example: OpenAPIResponse(model=[MyModel])
## Other responses

There are other responses you can have that does not necessessarily have to be the ones provided here. Every case is
Expand Down
2 changes: 1 addition & 1 deletion esmerald/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "2.0.0"
__version__ = "2.0.1"


from starlette import status
Expand Down
12 changes: 11 additions & 1 deletion esmerald/openapi/datastructures.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import List, Optional, Type, Union

from pydantic import BaseModel
from pydantic import BaseModel, field_validator

from esmerald.enums import MediaType

Expand All @@ -10,3 +10,13 @@ class OpenAPIResponse(BaseModel):
description: str = "Additional response"
media_type: MediaType = MediaType.JSON
status_text: Optional[str] = None

@field_validator("model", mode="before")
def validate_model(
cls, model: Union[Type[BaseModel], List[Type[BaseModel]]]
) -> Union[Type[BaseModel], List[Type[BaseModel]]]:
if isinstance(model, list) and len(model) > 1:
raise ValueError(
"The representation of a list of models in OpenAPI can only be a total of one. Example: OpenAPIResponse(model=[MyModel])."
)
return model
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ test = [
"polyfactory>=2.5.0,<3.0.0",
"python-jose>=3.3.0,<4",
"orjson>=3.8.5,<4.0.0",
"saffier[postgres]>=0.14.0",
"saffier[postgres]>=0.15.0",
"requests>=2.28.2,<3.0.0",
"ruff>=0.0.256,<1.0.0",
"ujson>=5.7.0,<6",
Expand Down
39 changes: 39 additions & 0 deletions tests/openapi/test_raise_value_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ class Error(BaseModel):
detail: str


class DummyErrorModel(BaseModel):
status: int
detail: str


@dataclass
class DummyErrorDataclass:
status: int
Expand Down Expand Up @@ -61,3 +66,37 @@ def test_openapi_response_value_for_class_as_list(test_client_factory, model):
)
async def read_item(id: str) -> None:
...


def test_openapi_response_value_for_class_as_list_multiple_models(test_client_factory):
with pytest.raises(ValueError) as raised:

@get(
"/item/{id}",
responses={422: OpenAPIResponse(model=[Error, DummyErrorModel], description="Error")},
)
async def read_item(id: str) -> None:
...

assert (
raised.value.errors()[0]["ctx"]["error"]
== "The representation of a list of models in OpenAPI can only be a total of one. Example: OpenAPIResponse(model=[MyModel])."
)


def xtest_openapi_response_value_for_class_as_list_multiple(test_client_factory):
with pytest.raises(ValueError) as raised:

@get(
"/item/{id}",
responses={
422: OpenAPIResponse(model=[DummyErrorDataclass, DummyError], description="Error")
},
)
async def read_item(id: str) -> None:
...

assert (
raised.value.errors()[0]["ctx"]["error"]
== "The representation of a list of models in OpenAPI can only be a total of one. Example: OpenAPIResponse(model=[MyModel])."
)

0 comments on commit b352a8f

Please sign in to comment.