DynamoDB - error when persisting item with wrong type (#4557)

This commit is contained in:
Bert Blommers 2021-11-10 20:42:33 -01:00 committed by GitHub
parent 701465df26
commit d324532e1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 109 additions and 136 deletions

View File

@ -206,6 +206,13 @@ class UpdateHashRangeKeyException(MockValidationException):
super(UpdateHashRangeKeyException, self).__init__(self.msg.format(key_name))
class InvalidAttributeTypeError(MockValidationException):
msg = "One or more parameter values were invalid: Type mismatch for key {} expected: {} actual: {}"
def __init__(self, name, expected_type, actual_type):
super().__init__(self.msg.format(name, expected_type, actual_type))
class TooManyAddClauses(InvalidUpdateExpression):
msg = 'The "ADD" section can only be used once in an update expression;'

View File

@ -23,6 +23,7 @@ from moto.dynamodb2.exceptions import (
ConditionalCheckFailed,
TransactionCanceledException,
EmptyKeyAttributeException,
InvalidAttributeTypeError,
)
from moto.dynamodb2.models.utilities import bytesize
from moto.dynamodb2.models.dynamo_type import DynamoType
@ -67,11 +68,9 @@ class LimitedSizeDict(dict):
class Item(BaseModel):
def __init__(self, hash_key, hash_key_type, range_key, range_key_type, attrs):
def __init__(self, hash_key, range_key, attrs):
self.hash_key = hash_key
self.hash_key_type = hash_key_type
self.range_key = range_key
self.range_key_type = range_key_type
if hash_key and hash_key.size() > HASH_KEY_MAX_LENGTH:
raise HashKeyTooLong
@ -86,9 +85,7 @@ class Item(BaseModel):
return all(
[
self.hash_key == other.hash_key,
self.hash_key_type == other.hash_key_type,
self.range_key == other.range_key,
self.range_key_type == other.range_key_type,
self.attrs == other.attrs,
]
)
@ -411,12 +408,17 @@ class Table(CloudFormationModel):
self.range_key_type = None
self.hash_key_type = None
for elem in schema:
attr_type = [
a["AttributeType"]
for a in attr
if a["AttributeName"] == elem["AttributeName"]
][0]
if elem["KeyType"] == "HASH":
self.hash_key_attr = elem["AttributeName"]
self.hash_key_type = elem["KeyType"]
self.hash_key_type = attr_type
else:
self.range_key_attr = elem["AttributeName"]
self.range_key_type = elem["KeyType"]
self.range_key_type = attr_type
self.table_key_attrs = [
key for key in (self.hash_key_attr, self.range_key_attr) if key
]
@ -620,6 +622,18 @@ class Table(CloudFormationModel):
else:
range_value = None
if hash_value.type != self.hash_key_type:
raise InvalidAttributeTypeError(
self.hash_key_attr,
expected_type=self.hash_key_type,
actual_type=hash_value.type,
)
if range_value and range_value.type != self.range_key_type:
raise InvalidAttributeTypeError(
self.range_key_attr,
expected_type=self.range_key_type,
actual_type=range_value.type,
)
if expected is None:
expected = {}
lookup_range_value = range_value
@ -630,9 +644,7 @@ class Table(CloudFormationModel):
else:
lookup_range_value = DynamoType(expected_range_value)
current = self.get_item(hash_value, lookup_range_value)
item = Item(
hash_value, self.hash_key_type, range_value, self.range_key_type, item_attrs
)
item = Item(hash_value, range_value, item_attrs)
if not overwrite:
if not get_expected(expected).expr(current):
@ -1427,13 +1439,7 @@ class DynamoDBBackend(BaseBackend):
if item is None:
if update_expression:
# Validate AST before creating anything
item = Item(
hash_value,
table.hash_key_type,
range_value,
table.range_key_type,
attrs={},
)
item = Item(hash_value, range_value, attrs={},)
UpdateExpressionValidator(
update_expression_ast,
expression_attribute_names=expression_attribute_names,

View File

@ -10,4 +10,8 @@ def table():
{"KeyType": "HASH", "AttributeName": "forum_name"},
{"KeyType": "RANGE", "AttributeName": "subject"},
],
attr=[
{"AttributeType": "S", "AttributeName": "forum_name"},
{"AttributeType": "S", "AttributeName": "subject"},
],
)

View File

@ -35,6 +35,10 @@ def test_list_tables():
# Should make tables properly with boto
dynamodb_backend2.create_table(
name,
attr=[
{"AttributeType": "S", "AttributeName": "forum_name"},
{"AttributeType": "S", "AttributeName": "subject"},
],
schema=[
{"KeyType": "HASH", "AttributeName": "forum_name"},
{"KeyType": "RANGE", "AttributeName": "subject"},
@ -70,10 +74,14 @@ def test_list_tables_boto3(names):
def test_list_tables_layer_1():
# Should make tables properly with boto
dynamodb_backend2.create_table(
"test_1", schema=[{"KeyType": "HASH", "AttributeName": "name"}]
"test_1",
attr=[{"AttributeType": "S", "AttributeName": "name"},],
schema=[{"KeyType": "HASH", "AttributeName": "name"}],
)
dynamodb_backend2.create_table(
"test_2", schema=[{"KeyType": "HASH", "AttributeName": "name"}]
"test_2",
attr=[{"AttributeType": "S", "AttributeName": "name"}],
schema=[{"KeyType": "HASH", "AttributeName": "name"}],
)
conn = boto.dynamodb2.connect_to_region(
"us-east-1", aws_access_key_id="ak", aws_secret_access_key="sk"
@ -1485,11 +1493,9 @@ def test_put_item_nonexisting_range_key():
def test_filter_expression():
row1 = moto.dynamodb2.models.Item(
None,
None,
None,
None,
{
hash_key=None,
range_key=None,
attrs={
"Id": {"N": "8"},
"Subs": {"N": "5"},
"Desc": {"S": "Some description"},
@ -1497,11 +1503,9 @@ def test_filter_expression():
},
)
row2 = moto.dynamodb2.models.Item(
None,
None,
None,
None,
{
hash_key=None,
range_key=None,
attrs={
"Id": {"N": "8"},
"Subs": {"N": "10"},
"Desc": {"S": "A description"},

View File

@ -328,3 +328,49 @@ def test_create_table_with_redundant_and_missing_attributes():
err["Message"].should.equal(
"One or more parameter values were invalid: Some index key attributes are not defined in AttributeDefinitions. Keys: [user], AttributeDefinitions: [created_at, id]"
)
@mock_dynamodb2
def test_put_item_wrong_attribute_type():
dynamodb = boto3.client("dynamodb", region_name="us-east-1")
dynamodb.create_table(
TableName="test-table",
AttributeDefinitions=[
{"AttributeName": "id", "AttributeType": "S"},
{"AttributeName": "created_at", "AttributeType": "N"},
],
KeySchema=[
{"AttributeName": "id", "KeyType": "HASH"},
{"AttributeName": "created_at", "KeyType": "RANGE"},
],
BillingMode="PAY_PER_REQUEST",
)
item = {
"id": {"N": "1"}, # should be a string
"created_at": {"N": "2"},
"someAttribute": {"S": "lore ipsum"},
}
with pytest.raises(ClientError) as exc:
dynamodb.put_item(TableName="test-table", Item=item)
err = exc.value.response["Error"]
err["Code"].should.equal("ValidationException")
err["Message"].should.equal(
"One or more parameter values were invalid: Type mismatch for key id expected: S actual: N"
)
item = {
"id": {"S": "some id"},
"created_at": {"S": "should be date not string"},
"someAttribute": {"S": "lore ipsum"},
}
with pytest.raises(ClientError) as exc:
dynamodb.put_item(TableName="test-table", Item=item)
err = exc.value.response["Error"]
err["Code"].should.equal("ValidationException")
err["Message"].should.equal(
"One or more parameter values were invalid: Type mismatch for key created_at expected: N actual: S"
)

View File

@ -12,9 +12,7 @@ def test_execution_of_if_not_exists_not_existing_value(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "a": {"S": "A"}},
)
validated_ast = UpdateExpressionValidator(
@ -27,9 +25,7 @@ def test_execution_of_if_not_exists_not_existing_value(table):
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "a": {"S": "A"}},
)
assert expected_item == item
@ -42,9 +38,7 @@ def test_execution_of_if_not_exists_with_existing_attribute_should_return_attrib
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "a": {"S": "A"}, "b": {"S": "B"}},
)
validated_ast = UpdateExpressionValidator(
@ -57,9 +51,7 @@ def test_execution_of_if_not_exists_with_existing_attribute_should_return_attrib
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "a": {"S": "B"}, "b": {"S": "B"}},
)
assert expected_item == item
@ -71,9 +63,7 @@ def test_execution_of_if_not_exists_with_existing_attribute_should_return_value(
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "b": {"N": "3"}},
)
validated_ast = UpdateExpressionValidator(
@ -86,9 +76,7 @@ def test_execution_of_if_not_exists_with_existing_attribute_should_return_value(
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "b": {"N": "3"}, "a": {"N": "3"}},
)
assert expected_item == item
@ -101,11 +89,7 @@ def test_execution_of_if_not_exists_with_non_existing_attribute_should_return_va
update_expression_values = {":val": {"N": "4"}}
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}},
hash_key=DynamoType({"S": "id"}), range_key=None, attrs={"id": {"S": "1"}},
)
validated_ast = UpdateExpressionValidator(
update_expression_ast,
@ -117,9 +101,7 @@ def test_execution_of_if_not_exists_with_non_existing_attribute_should_return_va
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "a": {"N": "4"}},
)
assert expected_item == item
@ -130,9 +112,7 @@ def test_execution_of_sum_operation(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "a": {"N": "3"}, "b": {"N": "4"}},
)
validated_ast = UpdateExpressionValidator(
@ -145,9 +125,7 @@ def test_execution_of_sum_operation(table):
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "a": {"N": "7"}, "b": {"N": "4"}},
)
assert expected_item == item
@ -158,9 +136,7 @@ def test_execution_of_remove(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "a": {"N": "3"}, "b": {"N": "4"}},
)
validated_ast = UpdateExpressionValidator(
@ -173,9 +149,7 @@ def test_execution_of_remove(table):
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "b": {"N": "4"}},
)
assert expected_item == item
@ -186,9 +160,7 @@ def test_execution_of_remove_in_map(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={
"id": {"S": "foo2"},
"itemmap": {
@ -213,9 +185,7 @@ def test_execution_of_remove_in_map(table):
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={
"id": {"S": "foo2"},
"itemmap": {
@ -238,9 +208,7 @@ def test_execution_of_remove_in_list(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={
"id": {"S": "foo2"},
"itemmap": {
@ -265,9 +233,7 @@ def test_execution_of_remove_in_list(table):
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={
"id": {"S": "foo2"},
"itemmap": {
@ -289,9 +255,7 @@ def test_execution_of_delete_element_from_set(table, attr_name):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "foo2"}, "s": {"SS": ["value1", "value2", "value3"]}},
)
validated_ast = UpdateExpressionValidator(
@ -304,9 +268,7 @@ def test_execution_of_delete_element_from_set(table, attr_name):
UpdateExpressionExecutor(validated_ast, item, expression_attribute_names).execute()
expected_item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "foo2"}, "s": {"SS": ["value1", "value3"]},},
)
assert expected_item == item
@ -323,11 +285,7 @@ def test_execution_of_delete_element_from_set(table, attr_name):
).validate()
UpdateExpressionExecutor(validated_ast, item, expression_attribute_names).execute()
expected_item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "foo2"}},
hash_key=DynamoType({"S": "id"}), range_key=None, attrs={"id": {"S": "foo2"}},
)
assert expected_item == item
@ -337,9 +295,7 @@ def test_execution_of_add_number(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "foo2"}, "s": {"N": "5"},},
)
validated_ast = UpdateExpressionValidator(
@ -352,9 +308,7 @@ def test_execution_of_add_number(table):
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "foo2"}, "s": {"N": "15"}},
)
assert expected_item == item
@ -365,9 +319,7 @@ def test_execution_of_add_set_to_a_number(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "foo2"}, "s": {"N": "5"},},
)
try:
@ -381,9 +333,7 @@ def test_execution_of_add_set_to_a_number(table):
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "foo2"}, "s": {"N": "15"}},
)
assert expected_item == item
@ -397,9 +347,7 @@ def test_execution_of_add_to_a_set(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "foo2"}, "s": {"SS": ["value1", "value2", "value3"]},},
)
validated_ast = UpdateExpressionValidator(
@ -412,9 +360,7 @@ def test_execution_of_add_to_a_set(table):
UpdateExpressionExecutor(validated_ast, item, None).execute()
expected_item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={
"id": {"S": "foo2"},
"s": {"SS": ["value1", "value2", "value3", "value5"]},
@ -443,9 +389,7 @@ def test_execution_of__delete_element_from_set_invalid_value(
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "foo2"}, "s": {"SS": ["value1", "value2", "value3"]},},
)
try:
@ -469,9 +413,7 @@ def test_execution_of_delete_element_from_a_string_attribute(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "foo2"}, "s": {"S": "5"},},
)
try:

View File

@ -400,8 +400,8 @@ def test_get_item_without_range_key():
throughput={"read": 10, "write": 10},
)
hash_key = 3241526475
range_key = 1234567890987
hash_key = "3241526475"
range_key = "1234567890987"
table.put_item(data={"test_hash": hash_key, "test_range": range_key})
table.get_item.when.called_with(test_hash=hash_key).should.throw(
ValidationException
@ -424,8 +424,8 @@ def test_get_item_without_range_key_boto3():
ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 5},
)
hash_key = 3241526475
range_key = 1234567890987
hash_key = "3241526475"
range_key = "1234567890987"
table.put_item(Item={"id": hash_key, "subject": range_key})
with pytest.raises(ClientError) as ex:
@ -1077,7 +1077,10 @@ def test_reverse_query():
def test_lookup():
table = Table.create(
"messages",
schema=[HashKey("test_hash"), RangeKey("test_range")],
schema=[
HashKey("test_hash", data_type=NUMBER),
RangeKey("test_range", data_type=NUMBER),
],
throughput={"read": 10, "write": 10},
)

View File

@ -12,6 +12,7 @@ from tests.helpers import requires_boto_gte
import botocore
try:
from boto.dynamodb2.types import NUMBER
from boto.dynamodb2.fields import HashKey
from boto.dynamodb2.table import Table
from boto.dynamodb2.table import Item
@ -660,7 +661,7 @@ def test_get_missing_item():
def test_get_special_item():
table = Table.create(
"messages",
schema=[HashKey("date-joined")],
schema=[HashKey("date-joined", data_type=NUMBER)],
throughput={"read": 10, "write": 10},
)

View File

@ -27,9 +27,7 @@ def test_valid_update_expression(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "forum_name"}),
hash_key_type="TYPE",
range_key=DynamoType({"S": "forum_type"}),
range_key_type="TYPE",
attrs={"forum_name": {"S": "hello"}},
)
UpdateExpressionValidator(
@ -48,9 +46,7 @@ def test_validation_of_update_expression_with_keyword(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "path": {"N": "3"}},
)
UpdateExpressionValidator(
@ -80,9 +76,7 @@ def test_validation_of_a_set_statement_with_incorrect_passed_value(
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "b": {"N": "3"}},
)
try:
@ -111,9 +105,7 @@ def test_validation_of_update_expression_with_attribute_that_does_not_exist_in_i
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "path": {"N": "3"}},
)
UpdateExpressionValidator(
@ -144,9 +136,7 @@ def test_validation_of_update_expression_with_attribute_name_that_is_not_defined
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "path": {"N": "3"}},
)
UpdateExpressionValidator(
@ -167,9 +157,7 @@ def test_validation_of_if_not_exists_not_existing_invalid_replace_value(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "a": {"S": "A"}},
)
UpdateExpressionValidator(
@ -211,9 +199,7 @@ def test_validation_of_if_not_exists_not_existing_value(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "a": {"S": "A"}},
)
validated_ast = UpdateExpressionValidator(
@ -234,9 +220,7 @@ def test_validation_of_if_not_exists_with_existing_attribute_should_return_attri
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "a": {"S": "A"}, "b": {"S": "B"}},
)
validated_ast = UpdateExpressionValidator(
@ -256,9 +240,7 @@ def test_validation_of_if_not_exists_with_existing_attribute_should_return_value
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "b": {"N": "3"}},
)
validated_ast = UpdateExpressionValidator(
@ -279,11 +261,7 @@ def test_validation_of_if_not_exists_with_non_existing_attribute_should_return_v
update_expression_values = {":val": {"N": "4"}}
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}},
hash_key=DynamoType({"S": "id"}), range_key=None, attrs={"id": {"S": "1"}},
)
validated_ast = UpdateExpressionValidator(
update_expression_ast,
@ -301,9 +279,7 @@ def test_validation_of_sum_operation(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "a": {"N": "3"}, "b": {"N": "4"}},
)
validated_ast = UpdateExpressionValidator(
@ -322,9 +298,7 @@ def test_validation_homogeneous_list_append_function(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "ri": {"L": [{"S": "i1"}, {"S": "i2"}]}},
)
validated_ast = UpdateExpressionValidator(
@ -345,9 +319,7 @@ def test_validation_hetereogenous_list_append_function(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "ri": {"L": [{"S": "i1"}, {"S": "i2"}]}},
)
validated_ast = UpdateExpressionValidator(
@ -374,9 +346,7 @@ def test_validation_list_append_function_with_non_list_arg(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "ri": {"L": [{"S": "i1"}, {"S": "i2"}]}},
)
UpdateExpressionValidator(
@ -403,9 +373,7 @@ def test_sum_with_incompatible_types(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "ri": {"L": [{"S": "i1"}, {"S": "i2"}]}},
)
UpdateExpressionValidator(
@ -425,9 +393,7 @@ def test_validation_of_subraction_operation(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "1"}, "a": {"N": "3"}, "b": {"N": "4"}},
)
validated_ast = UpdateExpressionValidator(
@ -451,9 +417,7 @@ def test_cannot_index_into_a_string(table):
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "foo2"}, "itemstr": {"S": "somestring"}},
)
UpdateExpressionValidator(
@ -476,9 +440,7 @@ def test_validation_set_path_does_not_need_to_be_resolvable_when_setting_a_new_a
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "foo2"}, "a": {"N": "3"}},
)
validated_ast = UpdateExpressionValidator(
@ -500,9 +462,7 @@ def test_validation_set_path_does_not_need_to_be_resolvable_but_must_be_creatabl
update_expression_ast = UpdateExpressionParser.make(update_expression)
item = Item(
hash_key=DynamoType({"S": "id"}),
hash_key_type="TYPE",
range_key=None,
range_key_type=None,
attrs={"id": {"S": "foo2"}, "a": {"N": "3"}},
)
UpdateExpressionValidator(