Skip to content

Commit 0dbf10c

Browse files
committed
Changing constructor of Entity to take a Key.
Also: - Dropping dataset and kind from Entity constructor. - Dropping Entity.from_path factory. - Removing Connection.dataset(). - helpers.entity_from_protobuf() no longer requires dataset. - Making Entity.key a data attribute instead of a getter/setter method. - Removing Entity.dataset() (since no longer stored). - Making Entity.kind() and Entity.exclude_from_indexes() @Property's. - Removing Entity._must_dataset (no longer needed). - Adding optional connection argument to Entity.save() and Entity.reload(). - Making Entity.save() and Entity.reload() return nothing. - Updating regression/datastore.py for changes.
1 parent 6d2a5a7 commit 0dbf10c

File tree

12 files changed

+99
-298
lines changed

12 files changed

+99
-298
lines changed

gcloud/datastore/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
from gcloud import credentials
5050
from gcloud.datastore import _implicit_environ
5151
from gcloud.datastore import connection as connection_module
52+
from gcloud.datastore.dataset import Dataset
5253

5354

5455
SCOPE = ('https://www.googleapis.com/auth/datastore ',
@@ -131,7 +132,7 @@ def get_dataset(dataset_id):
131132
:returns: A dataset with a connection using the provided credentials.
132133
"""
133134
connection = get_connection()
134-
return connection.dataset(dataset_id)
135+
return Dataset(dataset_id, connection=connection)
135136

136137

137138
def _require_dataset():

gcloud/datastore/connection.py

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from gcloud import connection as base_connection
1818
from gcloud.datastore import datastore_v1_pb2 as datastore_pb
1919
from gcloud.datastore import helpers
20-
from gcloud.datastore.dataset import Dataset
2120

2221

2322
class Connection(base_connection.Connection):
@@ -154,19 +153,6 @@ def mutation(self):
154153
else:
155154
return datastore_pb.Mutation()
156155

157-
def dataset(self, *args, **kwargs):
158-
"""Factory method for Dataset objects.
159-
160-
:param args: All args and kwargs will be passed along to the
161-
:class:`gcloud.datastore.dataset.Dataset` initializer.
162-
163-
:rtype: :class:`gcloud.datastore.dataset.Dataset`
164-
:returns: A dataset object that will use this connection as
165-
its transport.
166-
"""
167-
kwargs['connection'] = self
168-
return Dataset(*args, **kwargs)
169-
170156
def lookup(self, dataset_id, key_pbs,
171157
missing=None, deferred=None, eventual=False):
172158
"""Lookup keys from a dataset in the Cloud Datastore.
@@ -608,10 +594,9 @@ def get_entities(keys, connection, dataset_id, missing=None, deferred=None):
608594
missing=missing, deferred=deferred,
609595
)
610596

611-
new_dataset = Dataset(dataset_id, connection=connection)
612597
if missing is not None:
613598
missing[:] = [
614-
helpers.entity_from_protobuf(missed_pb, dataset=new_dataset)
599+
helpers.entity_from_protobuf(missed_pb)
615600
for missed_pb in missing]
616601

617602
if deferred is not None:
@@ -621,8 +606,7 @@ def get_entities(keys, connection, dataset_id, missing=None, deferred=None):
621606

622607
entities = []
623608
for entity_pb in entity_pbs:
624-
entities.append(helpers.entity_from_protobuf(
625-
entity_pb, dataset=new_dataset))
609+
entities.append(helpers.entity_from_protobuf(entity_pb))
626610
return entities
627611

628612

gcloud/datastore/entity.py

Lines changed: 28 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,12 @@
1515
"""Class for representing a single entity in the Cloud Datastore."""
1616

1717
from gcloud.datastore import _implicit_environ
18-
from gcloud.datastore.key import Key
1918

2019

2120
class NoKey(RuntimeError):
2221
"""Exception raised by Entity methods which require a key."""
2322

2423

25-
class NoDataset(RuntimeError):
26-
"""Exception raised by Entity methods which require a dataset."""
27-
28-
2924
class Entity(dict):
3025
"""Entities are akin to rows in a relational database
3126
@@ -75,72 +70,21 @@ class Entity(dict):
7570
Python3), will be saved using the 'blob_value' field, without
7671
any decoding / encoding step.
7772
78-
:type dataset: :class:`gcloud.datastore.dataset.Dataset`
79-
:param dataset: The dataset in which this entity belongs.
80-
81-
:type kind: string
82-
:param kind: The kind of entity this is, akin to a table name in a
83-
relational database.
84-
85-
:type dataset: :class:`gcloud.datastore.dataset.Dataset`, or None
86-
:param dataset: the Dataset instance associated with this entity.
87-
88-
:type kind: str
89-
:param kind: the "kind" of the entity (see
90-
https://cloud.google.com/datastore/docs/concepts/entities#Datastore_Kinds_and_identifiers)
73+
:type key: :class:`gcloud.datastore.key.Key`
74+
:param key: Optional key to be set on entity. Required for save() or
75+
reload().
9176
77+
:type exclude_from_indexes: `tuple` of :class:`str`
9278
:param exclude_from_indexes: names of fields whose values are not to be
9379
indexed for this entity.
9480
"""
9581

96-
def __init__(self, dataset=None, kind=None, exclude_from_indexes=()):
82+
def __init__(self, key=None, exclude_from_indexes=()):
9783
super(Entity, self).__init__()
98-
# Does not inherit directly from object, so we don't use
99-
# _implicit_environ._DatastoreBase to avoid split MRO.
100-
self._dataset = dataset or _implicit_environ.DATASET
101-
if kind:
102-
self._key = Key(kind, dataset_id=self.dataset().id())
103-
else:
104-
self._key = None
84+
self.key = key
10585
self._exclude_from_indexes = set(exclude_from_indexes)
10686

107-
def dataset(self):
108-
"""Get the :class:`.dataset.Dataset` in which this entity belongs.
109-
110-
.. note::
111-
This is based on the :class:`gcloud.datastore.key.Key` set on the
112-
entity. That means that if you have no key set, the dataset might
113-
be `None`. It also means that if you change the key on the entity,
114-
this will refer to that key's dataset.
115-
116-
:rtype: :class:`gcloud.datastore.dataset.Dataset`
117-
:returns: The Dataset containing the entity if there is a key,
118-
else None.
119-
"""
120-
return self._dataset
121-
122-
def key(self, key=None):
123-
"""Get or set the :class:`.datastore.key.Key` on the current entity.
124-
125-
:type key: :class:`glcouddatastore.key.Key`
126-
:param key: The key you want to set on the entity.
127-
128-
:rtype: :class:`gcloud.datastore.key.Key` or :class:`Entity`.
129-
:returns: Either the current key (on get) or the current
130-
object (on set).
131-
132-
>>> entity.key(my_other_key) # This returns the original entity.
133-
<Entity[{'kind': 'OtherKeyKind', 'id': 1234}] {'property': 'value'}>
134-
>>> entity.key() # This returns the key.
135-
<Key[{'kind': 'OtherKeyKind', 'id': 1234}]>
136-
"""
137-
138-
if key is not None:
139-
self._key = key
140-
return self
141-
else:
142-
return self._key
143-
87+
@property
14488
def kind(self):
14589
"""Get the kind of the current entity.
14690
@@ -150,32 +94,17 @@ def kind(self):
15094
of the entity at all, just the properties and a pointer to a
15195
Key which knows its Kind.
15296
"""
97+
if self.key:
98+
return self.key.kind
15399

154-
if self._key:
155-
return self._key.kind
156-
100+
@property
157101
def exclude_from_indexes(self):
158102
"""Names of fields which are *not* to be indexed for this entity.
159103
160104
:rtype: sequence of field names
161105
"""
162106
return frozenset(self._exclude_from_indexes)
163107

164-
@classmethod
165-
def from_key(cls, key, dataset=None):
166-
"""Create entity based on :class:`.datastore.key.Key`.
167-
168-
.. note:: This is a factory method.
169-
170-
:type key: :class:`gcloud.datastore.key.Key`
171-
:param key: The key for the entity.
172-
173-
:returns: The :class:`Entity` derived from the
174-
:class:`gcloud.datastore.key.Key`.
175-
"""
176-
177-
return cls(dataset).key(key)
178-
179108
@property
180109
def _must_key(self):
181110
"""Return our key, or raise NoKey if not set.
@@ -184,23 +113,11 @@ def _must_key(self):
184113
:returns: our key
185114
:raises: NoKey if key is None
186115
"""
187-
if self._key is None:
116+
if self.key is None:
188117
raise NoKey()
189-
return self._key
190-
191-
@property
192-
def _must_dataset(self):
193-
"""Return our dataset, or raise NoDataset if not set.
194-
195-
:rtype: :class:`gcloud.datastore.key.Key`.
196-
:returns: our key
197-
:raises: NoDataset if key is None
198-
"""
199-
if self._dataset is None:
200-
raise NoDataset()
201-
return self._dataset
118+
return self.key
202119

203-
def reload(self):
120+
def reload(self, connection=None):
204121
"""Reloads the contents of this entity from the datastore.
205122
206123
This method takes the :class:`gcloud.datastore.key.Key`, loads all
@@ -211,16 +128,19 @@ def reload(self):
211128
This will override any existing properties if a different value
212129
exists remotely, however it will *not* override any properties that
213130
exist only locally.
131+
132+
:type connection: :class:`gcloud.datastore.connection.Connection`
133+
:param connection: Optional connection used to connect to datastore.
214134
"""
135+
connection = connection or _implicit_environ.CONNECTION
136+
215137
key = self._must_key
216-
connection = self._must_dataset.connection()
217138
entity = key.get(connection=connection)
218139

219140
if entity:
220141
self.update(entity)
221-
return self
222142

223-
def save(self):
143+
def save(self, connection=None):
224144
"""Save the entity in the Cloud Datastore.
225145
226146
.. note::
@@ -234,17 +154,17 @@ def save(self):
234154
Python3) map to 'string_value' in the datastore; values which are
235155
"bytes" ('str' in Python2, 'bytes' in Python3) map to 'blob_value'.
236156
237-
:rtype: :class:`gcloud.datastore.entity.Entity`
238-
:returns: The entity with a possibly updated Key.
157+
:type connection: :class:`gcloud.datastore.connection.Connection`
158+
:param connection: Optional connection used to connect to datastore.
239159
"""
160+
connection = connection or _implicit_environ.CONNECTION
161+
240162
key = self._must_key
241-
dataset = self._must_dataset
242-
connection = dataset.connection()
243163
assigned, new_id = connection.save_entity(
244-
dataset_id=dataset.id(),
164+
dataset_id=key.dataset_id,
245165
key_pb=key.to_protobuf(),
246166
properties=dict(self),
247-
exclude_from_indexes=self.exclude_from_indexes())
167+
exclude_from_indexes=self.exclude_from_indexes)
248168

249169
# If we are in a transaction and the current entity needs an
250170
# automatically assigned ID, tell the transaction where to put that.
@@ -254,13 +174,11 @@ def save(self):
254174

255175
if assigned:
256176
# Update the key (which may have been altered).
257-
self.key(self.key().completed_key(new_id))
258-
259-
return self
177+
self.key = self.key.completed_key(new_id)
260178

261179
def __repr__(self):
262-
if self._key:
263-
return '<Entity%s %s>' % (self._key.path,
180+
if self.key:
181+
return '<Entity%s %s>' % (self.key.path,
264182
super(Entity, self).__repr__())
265183
else:
266184
return '<Entity %s>' % (super(Entity, self).__repr__())

gcloud/datastore/helpers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
INT_VALUE_CHECKER = Int64ValueChecker()
3333

3434

35-
def entity_from_protobuf(pb, dataset=None):
35+
def entity_from_protobuf(pb):
3636
"""Factory method for creating an entity based on a protobuf.
3737
3838
The protobuf should be one returned from the Cloud Datastore
@@ -45,7 +45,7 @@ def entity_from_protobuf(pb, dataset=None):
4545
:returns: The entity derived from the protobuf.
4646
"""
4747
key = key_from_protobuf(pb.key)
48-
entity = Entity.from_key(key, dataset)
48+
entity = Entity(key=key)
4949

5050
for property_pb in pb.property:
5151
value = _get_value_from_property_pb(property_pb)
@@ -246,7 +246,7 @@ def _set_protobuf_value(value_pb, val):
246246
elif attr == 'entity_value':
247247
e_pb = value_pb.entity_value
248248
e_pb.Clear()
249-
key = val.key()
249+
key = val.key
250250
if key is not None:
251251
e_pb.key.CopyFrom(key.to_protobuf())
252252
for item_key, value in val.items():

gcloud/datastore/key.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def get(self, connection=None):
248248
if entities:
249249
result = entities[0]
250250
# We assume that the backend has not changed the key.
251-
result.key(self)
251+
result.key = self
252252
return result
253253

254254
def delete(self, connection=None):

gcloud/datastore/query.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,7 @@ def fetch_page(self, limit=None):
365365
# for discussion.
366366
entity_pbs, cursor_as_bytes, more_results_enum = query_results[:3]
367367

368-
entities = [helpers.entity_from_protobuf(entity,
369-
dataset=self.dataset())
368+
entities = [helpers.entity_from_protobuf(entity)
370369
for entity in entity_pbs]
371370

372371
cursor = base64.b64encode(cursor_as_bytes)

gcloud/datastore/test_connection.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -204,13 +204,6 @@ def mutation(self):
204204
found = conn.mutation()
205205
self.assertTrue(isinstance(found, Mutation))
206206

207-
def test_dataset(self):
208-
DATASET_ID = 'DATASET'
209-
conn = self._makeOne()
210-
dataset = conn.dataset(DATASET_ID)
211-
self.assertTrue(dataset.connection() is conn)
212-
self.assertEqual(dataset.id(), DATASET_ID)
213-
214207
def test_lookup_single_key_empty_response(self):
215208
from gcloud.datastore import datastore_v1_pb2 as datastore_pb
216209

@@ -1178,7 +1171,7 @@ def test_get_entities_miss_w_missing(self):
11781171
entities = self._callFUT([key], connection, DATASET_ID,
11791172
missing=missing)
11801173
self.assertEqual(entities, [])
1181-
self.assertEqual([missed.key().to_protobuf() for missed in missing],
1174+
self.assertEqual([missed.key.to_protobuf() for missed in missing],
11821175
[key.to_protobuf()])
11831176

11841177
def test_get_entities_miss_w_deferred(self):
@@ -1222,7 +1215,7 @@ def test_get_entities_hit(self):
12221215

12231216
key = Key(KIND, ID, dataset_id=DATASET_ID)
12241217
result, = self._callFUT([key], connection, DATASET_ID)
1225-
new_key = result.key()
1218+
new_key = result.key
12261219

12271220
# Check the returned value is as expected.
12281221
self.assertFalse(new_key is key)

0 commit comments

Comments
 (0)