Bloop Patterns

DynamoDB Local

Connect to a local DynamoDB instance.

import boto3
import bloop

dynamodb = boto3.client("dynamodb", endpoint="http://127.0.0.1:8000")
dynamodbstreams = boto3.client("dynamodbstreams", endpoint="http://127.0.0.1:8000")

engine = bloop.Engine(dynamodb=dynamodb, dynamodbstreams=dynamodbstreams)

Note

DynamoDB Local has an issue with expressions and Global Secondary Indexes, and will throw errors about ExpressionAttributeName when you query or scan against a GSI. For example, see this issue.

Generic "if not exist"

Create a condition for any model or object that fails the operation if the item already exists.

from bloop import Condition

def if_not_exist(obj):
    condition = Condition()
    for key in obj.Meta.keys:
        condition &= key.is_(None)
    return condition

tweet = Tweet(account=uuid.uuid4(), id="numberoverzero")

engine.save(tweet, condition=if_not_exist(tweet))
# or
engine.save(tweet, condition=if_not_exist(Tweet))

Float Type

A number type with a decimal.Context that doesn't trap decimal.Rounded or decimal.Inexact.

import decimal
from bloop import Number

class Float(Number):
    def __init__(self):
        context = decimal.Context(
            Emin=-128, Emax=126, rounding=None, prec=38,
            traps=[decimal.Clamped, decimal.Overflow, decimal.Underflow])
        super().__init__(context=context)

    def dynamo_load(self, value, *, context, **kwargs):
        value = super().dynamo_load(value, context=context, **kwargs)
        # float goes in, float goes out.  You can't explain that!
        return float(value)

Warning

Do not use this pattern if you care about the accuracy of your data. This will almost certainly cause duplicate and missing data. You're probably here because dealing with decimal.Decimal can be frustrating, and it doesn't play nicely with the standard library.

Think carefully before you throw away correctness guarantees in your data layer. Before you copy and paste this into your secure bitcoin trading app, a brief reminder about floats:

>>> from decimal import Decimal
>>> d = Decimal("3.14")
>>> f = float(d)
>>> d2 = Decimal(f)
>>> d == d2
False