Skip to content

Bug: get_field_info_and_type_annotation doesn't respect tuple return types #5034

@philiptzou

Description

@philiptzou

Expected Behaviour

The get_field_info_and_type_annotation function should respect tuple response types since it is supported since 2.7.0. See #1845 and #1853.

Current Behaviour

Validation error (HTTP 422) happens when the endpoint function returning type annotation is a tuple, if we had enable_validation=True for OpenAPI validation.

Code snippet

from pydantic import BaseModel
from aws_lambda_powertools.event_handler import ALBResolver

app = ALBResolver(enable_validation=True)

class Result(BaseModel):
    payload: str

@app.post('/foobar')
def foobar() -> tuple[Result, int]:
    return Result(payload='foobar'), 201

def test_foobar():
    response = app.resolve({
        'path': '/foobar',
        'httpMethod': 'POST',
        'queryStringParameters': {},
        'headers': {}
    })
    assert response['statusCode'] == 201

Instead of 201 Created, the endpoint currently returns 422 error with following body:

{"statusCode":422,"detail":[{"loc":["response"],"type":"tuple_type"}]}

Possible Solution

Update here to support tuple type for a response. In addition, distinguishing is_response_param is necessary for avoiding changing behaviors for other types of annotations.

def get_field_info_and_type_annotation(annotation, value, is_path_param: bool) -> Tuple[Optional[FieldInfo], Any]:
"""
Get the FieldInfo and type annotation from an annotation and value.
"""
field_info: Optional[FieldInfo] = None
type_annotation: Any = Any
if annotation is not inspect.Signature.empty:
# If the annotation is an Annotated type, we need to extract the type annotation and the FieldInfo
if get_origin(annotation) is Annotated:
field_info, type_annotation = get_field_info_annotated_type(annotation, value, is_path_param)
# If the annotation is a Response type, we recursively call this function with the inner type
elif get_origin(annotation) is Response:
field_info, type_annotation = get_field_info_response_type(annotation, value)
# If the annotation is not an Annotated type, we use it as the type annotation
else:
type_annotation = annotation
return field_info, type_annotation

Steps to Reproduce

Please see above code snippet.

Powertools for AWS Lambda (Python) version

latest

AWS Lambda function runtime

3.11

Packaging format used

PyPi

Debugging logs

No response

Metadata

Metadata

Labels

bugSomething isn't workingdocumentationImprovements or additions to documentationevent_handlers

Projects

Status

Shipped

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions