Index: third_party/gsutil/third_party/boto/boto/dynamodb2/fields.py |
diff --git a/third_party/gsutil/third_party/boto/boto/dynamodb2/fields.py b/third_party/gsutil/third_party/boto/boto/dynamodb2/fields.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4443969e4e1c43d0c87bce02233a7b654410b498 |
--- /dev/null |
+++ b/third_party/gsutil/third_party/boto/boto/dynamodb2/fields.py |
@@ -0,0 +1,337 @@ |
+from boto.dynamodb2.types import STRING |
+ |
+ |
+class BaseSchemaField(object): |
+ """ |
+ An abstract class for defining schema fields. |
+ |
+ Contains most of the core functionality for the field. Subclasses must |
+ define an ``attr_type`` to pass to DynamoDB. |
+ """ |
+ attr_type = None |
+ |
+ def __init__(self, name, data_type=STRING): |
+ """ |
+ Creates a Python schema field, to represent the data to pass to |
+ DynamoDB. |
+ |
+ Requires a ``name`` parameter, which should be a string name of the |
+ field. |
+ |
+ Optionally accepts a ``data_type`` parameter, which should be a |
+ constant from ``boto.dynamodb2.types``. (Default: ``STRING``) |
+ """ |
+ self.name = name |
+ self.data_type = data_type |
+ |
+ def definition(self): |
+ """ |
+ Returns the attribute definition structure DynamoDB expects. |
+ |
+ Example:: |
+ |
+ >>> field.definition() |
+ { |
+ 'AttributeName': 'username', |
+ 'AttributeType': 'S', |
+ } |
+ |
+ """ |
+ return { |
+ 'AttributeName': self.name, |
+ 'AttributeType': self.data_type, |
+ } |
+ |
+ def schema(self): |
+ """ |
+ Returns the schema structure DynamoDB expects. |
+ |
+ Example:: |
+ |
+ >>> field.schema() |
+ { |
+ 'AttributeName': 'username', |
+ 'KeyType': 'HASH', |
+ } |
+ |
+ """ |
+ return { |
+ 'AttributeName': self.name, |
+ 'KeyType': self.attr_type, |
+ } |
+ |
+ |
+class HashKey(BaseSchemaField): |
+ """ |
+ An field representing a hash key. |
+ |
+ Example:: |
+ |
+ >>> from boto.dynamodb2.types import NUMBER |
+ >>> HashKey('username') |
+ >>> HashKey('date_joined', data_type=NUMBER) |
+ |
+ """ |
+ attr_type = 'HASH' |
+ |
+ |
+class RangeKey(BaseSchemaField): |
+ """ |
+ An field representing a range key. |
+ |
+ Example:: |
+ |
+ >>> from boto.dynamodb2.types import NUMBER |
+ >>> HashKey('username') |
+ >>> HashKey('date_joined', data_type=NUMBER) |
+ |
+ """ |
+ attr_type = 'RANGE' |
+ |
+ |
+class BaseIndexField(object): |
+ """ |
+ An abstract class for defining schema indexes. |
+ |
+ Contains most of the core functionality for the index. Subclasses must |
+ define a ``projection_type`` to pass to DynamoDB. |
+ """ |
+ def __init__(self, name, parts): |
+ self.name = name |
+ self.parts = parts |
+ |
+ def definition(self): |
+ """ |
+ Returns the attribute definition structure DynamoDB expects. |
+ |
+ Example:: |
+ |
+ >>> index.definition() |
+ { |
+ 'AttributeName': 'username', |
+ 'AttributeType': 'S', |
+ } |
+ |
+ """ |
+ definition = [] |
+ |
+ for part in self.parts: |
+ definition.append({ |
+ 'AttributeName': part.name, |
+ 'AttributeType': part.data_type, |
+ }) |
+ |
+ return definition |
+ |
+ def schema(self): |
+ """ |
+ Returns the schema structure DynamoDB expects. |
+ |
+ Example:: |
+ |
+ >>> index.schema() |
+ { |
+ 'IndexName': 'LastNameIndex', |
+ 'KeySchema': [ |
+ { |
+ 'AttributeName': 'username', |
+ 'KeyType': 'HASH', |
+ }, |
+ ], |
+ 'Projection': { |
+ 'ProjectionType': 'KEYS_ONLY', |
+ } |
+ } |
+ |
+ """ |
+ key_schema = [] |
+ |
+ for part in self.parts: |
+ key_schema.append(part.schema()) |
+ |
+ return { |
+ 'IndexName': self.name, |
+ 'KeySchema': key_schema, |
+ 'Projection': { |
+ 'ProjectionType': self.projection_type, |
+ } |
+ } |
+ |
+ |
+class AllIndex(BaseIndexField): |
+ """ |
+ An index signifying all fields should be in the index. |
+ |
+ Example:: |
+ |
+ >>> AllIndex('MostRecentlyJoined', parts=[ |
+ ... HashKey('username'), |
+ ... RangeKey('date_joined') |
+ ... ]) |
+ |
+ """ |
+ projection_type = 'ALL' |
+ |
+ |
+class KeysOnlyIndex(BaseIndexField): |
+ """ |
+ An index signifying only key fields should be in the index. |
+ |
+ Example:: |
+ |
+ >>> KeysOnlyIndex('MostRecentlyJoined', parts=[ |
+ ... HashKey('username'), |
+ ... RangeKey('date_joined') |
+ ... ]) |
+ |
+ """ |
+ projection_type = 'KEYS_ONLY' |
+ |
+ |
+class IncludeIndex(BaseIndexField): |
+ """ |
+ An index signifying only certain fields should be in the index. |
+ |
+ Example:: |
+ |
+ >>> IncludeIndex('GenderIndex', parts=[ |
+ ... HashKey('username'), |
+ ... RangeKey('date_joined') |
+ ... ], includes=['gender']) |
+ |
+ """ |
+ projection_type = 'INCLUDE' |
+ |
+ def __init__(self, *args, **kwargs): |
+ self.includes_fields = kwargs.pop('includes', []) |
+ super(IncludeIndex, self).__init__(*args, **kwargs) |
+ |
+ def schema(self): |
+ schema_data = super(IncludeIndex, self).schema() |
+ schema_data['Projection']['NonKeyAttributes'] = self.includes_fields |
+ return schema_data |
+ |
+ |
+class GlobalBaseIndexField(BaseIndexField): |
+ """ |
+ An abstract class for defining global indexes. |
+ |
+ Contains most of the core functionality for the index. Subclasses must |
+ define a ``projection_type`` to pass to DynamoDB. |
+ """ |
+ throughput = { |
+ 'read': 5, |
+ 'write': 5, |
+ } |
+ |
+ def __init__(self, *args, **kwargs): |
+ throughput = kwargs.pop('throughput', None) |
+ |
+ if throughput is not None: |
+ self.throughput = throughput |
+ |
+ super(GlobalBaseIndexField, self).__init__(*args, **kwargs) |
+ |
+ def schema(self): |
+ """ |
+ Returns the schema structure DynamoDB expects. |
+ |
+ Example:: |
+ |
+ >>> index.schema() |
+ { |
+ 'IndexName': 'LastNameIndex', |
+ 'KeySchema': [ |
+ { |
+ 'AttributeName': 'username', |
+ 'KeyType': 'HASH', |
+ }, |
+ ], |
+ 'Projection': { |
+ 'ProjectionType': 'KEYS_ONLY', |
+ }, |
+ 'ProvisionedThroughput': { |
+ 'ReadCapacityUnits': 5, |
+ 'WriteCapacityUnits': 5 |
+ } |
+ } |
+ |
+ """ |
+ schema_data = super(GlobalBaseIndexField, self).schema() |
+ schema_data['ProvisionedThroughput'] = { |
+ 'ReadCapacityUnits': int(self.throughput['read']), |
+ 'WriteCapacityUnits': int(self.throughput['write']), |
+ } |
+ return schema_data |
+ |
+ |
+class GlobalAllIndex(GlobalBaseIndexField): |
+ """ |
+ An index signifying all fields should be in the index. |
+ |
+ Example:: |
+ |
+ >>> GlobalAllIndex('MostRecentlyJoined', parts=[ |
+ ... HashKey('username'), |
+ ... RangeKey('date_joined') |
+ ... ], |
+ ... throughput={ |
+ ... 'read': 2, |
+ ... 'write': 1, |
+ ... }) |
+ |
+ """ |
+ projection_type = 'ALL' |
+ |
+ |
+class GlobalKeysOnlyIndex(GlobalBaseIndexField): |
+ """ |
+ An index signifying only key fields should be in the index. |
+ |
+ Example:: |
+ |
+ >>> GlobalKeysOnlyIndex('MostRecentlyJoined', parts=[ |
+ ... HashKey('username'), |
+ ... RangeKey('date_joined') |
+ ... ], |
+ ... throughput={ |
+ ... 'read': 2, |
+ ... 'write': 1, |
+ ... }) |
+ |
+ """ |
+ projection_type = 'KEYS_ONLY' |
+ |
+ |
+class GlobalIncludeIndex(GlobalBaseIndexField, IncludeIndex): |
+ """ |
+ An index signifying only certain fields should be in the index. |
+ |
+ Example:: |
+ |
+ >>> GlobalIncludeIndex('GenderIndex', parts=[ |
+ ... HashKey('username'), |
+ ... RangeKey('date_joined') |
+ ... ], |
+ ... includes=['gender'], |
+ ... throughput={ |
+ ... 'read': 2, |
+ ... 'write': 1, |
+ ... }) |
+ |
+ """ |
+ projection_type = 'INCLUDE' |
+ |
+ def __init__(self, *args, **kwargs): |
+ throughput = kwargs.pop('throughput', None) |
+ IncludeIndex.__init__(self, *args, **kwargs) |
+ if throughput: |
+ kwargs['throughput'] = throughput |
+ GlobalBaseIndexField.__init__(self, *args, **kwargs) |
+ |
+ def schema(self): |
+ # Pick up the includes. |
+ schema_data = IncludeIndex.schema(self) |
+ # Also the throughput. |
+ schema_data.update(GlobalBaseIndexField.schema(self)) |
+ return schema_data |