Skip to content

chore: ease maintenance of upcoming parser #118 #189

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Oct 14, 2020
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8539002
fix: comment out validators #118
heitorlessa Oct 4, 2020
df854d3
improv: rename advanced_parser to parser
heitorlessa Oct 4, 2020
1e4a49c
chore: remove test for commented code
heitorlessa Oct 4, 2020
991bec7
improv: envelope structure & import
heitorlessa Oct 4, 2020
c7f242a
fix: snake_case
heitorlessa Oct 4, 2020
64f3261
improv: raise own exception; remove duplicates
heitorlessa Oct 5, 2020
ad00cb0
fix: unnecessary return; better error handling
heitorlessa Oct 9, 2020
292c045
improv: test parser
heitorlessa Oct 9, 2020
f0ff926
improv: simplify base envelope; increase test cov
heitorlessa Oct 10, 2020
b868e1f
fix: code inspect issues
heitorlessa Oct 10, 2020
7840d6b
chore: kwarg over arg to ease refactoring
heitorlessa Oct 10, 2020
89929b3
feat: add standalone parse function
heitorlessa Oct 10, 2020
002cc54
chore: lint
heitorlessa Oct 10, 2020
89122ac
improv: propagate exception to parser
heitorlessa Oct 11, 2020
f21b3ca
improv: add docstrings; event internal param renamed
heitorlessa Oct 11, 2020
974a98c
improv: adjust high level imports
heitorlessa Oct 12, 2020
b1a4821
improv: expose all pydantic imports
heitorlessa Oct 12, 2020
0189db0
chore: explicit DynamoDB Stream schema naming
heitorlessa Oct 12, 2020
22a9a84
chore: remove flake8 polyfill as explicit dep
heitorlessa Oct 12, 2020
bcb763b
Update aws_lambda_powertools/utilities/parser/pydantic.py
heitorlessa Oct 13, 2020
404530f
improv: rename to event_parser as per Tom's review
heitorlessa Oct 14, 2020
7480985
improv: rename schema to model as per Tom's review
heitorlessa Oct 14, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions aws_lambda_powertools/utilities/advanced_parser/__init__.py

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

68 changes: 0 additions & 68 deletions aws_lambda_powertools/utilities/advanced_parser/parser.py

This file was deleted.

This file was deleted.

9 changes: 9 additions & 0 deletions aws_lambda_powertools/utilities/parser/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"""Advanced parser utility
"""
from . import envelopes
from .envelopes import BaseEnvelope
from .exceptions import SchemaValidationError
from .parser import parser
from .pydantic import BaseModel, root_validator, validator

__all__ = ["parser", "envelopes", "BaseEnvelope", "BaseModel", "validator", "root_validator", "SchemaValidationError"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from .base import BaseEnvelope
from .dynamodb import DynamoDBEnvelope
from .event_bridge import EventBridgeEnvelope
from .sqs import SqsEnvelope

__all__ = ["DynamoDBEnvelope", "EventBridgeEnvelope", "SqsEnvelope", "BaseEnvelope"]
58 changes: 58 additions & 0 deletions aws_lambda_powertools/utilities/parser/envelopes/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import logging
from abc import ABC, abstractmethod
from typing import Any, Dict, Union

from pydantic import BaseModel

logger = logging.getLogger(__name__)


class BaseEnvelope(ABC):
"""ABC implementation for creating a supported Envelope"""

@staticmethod
def _parse(data: Union[Dict[str, Any], str], schema: BaseModel) -> Any:
"""Parses envelope data against schema provided

Parameters
----------
data : Dict
Data to be parsed and validated
schema
Schema to parse and validate data against

Returns
-------
Any
Parsed data
"""
if data is None:
logger.debug("Skipping parsing as event is None")
return data

logger.debug("parsing event against schema")
if isinstance(data, str):
logger.debug("parsing event as string")
return schema.parse_raw(data)

return schema.parse_obj(data)

@abstractmethod
def parse(self, data: Dict[str, Any], schema: BaseModel):
"""Implementation to parse data against envelope schema, then against the schema

NOTE: Call `_parse` method to fully parse data with schema provided.

Example
-------

**EventBridge envelope implementation example**

def parse(...):
# 1. parses data against envelope schema
parsed_envelope = EventBridgeSchema(**data)

# 2. parses portion of data within the envelope against schema
return self._parse(data=parsed_envelope.detail, schema=schema)
"""
return NotImplemented # pragma: no cover
45 changes: 45 additions & 0 deletions aws_lambda_powertools/utilities/parser/envelopes/dynamodb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import logging
from typing import Any, Dict, List

from pydantic import BaseModel
from typing_extensions import Literal

from ..schemas import DynamoDBStreamSchema
from .base import BaseEnvelope

logger = logging.getLogger(__name__)


class DynamoDBEnvelope(BaseEnvelope):
""" DynamoDB Stream Envelope to extract data within NewImage/OldImage

Note: Values are the parsed schema models. Images' values can also be None, and
length of the list is the record's amount in the original event.
"""

def parse(self, data: Dict[str, Any], schema: BaseModel) -> List[Dict[Literal["NewImage", "OldImage"], BaseModel]]:
"""Parses DynamoDB Stream records found in either NewImage and OldImage with schema provided

Parameters
----------
data : Dict
Lambda event to be parsed
schema : BaseModel
User schema provided to parse after extracting data using envelope

Returns
-------
List
List of records parsed with schema provided
"""
parsed_envelope = DynamoDBStreamSchema(**data)
output = []
for record in parsed_envelope.Records:
output.append(
{
"NewImage": self._parse(record.dynamodb.NewImage, schema),
"OldImage": self._parse(record.dynamodb.OldImage, schema),
}
)
# noinspection PyTypeChecker
return output
Loading