|
1 |
| -from decimal import Clamped, Context, Decimal, Inexact, Overflow, Rounded, Underflow |
2 | 1 | from enum import Enum
|
3 |
| -from typing import Any, Callable, Dict, Iterator, Optional, Sequence, Set |
| 2 | +from typing import Any, Dict, Iterator, Optional |
4 | 3 |
|
| 4 | +from aws_lambda_powertools.shared.dynamodb_deserializer import TypeDeserializer |
5 | 5 | from aws_lambda_powertools.utilities.data_classes.common import DictWrapper
|
6 | 6 |
|
7 |
| -# NOTE: DynamoDB supports up to 38 digits precision |
8 |
| -# Therefore, this ensures our Decimal follows what's stored in the table |
9 |
| -DYNAMODB_CONTEXT = Context( |
10 |
| - Emin=-128, |
11 |
| - Emax=126, |
12 |
| - prec=38, |
13 |
| - traps=[Clamped, Overflow, Inexact, Rounded, Underflow], |
14 |
| -) |
15 |
| - |
16 |
| - |
17 |
| -class TypeDeserializer: |
18 |
| - """ |
19 |
| - Deserializes DynamoDB types to Python types. |
20 |
| -
|
21 |
| - It's based on boto3's [DynamoDB TypeDeserializer](https://boto3.amazonaws.com/v1/documentation/api/latest/_modules/boto3/dynamodb/types.html). |
22 |
| -
|
23 |
| - The only notable difference is that for Binary (`B`, `BS`) values we return Python Bytes directly, |
24 |
| - since we don't support Python 2. |
25 |
| - """ |
26 |
| - |
27 |
| - def deserialize(self, value: Dict) -> Any: |
28 |
| - """Deserialize DynamoDB data types into Python types. |
29 |
| -
|
30 |
| - Parameters |
31 |
| - ---------- |
32 |
| - value: Any |
33 |
| - DynamoDB value to be deserialized to a python type |
34 |
| -
|
35 |
| -
|
36 |
| - Here are the various conversions: |
37 |
| -
|
38 |
| - DynamoDB Python |
39 |
| - -------- ------ |
40 |
| - {'NULL': True} None |
41 |
| - {'BOOL': True/False} True/False |
42 |
| - {'N': Decimal(value)} Decimal(value) |
43 |
| - {'S': string} string |
44 |
| - {'B': bytes} bytes |
45 |
| - {'NS': [str(value)]} set([str(value)]) |
46 |
| - {'SS': [string]} set([string]) |
47 |
| - {'BS': [bytes]} set([bytes]) |
48 |
| - {'L': list} list |
49 |
| - {'M': dict} dict |
50 |
| -
|
51 |
| - Parameters |
52 |
| - ---------- |
53 |
| - value: Any |
54 |
| - DynamoDB value to be deserialized to a python type |
55 |
| -
|
56 |
| - Returns |
57 |
| - -------- |
58 |
| - any |
59 |
| - Python native type converted from DynamoDB type |
60 |
| - """ |
61 |
| - |
62 |
| - dynamodb_type = list(value.keys())[0] |
63 |
| - deserializer: Optional[Callable] = getattr(self, f"_deserialize_{dynamodb_type}".lower(), None) |
64 |
| - if deserializer is None: |
65 |
| - raise TypeError(f"Dynamodb type {dynamodb_type} is not supported") |
66 |
| - |
67 |
| - return deserializer(value[dynamodb_type]) |
68 |
| - |
69 |
| - def _deserialize_null(self, value: bool) -> None: |
70 |
| - return None |
71 |
| - |
72 |
| - def _deserialize_bool(self, value: bool) -> bool: |
73 |
| - return value |
74 |
| - |
75 |
| - def _deserialize_n(self, value: str) -> Decimal: |
76 |
| - return DYNAMODB_CONTEXT.create_decimal(value) |
77 |
| - |
78 |
| - def _deserialize_s(self, value: str) -> str: |
79 |
| - return value |
80 |
| - |
81 |
| - def _deserialize_b(self, value: bytes) -> bytes: |
82 |
| - return value |
83 |
| - |
84 |
| - def _deserialize_ns(self, value: Sequence[str]) -> Set[Decimal]: |
85 |
| - return set(map(self._deserialize_n, value)) |
86 |
| - |
87 |
| - def _deserialize_ss(self, value: Sequence[str]) -> Set[str]: |
88 |
| - return set(map(self._deserialize_s, value)) |
89 |
| - |
90 |
| - def _deserialize_bs(self, value: Sequence[bytes]) -> Set[bytes]: |
91 |
| - return set(map(self._deserialize_b, value)) |
92 |
| - |
93 |
| - def _deserialize_l(self, value: Sequence[Dict]) -> Sequence[Any]: |
94 |
| - return [self.deserialize(v) for v in value] |
95 |
| - |
96 |
| - def _deserialize_m(self, value: Dict) -> Dict: |
97 |
| - return {k: self.deserialize(v) for k, v in value.items()} |
98 |
| - |
99 | 7 |
|
100 | 8 | class StreamViewType(Enum):
|
101 | 9 | """The type of data from the modified DynamoDB item that was captured in this stream record"""
|
|
0 commit comments