Skip to content

Commit 42d8b06

Browse files
Merge branch 'develop' into feat/kafka-avro-offline-schema-prefix
2 parents e10e470 + fe7d5d2 commit 42d8b06

17 files changed

Lines changed: 122 additions & 145 deletions

File tree

‎.github/workflows/bootstrap_region.yml‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,11 @@ jobs:
8080
strategy:
8181
matrix:
8282
layer:
83-
- AWSLambdaPowertoolsPythonV3-python39-arm64
8483
- AWSLambdaPowertoolsPythonV3-python310-arm64
8584
- AWSLambdaPowertoolsPythonV3-python311-arm64
8685
- AWSLambdaPowertoolsPythonV3-python312-arm64
8786
- AWSLambdaPowertoolsPythonV3-python313-arm64
8887
- AWSLambdaPowertoolsPythonV3-python314-arm64
89-
- AWSLambdaPowertoolsPythonV3-python39-x86_64
9088
- AWSLambdaPowertoolsPythonV3-python310-x86_64
9189
- AWSLambdaPowertoolsPythonV3-python311-x86_64
9290
- AWSLambdaPowertoolsPythonV3-python312-x86_64

‎.github/workflows/layer_govcloud.yml‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ jobs:
5252
strategy:
5353
matrix:
5454
layer:
55-
- AWSLambdaPowertoolsPythonV3-python39
5655
- AWSLambdaPowertoolsPythonV3-python310
5756
- AWSLambdaPowertoolsPythonV3-python311
5857
- AWSLambdaPowertoolsPythonV3-python312
@@ -98,7 +97,6 @@ jobs:
9897
strategy:
9998
matrix:
10099
layer:
101-
- AWSLambdaPowertoolsPythonV3-python39
102100
- AWSLambdaPowertoolsPythonV3-python310
103101
- AWSLambdaPowertoolsPythonV3-python311
104102
- AWSLambdaPowertoolsPythonV3-python312
@@ -167,7 +165,6 @@ jobs:
167165
strategy:
168166
matrix:
169167
layer:
170-
- AWSLambdaPowertoolsPythonV3-python39
171168
- AWSLambdaPowertoolsPythonV3-python310
172169
- AWSLambdaPowertoolsPythonV3-python311
173170
- AWSLambdaPowertoolsPythonV3-python312

‎.github/workflows/layer_govcloud_verify.yml‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ jobs:
2828
strategy:
2929
matrix:
3030
layer:
31-
- AWSLambdaPowertoolsPythonV3-python39
3231
- AWSLambdaPowertoolsPythonV3-python310
3332
- AWSLambdaPowertoolsPythonV3-python311
3433
- AWSLambdaPowertoolsPythonV3-python312
@@ -59,7 +58,6 @@ jobs:
5958
strategy:
6059
matrix:
6160
layer:
62-
- AWSLambdaPowertoolsPythonV3-python39
6361
- AWSLambdaPowertoolsPythonV3-python310
6462
- AWSLambdaPowertoolsPythonV3-python311
6563
- AWSLambdaPowertoolsPythonV3-python312
@@ -91,7 +89,6 @@ jobs:
9189
strategy:
9290
matrix:
9391
layer:
94-
- AWSLambdaPowertoolsPythonV3-python39
9592
- AWSLambdaPowertoolsPythonV3-python310
9693
- AWSLambdaPowertoolsPythonV3-python311
9794
- AWSLambdaPowertoolsPythonV3-python312

‎.github/workflows/layers_partition_verify.yml‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ jobs:
7777
strategy:
7878
matrix:
7979
layer:
80+
# Python 3.9 remains here to verify its final layer version.
8081
- AWSLambdaPowertoolsPythonV3-python39
8182
- AWSLambdaPowertoolsPythonV3-python310
8283
- AWSLambdaPowertoolsPythonV3-python311
@@ -94,9 +95,11 @@ jobs:
9495
aws-region: us-east-1
9596
mask-aws-account-id: true
9697
- name: Output ${{ matrix.layer }}-${{ matrix.arch }}
98+
env:
99+
VERSION: ${{ matrix.layer == 'AWSLambdaPowertoolsPythonV3-python39' && '27' || inputs.version }}
97100
# fetch the specific layer version information from the us-east-1 commercial region
98101
run: |
99-
aws --region us-east-1 lambda get-layer-version-by-arn --arn 'arn:aws:lambda:us-east-1:017000801446:layer:${{ matrix.layer }}-${{ matrix.arch }}:${{ inputs.version }}' > '${{ matrix.layer }}-${{ matrix.arch }}.json'
102+
aws --region us-east-1 lambda get-layer-version-by-arn --arn "arn:aws:lambda:us-east-1:017000801446:layer:${{ matrix.layer }}-${{ matrix.arch }}:${VERSION}" > '${{ matrix.layer }}-${{ matrix.arch }}.json'
100103
- name: Store Metadata
101104
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
102105
with:
@@ -120,6 +123,7 @@ jobs:
120123
matrix:
121124
region: ${{ fromJson(needs.setup.outputs.regions) }}
122125
layer:
126+
# Python 3.9 remains here to verify its final layer version.
123127
- AWSLambdaPowertoolsPythonV3-python39
124128
- AWSLambdaPowertoolsPythonV3-python310
125129
- AWSLambdaPowertoolsPythonV3-python311
@@ -146,8 +150,10 @@ jobs:
146150
audience: ${{ needs.setup.outputs.aud }}
147151
- id: partition_version
148152
name: Partition Layer Version
153+
env:
154+
VERSION: ${{ matrix.layer == 'AWSLambdaPowertoolsPythonV3-python39' && '27' || inputs.partition_version || inputs.version }}
149155
run: |
150-
echo 'partition_version=$([[ -n "${{ inputs.partition_version}}" ]] && echo ${{ inputs.partition_version}} || echo ${{ inputs.version }} )' >> "$GITHUB_OUTPUT"
156+
echo "partition_version=$VERSION" >> "$GITHUB_OUTPUT"
151157
- name: Verify Layer
152158
run: |
153159
export layer_output='${{ matrix.layer }}-${{ matrix.arch }}-${{matrix.region}}.json'

‎.github/workflows/layers_partitions.yml‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ jobs:
7878
strategy:
7979
matrix:
8080
layer:
81-
- AWSLambdaPowertoolsPythonV3-python39
8281
- AWSLambdaPowertoolsPythonV3-python310
8382
- AWSLambdaPowertoolsPythonV3-python311
8483
- AWSLambdaPowertoolsPythonV3-python312
@@ -150,7 +149,6 @@ jobs:
150149
matrix:
151150
region: ${{ fromJson(needs.setup.outputs.regions) }}
152151
layer:
153-
- AWSLambdaPowertoolsPythonV3-python39
154152
- AWSLambdaPowertoolsPythonV3-python310
155153
- AWSLambdaPowertoolsPythonV3-python311
156154
- AWSLambdaPowertoolsPythonV3-python312

‎.github/workflows/publish_v3_layer.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ jobs:
284284
id: create-pr
285285
uses: ./.github/actions/create-pr
286286
with:
287-
files: "docs/index.md docs/includes/_layer_homepage_arm64.md docs/includes/_layer_homepage_x86.md examples CHANGELOG.md"
287+
files: "docs/index.md docs/getting-started/install.md docs/includes/_layer_homepage_arm64.md docs/includes/_layer_homepage_x86.md examples CHANGELOG.md"
288288
temp_branch_prefix: "ci-layer-docs"
289289
pull_request_title: "chore(ci): layer docs update"
290290
github_token: ${{ secrets.GITHUB_TOKEN }}

‎aws_lambda_powertools/utilities/data_classes/api_gateway_authorizer_event.py‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,8 +520,11 @@ def _add_route(self, effect: str, http_method: str, resource: str, conditions: l
520520
"""Adds a route to the internal lists of allowed or denied routes. Each object in
521521
the internal list contains a resource ARN and a condition statement. The condition
522522
statement can be null."""
523-
if http_method != "*" and http_method not in HttpVerb.__members__:
524-
allowed_values = [verb.value for verb in HttpVerb]
523+
allowed_values = [verb.value for verb in HttpVerb]
524+
if http_method in HttpVerb.__members__:
525+
http_method = HttpVerb[http_method].value
526+
527+
if http_method not in allowed_values:
525528
raise ValueError(f"Invalid HTTP verb: '{http_method}'. Use either '{allowed_values}'")
526529

527530
if not self._resource_pattern.match(resource):

‎aws_lambda_powertools/utilities/data_masking/base.py‎

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
from jsonpath_ng.ext import parse
1717

1818
from aws_lambda_powertools.utilities.data_masking.exceptions import (
19+
DataMaskingError,
1920
DataMaskingFieldNotFoundError,
2021
DataMaskingUnsupportedTypeError,
2122
)
2223
from aws_lambda_powertools.utilities.data_masking.provider import BaseProvider
23-
from aws_lambda_powertools.warnings import PowertoolsUserWarning
2424

2525
if TYPE_CHECKING:
2626
from collections.abc import Callable, Mapping, Sequence
@@ -395,10 +395,10 @@ def _apply_action_to_fields(
395395
if not result_parse:
396396
if self.raise_on_missing_field:
397397
# If the data for the field is not found, raise an exception.
398-
raise DataMaskingFieldNotFoundError(f"Field or expression {field_parse} not found in {data_parsed}")
398+
raise DataMaskingFieldNotFoundError(f"Field or expression {field_parse} not found")
399399
else:
400400
# If the data for the field is not found, warning.
401-
warnings.warn(f"Field or expression {field_parse} not found in {data_parsed}", stacklevel=2)
401+
warnings.warn(f"Field or expression {field_parse} not found", stacklevel=2)
402402

403403
# For in-place updates, json_parse accepts a callback function
404404
# that receives 3 args: field_value, fields, field_name
@@ -427,31 +427,30 @@ def _apply_masking_rules(self, data: dict, masking_rules: dict) -> dict:
427427
for path, rule in masking_rules.items():
428428
try:
429429
jsonpath_expr = parse(f"$.{path}")
430-
matches = jsonpath_expr.find(result)
430+
except Exception as exc:
431+
raise DataMaskingError(f"Invalid masking path: {path}") from exc
431432

432-
if not matches:
433-
warnings.warn(f"No matches found for path: {path}", stacklevel=2)
434-
continue
433+
matches = jsonpath_expr.find(result)
434+
if not matches:
435+
if self.raise_on_missing_field:
436+
raise DataMaskingFieldNotFoundError(f"Field or expression {path} not found")
435437

436-
for match in matches:
437-
try:
438-
value = match.value
439-
if value is not None:
440-
masked_value = self.provider.erase(str(value), **rule)
441-
match.full_path.update(result, masked_value)
442-
443-
except Exception as e:
444-
warnings.warn(
445-
f"Error masking value for path {path}: {str(e)}",
446-
category=PowertoolsUserWarning,
447-
stacklevel=2,
448-
)
449-
continue
450-
451-
except Exception as e:
452-
warnings.warn(f"Error processing path {path}: {str(e)}", category=PowertoolsUserWarning, stacklevel=2)
438+
warnings.warn(f"No matches found for path: {path}", stacklevel=2)
453439
continue
454440

441+
for match in matches:
442+
value = match.value
443+
if value is None:
444+
continue
445+
446+
try:
447+
masked_value = self.provider.erase(str(value), **rule)
448+
match.full_path.update(result, masked_value)
449+
except DataMaskingError:
450+
raise
451+
except Exception as exc:
452+
raise DataMaskingError(f"Failed to mask field at path: {path}") from exc
453+
455454
return result
456455

457456
def _mask_nested_field(self, data: dict, field_path: str, mask_function):
Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,40 @@
1-
class DataMaskingUnsupportedTypeError(Exception):
1+
class DataMaskingError(Exception):
2+
"""
3+
Base exception for data masking failures.
4+
"""
5+
6+
7+
class DataMaskingUnsupportedTypeError(DataMaskingError):
28
"""
39
UnsupportedType Error
410
"""
511

612

7-
class DataMaskingDecryptKeyError(Exception):
13+
class DataMaskingDecryptKeyError(DataMaskingError):
814
"""
915
Decrypting with an invalid AWS KMS Key ARN.
1016
"""
1117

1218

13-
class DataMaskingEncryptKeyError(Exception):
19+
class DataMaskingEncryptKeyError(DataMaskingError):
1420
"""
1521
Encrypting with an invalid AWS KMS Key ARN.
1622
"""
1723

1824

19-
class DataMaskingDecryptValueError(Exception):
25+
class DataMaskingDecryptValueError(DataMaskingError):
2026
"""
2127
Decrypting an invalid field.
2228
"""
2329

2430

25-
class DataMaskingContextMismatchError(Exception):
31+
class DataMaskingContextMismatchError(DataMaskingError):
2632
"""
2733
Decrypting with the incorrect encryption context.
2834
"""
2935

3036

31-
class DataMaskingFieldNotFoundError(Exception):
37+
class DataMaskingFieldNotFoundError(DataMaskingError):
3238
"""
3339
Field not found.
3440
"""

‎aws_lambda_powertools/utilities/data_masking/provider/base.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from typing import TYPE_CHECKING, Any
77

88
from aws_lambda_powertools.utilities.data_masking.constants import DATA_MASKING_STRING
9+
from aws_lambda_powertools.utilities.data_masking.exceptions import DataMaskingError
910

1011
if TYPE_CHECKING:
1112
from collections.abc import Callable
@@ -183,8 +184,8 @@ def _regex_mask(self, data: str, regex_pattern: str, mask_format: str) -> str:
183184
if regex_pattern not in _regex_cache:
184185
_regex_cache[regex_pattern] = re.compile(regex_pattern)
185186
return _regex_cache[regex_pattern].sub(mask_format, data)
186-
except re.error:
187-
return data
187+
except re.error as exc:
188+
raise DataMaskingError("Invalid regex pattern") from exc
188189

189190
def _custom_erase(self, data: str) -> str:
190191
if not data:

0 commit comments

Comments
 (0)