Skip to content

Commit 256c64b

Browse files
author
Lucas McDonald
committed
m
1 parent c2d54bb commit 256c64b

File tree

4 files changed

+130
-24
lines changed

4 files changed

+130
-24
lines changed

DynamoDbEncryption/runtimes/python/src/aws_database_encryption_sdk/internal/boto3_conversions.py

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
from abc import ABC, abstractmethod
2-
from boto3.dynamodb.conditions import (
3-
BuiltConditionExpression,
4-
)
5-
from copy import deepcopy
62

73
class BotoInterfaceShapeConverter(ABC):
84
"""
@@ -12,22 +8,19 @@ class BotoInterfaceShapeConverter(ABC):
128
boto3 resource methods accept different input shapes than boto3 clients, and return different output shapes.
139
(The members of these shapes are the same, but some shapes are formatted differently.)
1410
15-
DBESDK DynamoDB has an internal transformer layer that performs encryption, decryption, and query modification.
11+
DBESDK DynamoDB has an internal transformer layer that modifies requests and responses.
1612
This transformer layer only accepts client-formatted shapes.
1713
1814
This class exists to transform from/to resource shapes to/from client shapes
1915
for the internal DBESDK DynamoDB transformer layer.
16+
This class is also used to transform shapes if the EncryptedClient has expect_standard_dictionaries set to True.
2017
2118
This class is abstract, as some specific transformations depend on the transformation direction.
22-
But the structure modelling is the same for both directions, and is expressed here.
23-
Implementations of this class should implement the abstract methods to perform the transformations.
19+
(ex. Item, Key, AttributeValue, etc.)
20+
But many transformations are the same in both directions.
21+
That similarity is captured here, and implementations override the abstract methods to perform the transformations
22+
specific to the transformation direction.
2423
"""
25-
# def key_condition_expression(self, key_condition_expression, expression_attribute_names, expression_attribute_values):
26-
# return self.expression(key_condition_expression, expression_attribute_names, expression_attribute_values)
27-
28-
# def filter_expression(self, filter_expression, expression_attribute_names, expression_attribute_values):
29-
# return self.expression(filter_expression, expression_attribute_names, expression_attribute_values)
30-
3124
@abstractmethod
3225
def expression(self, condition_expression, expression_attribute_names, expression_attribute_values):
3326
raise NotImplementedError("Must be implemented by subclasses")
@@ -99,7 +92,6 @@ def attributes(self, attributes):
9992
return self.item(attributes)
10093

10194
def item_collection_metrics(self, item_collection_metrics):
102-
print(f"{item_collection_metrics=}")
10395
if "ItemCollectionKey" in item_collection_metrics:
10496
item_collection_metrics["ItemCollectionKey"] = self.item(item_collection_metrics["ItemCollectionKey"])
10597
return item_collection_metrics
@@ -283,6 +275,9 @@ def transact_write_items(self, transact_items):
283275
return output_transact_items
284276

285277
def transact_write_items_response(self, transact_write_items_response):
278+
if "ItemCollectionMetrics" in transact_write_items_response:
279+
# TODO this works but rename/refactor
280+
transact_write_items_response["ItemCollectionMetrics"] = self.batch_write_item_item_collection_metrics(transact_write_items_response["ItemCollectionMetrics"])
286281
return transact_write_items_response
287282

288283
def transact_get_items_request(self, transact_get_items_request):
@@ -302,13 +297,5 @@ def transact_get_items(self, transact_items):
302297

303298
def transact_get_items_response(self, transact_get_items_response):
304299
if "Responses" in transact_get_items_response:
305-
transact_get_items_response["Responses"] = self.transact_get_items_responses(transact_get_items_response["Responses"])
300+
transact_get_items_response["Responses"] = self.items(transact_get_items_response["Responses"])
306301
return transact_get_items_response
307-
308-
def transact_get_items_responses(self, responses):
309-
responses_out = []
310-
for response in responses:
311-
if "Item" in response:
312-
response["Item"] = self.item(response["Item"])
313-
responses_out.append(response)
314-
return responses_out

DynamoDbEncryption/runtimes/python/test/ddb_formatted_requests.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,12 @@ def basic_transact_get_item_request_ddb(keys):
220220
"TransactItems": [{"Get": {"TableName": INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME, "Key": key}} for key in keys]
221221
}
222222

223+
def basic_transact_write_item_condition_check_request_ddb(keys):
224+
"""Get a transact_write_item request in resource (ddb) format for any items."""
225+
return {
226+
"TransactItems": [{"ConditionCheck": {"TableName": INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME, "Key": key}} for key in keys]
227+
}
228+
223229
def basic_query_paginator_request_ddb(key):
224230
"""Get a query paginator request in resource (ddb) format for any item."""
225231
return {
@@ -230,3 +236,10 @@ def basic_query_paginator_request_ddb(key):
230236
":sk": key["sort_key"]
231237
}
232238
}
239+
240+
def basic_transact_get_item_request_ddb(keys):
241+
"""Get a transact_get_item request in resource (ddb) format for any keys."""
242+
return {
243+
"TransactItems": [{"Get": {"TableName": INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME, "Key": key}} for key in keys]
244+
}
245+

DynamoDbEncryption/runtimes/python/test/dict_formatted_requests.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,14 @@ def basic_transact_write_item_delete_request_dict(keys):
217217
]
218218
return basic_transact_write_item_request_dict(actions_with_keys)
219219

220+
def basic_transact_write_item_condition_check_request_dict(keys):
221+
"""Get a transact_write_item condition check request in resource (dict) format for any keys."""
222+
actions_with_keys = [
223+
{"ConditionCheck": {"TableName": INTEG_TEST_DEFAULT_DYNAMODB_TABLE_NAME, "Key": key}}
224+
for key in keys
225+
]
226+
return basic_transact_write_item_request_dict(actions_with_keys)
227+
220228
def basic_transact_get_item_request_dict(keys):
221229
"""Get a transact_get_item request in resource (dict) format for any keys."""
222230
return {

DynamoDbEncryption/runtimes/python/test/unit/internal/test_client_to_resource.py

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
basic_batch_get_item_request_ddb,
1111
basic_batch_write_item_put_request_ddb,
1212
basic_batch_write_item_delete_request_ddb,
13+
basic_transact_write_item_put_request_ddb,
14+
basic_transact_write_item_delete_request_ddb,
15+
basic_transact_write_item_condition_check_request_ddb,
16+
basic_transact_get_item_request_ddb,
1317
)
1418
from ...dict_formatted_requests import (
1519
basic_put_item_request_dict,
@@ -23,6 +27,10 @@
2327
basic_batch_get_item_request_dict,
2428
basic_batch_write_item_put_request_dict,
2529
basic_batch_write_item_delete_request_dict,
30+
basic_transact_write_item_put_request_dict,
31+
basic_transact_write_item_delete_request_dict,
32+
basic_transact_write_item_condition_check_request_dict,
33+
basic_transact_get_item_request_dict,
2634
)
2735
from ...responses import (
2836
basic_query_response,
@@ -37,6 +45,8 @@
3745
exhaustive_batch_get_item_response,
3846
basic_batch_write_item_put_response,
3947
exhaustive_batch_write_item_put_response,
48+
basic_transact_write_items_response,
49+
basic_transact_get_items_response,
4050
)
4151
from ...items import *
4252
from aws_database_encryption_sdk.internal.client_to_resource import ClientShapeToResourceShapeConverter
@@ -328,4 +338,92 @@ def test_GIVEN_test_batch_write_item_put_response_WHEN_client_to_resource_THEN_r
328338
# When: Converting to resource format
329339
dict_item = client_to_resource_converter.batch_write_item_response(response)
330340
# Then: Returns dict value
331-
assert dict_item == test_batch_write_item_put_response([test_dict_item])
341+
assert dict_item == test_batch_write_item_put_response([test_dict_item])
342+
343+
@pytest.fixture
344+
def test_transact_write_items_put_request_ddb():
345+
return basic_transact_write_item_put_request_ddb
346+
347+
@pytest.fixture
348+
def test_transact_write_items_put_request_dict():
349+
return basic_transact_write_item_put_request_dict
350+
351+
def test_GIVEN_test_transact_write_items_put_request_WHEN_client_to_resource_THEN_returns_dict_value(test_transact_write_items_put_request_ddb, test_transact_write_items_put_request_dict, test_ddb_item, test_dict_item):
352+
# Given: Transact write item put request
353+
request = test_transact_write_items_put_request_ddb([test_ddb_item])
354+
# When: Converting to resource format
355+
dict_item = client_to_resource_converter.transact_write_items_request(request)
356+
# Then: Returns dict value
357+
assert dict_item == test_transact_write_items_put_request_dict([test_dict_item])
358+
359+
@pytest.fixture
360+
def test_transact_write_items_delete_request_ddb():
361+
return basic_transact_write_item_delete_request_ddb
362+
363+
@pytest.fixture
364+
def test_transact_write_items_delete_request_dict():
365+
return basic_transact_write_item_delete_request_dict
366+
367+
def test_GIVEN_test_transact_write_items_delete_request_WHEN_client_to_resource_THEN_returns_dict_value(test_transact_write_items_delete_request_ddb, test_transact_write_items_delete_request_dict, test_ddb_key, test_dict_key):
368+
# Given: Transact write item delete request
369+
request = test_transact_write_items_delete_request_ddb([test_ddb_key])
370+
# When: Converting to resource format
371+
dict_item = client_to_resource_converter.transact_write_items_request(request)
372+
# Then: Returns dict value
373+
assert dict_item == test_transact_write_items_delete_request_dict([test_dict_key])
374+
375+
@pytest.fixture
376+
def test_transact_write_items_condition_check_request_ddb():
377+
return basic_transact_write_item_condition_check_request_ddb
378+
379+
@pytest.fixture
380+
def test_transact_write_items_condition_check_request_dict():
381+
return basic_transact_write_item_condition_check_request_dict
382+
383+
def test_GIVEN_test_transact_write_items_condition_check_request_WHEN_client_to_resource_THEN_returns_dict_value(test_transact_write_items_condition_check_request_ddb, test_transact_write_items_condition_check_request_dict, test_ddb_key, test_dict_key):
384+
# Given: Transact write item condition check request
385+
request = test_transact_write_items_condition_check_request_ddb([test_ddb_key])
386+
# When: Converting to resource format
387+
dict_item = client_to_resource_converter.transact_write_items_request(request)
388+
# Then: Returns dict value
389+
assert dict_item == test_transact_write_items_condition_check_request_dict([test_dict_key])
390+
391+
@pytest.fixture
392+
def test_transact_write_items_response():
393+
return basic_transact_write_items_response
394+
395+
def test_GIVEN_test_transact_write_items_response_WHEN_client_to_resource_THEN_returns_dict_value(test_transact_write_items_response, test_ddb_item, test_dict_item):
396+
# Given: Transact write items response
397+
response = test_transact_write_items_response([test_ddb_item])
398+
# When: Converting to resource format
399+
dict_item = client_to_resource_converter.transact_write_items_response(response)
400+
# Then: Returns dict value
401+
assert dict_item == test_transact_write_items_response([test_dict_item])
402+
403+
@pytest.fixture
404+
def test_transact_get_items_request_ddb():
405+
return basic_transact_get_item_request_ddb
406+
407+
@pytest.fixture
408+
def test_transact_get_items_request_dict():
409+
return basic_transact_get_item_request_dict
410+
411+
def test_GIVEN_test_transact_get_items_request_WHEN_client_to_resource_THEN_returns_dict_value(test_transact_get_items_request_ddb, test_transact_get_items_request_dict, test_ddb_key, test_dict_key):
412+
# Given: Transact get items request
413+
request = test_transact_get_items_request_ddb([test_ddb_key])
414+
# When: Converting to resource format
415+
dict_item = client_to_resource_converter.transact_get_items_request(request)
416+
# Then: Returns dict value
417+
assert dict_item == test_transact_get_items_request_dict([test_dict_key])
418+
419+
@pytest.fixture
420+
def test_transact_get_items_response():
421+
return basic_transact_get_items_response
422+
423+
def test_GIVEN_test_transact_get_items_response_WHEN_client_to_resource_THEN_returns_dict_value(test_transact_get_items_response, test_ddb_item, test_dict_item):
424+
# Given: Transact get items response
425+
response = test_transact_get_items_response([test_ddb_item])
426+
# When: Converting to resource format
427+
dict_item = client_to_resource_converter.transact_get_items_response(response)
428+
# Then: Returns dict value
429+
assert dict_item == test_transact_get_items_response([test_dict_item])

0 commit comments

Comments
 (0)