Skip to content

Commit 859721e

Browse files
Adding openapi_examples to parameters
1 parent 555f839 commit 859721e

File tree

4 files changed

+81
-27
lines changed

4 files changed

+81
-27
lines changed

aws_lambda_powertools/event_handler/api_gateway.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -552,11 +552,7 @@ def _get_openapi_path(
552552
operation_responses: dict[int, OpenAPIResponse] = {
553553
422: {
554554
"description": "Validation Error",
555-
"content": {
556-
"application/json": {
557-
"schema": {"$ref": COMPONENT_REF_PREFIX + "HTTPValidationError"},
558-
},
559-
},
555+
"content": {"application/json": {"schema": {"$ref": f"{COMPONENT_REF_PREFIX}HTTPValidationError"}}},
560556
},
561557
}
562558

@@ -761,6 +757,9 @@ def _openapi_operation_parameters(
761757
if field_info.description:
762758
parameter["description"] = field_info.description
763759

760+
if field_info.openapi_examples:
761+
parameter["examples"] = field_info.openapi_examples
762+
764763
if field_info.deprecated:
765764
parameter["deprecated"] = field_info.deprecated
766765

aws_lambda_powertools/event_handler/openapi/params.py

+14
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
)
2121

2222
if TYPE_CHECKING:
23+
from aws_lambda_powertools.event_handler.openapi.models import Example
2324
from aws_lambda_powertools.event_handler.openapi.types import CacheKey
2425

2526
"""
@@ -117,6 +118,7 @@ def __init__(
117118
max_digits: int | None = _Unset,
118119
decimal_places: int | None = _Unset,
119120
examples: list[Any] | None = None,
121+
openapi_examples: dict[str, Example] | None = None,
120122
deprecated: bool | None = None,
121123
include_in_schema: bool = True,
122124
json_schema_extra: dict[str, Any] | None = None,
@@ -205,8 +207,13 @@ def __init__(
205207
if examples is not None:
206208
kwargs["examples"] = examples
207209

210+
if openapi_examples is not None:
211+
kwargs["openapi_examples"] = openapi_examples
212+
208213
current_json_schema_extra = json_schema_extra or extra
209214

215+
self.openapi_examples = openapi_examples
216+
210217
kwargs.update(
211218
{
212219
"annotation": annotation,
@@ -262,6 +269,7 @@ def __init__(
262269
max_digits: int | None = _Unset,
263270
decimal_places: int | None = _Unset,
264271
examples: list[Any] | None = None,
272+
openapi_examples: dict[str, Example] | None = None,
265273
deprecated: bool | None = None,
266274
include_in_schema: bool = True,
267275
json_schema_extra: dict[str, Any] | None = None,
@@ -353,6 +361,7 @@ def __init__(
353361
decimal_places=decimal_places,
354362
deprecated=deprecated,
355363
examples=examples,
364+
openapi_examples=openapi_examples,
356365
include_in_schema=include_in_schema,
357366
json_schema_extra=json_schema_extra,
358367
**extra,
@@ -392,6 +401,7 @@ def __init__(
392401
max_digits: int | None = _Unset,
393402
decimal_places: int | None = _Unset,
394403
examples: list[Any] | None = None,
404+
openapi_examples: dict[str, Example] | None = None,
395405
deprecated: bool | None = None,
396406
include_in_schema: bool = True,
397407
json_schema_extra: dict[str, Any] | None = None,
@@ -480,6 +490,7 @@ def __init__(
480490
decimal_places=decimal_places,
481491
deprecated=deprecated,
482492
examples=examples,
493+
openapi_examples=openapi_examples,
483494
include_in_schema=include_in_schema,
484495
json_schema_extra=json_schema_extra,
485496
**extra,
@@ -522,6 +533,7 @@ def __init__(
522533
max_digits: int | None = _Unset,
523534
decimal_places: int | None = _Unset,
524535
examples: list[Any] | None = None,
536+
openapi_examples: dict[str, Example] | None = None,
525537
deprecated: bool | None = None,
526538
include_in_schema: bool = True,
527539
json_schema_extra: dict[str, Any] | None = None,
@@ -616,6 +628,7 @@ def __init__(
616628
decimal_places=decimal_places,
617629
deprecated=deprecated,
618630
examples=examples,
631+
openapi_examples=openapi_examples,
619632
include_in_schema=include_in_schema,
620633
json_schema_extra=json_schema_extra,
621634
**extra,
@@ -669,6 +682,7 @@ def __init__(
669682
max_digits: int | None = _Unset,
670683
decimal_places: int | None = _Unset,
671684
examples: list[Any] | None = None,
685+
openapi_examples: dict[str, Example] | None = None,
672686
deprecated: bool | None = None,
673687
include_in_schema: bool = True,
674688
json_schema_extra: dict[str, Any] | None = None,
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
<!-- markdownlint-disable MD041 MD043 -->
22
Whenever you use OpenAPI parameters to validate [query strings](api_gateway.md#validating-query-strings) or [path parameters](api_gateway.md#validating-path-parameters), you can enhance validation and OpenAPI documentation by using any of these parameters:
33

4-
| Field name | Type | Description |
5-
|-----------------------|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
6-
| `alias` | `str` | Alternative name for a field, used when serializing and deserializing data |
7-
| `validation_alias` | `str` | Alternative name for a field during validation (but not serialization) |
8-
| `serialization_alias` | `str` | Alternative name for a field during serialization (but not during validation) |
9-
| `description` | `str` | Human-readable description |
10-
| `gt` | `float` | Greater than. If set, value must be greater than this. Only applicable to numbers |
11-
| `ge` | `float` | Greater than or equal. If set, value must be greater than or equal to this. Only applicable to numbers |
12-
| `lt` | `float` | Less than. If set, value must be less than this. Only applicable to numbers |
13-
| `le` | `float` | Less than or equal. If set, value must be less than or equal to this. Only applicable to numbers |
14-
| `min_length` | `int` | Minimum length for strings |
15-
| `max_length` | `int` | Maximum length for strings |
16-
| `pattern` | `string` | A regular expression that the string must match. |
17-
| `strict` | `bool` | If `True`, strict validation is applied to the field. See [Strict Mode](https://docs.pydantic.dev/latest/concepts/strict_mode/){target"_blank" rel="nofollow"} for details |
18-
| `multiple_of` | `float` | Value must be a multiple of this. Only applicable to numbers |
19-
| `allow_inf_nan` | `bool` | Allow `inf`, `-inf`, `nan`. Only applicable to numbers |
20-
| `max_digits` | `int` | Maximum number of allow digits for strings |
21-
| `decimal_places` | `int` | Maximum number of decimal places allowed for numbers |
22-
| `examples` | `List[Any]` | List of examples of the field |
23-
| `deprecated` | `bool` | Marks the field as deprecated |
24-
| `include_in_schema` | `bool` | If `False` the field will not be part of the exported OpenAPI schema |
25-
| `json_schema_extra` | `JsonDict` | Any additional JSON schema data for the schema property |
4+
| Field name | Type | Description |
5+
| --------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------- |
6+
| `alias` | `str` | Alternative name for a field, used when serializing and deserializing data |
7+
| `validation_alias` | `str` | Alternative name for a field during validation (but not serialization) |
8+
| `serialization_alias` | `str` | Alternative name for a field during serialization (but not during validation) |
9+
| `description` | `str` | Human-readable description |
10+
| `gt` | `float` | Greater than. If set, value must be greater than this. Only applicable to numbers |
11+
| `ge` | `float` | Greater than or equal. If set, value must be greater than or equal to this. Only applicable to numbers |
12+
| `lt` | `float` | Less than. If set, value must be less than this. Only applicable to numbers |
13+
| `le` | `float` | Less than or equal. If set, value must be less than or equal to this. Only applicable to numbers |
14+
| `min_length` | `int` | Minimum length for strings |
15+
| `max_length` | `int` | Maximum length for strings |
16+
| `pattern` | `string` | A regular expression that the string must match. |
17+
| `strict` | `bool` | If `True`, strict validation is applied to the field. See [Strict Mode](https://docs.pydantic.dev/latest/concepts/strict_mode/){target"_blank" rel="nofollow"} for details |
18+
| `multiple_of` | `float` | Value must be a multiple of this. Only applicable to numbers |
19+
| `allow_inf_nan` | `bool` | Allow `inf`, `-inf`, `nan`. Only applicable to numbers |
20+
| `max_digits` | `int` | Maximum number of allow digits for strings |
21+
| `decimal_places` | `int` | Maximum number of decimal places allowed for numbers |
22+
| `openapi_examples` | `dict[str, Example]` | A list of examples to be displayed in the SwaggerUI interface. Avoid using the `examples` field for this purpose. |
23+
| `deprecated` | `bool` | Marks the field as deprecated |
24+
| `include_in_schema` | `bool` | If `False` the field will not be part of the exported OpenAPI schema |
25+
| `json_schema_extra` | `JsonDict` | Any additional JSON schema data for the schema property |

tests/functional/event_handler/_pydantic/test_openapi_params.py

+41
Original file line numberDiff line numberDiff line change
@@ -608,3 +608,44 @@ def handler() -> Todo:
608608
assert "completed" in todo_schema.properties
609609
completed_property = todo_schema.properties["completed"]
610610
assert completed_property.examples == [True]
611+
612+
613+
def test_openapi_with_openapi_example():
614+
app = APIGatewayRestResolver()
615+
616+
first_example = Example(summary="Example1", description="Example1", value="a")
617+
second_example = Example(summary="Example2", description="Example2", value="b")
618+
619+
@app.get("/users", summary="Get Users", operation_id="GetUsers", description="Get paginated users", tags=["Users"])
620+
def handler(
621+
count: Annotated[
622+
int,
623+
Query(
624+
openapi_examples={
625+
"first_example": first_example,
626+
"second_example": second_example,
627+
},
628+
),
629+
] = 1,
630+
):
631+
print(count)
632+
raise NotImplementedError()
633+
634+
schema = app.get_openapi_schema()
635+
636+
get = schema.paths["/users"].get
637+
assert len(get.parameters) == 1
638+
assert get.summary == "Get Users"
639+
assert get.operationId == "GetUsers"
640+
assert get.description == "Get paginated users"
641+
assert get.tags == ["Users"]
642+
643+
parameter = get.parameters[0]
644+
assert parameter.required is False
645+
assert parameter.name == "count"
646+
assert parameter.examples["first_example"] == first_example
647+
assert parameter.examples["second_example"] == second_example
648+
assert parameter.in_ == ParameterInType.query
649+
assert parameter.schema_.type == "integer"
650+
assert parameter.schema_.default == 1
651+
assert parameter.schema_.title == "Count"

0 commit comments

Comments
 (0)