Skip to content

Commit e4cff52

Browse files
Merge branch 'develop' into feature/openapi_examples
2 parents 4aff514 + df75e42 commit e4cff52

File tree

25 files changed

+323
-235
lines changed

25 files changed

+323
-235
lines changed

.github/workflows/bootstrap_region.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,11 @@ jobs:
7575
strategy:
7676
matrix:
7777
layer:
78-
- AWSLambdaPowertoolsPythonV3-python38-arm64
7978
- AWSLambdaPowertoolsPythonV3-python39-arm64
8079
- AWSLambdaPowertoolsPythonV3-python310-arm64
8180
- AWSLambdaPowertoolsPythonV3-python311-arm64
8281
- AWSLambdaPowertoolsPythonV3-python312-arm64
8382
- AWSLambdaPowertoolsPythonV3-python313-arm64
84-
- AWSLambdaPowertoolsPythonV3-python38-x86_64
8583
- AWSLambdaPowertoolsPythonV3-python39-x86_64
8684
- AWSLambdaPowertoolsPythonV3-python310-x86_64
8785
- AWSLambdaPowertoolsPythonV3-python311-x86_64

.github/workflows/layer_rename.yml

Lines changed: 0 additions & 163 deletions
This file was deleted.

.github/workflows/reusable_deploy_v3_layer_stack.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ jobs:
7474
# aws ec2 describe-regions --all-regions --query "Regions[].RegionName" --output text | tr "\t" "\n" | sort
7575
region: ["af-south-1", "ap-east-1", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3",
7676
"ap-south-1", "ap-south-2", "ap-southeast-1", "ap-southeast-2", "ap-southeast-3",
77-
"ap-southeast-4", "ap-southeast-5", "ca-central-1", "ca-west-1", "eu-central-1", "eu-central-2",
77+
"ap-southeast-4", "ap-southeast-5", "ap-southeast-7", "ca-central-1", "ca-west-1", "eu-central-1", "eu-central-2",
7878
"eu-north-1", "eu-south-1", "eu-south-2", "eu-west-1", "eu-west-2", "eu-west-3",
79-
"il-central-1", "me-central-1", "me-south-1", "sa-east-1", "us-east-1",
79+
"il-central-1", "me-central-1", "me-south-1", "mx-central-1", "sa-east-1", "us-east-1",
8080
"us-east-2", "us-west-1", "us-west-2"]
8181
python-version: ["3.9","3.10","3.11","3.12","3.13"]
8282
include:
@@ -104,6 +104,8 @@ jobs:
104104
has_arm64_support: "true"
105105
- region: "ap-southeast-5"
106106
has_arm64_support: "true"
107+
- region: "ap-southeast-7"
108+
has_arm64_support: "true"
107109
- region: "ca-central-1"
108110
has_arm64_support: "true"
109111
- region: "ca-west-1"
@@ -130,6 +132,8 @@ jobs:
130132
has_arm64_support: "true"
131133
- region: "me-south-1"
132134
has_arm64_support: "true"
135+
- region: "mx-central-1"
136+
has_arm64_support: "true"
133137
- region: "sa-east-1"
134138
has_arm64_support: "true"
135139
- region: "us-east-1"

.github/workflows/update_ssm.yml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ run-name: SSM Parameters - Python
1313
# A successful parameter would look similar to:
1414
# /aws/service/powertools/python/arm64/python3.13/3.1.0
1515
# And will have a value of:
16-
# arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python38-arm64:4
16+
# arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV3-python313-arm64:4
1717

1818
on:
1919
workflow_dispatch:
@@ -51,12 +51,11 @@ jobs:
5151
strategy:
5252
matrix:
5353
region: ["af-south-1", "ap-east-1", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3",
54-
"ap-south-1", "ap-south-2", "ap-southeast-1", "ap-southeast-2", "ap-southeast-3",
55-
"ap-southeast-4", "ca-central-1", "ca-west-1", "eu-central-1", "eu-central-2",
56-
"eu-north-1", "eu-south-1", "eu-south-2", "eu-west-1", "eu-west-2", "eu-west-3",
57-
"il-central-1", "me-central-1", "me-south-1", "sa-east-1", "us-east-1",
58-
"us-east-2", "us-west-1", "us-west-2", "ap-southeast-5"
59-
]
54+
"ap-south-1", "ap-south-2", "ap-southeast-1", "ap-southeast-2", "ap-southeast-3",
55+
"ap-southeast-4", "ap-southeast-5", "ap-southeast-7", "ca-central-1", "ca-west-1", "eu-central-1", "eu-central-2",
56+
"eu-north-1", "eu-south-1", "eu-south-2", "eu-west-1", "eu-west-2", "eu-west-3",
57+
"il-central-1", "me-central-1", "me-south-1", "mx-central-1", "sa-east-1", "us-east-1",
58+
"us-east-2", "us-west-1", "us-west-2"]
6059

6160
permissions:
6261
contents: read

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,26 @@
88

99
* **security:** fix encryption_context handling in data masking operations ([#6074](https://github.com/aws-powertools/powertools-lambda-python/issues/6074))
1010

11+
## Documentation
12+
13+
* **roadmap:** update roadmap ([#6077](https://github.com/aws-powertools/powertools-lambda-python/issues/6077))
14+
1115
## Maintenance
1216

1317
* **ci:** new pre-release 3.6.1a0 ([#6084](https://github.com/aws-powertools/powertools-lambda-python/issues/6084))
18+
* **ci:** new pre-release 3.6.1a2 ([#6098](https://github.com/aws-powertools/powertools-lambda-python/issues/6098))
19+
* **ci:** new pre-release 3.6.1a1 ([#6090](https://github.com/aws-powertools/powertools-lambda-python/issues/6090))
20+
* **ci:** new pre-release 3.6.1a3 ([#6107](https://github.com/aws-powertools/powertools-lambda-python/issues/6107))
21+
* **deps:** bump squidfunk/mkdocs-material from `c62453b` to `f5bcec4` in /docs ([#6087](https://github.com/aws-powertools/powertools-lambda-python/issues/6087))
1422
* **deps:** bump aws-actions/configure-aws-credentials from 4.0.3 to 4.1.0 ([#6082](https://github.com/aws-powertools/powertools-lambda-python/issues/6082))
23+
* **deps-dev:** bump boto3-stubs from 1.36.17 to 1.36.19 ([#6093](https://github.com/aws-powertools/powertools-lambda-python/issues/6093))
24+
* **deps-dev:** bump aws-cdk from 2.178.1 to 2.178.2 ([#6089](https://github.com/aws-powertools/powertools-lambda-python/issues/6089))
25+
* **deps-dev:** bump aws-cdk-aws-lambda-python-alpha from 2.178.1a0 to 2.178.2a0 ([#6095](https://github.com/aws-powertools/powertools-lambda-python/issues/6095))
1526
* **deps-dev:** bump coverage from 7.6.11 to 7.6.12 ([#6080](https://github.com/aws-powertools/powertools-lambda-python/issues/6080))
1627
* **deps-dev:** bump mkdocstrings-python from 1.14.6 to 1.15.0 ([#6079](https://github.com/aws-powertools/powertools-lambda-python/issues/6079))
1728
* **deps-dev:** bump boto3-stubs from 1.36.16 to 1.36.17 ([#6078](https://github.com/aws-powertools/powertools-lambda-python/issues/6078))
29+
* **deps-dev:** bump sentry-sdk from 2.20.0 to 2.21.0 ([#6096](https://github.com/aws-powertools/powertools-lambda-python/issues/6096))
30+
* **deps-dev:** bump mkdocs-material from 9.6.3 to 9.6.4 ([#6097](https://github.com/aws-powertools/powertools-lambda-python/issues/6097))
1831

1932

2033
<a name="v3.6.0"></a>

aws_lambda_powertools/logging/exceptions.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,11 @@ class InvalidLoggerSamplingRateError(Exception):
44
"""
55

66
pass
7+
8+
9+
class OrphanedChildLoggerError(Exception):
10+
"""
11+
Orphaned Child logger exception
12+
"""
13+
14+
pass

aws_lambda_powertools/logging/logger.py

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
import sys
1515
import warnings
1616
from contextlib import contextmanager
17-
from typing import IO, TYPE_CHECKING, Any, Callable, Generator, Iterable, Mapping, TypeVar, overload
17+
from typing import IO, TYPE_CHECKING, Any, Callable, Generator, Iterable, Mapping, TypeVar, cast, overload
1818

1919
from aws_lambda_powertools.logging.constants import (
20+
LOGGER_ATTRIBUTE_HANDLER,
21+
LOGGER_ATTRIBUTE_POWERTOOLS_HANDLER,
2022
LOGGER_ATTRIBUTE_PRECONFIGURED,
2123
)
22-
from aws_lambda_powertools.logging.exceptions import InvalidLoggerSamplingRateError
24+
from aws_lambda_powertools.logging.exceptions import InvalidLoggerSamplingRateError, OrphanedChildLoggerError
2325
from aws_lambda_powertools.logging.filters import SuppressFilter
2426
from aws_lambda_powertools.logging.formatter import (
2527
RESERVED_FORMATTER_CUSTOM_KEYS,
@@ -230,13 +232,14 @@ def __init__(
230232
self.child = child
231233
self.logger_formatter = logger_formatter
232234
self._stream = stream or sys.stdout
233-
self.logger_handler = logger_handler or logging.StreamHandler(self._stream)
235+
234236
self.log_uncaught_exceptions = log_uncaught_exceptions
235237

236238
self._is_deduplication_disabled = resolve_truthy_env_var_choice(
237239
env=os.getenv(constants.LOGGER_LOG_DEDUPLICATION_ENV, "false"),
238240
)
239241
self._logger = self._get_logger()
242+
self.logger_handler = logger_handler or self._get_handler()
240243

241244
# NOTE: This is primarily to improve UX, so IDEs can autocomplete LambdaPowertoolsFormatter options
242245
# previously, we masked all of them as kwargs thus limiting feature discovery
@@ -275,6 +278,23 @@ def _get_logger(self) -> logging.Logger:
275278

276279
return logging.getLogger(logger_name)
277280

281+
def _get_handler(self) -> logging.Handler:
282+
# is a logger handler already configured?
283+
if getattr(self, LOGGER_ATTRIBUTE_HANDLER, None):
284+
return self.logger_handler
285+
286+
# Detect Powertools logger by checking for unique handler
287+
# Retrieve the first handler if it's a Powertools instance
288+
if getattr(self._logger, "powertools_handler", None):
289+
return self._logger.handlers[0]
290+
291+
# for children, use parent's handler
292+
if self.child:
293+
return getattr(self._logger.parent, LOGGER_ATTRIBUTE_POWERTOOLS_HANDLER, None) # type: ignore[return-value] # always checked in formatting
294+
295+
# otherwise, create a new stream handler (first time init)
296+
return logging.StreamHandler(self._stream)
297+
278298
def _init_logger(
279299
self,
280300
formatter_options: dict | None = None,
@@ -317,6 +337,7 @@ def _init_logger(
317337
# std logging will return the same Logger with our attribute if name is reused
318338
logger.debug(f"Marking logger {self.service} as preconfigured")
319339
self._logger.init = True # type: ignore[attr-defined]
340+
self._logger.powertools_handler = self.logger_handler # type: ignore[attr-defined]
320341

321342
def _configure_sampling(self) -> None:
322343
"""Dynamically set log level based on sampling rate
@@ -723,13 +744,20 @@ def registered_handler(self) -> logging.Handler:
723744
"""Convenience property to access the first logger handler"""
724745
# We ignore mypy here because self.child encodes whether or not self._logger.parent is
725746
# None, mypy can't see this from context but we can
726-
handlers = self._logger.parent.handlers if self.child else self._logger.handlers # type: ignore[union-attr]
727-
return handlers[0]
747+
return self._get_handler()
728748

729749
@property
730750
def registered_formatter(self) -> BasePowertoolsFormatter:
731751
"""Convenience property to access the first logger formatter"""
732-
return self.registered_handler.formatter # type: ignore[return-value]
752+
handler = self.registered_handler
753+
if handler is None:
754+
raise OrphanedChildLoggerError(
755+
"Orphan child loggers cannot append nor remove keys until a parent is initialized first. "
756+
"To solve this issue, you can A) make sure a parent logger is initialized first, or B) move append/remove keys operations to a later stage." # noqa: E501
757+
"Reference: https://docs.powertools.aws.dev/lambda/python/latest/core/logger/#reusing-logger-across-your-code",
758+
)
759+
760+
return cast(BasePowertoolsFormatter, handler.formatter)
733761

734762
@property
735763
def log_level(self) -> int:
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 = "3.6.1a0"
3+
VERSION = "3.6.1a3"

aws_lambda_powertools/utilities/batch/decorators.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
BatchProcessor,
1313
EventType,
1414
)
15+
from aws_lambda_powertools.utilities.batch.exceptions import UnexpectedBatchTypeError
1516
from aws_lambda_powertools.warnings import PowertoolsDeprecationWarning
1617

1718
if TYPE_CHECKING:
@@ -204,6 +205,11 @@ def handler(event, context):
204205
"""
205206
try:
206207
records: list[dict] = event.get("Records", [])
208+
if not records or not isinstance(records, list):
209+
raise UnexpectedBatchTypeError(
210+
"Unexpected batch event type. Possible values are: SQS, KinesisDataStreams, DynamoDBStreams",
211+
)
212+
207213
except AttributeError:
208214
event_types = ", ".join(list(EventType.__members__))
209215
docs = "https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/#processing-messages-from-sqs" # noqa: E501 # long-line
@@ -268,6 +274,11 @@ def handler(event, context):
268274
"""
269275
try:
270276
records: list[dict] = event.get("Records", [])
277+
if not records or not isinstance(records, list):
278+
raise UnexpectedBatchTypeError(
279+
"Unexpected batch event type. Possible values are: SQS, KinesisDataStreams, DynamoDBStreams",
280+
)
281+
271282
except AttributeError:
272283
event_types = ", ".join(list(EventType.__members__))
273284
docs = "https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/#processing-messages-from-sqs" # noqa: E501 # long-line

0 commit comments

Comments
 (0)