Example #1
0
    def test_dynamodb_list_tables_long(self):
        # Reduce page size so test doesn't have to make over 100 tables
        ddb_table._PAGE_SIZE = 5

        dynamodb = DynamoDB()

        with ExitStack() as stack:
            for i in range(11):

                class Cls(DynamoModel):
                    _table_name_ = "abc" + str(i)

                table_ctx = temporary_dynamodb_table(Cls, "def" + str(i))
                stack.enter_context(table_ctx)

            self.assertEqual(len(dynamodb.list_tables()), 11)
Example #2
0
def get_movie(title, year):
    dynamodb = DynamoDB()
    table = dynamodb[Movie]

    item: Movie = table[year, title]

    return item
Example #3
0
def query_and_project_movies(year, title_range):
    dynamodb = DynamoDB()
    table = dynamodb[Movie]

    query = (Movie.year == year) & (Movie.title.between(*title_range))

    return table.query(query)
Example #4
0
def delete_underrated_movie(title, year, rating):
    dynamodb = DynamoDB()
    table = dynamodb[Movie]

    return table.delete_item(
        (year, title),
        condition_expression=Movie.info.rating <= rating,
    )
Example #5
0
def remove_actors(title, year, actor_count):
    dynamodb = DynamoDB()
    table = dynamodb[Movie]

    response = table.update_item(
        (year, title),
        update_expression=Movie.info.actors[0].remove(),
        condition_expression=Movie.info.actors.size() >= actor_count,
    )
    return response
Example #6
0
def load_movies(movies):
    dynamodb = DynamoDB()
    table = dynamodb[Movie]

    for movie_json in movies:
        movie = Movie(
            title=movie_json["title"],
            year=movie_json["year"],
            info=movie_json["info"],
        )
        table.put_item(movie)
Example #7
0
def update_movie(title, year, rating, plot, actors):
    dynamodb = DynamoDB()
    table = dynamodb[Movie]

    update_expression = (Movie.info.rating.set(rating)
                         & Movie.info.plot.set(plot)
                         & Movie.info.actors.set(actors))

    return table.update_item(
        key=(year, title),
        update_expression=update_expression,
    )
Example #8
0
def put_movie(title, year, plot, rating):
    dynamodb = DynamoDB()
    table = dynamodb[Movie]

    movie = Movie(
        title=title,
        year=year,
        info={
            "plot": plot,
            "rating": rating,
        },
    )
    response = table.put_item(movie)
    return response
Example #9
0
    def test_dynamodb_table(self):
        with self.table_without_sortkey as table:
            test_item = ModelWithoutSortkey(
                hashkey="test_value",
                another_attr=5.5,
            )

            # Table can be used
            table.put_item(test_item)
            result_item = table["test_value"]
            self.assertIsInstance(result_item, ModelWithoutSortkey)
            self.assertEqual(result_item, test_item)

            # DynamoDB can access table
            dynamodb = DynamoDB()
            ddb_result = dynamodb[ModelWithoutSortkey]["test_value"]
            self.assertIsInstance(ddb_result, ModelWithoutSortkey)
            self.assertEqual(ddb_result, test_item)
Example #10
0
def _temporary_table(
    table_name,
    delay,
    max_attempts,
    **table_kwargs,
):
    dynamodb = DynamoDB()

    dynamodb.client.create_table(TableName=table_name, **table_kwargs)

    exists_waiter = dynamodb.client.get_waiter("table_exists")
    not_exists_waiter = dynamodb.client.get_waiter("table_not_exists")

    result = exists_waiter.wait(
        TableName=table_name,
        WaiterConfig={
            "Delay": delay,
            "MaxAttempts": max_attempts,
        },
    )
    if result is not None:
        raise RuntimeError("Could not create table {!r}".format(table_name))

    try:
        yield
    finally:
        dynamodb.client.delete_table(TableName=table_name)

        result = not_exists_waiter.wait(
            TableName=table_name,
            WaiterConfig={
                "Delay": delay,
                "MaxAttempts": max_attempts,
            },
        )
        if result is not None:
            msg = "Could not delete table {!r}"
            raise RuntimeError(msg.format(table_name))
Example #11
0
    def test_dynamodb_indexes(self):
        class Student(DynamoModel):
            _table_name_ = "Students"

            # Hash key
            name = Key()

            # Sort key
            year = Key()

            homeroom = Attr()

        class ByHomeroomIndex(DynamoModel):
            _table_name_ = "Students"
            _index_name_ = "ByHomeroom"

            homeroom = Key()

            name = Key()

            year = Attr()

            def __eq__(self, other):
                if isinstance(other, ByHomeroomIndex):
                    return ((self.name == other.name)
                            & (self.homeroom == other.homeroom)
                            & (self.year == other.year))
                return NotImplemented

        with temporary_dynamodb_table(
                Student,
                "name",
                hashkey_type="S",
                sortkey_name="year",
                sortkey_type="N",
                extra_attributes=[
                    {
                        "AttributeName": "homeroom",
                        "AttributeType": "S",
                    },
                ],
                GlobalSecondaryIndexes=[{
                    "IndexName":
                    "ByHomeroom",
                    "KeySchema": [
                        {
                            "AttributeName": "homeroom",
                            "KeyType": "HASH",
                        },
                        {
                            "AttributeName": "name",
                            "KeyType": "RANGE",
                        },
                    ],
                    "Projection": {
                        "ProjectionType": "ALL",
                    },
                    "ProvisionedThroughput": {
                        "ReadCapacityUnits": 123,
                        "WriteCapacityUnits": 123,
                    },
                }],
        ) as students_table:
            item1 = Student(name="Cecil", year=10, homeroom="Faba")
            item2 = Student(name="Cecil", year=11, homeroom="Aaa")
            item3 = Student(name="Cloud", year=12, homeroom="Faba")
            item4 = Student(name="Aerith", year=12, homeroom="Faba")
            students_table.put_item(item1)
            students_table.put_item(item2)
            students_table.put_item(item3)
            students_table.put_item(item4)

            homeroom_index = DynamoDB()[ByHomeroomIndex]

            query_filter = (ByHomeroomIndex.homeroom
                            == "Faba") & (ByHomeroomIndex.name > "B")
            scan_filter = ByHomeroomIndex.year > 11

            items = list(homeroom_index.query(query_filter, scan_filter))
            self.assertEqual(len(items), 1)
            (item, ) = items

            expected = ByHomeroomIndex(name="Cloud", year=12, homeroom="Faba")
            self.assertEqual(item, expected)
Example #12
0
    def test_dynamodb_list_tables(self):
        with self.table_with_sortkey:
            with self.table_without_sortkey:
                tables = DynamoDB().list_tables()

        self.assertEqual(tables, ["test_with_sort", "test_without_sort"])
Example #13
0
def query_movies(year):
    dynamodb = DynamoDB()
    table = dynamodb[Movie]

    return table.query(Movie.year == year)
Example #14
0
def scan_movies(year_range, display_movies):
    dynamodb = DynamoDB()
    table = dynamodb[Movie]

    display_movies(table.scan(Movie.year.between(*year_range)))
Example #15
0
def temporary_dynamodb_table(
    data_model,
    hashkey_name,
    hashkey_type="S",
    sortkey_name=None,
    sortkey_type="S",
    delay=5.0,
    max_attempts=10,
    extra_attributes=None,
    **extra_kwargs,
):
    """
    Context manager creating a temporary DynamoDB table for testing.

    Ensures that the table is created and destroyed before entering and exiting
    the context.

    Parameters
    ----------
    data_model : DynamoModel
        Model to interface with this table
    hashkey_name : str
        Name of the hash key of the table
    hashkey_type : str, optional
        Type of the hash key ("S", "N", or "B"). Default "S"
    sortkey_name : str, optional
        Optional sort key for the temporary table
    sortkey_type : str, optional
        Type of the sort key if there is one ("S", "N", or "B"). Default "S"
    delay : float, optional
        Delay in seconds between checks if the table exists
    max_attempts : int, optional
        Max number of attempts to check if the table exists, after which the
        client gives up.
    extra_attributes : dict, optional
        Additional attribute definitions (boto3 specification)
    **extra_kwargs : dict
        Additional keyword arguments to pass to create_table
    """
    # TODO: make filter more specific
    warnings.simplefilter("ignore", ResourceWarning)

    table_name = data_model._table_name_

    dynamodb = DynamoDB()

    attribute_definitions = [
        {
            "AttributeName": hashkey_name,
            "AttributeType": hashkey_type,
        },
    ]
    key_schema = [
        {
            "AttributeName": hashkey_name,
            "KeyType": "HASH",
        },
    ]
    if sortkey_name is not None and sortkey_type is not None:
        attribute_definitions.append(
            {
                "AttributeName": sortkey_name,
                "AttributeType": sortkey_type,
            }
        )
        key_schema.append(
            {
                "AttributeName": sortkey_name,
                "KeyType": "RANGE",
            },
        )

    if extra_attributes:
        attribute_definitions.extend(extra_attributes)

    with _temporary_table(
        table_name,
        delay,
        max_attempts,
        AttributeDefinitions=attribute_definitions,
        KeySchema=key_schema,
        ProvisionedThroughput={"ReadCapacityUnits": 123, "WriteCapacityUnits": 123},
        **extra_kwargs,
    ):
        yield dynamodb[data_model]
Example #16
0
def load_movies(movies):
    dynamodb = DynamoDB()
    table = dynamodb[Movie]

    for movie in movies:
        table.put_item(movie)