class DynamoDb: def __init__(self): self._local_dynamodb = None self.Model = BaseModel self.engine = None def _init_local(self, local_dynamodb="http://127.0.0.1:4444", name_template="{table_name}"): dynamodb = boto3.client("dynamodb", endpoint_url=local_dynamodb) dynamodbstreams = boto3.client("dynamodbstreams", endpoint_url=local_dynamodb) self.engine = Engine(dynamodb=dynamodb, dynamodbstreams=dynamodbstreams, table_name_template=name_template) client = patch_engine(self.engine) client.mock_ttl["MyTableName"] = True client.mock_backups["MyTableName"] = False def init_app(self, local_dynamodb=None, prefix="", skip=False): name_template = prefix + "{table_name}" if local_dynamodb is not None: self._init_local(local_dynamodb, name_template) else: self.engine = Engine(table_name_template=name_template) self.engine.bind(self.Model, skip_table_setup=skip)
def engine(session, dynamodb, dynamodbstreams): # HACK: These clients won't be used. We're going to replace the session immediately. engine = Engine(dynamodb=dynamodb, dynamodbstreams=dynamodbstreams) # Toss the clients above and hook up the mock session engine.session = session engine.bind(BaseModel) return engine
def bind_all(engine: Engine) -> None: engine.bind(Person) engine.bind(QueueEntry)
print("Resource Not Found") break else: raise e time.sleep(30) # create table with updated schema print("Create table with new schema") for _ in range(5): resp = client.list_tables() tables = resp['TableNames'] if model.Meta.table_name not in tables: print('Creating Deployment Dynamodb Table ' 'in Region: {REGION}'.format(REGION=region)) print('Creating table: ', model.Meta.table_name) engine.bind(model) break else: time.sleep(30) # wait for table to be created for _ in range(5): try: resp = client.describe_table(TableName=model.Meta.table_name) if resp['Table']['AttributeDefinitions'][0]['AttributeName'] == 'script_number' and \ resp['Table']['AttributeDefinitions'][0]['AttributeType'] == 'N': print("Check for new table schema passed") break except: pass
class Blob(engine.model): class Meta: table_name = "blobapy-blob" key_name = Column(UUID, hash_key=True, name='k') admin_key = Column(UUID, name='a') deleted = Column(Boolean, name='d') NOT_EXISTS = key_name.is_(None) def __init__(self, **kwargs): default(kwargs, "deleted", False) super().__init__(**kwargs) @classmethod def unique(cls): with exc.on_botocore("Failed to generate unique key_name"): retries = 5 while retries: obj = cls(key_name=uuid.uuid4(), admin_key=uuid.uuid4()) try: engine.save(obj, condition=Blob.NOT_EXISTS) except ConstraintViolation: retries -= 1 else: return obj raise exc.OperationFailed engine.bind()
if __name__ == "__main__": if __name__ == '__main__': import sys import json import os args = sys.argv if len(args) >= 2: stage = args[1] config_filename = 'config.' + stage + '.json' parent_dir = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) config_filepath = os.path.join(parent_dir, config_filename) try: with open(config_filepath, 'r') as fp: config = json.load(fp) except FileNotFoundError: print("Cannot find config file: {0}".format(config_filename)) sys.exit(1) region = config['REGION'] client = boto3.client('dynamodb', region_name=region) engine = Engine(dynamodb=client) print("Creating deployment table in Dynamodb: ") print('Creating table: ', Deployment.Meta.table_name) engine.bind(Deployment)
'Updated': DateTime, 'Description': Map(**{ 'Title': String, 'Body': String }), 'Sellers': Set(Integer) }) class Item(BaseModel): id = Column(UUID, hash_key=True) data = Column(Product) engine = Engine() engine.bind(BaseModel) # ================================================ # Usage # ================================================ item = Item(id=uuid.uuid4()) item.data = { 'Name': 'item-name', 'Rating': decimal.Decimal(str(random.random())), 'Updated': datetime.now(timezone.utc), 'Description': { 'Title': 'item-title', 'Body': 'item-body', }, 'Sellers': set()
class Account(Base): class Meta: read_units = 5 write_units = 2 id = Column(UUID, hash_key=True) name = Column(String) email = Column(String) by_email = GlobalSecondaryIndex(hash_key='email', projection='keys_only', write_units=1, read_units=5) class Tweet(Base): class Meta: write_units = 10 account = Column(UUID, hash_key=True) id = Column(String, range_key=True) content = Column(String) date = Column(DateTime) favorites = Column(Integer) by_date = GlobalSecondaryIndex(hash_key='date', projection='keys_only') engine.bind(base=Base)
from bloop import BaseModel, Column, String, Integer, Engine from bloop.exceptions import ConstraintViolation class NumberStore(BaseModel): key = Column(String, hash_key=True) value = Column(Integer) engine = Engine(table_name_template="my-memory-{table_name}") engine.bind(NumberStore) def get(key): try: return engine.query(NumberStore, key=NumberStore.key == key).one().value except ConstraintViolation: return None def set(key, value): update = NumberStore(key=key, value=value) engine.save(update)
import json from os import environ from uuid import uuid4, UUID import boto3 from bloop import Engine, ConstraintViolation from todoapi.models.todo import TodoItem if environ.get("AWS_SAM_LOCAL") == "true": dynamodb = boto3.client('dynamodb', endpoint_url="http://dynamodb:8000") db = Engine(dynamodb=dynamodb) db.bind(TodoItem) else: dynamodb = boto3.client('dynamodb') db = Engine(dynamodb=dynamodb) db.bind(TodoItem, skip_table_setup=True ) # we can skip the table setup because CloudFormation will do it. def get(event, context): if event['pathParameters']: todo_item = db.query(TodoItem, key=TodoItem.uuid == UUID( event['pathParameters']['todo_id'])).one() body = todo_item.as_dict else: todos = db.scan(TodoItem) body = {"todos": [todo_item.as_dict for todo_item in todos]} return {"body": json.dumps(body), "statusCode": 200}
class VendorImports(BaseModel): class Meta: table_name = "teascraper.VendorImports" vendor_id = Column(String, hash_key=True, dynamo_name="id") last_run_at = Column(DateTime, dynamo_name="lr") engine = Engine() models = [Product, VendorImports, ScrapedData] # super hack to handle table setup # in read-only prod environment for model in models: try: engine.bind(model) except BloopException: print("Skipping table setup for " + model.__name__) engine.bind(model, skip_table_setup=True) def make_product_id(vendor: str, name: str, weight: str): name = name.lower().replace(" ", "-").replace(".", "_") product_name = vendor + "." + name + "." + weight return product_name def unique_product_name(name: str, weight: str): name = name.lower().replace(" ", "-").replace(".", "_") product_name = name + "." + weight return product_name