Skip to content

Commit e8fa3b2

Browse files
committed
feat: Add __str__ to Data Classes base DictWrapper
Add in a __str__ method to the base class used by all Data Classes. This provides a dictionary string primarily for debugging purposes. To construct the dictionary a helper method _str_helper recursively works through `properties` in each instance of a Data Class. Some Data Classes have sensitive properties, such as credentials, which can be excluded by setting the `_sensitive_properties` attribute (list of strings). These properties will have their value replaced with "[SENSITIVE]", which allows a developer to see a value arrived, but was hidden as it is sensitive.
1 parent 3e313bb commit e8fa3b2

File tree

1 file changed

+42
-1
lines changed
  • aws_lambda_powertools/utilities/data_classes

1 file changed

+42
-1
lines changed

aws_lambda_powertools/utilities/data_classes/common.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import base64
22
import json
33
from collections.abc import Mapping
4-
from typing import Any, Dict, Iterator, Optional
4+
from typing import Any, Dict, Iterator, List, Optional
55

66
from aws_lambda_powertools.shared.headers_serializer import BaseHeadersSerializer
77

@@ -28,6 +28,47 @@ def __iter__(self) -> Iterator:
2828
def __len__(self) -> int:
2929
return len(self._data)
3030

31+
def __str__(self) -> str:
32+
return str(self._str_helper())
33+
34+
def _str_helper(self) -> Dict[str, Any]:
35+
"""
36+
Recursively get a Dictionary of DictWrapper properties primarily
37+
for use by __str__ for debugging purposes.
38+
39+
Will remove "raw_event" properties, and any defined by the Data Class
40+
`_sensitive_properties` list field.
41+
This should be used in case where secrets, such as access keys, are
42+
stored in the Data Class but should not be logged out.
43+
"""
44+
properties = self._properties()
45+
sensitive_properties = ["raw_event"]
46+
if hasattr(self, "_sensitive_properties"):
47+
sensitive_properties.extend(self._sensitive_properties) # pyright: ignore
48+
49+
result: Dict[str, Any] = {}
50+
for property_key in properties:
51+
if property_key in sensitive_properties:
52+
result[property_key] = "[SENSITIVE]"
53+
else:
54+
try:
55+
property_value = getattr(self, property_key)
56+
result[property_key] = property_value
57+
58+
if issubclass(property_value.__class__, DictWrapper):
59+
result[property_key] = property_value._str_helper()
60+
elif isinstance(property_value, list):
61+
for seq, item in enumerate(property_value):
62+
if issubclass(item.__class__, DictWrapper):
63+
result[property_key][seq] = item._str_helper()
64+
except Exception as e:
65+
result[property_key] = f"[EXCEPTION {type(e)}]"
66+
67+
return result
68+
69+
def _properties(self) -> List[str]:
70+
return [p for p in dir(self.__class__) if isinstance(getattr(self.__class__, p), property)]
71+
3172
def get(self, key: str, default: Optional[Any] = None) -> Optional[Any]:
3273
return self._data.get(key, default)
3374

0 commit comments

Comments
 (0)