@@ -26,7 +26,7 @@ class NoDataset(RuntimeError):
2626 """Exception raised by Entity methods which require a dataset."""
2727
2828
29- class Entity (dict ):
29+ class Entity (object ):
3030 """Entities are akin to rows in a relational database
3131
3232 An entity storing the actual instance of data.
@@ -41,9 +41,9 @@ class Entity(dict):
4141 Entities in this API act like dictionaries with extras built in that
4242 allow you to delete or persist the data stored on the entity.
4343
44- Entities are mutable and act like a subclass of a dictionary.
45- This means you could take an existing entity and change the key
46- to duplicate the object.
44+ Entities are mutable and properties can be set, updated and deleted
45+ like keys in a dictionary. This means you could take an existing entity
46+ and change the key to duplicate the object.
4747
4848 Use :func:`gcloud.datastore.dataset.Dataset.get_entity`
4949 to retrieve an existing entity.
@@ -59,10 +59,9 @@ class Entity(dict):
5959 >>> entity
6060 <Entity[{'kind': 'EntityKind', id: 1234}] {'age': 20, 'name': 'JJ'}>
6161
62- And you can convert an entity to a regular Python dictionary with the
63- `dict` builtin:
62+ And you can convert an entity to a regular Python dictionary
6463
65- >>> dict( entity)
64+ >>> entity.to_dict( )
6665 {'age': 20, 'name': 'JJ'}
6766
6867 .. note::
@@ -94,14 +93,57 @@ class Entity(dict):
9493 """
9594
9695 def __init__ (self , dataset = None , kind = None , exclude_from_indexes = ()):
97- super (Entity , self ).__init__ ()
9896 self ._dataset = dataset
97+ self ._data = {}
9998 if kind :
10099 self ._key = Key ().kind (kind )
101100 else :
102101 self ._key = None
103102 self ._exclude_from_indexes = set (exclude_from_indexes )
104103
104+ def __getitem__ (self , item_name ):
105+ return self ._data [item_name ]
106+
107+ def __setitem__ (self , item_name , value ):
108+ self ._data [item_name ] = value
109+
110+ def __delitem__ (self , item_name ):
111+ del self ._data [item_name ]
112+
113+ def clear_properties (self ):
114+ """Clear all properties from the Entity."""
115+ self ._data .clear ()
116+
117+ def update_properties (self , * args , ** kwargs ):
118+ """Allows entity properties to be updated in bulk.
119+
120+ Either takes a single dictionary or uses the keywords passed in.
121+
122+ >>> entity
123+ <Entity[{'kind': 'Foo', 'id': 1}] {}>
124+ >>> entity.update_properties(prop1=u'bar', prop2=u'baz')
125+ >>> entity
126+ <Entity[{'kind': 'Foo', 'id': 1}] {'prop1': u'bar', 'prop2': u'baz'}>
127+ >>> entity.update_properties({'prop1': 0, 'prop2': 1})
128+ >>> entity
129+ <Entity[{'kind': 'Foo', 'id': 1}] {'prop1': 0, 'prop2': 1}>
130+
131+ :raises: `TypeError` a mix of positional and keyword arguments are
132+ used or if more than one positional argument is used.
133+ """
134+ if args and kwargs or len (args ) > 1 :
135+ raise TypeError ('Only a single dictionary or keyword arguments '
136+ 'may be used' )
137+ if args :
138+ dict_arg , = args
139+ self ._data .update (dict_arg )
140+ else :
141+ self ._data .update (kwargs )
142+
143+ def to_dict (self ):
144+ """Converts the stored properties to a dictionary."""
145+ return self ._data .copy ()
146+
105147 def dataset (self ):
106148 """Get the :class:`.dataset.Dataset` in which this entity belongs.
107149
@@ -215,7 +257,7 @@ def reload(self):
215257 entity = dataset .get_entity (key .to_protobuf ())
216258
217259 if entity :
218- self .update (entity )
260+ self .update_properties (entity . to_dict () )
219261 return self
220262
221263 def save (self ):
@@ -241,7 +283,7 @@ def save(self):
241283 key_pb = connection .save_entity (
242284 dataset_id = dataset .id (),
243285 key_pb = key .to_protobuf (),
244- properties = dict ( self ) ,
286+ properties = self . _data ,
245287 exclude_from_indexes = self .exclude_from_indexes ())
246288
247289 # If we are in a transaction and the current entity needs an
@@ -284,7 +326,6 @@ def delete(self):
284326
285327 def __repr__ (self ):
286328 if self ._key :
287- return '<Entity%s %s>' % (self ._key .path (),
288- super (Entity , self ).__repr__ ())
329+ return '<Entity%s %r>' % (self ._key .path (), self ._data )
289330 else :
290- return '<Entity %s >' % (super ( Entity , self ). __repr__ () )
331+ return '<Entity %r >' % (self . _data , )
0 commit comments