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