Skip to content

Commit

Permalink
fix: allow for legacy repeated structured properties with empty values (
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Rossi authored Jul 30, 2021
1 parent 45e590a commit 60c293d
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 13 deletions.
27 changes: 14 additions & 13 deletions google/cloud/ndb/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -4302,23 +4302,24 @@ def _to_datastore(self, entity, data, prefix="", repeated=False):
if not self._repeated:
values = (values,)

props = tuple(_properties_of(*values))
if values:
props = tuple(_properties_of(*values))

for value in values:
if value is None:
keys.extend(
super(StructuredProperty, self)._to_datastore(
entity, data, prefix=prefix, repeated=repeated
for value in values:
if value is None:
keys.extend(
super(StructuredProperty, self)._to_datastore(
entity, data, prefix=prefix, repeated=repeated
)
)
)
continue
continue

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

return set(keys)

Expand Down
27 changes: 27 additions & 0 deletions tests/system/test_crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,33 @@ class SomeKind(ndb.Model):
assert isinstance(retrieved.bar[2], OtherKind)


@pytest.mark.usefixtures("client_context")
def test_legacy_repeated_structured_property_w_expando_empty(
ds_client, dispose_of, client_context
):
"""Regression test for #669
https://github.com/googleapis/python-ndb/issues/669
"""

class OtherKind(ndb.Expando):
one = ndb.StringProperty()

class SomeKind(ndb.Model):
foo = ndb.IntegerProperty()
bar = ndb.StructuredProperty(OtherKind, repeated=True)

entity = SomeKind(foo=42, bar=[])

with client_context.new(legacy_data=True).use():
key = entity.put()
dispose_of(key._key)

retrieved = key.get()
assert retrieved.foo == 42
assert retrieved.bar == []


@pytest.mark.usefixtures("client_context")
def test_insert_expando(dispose_of):
class SomeKind(ndb.Expando):
Expand Down
14 changes: 14 additions & 0 deletions tests/unit/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -3524,6 +3524,20 @@ class SomeKind(model.Model):
assert SomeKind.foo._to_datastore(entity, data) == {"foo.bar"}
assert data == {"foo.bar": ["baz", "boz"]}

@staticmethod
def test__to_datastore_legacy_repeated_empty_value(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=[])
data = {}
assert SomeKind.foo._to_datastore(entity, data) == set()
assert data == {}

@staticmethod
def test__prepare_for_put():
class SubKind(model.Model):
Expand Down

0 comments on commit 60c293d

Please sign in to comment.