Skip to content
Closed
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
Next Next commit
Drop 'Dataset.query' and 'Dataset.entity' convenience APIs.
Point instead to constructing Query and Entity directly.

Addresses #260, but only partially, for gcloud.datastore.
  • Loading branch information
tseaver committed Oct 22, 2014
commit 1036f8592c60a8dc7aa91e6075cb0e08877be780
10 changes: 7 additions & 3 deletions gcloud/datastore/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
... 'long-email@googleapis.com',
... '/path/to/private.key')
>>> # Then do other things...
>>> query = dataset.query().kind('EntityKind')
>>> entity = dataset.entity('EntityKind')
>>> from gcloud.datastore.entity import Entity
>>> from gcloud.datastore.query import Query
>>> query = Query('EntityKind', dataset)
>>> entity = Entity(dataset, 'EntityKind')

This comment was marked as spam.

This comment was marked as spam.


The main concepts with this API are:

Expand Down Expand Up @@ -80,7 +82,9 @@ def get_dataset(dataset_id, client_email, private_key_path):
>>> from gcloud import datastore
>>> dataset = datastore.get_dataset('dataset-id', email, key_path)
>>> # Now you can do things with the dataset.
>>> dataset.query().kind('TestKind').fetch()
>>> from gcloud.datastore.query import Query
>>> query = Query('TestKind', dataset)
>>> query.fetch()
[...]

:type dataset_id: string
Expand Down
3 changes: 2 additions & 1 deletion gcloud/datastore/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,10 @@ def run_query(self, dataset_id, query_pb, namespace=None):
uses this method to fetch data:

>>> from gcloud import datastore
>>> from gcloud.datastore.query import Query
>>> connection = datastore.get_connection(email, key_path)
>>> dataset = connection.dataset('dataset-id')
>>> query = dataset.query().kind('MyKind').filter('property =', 'val')
>>> query = Query('MyKind', dataset).filter('property =', 'val')

Using the `fetch`` method...

Expand Down
28 changes: 0 additions & 28 deletions gcloud/datastore/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,34 +60,6 @@ def id(self):

return self._id

def query(self, *args, **kwargs):
"""Create a query bound to this dataset.

:param args: positional arguments, passed through to the Query

:param kw: keyword arguments, passed through to the Query

:rtype: :class:`gcloud.datastore.query.Query`
:returns: a new Query instance, bound to this dataset.
"""
# This import is here to avoid circular references.
from gcloud.datastore.query import Query
kwargs['dataset'] = self
return Query(*args, **kwargs)

def entity(self, kind):
"""Create an entity bound to this dataset.

:type kind: string
:param kind: the "kind" of the new entity.

:rtype: :class:`gcloud.datastore.entity.Entity`
:returns: a new Entity instance, bound to this dataset.
"""
# This import is here to avoid circular references.
from gcloud.datastore.entity import Entity
return Entity(dataset=self, kind=kind)

def transaction(self, *args, **kwargs):
"""Create a transaction bound to this dataset.

Expand Down
15 changes: 9 additions & 6 deletions gcloud/datastore/demo/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@

# Let's start by importing the demo module and getting a dataset:
from gcloud.datastore import demo
from gcloud.datastore.entity import Entity
from gcloud.datastore.query import Query

dataset = demo.get_dataset()

# Let's create a new entity of type "Thing" and name it 'Toy':
toy = dataset.entity('Thing')
toy = Entity(dataset, 'Thing')
toy.update({'name': 'Toy'})

# Now let's save it to our datastore:
Expand All @@ -26,7 +29,7 @@

# Now let's try a more advanced query.
# We'll start by look at all Thing entities:
query = dataset.query().kind('Thing')
query = Query('Thing', dataset)

# Let's look at the first two.
print query.limit(2).fetch()
Expand All @@ -42,13 +45,13 @@
# (Check the official docs for explanations of what's happening here.)
with dataset.transaction():
print 'Creating and savng an entity...'
thing = dataset.entity('Thing')
thing = Entity(dataset, 'Thing')
thing.key(thing.key().name('foo'))
thing['age'] = 10
thing.save()

print 'Creating and saving another entity...'
thing2 = dataset.entity('Thing')
thing2 = Entity(dataset, 'Thing')
thing2.key(thing2.key().name('bar'))
thing2['age'] = 15
thing2.save()
Expand All @@ -60,7 +63,7 @@

# To rollback a transaction, just call .rollback()
with dataset.transaction() as t:
thing = dataset.entity('Thing')
thing = Entity(dataset, 'Thing')
thing.key(thing.key().name('another'))
thing.save()
t.rollback()
Expand All @@ -72,7 +75,7 @@
# Remember, a key won't be complete until the transaction is commited.
# That is, while inside the transaction block, thing.key() will be incomplete.
with dataset.transaction():
thing = dataset.entity('Thing')
thing = Entity(dataset, 'Thing')
thing.save()
print thing.key() # This will be partial

Expand Down
9 changes: 2 additions & 7 deletions gcloud/datastore/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,10 @@ class Entity(dict):
This means you could take an existing entity and change the key
to duplicate the object.

This can be used on its own, however it is likely easier to use
the shortcut methods provided by :class:`gcloud.datastore.dataset.Dataset`
Entities can be constructed directly, or obtained via
the "lookup" methods provided by :class:`gcloud.datastore.dataset.Dataset`
such as:

- :func:`gcloud.datastore.dataset.Dataset.entity` to create a new entity.

>>> dataset.entity('MyEntityKind')
<Entity[{'kind': 'MyEntityKind'}] {}>

- :func:`gcloud.datastore.dataset.Dataset.get_entity`
to retrieve an existing entity.

Expand Down
18 changes: 3 additions & 15 deletions gcloud/datastore/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,13 @@ class Query(object):
and a clone is returned whenever
any part of the query is modified::

>>> query = Query('MyKind')
>>> query = Query('MyKind', dataset)
>>> limited_query = query.limit(10)
>>> query.limit() == 10
False
>>> limited_query.limit() == 10
True

You typically won't construct a :class:`Query`
by initializing it like ``Query('MyKind', dataset=...)``
but instead use the helper
:func:`gcloud.datastore.dataset.Dataset.query` method
which generates a query that can be executed
without any additional work::

>>> from gcloud import datastore
>>> dataset = datastore.get_dataset('dataset-id', email, key_path)
>>> query = dataset.query('MyKind')

:type kind: string
:param kind: The kind to query.

Expand Down Expand Up @@ -163,13 +152,12 @@ def ancestor(self, ancestor):
For example::

>>> parent_key = Key.from_path('Person', '1')
>>> query = dataset.query('Person')
>>> query = Query('Person', dataset)
>>> filtered_query = query.ancestor(parent_key)

If you don't have a :class:`gcloud.datastore.key.Key` but just
know the path, you can provide that as well::

>>> query = dataset.query('Person')
>>> filtered_query = query.ancestor(['Person', '1'])

Each call to ``.ancestor()`` returns a cloned :class:`Query`,
Expand Down Expand Up @@ -306,7 +294,7 @@ def fetch(self, limit=None):

>>> from gcloud import datastore
>>> dataset = datastore.get_dataset('dataset-id', email, key_path)
>>> query = dataset.query('Person').filter('name =', 'Sally')
>>> query = Query('Person', dataset).filter('name =', 'Sally')
>>> query.fetch()
[<Entity object>, <Entity object>, ...]
>>> query.fetch(1)
Expand Down
17 changes: 0 additions & 17 deletions gcloud/datastore/test_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,6 @@ def test_ctor_explicit(self):
self.assertEqual(dataset.id(), DATASET_ID)
self.assertTrue(dataset.connection() is CONNECTION)

def test_query_factory(self):
from gcloud.datastore.query import Query
DATASET_ID = 'DATASET'
dataset = self._makeOne(DATASET_ID)
query = dataset.query()
self.assertIsInstance(query, Query)
self.assertTrue(query.dataset() is dataset)

def test_entity_factory(self):
from gcloud.datastore.entity import Entity
DATASET_ID = 'DATASET'
KIND = 'KIND'
dataset = self._makeOne(DATASET_ID)
entity = dataset.entity(KIND)
self.assertIsInstance(entity, Entity)
self.assertEqual(entity.kind(), KIND)

def test_transaction_factory(self):
from gcloud.datastore.transaction import Transaction
DATASET_ID = 'DATASET'
Expand Down
23 changes: 11 additions & 12 deletions gcloud/datastore/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ class Transaction(object):
That means,
if you try::

>>> from gcloud.datastore.entity import Entity
>>> with dataset.transaction():
... entity = dataset.entity('Thing').save()
... entity = Entity(dataset, 'Thing').save()

``entity`` won't have a complete Key
until the transaction is committed.
Expand All @@ -53,7 +54,7 @@ class Transaction(object):
to the entity::

>>> with dataset.transaction():
... entity = dataset.entity('Thing')
... entity = Entity(dataset, 'Thing').save()
... entity.save()
... assert entity.key().is_partial() # There is no ID on this key.
>>> assert not entity.key().is_partial() # There *is* an ID.
Expand All @@ -75,7 +76,7 @@ class Transaction(object):
>>> transaction = dataset.transaction()
>>> transaction.begin()

>>> entity = dataset.entity('Thing')
>>> entity = Entity(dataset, 'Thing')
>>> entity.save()

>>> if error:
Expand All @@ -94,19 +95,17 @@ class Transaction(object):

For example, this is perfectly valid::

>>> from gcloud import datastore
>>> dataset = datastore.get_dataset('dataset-id', email, key_path)
>>> with dataset.transaction():
... dataset.entity('Thing').save()
... Entity(dataset, 'Thing').save()

However, this **wouldn't** be acceptable::

>>> from gcloud import datastore
>>> dataset = datastore.get_dataset('dataset-id', email, key_path)
>>> with dataset.transaction():
... dataset.entity('Thing').save()
... with dataset.transaction():
... dataset.entity('Thing').save()
... Entity(dataset, 'Thing').save()
... with dataset.transaction():
... Entity(dataset, 'Thing').save()

Technically, it looks like the Protobuf API supports this type of pattern,
however it makes the code particularly messy.
Expand All @@ -116,9 +115,9 @@ class Transaction(object):
>>> dataset1 = datastore.get_dataset('dataset-id', email, key_path)
>>> dataset2 = datastore.get_dataset('dataset-id', email, key_path)
>>> with dataset1.transaction():
... dataset1.entity('Thing').save()
... with dataset2.transaction():
... dataset2.entity('Thing').save()
... Entity(dataset1, 'Thing').save()
... with dataset2.transaction():
... Entity(dataset2, 'Thing').save()

:type dataset: :class:`gcloud.datastore.dataset.Dataset`
:param dataset: The dataset to which this :class:`Transaction` belongs.
Expand Down