diff --git a/moto/backends.py b/moto/backends.py index 7df167a0..1a333415 100644 --- a/moto/backends.py +++ b/moto/backends.py @@ -60,6 +60,7 @@ BACKENDS = { 'datapipeline': datapipeline_backends, 'dynamodb': dynamodb_backends, 'dynamodb2': dynamodb_backends2, + 'dynamodbstreams': dynamodbstreams_backends, 'ec2': ec2_backends, 'ecr': ecr_backends, 'ecs': ecs_backends, diff --git a/moto/dynamodb2/models.py b/moto/dynamodb2/models.py index 4283c038..e2882f1e 100644 --- a/moto/dynamodb2/models.py +++ b/moto/dynamodb2/models.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from collections import defaultdict, namedtuple +from collections import defaultdict import copy import datetime import decimal @@ -302,7 +302,7 @@ class StreamRecord(BaseModel): keys = {table.hash_key_attr: rec.hash_key.to_json()} if table.range_key_attr is not None: keys[table.range_key_attr] = rec.range_key.to_json() - + self.record = { 'eventID': uuid.uuid4().hex, 'eventName': event_name, @@ -317,7 +317,7 @@ class StreamRecord(BaseModel): 'Keys': keys } } - + if stream_type in ('NEW_IMAGE', 'NEW_AND_OLD_IMAGES'): self.record['dynamodb']['NewImage'] = new_a if stream_type in ('OLD_IMAGE', 'NEW_AND_OLD_IMAGES'): @@ -364,7 +364,7 @@ class StreamShard(BaseModel): assert start >= 0 end = start + quantity return [i.to_json() for i in self.items[start:end]] - + class Table(BaseModel): @@ -485,7 +485,7 @@ class Table(BaseModel): else: lookup_range_value = DynamoType(expected_range_value) current = self.get_item(hash_value, lookup_range_value) - + item = Item(hash_value, self.hash_key_type, range_value, self.range_key_type, item_attrs) @@ -520,10 +520,10 @@ class Table(BaseModel): self.items[hash_value][range_value] = item else: self.items[hash_value] = item - + if self.stream_shard is not None: self.stream_shard.add(current, item) - + return item def __nonzero__(self): @@ -560,7 +560,7 @@ class Table(BaseModel): if self.stream_shard is not None: self.stream_shard.add(item, None) - + return item except KeyError: return None diff --git a/moto/dynamodb2/responses.py b/moto/dynamodb2/responses.py index 73bd3ae3..d2bf99bf 100644 --- a/moto/dynamodb2/responses.py +++ b/moto/dynamodb2/responses.py @@ -175,7 +175,7 @@ class DynamoHandler(BaseResponse): table = self.dynamodb_backend.update_table_throughput(name, throughput) if 'StreamSpecification' in self.body: table = self.dynamodb_backend.update_table_streams(name, self.body['StreamSpecification']) - + return dynamo_json_dump(table.describe()) def describe_table(self): diff --git a/moto/dynamodbstreams/models.py b/moto/dynamodbstreams/models.py index 7b43eb74..41cc6e28 100644 --- a/moto/dynamodbstreams/models.py +++ b/moto/dynamodbstreams/models.py @@ -4,7 +4,6 @@ import os import json import boto3 import base64 -import datetime from moto.core import BaseBackend, BaseModel from moto.dynamodb2.models import dynamodb_backends @@ -31,7 +30,7 @@ class ShardIterator(BaseModel): self.stream_shard.table.table_arn, self.stream_shard.table.latest_stream_label, self.id) - + def to_json(self): return { 'ShardIterator': self.arn @@ -67,7 +66,7 @@ class DynamoDBStreamsBackend(BaseBackend): region = self.region self.__dict__ = {} self.__init__(region) - + @property def dynamodb(self): return dynamodb_backends[self.region] @@ -75,7 +74,7 @@ class DynamoDBStreamsBackend(BaseBackend): def _get_table_from_arn(self, arn): table_name = arn.split(':', 6)[5].split('/')[1] return self.dynamodb.get_table(table_name) - + def describe_stream(self, arn): table = self._get_table_from_arn(arn) resp = {'StreamDescription': { @@ -90,7 +89,7 @@ class DynamoDBStreamsBackend(BaseBackend): 'Shards': ([table.stream_shard.to_json()] if table.stream_shard else []) }} - + return json.dumps(resp) def list_streams(self, table_name=None): @@ -105,7 +104,7 @@ class DynamoDBStreamsBackend(BaseBackend): 'TableName': d['Table']['TableName'], 'StreamLabel': d['Table']['LatestStreamLabel'] }) - + return json.dumps({'Streams': streams}) def get_shard_iterator(self, arn, shard_id, shard_iterator_type, sequence_number=None): @@ -116,14 +115,13 @@ class DynamoDBStreamsBackend(BaseBackend): shard_iterator_type, sequence_number) self.shard_iterators[shard_iterator.arn] = shard_iterator - + return json.dumps(shard_iterator.to_json()) def get_records(self, iterator_arn, limit): shard_iterator = self.shard_iterators[iterator_arn] return json.dumps(shard_iterator.get(limit)) - available_regions = boto3.session.Session().get_available_regions( 'dynamodbstreams') diff --git a/moto/dynamodbstreams/responses.py b/moto/dynamodbstreams/responses.py index c07377d3..c9c11361 100644 --- a/moto/dynamodbstreams/responses.py +++ b/moto/dynamodbstreams/responses.py @@ -1,7 +1,5 @@ from __future__ import unicode_literals -import json - from moto.core.responses import BaseResponse from .models import dynamodbstreams_backends @@ -12,7 +10,7 @@ class DynamoDBStreamsHandler(BaseResponse): @property def backend(self): return dynamodbstreams_backends[self.region] - + def describe_stream(self): arn = self._get_param('StreamArn') return self.backend.describe_stream(arn)