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

Feature request: Support types annotated with Field for event_handler validation #5953

Open
1 of 2 tasks
rtandy opened this issue Jan 30, 2025 · 2 comments
Open
1 of 2 tasks
Labels
feature-request feature request

Comments

@rtandy
Copy link

rtandy commented Jan 30, 2025

Use case

Hi, thank you for working on Powertools.

My Pydantic models are shared between multiple applications. For example, a client application builds an instance of a model and submits it to the API, which validates the request against the same model.

A few types I want to accept as API payloads or parameters are annotated with Field, mainly tagged unions.

I am aware of the Powertools OpenAPI Param annotations, but they have downsides:

  • having to import Powertools into non-Lambda projects;
  • being stuck with a single Param type (i.e. Body, Path, etc) per annotated type, or having to duplicate the arguments for different types

With Powertools 3.5.0, the example code below fails:

  • with def create_action(action: Action): AssertionError: Param: action can only be a request body, use Body()
  • with def create_action(action: Annotated[Action, Body()]): AssertionError: Only one FieldInfo can be used per parameter

It would be nice if event_handler would allow nested Field annotations, so that I can apply Annotated[some_type, Body()] to an existing annotated type such as a tagged union.

Thank you for considering.

Solution/User Experience

class FooAction(BaseModel):
    action: Literal['foo']
    foo: int 

class BarAction(BaseModel):
    action: Literal['bar']
    bar: int 

Action = Annotated[FooAction | BarAction, Field(discriminator='action')]

app = APIGatewayHttpResolver(enable_validation=True)

@app.post('/actions')
def create_action(action: Action): # or Annotated[Action, Body()]
    ...

def lambda_handler(event, context):
    return app.resolve(event, context)

Alternative solutions

  1. use event_handler OpenAPI Param annotations exclusively
Action = Annotated[FooAction | BarAction, Body(discriminator='action')]
  1. use TypeAdapter manually
Action = Annotated[FooAction | BarAction, Field(discriminator='action')]
action_adapter = TypeAdapter(Action)

@app.post('/actions')
def create_action():
    try:
        action = action_adapter.validate_json(app.current_event.body)
    except ValidationError as e:
        raise RequestValidationError(e.errors())

Acknowledgment

@leandrodamascena
Copy link
Contributor

Hi @rtandy! Thanks for opening this issue! Yes, I agree that we need to support this.

Are you interested in submitting a PR to implement this support?

@leandrodamascena leandrodamascena removed the triage Pending triage from maintainers label Jan 31, 2025
@rtandy
Copy link
Author

rtandy commented Feb 3, 2025

Are you interested in submitting a PR to implement this support?

I'd like to, but it's not a priority for my employer (the workaround of using a TypeAdapter manually is sufficient) and it will be at least a few weeks before I can look at it on my own time. It's not an urgent request, just an idea for future improvement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request feature request
Projects
Development

No branches or pull requests

2 participants