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

docs(parser): change parser documentation #5262

Merged
merged 20 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
557 changes: 158 additions & 399 deletions docs/utilities/parser.md

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions examples/parser/src/bring_your_own_envelope.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": "0",
"id": "12345678-1234-1234-1234-123456789012",
"detail-type": "Order Placed",
"source": "com.mycompany.orders",
"account": "123456789012",
"time": "2023-05-03T12:00:00Z",
"region": "us-west-2",
"resources": [],
"detail": {
"order_id": "ORD-12345",
"amount": 99.99,
"customer_id": "CUST-6789"
}
}
47 changes: 47 additions & 0 deletions examples/parser/src/bring_your_own_envelope.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import json
from typing import Any, Dict, Optional, TypeVar, Union
from aws_lambda_powertools.utilities.parser import BaseEnvelope, BaseModel
from aws_lambda_powertools.utilities.parser.models import EventBridgeModel
from aws_lambda_powertools.utilities.parser import event_parser
from aws_lambda_powertools.utilities.typing import LambdaContext

Model = TypeVar("Model", bound=BaseModel)

class EventBridgeEnvelope(BaseEnvelope):
def parse(self, data: Optional[Union[Dict[str, Any], Any]], model: type[Model]) -> Optional[Model]:
if data is None:
return None

parsed_envelope = EventBridgeModel.parse_obj(data)
return self._parse(data=parsed_envelope.detail, model=model)

class OrderDetail(BaseModel):
order_id: str
amount: float
customer_id: str

@event_parser(model=OrderDetail, envelope=EventBridgeEnvelope)
def lambda_handler(event: OrderDetail, context: LambdaContext):
try:
# Process the order
print(f"Processing order {event.order_id} for customer {event.customer_id}")
print(f"Order amount: ${event.amount:.2f}")

# Your business logic here
# For example, you might save the order to a database or trigger a payment process

return {
"statusCode": 200,
"body": json.dumps({
"message": f"Order {event.order_id} processed successfully",
"order_id": event.order_id,
"amount": event.amount,
"customer_id": event.customer_id
})
}
except Exception as e:
print(f"Error processing order: {str(e)}")
return {
"statusCode": 500,
"body": json.dumps({"error": "Internal server error"})
}
23 changes: 23 additions & 0 deletions examples/parser/src/custom_data_model_with_eventbridge.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from aws_lambda_powertools.utilities.parser import BaseModel, parse, Field
from aws_lambda_powertools.utilities.parser.models import EventBridgeModel

# Define a custom EventBridge model by extending the built-in EventBridgeModel
class MyCustomEventBridgeModel(EventBridgeModel):
detail_type: str = Field(alias="detail-type")
source: str
detail: dict

def lambda_handler(event: dict, context):
try:
# Manually parse the incoming event into the custom model
parsed_event: MyCustomEventBridgeModel = parse(model=MyCustomEventBridgeModel, event=event)

return {
"statusCode": 200,
"body": f"Event from {parsed_event.source}, type: {parsed_event.detail_type}"
}
except ValidationError as e:
return {
"statusCode": 400,
"body": f"Validation error: {str(e)}"
}
14 changes: 14 additions & 0 deletions examples/parser/src/data_model_eventbridge.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"version": "0",
"id": "abcd-1234-efgh-5678",
"detail-type": "order.created",
"source": "my.order.service",
"account": "123456789012",
"time": "2023-09-10T12:00:00Z",
"region": "us-west-2",
"resources": [],
"detail": {
"orderId": "O-12345",
"amount": 100.0
}
}
17 changes: 17 additions & 0 deletions examples/parser/src/envelope_payload.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"version": "0",
"id": "6a7e8feb-b491-4cf7-a9f1-bf3703467718",
"detail-type": "CustomerSignedUp",
"source": "CustomerService",
"account": "111122223333",
"time": "2020-10-22T18:43:48Z",
"region": "us-west-1",
"resources": [
"some_additional_"
],
"detail": {
"username": "universe",
"parentid_1": "12345",
"parentid_2": "6789"
}
}
24 changes: 24 additions & 0 deletions examples/parser/src/envelope_with_event_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from aws_lambda_powertools.utilities.parser import event_parser, BaseModel
from aws_lambda_powertools.utilities.parser import envelopes
from aws_lambda_powertools.utilities.typing import LambdaContext

class UserModel(BaseModel):
username: str
parentid_1: str
parentid_2: str

@event_parser(model=UserModel, envelope=envelopes.EventBridgeEnvelope)
def lambda_handler(event: UserModel, context: LambdaContext):
if event.parentid_1!= event.parentid_2:
return {
"statusCode": 400,
"body": "Parent ids do not match"
}

# If parentids match, proceed with user registration
# Add your user registration logic here

return {
"statusCode": 200,
"body": f"User {event.username} registered successfully"
}
21 changes: 0 additions & 21 deletions examples/parser/src/extending_built_in_models_with_json_mypy.py

This file was deleted.

This file was deleted.

25 changes: 25 additions & 0 deletions examples/parser/src/field_validator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from aws_lambda_powertools.utilities.parser import parse, BaseModel
from aws_lambda_powertools.utilities.parser import field_validator
from aws_lambda_powertools.utilities.typing import LambdaContext

class HelloWorldModel(BaseModel):
message: str

@field_validator('message')
def is_hello_world(cls, v):
if v != "hello world":
raise ValueError("Message must be hello world!")
return v

def lambda_handler(event: dict, context: LambdaContext):
try:
parsed_event = parse(model=HelloWorldModel, event=event)
return {
"statusCode": 200,
"body": f"Received message: {parsed_event.message}"
}
except ValueError as e:
return {
"statusCode": 400,
"body": str(e)
}
26 changes: 26 additions & 0 deletions examples/parser/src/field_validator_all_values.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from aws_lambda_powertools.utilities.parser import parse, BaseModel
from aws_lambda_powertools.utilities.parser import field_validator
from aws_lambda_powertools.utilities.typing import LambdaContext

class HelloWorldModel(BaseModel):
message: str
sender: str

@field_validator('*')
def has_whitespace(cls, v):
if ' ' not in v:
raise ValueError("Must have whitespace...")
return v

def lambda_handler(event: dict, context: LambdaContext):
try:
parsed_event = parse(model=HelloWorldModel, event=event)
return {
"statusCode": 200,
"body": f"Received message: {parsed_event.message}"
}
except ValueError as e:
return {
"statusCode": 400,
"body": str(e)
}
13 changes: 13 additions & 0 deletions examples/parser/src/getting_started_with_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from aws_lambda_powertools.utilities.parser import BaseModel, ValidationError
from aws_lambda_powertools.utilities.parser import event_parser

class MyEvent(BaseModel):
id: int
name: str

@event_parser(model=MyEvent)
def lambda_handler(event: MyEvent, context):
try:
return {"statusCode": 200, "body": f"Hello {event.name}, your ID is {event.id}"}
except ValidationError as e:
return {"statusCode": 400, "body": f"Invalid input: {str(e)}"}
3 changes: 3 additions & 0 deletions examples/parser/src/json_data_string.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"body": "{\"order_id\": 12345, \"reason\": \"Changed my mind\"}"
}
27 changes: 27 additions & 0 deletions examples/parser/src/model_validator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from aws_lambda_powertools.utilities.typing import LambdaContext
from aws_lambda_powertools.utilities.parser import parse, BaseModel
from aws_lambda_powertools.utilities.parser import model_validator

class UserModel(BaseModel):
username: str
parentid_1: str
parentid_2: str

@model_validator(mode='after')
def check_parents_match(cls, values):
pi1, pi2 = values.get('parentid_1'), values.get('parentid_2')
if pi1 is not None and pi2 is not None and pi1 != pi2:
raise ValueError('Parent ids do not match')
return values
def lambda_handler(event: dict, context: LambdaContext):
try:
parsed_event = parse(model=UserModel, event=event)
return {
"statusCode": 200,
"body": f"Received parent id from: {parsed_event.username}"
}
except ValueError as e:
return {
"statusCode": 400,
"body": str(e)
}
33 changes: 0 additions & 33 deletions examples/parser/src/multiple_model_parsing.py

This file was deleted.

22 changes: 22 additions & 0 deletions examples/parser/src/parser_function.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from aws_lambda_powertools.utilities.parser import BaseModel, ValidationError
from aws_lambda_powertools.utilities.parser import parse

# Define a Pydantic model for the expected structure of the input
class MyEvent(BaseModel):
id: int
name: str

def lambda_handler(event: dict, context):
try:
# Manually parse the incoming event into MyEvent model
parsed_event: MyEvent = parse(model=MyEvent, event=event)
return {
"statusCode": 200,
"body": f"Hello {parsed_event.name}, your ID is {parsed_event.id}"
}
except ValidationError as e:
# Catch validation errors and return a 400 response
return {
"statusCode": 400,
"body": f"Validation error: {str(e)}"
}
Loading