Add support for empty strings in non-key dynamo attributes (#3467)

* Add support for empty strings in non-key attributes

https://github.com/spulec/moto/issues/3339

* Nose, not pytest

* Revert "Nose, not pytest"

This reverts commit 5a3cf6c887dd9fafa49096c82cfa3a3b7f91d224.

* PUT is default action
This commit is contained in:
Rich Unger 2020-11-17 01:12:39 -08:00 committed by GitHub
commit f045af7e0a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 257 additions and 52 deletions

View file

@ -7,7 +7,7 @@ from moto.dynamodb2.parsing.expressions import UpdateExpressionParser
from moto.dynamodb2.parsing.validators import UpdateExpressionValidator
def test_execution_of_if_not_exists_not_existing_value():
def test_execution_of_if_not_exists_not_existing_value(table):
update_expression = "SET a = if_not_exists(b, a)"
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
@ -22,6 +22,7 @@ def test_execution_of_if_not_exists_not_existing_value():
expression_attribute_names=None,
expression_attribute_values=None,
item=item,
table=table,
).validate()
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
@ -34,7 +35,9 @@ def test_execution_of_if_not_exists_not_existing_value():
assert expected_item == item
def test_execution_of_if_not_exists_with_existing_attribute_should_return_attribute():
def test_execution_of_if_not_exists_with_existing_attribute_should_return_attribute(
table,
):
update_expression = "SET a = if_not_exists(b, a)"
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
@ -49,6 +52,7 @@ def test_execution_of_if_not_exists_with_existing_attribute_should_return_attrib
expression_attribute_names=None,
expression_attribute_values=None,
item=item,
table=table,
).validate()
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
@ -61,7 +65,7 @@ def test_execution_of_if_not_exists_with_existing_attribute_should_return_attrib
assert expected_item == item
def test_execution_of_if_not_exists_with_existing_attribute_should_return_value():
def test_execution_of_if_not_exists_with_existing_attribute_should_return_value(table):
update_expression = "SET a = if_not_exists(b, :val)"
update_expression_values = {":val": {"N": "4"}}
update_expression_ast = UpdateExpressionParser.make(update_expression)
@ -77,6 +81,7 @@ def test_execution_of_if_not_exists_with_existing_attribute_should_return_value(
expression_attribute_names=None,
expression_attribute_values=update_expression_values,
item=item,
table=table,
).validate()
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
@ -89,7 +94,9 @@ def test_execution_of_if_not_exists_with_existing_attribute_should_return_value(
assert expected_item == item
def test_execution_of_if_not_exists_with_non_existing_attribute_should_return_value():
def test_execution_of_if_not_exists_with_non_existing_attribute_should_return_value(
table,
):
update_expression = "SET a = if_not_exists(b, :val)"
update_expression_values = {":val": {"N": "4"}}
update_expression_ast = UpdateExpressionParser.make(update_expression)
@ -105,6 +112,7 @@ def test_execution_of_if_not_exists_with_non_existing_attribute_should_return_va
expression_attribute_names=None,
expression_attribute_values=update_expression_values,
item=item,
table=table,
).validate()
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
@ -117,7 +125,7 @@ def test_execution_of_if_not_exists_with_non_existing_attribute_should_return_va
assert expected_item == item
def test_execution_of_sum_operation():
def test_execution_of_sum_operation(table):
update_expression = "SET a = a + b"
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
@ -132,6 +140,7 @@ def test_execution_of_sum_operation():
expression_attribute_names=None,
expression_attribute_values=None,
item=item,
table=table,
).validate()
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
@ -144,7 +153,7 @@ def test_execution_of_sum_operation():
assert expected_item == item
def test_execution_of_remove():
def test_execution_of_remove(table):
update_expression = "Remove a"
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
@ -159,6 +168,7 @@ def test_execution_of_remove():
expression_attribute_names=None,
expression_attribute_values=None,
item=item,
table=table,
).validate()
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
@ -171,7 +181,7 @@ def test_execution_of_remove():
assert expected_item == item
def test_execution_of_remove_in_map():
def test_execution_of_remove_in_map(table):
update_expression = "Remove itemmap.itemlist[1].foo11"
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
@ -198,6 +208,7 @@ def test_execution_of_remove_in_map():
expression_attribute_names=None,
expression_attribute_values=None,
item=item,
table=table,
).validate()
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
@ -222,7 +233,7 @@ def test_execution_of_remove_in_map():
assert expected_item == item
def test_execution_of_remove_in_list():
def test_execution_of_remove_in_list(table):
update_expression = "Remove itemmap.itemlist[1]"
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
@ -249,6 +260,7 @@ def test_execution_of_remove_in_list():
expression_attribute_names=None,
expression_attribute_values=None,
item=item,
table=table,
).validate()
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
@ -270,7 +282,7 @@ def test_execution_of_remove_in_list():
assert expected_item == item
def test_execution_of_delete_element_from_set():
def test_execution_of_delete_element_from_set(table):
update_expression = "delete s :value"
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
@ -285,6 +297,7 @@ def test_execution_of_delete_element_from_set():
expression_attribute_names=None,
expression_attribute_values={":value": {"SS": ["value2", "value5"]}},
item=item,
table=table,
).validate()
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
@ -297,7 +310,7 @@ def test_execution_of_delete_element_from_set():
assert expected_item == item
def test_execution_of_add_number():
def test_execution_of_add_number(table):
update_expression = "add s :value"
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
@ -312,6 +325,7 @@ def test_execution_of_add_number():
expression_attribute_names=None,
expression_attribute_values={":value": {"N": "10"}},
item=item,
table=table,
).validate()
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
@ -324,7 +338,7 @@ def test_execution_of_add_number():
assert expected_item == item
def test_execution_of_add_set_to_a_number():
def test_execution_of_add_set_to_a_number(table):
update_expression = "add s :value"
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
@ -340,6 +354,7 @@ def test_execution_of_add_set_to_a_number():
expression_attribute_names=None,
expression_attribute_values={":value": {"SS": ["s1"]}},
item=item,
table=table,
).validate()
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
@ -355,7 +370,7 @@ def test_execution_of_add_set_to_a_number():
assert True
def test_execution_of_add_to_a_set():
def test_execution_of_add_to_a_set(table):
update_expression = "ADD s :value"
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
@ -370,6 +385,7 @@ def test_execution_of_add_to_a_set():
expression_attribute_names=None,
expression_attribute_values={":value": {"SS": ["value2", "value5"]}},
item=item,
table=table,
).validate()
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
@ -398,7 +414,7 @@ def test_execution_of_add_to_a_set():
],
)
def test_execution_of__delete_element_from_set_invalid_value(
expression_attribute_values, unexpected_data_type
expression_attribute_values, unexpected_data_type, table
):
"""A delete statement must use a value of type SS in order to delete elements from a set."""
update_expression = "delete s :value"
@ -416,6 +432,7 @@ def test_execution_of__delete_element_from_set_invalid_value(
expression_attribute_names=None,
expression_attribute_values=expression_attribute_values,
item=item,
table=table,
).validate()
UpdateExpressionExecutor(validated_ast, item, None).execute()
assert False, "Must raise exception"
@ -424,7 +441,7 @@ def test_execution_of__delete_element_from_set_invalid_value(
assert e.operand_type == unexpected_data_type
def test_execution_of_delete_element_from_a_string_attribute():
def test_execution_of_delete_element_from_a_string_attribute(table):
"""A delete statement must use a value of type SS in order to delete elements from a set."""
update_expression = "delete s :value"
update_expression_ast = UpdateExpressionParser.make(update_expression)
@ -441,6 +458,7 @@ def test_execution_of_delete_element_from_a_string_attribute():
expression_attribute_names=None,
expression_attribute_values={":value": {"SS": ["value2"]}},
item=item,
table=table,
).validate()
UpdateExpressionExecutor(validated_ast, item, None).execute()
assert False, "Must raise exception"