Summary
This release brings a 1/ new handy decorator event_source
for data classes, 2/ API Gateway HTTP API support for Parser, 3/ a new parameter to reset logging state upon every Lambda invocation in Logger, and 4/ high level methods to fetch attribute values and their types when using DynamoDBStreamEvent
data class.
Event source decorator
Similarly to Parser's parse
decorator, you can now use event_source
decorator to instantiate a data class as part of the invocation more easily.
from typing import Dict, Any
from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEventV2, event_source
from aws_lambda_powertools.utilities.typing import LambdaContext
@event_source(data_class=APIGatewayProxyEventV2)
def lambda_handler(event: APIGatewayProxyEventV2, context: LambdaContext) -> Dict[str, Any]:
assert event.get_header_value("x-foo") == "Foo"
This also gives you the ability to combine other utilities like Idempotency which expects a dictionary to serialize/deserialize without losing the benefits of self-documented schema and high level data methods.
from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEventV2, event_source
from aws_lambda_powertools.utilities.typing import LambdaContext
from aws_lambda_powertools.utilities.idempotency import (
DynamoDBPersistenceLayer, idempotent
)
persistence_layer = DynamoDBPersistenceLayer(table_name="IdempotencyTable")
@event_source(data_class=APIGatewayProxyEventV2)
@idempotent(persistence_store=persistence_layer)
def lambda_handler(event: APIGatewayProxyEventV2, context):
assert isinstance(event, APIGatewayProxyEventV2)
API Gateway HTTP API Parser support
Parser now supports API Gateway HTTP API as a native model in addition to REST API.
from typing import Dict, Any
from aws_lambda_powertools.utilities.parser import envelopes, event_parser
from aws_lambda_powertools.utilities.parser.models import APIGatewayProxyEventV2Model
@event_parser(model=APIGatewayProxyEventV2Model)
def lambda_handler(event: APIGatewayProxyEventV2Model, context: LambdaContext) -> Dict[str, Any]:
...
Like REST API, Parser also supports an envelope for HTTP API to help you extract your model from the payload, providing deep data validation, type enforcement at runtime, and more.
from typing import Dict, Any
from aws_lambda_powertools.utilities.parser import envelopes, event_parser
from aws_lambda_powertools.utilities.parser.models import APIGatewayProxyEventV2Model
from aws_lambda_powertools.utilities.parser.pydantic import EmailStr, UUID4, Json
class UserModel(BaseModel):
id: UUID4
username: str
preferences: Json
email: EmailStr
@event_parser(model=APIGatewayProxyEventV2Model, envelope=envelopes.ApiGatewayV2Envelope)
def lambda_handler(event: UserModel, context: LambdaContext) -> Dict[str, Any]:
assert event.username == "ran_isenberg"
Resetting Logger state on every invocation
As Logger is initialized in the global scope, logging state can persist across invocations. It is a good practice to always append new keys and use default values (None
if unavailable), so Logger can update and remove keys on a per invocation basis.
However, there are times where you might add keys conditionally depending on the incoming event. For these type of use cases, you can now use clear_state
parameter when using inject_lambda_context
decorator.
from aws_lambda_powertools import Logger
logger = Logger(service="payment")
@logger.inject_lambda_context(clear_state=True)
def handler(event, context):
if event.get("special_key"):
# Should only be available in the first request log
# as the second request doesn't contain `special_key`
logger.append_keys(debugging_key="value")
logger.info("Collecting payment")
DynamoDB Stream Event AttributeValueType and AttributeValue
You can now introspect what DynamoDB Record type and value is more easily with AttributeValueType
and AttributeValue
. This is useful when you might want to deserialize or deal with certain records and their attributes differently based on their type, e.g. a map vs string.
Each DynamoDB key available in the stream record now has high level methods such as get_value
and get_type
.
from aws_lambda_powertools.utilities.data_classes import event_source, DynamoDBStreamEvent
from aws_lambda_powertools.utilities.data_classes.dynamo_db_stream_event import AttributeValueType, AttributeValue
from aws_lambda_powertools.utilities.typing import LambdaContext
@event_source(data_class=DynamoDBStreamEvent)
def lambda_handler(event: DynamoDBStreamEvent, context: LambdaContext):
for record in event.records:
key: AttributeValue = record.dynamodb.keys["id"]
if key == AttributeValueType.Number:
# {"N": "123.45"} => "123.45"
assert key.get_value == key.n_value
print(key.get_value)
elif key == AttributeValueType.Map:
assert key.get_value == key.map_value
print(key.get_value)
You can find their respective implementations and all contributors below.
Changes
πNew features and non-breaking changes
- feat(logger): add option to clear state per invocation (#467) by @heitorlessa
- feat(data-classes): add AttributeValueType to DynamoDBStreamEvent (#462) by @michaelbrewer
- feat(data-classes): decorator to instantiate data_classes and docs updates (#442) by @michaelbrewer
- feat(parser): add support for API Gateway HTTP API #434 (#441) by @risenberg-cyberark
π Documentation updates
- feat(logger): add option to clear state per invocation (#467) by @heitorlessa
- feat(data-classes): decorator to instantiate data_classes and docs updates (#442) by @michaelbrewer
- docs: include new public roadmap (#452) by @heitorlessa
- feat(parser): add support for API Gateway HTTP API #434 (#441) by @risenberg-cyberark
π§ Maintenance
- chore(deps): bump boto3 from 1.17.88 to 1.17.89 (#466) by @dependabot
- chore(deps): bump boto3 from 1.17.87 to 1.17.88 (#463) by @dependabot
- chore(deps-dev): bump mkdocs-material from 7.1.6 to 7.1.7 (#464) by @dependabot
- chore(deps): bump boto3 from 1.17.86 to 1.17.87 (#459) by @dependabot
- chore(deps): bump boto3 from 1.17.85 to 1.17.86 (#458) by @dependabot
- chore(deps): bump boto3 from 1.17.84 to 1.17.85 (#455) by @dependabot
- chore(deps-dev): bump pytest-cov from 2.12.0 to 2.12.1 (#454) by @dependabot
- chore: update mergify to require approval on dependabot (#456) by @heitorlessa
- chore: bump actions/setup-python from 1 to 2.2.2 (#445) by @dependabot
- chore: bump xenon from 0.7.1 to 0.7.3 (#446) by @dependabot
- chore: bump boto3 from 1.17.78 to 1.17.84 (#449) by @dependabot
- chore: bump mkdocs-material from 7.1.5 to 7.1.6 (#451) by @dependabot
- build(deps-dev): bump pytest-asyncio from 0.14.0 to 0.15.1 (#448) by @dependabot
- chore: enable mergify (#450) by @heitorlessa
- chore: enable dependabot for dep upgrades (#444) by @heitorlessa
- chore: assited changelog pre-generation, auto-label PR (#443) by @heitorlessa
This release was made possible by the following contributors:
@dependabot, @dependabot[bot], @heitorlessa, @michaelbrewer and @risenberg-cyberark