Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 1.8k
#260: break datastore cycles via factories#268
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
1036f851c432a98d051223c1d516cf29c9031f60d83a62db9daf889ca2c8bcb3cc965cd539b17File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -8,12 +8,53 @@ | ||
| from google.protobuf.internal.type_checkers import Int64ValueChecker | ||
| import pytz | ||
| from gcloud.datastore.entity import Entity | ||
| from gcloud.datastore.key import Key | ||
| INT_VALUE_CHECKER = Int64ValueChecker() | ||
| class DuplicateFactory(Exception): | ||
| """Conflicting factory registration.""" | ||
| class InvalidFactory(Exception): | ||
| """Unknown factory invocation.""" | ||
| class _FactoryRegistry(object): | ||
| """Single registry for named factories. | ||
| This registry provides an API for modules to instantiate objects from | ||
| other modules without needing to import them directly, allowing us | ||
| to break circular import chains. | ||
| """ | ||
| _MARKER = object() | ||
| def __init__(self): | ||
| self._registered = {} | ||
| def register(self, name, factory): | ||
| """Register a factory by name.""" | ||
| if self._registered.get(name) not in (None, factory): | ||
| raise DuplicateFactory(name) | ||
| self._registered[name] = factory | ||
| def get(self, name, default=_MARKER): | ||
| """Look up a factory by name.""" | ||
| found = self._registered.get(name, default) | ||
| if found is self._MARKER: | ||
| raise InvalidFactory(name) | ||
| return found | ||
| def invoke(self, name, *args, **kw): | ||
| """Look up and call a factory by name.""" | ||
| return self.get(name)(*args, **kw) | ||
| _FACTORIES = _FactoryRegistry() # singleton | ||
| del _FactoryRegistry | ||
This comment was marked as spam.Sorry, something went wrong. Uh oh!There was an error while loading. Please reload this page.
This comment was marked as spam.Sorry, something went wrong. Uh oh!There was an error while loading. Please reload this page.
This comment was marked as spam.Sorry, something went wrong. Uh oh!There was an error while loading. Please reload this page. | ||
| def _get_protobuf_attribute_and_value(val): | ||
| """Given a value, return the protobuf attribute name and proper value. | ||
| @@ -47,6 +88,8 @@ def _get_protobuf_attribute_and_value(val): | ||
| :returns: A tuple of the attribute name and proper value type. | ||
| """ | ||
| key_class = _FACTORIES.get('Key') | ||
| entity_class = _FACTORIES.get('Entity') | ||
| if isinstance(val, datetime.datetime): | ||
| name = 'timestamp_microseconds' | ||
| @@ -58,8 +101,6 @@ def _get_protobuf_attribute_and_value(val): | ||
| val = val.astimezone(pytz.utc) | ||
| # Convert the datetime to a microsecond timestamp. | ||
| value = long(calendar.timegm(val.timetuple()) * 1e6) + val.microsecond | ||
| elif isinstance(val, Key): | ||
| name, value = 'key', val.to_protobuf() | ||
| elif isinstance(val, bool): | ||
| name, value = 'boolean', val | ||
| elif isinstance(val, float): | ||
| @@ -71,10 +112,12 @@ def _get_protobuf_attribute_and_value(val): | ||
| name, value = 'string', val | ||
| elif isinstance(val, (bytes, str)): | ||
| name, value = 'blob', val | ||
| elif isinstance(val, Entity): | ||
| name, value = 'entity', val | ||
| elif isinstance(val, list): | ||
| name, value = 'list', val | ||
| elif key_class and isinstance(val, key_class): | ||
| name, value = 'key', val.to_protobuf() | ||
| elif entity_class and isinstance(val, entity_class): | ||
| name, value = 'entity', val | ||
| else: | ||
| raise ValueError("Unknown protobuf attr type %s" % type(val)) | ||
| @@ -105,7 +148,7 @@ def _get_value_from_value_pb(value_pb): | ||
| result = naive.replace(tzinfo=pytz.utc) | ||
| elif value_pb.HasField('key_value'): | ||
| result = Key.from_protobuf(value_pb.key_value) | ||
| result = _FACTORIES.invoke('Key_from_protobuf', value_pb.key_value) | ||
| elif value_pb.HasField('boolean_value'): | ||
| result = value_pb.boolean_value | ||
| @@ -123,7 +166,8 @@ def _get_value_from_value_pb(value_pb): | ||
| result = value_pb.blob_value | ||
| elif value_pb.HasField('entity_value'): | ||
| result = Entity.from_protobuf(value_pb.entity_value) | ||
| result = _FACTORIES.invoke( | ||
| 'Entity_from_protobuf', value_pb.entity_value) | ||
| elif value_pb.list_value: | ||
| result = [_get_value_from_value_pb(x) for x in value_pb.list_value] | ||
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.