Source code for aioriak.riak_object

from aioriak.content import RiakContent
from aioriak.error import ConflictError


def content_property(name, doc=None):
    '''
    Delegates a property to the first sibling in a RiakObject, raising
    an error when the object is in conflict.
    '''
    def _setter(self, value):
        if len(self.siblings) == 0:
            # In this case, assume that what the user wants is to
            # create a new sibling inside an empty object.
            self.siblings = [RiakContent(self)]
        if len(self.siblings) != 1:
            raise ConflictError()
        setattr(self.siblings[0], name, value)

    def _getter(self):
        if len(self.siblings) == 0:
            return
        if len(self.siblings) != 1:
            raise ConflictError()
        return getattr(self.siblings[0], name)

    return property(_getter, _setter, doc=doc)


[docs]class RiakObject: ''' The RiakObject holds meta information about a Riak object, plus the object's data. ''' siblings = [] def __init__(self, client, bucket, key=None): ''' Construct a new RiakObject. :param client: A RiakClient object. :type client: :class:`RiakClient <aioriak.client.RiakClient>` :param bucket: A RiakBucket object. :type bucket: :class:`RiakBucket <aioriak.bucket.RiakBucket>` :param key: An optional key. If not specified, then the key is generated by the server when :func:`store` is called. :type key: string ''' if key is not None and len(key) == 0: raise ValueError('Key name must either be "None"' ' or a non-empty string.') self.client = client self.bucket = bucket self.key = key self.vclock = None self.siblings = [RiakContent(self)] self._resolver = None def _exists(self): if len(self.siblings) == 0: return False elif len(self.siblings) > 1: # Even if all of the siblings are tombstones, the object # essentially exists. return True else: return self.siblings[0].exists exists = property(_exists, None, doc=''' Whether the object exists. This is only ``False`` when there are no siblings (the object was not found), or the solitary sibling is a tombstone. ''')
[docs] async def reload(self): ''' Reload the object from Riak. When this operation completes, the object could contain new metadata and a new value, if the object was updated in Riak since it was last retrieved. .. note:: Even if the key is not found in Riak, this will return a :class:`RiakObject`. Check the :attr:`exists` property to see if the key was found. :rtype: :class:`RiakObject` ''' await self.client.get(self) return self
[docs] async def store(self, return_body=True): ''' Store the object in Riak. When this operation completes, the object could contain new metadata and possibly new data if Riak contains a newer version of the object according to the object's vector clock. :param return_body: if the newly stored object should be retrieved :type return_body: bool :rtype: :class:`RiakObject` ''' if len(self.siblings) != 1: raise ConflictError("Attempting to store an invalid object, " "resolve the siblings first") await self.client.put(self, return_body) return self
[docs] async def delete(self): ''' Delete this object from Riak. :rtype: :class:`RiakObject` ''' await self.client.delete(self) self.clear() return self
def clear(self): ''' Reset this object. :rtype: RiakObject ''' self.siblings = [] return self data = content_property('data', doc=''' The data stored in this object, as Python objects. For the raw data, use the `encoded_data` property. If unset, accessing this property will result in decoding the `encoded_data` property into Python values. The decoding is dependent on the `content_type` property and the bucket's registered decoders. ''') encoded_data = content_property('encoded_data', doc=''' The raw data stored in this object, essentially the encoded form of the `data` property. If unset, accessing this property will result in encoding the `data` property into a string. The encoding is dependent on the `content_type` property and the bucket's registered encoders. ''') charset = content_property('charset', doc=''' The character set of the encoded data as a string ''') content_encoding = content_property('content_encoding', doc=''' The encoding (compression) of the encoded data. Valid values are identity, deflate, gzip ''') usermeta = content_property('usermeta', doc=''' Arbitrary user-defined metadata dict, mapping strings to strings. ''') links = content_property('links', doc=''' A set of bucket/key/tag 3-tuples representing links to other keys. ''') content_type = content_property('content_type', doc=''' The MIME media type of the encoded data as a string ''') indexes = content_property('indexes', doc=''' The set of secondary index entries, consisting of index-name/value tuples ''') def _get_resolver(self): if callable(self._resolver): return self._resolver elif self._resolver is None: return self.bucket.resolver else: raise TypeError("resolver is not a function") def _set_resolver(self, value): if value is None or callable(value): self._resolver = value else: raise TypeError("resolver is not a function") resolver = property(_get_resolver, _set_resolver, doc='''The sibling-resolution function for this object. If the resolver is not set, the bucket's resolver will be used.''')