Skip to content

Commit 83e19e3

Browse files
author
Neel Krishna
committed
refactor!: deprecate extract_data_from_envelope in jmespath_utils and replace with query
1 parent 0f610dc commit 83e19e3

15 files changed

+56
-34
lines changed

Diff for: aws_lambda_powertools/logging/logger.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ def decorate(event, context, *args, **kwargs):
440440

441441
if correlation_id_path:
442442
self.set_correlation_id(
443-
jmespath_utils.extract_data_from_envelope(envelope=correlation_id_path, data=event),
443+
jmespath_utils.query(envelope=correlation_id_path, data=event),
444444
)
445445

446446
if log_event:

Diff for: aws_lambda_powertools/utilities/feature_flags/appconfig.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def get_configuration(self) -> Dict[str, Any]:
103103

104104
if self.envelope:
105105
self.logger.debug("Envelope enabled; extracting data from config", extra={"envelope": self.envelope})
106-
config = jmespath_utils.extract_data_from_envelope(
106+
config = jmespath_utils.query(
107107
data=config,
108108
envelope=self.envelope,
109109
jmespath_options=self.jmespath_options,

Diff for: aws_lambda_powertools/utilities/jmespath_utils/__init__.py

+26-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import gzip
33
import json
44
import logging
5+
import warnings
56
from typing import Any, Dict, Optional, Union
67

78
import jmespath
@@ -33,6 +34,29 @@ def _func_powertools_base64_gzip(self, value):
3334
def extract_data_from_envelope(data: Union[Dict, str], envelope: str, jmespath_options: Optional[Dict] = None) -> Any:
3435
"""Searches and extracts data using JMESPath
3536
37+
*Deprecated*: Use query instead
38+
"""
39+
warnings.warn(
40+
"The extract_data_from_envelope method is deprecated and will be "
41+
"removed in the next major version. Use query instead.",
42+
category=DeprecationWarning,
43+
stacklevel=2,
44+
)
45+
46+
if not jmespath_options:
47+
jmespath_options = {"custom_functions": PowertoolsFunctions()}
48+
49+
try:
50+
logger.debug(f"Envelope detected: {envelope}. JMESPath options: {jmespath_options}")
51+
return jmespath.search(envelope, data, options=jmespath.Options(**jmespath_options))
52+
except (LexerError, TypeError, UnicodeError) as e:
53+
message = f"Failed to unwrap event from envelope using expression. Error: {e} Exp: {envelope}, Data: {data}" # noqa: B306, E501
54+
raise InvalidEnvelopeExpressionError(message)
55+
56+
57+
def query(data: Union[Dict, str], envelope: str, jmespath_options: Optional[Dict] = None) -> Any:
58+
"""Searches and extracts data using JMESPath
59+
3660
Envelope being the JMESPath expression to extract the data you're after
3761
3862
Built-in JMESPath functions include: powertools_json, powertools_base64, powertools_base64_gzip
@@ -42,13 +66,13 @@ def extract_data_from_envelope(data: Union[Dict, str], envelope: str, jmespath_o
4266
4367
**Deserialize JSON string and extracts data from body key**
4468
45-
from aws_lambda_powertools.utilities.jmespath_utils import extract_data_from_envelope
69+
from aws_lambda_powertools.utilities.jmespath_utils import query
4670
from aws_lambda_powertools.utilities.typing import LambdaContext
4771
4872
4973
def handler(event: dict, context: LambdaContext):
5074
# event = {"body": "{\"customerId\":\"dd4649e6-2484-4993-acb8-0f9123103394\"}"} # noqa: ERA001
51-
payload = extract_data_from_envelope(data=event, envelope="powertools_json(body)")
75+
payload = query(data=event, envelope="powertools_json(body)")
5276
customer = payload.get("customerId") # now deserialized
5377
...
5478

Diff for: aws_lambda_powertools/utilities/validation/validator.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def handler(event, context):
119119
When JMESPath expression to unwrap event is invalid
120120
""" # noqa: E501
121121
if envelope:
122-
event = jmespath_utils.extract_data_from_envelope(
122+
event = jmespath_utils.query(
123123
data=event,
124124
envelope=envelope,
125125
jmespath_options=jmespath_options,
@@ -223,7 +223,7 @@ def handler(event, context):
223223
When JMESPath expression to unwrap event is invalid
224224
""" # noqa: E501
225225
if envelope:
226-
event = jmespath_utils.extract_data_from_envelope(
226+
event = jmespath_utils.query(
227227
data=event,
228228
envelope=envelope,
229229
jmespath_options=jmespath_options,

Diff for: docs/utilities/jmespath_functions.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Powertools for AWS Lambda (Python) also have utilities like [validation](validat
3030

3131
### Extracting data
3232

33-
You can use the `extract_data_from_envelope` function with any [JMESPath expression](https://jmespath.org/tutorial.html){target="_blank" rel="nofollow"}.
33+
You can use the `query` function with any [JMESPath expression](https://jmespath.org/tutorial.html){target="_blank" rel="nofollow"}.
3434

3535
???+ tip
3636
Another common use case is to fetch deeply nested data, filter, flatten, and more.
@@ -69,15 +69,15 @@ These are all built-in envelopes you can use along with their expression as a re
6969
| **`API_GATEWAY_HTTP`** | `powertools_json(body)` |
7070
| **`API_GATEWAY_REST`** | `powertools_json(body)` |
7171
| **`CLOUDWATCH_EVENTS_SCHEDULED`** | `detail` |
72-
| **`CLOUDWATCH_LOGS`** | `awslogs.powertools_base64_gzip(data) | powertools_json(@).logEvents[*]` |
72+
| **`CLOUDWATCH_LOGS`** | `awslogs.powertools_base64_gzip(data) |
7373
| **`EVENTBRIDGE`** | `detail` |
7474
| **`KINESIS_DATA_STREAM`** | `Records[*].kinesis.powertools_json(powertools_base64(data))` |
7575
| **`S3_EVENTBRIDGE_SQS`** | `Records[*].powertools_json(body).detail` |
7676
| **`S3_KINESIS_FIREHOSE`** | `records[*].powertools_json(powertools_base64(data)).Records[0]` |
7777
| **`S3_SNS_KINESIS_FIREHOSE`** | `records[*].powertools_json(powertools_base64(data)).powertools_json(Message).Records[0]` |
7878
| **`S3_SNS_SQS`** | `Records[*].powertools_json(body).powertools_json(Message).Records[0]` |
7979
| **`S3_SQS`** | `Records[*].powertools_json(body).Records[0]` |
80-
| **`SNS`** | `Records[0].Sns.Message | powertools_json(@)` |
80+
| **`SNS`** | `Records[0].Sns.Message |
8181
| **`SQS`** | `Records[*].powertools_json(body)` |
8282

8383
???+ tip "Using SNS?"

Diff for: examples/jmespath_functions/src/extract_data_from_builtin_envelope.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
from aws_lambda_powertools import Logger
44
from aws_lambda_powertools.utilities.jmespath_utils import (
55
envelopes,
6-
extract_data_from_envelope,
6+
query,
77
)
88
from aws_lambda_powertools.utilities.typing import LambdaContext
99

1010
logger = Logger()
1111

1212

1313
def handler(event: dict, context: LambdaContext) -> dict:
14-
records: list = extract_data_from_envelope(data=event, envelope=envelopes.SQS)
14+
records: list = query(data=event, envelope=envelopes.SQS)
1515
for record in records: # records is a list
1616
logger.info(record.get("customerId")) # now deserialized
1717

Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
from aws_lambda_powertools.utilities.jmespath_utils import extract_data_from_envelope
1+
from aws_lambda_powertools.utilities.jmespath_utils import query
22
from aws_lambda_powertools.utilities.typing import LambdaContext
33

44

55
def handler(event: dict, context: LambdaContext) -> dict:
6-
payload = extract_data_from_envelope(data=event, envelope="powertools_json(body)")
6+
payload = query(data=event, envelope="powertools_json(body)")
77
customer_id = payload.get("customerId") # now deserialized
88

99
# also works for fetching and flattening deeply nested data
10-
some_data = extract_data_from_envelope(data=event, envelope="deeply_nested[*].some_data[]")
10+
some_data = query(data=event, envelope="deeply_nested[*].some_data[]")
1111

1212
return {"customer_id": customer_id, "message": "success", "context": some_data, "statusCode": 200}

Diff for: examples/jmespath_functions/src/powertools_base64_gzip_jmespath_function.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def lambda_handler(event, context: LambdaContext) -> dict:
1414
try:
1515
validate(event=event, schema=schemas.INPUT, envelope="powertools_base64_gzip(payload) | powertools_json(@)")
1616

17-
# Alternatively, extract_data_from_envelope works here too
17+
# Alternatively, query works here too
1818
encoded_payload = base64.b64decode(event["payload"])
1919
uncompressed_payload = gzip.decompress(encoded_payload).decode()
2020
log: dict = json.loads(uncompressed_payload)

Diff for: examples/jmespath_functions/src/powertools_base64_jmespath_function.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def lambda_handler(event, context: LambdaContext) -> dict:
3535
try:
3636
validate(event=event, schema=schemas.INPUT, envelope="powertools_json(powertools_base64(payload))")
3737

38-
# alternatively, extract_data_from_envelope works here too
38+
# alternatively, query works here too
3939
payload_decoded = base64.b64decode(event["payload"]).decode()
4040

4141
order_payload: dict = json.loads(payload_decoded)

Diff for: examples/jmespath_functions/src/powertools_custom_jmespath_function.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from aws_lambda_powertools.utilities.jmespath_utils import (
99
PowertoolsFunctions,
10-
extract_data_from_envelope,
10+
query,
1111
)
1212

1313

@@ -27,7 +27,7 @@ def lambda_handler(event, context) -> dict:
2727
try:
2828
logs = []
2929
logs.append(
30-
extract_data_from_envelope(
30+
query(
3131
data=event,
3232
# NOTE: Use the prefix `_func_` before the name of the function
3333
envelope="Records[*].decode_zlib_compression(log)",

Diff for: examples/jmespath_functions/src/powertools_json_jmespath_function.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def lambda_handler(event, context: LambdaContext) -> dict:
3434
validate(event=event, schema=schemas.INPUT, envelope="powertools_json(payload)")
3535

3636
# Deserialize JSON string order as dict
37-
# alternatively, extract_data_from_envelope works here too
37+
# alternatively, query works here too
3838
order_payload: dict = json.loads(event.get("payload"))
3939

4040
return {

Diff for: examples/middleware_factory/src/combining_powertools_utilities_function.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from aws_lambda_powertools.middleware_factory import lambda_handler_decorator
1212
from aws_lambda_powertools.shared.types import JSONType
1313
from aws_lambda_powertools.utilities.feature_flags import AppConfigStore, FeatureFlags
14-
from aws_lambda_powertools.utilities.jmespath_utils import extract_data_from_envelope
14+
from aws_lambda_powertools.utilities.jmespath_utils import query
1515
from aws_lambda_powertools.utilities.typing import LambdaContext
1616
from aws_lambda_powertools.utilities.validation import SchemaValidationError, validate
1717

@@ -42,8 +42,8 @@ def middleware_custom(
4242
}
4343

4444
# extracting headers and requestContext from event
45-
headers = extract_data_from_envelope(data=event, envelope="headers")
46-
request_context = extract_data_from_envelope(data=event, envelope="requestContext")
45+
headers = query(data=event, envelope="headers")
46+
request_context = query(data=event, envelope="requestContext")
4747

4848
logger.debug(f"X-Customer-Id => {headers.get('X-Customer-Id')}")
4949
tracer.put_annotation(key="CustomerId", value=headers.get("X-Customer-Id"))

Diff for: examples/middleware_factory/src/getting_started_middleware_before_logic_function.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from aws_lambda_powertools.middleware_factory import lambda_handler_decorator
66
from aws_lambda_powertools.utilities.jmespath_utils import (
77
envelopes,
8-
extract_data_from_envelope,
8+
query,
99
)
1010
from aws_lambda_powertools.utilities.typing import LambdaContext
1111

@@ -19,8 +19,7 @@ class Payment:
1919
payment_id: str = field(default_factory=lambda: f"{uuid4()}")
2020

2121

22-
class PaymentError(Exception):
23-
...
22+
class PaymentError(Exception): ...
2423

2524

2625
@lambda_handler_decorator
@@ -30,7 +29,7 @@ def middleware_before(
3029
context: LambdaContext,
3130
) -> dict:
3231
# extract payload from a EventBridge event
33-
detail: dict = extract_data_from_envelope(data=event, envelope=envelopes.EVENTBRIDGE)
32+
detail: dict = query(data=event, envelope=envelopes.EVENTBRIDGE)
3433

3534
# check if status_id exists in payload, otherwise add default state before processing payment
3635
if "status_id" not in detail:
@@ -44,7 +43,7 @@ def middleware_before(
4443
@middleware_before
4544
def lambda_handler(event: dict, context: LambdaContext) -> dict:
4645
try:
47-
payment_payload: dict = extract_data_from_envelope(data=event, envelope=envelopes.EVENTBRIDGE)
46+
payment_payload: dict = query(data=event, envelope=envelopes.EVENTBRIDGE)
4847
return {
4948
"order": Payment(**payment_payload).__dict__,
5049
"message": "payment created",

Diff for: examples/middleware_factory/src/getting_started_middleware_with_params_function.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from aws_lambda_powertools.middleware_factory import lambda_handler_decorator
77
from aws_lambda_powertools.utilities.jmespath_utils import (
88
envelopes,
9-
extract_data_from_envelope,
9+
query,
1010
)
1111
from aws_lambda_powertools.utilities.typing import LambdaContext
1212

@@ -23,8 +23,7 @@ class Booking:
2323
booking_id: str = field(default_factory=lambda: f"{uuid4()}")
2424

2525

26-
class BookingError(Exception):
27-
...
26+
class BookingError(Exception): ...
2827

2928

3029
@lambda_handler_decorator
@@ -35,7 +34,7 @@ def obfuscate_sensitive_data(
3534
fields: List,
3635
) -> dict:
3736
# extracting payload from a EventBridge event
38-
detail: dict = extract_data_from_envelope(data=event, envelope=envelopes.EVENTBRIDGE)
37+
detail: dict = query(data=event, envelope=envelopes.EVENTBRIDGE)
3938
guest_data: Any = detail.get("guest")
4039

4140
# Obfuscate fields (email, vat, passport) before calling Lambda handler
@@ -56,7 +55,7 @@ def obfuscate_data(value: str) -> bytes:
5655
@obfuscate_sensitive_data(fields=["email", "passport", "vat"])
5756
def lambda_handler(event: dict, context: LambdaContext) -> dict:
5857
try:
59-
booking_payload: dict = extract_data_from_envelope(data=event, envelope=envelopes.EVENTBRIDGE)
58+
booking_payload: dict = query(data=event, envelope=envelopes.EVENTBRIDGE)
6059
return {
6160
"book": Booking(**booking_payload).__dict__,
6261
"message": "booking created",

Diff for: tests/functional/idempotency/conftest.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from aws_lambda_powertools.utilities.idempotency import DynamoDBPersistenceLayer
1313
from aws_lambda_powertools.utilities.idempotency.idempotency import IdempotencyConfig
14-
from aws_lambda_powertools.utilities.jmespath_utils import extract_data_from_envelope
14+
from aws_lambda_powertools.utilities.jmespath_utils import query
1515
from aws_lambda_powertools.utilities.validation import envelopes
1616
from tests.functional.idempotency.utils import hash_idempotency_key
1717
from tests.functional.utils import json_serialize, load_event
@@ -195,7 +195,7 @@ def hashed_idempotency_key(request, lambda_apigw_event, default_jmespath, lambda
195195

196196
@pytest.fixture
197197
def hashed_idempotency_key_with_envelope(request, lambda_apigw_event):
198-
event = extract_data_from_envelope(
198+
event = query(
199199
data=lambda_apigw_event,
200200
envelope=envelopes.API_GATEWAY_HTTP,
201201
jmespath_options={},

0 commit comments

Comments
 (0)