From 89f4cae5b30cf5f54cc11f15d7696c7976188ac5 Mon Sep 17 00:00:00 2001 From: JamesAbel Date: Sat, 15 Nov 2025 17:56:30 -0800 Subject: [PATCH] allow Enum to be used as a dict key --- README.md | 3 +++ awsimple/__version__.py | 2 +- awsimple/dynamodb.py | 2 ++ test_awsimple/test_dynamodb.py | 16 ++++++++++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 059c800..42a4e75 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,9 @@ Full documentation available on [Read the Docs](https://awsimple.readthedocs.io/ - DynamoDB full table scans (with local cache option that only rescans if the table has changed). +- Convert back and forth between DynamoDB items and Python dictionaries automatically. Converts many common data types to DynamoDB compatible types, +including nested structures, sets, images (PIL), and Enum/StrEnum. + - True file hashing (SHA512) for S3 files (S3's etag is not a true file hash). - Supports moto mock and localstack. Handy for testing and CI. diff --git a/awsimple/__version__.py b/awsimple/__version__.py index 72a39a6..d4f8f07 100644 --- a/awsimple/__version__.py +++ b/awsimple/__version__.py @@ -1,7 +1,7 @@ __application_name__ = "awsimple" __title__ = __application_name__ __author__ = "abel" -__version__ = "7.0.0" +__version__ = "7.1.0" __author_email__ = "j@abel.co" __url__ = "https://github.com/jamesabel/awsimple" __download_url__ = "https://github.com/jamesabel/awsimple" diff --git a/awsimple/dynamodb.py b/awsimple/dynamodb.py index fb8e166..8c4ba46 100644 --- a/awsimple/dynamodb.py +++ b/awsimple/dynamodb.py @@ -154,6 +154,8 @@ def dict_to_dynamodb(input_value: Any, convert_images: bool = True, raise_except for k, v in input_value.items(): if type(k) is int: k = str(k) # allow int as key since it is unambiguous (e.g. bool and float are ambiguous) + elif isinstance(k, Enum): + k = dict_to_dynamodb(k, False, raise_exception) # convert Enum, including StrEnum, etc. as keys resp[k] = dict_to_dynamodb(v, convert_images, raise_exception) elif type(input_value) is list or type(input_value) is tuple: # converts tuple to list diff --git a/test_awsimple/test_dynamodb.py b/test_awsimple/test_dynamodb.py index 44af3af..a1a3cca 100644 --- a/test_awsimple/test_dynamodb.py +++ b/test_awsimple/test_dynamodb.py @@ -8,6 +8,7 @@ import pickle from pathlib import Path import time +from enum import Enum, StrEnum, auto from PIL import Image from ismain import is_main @@ -31,6 +32,17 @@ dd = defaultdict(int) dd[1] = 2 + +class TestEnum(Enum): + A = 1 + B = 2 + + +class TestStrEnum(StrEnum): + X = auto() + Y = auto() + + sample_input = { id_str: dict_id, "sample1": "Test Data", @@ -53,6 +65,8 @@ "test_date_time": datetime.datetime.fromtimestamp(1559679535, tz=timezone.utc), # 2019-06-04T20:18:55+00:00 "zero_len_string": "", "dictim": dictim({"HI": dictim({"there": 1})}), # nested + TestEnum.A: "i am A", # Enum key + TestStrEnum.Y: "why", # StrEnum key } @@ -90,6 +104,8 @@ def test_dynamodb(): assert dynamodb_dict["42"] == "my_key_is_an_int" # test conversion of an int key to a string assert dynamodb_dict["test_date_time"] == "2019-06-04T20:18:55+00:00" assert dynamodb_dict["zero_len_string"] is None + assert dynamodb_dict["A"] == "i am A" # Enum key (conversion uses the Enum name) + assert dynamodb_dict["Y"] == "why" # StrEnum key # while dictim is case-insensitive, when we convert to dict for DynamoDB it becomes case-sensitive assert list(dynamodb_dict["dictim"]["HI"])[0] == "there"