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)
Example #3
0
    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
Example #4
0
 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)
Example #6
0
    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)