Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion docs/_components/datastore-getting-started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Open a Python console and...
>>> entity = datastore.Entity(key=datastore.Key('Person'))
>>> entity['name'] = 'Your name'
>>> entity['age'] = 25
>>> entity.save()
>>> datastore.put([entity])
>>> list(Query(kind='Person').fetch())
[<Entity{...} {'name': 'Your name', 'age': 25}>]

Expand Down
2 changes: 1 addition & 1 deletion docs/_components/datastore-quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ you can create entities and save them::
>>> entity = datastore.Entity(key=datastore.Key('Person'))
>>> entity['name'] = 'Your name'
>>> entity['age'] = 25
>>> entity.save()
>>> datastore.put([entity])
>>> list(datastore.Query(kind='Person').fetch())
[<Entity{...} {'name': 'Your name', 'age': 25}>]

Expand Down
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Cloud Datastore
entity = datastore.Entity(key=datastore.Key('Person'))
entity['name'] = 'Your name'
entity['age'] = 25
entity.save()
datastore.put([entity])

Cloud Storage
~~~~~~~~~~~~~
Expand Down
1 change: 1 addition & 0 deletions gcloud/datastore/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
from gcloud.datastore.api import allocate_ids
from gcloud.datastore.api import delete
from gcloud.datastore.api import get
from gcloud.datastore.api import put
from gcloud.datastore.batch import Batch
from gcloud.datastore.connection import Connection
from gcloud.datastore.entity import Entity
Expand Down
29 changes: 29 additions & 0 deletions gcloud/datastore/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ def _get_dataset_id_from_keys(keys):
:returns: The dataset ID of the keys.
:raises: :class:`ValueError` if the key dataset IDs don't agree.
"""
if any(key is None for key in keys):
raise ValueError('None not allowed')

dataset_id = keys[0].dataset_id
# Rather than creating a list or set of all dataset IDs, we iterate
# and check. We could allow the backend to check this for us if IDs
Expand Down Expand Up @@ -133,6 +136,32 @@ def get(keys, missing=None, deferred=None, connection=None):
return entities


def put(entities, connection=None):
"""Save the entities in the Cloud Datastore.

:type entities: list of :class:`gcloud.datastore.entity.Entity`
:param entities: The entities to be saved to the datastore.

:type connection: :class:`gcloud.datastore.connection.Connection`
:param connection: Optional connection used to connect to datastore.
"""
if not entities:
return

connection = connection or _implicit_environ.CONNECTION

current = _BATCHES.top
in_batch = current is not None
if not in_batch:
keys = [entity.key for entity in entities]
dataset_id = _get_dataset_id_from_keys(keys)
current = Batch(dataset_id=dataset_id, connection=connection)
for entity in entities:
current.put(entity)

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

if not in_batch:
current.commit()


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

Expand Down
20 changes: 10 additions & 10 deletions gcloud/datastore/demo/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
toy.update({'name': 'Toy'})

# Now let's save it to our datastore:
toy.save()
datastore.put([toy])

# If we look it up by its key, we should find it...
print(datastore.get([toy.key]))
Expand All @@ -55,7 +55,7 @@
entity = datastore.Entity(key)
entity['name'] = name
entity['age'] = age
entity.save()
datastore.put([entity])
# We'll start by look at all Thing entities:
query = datastore.Query(kind='Thing')

Expand All @@ -76,41 +76,41 @@

# You can also work inside a transaction.
# (Check the official docs for explanations of what's happening here.)
with datastore.Transaction():
with datastore.Transaction() as xact:
print('Creating and saving an entity...')
key = datastore.Key('Thing', 'foo')
thing = datastore.Entity(key)
thing['age'] = 10
thing.save()
xact.put(thing)

This comment was marked as spam.


print('Creating and saving another entity...')
key2 = datastore.Key('Thing', 'bar')
thing2 = datastore.Entity(key2)
thing2['age'] = 15
thing2.save()
xact.put(thing2)

print('Committing the transaction...')

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

# To rollback a transaction, just call .rollback()
with datastore.Transaction() as t:
with datastore.Transaction() as xact:
key = datastore.Key('Thing', 'another')
thing = datastore.Entity(key)
thing.save()
t.rollback()
xact.put(thing)
xact.rollback()

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.


# Let's check if the entity was actually created:
created = datastore.get([key])
print('yes' if created else 'no')

# 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 datastore.Transaction():
with datastore.Transaction() as xact:
key = datastore.Key('Thing') # partial
thing = datastore.Entity(key)
thing.save()
xact.put(thing)
print(thing.key) # This will still be partial

print(thing.key) # This will be complete
Expand Down
59 changes: 2 additions & 57 deletions gcloud/datastore/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@

"""Class for representing a single entity in the Cloud Datastore."""

from gcloud.datastore import _implicit_environ


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


class Entity(dict):
"""Entities are akin to rows in a relational database
Expand Down Expand Up @@ -70,8 +64,8 @@ class Entity(dict):
any decoding / encoding step.

:type key: :class:`gcloud.datastore.key.Key`
:param key: Optional key to be set on entity. Required for :meth:`save()`
or :meth:`reload()`.
:param key: Optional key to be set on entity. Required for
:func:`gcloud.datastore.put()`

:type exclude_from_indexes: tuple of string
:param exclude_from_indexes: Names of fields whose values are not to be
Expand Down Expand Up @@ -104,55 +98,6 @@ def exclude_from_indexes(self):
"""
return frozenset(self._exclude_from_indexes)

@property
def _must_key(self):
"""Return our key, or raise NoKey if not set.

:rtype: :class:`gcloud.datastore.key.Key`.
:returns: The entity's key.
:raises: :class:`NoKey` if no key is set.
"""
if self.key is None:
raise NoKey()
return self.key

def save(self, connection=None):
"""Save the entity in the Cloud Datastore.

.. note::
Any existing properties for the entity will be replaced by those
currently set on this instance. Already-stored properties which do
not correspond to keys set on this instance will be removed from
the datastore.

.. note::
Property values which are "text" (``unicode`` in Python2, ``str`` in
Python3) map to 'string_value' in the datastore; values which are
"bytes" (``str`` in Python2, ``bytes`` in Python3) map to
'blob_value'.

:type connection: :class:`gcloud.datastore.connection.Connection`
:param connection: Optional connection used to connect to datastore.
"""
connection = connection or _implicit_environ.CONNECTION

key = self._must_key
assigned, new_id = connection.save_entity(
dataset_id=key.dataset_id,
key_pb=key.to_protobuf(),
properties=dict(self),
exclude_from_indexes=self.exclude_from_indexes)

# If we are in a transaction and the current entity needs an
# automatically assigned ID, tell the transaction where to put that.
transaction = connection.transaction()
if transaction and key.is_partial:
transaction.add_auto_id_entity(self)

if assigned:
# Update the key (which may have been altered).
self.key = self.key.completed_key(new_id)

def __repr__(self):
if self.key:
return '<Entity%s %s>' % (self.key.path,
Expand Down
Loading