Skip to content

Commit 1dab892

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 a02a73e commit 1dab892

File tree

13 files changed

+103
-302
lines changed

13 files changed

+103
-302
lines changed

gcloud/datastore/__init__.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def get_dataset(dataset_id):
133133
:returns: A dataset with a connection using the provided credentials.
134134
"""
135135
connection = get_connection()
136-
return connection.dataset(dataset_id)
136+
return Dataset(dataset_id, connection=connection)
137137

138138

139139
def _require_dataset():
@@ -195,10 +195,9 @@ def get_entities(keys, missing=None, deferred=None,
195195
missing=missing, deferred=deferred,
196196
)
197197

198-
new_dataset = Dataset(dataset_id, connection=connection)
199198
if missing is not None:
200199
missing[:] = [
201-
helpers.entity_from_protobuf(missed_pb, dataset=new_dataset)
200+
helpers.entity_from_protobuf(missed_pb)
202201
for missed_pb in missing]
203202

204203
if deferred is not None:
@@ -208,8 +207,8 @@ def get_entities(keys, missing=None, deferred=None,
208207

209208
entities = []
210209
for entity_pb in entity_pbs:
211-
entities.append(helpers.entity_from_protobuf(
212-
entity_pb, dataset=new_dataset))
210+
entities.append(helpers.entity_from_protobuf(entity_pb))
211+
213212
return entities
214213

215214

gcloud/datastore/connection.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from gcloud import 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(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.

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
@@ -390,9 +390,8 @@ def next_page(self):
390390
else:
391391
raise ValueError('Unexpected value returned for `more_results`.')
392392

393-
dataset = self._query.dataset
394393
self._page = [
395-
helpers.entity_from_protobuf(entity, dataset=dataset)
394+
helpers.entity_from_protobuf(entity)
396395
for entity in entity_pbs]
397396
return self._page, self._more_results, self._start_cursor
398397

gcloud/datastore/test___init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ def test_get_entities_miss_w_missing(self):
234234
entities = self._callFUT([key], connection=connection,
235235
dataset_id=DATASET_ID, missing=missing)
236236
self.assertEqual(entities, [])
237-
self.assertEqual([missed.key().to_protobuf() for missed in missing],
237+
self.assertEqual([missed.key.to_protobuf() for missed in missing],
238238
[key.to_protobuf()])
239239

240240
def test_get_entities_miss_w_deferred(self):
@@ -288,7 +288,7 @@ def test_get_entities_hit(self):
288288
key = Key(KIND, ID, dataset_id=DATASET_ID)
289289
result, = self._callFUT([key], connection=connection,
290290
dataset_id=DATASET_ID)
291-
new_key = result.key()
291+
new_key = result.key
292292

293293
# Check the returned value is as expected.
294294
self.assertFalse(new_key is key)
@@ -328,7 +328,7 @@ def test_get_entities_implicit(self):
328328
}
329329
self.assertEqual(CUSTOM_CONNECTION._called_with, expected_called_with)
330330

331-
new_key = result.key()
331+
new_key = result.key
332332
# Check the returned value is as expected.
333333
self.assertFalse(new_key is key)
334334
self.assertEqual(new_key.dataset_id, DATASET_ID)

gcloud/datastore/test_connection.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -210,13 +210,6 @@ def mutation(self):
210210
found = conn.mutation()
211211
self.assertTrue(isinstance(found, Mutation))
212212

213-
def test_dataset(self):
214-
DATASET_ID = 'DATASET'
215-
conn = self._makeOne()
216-
dataset = conn.dataset(DATASET_ID)
217-
self.assertTrue(dataset.connection() is conn)
218-
self.assertEqual(dataset.id(), DATASET_ID)
219-
220213
def test_lookup_single_key_empty_response(self):
221214
from gcloud.datastore import datastore_v1_pb2 as datastore_pb
222215

0 commit comments

Comments
 (0)