@@ -56,7 +56,11 @@ def __init__(self, client, bucket, key=None):
5656 self ._data = None
5757 self ._encoded_data = None
5858 self .vclock = None
59- self .metadata = {MD_USERMETA : {}, MD_INDEX : []}
59+ self .charset = None
60+ self .content_type = 'application/json'
61+ self .content_encoding = None
62+ self .usermeta = {}
63+ self .indexes = set ()
6064 self .links = []
6165 self .siblings = []
6266 self .exists = False
@@ -141,26 +145,6 @@ def _deserialize(self, value):
141145 raise TypeError ('No decoder for content type "{0}"' .
142146 format (self .content_type ))
143147
144- def _get_usermeta (self ):
145- if MD_USERMETA in self .metadata :
146- return self .metadata [MD_USERMETA ]
147- else :
148- return {}
149-
150- def _set_usermeta (self , usermeta ):
151- self .metadata [MD_USERMETA ] = usermeta
152- return self
153-
154- usermeta = property (_get_usermeta , _set_usermeta ,
155- doc = """
156- The custom user metadata on this object. This doesn't
157- include things like content type and links, but only
158- user-defined meta attributes stored with the Riak object.
159-
160- :param userdata: The user metadata to store.
161- :type userdata: dict
162- """ )
163-
164148 def add_index (self , field , value ):
165149 """
166150 Tag this object with the specified field/value pair for
@@ -176,9 +160,7 @@ def add_index(self, field, value):
176160 raise RiakError ("Riak 2i fields must end with either '_bin'"
177161 " or '_int'." )
178162
179- rie = (field , value )
180- if not rie in self .metadata [MD_INDEX ]:
181- self .metadata [MD_INDEX ].append (rie )
163+ self .indexes .add ((field , value ))
182164
183165 return self
184166
@@ -194,117 +176,20 @@ def remove_index(self, field=None, value=None):
194176 :rtype: RiakObject
195177 """
196178 if not field and not value :
197- ries = self .metadata [ MD_INDEX ][:]
179+ self .indexes . clear ()
198180 elif field and not value :
199- ries = [x for x in self .metadata [ MD_INDEX ]
200- if x [ 0 ] == field ]
181+ for index in [x for x in self .indexes if x [ 0 ] == field ]:
182+ self . indexes . remove ( index )
201183 elif field and value :
202- ries = [( field , value )]
184+ self . indexes . remove (( field , value ))
203185 else :
204186 raise RiakError ("Cannot pass value without a field"
205187 " name while removing index" )
206188
207- # This removes the index entries that's in the ries list.
208- # Done because this is preferred over metadata[MD_INDEX].remove(rie)
209- self .metadata [MD_INDEX ] = [rie for rie in self .metadata [MD_INDEX ]
210- if rie not in ries ]
211189 return self
212190
213191 remove_indexes = remove_index
214192
215- def set_indexes (self , indexes ):
216- """
217- Replaces all indexes on a Riak object. Currently supports an
218- iterable of 2 item tuples, (field, value).
219-
220- :param indexes: iterable of 2 item tuples consisting the field
221- and value. Both the field and the value must
222- be a string.
223- :rtype: RiakObject
224- """
225- # makes a copy and does type conversion
226- # this seems rather slow
227- self .metadata [MD_INDEX ] = indexes [:]
228- return self
229-
230- def get_indexes (self , field = None ):
231- """
232- Get a list of the index entries for this object. If a field is
233- provided, returns a list
234-
235- :param field: The index field.
236- :type field: string or None
237- :rtype: (array of 2 element tuples with field, value) or
238- (array of string or integer)
239- """
240- if field is None :
241- return self .metadata [MD_INDEX ]
242- else :
243- return [v for f , v in self .metadata [MD_INDEX ] if f == field ]
244-
245- def _get_content_type (self ):
246- try :
247- return self .metadata [MD_CTYPE ]
248- except KeyError :
249- if self ._data :
250- return "application/json"
251- else :
252- return "application/octet-stream"
253-
254- def _set_content_type (self , content_type ):
255- """
256- Set the content type of this object.
257-
258- :param content_type: The new content type.
259- :type content_type: string
260- :rtype: self
261- """
262- self .metadata [MD_CTYPE ] = content_type
263- return self
264-
265- content_type = property (_get_content_type , _set_content_type ,
266- doc = """
267- The content type of this object. This is either
268- ``application/json``, or the provided content type if the
269- object was created via :func:`RiakBucket.new_binary
270- <riak.bucket.RiakBucket.new_binary>`.
271-
272- :rtype: string """ )
273-
274- def set_links (self , links , all_link = False ):
275- """
276- Replaces all links to a RiakObject
277-
278- :param links: An iterable of 2-item tuples, consisting of
279- (RiakObject, tag). This could also be an iterable of just
280- a RiakObject, instead of the tuple, then a tag of None
281- would be used. Lastly, it could also be an iterable of
282- 3 item tuples with the format of (bucket, key, tag), where tag
283- could be None
284-
285- :param all_link: A boolean indicates if links are all 3 item tuples
286- objects This speeds up the operation so there is no iterating
287- through and parsing elements.
288- """
289- if all_link :
290- self .metadata [MD_LINKS ] = links
291- return self
292-
293- new_links = []
294- for item in links :
295- if isinstance (item , tuple ):
296- if len (item ) == 3 :
297- link = item
298- elif len (item ) == 2 :
299- link = (item [0 ].bucket .name , item [0 ].key , item [1 ])
300- elif isinstance (item , RiakObject ):
301- link = (item .bucket .name , item .key , None )
302-
303- new_links .append (link )
304-
305- self .metadata [MD_LINKS ] = new_links
306- return self
307-
308193 def add_link (self , obj , tag = None ):
309194 """
310195 Add a link to a RiakObject.
@@ -322,45 +207,9 @@ def add_link(self, obj, tag=None):
322207 else :
323208 newlink = (obj .bucket .name , obj .key , tag )
324209
325- self .remove_link (newlink )
326- links = self .metadata [MD_LINKS ]
327- links .append (newlink )
328- return self
329-
330- def remove_link (self , obj , tag = None ):
331- """
332- Remove a link to a RiakObject.
333-
334- :param obj: Either a RiakObject or 3 item link tuple consisting
335- of (bucket, key, tag).
336- :type obj: mixed
337- :param tag: Optional link tag. Defaults to bucket name. It is ignored
338- if ``obj`` is a 3 item link tuple.
339- :type tag: string
340- :rtype: RiakObject
341- """
342- if isinstance (obj , tuple ):
343- oldlink = obj
344- else :
345- oldlink = (obj .bucket .name , obj .key , tag )
346-
347- a = []
348- links = self .metadata .get (MD_LINKS , [])
349- for link in links :
350- if not link == oldlink :
351- a .append (link )
352-
353- self .metadata [MD_LINKS ] = a
210+ self .links .append (newlink )
354211 return self
355212
356- def get_links (self ):
357- """
358- Return an array of 3 item link tuples.
359-
360- :rtype: list
361- """
362- return self .metadata .get (MD_LINKS , [])
363-
364213 def store (self , w = None , dw = None , pw = None , return_body = True ,
365214 if_none_match = False ):
366215 """
@@ -392,14 +241,11 @@ def store(self, w=None, dw=None, pw=None, return_body=True,
392241 "store one of the siblings instead" )
393242
394243 if self .key is None :
395- key , vclock , metadata = self .client .put_new (
244+ result = self .client .put_new (
396245 self , w = w , dw = dw , pw = pw ,
397246 return_body = return_body ,
398247 if_none_match = if_none_match )
399- self .exists = True
400- self .key = key
401- self .vclock = vclock
402- self .metadata = metadata
248+ self ._populate (result )
403249 else :
404250 result = self .client .put (self , w = w , dw = dw , pw = pw ,
405251 return_body = return_body ,
@@ -422,10 +268,10 @@ def reload(self, r=None, pr=None, vtag=None):
422268 """
423269
424270 result = self .client .get (self , r = r , pr = pr , vtag = vtag )
425-
426- self .clear ()
427- if result is not None and result != ('' , []):
271+ if result and result != ('' , []):
428272 self ._populate (result )
273+ else :
274+ self .clear ()
429275
430276 return self
431277
@@ -483,30 +329,11 @@ def _populate(self, result):
483329 If a list of vtags is returned there are multiple
484330 sibling that need to be retrieved with get.
485331 """
486- self .clear ()
487- if result is None :
332+ if result is None or result is self :
488333 return self
489- elif type (result ) is list :
490- self ._set_siblings (result )
491- elif type (result ) is tuple :
492- (vclock , contents ) = result
493- self .vclock = vclock
494- if len (contents ) > 0 :
495- (metadata , data ) = contents .pop (0 )
496- self .exists = True
497- if not MD_INDEX in metadata :
498- metadata [MD_INDEX ] = []
499- self .metadata = metadata
500- self ._encoded_data = data
501- # Create objects for all siblings
502- siblings = [self ]
503- for (metadata , data ) in contents :
504- sibling = copy .copy (self )
505- sibling .metadata = metadata
506- sibling .encoded_data = data
507- siblings .append (sibling )
508- for sibling in siblings :
509- sibling ._set_siblings (siblings )
334+ elif type (result ) is RiakObject :
335+ self .clear ()
336+ self .__dict__ = result .__dict__ .copy ()
510337 else :
511338 raise RiakError ("do not know how to handle type %s" % type (result ))
512339
@@ -531,31 +358,9 @@ def get_sibling(self, i, r=None, pr=None):
531358
532359 # And make sure it knows who its siblings are
533360 self .siblings [i ] = obj
534- obj ._set_siblings ( self .siblings )
361+ obj .siblings = self .siblings
535362 return obj
536363
537- def _set_siblings (self , siblings ):
538- """
539- Set the array of siblings - used internally
540-
541- .. warning::
542-
543- Make sure this object is at index 0 so get_siblings(0)
544- always returns the current object
545- """
546- try :
547- i = siblings .index (self )
548- if i != 0 :
549- siblings .pop (i )
550- siblings .insert (0 , self )
551- except ValueError :
552- pass
553-
554- if len (siblings ) > 1 :
555- self .siblings = siblings
556- else :
557- self .siblings = []
558-
559364 def add (self , * args ):
560365 """
561366 Start assembling a Map/Reduce operation.
0 commit comments