Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Implementing delete_multi in datastore.
Makes distinction between an iterable of keys and a single
key for delete requests and re-purposes the delete() name for
the single key case.

Follow-up after discussion in closing #701.
  • Loading branch information
dhermes committed May 26, 2015
commit 7d1bbb98f66fdeec53072a7337a5877de646d871
1 change: 1 addition & 0 deletions gcloud/datastore/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
from gcloud.datastore._implicit_environ import set_default_dataset_id
from gcloud.datastore.api import allocate_ids
from gcloud.datastore.api import delete
from gcloud.datastore.api import delete_multi
from gcloud.datastore.api import get
from gcloud.datastore.api import get_multi
from gcloud.datastore.api import put
Expand Down
25 changes: 24 additions & 1 deletion gcloud/datastore/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ def put(entity, connection=None, dataset_id=None):
put_multi([entity], connection=connection, dataset_id=dataset_id)


def delete(keys, connection=None, dataset_id=None):
def delete_multi(keys, connection=None, dataset_id=None):
"""Delete the keys in the Cloud Datastore.

:type keys: list of :class:`gcloud.datastore.key.Key`
Expand Down Expand Up @@ -371,6 +371,29 @@ def delete(keys, connection=None, dataset_id=None):
current.commit()


def delete(key, connection=None, dataset_id=None):
"""Delete the key in the Cloud Datastore.

.. note::

This is just a thin wrapper over :func:`gcloud.datastore.delete_multi`.
The backend API does not make a distinction between a single key or
multiple keys in a commit request.

:type key: :class:`gcloud.datastore.key.Key`
:param key: The key to be deleted from the datastore.

:type connection: :class:`gcloud.datastore.connection.Connection`
:param connection: Optional connection used to connect to datastore.
If not passed, inferred from the environment.

:type dataset_id: :class:`gcloud.datastore.connection.Connection`
:param dataset_id: Optional. The dataset ID used to connect to datastore.
If not passed, inferred from the environment.
"""
delete_multi([key], connection=connection, dataset_id=dataset_id)


def allocate_ids(incomplete_key, num_ids, connection=None):
"""Allocates a list of IDs from a partial key.

Expand Down
13 changes: 11 additions & 2 deletions gcloud/datastore/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"""Convenience wrapper for invoking APIs/factories w/ a dataset ID."""

from gcloud.datastore.api import delete
from gcloud.datastore.api import delete_multi
from gcloud.datastore.api import get
from gcloud.datastore.api import get_multi
from gcloud.datastore.api import put
Expand Down Expand Up @@ -73,14 +74,22 @@ def put_multi(self, entities):
return put_multi(entities, connection=self.connection,
dataset_id=self.dataset_id)

def delete(self, keys):
def delete(self, key):
"""Proxy to :func:`gcloud.datastore.api.delete`.

Passes our ``dataset_id``.
"""
return delete(keys, connection=self.connection,
return delete(key, connection=self.connection,
dataset_id=self.dataset_id)

def delete_multi(self, keys):
"""Proxy to :func:`gcloud.datastore.api.delete_multi`.

Passes our ``dataset_id``.
"""
return delete_multi(keys, connection=self.connection,
dataset_id=self.dataset_id)

def key(self, *path_args, **kwargs):
"""Proxy to :class:`gcloud.datastore.key.Key`.

Expand Down
8 changes: 4 additions & 4 deletions gcloud/datastore/demo/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
print(datastore.get(toy.key))

# And we should be able to delete it...
datastore.delete([toy.key])
datastore.delete(toy.key)

# Since we deleted it, if we do another lookup it shouldn't be there again:
print(datastore.get(toy.key))
Expand Down Expand Up @@ -74,7 +74,7 @@
print(list(query.fetch()))

# Now delete them.
datastore.delete(sample_keys)
datastore.delete_multi(sample_keys)

# You can also work inside a transaction.
# (Check the official docs for explanations of what's happening here.)
Expand All @@ -94,7 +94,7 @@
print('Committing the transaction...')

# Now that the transaction is commited, let's delete the entities.
datastore.delete([key, key2])
datastore.delete_multi([key, key2])

# To rollback a transaction, just call .rollback()
with datastore.Transaction() as xact:
Expand All @@ -118,4 +118,4 @@
print(thing.key) # This will be complete

# Now let's delete the entity.
datastore.delete([thing.key])
datastore.delete(thing.key)
38 changes: 35 additions & 3 deletions gcloud/datastore/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@ def test_implicit_connection(self):
self.assertEqual(len(CURR_BATCH.mutation.delete), 0)


class Test_delete_function(unittest2.TestCase):
class Test_delete_multi_function(unittest2.TestCase):

def setUp(self):
from gcloud.datastore._testing import _setup_defaults
Expand All @@ -817,8 +817,8 @@ def tearDown(self):
_tear_down_defaults(self)

def _callFUT(self, keys, connection=None, dataset_id=None):
from gcloud.datastore.api import delete
return delete(keys, connection=connection, dataset_id=dataset_id)
from gcloud.datastore.api import delete_multi
return delete_multi(keys, connection=connection, dataset_id=dataset_id)

def test_no_connection(self):
from gcloud.datastore import _implicit_environ
Expand Down Expand Up @@ -962,6 +962,38 @@ def test_implicit_connection_and_dataset_id(self):
self.assertEqual(len(connection._committed), 0)


class Test_delete_function(unittest2.TestCase):

def setUp(self):
from gcloud.datastore._testing import _setup_defaults
_setup_defaults(self)

def tearDown(self):
from gcloud.datastore._testing import _tear_down_defaults
_tear_down_defaults(self)

def _callFUT(self, key, connection=None, dataset_id=None):
from gcloud.datastore.api import delete
return delete(key, connection=connection, dataset_id=dataset_id)

def test_no_batch(self):
from gcloud.datastore.test_batch import _Connection
from gcloud.datastore.test_batch import _Key

# Build basic mocks needed to delete.
_DATASET = 'DATASET'
connection = _Connection()
key = _Key(_DATASET)

result = self._callFUT(key, connection=connection,
dataset_id=_DATASET)
self.assertEqual(result, None)
self.assertEqual(len(connection._committed), 1)
dataset_id, mutation = connection._committed[0]
self.assertEqual(dataset_id, _DATASET)
self.assertEqual(list(mutation.delete), [key.to_protobuf()])


class Test_allocate_ids_function(unittest2.TestCase):

def _callFUT(self, incomplete_key, num_ids, connection=None):
Expand Down
43 changes: 40 additions & 3 deletions gcloud/datastore/test_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,9 @@ def _delete(*args, **kw):
key = object()

with _Monkey(MUT, delete=_delete):
dataset.delete([key])
dataset.delete(key)

self.assertEqual(_called_with[0][0], ([key],))
self.assertEqual(_called_with[0][0], (key,))
self.assertTrue(_called_with[0][1]['connection'] is None)
self.assertEqual(_called_with[0][1]['dataset_id'], self.DATASET_ID)

Expand All @@ -232,7 +232,44 @@ def _delete(*args, **kw):
key, conn = object(), object()
dataset = self._makeOne(connection=conn)
with _Monkey(MUT, delete=_delete):
dataset.delete([key])
dataset.delete(key)

self.assertEqual(_called_with[0][0], (key,))
self.assertTrue(_called_with[0][1]['connection'] is conn)
self.assertEqual(_called_with[0][1]['dataset_id'], self.DATASET_ID)

def test_delete_multi_wo_connection(self):
from gcloud.datastore import dataset as MUT
from gcloud._testing import _Monkey

_called_with = []

def _delete_multi(*args, **kw):
_called_with.append((args, kw))

dataset = self._makeOne()
key = object()

with _Monkey(MUT, delete_multi=_delete_multi):
dataset.delete_multi([key])

self.assertEqual(_called_with[0][0], ([key],))
self.assertTrue(_called_with[0][1]['connection'] is None)
self.assertEqual(_called_with[0][1]['dataset_id'], self.DATASET_ID)

def test_delete_multi_w_connection(self):
from gcloud.datastore import dataset as MUT
from gcloud._testing import _Monkey

_called_with = []

def _delete_multi(*args, **kw):
_called_with.append((args, kw))

key, conn = object(), object()
dataset = self._makeOne(connection=conn)
with _Monkey(MUT, delete_multi=_delete_multi):
dataset.delete_multi([key])

self.assertEqual(_called_with[0][0], ([key],))
self.assertTrue(_called_with[0][1]['connection'] is conn)
Expand Down
4 changes: 2 additions & 2 deletions regression/clear_datastore.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ def remove_kind(kind):
if len(ancestors) > TRANSACTION_MAX_GROUPS:
delete_outside_transaction = True
else:
datastore.delete([result.key for result in results])
datastore.delete_multi([result.key for result in results])

if delete_outside_transaction:
datastore.delete([result.key for result in results])
datastore.delete_multi([result.key for result in results])


def remove_all_entities():
Expand Down
2 changes: 1 addition & 1 deletion regression/datastore.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def setUp(self):
def tearDown(self):
with datastore.Transaction():
keys = [entity.key for entity in self.case_entities_to_delete]
datastore.delete(keys)
datastore.delete_multi(keys)


class TestDatastoreAllocateIDs(TestDatastore):
Expand Down