Skip to content

Commit 4ee67b2

Browse files
Merge branch 'develop' into bug-cors
2 parents 90eafc5 + c8eec42 commit 4ee67b2

26 files changed

+353
-102
lines changed

.github/workflows/publish_v2_layer.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ jobs:
117117
pip install --require-hashes -r requirements.txt
118118
119119
- name: Set up QEMU
120-
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v2.0.0
120+
uses: docker/setup-qemu-action@5927c834f5b4fdf503fca6f4c7eccda82949e1ee # v2.0.0
121121
with:
122122
platforms: arm64
123123
# NOTE: we need QEMU to build Layer against a different architecture (e.g., ARM)

.github/workflows/quality_check.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ jobs:
7777
- name: Upload coverage to Codecov
7878
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # 4.5.0
7979
with:
80+
token: ${{ secrets.CODECOV_TOKEN }}
8081
file: ./coverage.xml
8182
env_vars: PYTHON
8283
name: aws-lambda-powertools-python-codecov

.github/workflows/secure_workflows.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
- name: Checkout code
3333
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
3434
- name: Ensure 3rd party workflows have SHA pinned
35-
uses: zgosalvez/github-actions-ensure-sha-pinned-actions@74606c30450304eee8660aae751818321754feb1 # v3.0.9
35+
uses: zgosalvez/github-actions-ensure-sha-pinned-actions@b88cd0aad2c36a63e42c71f81cb1958fed95ac87 # v3.0.10
3636
with:
3737
allowlist: |
3838
slsa-framework/slsa-github-generator

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,41 @@
44
<a name="unreleased"></a>
55
# Unreleased
66

7+
## Bug Fixes
8+
9+
* **event_handler:** custom serializer recursive values when using data validation ([#4664](https://github.com/aws-powertools/powertools-lambda-python/issues/4664))
10+
11+
## Maintenance
12+
13+
* **ci:** new pre-release 2.40.2a0 ([#4665](https://github.com/aws-powertools/powertools-lambda-python/issues/4665))
14+
* **ci:** new pre-release 2.40.2a1 ([#4669](https://github.com/aws-powertools/powertools-lambda-python/issues/4669))
15+
* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#4659](https://github.com/aws-powertools/powertools-lambda-python/issues/4659))
16+
* **deps:** bump zgosalvez/github-actions-ensure-sha-pinned-actions from 3.0.9 to 3.0.10 ([#4678](https://github.com/aws-powertools/powertools-lambda-python/issues/4678))
17+
* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.198 to 0.1.199 ([#4668](https://github.com/aws-powertools/powertools-lambda-python/issues/4668))
18+
* **deps-dev:** bump mypy-boto3-s3 from 1.34.120 to 1.34.138 in the boto-typing group ([#4673](https://github.com/aws-powertools/powertools-lambda-python/issues/4673))
19+
* **deps-dev:** bump aws-cdk from 2.147.2 to 2.147.3 ([#4672](https://github.com/aws-powertools/powertools-lambda-python/issues/4672))
20+
* **deps-dev:** bump cfn-lint from 1.4.1 to 1.4.2 ([#4660](https://github.com/aws-powertools/powertools-lambda-python/issues/4660))
21+
* **deps-dev:** bump aws-cdk-lib from 2.147.1 to 2.147.2 ([#4661](https://github.com/aws-powertools/powertools-lambda-python/issues/4661))
22+
* **deps-dev:** bump aws-cdk-aws-lambda-python-alpha from 2.147.1a0 to 2.147.2a0 ([#4667](https://github.com/aws-powertools/powertools-lambda-python/issues/4667))
23+
* **deps-dev:** bump aws-cdk from 2.147.1 to 2.147.2 ([#4657](https://github.com/aws-powertools/powertools-lambda-python/issues/4657))
24+
* **deps-dev:** bump ruff from 0.4.10 to 0.5.0 ([#4644](https://github.com/aws-powertools/powertools-lambda-python/issues/4644))
25+
* **deps-dev:** bump cdklabs-generative-ai-cdk-constructs from 0.1.199 to 0.1.200 ([#4677](https://github.com/aws-powertools/powertools-lambda-python/issues/4677))
26+
* **deps-dev:** bump mkdocs-material from 9.5.27 to 9.5.28 ([#4676](https://github.com/aws-powertools/powertools-lambda-python/issues/4676))
27+
728

829
<a name="v2.40.1"></a>
930
## [v2.40.1] - 2024-06-28
31+
## Bug Fixes
32+
33+
* **event_handler:** current_event regression AppSyncResolver Router ([#4652](https://github.com/aws-powertools/powertools-lambda-python/issues/4652))
34+
1035
## Maintenance
1136

1237
* version bump
1338
* **ci:** new pre-release 2.40.1a1 ([#4653](https://github.com/aws-powertools/powertools-lambda-python/issues/4653))
39+
* **ci:** new pre-release 2.40.1a0 ([#4648](https://github.com/aws-powertools/powertools-lambda-python/issues/4648))
40+
* **deps-dev:** bump cfn-lint from 1.3.7 to 1.4.1 ([#4646](https://github.com/aws-powertools/powertools-lambda-python/issues/4646))
41+
* **deps-dev:** bump sentry-sdk from 2.7.0 to 2.7.1 ([#4645](https://github.com/aws-powertools/powertools-lambda-python/issues/4645))
1442

1543

1644
<a name="v2.40.0"></a>

aws_lambda_powertools/event_handler/api_gateway.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
cast,
3131
)
3232

33+
from typing_extensions import override
34+
3335
from aws_lambda_powertools.event_handler import content_types
3436
from aws_lambda_powertools.event_handler.exceptions import NotFoundError, ServiceError
3537
from aws_lambda_powertools.event_handler.openapi.constants import DEFAULT_API_VERSION, DEFAULT_OPENAPI_VERSION
@@ -2659,3 +2661,24 @@ def __init__(
26592661
def _get_base_path(self) -> str:
26602662
# ALB doesn't have a stage variable, so we just return an empty string
26612663
return ""
2664+
2665+
@override
2666+
def _to_response(self, result: Union[Dict, Tuple, Response]) -> Response:
2667+
"""Convert the route's result to a Response
2668+
2669+
ALB requires a non-null body otherwise it converts as HTTP 5xx
2670+
2671+
3 main result types are supported:
2672+
2673+
- Dict[str, Any]: Rest api response with just the Dict to json stringify and content-type is set to
2674+
application/json
2675+
- Tuple[dict, int]: Same dict handling as above but with the option of including a status code
2676+
- Response: returned as is, and allows for more flexibility
2677+
"""
2678+
2679+
# NOTE: Minor override for early return on Response with null body for ALB
2680+
if isinstance(result, Response) and result.body is None:
2681+
logger.debug("ALB doesn't allow None responses; converting to empty string")
2682+
result.body = ""
2683+
2684+
return super()._to_response(result)

aws_lambda_powertools/event_handler/openapi/encoders.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def jsonable_encoder( # noqa: PLR0911
9494
exclude_unset=exclude_unset,
9595
exclude_defaults=exclude_defaults,
9696
exclude_none=exclude_none,
97+
custom_serializer=custom_serializer,
9798
)
9899

99100
# Enums
@@ -115,8 +116,9 @@ def jsonable_encoder( # noqa: PLR0911
115116
include=include,
116117
exclude=exclude,
117118
by_alias=by_alias,
118-
exclude_none=exclude_none,
119119
exclude_unset=exclude_unset,
120+
exclude_none=exclude_none,
121+
custom_serializer=custom_serializer,
120122
)
121123

122124
# Sequences
@@ -129,6 +131,7 @@ def jsonable_encoder( # noqa: PLR0911
129131
exclude_none=exclude_none,
130132
exclude_defaults=exclude_defaults,
131133
exclude_unset=exclude_unset,
134+
custom_serializer=custom_serializer,
132135
)
133136

134137
# Other types
@@ -152,6 +155,7 @@ def jsonable_encoder( # noqa: PLR0911
152155
exclude_none=exclude_none,
153156
exclude_unset=exclude_unset,
154157
exclude_defaults=exclude_defaults,
158+
custom_serializer=custom_serializer,
155159
)
156160
except ValueError as exc:
157161
raise SerializationError(
@@ -201,9 +205,15 @@ def _dump_dict(
201205
by_alias: bool = True,
202206
exclude_unset: bool = False,
203207
exclude_none: bool = False,
208+
custom_serializer: Optional[Callable[[Any], str]] = None,
204209
) -> Dict[str, Any]:
205210
"""
206211
Dump a dict to a dict, using the same parameters as jsonable_encoder
212+
213+
Parameters
214+
----------
215+
custom_serializer : Callable, optional
216+
A custom serializer to use for encoding the object, when everything else fails.
207217
"""
208218
encoded_dict = {}
209219
allowed_keys = set(obj.keys())
@@ -222,12 +232,14 @@ def _dump_dict(
222232
by_alias=by_alias,
223233
exclude_unset=exclude_unset,
224234
exclude_none=exclude_none,
235+
custom_serializer=custom_serializer,
225236
)
226237
encoded_value = jsonable_encoder(
227238
value,
228239
by_alias=by_alias,
229240
exclude_unset=exclude_unset,
230241
exclude_none=exclude_none,
242+
custom_serializer=custom_serializer,
231243
)
232244
encoded_dict[encoded_key] = encoded_value
233245
return encoded_dict
@@ -242,9 +254,10 @@ def _dump_sequence(
242254
exclude_unset: bool = False,
243255
exclude_none: bool = False,
244256
exclude_defaults: bool = False,
257+
custom_serializer: Optional[Callable[[Any], str]] = None,
245258
) -> List[Any]:
246259
"""
247-
Dump a sequence to a list, using the same parameters as jsonable_encoder
260+
Dump a sequence to a list, using the same parameters as jsonable_encoder.
248261
"""
249262
encoded_list = []
250263
for item in obj:
@@ -257,6 +270,7 @@ def _dump_sequence(
257270
exclude_unset=exclude_unset,
258271
exclude_defaults=exclude_defaults,
259272
exclude_none=exclude_none,
273+
custom_serializer=custom_serializer,
260274
),
261275
)
262276
return encoded_list
@@ -271,6 +285,7 @@ def _dump_other(
271285
exclude_unset: bool = False,
272286
exclude_none: bool = False,
273287
exclude_defaults: bool = False,
288+
custom_serializer: Optional[Callable[[Any], str]] = None,
274289
) -> Any:
275290
"""
276291
Dump an object to a hashable object, using the same parameters as jsonable_encoder
@@ -292,6 +307,7 @@ def _dump_other(
292307
exclude_unset=exclude_unset,
293308
exclude_defaults=exclude_defaults,
294309
exclude_none=exclude_none,
310+
custom_serializer=custom_serializer,
295311
)
296312

297313

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Exposes version constant to avoid circular dependencies."""
22

3-
VERSION = "2.40.1"
3+
VERSION = "2.40.2a3"

docs/core/event_handler/api_gateway.md

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,45 @@ This is the sample infrastructure for API Gateway and Lambda Function URLs we ar
5151

5252
### Event Resolvers
5353

54-
Before you decorate your functions to handle a given path and HTTP method(s), you need to initialize a resolver.
54+
Before you decorate your functions to handle a given path and HTTP method(s), you need to initialize a resolver. A resolver will handle request resolution, including [one or more routers](#split-routes-with-router), and give you access to the current event via typed properties.
5555

56-
A resolver will handle request resolution, including [one or more routers](#split-routes-with-router), and give you access to the current event via typed properties.
56+
By default, we will use `APIGatewayRestResolver` throughout the documentation. You can use any of the following:
5757

58-
For resolvers, we provide: `APIGatewayRestResolver`, `APIGatewayHttpResolver`, `ALBResolver`, `LambdaFunctionUrlResolver`, and `VPCLatticeResolver`. From here on, we will default to `APIGatewayRestResolver` across examples.
58+
| Resolver | AWS service |
59+
| ------------------------------------------------------- | -------------------------------------- |
60+
| **[`APIGatewayRestResolver`](#api-gateway-rest-api)** | Amazon API Gateway REST API |
61+
| **[`APIGatewayHttpResolver`](#api-gateway-http-api)** | Amazon API Gateway HTTP API |
62+
| **[`ALBResolver`](#application-load-balancer)** | Amazon Application Load Balancer (ALB) |
63+
| **[`LambdaFunctionUrlResolver`](#lambda-function-url)** | AWS Lambda Function URL |
64+
| **[`VPCLatticeResolver`](#vpc-lattice)** | Amazon VPC Lattice |
5965

60-
???+ info "Auto-serialization"
61-
We serialize `Dict` responses as JSON, trim whitespace for compact responses, set content-type to `application/json`, and
62-
return a 200 OK HTTP status. You can optionally set a different HTTP status code as the second argument of the tuple:
66+
#### Response auto-serialization
67+
68+
> Want full control of the response, headers and status code? [Read about `Response` object here](#fine-grained-responses).
69+
70+
For your convenience, we automatically perform these if you return a dictionary response:
71+
72+
1. Auto-serialize `dictionary` responses to JSON and trim it
73+
2. Include the response under each resolver's equivalent of a `body`
74+
3. Set `Content-Type` to `application/json`
75+
4. Set `status_code` to 200 (OK)
76+
77+
=== "getting_started_resolvers_response_serialization.py"
78+
79+
```python hl_lines="9"
80+
--8<-- "examples/event_handler_rest/src/getting_started_resolvers_response_serialization.py"
81+
```
82+
83+
1. This dictionary will be serialized, trimmed, and included under the `body` key
84+
85+
=== "getting_started_resolvers_response_serialization_output.json"
86+
87+
```json hl_lines="8"
88+
--8<-- "examples/event_handler_rest/src/getting_started_resolvers_response_serialization_output.json"
89+
```
90+
91+
??? info "Coming from Flask? We also support tuple response"
92+
You can optionally set a different HTTP status code as the second argument of the tuple.
6393

6494
```python hl_lines="15 16"
6595
--8<-- "examples/event_handler_rest/src/getting_started_return_tuple.py"
@@ -462,16 +492,16 @@ In the following example, we use a new `Header` OpenAPI type to add [one out of
462492

463493
With data validation enabled, we natively support serializing the following data types to JSON:
464494

465-
| Data type | Serialized type |
466-
| -------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
467-
| **Pydantic models** | `dict` |
468-
| **Python Dataclasses** | `dict` |
469-
| **Enum** | Enum values |
470-
| **Datetime** | Datetime ISO format string |
471-
| **Decimal** | `int` if no exponent, or `float` |
472-
| **Path** | `str` |
473-
| **UUID** | `str` |
474-
| **Set** | `list` |
495+
| Data type | Serialized type |
496+
| -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
497+
| **Pydantic models** | `dict` |
498+
| **Python Dataclasses** | `dict` |
499+
| **Enum** | Enum values |
500+
| **Datetime** | Datetime ISO format string |
501+
| **Decimal** | `int` if no exponent, or `float` |
502+
| **Path** | `str` |
503+
| **UUID** | `str` |
504+
| **Set** | `list` |
475505
| **Python primitives** _(dict, string, sequences, numbers, booleans)_ | [Python's default JSON serializable types](https://docs.python.org/3/library/json.html#encoders-and-decoders){target="_blank" rel="nofollow"} |
476506

477507
???+ info "See [custom serializer section](#custom-serializer) for bringing your own."
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
2+
from aws_lambda_powertools.utilities.typing.lambda_context import LambdaContext
3+
4+
app = APIGatewayRestResolver()
5+
6+
7+
@app.get("/ping")
8+
def ping():
9+
return {"message": "pong"} # (1)!
10+
11+
12+
def lambda_handler(event: dict, context: LambdaContext) -> dict:
13+
return app.resolve(event, context)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"statusCode": 200,
3+
"multiValueHeaders": {
4+
"Content-Type": [
5+
"application/json"
6+
]
7+
},
8+
"body": "{'message':'pong'}",
9+
"isBase64Encoded": false
10+
}

layer/scripts/layer-balancer/go.mod

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,25 @@ module layerbalancer
33
go 1.18
44

55
require (
6-
github.com/aws/aws-sdk-go-v2 v1.30.0
7-
github.com/aws/aws-sdk-go-v2/config v1.27.22
8-
github.com/aws/aws-sdk-go-v2/service/lambda v1.56.0
6+
github.com/aws/aws-sdk-go-v2 v1.30.1
7+
github.com/aws/aws-sdk-go-v2/config v1.27.24
8+
github.com/aws/aws-sdk-go-v2/service/lambda v1.56.1
99
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
1010
golang.org/x/sync v0.7.0
1111
)
1212

1313
require (
14-
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect
15-
github.com/aws/aws-sdk-go-v2/credentials v1.17.22 // indirect
16-
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.8 // indirect
17-
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.12 // indirect
18-
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.12 // indirect
14+
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 // indirect
15+
github.com/aws/aws-sdk-go-v2/credentials v1.17.24 // indirect
16+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.9 // indirect
17+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.13 // indirect
18+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.13 // indirect
1919
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
20-
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
21-
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.14 // indirect
22-
github.com/aws/aws-sdk-go-v2/service/sso v1.22.0 // indirect
23-
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.0 // indirect
24-
github.com/aws/aws-sdk-go-v2/service/sts v1.30.0 // indirect
25-
github.com/aws/smithy-go v1.20.2 // indirect
20+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect
21+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.15 // indirect
22+
github.com/aws/aws-sdk-go-v2/service/sso v1.22.1 // indirect
23+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.2 // indirect
24+
github.com/aws/aws-sdk-go-v2/service/sts v1.30.1 // indirect
25+
github.com/aws/smithy-go v1.20.3 // indirect
2626
github.com/jmespath/go-jmespath v0.4.0 // indirect
2727
)

0 commit comments

Comments
 (0)