| 
									
										
										
										
											2014-08-26 13:25:50 -04:00
										 |  |  | from __future__ import unicode_literals, print_function | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  | from decimal import Decimal | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-26 13:25:50 -04:00
										 |  |  | import six | 
					
						
							| 
									
										
										
										
											2013-12-05 13:16:56 +02:00
										 |  |  | import boto | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  | import boto3 | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  | from boto3.dynamodb.conditions import Attr, Key | 
					
						
							| 
									
										
										
										
											2013-12-05 13:16:56 +02:00
										 |  |  | import sure  # noqa | 
					
						
							|  |  |  | import requests | 
					
						
							| 
									
										
										
										
											2017-02-15 22:35:45 -05:00
										 |  |  | from moto import mock_dynamodb2, mock_dynamodb2_deprecated | 
					
						
							| 
									
										
										
										
											2019-12-24 10:23:46 -08:00
										 |  |  | from moto.dynamodb2 import dynamodb_backend2, dynamodb_backends2 | 
					
						
							| 
									
										
										
										
											2013-12-05 13:16:56 +02:00
										 |  |  | from boto.exception import JSONResponseError | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | from botocore.exceptions import ClientError, ParamValidationError | 
					
						
							| 
									
										
										
										
											2014-01-07 10:56:51 +02:00
										 |  |  | from tests.helpers import requires_boto_gte | 
					
						
							| 
									
										
										
										
											2014-08-26 13:25:50 -04:00
										 |  |  | import tests.backport_assert_raises | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import moto.dynamodb2.comparisons | 
					
						
							|  |  |  | import moto.dynamodb2.models | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-26 13:25:50 -04:00
										 |  |  | from nose.tools import assert_raises | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-07 12:59:36 +02:00
										 |  |  | try: | 
					
						
							|  |  |  |     import boto.dynamodb2 | 
					
						
							|  |  |  | except ImportError: | 
					
						
							| 
									
										
										
										
											2014-08-26 13:25:50 -04:00
										 |  |  |     print("This boto version is not supported") | 
					
						
							| 
									
										
										
										
											2013-12-05 13:16:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 21:37:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-07 10:56:51 +02:00
										 |  |  | @requires_boto_gte("2.9") | 
					
						
							| 
									
										
										
										
											2017-02-15 22:35:45 -05:00
										 |  |  | @mock_dynamodb2_deprecated | 
					
						
							| 
									
										
										
										
											2013-12-05 13:16:56 +02:00
										 |  |  | def test_list_tables(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     name = "TestTable" | 
					
						
							| 
									
										
										
										
											2017-10-29 16:25:17 +00:00
										 |  |  |     # Should make tables properly with boto | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb_backend2.create_table( | 
					
						
							|  |  |  |         name, | 
					
						
							|  |  |  |         schema=[ | 
					
						
							|  |  |  |             {"KeyType": "HASH", "AttributeName": "forum_name"}, | 
					
						
							|  |  |  |             {"KeyType": "RANGE", "AttributeName": "subject"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-02-23 21:37:43 -05:00
										 |  |  |     conn = boto.dynamodb2.connect_to_region( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         "us-east-1", aws_access_key_id="ak", aws_secret_access_key="sk" | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2013-12-05 13:16:56 +02:00
										 |  |  |     assert conn.list_tables()["TableNames"] == [name] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-07 10:56:51 +02:00
										 |  |  | @requires_boto_gte("2.9") | 
					
						
							| 
									
										
										
										
											2017-02-15 22:35:45 -05:00
										 |  |  | @mock_dynamodb2_deprecated | 
					
						
							| 
									
										
										
										
											2013-12-05 13:16:56 +02:00
										 |  |  | def test_list_tables_layer_1(): | 
					
						
							| 
									
										
										
										
											2017-10-29 16:25:17 +00:00
										 |  |  |     # Should make tables properly with boto | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb_backend2.create_table( | 
					
						
							|  |  |  |         "test_1", schema=[{"KeyType": "HASH", "AttributeName": "name"}] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     dynamodb_backend2.create_table( | 
					
						
							|  |  |  |         "test_2", schema=[{"KeyType": "HASH", "AttributeName": "name"}] | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-02-23 21:37:43 -05:00
										 |  |  |     conn = boto.dynamodb2.connect_to_region( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         "us-east-1", aws_access_key_id="ak", aws_secret_access_key="sk" | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2014-08-27 11:17:06 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-05 13:16:56 +02:00
										 |  |  |     res = conn.list_tables(limit=1) | 
					
						
							|  |  |  |     expected = {"TableNames": ["test_1"], "LastEvaluatedTableName": "test_1"} | 
					
						
							|  |  |  |     res.should.equal(expected) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     res = conn.list_tables(limit=1, exclusive_start_table_name="test_1") | 
					
						
							|  |  |  |     expected = {"TableNames": ["test_2"]} | 
					
						
							|  |  |  |     res.should.equal(expected) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-07 10:56:51 +02:00
										 |  |  | @requires_boto_gte("2.9") | 
					
						
							| 
									
										
										
										
											2017-02-15 22:35:45 -05:00
										 |  |  | @mock_dynamodb2_deprecated | 
					
						
							| 
									
										
										
										
											2013-12-05 13:16:56 +02:00
										 |  |  | def test_describe_missing_table(): | 
					
						
							| 
									
										
										
										
											2017-02-23 21:37:43 -05:00
										 |  |  |     conn = boto.dynamodb2.connect_to_region( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         "us-west-2", aws_access_key_id="ak", aws_secret_access_key="sk" | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2014-08-26 13:25:50 -04:00
										 |  |  |     with assert_raises(JSONResponseError): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         conn.describe_table("messages") | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @requires_boto_gte("2.9") | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_list_table_tags(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     name = "TestTable" | 
					
						
							|  |  |  |     conn = boto3.client( | 
					
						
							|  |  |  |         "dynamodb", | 
					
						
							|  |  |  |         region_name="us-west-2", | 
					
						
							|  |  |  |         aws_access_key_id="ak", | 
					
						
							|  |  |  |         aws_secret_access_key="sk", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     conn.create_table( | 
					
						
							|  |  |  |         TableName=name, | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  |     table_description = conn.describe_table(TableName=name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     arn = table_description["Table"]["TableArn"] | 
					
						
							| 
									
										
										
										
											2017-10-29 16:06:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Tag table | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     tags = [ | 
					
						
							|  |  |  |         {"Key": "TestTag", "Value": "TestValue"}, | 
					
						
							|  |  |  |         {"Key": "TestTag2", "Value": "TestValue2"}, | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2017-10-29 16:06:09 +00:00
										 |  |  |     conn.tag_resource(ResourceArn=arn, Tags=tags) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Check tags | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  |     resp = conn.list_tags_of_resource(ResourceArn=arn) | 
					
						
							|  |  |  |     assert resp["Tags"] == tags | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-29 16:06:09 +00:00
										 |  |  |     # Remove 1 tag | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     conn.untag_resource(ResourceArn=arn, TagKeys=["TestTag"]) | 
					
						
							| 
									
										
										
										
											2017-10-29 16:06:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Check tags | 
					
						
							|  |  |  |     resp = conn.list_tags_of_resource(ResourceArn=arn) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert resp["Tags"] == [{"Key": "TestTag2", "Value": "TestValue2"}] | 
					
						
							| 
									
										
										
										
											2017-10-29 16:06:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | @requires_boto_gte("2.9") | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_list_table_tags_empty(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     name = "TestTable" | 
					
						
							|  |  |  |     conn = boto3.client( | 
					
						
							|  |  |  |         "dynamodb", | 
					
						
							|  |  |  |         region_name="us-west-2", | 
					
						
							|  |  |  |         aws_access_key_id="ak", | 
					
						
							|  |  |  |         aws_secret_access_key="sk", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     conn.create_table( | 
					
						
							|  |  |  |         TableName=name, | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  |     table_description = conn.describe_table(TableName=name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     arn = table_description["Table"]["TableArn"] | 
					
						
							|  |  |  |     tags = [{"Key": "TestTag", "Value": "TestValue"}] | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  |     # conn.tag_resource(ResourceArn=arn, | 
					
						
							|  |  |  |     #                   Tags=tags) | 
					
						
							|  |  |  |     resp = conn.list_tags_of_resource(ResourceArn=arn) | 
					
						
							|  |  |  |     assert resp["Tags"] == [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @requires_boto_gte("2.9") | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_list_table_tags_paginated(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     name = "TestTable" | 
					
						
							|  |  |  |     conn = boto3.client( | 
					
						
							|  |  |  |         "dynamodb", | 
					
						
							|  |  |  |         region_name="us-west-2", | 
					
						
							|  |  |  |         aws_access_key_id="ak", | 
					
						
							|  |  |  |         aws_secret_access_key="sk", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     conn.create_table( | 
					
						
							|  |  |  |         TableName=name, | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  |     table_description = conn.describe_table(TableName=name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     arn = table_description["Table"]["TableArn"] | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  |     for i in range(11): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         tags = [{"Key": "TestTag%d" % i, "Value": "TestValue"}] | 
					
						
							|  |  |  |         conn.tag_resource(ResourceArn=arn, Tags=tags) | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  |     resp = conn.list_tags_of_resource(ResourceArn=arn) | 
					
						
							|  |  |  |     assert len(resp["Tags"]) == 10 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "NextToken" in resp.keys() | 
					
						
							|  |  |  |     resp2 = conn.list_tags_of_resource(ResourceArn=arn, NextToken=resp["NextToken"]) | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  |     assert len(resp2["Tags"]) == 1 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "NextToken" not in resp2.keys() | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @requires_boto_gte("2.9") | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_list_not_found_table_tags(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     conn = boto3.client( | 
					
						
							|  |  |  |         "dynamodb", | 
					
						
							|  |  |  |         region_name="us-west-2", | 
					
						
							|  |  |  |         aws_access_key_id="ak", | 
					
						
							|  |  |  |         aws_secret_access_key="sk", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     arn = "DymmyArn" | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  |     try: | 
					
						
							|  |  |  |         conn.list_tags_of_resource(ResourceArn=arn) | 
					
						
							|  |  |  |     except ClientError as exception: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         assert exception.response["Error"]["Code"] == "ResourceNotFoundException" | 
					
						
							| 
									
										
										
										
											2017-09-12 09:28:36 +12:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @requires_boto_gte("2.9") | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_item_add_empty_string_exception(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     name = "TestTable" | 
					
						
							|  |  |  |     conn = boto3.client( | 
					
						
							|  |  |  |         "dynamodb", | 
					
						
							|  |  |  |         region_name="us-west-2", | 
					
						
							|  |  |  |         aws_access_key_id="ak", | 
					
						
							|  |  |  |         aws_secret_access_key="sk", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     conn.create_table( | 
					
						
							|  |  |  |         TableName=name, | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-09-12 12:21:08 +12:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-13 08:28:42 +12:00
										 |  |  |     with assert_raises(ClientError) as ex: | 
					
						
							| 
									
										
										
										
											2017-09-12 12:21:08 +12:00
										 |  |  |         conn.put_item( | 
					
						
							|  |  |  |             TableName=name, | 
					
						
							|  |  |  |             Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 "forum_name": {"S": "LOLCat Forum"}, | 
					
						
							|  |  |  |                 "subject": {"S": "Check this out!"}, | 
					
						
							|  |  |  |                 "Body": {"S": "http://url_to_lolcat.gif"}, | 
					
						
							|  |  |  |                 "SentBy": {"S": ""}, | 
					
						
							|  |  |  |                 "ReceivedTime": {"S": "12/9/2011 11:36:03 PM"}, | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2017-09-12 12:21:08 +12:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     ex.exception.response["Error"]["Code"].should.equal("ValidationException") | 
					
						
							|  |  |  |     ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.exception.response["Error"]["Message"].should.equal( | 
					
						
							|  |  |  |         "One or more parameter values were invalid: An AttributeValue may not contain an empty string" | 
					
						
							| 
									
										
										
										
											2017-09-13 08:28:42 +12:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-09-19 21:43:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-02 12:38:50 +09:00
										 |  |  | @requires_boto_gte("2.9") | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_item_with_empty_string_exception(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     name = "TestTable" | 
					
						
							|  |  |  |     conn = boto3.client( | 
					
						
							|  |  |  |         "dynamodb", | 
					
						
							|  |  |  |         region_name="us-west-2", | 
					
						
							|  |  |  |         aws_access_key_id="ak", | 
					
						
							|  |  |  |         aws_secret_access_key="sk", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     conn.create_table( | 
					
						
							|  |  |  |         TableName=name, | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2018-08-02 12:38:50 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     conn.put_item( | 
					
						
							|  |  |  |         TableName=name, | 
					
						
							|  |  |  |         Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "forum_name": {"S": "LOLCat Forum"}, | 
					
						
							|  |  |  |             "subject": {"S": "Check this out!"}, | 
					
						
							|  |  |  |             "Body": {"S": "http://url_to_lolcat.gif"}, | 
					
						
							|  |  |  |             "SentBy": {"S": "test"}, | 
					
						
							|  |  |  |             "ReceivedTime": {"S": "12/9/2011 11:36:03 PM"}, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2018-08-02 12:38:50 +09:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with assert_raises(ClientError) as ex: | 
					
						
							|  |  |  |         conn.update_item( | 
					
						
							|  |  |  |             TableName=name, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             Key={"forum_name": {"S": "LOLCat Forum"}}, | 
					
						
							|  |  |  |             UpdateExpression="set Body=:Body", | 
					
						
							|  |  |  |             ExpressionAttributeValues={":Body": {"S": ""}}, | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-08-02 12:38:50 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     ex.exception.response["Error"]["Code"].should.equal("ValidationException") | 
					
						
							|  |  |  |     ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.exception.response["Error"]["Message"].should.equal( | 
					
						
							|  |  |  |         "One or more parameter values were invalid: An AttributeValue may not contain an empty string" | 
					
						
							| 
									
										
										
										
											2018-08-02 12:38:50 +09:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-19 21:43:55 +01:00
										 |  |  | @requires_boto_gte("2.9") | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_query_invalid_table(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     conn = boto3.client( | 
					
						
							|  |  |  |         "dynamodb", | 
					
						
							|  |  |  |         region_name="us-west-2", | 
					
						
							|  |  |  |         aws_access_key_id="ak", | 
					
						
							|  |  |  |         aws_secret_access_key="sk", | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-09-19 21:43:55 +01:00
										 |  |  |     try: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         conn.query( | 
					
						
							|  |  |  |             TableName="invalid_table", | 
					
						
							|  |  |  |             KeyConditionExpression="index1 = :partitionkeyval", | 
					
						
							|  |  |  |             ExpressionAttributeValues={":partitionkeyval": {"S": "test"}}, | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2017-09-19 21:43:55 +01:00
										 |  |  |     except ClientError as exception: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         assert exception.response["Error"]["Code"] == "ResourceNotFoundException" | 
					
						
							| 
									
										
										
										
											2017-09-20 13:51:22 +12:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @requires_boto_gte("2.9") | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_scan_returns_consumed_capacity(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     name = "TestTable" | 
					
						
							|  |  |  |     conn = boto3.client( | 
					
						
							|  |  |  |         "dynamodb", | 
					
						
							|  |  |  |         region_name="us-west-2", | 
					
						
							|  |  |  |         aws_access_key_id="ak", | 
					
						
							|  |  |  |         aws_secret_access_key="sk", | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-09-20 13:51:22 +12:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     conn.create_table( | 
					
						
							|  |  |  |         TableName=name, | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-09-20 13:51:22 +12:00
										 |  |  | 
 | 
					
						
							|  |  |  |     conn.put_item( | 
					
						
							|  |  |  |         TableName=name, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": {"S": "LOLCat Forum"}, | 
					
						
							|  |  |  |             "subject": {"S": "Check this out!"}, | 
					
						
							|  |  |  |             "Body": {"S": "http://url_to_lolcat.gif"}, | 
					
						
							|  |  |  |             "SentBy": {"S": "test"}, | 
					
						
							|  |  |  |             "ReceivedTime": {"S": "12/9/2011 11:36:03 PM"}, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2017-09-20 13:51:22 +12:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = conn.scan(TableName=name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert "ConsumedCapacity" in response | 
					
						
							|  |  |  |     assert "CapacityUnits" in response["ConsumedCapacity"] | 
					
						
							|  |  |  |     assert response["ConsumedCapacity"]["TableName"] == name | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-14 11:16:43 -04:00
										 |  |  | @requires_boto_gte("2.9") | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_put_item_with_special_chars(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     name = "TestTable" | 
					
						
							|  |  |  |     conn = boto3.client( | 
					
						
							|  |  |  |         "dynamodb", | 
					
						
							|  |  |  |         region_name="us-west-2", | 
					
						
							|  |  |  |         aws_access_key_id="ak", | 
					
						
							|  |  |  |         aws_secret_access_key="sk", | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2018-04-14 11:16:43 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     conn.create_table( | 
					
						
							|  |  |  |         TableName=name, | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2018-04-14 11:16:43 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     conn.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName=name, | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": {"S": "LOLCat Forum"}, | 
					
						
							|  |  |  |             "subject": {"S": "Check this out!"}, | 
					
						
							|  |  |  |             "Body": {"S": "http://url_to_lolcat.gif"}, | 
					
						
							|  |  |  |             "SentBy": {"S": "test"}, | 
					
						
							|  |  |  |             "ReceivedTime": {"S": "12/9/2011 11:36:03 PM"}, | 
					
						
							|  |  |  |             '"': {"S": "foo"}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-12-20 11:30:36 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-20 11:16:17 -08:00
										 |  |  | @requires_boto_gte("2.9") | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_put_item_with_streams(): | 
					
						
							|  |  |  |     name = "TestTable" | 
					
						
							|  |  |  |     conn = boto3.client( | 
					
						
							|  |  |  |         "dynamodb", | 
					
						
							|  |  |  |         region_name="us-west-2", | 
					
						
							|  |  |  |         aws_access_key_id="ak", | 
					
						
							|  |  |  |         aws_secret_access_key="sk", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     conn.create_table( | 
					
						
							|  |  |  |         TableName=name, | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							| 
									
										
										
										
											2019-12-20 11:30:36 -08:00
										 |  |  |         StreamSpecification={ | 
					
						
							|  |  |  |             "StreamEnabled": True, | 
					
						
							|  |  |  |             "StreamViewType": "NEW_AND_OLD_IMAGES", | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2019-12-20 11:16:17 -08:00
										 |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     conn.put_item( | 
					
						
							|  |  |  |         TableName=name, | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": {"S": "LOLCat Forum"}, | 
					
						
							|  |  |  |             "subject": {"S": "Check this out!"}, | 
					
						
							|  |  |  |             "Body": {"S": "http://url_to_lolcat.gif"}, | 
					
						
							|  |  |  |             "SentBy": {"S": "test"}, | 
					
						
							| 
									
										
										
										
											2019-12-20 11:30:36 -08:00
										 |  |  |             "Data": {"M": {"Key1": {"S": "Value1"}, "Key2": {"S": "Value2"}}}, | 
					
						
							| 
									
										
										
										
											2019-12-20 11:16:17 -08:00
										 |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2018-04-14 11:16:43 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-24 10:23:46 -08:00
										 |  |  |     result = conn.get_item(TableName=name, Key={"forum_name": {"S": "LOLCat Forum"}}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result["Item"].should.be.equal( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "forum_name": {"S": "LOLCat Forum"}, | 
					
						
							|  |  |  |             "subject": {"S": "Check this out!"}, | 
					
						
							|  |  |  |             "Body": {"S": "http://url_to_lolcat.gif"}, | 
					
						
							|  |  |  |             "SentBy": {"S": "test"}, | 
					
						
							|  |  |  |             "Data": {"M": {"Key1": {"S": "Value1"}, "Key2": {"S": "Value2"}}}, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-12-24 11:01:54 -08:00
										 |  |  |     table = dynamodb_backends2["us-west-2"].get_table(name) | 
					
						
							|  |  |  |     if not table: | 
					
						
							|  |  |  |         # There is no way to access stream data over the API, so this part can't run in server-tests mode. | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     len(table.stream_shard.items).should.be.equal(1) | 
					
						
							|  |  |  |     stream_record = table.stream_shard.items[0].record | 
					
						
							| 
									
										
										
										
											2019-12-24 10:23:46 -08:00
										 |  |  |     stream_record["eventName"].should.be.equal("INSERT") | 
					
						
							|  |  |  |     stream_record["dynamodb"]["SizeBytes"].should.be.equal(447) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-14 11:16:43 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  | @requires_boto_gte("2.9") | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_query_returns_consumed_capacity(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     table = dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="users", | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  |         KeySchema=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "KeyType": "RANGE"}, | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  |         ], | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "AttributeType": "S"}, | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("users") | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={"forum_name": "the-key", "subject": "123", "body": "some test message"} | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     results = table.query(KeyConditionExpression=Key("forum_name").eq("the-key")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert "ConsumedCapacity" in results | 
					
						
							|  |  |  |     assert "CapacityUnits" in results["ConsumedCapacity"] | 
					
						
							|  |  |  |     assert results["ConsumedCapacity"]["CapacityUnits"] == 1 | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  | @mock_dynamodb2 | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | def test_basic_projection_expression_using_get_item(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     table = dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="users", | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  |         KeySchema=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "KeyType": "RANGE"}, | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  |         ], | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "AttributeType": "S"}, | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("users") | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={"forum_name": "the-key", "subject": "123", "body": "some test message"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "not-the-key", | 
					
						
							|  |  |  |             "subject": "123", | 
					
						
							|  |  |  |             "body": "some other test message", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  |     result = table.get_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         Key={"forum_name": "the-key", "subject": "123"}, | 
					
						
							|  |  |  |         ProjectionExpression="body, subject", | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result["Item"].should.be.equal({"subject": "123", "body": "some test message"}) | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # The projection expression should not remove data from storage | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result = table.get_item(Key={"forum_name": "the-key", "subject": "123"}) | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result["Item"].should.be.equal( | 
					
						
							|  |  |  |         {"forum_name": "the-key", "subject": "123", "body": "some test message"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_basic_projection_expressions_using_query(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     table = dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="users", | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  |         KeySchema=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "KeyType": "RANGE"}, | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  |         ], | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "AttributeType": "S"}, | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("users") | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={"forum_name": "the-key", "subject": "123", "body": "some test message"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "not-the-key", | 
					
						
							|  |  |  |             "subject": "123", | 
					
						
							|  |  |  |             "body": "some other test message", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  |     # Test a query returning all items | 
					
						
							|  |  |  |     results = table.query( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         KeyConditionExpression=Key("forum_name").eq("the-key"), | 
					
						
							|  |  |  |         ProjectionExpression="body, subject", | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "body" in results["Items"][0] | 
					
						
							|  |  |  |     assert results["Items"][0]["body"] == "some test message" | 
					
						
							|  |  |  |     assert "subject" in results["Items"][0] | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "the-key", | 
					
						
							|  |  |  |             "subject": "1234", | 
					
						
							|  |  |  |             "body": "yet another test message", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  | 
 | 
					
						
							|  |  |  |     results = table.query( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         KeyConditionExpression=Key("forum_name").eq("the-key"), | 
					
						
							|  |  |  |         ProjectionExpression="body", | 
					
						
							| 
									
										
										
										
											2017-09-22 13:12:11 +12:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "body" in results["Items"][0] | 
					
						
							|  |  |  |     assert "subject" not in results["Items"][0] | 
					
						
							|  |  |  |     assert results["Items"][0]["body"] == "some test message" | 
					
						
							|  |  |  |     assert "body" in results["Items"][1] | 
					
						
							|  |  |  |     assert "subject" not in results["Items"][1] | 
					
						
							|  |  |  |     assert results["Items"][1]["body"] == "yet another test message" | 
					
						
							| 
									
										
										
										
											2017-09-22 15:40:30 +12:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-10 21:35:01 -08:00
										 |  |  |     # The projection expression should not remove data from storage | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     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] | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_basic_projection_expressions_using_scan(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     table = dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="users", | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  |         KeySchema=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "KeyType": "RANGE"}, | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  |         ], | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "AttributeType": "S"}, | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("users") | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={"forum_name": "the-key", "subject": "123", "body": "some test message"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "not-the-key", | 
					
						
							|  |  |  |             "subject": "123", | 
					
						
							|  |  |  |             "body": "some other test message", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-06-27 19:37:46 +01:00
										 |  |  |     # Test a scan returning all items | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  |     results = table.scan( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         FilterExpression=Key("forum_name").eq("the-key"), | 
					
						
							|  |  |  |         ProjectionExpression="body, subject", | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "body" in results["Items"][0] | 
					
						
							|  |  |  |     assert results["Items"][0]["body"] == "some test message" | 
					
						
							|  |  |  |     assert "subject" in results["Items"][0] | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "the-key", | 
					
						
							|  |  |  |             "subject": "1234", | 
					
						
							|  |  |  |             "body": "yet another test message", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     results = table.scan( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         FilterExpression=Key("forum_name").eq("the-key"), ProjectionExpression="body" | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     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] | 
					
						
							| 
									
										
										
										
											2019-06-26 21:54:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # The projection expression should not remove data from storage | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     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] | 
					
						
							| 
									
										
										
										
											2017-11-10 21:35:01 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_nested_projection_expression_using_get_item(): | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     dynamodb.create_table( | 
					
						
							|  |  |  |         TableName="users", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table = dynamodb.Table("users") | 
					
						
							|  |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "key1", | 
					
						
							|  |  |  |             "nested": { | 
					
						
							|  |  |  |                 "level1": {"id": "id1", "att": "irrelevant"}, | 
					
						
							|  |  |  |                 "level2": {"id": "id2", "include": "all"}, | 
					
						
							|  |  |  |                 "level3": {"id": "irrelevant"}, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "key2", | 
					
						
							|  |  |  |             "nested": {"id": "id2", "incode": "code2"}, | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Test a get_item returning all items | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     result = table.get_item( | 
					
						
							|  |  |  |         Key={"forum_name": "key1"}, | 
					
						
							|  |  |  |         ProjectionExpression="nested.level1.id, nested.level2", | 
					
						
							|  |  |  |     )["Item"] | 
					
						
							|  |  |  |     result.should.equal( | 
					
						
							|  |  |  |         {"nested": {"level1": {"id": "id1"}, "level2": {"id": "id2", "include": "all"}}} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  |     # Assert actual data has not been deleted | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     result = table.get_item(Key={"forum_name": "key1"})["Item"] | 
					
						
							|  |  |  |     result.should.equal( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |             "forum_name": "key1", | 
					
						
							|  |  |  |             "nested": { | 
					
						
							|  |  |  |                 "level1": {"id": "id1", "att": "irrelevant"}, | 
					
						
							|  |  |  |                 "level2": {"id": "id2", "include": "all"}, | 
					
						
							|  |  |  |                 "level3": {"id": "irrelevant"}, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_basic_projection_expressions_using_query(): | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     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", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Test a query returning all items | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     result = table.query( | 
					
						
							|  |  |  |         KeyConditionExpression=Key("forum_name").eq("the-key"), | 
					
						
							|  |  |  |         ProjectionExpression="body, subject", | 
					
						
							|  |  |  |     )["Items"][0] | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     assert "body" in result | 
					
						
							|  |  |  |     assert result["body"] == "some test message" | 
					
						
							|  |  |  |     assert "subject" in result | 
					
						
							|  |  |  |     assert "forum_name" not in result | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "the-key", | 
					
						
							|  |  |  |             "subject": "1234", | 
					
						
							|  |  |  |             "body": "yet another test message", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     items = table.query( | 
					
						
							|  |  |  |         KeyConditionExpression=Key("forum_name").eq("the-key"), | 
					
						
							|  |  |  |         ProjectionExpression="body", | 
					
						
							|  |  |  |     )["Items"] | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     assert "body" in items[0] | 
					
						
							|  |  |  |     assert "subject" not in items[0] | 
					
						
							|  |  |  |     assert items[0]["body"] == "some test message" | 
					
						
							|  |  |  |     assert "body" in items[1] | 
					
						
							|  |  |  |     assert "subject" not in items[1] | 
					
						
							|  |  |  |     assert items[1]["body"] == "yet another test message" | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # The projection expression should not remove data from storage | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     items = table.query(KeyConditionExpression=Key("forum_name").eq("the-key"))["Items"] | 
					
						
							|  |  |  |     assert "subject" in items[0] | 
					
						
							|  |  |  |     assert "body" in items[1] | 
					
						
							|  |  |  |     assert "forum_name" in items[1] | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_nested_projection_expression_using_query(): | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     dynamodb.create_table( | 
					
						
							|  |  |  |         TableName="users", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table = dynamodb.Table("users") | 
					
						
							|  |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "key1", | 
					
						
							|  |  |  |             "nested": { | 
					
						
							|  |  |  |                 "level1": {"id": "id1", "att": "irrelevant"}, | 
					
						
							|  |  |  |                 "level2": {"id": "id2", "include": "all"}, | 
					
						
							|  |  |  |                 "level3": {"id": "irrelevant"}, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "key2", | 
					
						
							|  |  |  |             "nested": {"id": "id2", "incode": "code2"}, | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Test a query returning all items | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     result = table.query( | 
					
						
							|  |  |  |         KeyConditionExpression=Key("forum_name").eq("key1"), | 
					
						
							|  |  |  |         ProjectionExpression="nested.level1.id, nested.level2", | 
					
						
							|  |  |  |     )["Items"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert "nested" in result | 
					
						
							|  |  |  |     result["nested"].should.equal( | 
					
						
							|  |  |  |         {"level1": {"id": "id1"}, "level2": {"id": "id2", "include": "all"}} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     assert "foo" not in result | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  |     # Assert actual data has not been deleted | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     result = table.query(KeyConditionExpression=Key("forum_name").eq("key1"))["Items"][ | 
					
						
							|  |  |  |         0 | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     result.should.equal( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |             "forum_name": "key1", | 
					
						
							|  |  |  |             "nested": { | 
					
						
							|  |  |  |                 "level1": {"id": "id1", "att": "irrelevant"}, | 
					
						
							|  |  |  |                 "level2": {"id": "id2", "include": "all"}, | 
					
						
							|  |  |  |                 "level3": {"id": "irrelevant"}, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_basic_projection_expressions_using_scan(): | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     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", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  |     # Test a scan returning all items | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     results = table.scan( | 
					
						
							|  |  |  |         FilterExpression=Key("forum_name").eq("the-key"), | 
					
						
							|  |  |  |         ProjectionExpression="body, subject", | 
					
						
							|  |  |  |     )["Items"] | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     results.should.equal([{"body": "some test message", "subject": "123"}]) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "the-key", | 
					
						
							|  |  |  |             "subject": "1234", | 
					
						
							|  |  |  |             "body": "yet another test message", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     results = table.scan( | 
					
						
							|  |  |  |         FilterExpression=Key("forum_name").eq("the-key"), ProjectionExpression="body" | 
					
						
							|  |  |  |     )["Items"] | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     assert {"body": "some test message"} in results | 
					
						
							|  |  |  |     assert {"body": "yet another test message"} in results | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # The projection expression should not remove data from storage | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     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] | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_nested_projection_expression_using_scan(): | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     dynamodb.create_table( | 
					
						
							|  |  |  |         TableName="users", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table = dynamodb.Table("users") | 
					
						
							|  |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "key1", | 
					
						
							|  |  |  |             "nested": { | 
					
						
							|  |  |  |                 "level1": {"id": "id1", "att": "irrelevant"}, | 
					
						
							|  |  |  |                 "level2": {"id": "id2", "include": "all"}, | 
					
						
							|  |  |  |                 "level3": {"id": "irrelevant"}, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "key2", | 
					
						
							|  |  |  |             "nested": {"id": "id2", "incode": "code2"}, | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Test a scan | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     results = table.scan( | 
					
						
							|  |  |  |         FilterExpression=Key("forum_name").eq("key1"), | 
					
						
							|  |  |  |         ProjectionExpression="nested.level1.id, nested.level2", | 
					
						
							|  |  |  |     )["Items"] | 
					
						
							|  |  |  |     results.should.equal( | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 "nested": { | 
					
						
							|  |  |  |                     "level1": {"id": "id1"}, | 
					
						
							|  |  |  |                     "level2": {"include": "all", "id": "id2"}, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  |     # Assert original data is still there | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     results = table.scan(FilterExpression=Key("forum_name").eq("key1"))["Items"] | 
					
						
							|  |  |  |     results.should.equal( | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 "forum_name": "key1", | 
					
						
							|  |  |  |                 "foo": "bar", | 
					
						
							|  |  |  |                 "nested": { | 
					
						
							|  |  |  |                     "level1": {"att": "irrelevant", "id": "id1"}, | 
					
						
							|  |  |  |                     "level2": {"include": "all", "id": "id2"}, | 
					
						
							|  |  |  |                     "level3": {"id": "irrelevant"}, | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-22 15:40:30 +12:00
										 |  |  | @mock_dynamodb2 | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | def test_basic_projection_expression_using_get_item_with_attr_expression_names(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     table = dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="users", | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  |         KeySchema=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "KeyType": "RANGE"}, | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  |         ], | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "AttributeType": "S"}, | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         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", | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     result = table.get_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         Key={"forum_name": "the-key", "subject": "123"}, | 
					
						
							|  |  |  |         ProjectionExpression="#rl, #rt, subject", | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#rl": "body", "#rt": "attachment"}, | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result["Item"].should.be.equal( | 
					
						
							|  |  |  |         {"subject": "123", "body": "some test message", "attachment": "something"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_basic_projection_expressions_using_query_with_attr_expression_names(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-09-22 15:40:30 +12:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     table = dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="users", | 
					
						
							| 
									
										
										
										
											2017-09-22 15:40:30 +12:00
										 |  |  |         KeySchema=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "KeyType": "RANGE"}, | 
					
						
							| 
									
										
										
										
											2017-09-22 15:40:30 +12:00
										 |  |  |         ], | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "AttributeType": "S"}, | 
					
						
							| 
									
										
										
										
											2017-09-22 15:40:30 +12:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         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", | 
					
						
							| 
									
										
										
										
											2017-09-22 15:40:30 +12:00
										 |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     # Test a query returning all items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     results = table.query( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         KeyConditionExpression=Key("forum_name").eq("the-key"), | 
					
						
							|  |  |  |         ProjectionExpression="#rl, #rt, subject", | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#rl": "body", "#rt": "attachment"}, | 
					
						
							| 
									
										
										
										
											2017-09-22 15:40:30 +12:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "body" in results["Items"][0] | 
					
						
							|  |  |  |     assert results["Items"][0]["body"] == "some test message" | 
					
						
							|  |  |  |     assert "subject" in results["Items"][0] | 
					
						
							|  |  |  |     assert results["Items"][0]["subject"] == "123" | 
					
						
							|  |  |  |     assert "attachment" in results["Items"][0] | 
					
						
							|  |  |  |     assert results["Items"][0]["attachment"] == "something" | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_nested_projection_expression_using_get_item_with_attr_expression(): | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     dynamodb.create_table( | 
					
						
							|  |  |  |         TableName="users", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table = dynamodb.Table("users") | 
					
						
							|  |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "key1", | 
					
						
							|  |  |  |             "nested": { | 
					
						
							|  |  |  |                 "level1": {"id": "id1", "att": "irrelevant"}, | 
					
						
							|  |  |  |                 "level2": {"id": "id2", "include": "all"}, | 
					
						
							|  |  |  |                 "level3": {"id": "irrelevant"}, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "key2", | 
					
						
							|  |  |  |             "nested": {"id": "id2", "incode": "code2"}, | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Test a get_item returning all items | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     result = table.get_item( | 
					
						
							|  |  |  |         Key={"forum_name": "key1"}, | 
					
						
							|  |  |  |         ProjectionExpression="#nst.level1.id, #nst.#lvl2", | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#nst": "nested", "#lvl2": "level2"}, | 
					
						
							|  |  |  |     )["Item"] | 
					
						
							|  |  |  |     result.should.equal( | 
					
						
							|  |  |  |         {"nested": {"level1": {"id": "id1"}, "level2": {"id": "id2", "include": "all"}}} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  |     # Assert actual data has not been deleted | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     result = table.get_item(Key={"forum_name": "key1"})["Item"] | 
					
						
							|  |  |  |     result.should.equal( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |             "forum_name": "key1", | 
					
						
							|  |  |  |             "nested": { | 
					
						
							|  |  |  |                 "level1": {"id": "id1", "att": "irrelevant"}, | 
					
						
							|  |  |  |                 "level2": {"id": "id2", "include": "all"}, | 
					
						
							|  |  |  |                 "level3": {"id": "irrelevant"}, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_nested_projection_expression_using_query_with_attr_expression_names(): | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     dynamodb.create_table( | 
					
						
							|  |  |  |         TableName="users", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table = dynamodb.Table("users") | 
					
						
							|  |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "key1", | 
					
						
							|  |  |  |             "nested": { | 
					
						
							|  |  |  |                 "level1": {"id": "id1", "att": "irrelevant"}, | 
					
						
							|  |  |  |                 "level2": {"id": "id2", "include": "all"}, | 
					
						
							|  |  |  |                 "level3": {"id": "irrelevant"}, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "key2", | 
					
						
							|  |  |  |             "nested": {"id": "id2", "incode": "code2"}, | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Test a query returning all items | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     result = table.query( | 
					
						
							|  |  |  |         KeyConditionExpression=Key("forum_name").eq("key1"), | 
					
						
							|  |  |  |         ProjectionExpression="#nst.level1.id, #nst.#lvl2", | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#nst": "nested", "#lvl2": "level2"}, | 
					
						
							|  |  |  |     )["Items"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert "nested" in result | 
					
						
							|  |  |  |     result["nested"].should.equal( | 
					
						
							|  |  |  |         {"level1": {"id": "id1"}, "level2": {"id": "id2", "include": "all"}} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     assert "foo" not in result | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  |     # Assert actual data has not been deleted | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     result = table.query(KeyConditionExpression=Key("forum_name").eq("key1"))["Items"][ | 
					
						
							|  |  |  |         0 | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     result.should.equal( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |             "forum_name": "key1", | 
					
						
							|  |  |  |             "nested": { | 
					
						
							|  |  |  |                 "level1": {"id": "id1", "att": "irrelevant"}, | 
					
						
							|  |  |  |                 "level2": {"id": "id2", "include": "all"}, | 
					
						
							|  |  |  |                 "level3": {"id": "irrelevant"}, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-27 19:37:46 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_basic_projection_expressions_using_scan_with_attr_expression_names(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-06-27 19:37:46 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     table = dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="users", | 
					
						
							| 
									
										
										
										
											2019-06-27 19:37:46 +01:00
										 |  |  |         KeySchema=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "KeyType": "RANGE"}, | 
					
						
							| 
									
										
										
										
											2019-06-27 19:37:46 +01:00
										 |  |  |         ], | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "AttributeType": "S"}, | 
					
						
							| 
									
										
										
										
											2019-06-27 19:37:46 +01:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         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", | 
					
						
							| 
									
										
										
										
											2019-06-27 19:37:46 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     # Test a scan returning all items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     results = table.scan( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         FilterExpression=Key("forum_name").eq("the-key"), | 
					
						
							|  |  |  |         ProjectionExpression="#rl, #rt, subject", | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#rl": "body", "#rt": "attachment"}, | 
					
						
							| 
									
										
										
										
											2019-06-27 19:37:46 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     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] | 
					
						
							| 
									
										
										
										
											2019-06-27 19:37:46 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Test without a FilterExpression | 
					
						
							|  |  |  |     results = table.scan( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ProjectionExpression="#rl, #rt, subject", | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#rl": "body", "#rt": "attachment"}, | 
					
						
							| 
									
										
										
										
											2019-06-27 19:37:46 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     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] | 
					
						
							| 
									
										
										
										
											2019-06-27 19:37:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_nested_projection_expression_using_scan_with_attr_expression_names(): | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     dynamodb.create_table( | 
					
						
							|  |  |  |         TableName="users", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table = dynamodb.Table("users") | 
					
						
							|  |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "key1", | 
					
						
							|  |  |  |             "nested": { | 
					
						
							|  |  |  |                 "level1": {"id": "id1", "att": "irrelevant"}, | 
					
						
							|  |  |  |                 "level2": {"id": "id2", "include": "all"}, | 
					
						
							|  |  |  |                 "level3": {"id": "irrelevant"}, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "key2", | 
					
						
							|  |  |  |             "nested": {"id": "id2", "incode": "code2"}, | 
					
						
							|  |  |  |             "foo": "bar", | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Test a scan | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     results = table.scan( | 
					
						
							|  |  |  |         FilterExpression=Key("forum_name").eq("key1"), | 
					
						
							|  |  |  |         ProjectionExpression="nested.level1.id, nested.level2", | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#nst": "nested", "#lvl2": "level2"}, | 
					
						
							|  |  |  |     )["Items"] | 
					
						
							|  |  |  |     results.should.equal( | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 "nested": { | 
					
						
							|  |  |  |                     "level1": {"id": "id1"}, | 
					
						
							|  |  |  |                     "level2": {"include": "all", "id": "id2"}, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  |     # Assert original data is still there | 
					
						
							| 
									
										
										
										
											2019-11-03 07:33:27 -08:00
										 |  |  |     results = table.scan(FilterExpression=Key("forum_name").eq("key1"))["Items"] | 
					
						
							|  |  |  |     results.should.equal( | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 "forum_name": "key1", | 
					
						
							|  |  |  |                 "foo": "bar", | 
					
						
							|  |  |  |                 "nested": { | 
					
						
							|  |  |  |                     "level1": {"att": "irrelevant", "id": "id1"}, | 
					
						
							|  |  |  |                     "level2": {"include": "all", "id": "id2"}, | 
					
						
							|  |  |  |                     "level3": {"id": "irrelevant"}, | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-03 14:02:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_put_item_returns_consumed_capacity(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     table = dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="users", | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  |         KeySchema=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "KeyType": "RANGE"}, | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  |         ], | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "AttributeType": "S"}, | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("users") | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = table.put_item( | 
					
						
							|  |  |  |         Item={"forum_name": "the-key", "subject": "123", "body": "some test message"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "ConsumedCapacity" in response | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_item_returns_consumed_capacity(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     table = dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="users", | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  |         KeySchema=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "KeyType": "RANGE"}, | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  |         ], | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "AttributeType": "S"}, | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("users") | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={"forum_name": "the-key", "subject": "123", "body": "some test message"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = table.update_item( | 
					
						
							|  |  |  |         Key={"forum_name": "the-key", "subject": "123"}, | 
					
						
							|  |  |  |         UpdateExpression="set body=:tb", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":tb": "a new message"}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-09-25 11:39:09 +13:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "ConsumedCapacity" in response | 
					
						
							|  |  |  |     assert "CapacityUnits" in response["ConsumedCapacity"] | 
					
						
							|  |  |  |     assert "TableName" in response["ConsumedCapacity"] | 
					
						
							| 
									
										
										
										
											2017-09-25 11:44:10 +13:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-25 11:44:10 +13:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_get_item_returns_consumed_capacity(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-09-25 11:44:10 +13:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     table = dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="users", | 
					
						
							| 
									
										
										
										
											2017-09-25 11:44:10 +13:00
										 |  |  |         KeySchema=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "KeyType": "RANGE"}, | 
					
						
							| 
									
										
										
										
											2017-09-25 11:44:10 +13:00
										 |  |  |         ], | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "AttributeType": "S"}, | 
					
						
							| 
									
										
										
										
											2017-09-25 11:44:10 +13:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							| 
									
										
										
										
											2017-09-25 11:44:10 +13:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("users") | 
					
						
							| 
									
										
										
										
											2017-09-25 11:44:10 +13:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={"forum_name": "the-key", "subject": "123", "body": "some test message"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-09-25 11:44:10 +13:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = table.get_item(Key={"forum_name": "the-key", "subject": "123"}) | 
					
						
							| 
									
										
										
										
											2017-09-25 11:44:10 +13:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "ConsumedCapacity" in response | 
					
						
							|  |  |  |     assert "CapacityUnits" in response["ConsumedCapacity"] | 
					
						
							|  |  |  |     assert "TableName" in response["ConsumedCapacity"] | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def test_filter_expression(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     row1 = moto.dynamodb2.models.Item( | 
					
						
							|  |  |  |         None, | 
					
						
							|  |  |  |         None, | 
					
						
							|  |  |  |         None, | 
					
						
							|  |  |  |         None, | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "Id": {"N": "8"}, | 
					
						
							|  |  |  |             "Subs": {"N": "5"}, | 
					
						
							|  |  |  |             "Desc": {"S": "Some description"}, | 
					
						
							|  |  |  |             "KV": {"SS": ["test1", "test2"]}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     row2 = moto.dynamodb2.models.Item( | 
					
						
							|  |  |  |         None, | 
					
						
							|  |  |  |         None, | 
					
						
							|  |  |  |         None, | 
					
						
							|  |  |  |         None, | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "Id": {"N": "8"}, | 
					
						
							|  |  |  |             "Subs": {"N": "10"}, | 
					
						
							|  |  |  |             "Desc": {"S": "A description"}, | 
					
						
							|  |  |  |             "KV": {"SS": ["test3", "test4"]}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-22 23:20:00 +01:00
										 |  |  |     # NOT test 1 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     filter_expr = moto.dynamodb2.comparisons.get_filter_expression( | 
					
						
							|  |  |  |         "NOT attribute_not_exists(Id)", {}, {} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-10-22 23:20:00 +01:00
										 |  |  |     filter_expr.expr(row1).should.be(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # NOT test 2 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     filter_expr = moto.dynamodb2.comparisons.get_filter_expression( | 
					
						
							|  |  |  |         "NOT (Id = :v0)", {}, {":v0": {"N": "8"}} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-10-22 23:20:00 +01:00
										 |  |  |     filter_expr.expr(row1).should.be(False)  # Id = 8 so should be false | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     # AND test | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     filter_expr = moto.dynamodb2.comparisons.get_filter_expression( | 
					
						
							|  |  |  |         "Id > :v0 AND Subs < :v1", {}, {":v0": {"N": "5"}, ":v1": {"N": "7"}} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     filter_expr.expr(row1).should.be(True) | 
					
						
							|  |  |  |     filter_expr.expr(row2).should.be(False) | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     # OR test | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     filter_expr = moto.dynamodb2.comparisons.get_filter_expression( | 
					
						
							|  |  |  |         "Id = :v0 OR Id=:v1", {}, {":v0": {"N": "5"}, ":v1": {"N": "8"}} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     filter_expr.expr(row1).should.be(True) | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     # BETWEEN test | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     filter_expr = moto.dynamodb2.comparisons.get_filter_expression( | 
					
						
							|  |  |  |         "Id BETWEEN :v0 AND :v1", {}, {":v0": {"N": "5"}, ":v1": {"N": "10"}} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     filter_expr.expr(row1).should.be(True) | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     # PAREN test | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     filter_expr = moto.dynamodb2.comparisons.get_filter_expression( | 
					
						
							|  |  |  |         "Id = :v0 AND (Subs = :v0 OR Subs = :v1)", | 
					
						
							|  |  |  |         {}, | 
					
						
							|  |  |  |         {":v0": {"N": "8"}, ":v1": {"N": "5"}}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     filter_expr.expr(row1).should.be(True) | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     # IN test | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     filter_expr = moto.dynamodb2.comparisons.get_filter_expression( | 
					
						
							|  |  |  |         "Id IN (:v0, :v1, :v2)", | 
					
						
							|  |  |  |         {}, | 
					
						
							|  |  |  |         {":v0": {"N": "7"}, ":v1": {"N": "8"}, ":v2": {"N": "9"}}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     filter_expr.expr(row1).should.be(True) | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-12 16:59:52 +09:00
										 |  |  |     # attribute function tests (with extra spaces) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     filter_expr = moto.dynamodb2.comparisons.get_filter_expression( | 
					
						
							|  |  |  |         "attribute_exists(Id) AND attribute_not_exists (User)", {}, {} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     filter_expr.expr(row1).should.be(True) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     filter_expr = moto.dynamodb2.comparisons.get_filter_expression( | 
					
						
							|  |  |  |         "attribute_type(Id, :v0)", {}, {":v0": {"S": "N"}} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     filter_expr.expr(row1).should.be(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # beginswith function test | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     filter_expr = moto.dynamodb2.comparisons.get_filter_expression( | 
					
						
							|  |  |  |         "begins_with(Desc, :v0)", {}, {":v0": {"S": "Some"}} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     filter_expr.expr(row1).should.be(True) | 
					
						
							|  |  |  |     filter_expr.expr(row2).should.be(False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # contains function test | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     filter_expr = moto.dynamodb2.comparisons.get_filter_expression( | 
					
						
							|  |  |  |         "contains(KV, :v0)", {}, {":v0": {"S": "test1"}} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     filter_expr.expr(row1).should.be(True) | 
					
						
							|  |  |  |     filter_expr.expr(row2).should.be(False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # size function test | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     filter_expr = moto.dynamodb2.comparisons.get_filter_expression( | 
					
						
							|  |  |  |         "size(Desc) > size(KV)", {}, {} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     filter_expr.expr(row1).should.be(True) | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-22 23:20:00 +01:00
										 |  |  |     # Expression from @batkuip | 
					
						
							|  |  |  |     filter_expr = moto.dynamodb2.comparisons.get_filter_expression( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         "(#n0 < :v0 AND attribute_not_exists(#n1))", | 
					
						
							|  |  |  |         {"#n0": "Subs", "#n1": "fanout_ts"}, | 
					
						
							|  |  |  |         {":v0": {"N": "7"}}, | 
					
						
							| 
									
										
										
										
											2017-10-22 23:20:00 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  |     filter_expr.expr(row1).should.be(True) | 
					
						
							| 
									
										
										
										
											2018-04-09 13:42:50 +05:30
										 |  |  |     # Expression from to check contains on string value | 
					
						
							|  |  |  |     filter_expr = moto.dynamodb2.comparisons.get_filter_expression( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         "contains(#n0, :v0)", {"#n0": "Desc"}, {":v0": {"S": "Some"}} | 
					
						
							| 
									
										
										
										
											2018-04-09 13:42:50 +05:30
										 |  |  |     ) | 
					
						
							|  |  |  |     filter_expr.expr(row1).should.be(True) | 
					
						
							|  |  |  |     filter_expr.expr(row2).should.be(False) | 
					
						
							| 
									
										
										
										
											2017-10-22 23:20:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 22:53:31 +00:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_query_filter(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-11-08 22:53:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "AttributeType": "S"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							| 
									
										
										
										
											2017-11-08 22:53:31 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							| 
									
										
										
										
											2017-11-08 22:53:31 +00:00
										 |  |  |         Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "client": {"S": "client1"}, | 
					
						
							|  |  |  |             "app": {"S": "app1"}, | 
					
						
							|  |  |  |             "nested": { | 
					
						
							|  |  |  |                 "M": { | 
					
						
							|  |  |  |                     "version": {"S": "version1"}, | 
					
						
							|  |  |  |                     "contents": {"L": [{"S": "value1"}, {"S": "value2"}]}, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2017-11-08 22:53:31 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							| 
									
										
										
										
											2017-11-08 22:53:31 +00:00
										 |  |  |         Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "client": {"S": "client1"}, | 
					
						
							|  |  |  |             "app": {"S": "app2"}, | 
					
						
							|  |  |  |             "nested": { | 
					
						
							|  |  |  |                 "M": { | 
					
						
							|  |  |  |                     "version": {"S": "version2"}, | 
					
						
							|  |  |  |                     "contents": {"L": [{"S": "value1"}, {"S": "value2"}]}, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2017-11-08 22:53:31 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("test1") | 
					
						
							|  |  |  |     response = table.query(KeyConditionExpression=Key("client").eq("client1")) | 
					
						
							|  |  |  |     assert response["Count"] == 2 | 
					
						
							| 
									
										
										
										
											2017-11-08 22:53:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     response = table.query( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         KeyConditionExpression=Key("client").eq("client1"), | 
					
						
							|  |  |  |         FilterExpression=Attr("app").eq("app2"), | 
					
						
							| 
									
										
										
										
											2017-11-08 22:53:31 +00:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert response["Count"] == 1 | 
					
						
							|  |  |  |     assert response["Items"][0]["app"] == "app2" | 
					
						
							| 
									
										
										
										
											2018-04-09 13:42:50 +05:30
										 |  |  |     response = table.query( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         KeyConditionExpression=Key("client").eq("client1"), | 
					
						
							|  |  |  |         FilterExpression=Attr("app").contains("app"), | 
					
						
							| 
									
										
										
										
											2018-04-09 13:42:50 +05:30
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert response["Count"] == 2 | 
					
						
							| 
									
										
										
										
											2017-11-08 22:53:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 15:15:20 -04:00
										 |  |  |     response = table.query( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         KeyConditionExpression=Key("client").eq("client1"), | 
					
						
							|  |  |  |         FilterExpression=Attr("nested.version").contains("version"), | 
					
						
							| 
									
										
										
										
											2019-04-01 15:15:20 -04:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert response["Count"] == 2 | 
					
						
							| 
									
										
										
										
											2019-04-01 15:15:20 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     response = table.query( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         KeyConditionExpression=Key("client").eq("client1"), | 
					
						
							|  |  |  |         FilterExpression=Attr("nested.contents[0]").eq("value1"), | 
					
						
							| 
									
										
										
										
											2019-04-01 15:15:20 -04:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert response["Count"] == 2 | 
					
						
							| 
									
										
										
										
											2019-04-01 15:15:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 22:53:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-09 19:08:16 -04:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_query_filter_overlapping_expression_prefixes(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-09-09 19:08:16 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "AttributeType": "S"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							| 
									
										
										
										
											2019-09-09 19:08:16 -04:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							| 
									
										
										
										
											2019-09-09 19:08:16 -04:00
										 |  |  |         Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "client": {"S": "client1"}, | 
					
						
							|  |  |  |             "app": {"S": "app1"}, | 
					
						
							|  |  |  |             "nested": { | 
					
						
							|  |  |  |                 "M": { | 
					
						
							|  |  |  |                     "version": {"S": "version1"}, | 
					
						
							|  |  |  |                     "contents": {"L": [{"S": "value1"}, {"S": "value2"}]}, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     table = dynamodb.Table("test1") | 
					
						
							| 
									
										
										
										
											2019-09-09 19:08:16 -04:00
										 |  |  |     response = table.query( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         KeyConditionExpression=Key("client").eq("client1") & Key("app").eq("app1"), | 
					
						
							|  |  |  |         ProjectionExpression="#1, #10, nested", | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#1": "client", "#10": "app"}, | 
					
						
							| 
									
										
										
										
											2019-09-09 19:08:16 -04:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert response["Count"] == 1 | 
					
						
							|  |  |  |     assert response["Items"][0] == { | 
					
						
							|  |  |  |         "client": "client1", | 
					
						
							|  |  |  |         "app": "app1", | 
					
						
							|  |  |  |         "nested": {"version": "version1", "contents": ["value1", "value2"]}, | 
					
						
							| 
									
										
										
										
											2019-09-09 19:08:16 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_scan_filter(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "AttributeType": "S"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", Item={"client": {"S": "client1"}, "app": {"S": "app1"}} | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("test1") | 
					
						
							|  |  |  |     response = table.scan(FilterExpression=Attr("app").eq("app2")) | 
					
						
							|  |  |  |     assert response["Count"] == 0 | 
					
						
							| 
									
										
										
										
											2017-10-07 21:57:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = table.scan(FilterExpression=Attr("app").eq("app1")) | 
					
						
							|  |  |  |     assert response["Count"] == 1 | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = table.scan(FilterExpression=Attr("app").ne("app2")) | 
					
						
							|  |  |  |     assert response["Count"] == 1 | 
					
						
							| 
									
										
										
										
											2018-10-23 15:37:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = table.scan(FilterExpression=Attr("app").ne("app1")) | 
					
						
							|  |  |  |     assert response["Count"] == 0 | 
					
						
							| 
									
										
										
										
											2018-10-23 15:37:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-16 21:56:03 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_scan_filter2(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-10-16 21:56:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "AttributeType": "N"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							| 
									
										
										
										
											2017-10-16 21:56:03 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", Item={"client": {"S": "client1"}, "app": {"N": "1"}} | 
					
						
							| 
									
										
										
										
											2017-10-16 21:56:03 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     response = client.scan( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         Select="ALL_ATTRIBUTES", | 
					
						
							|  |  |  |         FilterExpression="#tb >= :dt", | 
					
						
							| 
									
										
										
										
											2017-10-16 21:56:03 +01:00
										 |  |  |         ExpressionAttributeNames={"#tb": "app"}, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ExpressionAttributeValues={":dt": {"N": str(1)}}, | 
					
						
							| 
									
										
										
										
											2017-10-16 21:56:03 +01:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert response["Count"] == 1 | 
					
						
							| 
									
										
										
										
											2017-10-16 21:56:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_scan_filter3(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-10-16 21:56:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "AttributeType": "N"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							| 
									
										
										
										
											2017-10-16 21:56:03 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         Item={"client": {"S": "client1"}, "app": {"N": "1"}, "active": {"BOOL": True}}, | 
					
						
							| 
									
										
										
										
											2017-10-16 21:56:03 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("test1") | 
					
						
							|  |  |  |     response = table.scan(FilterExpression=Attr("active").eq(True)) | 
					
						
							|  |  |  |     assert response["Count"] == 1 | 
					
						
							| 
									
										
										
										
											2017-10-16 21:56:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = table.scan(FilterExpression=Attr("active").ne(True)) | 
					
						
							|  |  |  |     assert response["Count"] == 0 | 
					
						
							| 
									
										
										
										
											2018-10-23 15:37:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = table.scan(FilterExpression=Attr("active").ne(False)) | 
					
						
							|  |  |  |     assert response["Count"] == 1 | 
					
						
							| 
									
										
										
										
											2018-10-23 15:37:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = table.scan(FilterExpression=Attr("app").ne(1)) | 
					
						
							|  |  |  |     assert response["Count"] == 0 | 
					
						
							| 
									
										
										
										
											2018-10-23 15:37:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = table.scan(FilterExpression=Attr("app").ne(2)) | 
					
						
							|  |  |  |     assert response["Count"] == 1 | 
					
						
							| 
									
										
										
										
											2018-10-23 15:37:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-16 21:56:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-22 23:20:00 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_scan_filter4(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-10-22 23:20:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "AttributeType": "N"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							| 
									
										
										
										
											2017-10-22 23:20:00 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("test1") | 
					
						
							| 
									
										
										
										
											2017-10-22 23:20:00 +01:00
										 |  |  |     response = table.scan( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         FilterExpression=Attr("epoch_ts").lt(7) & Attr("fanout_ts").not_exists() | 
					
						
							| 
									
										
										
										
											2017-10-22 23:20:00 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  |     # Just testing | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert response["Count"] == 0 | 
					
						
							| 
									
										
										
										
											2017-10-22 23:20:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-12 12:05:08 +00:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_scan_filter_should_not_return_non_existing_attributes(): | 
					
						
							|  |  |  |     table_name = "my-table" | 
					
						
							|  |  |  |     item = {"partitionKey": "pk-2", "my-attr": 42} | 
					
						
							|  |  |  |     # Create table | 
					
						
							| 
									
										
										
										
											2020-01-12 12:20:55 +00:00
										 |  |  |     res = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2020-01-12 12:05:08 +00:00
										 |  |  |     res.create_table( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "partitionKey", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "partitionKey", "AttributeType": "S"}], | 
					
						
							|  |  |  |         BillingMode="PAY_PER_REQUEST", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table = res.Table(table_name) | 
					
						
							|  |  |  |     # Insert items | 
					
						
							|  |  |  |     table.put_item(Item={"partitionKey": "pk-1"}) | 
					
						
							|  |  |  |     table.put_item(Item=item) | 
					
						
							|  |  |  |     # Verify a few operations | 
					
						
							|  |  |  |     # Assert we only find the item that has this attribute | 
					
						
							|  |  |  |     table.scan(FilterExpression=Attr("my-attr").lt(43))["Items"].should.equal([item]) | 
					
						
							|  |  |  |     table.scan(FilterExpression=Attr("my-attr").lte(42))["Items"].should.equal([item]) | 
					
						
							|  |  |  |     table.scan(FilterExpression=Attr("my-attr").gte(42))["Items"].should.equal([item]) | 
					
						
							|  |  |  |     table.scan(FilterExpression=Attr("my-attr").gt(41))["Items"].should.equal([item]) | 
					
						
							|  |  |  |     # Sanity check that we can't find the item if the FE is wrong | 
					
						
							|  |  |  |     table.scan(FilterExpression=Attr("my-attr").gt(43))["Items"].should.equal([]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_bad_scan_filter(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "AttributeType": "S"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("test1") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Bad expression | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         table.scan(FilterExpression="client test") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     except ClientError as err: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         err.response["Error"]["Code"].should.equal("ValidationError") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         raise RuntimeError("Should have raised ResourceInUseException") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-30 19:35:21 +09:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_create_table_pay_per_request(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-04-30 19:35:21 +09:00
										 |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "AttributeType": "S"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         BillingMode="PAY_PER_REQUEST", | 
					
						
							| 
									
										
										
										
											2019-04-30 19:35:21 +09:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_create_table_error_pay_per_request_with_provisioned_param(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-04-30 19:35:21 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             TableName="test1", | 
					
						
							|  |  |  |             AttributeDefinitions=[ | 
					
						
							|  |  |  |                 {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |                 {"AttributeName": "app", "AttributeType": "S"}, | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             KeySchema=[ | 
					
						
							|  |  |  |                 {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |                 {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							|  |  |  |             BillingMode="PAY_PER_REQUEST", | 
					
						
							| 
									
										
										
										
											2019-04-30 19:35:21 +09:00
										 |  |  |         ) | 
					
						
							|  |  |  |     except ClientError as err: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         err.response["Error"]["Code"].should.equal("ValidationException") | 
					
						
							| 
									
										
										
										
											2019-04-30 19:35:21 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_duplicate_create(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "AttributeType": "S"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             TableName="test1", | 
					
						
							|  |  |  |             AttributeDefinitions=[ | 
					
						
							|  |  |  |                 {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |                 {"AttributeName": "app", "AttributeType": "S"}, | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             KeySchema=[ | 
					
						
							|  |  |  |                 {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |                 {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |         ) | 
					
						
							|  |  |  |     except ClientError as err: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         err.response["Error"]["Code"].should.equal("ResourceInUseException") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         raise RuntimeError("Should have raised ResourceInUseException") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_delete_table(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "AttributeType": "S"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.delete_table(TableName="test1") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     resp = client.list_tables() | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     len(resp["TableNames"]).should.equal(0) | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         client.delete_table(TableName="test1") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     except ClientError as err: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         err.response["Error"]["Code"].should.equal("ResourceNotFoundException") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         raise RuntimeError("Should have raised ResourceNotFoundException") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_delete_item(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "AttributeType": "S"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", Item={"client": {"S": "client1"}, "app": {"S": "app1"}} | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", Item={"client": {"S": "client1"}, "app": {"S": "app2"}} | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("test1") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     response = table.scan() | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert response["Count"] == 2 | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 13:21:38 -05:00
										 |  |  |     # Test ReturnValues validation | 
					
						
							|  |  |  |     with assert_raises(ClientError) as ex: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         table.delete_item( | 
					
						
							|  |  |  |             Key={"client": "client1", "app": "app1"}, ReturnValues="ALL_NEW" | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2019-04-01 15:15:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  |     # Test deletion and returning old value | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = table.delete_item( | 
					
						
							|  |  |  |         Key={"client": "client1", "app": "app1"}, ReturnValues="ALL_OLD" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     response["Attributes"].should.contain("client") | 
					
						
							|  |  |  |     response["Attributes"].should.contain("app") | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     response = table.scan() | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert response["Count"] == 1 | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Test deletion returning nothing | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = table.delete_item(Key={"client": "client1", "app": "app2"}) | 
					
						
							|  |  |  |     len(response["Attributes"]).should.equal(0) | 
					
						
							| 
									
										
										
										
											2017-10-08 04:18:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     response = table.scan() | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert response["Count"] == 0 | 
					
						
							| 
									
										
										
										
											2017-10-29 16:06:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_describe_limits(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="eu-central-1") | 
					
						
							| 
									
										
										
										
											2017-10-29 16:06:09 +00:00
										 |  |  |     resp = client.describe_limits() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     resp["AccountMaxReadCapacityUnits"].should.equal(20000) | 
					
						
							|  |  |  |     resp["AccountMaxWriteCapacityUnits"].should.equal(20000) | 
					
						
							|  |  |  |     resp["TableMaxWriteCapacityUnits"].should.equal(10000) | 
					
						
							|  |  |  |     resp["TableMaxReadCapacityUnits"].should.equal(10000) | 
					
						
							| 
									
										
										
										
											2017-10-29 16:06:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_set_ttl(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-10-29 16:06:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "AttributeType": "S"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							| 
									
										
										
										
											2017-10-29 16:06:09 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     client.update_time_to_live( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         TimeToLiveSpecification={"Enabled": True, "AttributeName": "expire"}, | 
					
						
							| 
									
										
										
										
											2017-10-29 16:06:09 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     resp = client.describe_time_to_live(TableName="test1") | 
					
						
							|  |  |  |     resp["TimeToLiveDescription"]["TimeToLiveStatus"].should.equal("ENABLED") | 
					
						
							|  |  |  |     resp["TimeToLiveDescription"]["AttributeName"].should.equal("expire") | 
					
						
							| 
									
										
										
										
											2017-10-29 16:06:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     client.update_time_to_live( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         TimeToLiveSpecification={"Enabled": False, "AttributeName": "expire"}, | 
					
						
							| 
									
										
										
										
											2017-10-29 16:06:09 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     resp = client.describe_time_to_live(TableName="test1") | 
					
						
							|  |  |  |     resp["TimeToLiveDescription"]["TimeToLiveStatus"].should.equal("DISABLED") | 
					
						
							| 
									
										
										
										
											2017-11-10 21:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # https://github.com/spulec/moto/issues/1043 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_query_missing_expr_names(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-11-10 21:00:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "AttributeType": "S"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName="test1", Item={"client": {"S": "test1"}, "app": {"S": "test1"}} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName="test1", Item={"client": {"S": "test2"}, "app": {"S": "test2"}} | 
					
						
							| 
									
										
										
										
											2017-11-10 21:00:21 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     resp = client.query( | 
					
						
							|  |  |  |         TableName="test1", | 
					
						
							|  |  |  |         KeyConditionExpression="client=:client", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":client": {"S": "test1"}}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-11-10 21:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     resp["Count"].should.equal(1) | 
					
						
							|  |  |  |     resp["Items"][0]["client"]["S"].should.equal("test1") | 
					
						
							| 
									
										
										
										
											2017-11-10 21:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     resp = client.query( | 
					
						
							|  |  |  |         TableName="test1", | 
					
						
							|  |  |  |         KeyConditionExpression=":name=test2", | 
					
						
							|  |  |  |         ExpressionAttributeNames={":name": "client"}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-11-10 21:00:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     resp["Count"].should.equal(1) | 
					
						
							|  |  |  |     resp["Items"][0]["client"]["S"].should.equal("test2") | 
					
						
							| 
									
										
										
										
											2017-11-17 08:49:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 00:34:20 +09:00
										 |  |  | # https://github.com/spulec/moto/issues/2328 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_item_with_list(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-07-22 00:34:20 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="Table", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "key", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "key", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							| 
									
										
										
										
											2019-07-22 00:34:20 +09:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("Table") | 
					
						
							| 
									
										
										
										
											2019-07-22 00:34:20 +09:00
										 |  |  |     table.update_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         Key={"key": "the-key"}, | 
					
						
							|  |  |  |         AttributeUpdates={"list": {"Value": [1, 2], "Action": "PUT"}}, | 
					
						
							| 
									
										
										
										
											2019-07-22 00:34:20 +09:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     resp = table.get_item(Key={"key": "the-key"}) | 
					
						
							|  |  |  |     resp["Item"].should.equal({"key": "the-key", "list": [1, 2]}) | 
					
						
							| 
									
										
										
										
											2019-07-22 00:34:20 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-17 08:49:59 +00:00
										 |  |  | # https://github.com/spulec/moto/issues/1342 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_item_on_map(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-11-17 08:49:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="users", | 
					
						
							| 
									
										
										
										
											2017-11-17 08:49:59 +00:00
										 |  |  |         KeySchema=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "KeyType": "RANGE"}, | 
					
						
							| 
									
										
										
										
											2017-11-17 08:49:59 +00:00
										 |  |  |         ], | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "AttributeType": "S"}, | 
					
						
							| 
									
										
										
										
											2017-11-17 08:49:59 +00:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							| 
									
										
										
										
											2017-11-17 08:49:59 +00:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("users") | 
					
						
							| 
									
										
										
										
											2017-11-17 08:49:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.put_item( | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "forum_name": "the-key", | 
					
						
							|  |  |  |             "subject": "123", | 
					
						
							|  |  |  |             "body": {"nested": {"data": "test"}}, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-11-17 08:49:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     resp = table.scan() | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     resp["Items"][0]["body"].should.equal({"nested": {"data": "test"}}) | 
					
						
							| 
									
										
										
										
											2017-11-17 08:49:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-04 20:33:56 +02:00
										 |  |  |     # Nonexistent nested attributes are supported for existing top-level attributes. | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.update_item( | 
					
						
							|  |  |  |         Key={"forum_name": "the-key", "subject": "123"}, | 
					
						
							|  |  |  |         UpdateExpression="SET body.#nested.#data = :tb, body.nested.#nonexistentnested.#data = :tb2", | 
					
						
							| 
									
										
										
										
											2017-11-17 08:49:59 +00:00
										 |  |  |         ExpressionAttributeNames={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "#nested": "nested", | 
					
						
							|  |  |  |             "#nonexistentnested": "nonexistentnested", | 
					
						
							|  |  |  |             "#data": "data", | 
					
						
							| 
									
										
										
										
											2017-11-17 08:49:59 +00:00
										 |  |  |         }, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ExpressionAttributeValues={":tb": "new_value", ":tb2": "other_value"}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2017-11-17 08:49:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     resp = table.scan() | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     resp["Items"][0]["body"].should.equal( | 
					
						
							|  |  |  |         {"nested": {"data": "new_value", "nonexistentnested": {"data": "other_value"}}} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2018-05-04 20:33:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Test nested value for a nonexistent attribute. | 
					
						
							| 
									
										
										
										
											2018-06-06 12:09:09 -04:00
										 |  |  |     with assert_raises(client.exceptions.ConditionalCheckFailedException): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         table.update_item( | 
					
						
							|  |  |  |             Key={"forum_name": "the-key", "subject": "123"}, | 
					
						
							|  |  |  |             UpdateExpression="SET nonexistent.#nested = :tb", | 
					
						
							|  |  |  |             ExpressionAttributeNames={"#nested": "nested"}, | 
					
						
							|  |  |  |             ExpressionAttributeValues={":tb": "new_value"}, | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2017-11-26 22:29:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # https://github.com/spulec/moto/issues/1358 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_if_not_exists(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-11-26 22:29:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="users", | 
					
						
							| 
									
										
										
										
											2017-11-26 22:29:23 +00:00
										 |  |  |         KeySchema=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "KeyType": "RANGE"}, | 
					
						
							| 
									
										
										
										
											2017-11-26 22:29:23 +00:00
										 |  |  |         ], | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "forum_name", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "subject", "AttributeType": "S"}, | 
					
						
							| 
									
										
										
										
											2017-11-26 22:29:23 +00:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							| 
									
										
										
										
											2017-11-26 22:29:23 +00:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("users") | 
					
						
							| 
									
										
										
										
											2017-11-26 22:29:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.put_item(Item={"forum_name": "the-key", "subject": "123"}) | 
					
						
							| 
									
										
										
										
											2017-11-26 22:29:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.update_item( | 
					
						
							|  |  |  |         Key={"forum_name": "the-key", "subject": "123"}, | 
					
						
							| 
									
										
										
										
											2018-10-11 18:21:53 +09:00
										 |  |  |         # if_not_exists without space | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         UpdateExpression="SET created_at=if_not_exists(created_at,:created_at)", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":created_at": 123}, | 
					
						
							| 
									
										
										
										
											2017-11-26 22:29:23 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = table.scan() | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert resp["Items"][0]["created_at"] == 123 | 
					
						
							| 
									
										
										
										
											2017-11-26 22:29:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table.update_item( | 
					
						
							|  |  |  |         Key={"forum_name": "the-key", "subject": "123"}, | 
					
						
							| 
									
										
										
										
											2018-10-11 18:21:53 +09:00
										 |  |  |         # if_not_exists with space | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         UpdateExpression="SET created_at = if_not_exists (created_at, :created_at)", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":created_at": 456}, | 
					
						
							| 
									
										
										
										
											2017-11-26 22:29:23 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = table.scan() | 
					
						
							|  |  |  |     # Still the original value | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert resp["Items"][0]["created_at"] == 123 | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  | # https://github.com/spulec/moto/issues/1937 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_return_attributes(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="moto-test", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def update(col, to, rv): | 
					
						
							|  |  |  |         return dynamodb.update_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             TableName="moto-test", | 
					
						
							|  |  |  |             Key={"id": {"S": "foo"}}, | 
					
						
							|  |  |  |             AttributeUpdates={col: {"Value": {"S": to}, "Action": "PUT"}}, | 
					
						
							|  |  |  |             ReturnValues=rv, | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     r = update("col1", "val1", "ALL_NEW") | 
					
						
							|  |  |  |     assert r["Attributes"] == {"id": {"S": "foo"}, "col1": {"S": "val1"}} | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     r = update("col1", "val2", "ALL_OLD") | 
					
						
							|  |  |  |     assert r["Attributes"] == {"id": {"S": "foo"}, "col1": {"S": "val1"}} | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     r = update("col2", "val3", "UPDATED_NEW") | 
					
						
							|  |  |  |     assert r["Attributes"] == {"col2": {"S": "val3"}} | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     r = update("col2", "val4", "UPDATED_OLD") | 
					
						
							|  |  |  |     assert r["Attributes"] == {"col2": {"S": "val3"}} | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     r = update("col1", "val5", "NONE") | 
					
						
							|  |  |  |     assert r["Attributes"] == {} | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 13:21:38 -05:00
										 |  |  |     with assert_raises(ClientError) as ex: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         r = update("col1", "val6", "WRONG") | 
					
						
							| 
									
										
										
										
											2018-11-09 13:21:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_put_return_attributes(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="moto-test", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     r = dynamodb.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="moto-test", | 
					
						
							|  |  |  |         Item={"id": {"S": "foo"}, "col1": {"S": "val1"}}, | 
					
						
							|  |  |  |         ReturnValues="NONE", | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "Attributes" not in r | 
					
						
							| 
									
										
										
										
											2019-04-01 15:15:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  |     r = dynamodb.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="moto-test", | 
					
						
							|  |  |  |         Item={"id": {"S": "foo"}, "col1": {"S": "val2"}}, | 
					
						
							|  |  |  |         ReturnValues="ALL_OLD", | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert r["Attributes"] == {"id": {"S": "foo"}, "col1": {"S": "val1"}} | 
					
						
							| 
									
										
										
										
											2018-11-09 13:21:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     with assert_raises(ClientError) as ex: | 
					
						
							|  |  |  |         dynamodb.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             TableName="moto-test", | 
					
						
							|  |  |  |             Item={"id": {"S": "foo"}, "col1": {"S": "val3"}}, | 
					
						
							|  |  |  |             ReturnValues="ALL_NEW", | 
					
						
							| 
									
										
										
										
											2018-11-09 13:21:38 -05:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     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" | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-04-01 15:15:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-08 16:21:06 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_query_global_secondary_index_when_created_via_update_table_resource(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="users", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "user_id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "user_id", "AttributeType": "N"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("users") | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  |     table.update( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  |         GlobalSecondaryIndexUpdates=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             { | 
					
						
							|  |  |  |                 "Create": { | 
					
						
							|  |  |  |                     "IndexName": "forum_name_index", | 
					
						
							|  |  |  |                     "KeySchema": [{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |                     "Projection": {"ProjectionType": "ALL"}, | 
					
						
							|  |  |  |                     "ProvisionedThroughput": { | 
					
						
							|  |  |  |                         "ReadCapacityUnits": 5, | 
					
						
							|  |  |  |                         "WriteCapacityUnits": 5, | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  |                     }, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     next_user_id = 1 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     for my_forum_name in ["cats", "dogs"]: | 
					
						
							|  |  |  |         for my_subject in [ | 
					
						
							|  |  |  |             "my pet is the cutest", | 
					
						
							|  |  |  |             "wow look at what my pet did", | 
					
						
							|  |  |  |             "don't you love my pet?", | 
					
						
							|  |  |  |         ]: | 
					
						
							|  |  |  |             table.put_item( | 
					
						
							|  |  |  |                 Item={ | 
					
						
							|  |  |  |                     "user_id": next_user_id, | 
					
						
							|  |  |  |                     "forum_name": my_forum_name, | 
					
						
							|  |  |  |                     "subject": my_subject, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  |             next_user_id += 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # get all the cat users | 
					
						
							|  |  |  |     forum_only_query_response = table.query( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         IndexName="forum_name_index", | 
					
						
							|  |  |  |         Select="ALL_ATTRIBUTES", | 
					
						
							|  |  |  |         KeyConditionExpression=Key("forum_name").eq("cats"), | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     forum_only_items = forum_only_query_response["Items"] | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  |     assert len(forum_only_items) == 3 | 
					
						
							|  |  |  |     for item in forum_only_items: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         assert item["forum_name"] == "cats" | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # query all cat users with a particular subject | 
					
						
							|  |  |  |     forum_and_subject_query_results = table.query( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         IndexName="forum_name_index", | 
					
						
							|  |  |  |         Select="ALL_ATTRIBUTES", | 
					
						
							|  |  |  |         KeyConditionExpression=Key("forum_name").eq("cats"), | 
					
						
							|  |  |  |         FilterExpression=Attr("subject").eq("my pet is the cutest"), | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     forum_and_subject_items = forum_and_subject_query_results["Items"] | 
					
						
							| 
									
										
										
										
											2018-06-06 12:50:29 -04:00
										 |  |  |     assert len(forum_and_subject_items) == 1 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert forum_and_subject_items[0] == { | 
					
						
							|  |  |  |         "user_id": Decimal("1"), | 
					
						
							|  |  |  |         "forum_name": "cats", | 
					
						
							|  |  |  |         "subject": "my pet is the cutest", | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-11-07 15:03:25 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_dynamodb_streams_1(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     conn = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2018-11-07 15:03:25 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     resp = conn.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test-streams", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							| 
									
										
										
										
											2018-11-07 15:03:25 -05:00
										 |  |  |         StreamSpecification={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "StreamEnabled": True, | 
					
						
							|  |  |  |             "StreamViewType": "NEW_AND_OLD_IMAGES", | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2018-11-07 15:03:25 -05:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-04-01 15:15:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "StreamSpecification" in resp["TableDescription"] | 
					
						
							|  |  |  |     assert resp["TableDescription"]["StreamSpecification"] == { | 
					
						
							|  |  |  |         "StreamEnabled": True, | 
					
						
							|  |  |  |         "StreamViewType": "NEW_AND_OLD_IMAGES", | 
					
						
							| 
									
										
										
										
											2018-11-07 15:03:25 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "LatestStreamLabel" in resp["TableDescription"] | 
					
						
							|  |  |  |     assert "LatestStreamArn" in resp["TableDescription"] | 
					
						
							| 
									
										
										
										
											2019-04-01 15:15:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     resp = conn.delete_table(TableName="test-streams") | 
					
						
							| 
									
										
										
										
											2018-11-07 15:03:25 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "StreamSpecification" in resp["TableDescription"] | 
					
						
							| 
									
										
										
										
											2019-04-01 15:15:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-07 15:03:25 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_dynamodb_streams_2(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     conn = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2018-11-07 15:03:25 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     resp = conn.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test-stream-update", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							| 
									
										
										
										
											2018-11-07 15:03:25 -05:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "StreamSpecification" not in resp["TableDescription"] | 
					
						
							| 
									
										
										
										
											2018-11-07 15:03:25 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     resp = conn.update_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test-stream-update", | 
					
						
							|  |  |  |         StreamSpecification={"StreamEnabled": True, "StreamViewType": "NEW_IMAGE"}, | 
					
						
							| 
									
										
										
										
											2018-11-07 15:03:25 -05:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "StreamSpecification" in resp["TableDescription"] | 
					
						
							|  |  |  |     assert resp["TableDescription"]["StreamSpecification"] == { | 
					
						
							|  |  |  |         "StreamEnabled": True, | 
					
						
							|  |  |  |         "StreamViewType": "NEW_IMAGE", | 
					
						
							| 
									
										
										
										
											2018-11-07 15:03:25 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert "LatestStreamLabel" in resp["TableDescription"] | 
					
						
							|  |  |  |     assert "LatestStreamArn" in resp["TableDescription"] | 
					
						
							| 
									
										
										
										
											2019-05-22 01:45:30 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 15:15:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_condition_expressions(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create the DynamoDB table. | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "AttributeType": "S"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "client", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "app", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123}, | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |         Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "client": {"S": "client1"}, | 
					
						
							|  |  |  |             "app": {"S": "app1"}, | 
					
						
							|  |  |  |             "match": {"S": "match"}, | 
					
						
							|  |  |  |             "existing": {"S": "existing"}, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |         Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "client": {"S": "client1"}, | 
					
						
							|  |  |  |             "app": {"S": "app1"}, | 
					
						
							|  |  |  |             "match": {"S": "match"}, | 
					
						
							|  |  |  |             "existing": {"S": "existing"}, | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |         }, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ConditionExpression="attribute_exists(#existing) AND attribute_not_exists(#nonexistent) AND #match = :match", | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |         ExpressionAttributeNames={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "#existing": "existing", | 
					
						
							|  |  |  |             "#nonexistent": "nope", | 
					
						
							|  |  |  |             "#match": "match", | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |         }, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ExpressionAttributeValues={":match": {"S": "match"}}, | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |         Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "client": {"S": "client1"}, | 
					
						
							|  |  |  |             "app": {"S": "app1"}, | 
					
						
							|  |  |  |             "match": {"S": "match"}, | 
					
						
							|  |  |  |             "existing": {"S": "existing"}, | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |         }, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ConditionExpression="NOT(attribute_exists(#nonexistent1) AND attribute_exists(#nonexistent2))", | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#nonexistent1": "nope", "#nonexistent2": "nope2"}, | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 16:48:00 -04:00
										 |  |  |     client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							| 
									
										
										
										
											2019-04-01 16:48:00 -04:00
										 |  |  |         Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "client": {"S": "client1"}, | 
					
						
							|  |  |  |             "app": {"S": "app1"}, | 
					
						
							|  |  |  |             "match": {"S": "match"}, | 
					
						
							|  |  |  |             "existing": {"S": "existing"}, | 
					
						
							| 
									
										
										
										
											2019-04-01 16:48:00 -04:00
										 |  |  |         }, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ConditionExpression="attribute_exists(#nonexistent) OR attribute_exists(#existing)", | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#nonexistent": "nope", "#existing": "existing"}, | 
					
						
							| 
									
										
										
										
											2019-04-01 16:48:00 -04:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 17:00:02 -04:00
										 |  |  |     client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							| 
									
										
										
										
											2019-04-01 17:00:02 -04:00
										 |  |  |         Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "client": {"S": "client1"}, | 
					
						
							|  |  |  |             "app": {"S": "app1"}, | 
					
						
							|  |  |  |             "match": {"S": "match"}, | 
					
						
							|  |  |  |             "existing": {"S": "existing"}, | 
					
						
							| 
									
										
										
										
											2019-04-01 17:00:02 -04:00
										 |  |  |         }, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ConditionExpression="#client BETWEEN :a AND :z", | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#client": "client"}, | 
					
						
							|  |  |  |         ExpressionAttributeValues={":a": {"S": "a"}, ":z": {"S": "z"}}, | 
					
						
							| 
									
										
										
										
											2019-04-01 17:00:02 -04:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 17:02:14 -04:00
										 |  |  |     client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test1", | 
					
						
							| 
									
										
										
										
											2019-04-01 17:02:14 -04:00
										 |  |  |         Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "client": {"S": "client1"}, | 
					
						
							|  |  |  |             "app": {"S": "app1"}, | 
					
						
							|  |  |  |             "match": {"S": "match"}, | 
					
						
							|  |  |  |             "existing": {"S": "existing"}, | 
					
						
							| 
									
										
										
										
											2019-04-01 17:02:14 -04:00
										 |  |  |         }, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ConditionExpression="#client IN (:client1, :client2)", | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#client": "client"}, | 
					
						
							| 
									
										
										
										
											2019-04-01 17:02:14 -04:00
										 |  |  |         ExpressionAttributeValues={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             ":client1": {"S": "client1"}, | 
					
						
							|  |  |  |             ":client2": {"S": "client2"}, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2019-04-01 17:02:14 -04:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |     with assert_raises(client.exceptions.ConditionalCheckFailedException): | 
					
						
							|  |  |  |         client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             TableName="test1", | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |             Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 "client": {"S": "client1"}, | 
					
						
							|  |  |  |                 "app": {"S": "app1"}, | 
					
						
							|  |  |  |                 "match": {"S": "match"}, | 
					
						
							|  |  |  |                 "existing": {"S": "existing"}, | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |             }, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             ConditionExpression="attribute_exists(#nonexistent1) AND attribute_exists(#nonexistent2)", | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |             ExpressionAttributeNames={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 "#nonexistent1": "nope", | 
					
						
							|  |  |  |                 "#nonexistent2": "nope2", | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with assert_raises(client.exceptions.ConditionalCheckFailedException): | 
					
						
							|  |  |  |         client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             TableName="test1", | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |             Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 "client": {"S": "client1"}, | 
					
						
							|  |  |  |                 "app": {"S": "app1"}, | 
					
						
							|  |  |  |                 "match": {"S": "match"}, | 
					
						
							|  |  |  |                 "existing": {"S": "existing"}, | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |             }, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             ConditionExpression="NOT(attribute_not_exists(#nonexistent1) AND attribute_not_exists(#nonexistent2))", | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |             ExpressionAttributeNames={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 "#nonexistent1": "nope", | 
					
						
							|  |  |  |                 "#nonexistent2": "nope2", | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with assert_raises(client.exceptions.ConditionalCheckFailedException): | 
					
						
							|  |  |  |         client.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             TableName="test1", | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |             Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 "client": {"S": "client1"}, | 
					
						
							|  |  |  |                 "app": {"S": "app1"}, | 
					
						
							|  |  |  |                 "match": {"S": "match"}, | 
					
						
							|  |  |  |                 "existing": {"S": "existing"}, | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |             }, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             ConditionExpression="attribute_exists(#existing) AND attribute_not_exists(#nonexistent) AND #match = :match", | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |             ExpressionAttributeNames={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 "#existing": "existing", | 
					
						
							|  |  |  |                 "#nonexistent": "nope", | 
					
						
							|  |  |  |                 "#match": "match", | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |             }, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             ExpressionAttributeValues={":match": {"S": "match2"}}, | 
					
						
							| 
									
										
										
										
											2019-02-14 18:10:01 -08:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-14 19:37:43 -04:00
										 |  |  |     # Make sure update_item honors ConditionExpression as well | 
					
						
							| 
									
										
										
										
											2019-06-26 23:13:01 +01:00
										 |  |  |     client.update_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         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"}}, | 
					
						
							| 
									
										
										
										
											2019-04-14 19:37:43 -04:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-26 23:13:01 +01:00
										 |  |  |     with assert_raises(client.exceptions.ConditionalCheckFailedException): | 
					
						
							|  |  |  |         client.update_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             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"}, | 
					
						
							| 
									
										
										
										
											2019-04-14 19:37:43 -04:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-06 16:49:02 +02:00
										 |  |  |     with assert_raises(client.exceptions.ConditionalCheckFailedException): | 
					
						
							|  |  |  |         client.delete_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             TableName="test1", | 
					
						
							|  |  |  |             Key={"client": {"S": "client1"}, "app": {"S": "app1"}}, | 
					
						
							|  |  |  |             ConditionExpression="attribute_not_exists(#existing)", | 
					
						
							|  |  |  |             ExpressionAttributeValues={":match": {"S": "match"}}, | 
					
						
							|  |  |  |             ExpressionAttributeNames={"#existing": "existing", "#match": "match"}, | 
					
						
							| 
									
										
										
										
											2019-10-06 16:49:02 +02:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-22 11:30:17 +00:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_condition_expression_numerical_attribute(): | 
					
						
							| 
									
										
										
										
											2020-01-22 11:42:06 +00:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2020-01-22 11:30:17 +00:00
										 |  |  |     dynamodb.create_table( | 
					
						
							|  |  |  |         TableName="my-table", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "partitionKey", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "partitionKey", "AttributeType": "S"}], | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table = dynamodb.Table("my-table") | 
					
						
							|  |  |  |     table.put_item(Item={"partitionKey": "pk-pos", "myAttr": 5}) | 
					
						
							|  |  |  |     table.put_item(Item={"partitionKey": "pk-neg", "myAttr": -5}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # try to update the item we put in the table using numerical condition expression | 
					
						
							|  |  |  |     # Specifically, verify that we can compare with a zero-value | 
					
						
							|  |  |  |     # First verify that > and >= work on positive numbers | 
					
						
							|  |  |  |     update_numerical_con_expr( | 
					
						
							|  |  |  |         key="pk-pos", con_expr="myAttr > :zero", res="6", table=table | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     update_numerical_con_expr( | 
					
						
							|  |  |  |         key="pk-pos", con_expr="myAttr >= :zero", res="7", table=table | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     # Second verify that < and <= work on negative numbers | 
					
						
							|  |  |  |     update_numerical_con_expr( | 
					
						
							|  |  |  |         key="pk-neg", con_expr="myAttr < :zero", res="-4", table=table | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     update_numerical_con_expr( | 
					
						
							|  |  |  |         key="pk-neg", con_expr="myAttr <= :zero", res="-3", table=table | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def update_numerical_con_expr(key, con_expr, res, table): | 
					
						
							|  |  |  |     table.update_item( | 
					
						
							|  |  |  |         Key={"partitionKey": key}, | 
					
						
							|  |  |  |         UpdateExpression="ADD myAttr :one", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":zero": 0, ":one": 1}, | 
					
						
							|  |  |  |         ConditionExpression=con_expr, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table.get_item(Key={"partitionKey": key})["Item"]["myAttr"].should.equal( | 
					
						
							|  |  |  |         Decimal(res) | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-26 23:13:01 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_condition_expression__attr_doesnt_exist(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-06-26 23:13:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-06-26 23:13:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName="test", Item={"forum_name": {"S": "foo"}, "ttl": {"N": "bar"}} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-06-26 23:13:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def update_if_attr_doesnt_exist(): | 
					
						
							|  |  |  |         # Test nonexistent top-level attribute. | 
					
						
							|  |  |  |         client.update_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             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"}, | 
					
						
							| 
									
										
										
										
											2019-06-26 23:13:01 +01:00
										 |  |  |             ExpressionAttributeValues={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 ":new_state": {"S": "some-value"}, | 
					
						
							|  |  |  |                 ":ttl": {"N": "12345.67"}, | 
					
						
							| 
									
										
										
										
											2019-06-26 23:13:01 +01:00
										 |  |  |             }, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             ReturnValues="ALL_NEW", | 
					
						
							| 
									
										
										
										
											2019-06-26 23:13:01 +01:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     update_if_attr_doesnt_exist() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Second time should fail | 
					
						
							|  |  |  |     with assert_raises(client.exceptions.ConditionalCheckFailedException): | 
					
						
							|  |  |  |         update_if_attr_doesnt_exist() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-11 08:27:05 -04:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_condition_expression__or_order(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-07-11 08:27:05 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							| 
									
										
										
										
											2019-07-11 08:27:05 -04:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # 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( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         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"}}, | 
					
						
							| 
									
										
										
										
											2019-07-11 08:27:05 -04:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-16 23:33:52 +09:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_condition_expression__and_order(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-09-16 23:33:52 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							| 
									
										
										
										
											2019-09-16 23:33:52 +09:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-16 23:33:52 +09:00
										 |  |  |     # ensure that the RHS of the AND expression is not evaluated if the LHS | 
					
						
							|  |  |  |     # returns true (as it would result an error) | 
					
						
							|  |  |  |     with assert_raises(client.exceptions.ConditionalCheckFailedException): | 
					
						
							|  |  |  |         client.update_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             TableName="test", | 
					
						
							|  |  |  |             Key={"forum_name": {"S": "the-key"}}, | 
					
						
							|  |  |  |             UpdateExpression="set #ttl=:ttl", | 
					
						
							|  |  |  |             ConditionExpression="attribute_exists(#ttl) AND #ttl <= :old_ttl", | 
					
						
							|  |  |  |             ExpressionAttributeNames={"#ttl": "ttl"}, | 
					
						
							|  |  |  |             ExpressionAttributeValues={":ttl": {"N": "6"}, ":old_ttl": {"N": "5"}}, | 
					
						
							| 
									
										
										
										
											2019-09-16 23:33:52 +09:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-22 20:40:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_query_gsi_with_range_key(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  |     dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  |         AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "id", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "gsi_hash_key", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "gsi_range_key", "AttributeType": "S"}, | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  |         GlobalSecondaryIndexes=[ | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 "IndexName": "test_gsi", | 
					
						
							|  |  |  |                 "KeySchema": [ | 
					
						
							|  |  |  |                     {"AttributeName": "gsi_hash_key", "KeyType": "HASH"}, | 
					
						
							|  |  |  |                     {"AttributeName": "gsi_range_key", "KeyType": "RANGE"}, | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  |                 ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 "Projection": {"ProjectionType": "ALL"}, | 
					
						
							|  |  |  |                 "ProvisionedThroughput": { | 
					
						
							|  |  |  |                     "ReadCapacityUnits": 1, | 
					
						
							|  |  |  |                     "WriteCapacityUnits": 1, | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  |                 }, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             } | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     dynamodb.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test", | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  |         Item={ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "id": {"S": "test1"}, | 
					
						
							|  |  |  |             "gsi_hash_key": {"S": "key1"}, | 
					
						
							|  |  |  |             "gsi_range_key": {"S": "range1"}, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  |     ) | 
					
						
							|  |  |  |     dynamodb.put_item( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test", Item={"id": {"S": "test2"}, "gsi_hash_key": {"S": "key1"}} | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     res = dynamodb.query( | 
					
						
							|  |  |  |         TableName="test", | 
					
						
							|  |  |  |         IndexName="test_gsi", | 
					
						
							|  |  |  |         KeyConditionExpression="gsi_hash_key = :gsi_hash_key AND gsi_range_key = :gsi_range_key", | 
					
						
							|  |  |  |         ExpressionAttributeValues={ | 
					
						
							|  |  |  |             ":gsi_hash_key": {"S": "key1"}, | 
					
						
							|  |  |  |             ":gsi_range_key": {"S": "range1"}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-04-18 20:31:46 +09:00
										 |  |  |     res.should.have.key("Count").equal(1) | 
					
						
							|  |  |  |     res.should.have.key("Items") | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     res["Items"][0].should.equal( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "id": {"S": "test1"}, | 
					
						
							|  |  |  |             "gsi_hash_key": {"S": "key1"}, | 
					
						
							|  |  |  |             "gsi_range_key": {"S": "range1"}, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-05-22 01:45:30 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_scan_by_non_exists_index(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-05-22 01:45:30 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							| 
									
										
										
										
											2019-05-22 01:45:30 +09:00
										 |  |  |         AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             {"AttributeName": "id", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "gsi_col", "AttributeType": "S"}, | 
					
						
							| 
									
										
										
										
											2019-05-22 01:45:30 +09:00
										 |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							| 
									
										
										
										
											2019-05-22 01:45:30 +09:00
										 |  |  |         GlobalSecondaryIndexes=[ | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 "IndexName": "test_gsi", | 
					
						
							|  |  |  |                 "KeySchema": [{"AttributeName": "gsi_col", "KeyType": "HASH"}], | 
					
						
							|  |  |  |                 "Projection": {"ProjectionType": "ALL"}, | 
					
						
							|  |  |  |                 "ProvisionedThroughput": { | 
					
						
							|  |  |  |                     "ReadCapacityUnits": 1, | 
					
						
							|  |  |  |                     "WriteCapacityUnits": 1, | 
					
						
							| 
									
										
										
										
											2019-05-22 01:45:30 +09:00
										 |  |  |                 }, | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             } | 
					
						
							|  |  |  |         ], | 
					
						
							| 
									
										
										
										
											2019-05-22 01:45:30 +09:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with assert_raises(ClientError) as ex: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         dynamodb.scan(TableName="test", IndexName="non_exists_index") | 
					
						
							| 
									
										
										
										
											2019-05-22 01:45:30 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     ex.exception.response["Error"]["Code"].should.equal("ValidationException") | 
					
						
							|  |  |  |     ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.exception.response["Error"]["Message"].should.equal( | 
					
						
							|  |  |  |         "The table does not have the specified index: non_exists_index" | 
					
						
							| 
									
										
										
										
											2019-05-22 01:45:30 +09:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-08-22 16:12:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-11 15:08:45 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_query_by_non_exists_index(): | 
					
						
							|  |  |  |     dynamodb = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     dynamodb.create_table( | 
					
						
							|  |  |  |         TableName="test", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "id", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "gsi_col", "AttributeType": "S"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							|  |  |  |         GlobalSecondaryIndexes=[ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 "IndexName": "test_gsi", | 
					
						
							|  |  |  |                 "KeySchema": [{"AttributeName": "gsi_col", "KeyType": "HASH"}], | 
					
						
							|  |  |  |                 "Projection": {"ProjectionType": "ALL"}, | 
					
						
							|  |  |  |                 "ProvisionedThroughput": { | 
					
						
							|  |  |  |                     "ReadCapacityUnits": 1, | 
					
						
							|  |  |  |                     "WriteCapacityUnits": 1, | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-12 10:49:07 +01:00
										 |  |  |     with assert_raises(ClientError) as ex: | 
					
						
							| 
									
										
										
										
											2019-12-11 15:08:45 +01:00
										 |  |  |         dynamodb.query( | 
					
						
							|  |  |  |             TableName="test", | 
					
						
							|  |  |  |             IndexName="non_exists_index", | 
					
						
							|  |  |  |             KeyConditionExpression="CarModel=M", | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-12 10:49:07 +01:00
										 |  |  |     ex.exception.response["Error"]["Code"].should.equal("ResourceNotFoundException") | 
					
						
							|  |  |  |     ex.exception.response["Error"]["Message"].should.equal( | 
					
						
							| 
									
										
										
										
											2019-12-11 15:08:45 +01:00
										 |  |  |         "Invalid index: non_exists_index for table: test. Available indexes are: test_gsi" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-22 16:12:48 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_batch_items_returns_all(): | 
					
						
							|  |  |  |     dynamodb = _create_user_table() | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     returned_items = dynamodb.batch_get_item( | 
					
						
							|  |  |  |         RequestItems={ | 
					
						
							|  |  |  |             "users": { | 
					
						
							|  |  |  |                 "Keys": [ | 
					
						
							|  |  |  |                     {"username": {"S": "user0"}}, | 
					
						
							|  |  |  |                     {"username": {"S": "user1"}}, | 
					
						
							|  |  |  |                     {"username": {"S": "user2"}}, | 
					
						
							|  |  |  |                     {"username": {"S": "user3"}}, | 
					
						
							|  |  |  |                 ], | 
					
						
							|  |  |  |                 "ConsistentRead": True, | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-08-22 16:12:48 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     )["Responses"]["users"] | 
					
						
							| 
									
										
										
										
											2019-08-22 16:12:48 +01:00
										 |  |  |     assert len(returned_items) == 3 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert [item["username"]["S"] for item in returned_items] == [ | 
					
						
							|  |  |  |         "user1", | 
					
						
							|  |  |  |         "user2", | 
					
						
							|  |  |  |         "user3", | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2019-08-22 16:12:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_batch_items_with_basic_projection_expression(): | 
					
						
							|  |  |  |     dynamodb = _create_user_table() | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     returned_items = dynamodb.batch_get_item( | 
					
						
							|  |  |  |         RequestItems={ | 
					
						
							|  |  |  |             "users": { | 
					
						
							|  |  |  |                 "Keys": [ | 
					
						
							|  |  |  |                     {"username": {"S": "user0"}}, | 
					
						
							|  |  |  |                     {"username": {"S": "user1"}}, | 
					
						
							|  |  |  |                     {"username": {"S": "user2"}}, | 
					
						
							|  |  |  |                     {"username": {"S": "user3"}}, | 
					
						
							|  |  |  |                 ], | 
					
						
							|  |  |  |                 "ConsistentRead": True, | 
					
						
							|  |  |  |                 "ProjectionExpression": "username", | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     )["Responses"]["users"] | 
					
						
							| 
									
										
										
										
											2019-10-11 14:30:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     returned_items.should.have.length_of(3) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     [item["username"]["S"] for item in returned_items].should.be.equal( | 
					
						
							|  |  |  |         ["user1", "user2", "user3"] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     [item.get("foo") for item in returned_items].should.be.equal([None, None, None]) | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # The projection expression should not remove data from storage | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     returned_items = dynamodb.batch_get_item( | 
					
						
							|  |  |  |         RequestItems={ | 
					
						
							|  |  |  |             "users": { | 
					
						
							|  |  |  |                 "Keys": [ | 
					
						
							|  |  |  |                     {"username": {"S": "user0"}}, | 
					
						
							|  |  |  |                     {"username": {"S": "user1"}}, | 
					
						
							|  |  |  |                     {"username": {"S": "user2"}}, | 
					
						
							|  |  |  |                     {"username": {"S": "user3"}}, | 
					
						
							|  |  |  |                 ], | 
					
						
							|  |  |  |                 "ConsistentRead": True, | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     )["Responses"]["users"] | 
					
						
							| 
									
										
										
										
											2019-10-11 14:30:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     [item["username"]["S"] for item in returned_items].should.be.equal( | 
					
						
							|  |  |  |         ["user1", "user2", "user3"] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     [item["foo"]["S"] for item in returned_items].should.be.equal(["bar", "bar", "bar"]) | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_batch_items_with_basic_projection_expression_and_attr_expression_names(): | 
					
						
							|  |  |  |     dynamodb = _create_user_table() | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     returned_items = dynamodb.batch_get_item( | 
					
						
							|  |  |  |         RequestItems={ | 
					
						
							|  |  |  |             "users": { | 
					
						
							|  |  |  |                 "Keys": [ | 
					
						
							|  |  |  |                     {"username": {"S": "user0"}}, | 
					
						
							|  |  |  |                     {"username": {"S": "user1"}}, | 
					
						
							|  |  |  |                     {"username": {"S": "user2"}}, | 
					
						
							|  |  |  |                     {"username": {"S": "user3"}}, | 
					
						
							|  |  |  |                 ], | 
					
						
							|  |  |  |                 "ConsistentRead": True, | 
					
						
							|  |  |  |                 "ProjectionExpression": "#rl", | 
					
						
							|  |  |  |                 "ExpressionAttributeNames": {"#rl": "username"}, | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     )["Responses"]["users"] | 
					
						
							| 
									
										
										
										
											2019-10-11 14:30:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     returned_items.should.have.length_of(3) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     [item["username"]["S"] for item in returned_items].should.be.equal( | 
					
						
							|  |  |  |         ["user1", "user2", "user3"] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     [item.get("foo") for item in returned_items].should.be.equal([None, None, None]) | 
					
						
							| 
									
										
										
										
											2019-10-08 21:29:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-22 16:12:48 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_batch_items_should_throw_exception_for_duplicate_request(): | 
					
						
							|  |  |  |     client = _create_user_table() | 
					
						
							|  |  |  |     with assert_raises(ClientError) as ex: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         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" | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-08-22 16:12:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-03 10:54:10 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_index_with_unknown_attributes_should_fail(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-10-03 10:54:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     expected_exception = ( | 
					
						
							|  |  |  |         "Some index key attributes are not defined in AttributeDefinitions." | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-03 10:54:10 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     with assert_raises(ClientError) as ex: | 
					
						
							|  |  |  |         dynamodb.create_table( | 
					
						
							|  |  |  |             AttributeDefinitions=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 {"AttributeName": "customer_nr", "AttributeType": "S"}, | 
					
						
							|  |  |  |                 {"AttributeName": "last_name", "AttributeType": "S"}, | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             TableName="table_with_missing_attribute_definitions", | 
					
						
							| 
									
										
										
										
											2019-10-03 10:54:10 +01:00
										 |  |  |             KeySchema=[ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 {"AttributeName": "customer_nr", "KeyType": "HASH"}, | 
					
						
							|  |  |  |                 {"AttributeName": "last_name", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             LocalSecondaryIndexes=[ | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     "IndexName": "indexthataddsanadditionalattribute", | 
					
						
							|  |  |  |                     "KeySchema": [ | 
					
						
							|  |  |  |                         {"AttributeName": "customer_nr", "KeyType": "HASH"}, | 
					
						
							|  |  |  |                         {"AttributeName": "postcode", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |                     ], | 
					
						
							|  |  |  |                     "Projection": {"ProjectionType": "ALL"}, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             BillingMode="PAY_PER_REQUEST", | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2019-10-03 10:54:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     ex.exception.response["Error"]["Code"].should.equal("ValidationException") | 
					
						
							|  |  |  |     ex.exception.response["Error"]["Message"].should.contain(expected_exception) | 
					
						
							| 
									
										
										
										
											2019-10-03 10:54:10 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_list_index__set_existing_index(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table_name = "test_list_index_access" | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     client = create_table_with_list(table_name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "id": {"S": "foo"}, | 
					
						
							|  |  |  |             "itemlist": {"L": [{"S": "bar1"}, {"S": "bar2"}, {"S": "bar3"}]}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Key={"id": {"S": "foo"}}, | 
					
						
							|  |  |  |         UpdateExpression="set itemlist[1]=:Item", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":Item": {"S": "bar2_update"}}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     # | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result = client.get_item(TableName=table_name, Key={"id": {"S": "foo"}})["Item"] | 
					
						
							|  |  |  |     result["id"].should.equal({"S": "foo"}) | 
					
						
							|  |  |  |     result["itemlist"].should.equal( | 
					
						
							|  |  |  |         {"L": [{"S": "bar1"}, {"S": "bar2_update"}, {"S": "bar3"}]} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_list_index__set_existing_nested_index(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table_name = "test_list_index_access" | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     client = create_table_with_list(table_name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "id": {"S": "foo2"}, | 
					
						
							|  |  |  |             "itemmap": { | 
					
						
							|  |  |  |                 "M": {"itemlist": {"L": [{"S": "bar1"}, {"S": "bar2"}, {"S": "bar3"}]}} | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Key={"id": {"S": "foo2"}}, | 
					
						
							|  |  |  |         UpdateExpression="set itemmap.itemlist[1]=:Item", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":Item": {"S": "bar2_update"}}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     # | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result = client.get_item(TableName=table_name, Key={"id": {"S": "foo2"}})["Item"] | 
					
						
							|  |  |  |     result["id"].should.equal({"S": "foo2"}) | 
					
						
							|  |  |  |     result["itemmap"]["M"]["itemlist"]["L"].should.equal( | 
					
						
							|  |  |  |         [{"S": "bar1"}, {"S": "bar2_update"}, {"S": "bar3"}] | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_list_index__set_index_out_of_range(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table_name = "test_list_index_access" | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     client = create_table_with_list(table_name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "id": {"S": "foo"}, | 
					
						
							|  |  |  |             "itemlist": {"L": [{"S": "bar1"}, {"S": "bar2"}, {"S": "bar3"}]}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Key={"id": {"S": "foo"}}, | 
					
						
							|  |  |  |         UpdateExpression="set itemlist[10]=:Item", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":Item": {"S": "bar10"}}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     # | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result = client.get_item(TableName=table_name, Key={"id": {"S": "foo"}})["Item"] | 
					
						
							|  |  |  |     assert result["id"] == {"S": "foo"} | 
					
						
							|  |  |  |     assert result["itemlist"] == { | 
					
						
							|  |  |  |         "L": [{"S": "bar1"}, {"S": "bar2"}, {"S": "bar3"}, {"S": "bar10"}] | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_list_index__set_nested_index_out_of_range(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table_name = "test_list_index_access" | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     client = create_table_with_list(table_name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "id": {"S": "foo2"}, | 
					
						
							|  |  |  |             "itemmap": { | 
					
						
							|  |  |  |                 "M": {"itemlist": {"L": [{"S": "bar1"}, {"S": "bar2"}, {"S": "bar3"}]}} | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Key={"id": {"S": "foo2"}}, | 
					
						
							|  |  |  |         UpdateExpression="set itemmap.itemlist[10]=:Item", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":Item": {"S": "bar10"}}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     # | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result = client.get_item(TableName=table_name, Key={"id": {"S": "foo2"}})["Item"] | 
					
						
							|  |  |  |     assert result["id"] == {"S": "foo2"} | 
					
						
							|  |  |  |     assert result["itemmap"]["M"]["itemlist"]["L"] == [ | 
					
						
							|  |  |  |         {"S": "bar1"}, | 
					
						
							|  |  |  |         {"S": "bar2"}, | 
					
						
							|  |  |  |         {"S": "bar3"}, | 
					
						
							|  |  |  |         {"S": "bar10"}, | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-22 20:40:41 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_list_index__set_double_nested_index(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table_name = "test_list_index_access" | 
					
						
							| 
									
										
										
										
											2019-10-22 20:40:41 +01:00
										 |  |  |     client = create_table_with_list(table_name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "id": {"S": "foo2"}, | 
					
						
							|  |  |  |             "itemmap": { | 
					
						
							|  |  |  |                 "M": { | 
					
						
							|  |  |  |                     "itemlist": { | 
					
						
							|  |  |  |                         "L": [ | 
					
						
							|  |  |  |                             {"M": {"foo": {"S": "bar11"}, "foos": {"S": "bar12"}}}, | 
					
						
							|  |  |  |                             {"M": {"foo": {"S": "bar21"}, "foos": {"S": "bar21"}}}, | 
					
						
							|  |  |  |                         ] | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Key={"id": {"S": "foo2"}}, | 
					
						
							|  |  |  |         UpdateExpression="set itemmap.itemlist[1].foos=:Item", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":Item": {"S": "bar22"}}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-22 20:40:41 +01:00
										 |  |  |     # | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result = client.get_item(TableName=table_name, Key={"id": {"S": "foo2"}})["Item"] | 
					
						
							|  |  |  |     assert result["id"] == {"S": "foo2"} | 
					
						
							|  |  |  |     len(result["itemmap"]["M"]["itemlist"]["L"]).should.equal(2) | 
					
						
							|  |  |  |     result["itemmap"]["M"]["itemlist"]["L"][0].should.equal( | 
					
						
							|  |  |  |         {"M": {"foo": {"S": "bar11"}, "foos": {"S": "bar12"}}} | 
					
						
							|  |  |  |     )  # unchanged | 
					
						
							|  |  |  |     result["itemmap"]["M"]["itemlist"]["L"][1].should.equal( | 
					
						
							|  |  |  |         {"M": {"foo": {"S": "bar21"}, "foos": {"S": "bar22"}}} | 
					
						
							|  |  |  |     )  # updated | 
					
						
							| 
									
										
										
										
											2019-10-22 20:40:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_list_index__set_index_of_a_string(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table_name = "test_list_index_access" | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     client = create_table_with_list(table_name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName=table_name, Item={"id": {"S": "foo2"}, "itemstr": {"S": "somestring"}} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     with assert_raises(ClientError) as ex: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         client.update_item( | 
					
						
							|  |  |  |             TableName=table_name, | 
					
						
							|  |  |  |             Key={"id": {"S": "foo2"}}, | 
					
						
							|  |  |  |             UpdateExpression="set itemstr[1]=:Item", | 
					
						
							|  |  |  |             ExpressionAttributeValues={":Item": {"S": "string_update"}}, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         result = client.get_item(TableName=table_name, Key={"id": {"S": "foo2"}})[ | 
					
						
							|  |  |  |             "Item" | 
					
						
							|  |  |  |         ] | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     ex.exception.response["Error"]["Code"].should.equal("ValidationException") | 
					
						
							|  |  |  |     ex.exception.response["Error"]["Message"].should.equal( | 
					
						
							|  |  |  |         "The document path provided in the update expression is invalid for update" | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-22 20:40:41 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_remove_top_level_attribute(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table_name = "test_remove" | 
					
						
							| 
									
										
										
										
											2019-10-22 20:40:41 +01:00
										 |  |  |     client = create_table_with_list(table_name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName=table_name, Item={"id": {"S": "foo"}, "item": {"S": "bar"}} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName=table_name, Key={"id": {"S": "foo"}}, UpdateExpression="REMOVE item" | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-22 20:40:41 +01:00
										 |  |  |     # | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result = client.get_item(TableName=table_name, Key={"id": {"S": "foo"}})["Item"] | 
					
						
							|  |  |  |     result.should.equal({"id": {"S": "foo"}}) | 
					
						
							| 
									
										
										
										
											2019-10-22 20:40:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_remove_list_index__remove_existing_index(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table_name = "test_list_index_access" | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     client = create_table_with_list(table_name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "id": {"S": "foo"}, | 
					
						
							|  |  |  |             "itemlist": {"L": [{"S": "bar1"}, {"S": "bar2"}, {"S": "bar3"}]}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Key={"id": {"S": "foo"}}, | 
					
						
							|  |  |  |         UpdateExpression="REMOVE itemlist[1]", | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     # | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result = client.get_item(TableName=table_name, Key={"id": {"S": "foo"}})["Item"] | 
					
						
							|  |  |  |     result["id"].should.equal({"S": "foo"}) | 
					
						
							|  |  |  |     result["itemlist"].should.equal({"L": [{"S": "bar1"}, {"S": "bar3"}]}) | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_remove_list_index__remove_existing_nested_index(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table_name = "test_list_index_access" | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     client = create_table_with_list(table_name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "id": {"S": "foo2"}, | 
					
						
							|  |  |  |             "itemmap": {"M": {"itemlist": {"L": [{"S": "bar1"}, {"S": "bar2"}]}}}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Key={"id": {"S": "foo2"}}, | 
					
						
							|  |  |  |         UpdateExpression="REMOVE itemmap.itemlist[1]", | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     # | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result = client.get_item(TableName=table_name, Key={"id": {"S": "foo2"}})["Item"] | 
					
						
							|  |  |  |     result["id"].should.equal({"S": "foo2"}) | 
					
						
							|  |  |  |     result["itemmap"]["M"]["itemlist"]["L"].should.equal([{"S": "bar1"}]) | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-14 09:59:52 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_remove_list_index__remove_existing_double_nested_index(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table_name = "test_list_index_access" | 
					
						
							| 
									
										
										
										
											2019-10-14 09:59:52 +01:00
										 |  |  |     client = create_table_with_list(table_name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "id": {"S": "foo2"}, | 
					
						
							|  |  |  |             "itemmap": { | 
					
						
							|  |  |  |                 "M": { | 
					
						
							|  |  |  |                     "itemlist": { | 
					
						
							|  |  |  |                         "L": [ | 
					
						
							|  |  |  |                             {"M": {"foo00": {"S": "bar1"}, "foo01": {"S": "bar2"}}}, | 
					
						
							|  |  |  |                             {"M": {"foo10": {"S": "bar1"}, "foo11": {"S": "bar2"}}}, | 
					
						
							|  |  |  |                         ] | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Key={"id": {"S": "foo2"}}, | 
					
						
							|  |  |  |         UpdateExpression="REMOVE itemmap.itemlist[1].foo10", | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-14 09:59:52 +01:00
										 |  |  |     # | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result = client.get_item(TableName=table_name, Key={"id": {"S": "foo2"}})["Item"] | 
					
						
							|  |  |  |     assert result["id"] == {"S": "foo2"} | 
					
						
							|  |  |  |     assert result["itemmap"]["M"]["itemlist"]["L"][0]["M"].should.equal( | 
					
						
							|  |  |  |         {"foo00": {"S": "bar1"}, "foo01": {"S": "bar2"}} | 
					
						
							|  |  |  |     )  # untouched | 
					
						
							|  |  |  |     assert result["itemmap"]["M"]["itemlist"]["L"][1]["M"].should.equal( | 
					
						
							|  |  |  |         {"foo11": {"S": "bar2"}} | 
					
						
							|  |  |  |     )  # changed | 
					
						
							| 
									
										
										
										
											2019-10-14 09:59:52 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_remove_list_index__remove_index_out_of_range(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table_name = "test_list_index_access" | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     client = create_table_with_list(table_name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "id": {"S": "foo"}, | 
					
						
							|  |  |  |             "itemlist": {"L": [{"S": "bar1"}, {"S": "bar2"}, {"S": "bar3"}]}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         Key={"id": {"S": "foo"}}, | 
					
						
							|  |  |  |         UpdateExpression="REMOVE itemlist[10]", | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     # | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result = client.get_item(TableName=table_name, Key={"id": {"S": "foo"}})["Item"] | 
					
						
							|  |  |  |     assert result["id"] == {"S": "foo"} | 
					
						
							|  |  |  |     assert result["itemlist"] == {"L": [{"S": "bar1"}, {"S": "bar2"}, {"S": "bar3"}]} | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def create_table_with_list(table_name): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         BillingMode="PAY_PER_REQUEST", | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-09 17:25:50 +01:00
										 |  |  |     return client | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-10 09:33:11 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_sorted_query_with_numerical_sort_key(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  |     dynamodb.create_table( | 
					
						
							|  |  |  |         TableName="CarCollection", | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "CarModel", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "CarPrice", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "CarModel", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "CarPrice", "AttributeType": "N"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-10 09:33:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def create_item(price): | 
					
						
							|  |  |  |         return {"CarModel": "M", "CarPrice": price} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("CarCollection") | 
					
						
							| 
									
										
										
										
											2019-10-10 09:33:11 +01:00
										 |  |  |     items = list(map(create_item, [2, 1, 10, 3])) | 
					
						
							|  |  |  |     for item in items: | 
					
						
							|  |  |  |         table.put_item(Item=item) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = table.query(KeyConditionExpression=Key("CarModel").eq("M")) | 
					
						
							| 
									
										
										
										
											2019-10-10 09:33:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response_items = response["Items"] | 
					
						
							| 
									
										
										
										
											2019-10-10 09:33:11 +01:00
										 |  |  |     assert len(items) == len(response_items) | 
					
						
							|  |  |  |     assert all(isinstance(item["CarPrice"], Decimal) for item in response_items) | 
					
						
							|  |  |  |     response_prices = [item["CarPrice"] for item in response_items] | 
					
						
							|  |  |  |     expected_prices = [Decimal(item["CarPrice"]) for item in items] | 
					
						
							|  |  |  |     expected_prices.sort() | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert ( | 
					
						
							|  |  |  |         expected_prices == response_prices | 
					
						
							|  |  |  |     ), "result items are not sorted by numerical value" | 
					
						
							| 
									
										
										
										
											2019-10-10 09:33:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 15:20:43 +01:00
										 |  |  | # https://github.com/spulec/moto/issues/1874 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_item_size_is_under_400KB(): | 
					
						
							| 
									
										
										
										
											2019-11-17 23:16:15 -08:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-10-05 15:20:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="moto-test", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table = dynamodb.Table("moto-test") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     large_item = "x" * 410 * 1000 | 
					
						
							|  |  |  |     assert_failure_due_to_item_size( | 
					
						
							|  |  |  |         func=client.put_item, | 
					
						
							|  |  |  |         TableName="moto-test", | 
					
						
							|  |  |  |         Item={"id": {"S": "foo"}, "item": {"S": large_item}}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     assert_failure_due_to_item_size( | 
					
						
							|  |  |  |         func=table.put_item, Item={"id": "bar", "item": large_item} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     assert_failure_due_to_item_size( | 
					
						
							|  |  |  |         func=client.update_item, | 
					
						
							|  |  |  |         TableName="moto-test", | 
					
						
							|  |  |  |         Key={"id": {"S": "foo2"}}, | 
					
						
							|  |  |  |         UpdateExpression="set item=:Item", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":Item": {"S": large_item}}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-08 15:51:46 +01:00
										 |  |  |     # Assert op fails when updating a nested item | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     assert_failure_due_to_item_size( | 
					
						
							|  |  |  |         func=table.put_item, Item={"id": "bar", "itemlist": [{"item": large_item}]} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     assert_failure_due_to_item_size( | 
					
						
							|  |  |  |         func=client.put_item, | 
					
						
							|  |  |  |         TableName="moto-test", | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "id": {"S": "foo"}, | 
					
						
							|  |  |  |             "itemlist": {"L": [{"M": {"item1": {"S": large_item}}}]}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-08 15:51:46 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | def assert_failure_due_to_item_size(func, **kwargs): | 
					
						
							|  |  |  |     with assert_raises(ClientError) as ex: | 
					
						
							|  |  |  |         func(**kwargs) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     ex.exception.response["Error"]["Code"].should.equal("ValidationException") | 
					
						
							|  |  |  |     ex.exception.response["Error"]["Message"].should.equal( | 
					
						
							|  |  |  |         "Item size has exceeded the maximum allowed size" | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-18 09:58:09 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | # https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html#DDB-Query-request-KeyConditionExpression | 
					
						
							|  |  |  | def test_hash_key_cannot_use_begins_with_operations(): | 
					
						
							| 
									
										
										
										
											2019-11-17 23:16:15 -08:00
										 |  |  |     dynamodb = boto3.resource("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-10-18 09:58:09 +01:00
										 |  |  |     table = dynamodb.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         TableName="test-table", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "key", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "key", "AttributeType": "S"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-18 09:58:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     items = [ | 
					
						
							|  |  |  |         {"key": "prefix-$LATEST", "value": "$LATEST"}, | 
					
						
							|  |  |  |         {"key": "prefix-DEV", "value": "DEV"}, | 
					
						
							|  |  |  |         {"key": "prefix-PROD", "value": "PROD"}, | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2019-10-18 09:58:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     with table.batch_writer() as batch: | 
					
						
							|  |  |  |         for item in items: | 
					
						
							|  |  |  |             batch.put_item(Item=item) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     table = dynamodb.Table("test-table") | 
					
						
							| 
									
										
										
										
											2019-10-18 09:58:09 +01:00
										 |  |  |     with assert_raises(ClientError) as ex: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         table.query(KeyConditionExpression=Key("key").begins_with("prefix-")) | 
					
						
							|  |  |  |     ex.exception.response["Error"]["Code"].should.equal("ValidationException") | 
					
						
							|  |  |  |     ex.exception.response["Error"]["Message"].should.equal( | 
					
						
							|  |  |  |         "Query key condition not supported" | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-18 09:58:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_supports_complex_expression_attribute_values(): | 
					
						
							| 
									
										
										
										
											2019-11-17 23:16:15 -08:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.create_table( | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "SHA256", "AttributeType": "S"}], | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "SHA256", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         Key={"SHA256": {"S": "sha-of-file"}}, | 
					
						
							|  |  |  |         UpdateExpression=( | 
					
						
							|  |  |  |             "SET MD5 = :md5," "MyStringSet = :string_set," "MyMap = :map" | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         ExpressionAttributeValues={ | 
					
						
							|  |  |  |             ":md5": {"S": "md5-of-file"}, | 
					
						
							|  |  |  |             ":string_set": {"SS": ["string1", "string2"]}, | 
					
						
							|  |  |  |             ":map": {"M": {"EntryKey": {"SS": ["thing1", "thing2"]}}}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     result = client.get_item( | 
					
						
							|  |  |  |         TableName="TestTable", Key={"SHA256": {"S": "sha-of-file"}} | 
					
						
							|  |  |  |     )["Item"] | 
					
						
							|  |  |  |     result.should.equal( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "MyStringSet": {"SS": ["string1", "string2"]}, | 
					
						
							|  |  |  |             "MyMap": {"M": {"EntryKey": {"SS": ["thing1", "thing2"]}}}, | 
					
						
							|  |  |  |             "SHA256": {"S": "sha-of-file"}, | 
					
						
							|  |  |  |             "MD5": {"S": "md5-of-file"}, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_supports_list_append(): | 
					
						
							| 
									
										
										
										
											2019-11-25 14:55:43 +00:00
										 |  |  |     # Verify whether the list_append operation works as expected | 
					
						
							| 
									
										
										
										
											2019-11-17 23:16:15 -08:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.create_table( | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "SHA256", "AttributeType": "S"}], | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "SHA256", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         Item={"SHA256": {"S": "sha-of-file"}, "crontab": {"L": [{"S": "bar1"}]}}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Update item using list_append expression | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         Key={"SHA256": {"S": "sha-of-file"}}, | 
					
						
							|  |  |  |         UpdateExpression="SET crontab = list_append(crontab, :i)", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":i": {"L": [{"S": "bar2"}]}}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Verify item is appended to the existing list | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     result = client.get_item( | 
					
						
							|  |  |  |         TableName="TestTable", Key={"SHA256": {"S": "sha-of-file"}} | 
					
						
							|  |  |  |     )["Item"] | 
					
						
							|  |  |  |     result.should.equal( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "SHA256": {"S": "sha-of-file"}, | 
					
						
							|  |  |  |             "crontab": {"L": [{"S": "bar1"}, {"S": "bar2"}]}, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-25 14:55:43 +00:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_supports_nested_list_append(): | 
					
						
							|  |  |  |     # Verify whether we can append a list that's inside a map | 
					
						
							|  |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "id": {"S": "nested_list_append"}, | 
					
						
							|  |  |  |             "a": {"M": {"b": {"L": [{"S": "bar1"}]}}}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Update item using list_append expression | 
					
						
							|  |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         Key={"id": {"S": "nested_list_append"}}, | 
					
						
							|  |  |  |         UpdateExpression="SET a.#b = list_append(a.#b, :i)", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":i": {"L": [{"S": "bar2"}]}}, | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#b": "b"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Verify item is appended to the existing list | 
					
						
							|  |  |  |     result = client.get_item( | 
					
						
							|  |  |  |         TableName="TestTable", Key={"id": {"S": "nested_list_append"}} | 
					
						
							|  |  |  |     )["Item"] | 
					
						
							|  |  |  |     result.should.equal( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "id": {"S": "nested_list_append"}, | 
					
						
							|  |  |  |             "a": {"M": {"b": {"L": [{"S": "bar1"}, {"S": "bar2"}]}}}, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_supports_multiple_levels_nested_list_append(): | 
					
						
							|  |  |  |     # Verify whether we can append a list that's inside a map that's inside a map  (Inception!) | 
					
						
							|  |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "id": {"S": "nested_list_append"}, | 
					
						
							|  |  |  |             "a": {"M": {"b": {"M": {"c": {"L": [{"S": "bar1"}]}}}}}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Update item using list_append expression | 
					
						
							|  |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         Key={"id": {"S": "nested_list_append"}}, | 
					
						
							|  |  |  |         UpdateExpression="SET a.#b.c = list_append(a.#b.#c, :i)", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":i": {"L": [{"S": "bar2"}]}}, | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#b": "b", "#c": "c"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Verify item is appended to the existing list | 
					
						
							|  |  |  |     result = client.get_item( | 
					
						
							|  |  |  |         TableName="TestTable", Key={"id": {"S": "nested_list_append"}} | 
					
						
							|  |  |  |     )["Item"] | 
					
						
							|  |  |  |     result.should.equal( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "id": {"S": "nested_list_append"}, | 
					
						
							|  |  |  |             "a": {"M": {"b": {"M": {"c": {"L": [{"S": "bar1"}, {"S": "bar2"}]}}}}}, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_supports_nested_list_append_onto_another_list(): | 
					
						
							|  |  |  |     # Verify whether we can take the contents of one list, and use that to fill another list | 
					
						
							|  |  |  |     # Note that the contents of the other list is completely overwritten | 
					
						
							|  |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "id": {"S": "list_append_another"}, | 
					
						
							|  |  |  |             "a": {"M": {"b": {"L": [{"S": "bar1"}]}, "c": {"L": [{"S": "car1"}]}}}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Update item using list_append expression | 
					
						
							|  |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         Key={"id": {"S": "list_append_another"}}, | 
					
						
							|  |  |  |         UpdateExpression="SET a.#c = list_append(a.#b, :i)", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":i": {"L": [{"S": "bar2"}]}}, | 
					
						
							|  |  |  |         ExpressionAttributeNames={"#b": "b", "#c": "c"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Verify item is appended to the existing list | 
					
						
							|  |  |  |     result = client.get_item( | 
					
						
							|  |  |  |         TableName="TestTable", Key={"id": {"S": "list_append_another"}} | 
					
						
							|  |  |  |     )["Item"] | 
					
						
							|  |  |  |     result.should.equal( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "id": {"S": "list_append_another"}, | 
					
						
							|  |  |  |             "a": { | 
					
						
							|  |  |  |                 "M": { | 
					
						
							|  |  |  |                     "b": {"L": [{"S": "bar1"}]}, | 
					
						
							|  |  |  |                     "c": {"L": [{"S": "bar1"}, {"S": "bar2"}]}, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-06 08:16:09 +00:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_supports_list_append_maps(): | 
					
						
							|  |  |  |     client = boto3.client("dynamodb", region_name="us-west-1") | 
					
						
							|  |  |  |     client.create_table( | 
					
						
							|  |  |  |         AttributeDefinitions=[ | 
					
						
							|  |  |  |             {"AttributeName": "id", "AttributeType": "S"}, | 
					
						
							|  |  |  |             {"AttributeName": "rid", "AttributeType": "S"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         KeySchema=[ | 
					
						
							|  |  |  |             {"AttributeName": "id", "KeyType": "HASH"}, | 
					
						
							|  |  |  |             {"AttributeName": "rid", "KeyType": "RANGE"}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         Item={ | 
					
						
							|  |  |  |             "id": {"S": "nested_list_append"}, | 
					
						
							|  |  |  |             "rid": {"S": "range_key"}, | 
					
						
							|  |  |  |             "a": {"L": [{"M": {"b": {"S": "bar1"}}}]}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Update item using list_append expression | 
					
						
							|  |  |  |     client.update_item( | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         Key={"id": {"S": "nested_list_append"}, "rid": {"S": "range_key"}}, | 
					
						
							|  |  |  |         UpdateExpression="SET a = list_append(a, :i)", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":i": {"L": [{"M": {"b": {"S": "bar2"}}}]}}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Verify item is appended to the existing list | 
					
						
							|  |  |  |     result = client.query( | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         KeyConditionExpression="id = :i AND begins_with(rid, :r)", | 
					
						
							|  |  |  |         ExpressionAttributeValues={ | 
					
						
							|  |  |  |             ":i": {"S": "nested_list_append"}, | 
					
						
							|  |  |  |             ":r": {"S": "range_key"}, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     )["Items"] | 
					
						
							|  |  |  |     result.should.equal( | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 "a": {"L": [{"M": {"b": {"S": "bar1"}}}, {"M": {"b": {"S": "bar2"}}}]}, | 
					
						
							|  |  |  |                 "rid": {"S": "range_key"}, | 
					
						
							|  |  |  |                 "id": {"S": "nested_list_append"}, | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-09 11:47:02 +00:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_supports_list_append_with_nested_if_not_exists_operation(): | 
					
						
							| 
									
										
										
										
											2020-02-09 11:58:41 +00:00
										 |  |  |     dynamo = boto3.resource("dynamodb", region_name="us-west-1") | 
					
						
							| 
									
										
										
										
											2020-02-09 11:47:02 +00:00
										 |  |  |     table_name = "test" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     dynamo.create_table( | 
					
						
							|  |  |  |         TableName=table_name, | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "Id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "Id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 20, "WriteCapacityUnits": 20}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     table = dynamo.Table(table_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     table.put_item(Item={"Id": "item-id", "nest1": {"nest2": {}}}) | 
					
						
							|  |  |  |     table.update_item( | 
					
						
							|  |  |  |         Key={"Id": "item-id"}, | 
					
						
							|  |  |  |         UpdateExpression="SET nest1.nest2.event_history = list_append(if_not_exists(nest1.nest2.event_history, :empty_list), :new_value)", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":empty_list": [], ":new_value": ["some_value"]}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table.get_item(Key={"Id": "item-id"})["Item"].should.equal( | 
					
						
							|  |  |  |         {"Id": "item-id", "nest1": {"nest2": {"event_history": ["some_value"]}}} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_catches_invalid_list_append_operation(): | 
					
						
							| 
									
										
										
										
											2019-11-17 23:16:15 -08:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client.create_table( | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "SHA256", "AttributeType": "S"}], | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "SHA256", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.put_item( | 
					
						
							|  |  |  |         TableName="TestTable", | 
					
						
							|  |  |  |         Item={"SHA256": {"S": "sha-of-file"}, "crontab": {"L": [{"S": "bar1"}]}}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Update item using invalid list_append expression | 
					
						
							|  |  |  |     with assert_raises(ParamValidationError) as ex: | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         client.update_item( | 
					
						
							|  |  |  |             TableName="TestTable", | 
					
						
							|  |  |  |             Key={"SHA256": {"S": "sha-of-file"}}, | 
					
						
							|  |  |  |             UpdateExpression="SET crontab = list_append(crontab, :i)", | 
					
						
							|  |  |  |             ExpressionAttributeValues={":i": [{"S": "bar2"}]}, | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2019-10-23 09:12:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Verify correct error is returned | 
					
						
							| 
									
										
										
										
											2019-10-23 02:26:26 -07:00
										 |  |  |     str(ex.exception).should.match("Parameter validation failed:") | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     str(ex.exception).should.match( | 
					
						
							|  |  |  |         "Invalid type for parameter ExpressionAttributeValues." | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-10-05 15:20:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-22 16:12:48 +01:00
										 |  |  | def _create_user_table(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("dynamodb", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-08-22 16:12:48 +01:00
										 |  |  |     client.create_table( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         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"}} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-08-22 16:12:48 +01:00
										 |  |  |     return client | 
					
						
							| 
									
										
										
										
											2019-11-15 15:47:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_item_if_original_value_is_none(): | 
					
						
							|  |  |  |     dynamo = boto3.resource("dynamodb", region_name="eu-central-1") | 
					
						
							|  |  |  |     dynamo.create_table( | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "job_id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         TableName="origin-rbu-dev", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "job_id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table = dynamo.Table("origin-rbu-dev") | 
					
						
							|  |  |  |     table.put_item(Item={"job_id": "a", "job_name": None}) | 
					
						
							|  |  |  |     table.update_item( | 
					
						
							|  |  |  |         Key={"job_id": "a"}, | 
					
						
							|  |  |  |         UpdateExpression="SET job_name = :output", | 
					
						
							| 
									
										
										
										
											2019-11-21 17:53:58 -05:00
										 |  |  |         ExpressionAttributeValues={":output": "updated"}, | 
					
						
							| 
									
										
										
										
											2019-11-15 15:47:18 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  |     table.scan()["Items"][0]["job_name"].should.equal("updated") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_update_nested_item_if_original_value_is_none(): | 
					
						
							|  |  |  |     dynamo = boto3.resource("dynamodb", region_name="eu-central-1") | 
					
						
							|  |  |  |     dynamo.create_table( | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "job_id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         TableName="origin-rbu-dev", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "job_id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table = dynamo.Table("origin-rbu-dev") | 
					
						
							|  |  |  |     table.put_item(Item={"job_id": "a", "job_details": {"job_name": None}}) | 
					
						
							|  |  |  |     table.update_item( | 
					
						
							|  |  |  |         Key={"job_id": "a"}, | 
					
						
							|  |  |  |         UpdateExpression="SET job_details.job_name = :output", | 
					
						
							| 
									
										
										
										
											2019-11-21 17:53:58 -05:00
										 |  |  |         ExpressionAttributeValues={":output": "updated"}, | 
					
						
							| 
									
										
										
										
											2019-11-15 15:47:18 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  |     table.scan()["Items"][0]["job_details"]["job_name"].should.equal("updated") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_allow_update_to_item_with_different_type(): | 
					
						
							|  |  |  |     dynamo = boto3.resource("dynamodb", region_name="eu-central-1") | 
					
						
							|  |  |  |     dynamo.create_table( | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "job_id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         TableName="origin-rbu-dev", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "job_id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table = dynamo.Table("origin-rbu-dev") | 
					
						
							|  |  |  |     table.put_item(Item={"job_id": "a", "job_details": {"job_name": {"nested": "yes"}}}) | 
					
						
							|  |  |  |     table.put_item(Item={"job_id": "b", "job_details": {"job_name": {"nested": "yes"}}}) | 
					
						
							|  |  |  |     table.update_item( | 
					
						
							|  |  |  |         Key={"job_id": "a"}, | 
					
						
							|  |  |  |         UpdateExpression="SET job_details.job_name = :output", | 
					
						
							|  |  |  |         ExpressionAttributeValues={":output": "updated"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table.get_item(Key={"job_id": "a"})["Item"]["job_details"][ | 
					
						
							|  |  |  |         "job_name" | 
					
						
							|  |  |  |     ].should.be.equal("updated") | 
					
						
							|  |  |  |     table.get_item(Key={"job_id": "b"})["Item"]["job_details"][ | 
					
						
							|  |  |  |         "job_name" | 
					
						
							|  |  |  |     ].should.be.equal({"nested": "yes"}) | 
					
						
							| 
									
										
										
										
											2020-02-01 22:00:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_dynamodb2 | 
					
						
							|  |  |  | def test_query_catches_when_no_filters(): | 
					
						
							|  |  |  |     dynamo = boto3.resource("dynamodb", region_name="eu-central-1") | 
					
						
							|  |  |  |     dynamo.create_table( | 
					
						
							|  |  |  |         AttributeDefinitions=[{"AttributeName": "job_id", "AttributeType": "S"}], | 
					
						
							|  |  |  |         TableName="origin-rbu-dev", | 
					
						
							|  |  |  |         KeySchema=[{"AttributeName": "job_id", "KeyType": "HASH"}], | 
					
						
							|  |  |  |         ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     table = dynamo.Table("origin-rbu-dev") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with assert_raises(ClientError) as ex: | 
					
						
							|  |  |  |         table.query(TableName="original-rbu-dev") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ex.exception.response["Error"]["Code"].should.equal("ValidationException") | 
					
						
							|  |  |  |     ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.exception.response["Error"]["Message"].should.equal( | 
					
						
							|  |  |  |         "Either KeyConditions or QueryFilter should be present" | 
					
						
							|  |  |  |     ) |