Source code for aioriak.content

'''
Copyright 2013 Basho Technologies, Inc.
This file is provided to you under the Apache License,
Version 2.0 (the "License"); you may not use this file
except in compliance with the License.  You may obtain
a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
'''
from aioriak.error import RiakError


[docs]class RiakContent(object): ''' The RiakContent holds the metadata and value of a single sibling within a RiakObject. RiakObjects that have more than one sibling are considered to be in conflict. ''' def __init__(self, robject, data=None, encoded_data=None, charset=None, content_type='application/json', content_encoding=None, last_modified=None, etag=None, usermeta=None, links=None, indexes=None, exists=False): self._robject = robject self._data = data self._encoded_data = encoded_data self.charset = charset self.content_type = content_type self.content_encoding = content_encoding self.last_modified = last_modified self.etag = etag self.usermeta = usermeta or {} self.links = links or [] self.indexes = indexes or set() self.exists = exists def _get_data(self): if self._encoded_data is not None and self._data is None: self._data = self._deserialize(self._encoded_data) self._encoded_data = None return self._data def _set_data(self, value): self._encoded_data = None self._data = value data = property(_get_data, _set_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. :type mixed''') def _get_encoded_data(self): if self._data is not None and self._encoded_data is None: self._encoded_data = self._serialize(self._data) self._data = None return self._encoded_data def _set_encoded_data(self, value): self._data = None self._encoded_data = value encoded_data = property(_get_encoded_data, _set_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. :type str''') def _serialize(self, value): encoder = self._robject.bucket.get_encoder(self.content_type) if encoder: return encoder(value) elif isinstance(value, str): return value.encode() else: raise TypeError('No encoder for non-string data ' 'with content type "{0}"'. format(self.content_type)) def _deserialize(self, value): decoder = self._robject.bucket.get_decoder(self.content_type) if decoder: return decoder(value) else: raise TypeError('No decoder for content type "{0}"'. format(self.content_type)) def add_index(self, field, value): ''' add_index(field, value) Tag this object with the specified field/value pair for indexing. :param field: The index field. :type field: string :param value: The index value. :type value: string or integer :rtype: :class:`RiakObject <riak.riak_object.RiakObject>` ''' if field[-4:] not in ("_bin", "_int"): raise RiakError("Riak 2i fields must end with either '_bin'" " or '_int'.") self.indexes.add((field, value)) return self._robject def remove_index(self, field=None, value=None): ''' remove_index(field=None, value=None) Remove the specified field/value pair as an index on this object. :param field: The index field. :type field: string :param value: The index value. :type value: string or integer :rtype: :class:`RiakObject <riak.riak_object.RiakObject>` ''' if not field and not value: self.indexes.clear() elif field and not value: for index in [x for x in self.indexes if x[0] == field]: self.indexes.remove(index) elif field and value: self.indexes.remove((field, value)) else: raise RiakError("Cannot pass value without a field" " name while removing index") return self._robject remove_indexes = remove_index def set_index(self, field, value): ''' Works like :meth:`add_index`, but ensures that there is only one index on given field. If other found, then removes it first. :param field: The index field. :type field: string :param value: The index value. :type value: string or integer :rtype: :class:`RiakObject <riak.riak_object.RiakObject>` ''' to_rem = set((x for x in self.indexes if x[0] == field)) self.indexes.difference_update(to_rem) return self.add_index(field, value) def add_link(self, obj, tag=None): ''' Add a link to a RiakObject. :param obj: Either a RiakObject or 3 item link tuple consisting of (bucket, key, tag). :type obj: mixed :param tag: Optional link tag. Defaults to bucket name. It is ignored if ``obj`` is a 3 item link tuple. :type tag: string :rtype: :class:`RiakObject <riak.riak_object.RiakObject>` ''' if isinstance(obj, tuple): newlink = obj else: newlink = (obj.bucket.name, obj.key, tag) self.links.append(newlink) return self._robject