Skip to content

Commit

Permalink
Finish up.
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Rossi committed Sep 3, 2019
1 parent 0bdcbca commit f316a37
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 13 deletions.
10 changes: 6 additions & 4 deletions google/cloud/ndb/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -3933,11 +3933,13 @@ def _to_datastore(self, entity, data, prefix="", repeated=False):
continue

for prop in _properties_of(value):
keys.extend(prop._to_datastore(
value, data, prefix=next_prefix, repeated=next_repeated
))
keys.extend(
prop._to_datastore(
value, data, prefix=next_prefix, repeated=next_repeated
)
)

return keys
return set(keys)


class LocalStructuredProperty(BlobProperty):
Expand Down
1 change: 1 addition & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ def context():
stub=mock.Mock(spec=()),
eventloop=TestingEventLoop(),
datastore_policy=True,
legacy_data=False,
)
return context

Expand Down
5 changes: 1 addition & 4 deletions tests/system/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,5 @@ def namespace():
@pytest.fixture
def client_context(namespace):
client = ndb.Client(namespace=namespace)
with client.context(
cache_policy=False,
legacy_data=False,
) as the_context:
with client.context(cache_policy=False, legacy_data=False) as the_context:
yield the_context
6 changes: 3 additions & 3 deletions tests/system/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -1168,9 +1168,9 @@ def make_entities():
SomeKind.foo < 2
)

# This counter-intuitive result is consistent with Legacy NDB behavior and
# is a result of the odd way Datastore handles projection queries with
# array valued properties:
# This counter-intuitive result is consistent with Legacy NDB behavior
# and is a result of the odd way Datastore handles projection queries
# with array valued properties:
#
# https://cloud.google.com/datastore/docs/concepts/queries#projections_and_array-valued_properties
#
Expand Down
106 changes: 104 additions & 2 deletions tests/unit/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1308,6 +1308,50 @@ def test__get_for_dict():
# Cache is untouched.
assert model.Property._FIND_METHODS_CACHE == {}

@staticmethod
def test__to_datastore():
class SomeKind(model.Model):
prop = model.Property()

entity = SomeKind(prop="foo")
data = {}
assert SomeKind.prop._to_datastore(entity, data) == ("prop",)
assert data == {"prop": "foo"}

@staticmethod
def test__to_datastore_prop_is_repeated():
class SomeKind(model.Model):
prop = model.Property(repeated=True)

entity = SomeKind(prop=["foo", "bar"])
data = {}
assert SomeKind.prop._to_datastore(entity, data) == ("prop",)
assert data == {"prop": ["foo", "bar"]}

@staticmethod
def test__to_datastore_w_prefix():
class SomeKind(model.Model):
prop = model.Property()

entity = SomeKind(prop="foo")
data = {}
assert SomeKind.prop._to_datastore(entity, data, prefix="pre.") == (
"pre.prop",
)
assert data == {"pre.prop": "foo"}

@staticmethod
def test__to_datastore_w_prefix_ancestor_repeated():
class SomeKind(model.Model):
prop = model.Property()

entity = SomeKind(prop="foo")
data = {}
assert SomeKind.prop._to_datastore(
entity, data, prefix="pre.", repeated=True
) == ("pre.prop",)
assert data == {"pre.prop": ["foo"]}


class Test__validate_key:
@staticmethod
Expand Down Expand Up @@ -3083,6 +3127,63 @@ class Simple(model.Model):
value = object()
assert prop._from_base_type(value) is value

@staticmethod
@pytest.mark.usefixtures("in_context")
def test__to_datastore_non_legacy():
class SubKind(model.Model):
bar = model.Property()

class SomeKind(model.Model):
foo = model.StructuredProperty(SubKind)

entity = SomeKind(foo=SubKind(bar="baz"))
data = {}
assert SomeKind.foo._to_datastore(entity, data) == ("foo",)
assert len(data) == 1
assert dict(data["foo"]) == {"bar": "baz"}

@staticmethod
def test__to_datastore_legacy(in_context):
class SubKind(model.Model):
bar = model.Property()

class SomeKind(model.Model):
foo = model.StructuredProperty(SubKind)

with in_context.new(legacy_data=True).use():
entity = SomeKind(foo=SubKind(bar="baz"))
data = {}
assert SomeKind.foo._to_datastore(entity, data) == {"foo.bar"}
assert data == {"foo.bar": "baz"}

@staticmethod
def test__to_datastore_legacy_subentity_is_None(in_context):
class SubKind(model.Model):
bar = model.Property()

class SomeKind(model.Model):
foo = model.StructuredProperty(SubKind)

with in_context.new(legacy_data=True).use():
entity = SomeKind()
data = {}
assert SomeKind.foo._to_datastore(entity, data) == {"foo"}
assert data == {"foo": None}

@staticmethod
def test__to_datastore_legacy_repeated(in_context):
class SubKind(model.Model):
bar = model.Property()

class SomeKind(model.Model):
foo = model.StructuredProperty(SubKind, repeated=True)

with in_context.new(legacy_data=True).use():
entity = SomeKind(foo=[SubKind(bar="baz"), SubKind(bar="boz")])
data = {}
assert SomeKind.foo._to_datastore(entity, data) == {"foo.bar"}
assert data == {"foo.bar": ["baz", "boz"]}


class TestLocalStructuredProperty:
@staticmethod
Expand Down Expand Up @@ -4702,6 +4803,8 @@ class ThisKind(model.Model):
assert entity.baz[0].bar == "himom"
assert entity.copacetic is True


class Test_entity_from_ds_entity:
@staticmethod
@pytest.mark.usefixtures("in_context")
def test_legacy_repeated_structured_property_uneven():
Expand All @@ -4724,8 +4827,7 @@ class ThisKind(model.Model):
)
)

protobuf = helpers.entity_to_protobuf(datastore_entity)
entity = model._entity_from_protobuf(protobuf)
entity = model._entity_from_ds_entity(datastore_entity)
assert isinstance(entity, ThisKind)
assert entity.baz[0].foo == 42
assert entity.baz[0].bar == "himom"
Expand Down

0 comments on commit f316a37

Please sign in to comment.