Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
5a9c921d97
132 changed files with 33915 additions and 9581 deletions
|
|
@ -452,6 +452,90 @@ def test_basic_projection_expressions():
|
|||
assert 'body' in results['Items'][1]
|
||||
assert 'forum_name' in results['Items'][1]
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_basic_projection_expressions_using_scan():
|
||||
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
|
||||
|
||||
# Create the DynamoDB table.
|
||||
table = dynamodb.create_table(
|
||||
TableName='users',
|
||||
KeySchema=[
|
||||
{
|
||||
'AttributeName': 'forum_name',
|
||||
'KeyType': 'HASH'
|
||||
},
|
||||
{
|
||||
'AttributeName': 'subject',
|
||||
'KeyType': 'RANGE'
|
||||
},
|
||||
],
|
||||
AttributeDefinitions=[
|
||||
{
|
||||
'AttributeName': 'forum_name',
|
||||
'AttributeType': 'S'
|
||||
},
|
||||
{
|
||||
'AttributeName': 'subject',
|
||||
'AttributeType': 'S'
|
||||
},
|
||||
],
|
||||
ProvisionedThroughput={
|
||||
'ReadCapacityUnits': 5,
|
||||
'WriteCapacityUnits': 5
|
||||
}
|
||||
)
|
||||
table = dynamodb.Table('users')
|
||||
|
||||
table.put_item(Item={
|
||||
'forum_name': 'the-key',
|
||||
'subject': '123',
|
||||
'body': 'some test message'
|
||||
})
|
||||
|
||||
table.put_item(Item={
|
||||
'forum_name': 'not-the-key',
|
||||
'subject': '123',
|
||||
'body': 'some other test message'
|
||||
})
|
||||
# Test a scan returning all items
|
||||
results = table.scan(
|
||||
FilterExpression=Key('forum_name').eq(
|
||||
'the-key'),
|
||||
ProjectionExpression='body, subject'
|
||||
)
|
||||
|
||||
assert 'body' in results['Items'][0]
|
||||
assert results['Items'][0]['body'] == 'some test message'
|
||||
assert 'subject' in results['Items'][0]
|
||||
|
||||
table.put_item(Item={
|
||||
'forum_name': 'the-key',
|
||||
'subject': '1234',
|
||||
'body': 'yet another test message'
|
||||
})
|
||||
|
||||
results = table.scan(
|
||||
FilterExpression=Key('forum_name').eq(
|
||||
'the-key'),
|
||||
ProjectionExpression='body'
|
||||
)
|
||||
|
||||
assert 'body' in results['Items'][0]
|
||||
assert 'subject' not in results['Items'][0]
|
||||
assert 'forum_name' not in results['Items'][0]
|
||||
assert 'body' in results['Items'][1]
|
||||
assert 'subject' not in results['Items'][1]
|
||||
assert 'forum_name' not in results['Items'][1]
|
||||
|
||||
# The projection expression should not remove data from storage
|
||||
results = table.query(
|
||||
KeyConditionExpression=Key('forum_name').eq(
|
||||
'the-key'),
|
||||
)
|
||||
assert 'subject' in results['Items'][0]
|
||||
assert 'body' in results['Items'][1]
|
||||
assert 'forum_name' in results['Items'][1]
|
||||
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_basic_projection_expressions_with_attr_expression_names():
|
||||
|
|
@ -519,6 +603,84 @@ def test_basic_projection_expressions_with_attr_expression_names():
|
|||
assert 'attachment' in results['Items'][0]
|
||||
assert results['Items'][0]['attachment'] == 'something'
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_basic_projection_expressions_using_scan_with_attr_expression_names():
|
||||
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
|
||||
|
||||
# Create the DynamoDB table.
|
||||
table = dynamodb.create_table(
|
||||
TableName='users',
|
||||
KeySchema=[
|
||||
{
|
||||
'AttributeName': 'forum_name',
|
||||
'KeyType': 'HASH'
|
||||
},
|
||||
{
|
||||
'AttributeName': 'subject',
|
||||
'KeyType': 'RANGE'
|
||||
},
|
||||
],
|
||||
AttributeDefinitions=[
|
||||
{
|
||||
'AttributeName': 'forum_name',
|
||||
'AttributeType': 'S'
|
||||
},
|
||||
{
|
||||
'AttributeName': 'subject',
|
||||
'AttributeType': 'S'
|
||||
},
|
||||
],
|
||||
ProvisionedThroughput={
|
||||
'ReadCapacityUnits': 5,
|
||||
'WriteCapacityUnits': 5
|
||||
}
|
||||
)
|
||||
table = dynamodb.Table('users')
|
||||
|
||||
table.put_item(Item={
|
||||
'forum_name': 'the-key',
|
||||
'subject': '123',
|
||||
'body': 'some test message',
|
||||
'attachment': 'something'
|
||||
})
|
||||
|
||||
table.put_item(Item={
|
||||
'forum_name': 'not-the-key',
|
||||
'subject': '123',
|
||||
'body': 'some other test message',
|
||||
'attachment': 'something'
|
||||
})
|
||||
# Test a scan returning all items
|
||||
|
||||
results = table.scan(
|
||||
FilterExpression=Key('forum_name').eq(
|
||||
'the-key'),
|
||||
ProjectionExpression='#rl, #rt, subject',
|
||||
ExpressionAttributeNames={
|
||||
'#rl': 'body',
|
||||
'#rt': 'attachment'
|
||||
},
|
||||
)
|
||||
|
||||
assert 'body' in results['Items'][0]
|
||||
assert 'attachment' in results['Items'][0]
|
||||
assert 'subject' in results['Items'][0]
|
||||
assert 'form_name' not in results['Items'][0]
|
||||
|
||||
# Test without a FilterExpression
|
||||
results = table.scan(
|
||||
ProjectionExpression='#rl, #rt, subject',
|
||||
ExpressionAttributeNames={
|
||||
'#rl': 'body',
|
||||
'#rt': 'attachment'
|
||||
},
|
||||
)
|
||||
|
||||
assert 'body' in results['Items'][0]
|
||||
assert 'attachment' in results['Items'][0]
|
||||
assert 'subject' in results['Items'][0]
|
||||
assert 'form_name' not in results['Items'][0]
|
||||
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_put_item_returns_consumed_capacity():
|
||||
|
|
@ -676,44 +838,47 @@ def test_filter_expression():
|
|||
filter_expr.expr(row1).should.be(True)
|
||||
|
||||
# NOT test 2
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('NOT (Id = :v0)', {}, {':v0': {'N': 8}})
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('NOT (Id = :v0)', {}, {':v0': {'N': '8'}})
|
||||
filter_expr.expr(row1).should.be(False) # Id = 8 so should be false
|
||||
|
||||
# AND test
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id > :v0 AND Subs < :v1', {}, {':v0': {'N': 5}, ':v1': {'N': 7}})
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id > :v0 AND Subs < :v1', {}, {':v0': {'N': '5'}, ':v1': {'N': '7'}})
|
||||
filter_expr.expr(row1).should.be(True)
|
||||
filter_expr.expr(row2).should.be(False)
|
||||
|
||||
# OR test
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id = :v0 OR Id=:v1', {}, {':v0': {'N': 5}, ':v1': {'N': 8}})
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id = :v0 OR Id=:v1', {}, {':v0': {'N': '5'}, ':v1': {'N': '8'}})
|
||||
filter_expr.expr(row1).should.be(True)
|
||||
|
||||
# BETWEEN test
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id BETWEEN :v0 AND :v1', {}, {':v0': {'N': 5}, ':v1': {'N': 10}})
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id BETWEEN :v0 AND :v1', {}, {':v0': {'N': '5'}, ':v1': {'N': '10'}})
|
||||
filter_expr.expr(row1).should.be(True)
|
||||
|
||||
# PAREN test
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id = :v0 AND (Subs = :v0 OR Subs = :v1)', {}, {':v0': {'N': 8}, ':v1': {'N': 5}})
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id = :v0 AND (Subs = :v0 OR Subs = :v1)', {}, {':v0': {'N': '8'}, ':v1': {'N': '5'}})
|
||||
filter_expr.expr(row1).should.be(True)
|
||||
|
||||
# IN test
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id IN :v0', {}, {':v0': {'NS': [7, 8, 9]}})
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id IN (:v0, :v1, :v2)', {}, {
|
||||
':v0': {'N': '7'},
|
||||
':v1': {'N': '8'},
|
||||
':v2': {'N': '9'}})
|
||||
filter_expr.expr(row1).should.be(True)
|
||||
|
||||
# attribute function tests (with extra spaces)
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('attribute_exists(Id) AND attribute_not_exists (User)', {}, {})
|
||||
filter_expr.expr(row1).should.be(True)
|
||||
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('attribute_type(Id, N)', {}, {})
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('attribute_type(Id, :v0)', {}, {':v0': {'S': 'N'}})
|
||||
filter_expr.expr(row1).should.be(True)
|
||||
|
||||
# beginswith function test
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('begins_with(Desc, Some)', {}, {})
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('begins_with(Desc, :v0)', {}, {':v0': {'S': 'Some'}})
|
||||
filter_expr.expr(row1).should.be(True)
|
||||
filter_expr.expr(row2).should.be(False)
|
||||
|
||||
# contains function test
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('contains(KV, test1)', {}, {})
|
||||
filter_expr = moto.dynamodb2.comparisons.get_filter_expression('contains(KV, :v0)', {}, {':v0': {'S': 'test1'}})
|
||||
filter_expr.expr(row1).should.be(True)
|
||||
filter_expr.expr(row2).should.be(False)
|
||||
|
||||
|
|
@ -754,14 +919,26 @@ def test_query_filter():
|
|||
TableName='test1',
|
||||
Item={
|
||||
'client': {'S': 'client1'},
|
||||
'app': {'S': 'app1'}
|
||||
'app': {'S': 'app1'},
|
||||
'nested': {'M': {
|
||||
'version': {'S': 'version1'},
|
||||
'contents': {'L': [
|
||||
{'S': 'value1'}, {'S': 'value2'},
|
||||
]},
|
||||
}},
|
||||
}
|
||||
)
|
||||
client.put_item(
|
||||
TableName='test1',
|
||||
Item={
|
||||
'client': {'S': 'client1'},
|
||||
'app': {'S': 'app2'}
|
||||
'app': {'S': 'app2'},
|
||||
'nested': {'M': {
|
||||
'version': {'S': 'version2'},
|
||||
'contents': {'L': [
|
||||
{'S': 'value1'}, {'S': 'value2'},
|
||||
]},
|
||||
}},
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -783,6 +960,18 @@ def test_query_filter():
|
|||
)
|
||||
assert response['Count'] == 2
|
||||
|
||||
response = table.query(
|
||||
KeyConditionExpression=Key('client').eq('client1'),
|
||||
FilterExpression=Attr('nested.version').contains('version')
|
||||
)
|
||||
assert response['Count'] == 2
|
||||
|
||||
response = table.query(
|
||||
KeyConditionExpression=Key('client').eq('client1'),
|
||||
FilterExpression=Attr('nested.contents[0]').eq('value1')
|
||||
)
|
||||
assert response['Count'] == 2
|
||||
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_scan_filter():
|
||||
|
|
@ -1061,7 +1250,7 @@ def test_delete_item():
|
|||
with assert_raises(ClientError) as ex:
|
||||
table.delete_item(Key={'client': 'client1', 'app': 'app1'},
|
||||
ReturnValues='ALL_NEW')
|
||||
|
||||
|
||||
# Test deletion and returning old value
|
||||
response = table.delete_item(Key={'client': 'client1', 'app': 'app1'}, ReturnValues='ALL_OLD')
|
||||
response['Attributes'].should.contain('client')
|
||||
|
|
@ -1153,6 +1342,46 @@ def test_query_missing_expr_names():
|
|||
resp['Items'][0]['client']['S'].should.equal('test2')
|
||||
|
||||
|
||||
# https://github.com/spulec/moto/issues/2328
|
||||
@mock_dynamodb2
|
||||
def test_update_item_with_list():
|
||||
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
|
||||
|
||||
# Create the DynamoDB table.
|
||||
dynamodb.create_table(
|
||||
TableName='Table',
|
||||
KeySchema=[
|
||||
{
|
||||
'AttributeName': 'key',
|
||||
'KeyType': 'HASH'
|
||||
}
|
||||
],
|
||||
AttributeDefinitions=[
|
||||
{
|
||||
'AttributeName': 'key',
|
||||
'AttributeType': 'S'
|
||||
},
|
||||
],
|
||||
ProvisionedThroughput={
|
||||
'ReadCapacityUnits': 1,
|
||||
'WriteCapacityUnits': 1
|
||||
}
|
||||
)
|
||||
table = dynamodb.Table('Table')
|
||||
table.update_item(
|
||||
Key={'key': 'the-key'},
|
||||
AttributeUpdates={
|
||||
'list': {'Value': [1, 2], 'Action': 'PUT'}
|
||||
}
|
||||
)
|
||||
|
||||
resp = table.get_item(Key={'key': 'the-key'})
|
||||
resp['Item'].should.equal({
|
||||
'key': 'the-key',
|
||||
'list': [1, 2]
|
||||
})
|
||||
|
||||
|
||||
# https://github.com/spulec/moto/issues/1342
|
||||
@mock_dynamodb2
|
||||
def test_update_item_on_map():
|
||||
|
|
@ -1364,7 +1593,7 @@ def test_put_return_attributes():
|
|||
ReturnValues='NONE'
|
||||
)
|
||||
assert 'Attributes' not in r
|
||||
|
||||
|
||||
r = dynamodb.put_item(
|
||||
TableName='moto-test',
|
||||
Item={'id': {'S': 'foo'}, 'col1': {'S': 'val2'}},
|
||||
|
|
@ -1381,7 +1610,7 @@ def test_put_return_attributes():
|
|||
ex.exception.response['Error']['Code'].should.equal('ValidationException')
|
||||
ex.exception.response['ResponseMetadata']['HTTPStatusCode'].should.equal(400)
|
||||
ex.exception.response['Error']['Message'].should.equal('Return values set to invalid value')
|
||||
|
||||
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_query_global_secondary_index_when_created_via_update_table_resource():
|
||||
|
|
@ -1489,7 +1718,7 @@ def test_dynamodb_streams_1():
|
|||
'StreamViewType': 'NEW_AND_OLD_IMAGES'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
assert 'StreamSpecification' in resp['TableDescription']
|
||||
assert resp['TableDescription']['StreamSpecification'] == {
|
||||
'StreamEnabled': True,
|
||||
|
|
@ -1497,11 +1726,11 @@ def test_dynamodb_streams_1():
|
|||
}
|
||||
assert 'LatestStreamLabel' in resp['TableDescription']
|
||||
assert 'LatestStreamArn' in resp['TableDescription']
|
||||
|
||||
|
||||
resp = conn.delete_table(TableName='test-streams')
|
||||
|
||||
assert 'StreamSpecification' in resp['TableDescription']
|
||||
|
||||
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_dynamodb_streams_2():
|
||||
|
|
@ -1532,11 +1761,10 @@ def test_dynamodb_streams_2():
|
|||
assert 'LatestStreamLabel' in resp['TableDescription']
|
||||
assert 'LatestStreamArn' in resp['TableDescription']
|
||||
|
||||
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_condition_expressions():
|
||||
client = boto3.client('dynamodb', region_name='us-east-1')
|
||||
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
|
||||
|
||||
# Create the DynamoDB table.
|
||||
client.create_table(
|
||||
|
|
@ -1589,6 +1817,57 @@ def test_condition_expressions():
|
|||
}
|
||||
)
|
||||
|
||||
client.put_item(
|
||||
TableName='test1',
|
||||
Item={
|
||||
'client': {'S': 'client1'},
|
||||
'app': {'S': 'app1'},
|
||||
'match': {'S': 'match'},
|
||||
'existing': {'S': 'existing'},
|
||||
},
|
||||
ConditionExpression='attribute_exists(#nonexistent) OR attribute_exists(#existing)',
|
||||
ExpressionAttributeNames={
|
||||
'#nonexistent': 'nope',
|
||||
'#existing': 'existing'
|
||||
}
|
||||
)
|
||||
|
||||
client.put_item(
|
||||
TableName='test1',
|
||||
Item={
|
||||
'client': {'S': 'client1'},
|
||||
'app': {'S': 'app1'},
|
||||
'match': {'S': 'match'},
|
||||
'existing': {'S': 'existing'},
|
||||
},
|
||||
ConditionExpression='#client BETWEEN :a AND :z',
|
||||
ExpressionAttributeNames={
|
||||
'#client': 'client',
|
||||
},
|
||||
ExpressionAttributeValues={
|
||||
':a': {'S': 'a'},
|
||||
':z': {'S': 'z'},
|
||||
}
|
||||
)
|
||||
|
||||
client.put_item(
|
||||
TableName='test1',
|
||||
Item={
|
||||
'client': {'S': 'client1'},
|
||||
'app': {'S': 'app1'},
|
||||
'match': {'S': 'match'},
|
||||
'existing': {'S': 'existing'},
|
||||
},
|
||||
ConditionExpression='#client IN (:client1, :client2)',
|
||||
ExpressionAttributeNames={
|
||||
'#client': 'client',
|
||||
},
|
||||
ExpressionAttributeValues={
|
||||
':client1': {'S': 'client1'},
|
||||
':client2': {'S': 'client2'},
|
||||
}
|
||||
)
|
||||
|
||||
with assert_raises(client.exceptions.ConditionalCheckFailedException):
|
||||
client.put_item(
|
||||
TableName='test1',
|
||||
|
|
@ -1641,6 +1920,119 @@ def test_condition_expressions():
|
|||
}
|
||||
)
|
||||
|
||||
# Make sure update_item honors ConditionExpression as well
|
||||
client.update_item(
|
||||
TableName='test1',
|
||||
Key={
|
||||
'client': {'S': 'client1'},
|
||||
'app': {'S': 'app1'},
|
||||
},
|
||||
UpdateExpression='set #match=:match',
|
||||
ConditionExpression='attribute_exists(#existing)',
|
||||
ExpressionAttributeNames={
|
||||
'#existing': 'existing',
|
||||
'#match': 'match',
|
||||
},
|
||||
ExpressionAttributeValues={
|
||||
':match': {'S': 'match'}
|
||||
}
|
||||
)
|
||||
|
||||
with assert_raises(client.exceptions.ConditionalCheckFailedException):
|
||||
client.update_item(
|
||||
TableName='test1',
|
||||
Key={
|
||||
'client': { 'S': 'client1'},
|
||||
'app': { 'S': 'app1'},
|
||||
},
|
||||
UpdateExpression='set #match=:match',
|
||||
ConditionExpression='attribute_not_exists(#existing)',
|
||||
ExpressionAttributeValues={
|
||||
':match': {'S': 'match'}
|
||||
},
|
||||
ExpressionAttributeNames={
|
||||
'#existing': 'existing',
|
||||
'#match': 'match',
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_condition_expression__attr_doesnt_exist():
|
||||
client = boto3.client('dynamodb', region_name='us-east-1')
|
||||
|
||||
client.create_table(
|
||||
TableName='test',
|
||||
KeySchema=[{'AttributeName': 'forum_name', 'KeyType': 'HASH'}],
|
||||
AttributeDefinitions=[
|
||||
{'AttributeName': 'forum_name', 'AttributeType': 'S'},
|
||||
],
|
||||
ProvisionedThroughput={'ReadCapacityUnits': 1, 'WriteCapacityUnits': 1},
|
||||
)
|
||||
|
||||
client.put_item(
|
||||
TableName='test',
|
||||
Item={
|
||||
'forum_name': {'S': 'foo'},
|
||||
'ttl': {'N': 'bar'},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def update_if_attr_doesnt_exist():
|
||||
# Test nonexistent top-level attribute.
|
||||
client.update_item(
|
||||
TableName='test',
|
||||
Key={
|
||||
'forum_name': {'S': 'the-key'},
|
||||
'subject': {'S': 'the-subject'},
|
||||
},
|
||||
UpdateExpression='set #new_state=:new_state, #ttl=:ttl',
|
||||
ConditionExpression='attribute_not_exists(#new_state)',
|
||||
ExpressionAttributeNames={'#new_state': 'foobar', '#ttl': 'ttl'},
|
||||
ExpressionAttributeValues={
|
||||
':new_state': {'S': 'some-value'},
|
||||
':ttl': {'N': '12345.67'},
|
||||
},
|
||||
ReturnValues='ALL_NEW',
|
||||
)
|
||||
|
||||
update_if_attr_doesnt_exist()
|
||||
|
||||
# Second time should fail
|
||||
with assert_raises(client.exceptions.ConditionalCheckFailedException):
|
||||
update_if_attr_doesnt_exist()
|
||||
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_condition_expression__or_order():
|
||||
client = boto3.client('dynamodb', region_name='us-east-1')
|
||||
|
||||
client.create_table(
|
||||
TableName='test',
|
||||
KeySchema=[{'AttributeName': 'forum_name', 'KeyType': 'HASH'}],
|
||||
AttributeDefinitions=[
|
||||
{'AttributeName': 'forum_name', 'AttributeType': 'S'},
|
||||
],
|
||||
ProvisionedThroughput={'ReadCapacityUnits': 1, 'WriteCapacityUnits': 1},
|
||||
)
|
||||
|
||||
# ensure that the RHS of the OR expression is not evaluated if the LHS
|
||||
# returns true (as it would result an error)
|
||||
client.update_item(
|
||||
TableName='test',
|
||||
Key={
|
||||
'forum_name': {'S': 'the-key'},
|
||||
},
|
||||
UpdateExpression='set #ttl=:ttl',
|
||||
ConditionExpression='attribute_not_exists(#ttl) OR #ttl <= :old_ttl',
|
||||
ExpressionAttributeNames={'#ttl': 'ttl'},
|
||||
ExpressionAttributeValues={
|
||||
':ttl': {'N': '6'},
|
||||
':old_ttl': {'N': '5'},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_query_gsi_with_range_key():
|
||||
|
|
@ -1749,3 +2141,55 @@ def test_scan_by_non_exists_index():
|
|||
ex.exception.response['Error']['Message'].should.equal(
|
||||
'The table does not have the specified index: non_exists_index'
|
||||
)
|
||||
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_batch_items_returns_all():
|
||||
dynamodb = _create_user_table()
|
||||
returned_items = dynamodb.batch_get_item(RequestItems={
|
||||
'users': {
|
||||
'Keys': [{
|
||||
'username': {'S': 'user0'}
|
||||
}, {
|
||||
'username': {'S': 'user1'}
|
||||
}, {
|
||||
'username': {'S': 'user2'}
|
||||
}, {
|
||||
'username': {'S': 'user3'}
|
||||
}],
|
||||
'ConsistentRead': True
|
||||
}
|
||||
})['Responses']['users']
|
||||
assert len(returned_items) == 3
|
||||
assert [item['username']['S'] for item in returned_items] == ['user1', 'user2', 'user3']
|
||||
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_batch_items_should_throw_exception_for_duplicate_request():
|
||||
client = _create_user_table()
|
||||
with assert_raises(ClientError) as ex:
|
||||
client.batch_get_item(RequestItems={
|
||||
'users': {
|
||||
'Keys': [{
|
||||
'username': {'S': 'user0'}
|
||||
}, {
|
||||
'username': {'S': 'user0'}
|
||||
}],
|
||||
'ConsistentRead': True
|
||||
}})
|
||||
ex.exception.response['Error']['Code'].should.equal('ValidationException')
|
||||
ex.exception.response['Error']['Message'].should.equal('Provided list of item keys contains duplicates')
|
||||
|
||||
|
||||
def _create_user_table():
|
||||
client = boto3.client('dynamodb', region_name='us-east-1')
|
||||
client.create_table(
|
||||
TableName='users',
|
||||
KeySchema=[{'AttributeName': 'username', 'KeyType': 'HASH'}],
|
||||
AttributeDefinitions=[{'AttributeName': 'username', 'AttributeType': 'S'}],
|
||||
ProvisionedThroughput={'ReadCapacityUnits': 5, 'WriteCapacityUnits': 5}
|
||||
)
|
||||
client.put_item(TableName='users', Item={'username': {'S': 'user1'}, 'foo': {'S': 'bar'}})
|
||||
client.put_item(TableName='users', Item={'username': {'S': 'user2'}, 'foo': {'S': 'bar'}})
|
||||
client.put_item(TableName='users', Item={'username': {'S': 'user3'}, 'foo': {'S': 'bar'}})
|
||||
return client
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue