Add basic support for the add operation in an update operation

Add basic delete functionality


Improve testing coverage and make behave more like actual dynamo on errors


Lint fix
This commit is contained in:
Brian Rower 2017-09-12 21:42:29 -07:00
commit 6affc7a4ec
3 changed files with 188 additions and 1 deletions

View file

@ -5,6 +5,7 @@ from decimal import Decimal
import boto
import boto3
from boto3.dynamodb.conditions import Key
from botocore.exceptions import ClientError
import sure # noqa
from freezegun import freeze_time
from moto import mock_dynamodb2, mock_dynamodb2_deprecated
@ -1190,6 +1191,14 @@ def _create_table_with_range_key():
'AttributeName': 'subject',
'AttributeType': 'S'
},
{
'AttributeName': 'username',
'AttributeType': 'S'
},
{
'AttributeName': 'created',
'AttributeType': 'N'
}
],
ProvisionedThroughput={
'ReadCapacityUnits': 5,
@ -1392,6 +1401,123 @@ def test_update_item_with_expression():
'subject': '123',
})
@mock_dynamodb2
def test_update_item_add_with_expression():
table = _create_table_with_range_key()
item_key = {'forum_name': 'the-key', 'subject': '123'}
current_item = {
'forum_name': 'the-key',
'subject': '123',
'str_set': {'item1', 'item2', 'item3'},
'num_set': {1, 2, 3},
'num_val': 6
}
# Put an entry in the DB to play with
table.put_item(Item=current_item)
# Update item to add a string value to a string set
table.update_item(
Key=item_key,
UpdateExpression='ADD str_set :v',
ExpressionAttributeValues={
':v': {'item4'}
}
)
current_item['str_set'] = current_item['str_set'].union({'item4'})
dict(table.get_item(Key=item_key)['Item']).should.equal(current_item)
# Update item to add a num value to a num set
table.update_item(
Key=item_key,
UpdateExpression='ADD num_set :v',
ExpressionAttributeValues={
':v': {6}
}
)
current_item['num_set'] = current_item['num_set'].union({6})
dict(table.get_item(Key=item_key)['Item']).should.equal(current_item)
# Update item to add a value to a number value
table.update_item(
Key=item_key,
UpdateExpression='ADD num_val :v',
ExpressionAttributeValues={
':v': 20
}
)
current_item['num_val'] = current_item['num_val'] + 20
dict(table.get_item(Key=item_key)['Item']).should.equal(current_item)
# Attempt to add a number value to a string set, should raise Client Error
table.update_item.when.called_with(
Key=item_key,
UpdateExpression='ADD str_set :v',
ExpressionAttributeValues={
':v': 20
}
).should.have.raised(ClientError)
dict(table.get_item(Key=item_key)['Item']).should.equal(current_item)
# Attempt to add a number set to the string set, should raise a ClientError
table.update_item.when.called_with(
Key=item_key,
UpdateExpression='ADD str_set :v',
ExpressionAttributeValues={
':v': { 20 }
}
).should.have.raised(ClientError)
dict(table.get_item(Key=item_key)['Item']).should.equal(current_item)
@mock_dynamodb2
def test_update_item_delete_with_expression():
table = _create_table_with_range_key()
item_key = {'forum_name': 'the-key', 'subject': '123'}
current_item = {
'forum_name': 'the-key',
'subject': '123',
'str_set': {'item1', 'item2', 'item3'},
'num_set': {1, 2, 3},
'num_val': 6
}
# Put an entry in the DB to play with
table.put_item(Item=current_item)
# Update item to delete a string value from a string set
table.update_item(
Key=item_key,
UpdateExpression='DELETE str_set :v',
ExpressionAttributeValues={
':v': {'item2'}
}
)
current_item['str_set'] = current_item['str_set'].difference({'item2'})
dict(table.get_item(Key=item_key)['Item']).should.equal(current_item)
# Update item to delete a num value from a num set
table.update_item(
Key=item_key,
UpdateExpression='DELETE num_set :v',
ExpressionAttributeValues={
':v': {2}
}
)
current_item['num_set'] = current_item['num_set'].difference({2})
dict(table.get_item(Key=item_key)['Item']).should.equal(current_item)
# Try to delete on a number, this should fail
table.update_item.when.called_with(
Key=item_key,
UpdateExpression='DELETE num_val :v',
ExpressionAttributeValues={
':v': 20
}
).should.have.raised(ClientError)
dict(table.get_item(Key=item_key)['Item']).should.equal(current_item)
@mock_dynamodb2
def test_boto3_query_gsi_range_comparison():