github aws-powertools/powertools-lambda-python v1.17.0

latest releases: v3.3.0, v3.2.0, v3.1.0...
3 years ago

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

This release was made possible by the following contributors:

@dependabot, @dependabot[bot], @heitorlessa, @michaelbrewer and @risenberg-cyberark

Don't miss a new powertools-lambda-python release

NewReleases is sending notifications on new releases.