async def test_update_table(self): """ TableConnection.update_table """ with patch(PATCH_METHOD) as req: req.return_value = HttpOK(), None conn = TableConnection(self.test_table_name) params = { 'ProvisionedThroughput': { 'WriteCapacityUnits': 2, 'ReadCapacityUnits': 2 }, 'TableName': self.test_table_name } await conn.update_table( read_capacity_units=2, write_capacity_units=2 ) self.assertEqual(req.call_args[0][1], params) with patch(PATCH_METHOD) as req: req.return_value = HttpOK(), None conn = TableConnection(self.test_table_name) global_secondary_index_updates = [ { "index_name": "foo-index", "read_capacity_units": 2, "write_capacity_units": 2 } ] params = { 'TableName': self.test_table_name, 'ProvisionedThroughput': { 'ReadCapacityUnits': 2, 'WriteCapacityUnits': 2, }, 'GlobalSecondaryIndexUpdates': [ { 'Update': { 'IndexName': 'foo-index', 'ProvisionedThroughput': { 'ReadCapacityUnits': 2, 'WriteCapacityUnits': 2, } } } ] } await conn.update_table( read_capacity_units=2, write_capacity_units=2, global_secondary_index_updates=global_secondary_index_updates ) self.assertEqual(req.call_args[0][1], params)
async def test_delete_item(self): """ TableConnection.delete_item """ conn = TableConnection(self.test_table_name) with patch(PATCH_METHOD) as req: req.return_value = DESCRIBE_TABLE_DATA await conn.describe_table() with patch(PATCH_METHOD) as req: req.return_value = {} await conn.delete_item( "Amazon DynamoDB", "How do I update multiple items?") params = { 'ReturnConsumedCapacity': 'TOTAL', 'Key': { 'ForumName': { 'S': 'Amazon DynamoDB' }, 'Subject': { 'S': 'How do I update multiple items?' } }, 'TableName': self.test_table_name } self.assertEqual(req.call_args[0][1], params)
def _get_connection(cls): """ Returns a (cached) connection """ if not hasattr(cls, "Meta"): raise AttributeError( f'As of v1.0 InPynamoDB Models require a `Meta` class.\n' f'Model: {cls.__module__}.{cls.__name__}\n' f'See https://pynamodb.readthedocs.io/en/latest/release_notes.html\n' ) elif not hasattr(cls.Meta, "table_name") or cls.Meta.table_name is None: raise AttributeError( f'As of v1.0 InPyanmoDB Models must have a table_name\n' f'Model: {cls.__module__}.{cls.__name__}\n' f'See https://pynamodb.readthedocs.io/en/latest/release_notes.html' ) if cls._connection is None: cls._connection = TableConnection( cls.Meta.table_name, region=cls.Meta.region, host=cls.Meta.host, session_cls=cls.Meta.session_cls, request_timeout_seconds=cls.Meta.request_timeout_seconds, max_retry_attempts=cls.Meta.max_retry_attempts, base_backoff_ms=cls.Meta.base_backoff_ms, aws_access_key_id=cls.Meta.aws_access_key_id, aws_secret_access_key=cls.Meta.aws_secret_access_key, aws_session_token=getattr(cls.Meta, 'aws_session_token', None)) return cls._connection
async def test_rate_limited_scan(self): """ TableConnection.rate_limited_scan """ conn = TableConnection(self.test_table_name) with patch('inpynamodb.connection.AsyncConnection.rate_limited_scan' ) as req: req.return_value = {} conn.rate_limited_scan( attributes_to_get='attributes_to_get', page_size=1, limit=2, conditional_operator='AND', scan_filter={'filter': 'X'}, segment=2, total_segments=4, exclusive_start_key='EX', timeout_seconds=11, read_capacity_to_consume_per_second=12, allow_rate_limited_scan_without_consumed_capacity=False, max_sleep_between_retry=3, max_consecutive_exceptions=7, consistent_read=True, index_name='index') self.assertEqual(self.test_table_name, req.call_args[0][0]) params = { 'filter_condition': None, 'attributes_to_get': 'attributes_to_get', 'page_size': 1, 'limit': 2, 'conditional_operator': 'AND', 'scan_filter': { 'filter': 'X' }, 'segment': 2, 'total_segments': 4, 'exclusive_start_key': 'EX', 'timeout_seconds': 11, 'read_capacity_to_consume_per_second': 12, 'allow_rate_limited_scan_without_consumed_capacity': False, 'max_sleep_between_retry': 3, 'max_consecutive_exceptions': 7, 'consistent_read': True, 'index_name': 'index' } self.assertEqual(params, req.call_args[1])
async def test_query(self): """ TableConnection.query """ conn = TableConnection(self.test_table_name) with patch(PATCH_METHOD) as req: req.return_value = DESCRIBE_TABLE_DATA await conn.describe_table() with patch(PATCH_METHOD) as req: req.return_value = {} await conn.query( "FooForum", Path('Subject').startswith('thread') ) params = { 'ReturnConsumedCapacity': 'TOTAL', 'KeyConditionExpression': '(#0 = :0 AND begins_with (#1, :1))', 'ExpressionAttributeNames': { '#0': 'ForumName', '#1': 'Subject' }, 'ExpressionAttributeValues': { ':0': { 'S': 'FooForum' }, ':1': { 'S': 'thread' } }, 'TableName': self.test_table_name } self.assertEqual(req.call_args[0][1], params) with patch(PATCH_METHOD) as req: req.return_value = {} await conn.query( "FooForum", key_conditions={'Subject': {'ComparisonOperator': 'BEGINS_WITH', 'AttributeValueList': ['thread']}} ) params = { 'ReturnConsumedCapacity': 'TOTAL', 'KeyConditionExpression': '(#0 = :0 AND begins_with (#1, :1))', 'ExpressionAttributeNames': { '#0': 'ForumName', '#1': 'Subject' }, 'ExpressionAttributeValues': { ':0': { 'S': 'FooForum' }, ':1': { 'S': 'thread' } }, 'TableName': self.test_table_name } self.assertEqual(req.call_args[0][1], params)
async def test_create_table(self): """ TableConnection.create_table """ conn = TableConnection(self.test_table_name) kwargs = { 'read_capacity_units': 1, 'write_capacity_units': 1, } with pytest.raises(ValueError): await conn.create_table(**kwargs) kwargs['attribute_definitions'] = [{ 'attribute_name': 'key1', 'attribute_type': 'S' }, { 'attribute_name': 'key2', 'attribute_type': 'S' }] with pytest.raises(ValueError): await conn.create_table(**kwargs) kwargs['key_schema'] = [{ 'attribute_name': 'key1', 'key_type': 'hash' }, { 'attribute_name': 'key2', 'key_type': 'range' }] params = { 'TableName': 'ci-table', 'ProvisionedThroughput': { 'WriteCapacityUnits': 1, 'ReadCapacityUnits': 1 }, 'AttributeDefinitions': [{ 'AttributeType': 'S', 'AttributeName': 'key1' }, { 'AttributeType': 'S', 'AttributeName': 'key2' }], 'KeySchema': [{ 'KeyType': 'HASH', 'AttributeName': 'key1' }, { 'KeyType': 'RANGE', 'AttributeName': 'key2' }] } with patch(PATCH_METHOD) as req: req.return_value = {} await conn.create_table(**kwargs) kwargs = req.call_args[0][1] self.assertEqual(kwargs, params)
async def test_describe_table(self): """ TableConnection.describe_table """ with patch(PATCH_METHOD) as req: req.return_value = DESCRIBE_TABLE_DATA conn = TableConnection(self.test_table_name) await conn.describe_table() self.assertEqual(conn.table_name, self.test_table_name) self.assertEqual(req.call_args[0][1], {'TableName': 'ci-table'})
async def test_delete_table(self): """ TableConnection.delete_table """ params = {'TableName': 'ci-table'} with patch(PATCH_METHOD) as req: req.return_value = HttpOK(), None conn = TableConnection(self.test_table_name) await conn.delete_table() kwargs = req.call_args[0][1] self.assertEqual(kwargs, params)
async def test_get_item(self): """ TableConnection.get_item """ conn = TableConnection(self.test_table_name) with patch(PATCH_METHOD) as req: req.return_value = DESCRIBE_TABLE_DATA await conn.describe_table() with patch(PATCH_METHOD) as req: req.return_value = GET_ITEM_DATA item = await conn.get_item("Amazon DynamoDB", "How do I update multiple items?") self.assertEqual(item, GET_ITEM_DATA)
async def test_scan(self): """ TableConnection.scan """ conn = TableConnection(self.test_table_name) with patch(PATCH_METHOD) as req: req.return_value = DESCRIBE_TABLE_DATA await conn.describe_table() with patch(PATCH_METHOD) as req: req.return_value = HttpOK(), {} await conn.scan() params = { 'ReturnConsumedCapacity': 'TOTAL', 'TableName': self.test_table_name } self.assertEqual(req.call_args[0][1], params)
async def test_batch_get_item(self): """ TableConnection.batch_get_item """ items = [] conn = TableConnection(self.test_table_name) for i in range(10): items.append( {"ForumName": "FooForum", "Subject": "thread-{0}".format(i)} ) with patch(PATCH_METHOD) as req: req.return_value = DESCRIBE_TABLE_DATA await conn.describe_table() with patch(PATCH_METHOD) as req: req.return_value = {} await conn.batch_get_item( items ) params = { 'ReturnConsumedCapacity': 'TOTAL', 'RequestItems': { self.test_table_name: { 'Keys': [ {'ForumName': {'S': 'FooForum'}, 'Subject': {'S': 'thread-0'}}, {'ForumName': {'S': 'FooForum'}, 'Subject': {'S': 'thread-1'}}, {'ForumName': {'S': 'FooForum'}, 'Subject': {'S': 'thread-2'}}, {'ForumName': {'S': 'FooForum'}, 'Subject': {'S': 'thread-3'}}, {'ForumName': {'S': 'FooForum'}, 'Subject': {'S': 'thread-4'}}, {'ForumName': {'S': 'FooForum'}, 'Subject': {'S': 'thread-5'}}, {'ForumName': {'S': 'FooForum'}, 'Subject': {'S': 'thread-6'}}, {'ForumName': {'S': 'FooForum'}, 'Subject': {'S': 'thread-7'}}, {'ForumName': {'S': 'FooForum'}, 'Subject': {'S': 'thread-8'}}, {'ForumName': {'S': 'FooForum'}, 'Subject': {'S': 'thread-9'}} ] } } } self.assertEqual(req.call_args[0][1], params)
async def test_put_item(self): """ TableConnection.put_item """ conn = TableConnection(self.test_table_name) with patch(PATCH_METHOD) as req: req.return_value = DESCRIBE_TABLE_DATA await conn.describe_table() with patch(PATCH_METHOD) as req: req.return_value = {} await conn.put_item( 'foo-key', range_key='foo-range-key', attributes={'ForumName': 'foo-value'} ) params = { 'ReturnConsumedCapacity': 'TOTAL', 'TableName': self.test_table_name, 'Item': {'ForumName': {'S': 'foo-value'}, 'Subject': {'S': 'foo-range-key'}} } self.assertEqual(req.call_args[0][1], params) with patch(PATCH_METHOD) as req: req.return_value = {} await conn.put_item( 'foo-key', range_key='foo-range-key', attributes={'ForumName': 'foo-value'} ) params = { 'ReturnConsumedCapacity': 'TOTAL', 'Item': { 'ForumName': { 'S': 'foo-value' }, 'Subject': { 'S': 'foo-range-key' } }, 'TableName': self.test_table_name } self.assertEqual(req.call_args[0][1], params) with patch(PATCH_METHOD) as req: req.return_value = HttpOK(), {} await conn.put_item( 'foo-key', range_key='foo-range-key', attributes={'ForumName': 'foo-value'}, condition=Path('ForumName').does_not_exist() ) params = { 'ReturnConsumedCapacity': 'TOTAL', 'Item': { 'ForumName': { 'S': 'foo-value' }, 'Subject': { 'S': 'foo-range-key' } }, 'TableName': self.test_table_name, 'ConditionExpression': 'attribute_not_exists (#0)', 'ExpressionAttributeNames': { '#0': 'ForumName' } } self.assertEqual(req.call_args[0][1], params) with patch(PATCH_METHOD) as req: req.return_value = HttpOK(), {} await conn.put_item( 'foo-key', range_key='foo-range-key', attributes={'ForumName': 'foo-value'}, conditional_operator='and', expected={ 'ForumName': { 'Exists': False } } ) params = { 'ReturnConsumedCapacity': 'TOTAL', 'Item': { 'ForumName': { 'S': 'foo-value' }, 'Subject': { 'S': 'foo-range-key' } }, 'TableName': self.test_table_name, 'ConditionExpression': 'attribute_not_exists (#0)', 'ExpressionAttributeNames': { '#0': 'ForumName' } } self.assertEqual(req.call_args[0][1], params)
def test_create_connection(self): """ TableConnection() """ conn = TableConnection(self.test_table_name) self.assertIsNotNone(conn)
async def test_update_item(self): """ TableConnection.update_item """ conn = TableConnection(self.test_table_name) with patch(PATCH_METHOD) as req: req.return_value = DESCRIBE_TABLE_DATA await conn.describe_table() attr_updates = { 'Subject': { 'Value': 'foo-subject', 'Action': 'PUT' }, } with patch(PATCH_METHOD) as req: req.return_value = HttpOK(), {} await conn.update_item( 'foo-key', actions=[Path('Subject').set('foo-subject')], range_key='foo-range-key', ) params = { 'Key': { 'ForumName': { 'S': 'foo-key' }, 'Subject': { 'S': 'foo-range-key' } }, 'UpdateExpression': 'SET #0 = :0', 'ExpressionAttributeNames': { '#0': 'Subject' }, 'ExpressionAttributeValues': { ':0': { 'S': 'foo-subject' } }, 'ReturnConsumedCapacity': 'TOTAL', 'TableName': 'ci-table' } self.assertEqual(req.call_args[0][1], params) with patch(PATCH_METHOD) as req: req.return_value = HttpOK(), {} await conn.update_item( 'foo-key', attribute_updates=attr_updates, range_key='foo-range-key', ) params = { 'Key': { 'ForumName': { 'S': 'foo-key' }, 'Subject': { 'S': 'foo-range-key' } }, 'UpdateExpression': 'SET #0 = :0', 'ExpressionAttributeNames': { '#0': 'Subject' }, 'ExpressionAttributeValues': { ':0': { 'S': 'foo-subject' } }, 'ReturnConsumedCapacity': 'TOTAL', 'TableName': 'ci-table' } self.assertEqual(req.call_args[0][1], params)