Skip to content

Commit

Permalink
fix(docs): Extract jmespath code examples
Browse files Browse the repository at this point in the history
Changes:
- Extract code examples
- Run isort, black
- Fix python syntax errors
- Fix line highlights
- Add make task

Related to:
- aws-powertools#1064
  • Loading branch information
michaelbrewer committed Apr 13, 2022
1 parent b577366 commit 82f8de2
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 103 deletions.
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,13 @@ changelog:

mypy:
poetry run mypy --pretty aws_lambda_powertools

format-examples:
poetry run isort docs/shared
poetry run black docs/shared/*.py
poetry run isort docs/examples
poetry run black docs/examples/*/*/*.py

lint-examples:
poetry run python3 -m py_compile docs/shared/*.py
poetry run python3 -m py_compile docs/examples/*/*/*.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from jmespath.functions import signature

from aws_lambda_powertools.utilities.jmespath_utils import PowertoolsFunctions, extract_data_from_envelope


class CustomFunctions(PowertoolsFunctions):
@signature({"types": ["string"]}) # Only decode if value is a string
def _func_special_decoder(self, s):
return my_custom_decoder_logic(s)


custom_jmespath_options = {"custom_functions": CustomFunctions()}


def handler(event, context):
# use the custom name after `_func_`
extract_data_from_envelope(
data=event,
envelope="special_decoder(body)",
jmespath_options=custom_jmespath_options,
)
...
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from aws_lambda_powertools.utilities.jmespath_utils import envelopes, extract_data_from_envelope
from aws_lambda_powertools.utilities.typing import LambdaContext


def handler(event: dict, context: LambdaContext):
payload = extract_data_from_envelope(data=event, envelope=envelopes.SNS)
customer = payload.get("customerId") # now deserialized
...
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from aws_lambda_powertools.utilities.jmespath_utils import extract_data_from_envelope
from aws_lambda_powertools.utilities.typing import LambdaContext


def handler(event: dict, context: LambdaContext):
payload = extract_data_from_envelope(data=event, envelope="powertools_json(body)")
customer = payload.get("customerId") # now deserialized
...
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import schemas

from aws_lambda_powertools.utilities.validation import validate

sample_event = {
"data": "H4sIACZAXl8C/52PzUrEMBhFX2UILpX8tPbHXWHqIOiq3Q1F0ubrWEiakqTWofTdTYYB0YWL2d5zvnuTFellBIOedoiyKH5M0iwnlKH7HZL6dDB6ngLDfLFYctUKjie9gHFaS/sAX1xNEq525QxwFXRGGMEkx4Th491rUZdV3YiIZ6Ljfd+lfSyAtZloacQgAkqSJCGhxM6t7cwwuUGPz4N0YKyvO6I9WDeMPMSo8Z4Ca/kJ6vMEYW5f1MX7W1lVxaG8vqX8hNFdjlc0iCBBSF4ERT/3Pl7RbMGMXF2KZMh/C+gDpNS7RRsp0OaRGzx0/t8e0jgmcczyLCWEePhni/23JWalzjdu0a3ZvgEaNLXeugEAAA=="
}

validate(
event=sample_event,
schema=schemas.INPUT,
envelope="powertools_base64_gzip(data) | powertools_json(@)",
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import schemas

from aws_lambda_powertools.utilities.validation import validate

sample_event = {
"data": "eyJtZXNzYWdlIjogImhlbGxvIGhlbGxvIiwgInVzZXJuYW1lIjogImJsYWggYmxhaCJ9=",
}

validate(
event=sample_event,
schema=schemas.INPUT,
envelope="powertools_json(powertools_base64(data))",
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import schemas

from aws_lambda_powertools.utilities.validation import validate

sample_event = {
"data": '{"payload": {"message": "hello hello", "username": "blah blah"}}',
}

validate(event=sample_event, schema=schemas.INPUT, envelope="powertools_json(data)")
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import json

from aws_lambda_powertools.utilities.idempotency import DynamoDBPersistenceLayer, IdempotencyConfig, idempotent

persistence_layer = DynamoDBPersistenceLayer(table_name="IdempotencyTable")
config = IdempotencyConfig(event_key_jmespath="powertools_json(body)")


@idempotent(config=config, persistence_store=persistence_layer)
def handler(event: dict, context):
body = json.loads(event["body"])
payment = create_subscription_payment(
user=body["user"],
product=body["product_id"],
)
...
return {
"payment_id": payment.id,
"message": "success",
"statusCode": 200,
}
12 changes: 10 additions & 2 deletions docs/shared/validation_basic_jsonschema.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,15 @@
"examples": [{"statusCode": 200, "body": "response"}],
"required": ["statusCode", "body"],
"properties": {
"statusCode": {"$id": "#/properties/statusCode", "type": "integer", "title": "The statusCode"},
"body": {"$id": "#/properties/body", "type": "string", "title": "The response"},
"statusCode": {
"$id": "#/properties/statusCode",
"type": "integer",
"title": "The statusCode",
},
"body": {
"$id": "#/properties/body",
"type": "string",
"title": "The response",
},
},
}
118 changes: 17 additions & 101 deletions docs/utilities/jmespath_functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,8 @@ You can use the `extract_data_from_envelope` function along with any [JMESPath e

=== "app.py"

```python hl_lines="1 7"
from aws_lambda_powertools.utilities.jmespath_utils import extract_data_from_envelope

from aws_lambda_powertools.utilities.typing import LambdaContext


def handler(event: dict, context: LambdaContext):
payload = extract_data_from_envelope(data=event, envelope="powertools_json(body)")
customer = payload.get("customerId") # now deserialized
...
```python hl_lines="1 6"
--8<-- "docs/examples/utilities/jmespath_functions/extract_data_jmespath.py"
```

=== "event.json"
Expand All @@ -54,16 +46,8 @@ We provide built-in envelopes for popular JMESPath expressions used when looking

=== "app.py"

```python hl_lines="1 7"
from aws_lambda_powertools.utilities.jmespath_utils import extract_data_from_envelope, envelopes

from aws_lambda_powertools.utilities.typing import LambdaContext


def handler(event: dict, context: LambdaContext):
payload = extract_data_from_envelope(data=event, envelope=envelopes.SNS)
customer = payload.get("customerId") # now deserialized
...
```python hl_lines="1 6"
--8<-- "docs/examples/utilities/jmespath_functions/extract_data_built_in_jmespath.py"
```

=== "event.json"
Expand Down Expand Up @@ -107,6 +91,7 @@ Envelope | JMESPath expression
## Advanced

### Built-in JMESPath functions

You can use our built-in JMESPath functions within your expressions to do exactly that to decode JSON Strings, base64, and uncompress gzip data.

???+ info
Expand All @@ -123,49 +108,21 @@ This sample will decode the value within the `data` key into a valid JSON before
=== "powertools_json_jmespath_function.py"

```python hl_lines="9"
from aws_lambda_powertools.utilities.validation import validate

import schemas

sample_event = {
'data': '{"payload": {"message": "hello hello", "username": "blah blah"}}'
}

validate(event=sample_event, schema=schemas.INPUT, envelope="powertools_json(data)")
--8<-- "docs/examples/utilities/jmespath_functions/powertools_json_jmespath_function.py"
```

=== "schemas.py"

```python hl_lines="7 14 16 23 39 45 47 52"
```python hl_lines="8 10 17 34 36 41"
--8<-- "docs/shared/validation_basic_jsonschema.py"
```

> **Idempotency scenario**
This sample will decode the value within the `body` key of an API Gateway event into a valid JSON object to ensure the Idempotency utility processes a JSON object instead of a string.

```python hl_lines="7" title="Deserializing JSON before using as idempotency key"
import json
from aws_lambda_powertools.utilities.idempotency import (
IdempotencyConfig, DynamoDBPersistenceLayer, idempotent
)

persistence_layer = DynamoDBPersistenceLayer(table_name="IdempotencyTable")
config = IdempotencyConfig(event_key_jmespath="powertools_json(body)")

@idempotent(config=config, persistence_store=persistence_layer)
def handler(event:APIGatewayProxyEvent, context):
body = json.loads(event['body'])
payment = create_subscription_payment(
user=body['user'],
product=body['product_id']
)
...
return {
"payment_id": payment.id,
"message": "success",
"statusCode": 200
}
```python hl_lines="6" title="Deserializing JSON before using as idempotency key"
--8<-- "docs/examples/utilities/jmespath_functions/powertools_json_jmespath_function_idempotency.py"
```

#### powertools_base64 function
Expand All @@ -174,27 +131,15 @@ Use `powertools_base64` function to decode any base64 data.

This sample will decode the base64 value within the `data` key, and decode the JSON string into a valid JSON before we can validate it.

=== "powertools_json_jmespath_function.py"
=== "powertools_base64_jmespath_function.py"

```python hl_lines="12"
from aws_lambda_powertools.utilities.validation import validate

import schemas

sample_event = {
"data": "eyJtZXNzYWdlIjogImhlbGxvIGhlbGxvIiwgInVzZXJuYW1lIjogImJsYWggYmxhaCJ9="
}

validate(
event=sample_event,
schema=schemas.INPUT,
envelope="powertools_json(powertools_base64(data))"
)
--8<-- "docs/examples/utilities/jmespath_functions/powertools_base64_jmespath_function.py"
```

=== "schemas.py"

```python hl_lines="7 14 16 23 39 45 47 52"
```python hl_lines="8 10 17 34 36 41"
--8<-- "docs/shared/validation_basic_jsonschema.py"
```

Expand All @@ -204,27 +149,15 @@ Use `powertools_base64_gzip` function to decompress and decode base64 data.

This sample will decompress and decode base64 data, then use JMESPath pipeline expression to pass the result for decoding its JSON string.

=== "powertools_json_jmespath_function.py"
=== "powertools_base64_gzip_jmespath_function.py"

```python hl_lines="12"
from aws_lambda_powertools.utilities.validation import validate

import schemas

sample_event = {
"data": "H4sIACZAXl8C/52PzUrEMBhFX2UILpX8tPbHXWHqIOiq3Q1F0ubrWEiakqTWofTdTYYB0YWL2d5zvnuTFellBIOedoiyKH5M0iwnlKH7HZL6dDB6ngLDfLFYctUKjie9gHFaS/sAX1xNEq525QxwFXRGGMEkx4Th491rUZdV3YiIZ6Ljfd+lfSyAtZloacQgAkqSJCGhxM6t7cwwuUGPz4N0YKyvO6I9WDeMPMSo8Z4Ca/kJ6vMEYW5f1MX7W1lVxaG8vqX8hNFdjlc0iCBBSF4ERT/3Pl7RbMGMXF2KZMh/C+gDpNS7RRsp0OaRGzx0/t8e0jgmcczyLCWEePhni/23JWalzjdu0a3ZvgEaNLXeugEAAA=="
}

validate(
event=sample_event,
schema=schemas.INPUT,
envelope="powertools_base64_gzip(data) | powertools_json(@)"
)
--8<-- "docs/examples/utilities/jmespath_functions/powertools_base64_gzip_jmespath_function.py"
```

=== "schemas.py"

```python hl_lines="7 14 16 23 39 45 47 52"
```python hl_lines="8 10 17 34 36 41"
--8<-- "docs/shared/validation_basic_jsonschema.py"
```

Expand All @@ -239,25 +172,8 @@ In order to keep the built-in functions from Powertools, you can subclass from `

=== "custom_jmespath_function.py"

```python hl_lines="2-3 6-9 11 17"
from aws_lambda_powertools.utilities.jmespath_utils import (
PowertoolsFunctions, extract_data_from_envelope)
from jmespath.functions import signature


class CustomFunctions(PowertoolsFunctions):
@signature({'types': ['string']}) # Only decode if value is a string
def _func_special_decoder(self, s):
return my_custom_decoder_logic(s)

custom_jmespath_options = {"custom_functions": CustomFunctions()}

def handler(event, context):
# use the custom name after `_func_`
extract_data_from_envelope(data=event,
envelope="special_decoder(body)",
jmespath_options=**custom_jmespath_options)
...
```python hl_lines="1 3 6-9 12 20"
--8<-- "docs/examples/utilities/jmespath_functions/custom_jmespath_function.py"
```

=== "event.json"
Expand Down

0 comments on commit 82f8de2

Please sign in to comment.