Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ae8f533

Browse files
authored
fix: properly exclude from indexes non-indexed subproperties of structured properties (#346)
Refs (#341).
1 parent e450739 commit ae8f533

File tree

3 files changed

+50
-10
lines changed

3 files changed

+50
-10
lines changed

packages/google-cloud-ndb/google/cloud/ndb/model.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -724,26 +724,22 @@ def _entity_to_ds_entity(entity, set_key=True):
724724
Raises:
725725
ndb.exceptions.BadValueError: If entity has uninitialized properties.
726726
"""
727-
data = {}
727+
data = {"_exclude_from_indexes": []}
728728
uninitialized = []
729-
exclude_from_indexes = []
730729

731730
for prop in _properties_of(entity):
732731
if not prop._is_initialized(entity):
733732
uninitialized.append(prop._name)
734733

735-
names = prop._to_datastore(entity, data)
736-
737-
if not prop._indexed:
738-
for name in names:
739-
exclude_from_indexes.append(name)
734+
prop._to_datastore(entity, data)
740735

741736
if uninitialized:
742737
missing = ", ".join(uninitialized)
743738
raise exceptions.BadValueError(
744739
"Entity has uninitialized properties: {}".format(missing)
745740
)
746741

742+
exclude_from_indexes = data.pop("_exclude_from_indexes")
747743
ds_entity = None
748744
if set_key:
749745
key = entity._key
@@ -2095,6 +2091,9 @@ def _to_datastore(self, entity, data, prefix="", repeated=False):
20952091
else:
20962092
data[key] = value
20972093

2094+
if not self._indexed:
2095+
data["_exclude_from_indexes"].append(key)
2096+
20982097
return (key,)
20992098

21002099
def _from_datastore(self, ds_entity, value):

packages/google-cloud-ndb/tests/system/test_crud.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,3 +1254,26 @@ class SomeKind(ndb.Model):
12541254

12551255
assert isinstance(retrieved.bar[0], OtherKind)
12561256
assert isinstance(retrieved.bar[1], OtherKind)
1257+
1258+
1259+
def test_insert_structured_property_with_unindexed_subproperty_legacy_data(
1260+
client_context, dispose_of, ds_client
1261+
):
1262+
"""Regression test for #341
1263+
1264+
https://github.com/googleapis/python-ndb/issues/341
1265+
"""
1266+
1267+
class OtherKind(ndb.Model):
1268+
data = ndb.BlobProperty(indexed=False)
1269+
1270+
class SomeKind(ndb.Model):
1271+
entry = ndb.StructuredProperty(OtherKind)
1272+
1273+
with client_context.new(legacy_data=True).use():
1274+
entity = SomeKind(entry=OtherKind(data=b"01234567890" * 1000))
1275+
key = entity.put()
1276+
dispose_of(key._key)
1277+
1278+
retrieved = key.get()
1279+
assert isinstance(retrieved.entry, OtherKind)

packages/google-cloud-ndb/tests/unit/test_model.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3476,6 +3476,21 @@ class SomeKind(model.Model):
34763476
assert SomeKind.foo._to_datastore(entity, data) == {"foo"}
34773477
assert data == {"foo": None}
34783478

3479+
@staticmethod
3480+
def test__to_datastore_legacy_subentity_is_unindexed(in_context):
3481+
class SubKind(model.Model):
3482+
bar = model.BlobProperty(indexed=False)
3483+
3484+
class SomeKind(model.Model):
3485+
foo = model.StructuredProperty(SubKind)
3486+
3487+
with in_context.new(legacy_data=True).use():
3488+
entity = SomeKind(foo=SubKind())
3489+
data = {"_exclude_from_indexes": []}
3490+
assert SomeKind.foo._to_datastore(entity, data) == {"foo.bar"}
3491+
assert data.pop("_exclude_from_indexes") == ["foo.bar"]
3492+
assert data == {"foo.bar": None}
3493+
34793494
@staticmethod
34803495
def test__to_datastore_legacy_repeated(in_context):
34813496
class SubKind(model.Model):
@@ -3682,12 +3697,13 @@ class SomeKind(model.Model):
36823697
)
36833698

36843699
entity = SomeKind(foo=[SubKind(bar="baz")])
3685-
data = {}
3700+
data = {"_exclude_from_indexes": []}
36863701
protobuf = model._entity_to_protobuf(entity.foo[0], set_key=False)
36873702
protobuf = protobuf.SerializePartialToString()
36883703
assert SomeKind.foo._to_datastore(entity, data, repeated=True) == (
36893704
"foo",
36903705
)
3706+
assert data.pop("_exclude_from_indexes") == ["foo"]
36913707
assert data == {"foo": [[protobuf]]}
36923708

36933709
@staticmethod
@@ -3702,13 +3718,14 @@ class SomeKind(model.Model):
37023718

37033719
with in_context.new(legacy_data=True).use():
37043720
entity = SomeKind(foo=[SubKind(bar="baz")])
3705-
data = {}
3721+
data = {"_exclude_from_indexes": []}
37063722
ds_entity = model._entity_to_ds_entity(
37073723
entity.foo[0], set_key=False
37083724
)
37093725
assert SomeKind.foo._to_datastore(entity, data, repeated=True) == (
37103726
"foo",
37113727
)
3728+
assert data.pop("_exclude_from_indexes") == ["foo"]
37123729
assert data == {"foo": [ds_entity]}
37133730

37143731
@staticmethod
@@ -3721,8 +3738,9 @@ class SomeKind(model.Model):
37213738

37223739
with in_context.new(legacy_data=True).use():
37233740
entity = SomeKind(foo=SubKind(bar="baz"))
3724-
data = {}
3741+
data = {"_exclude_from_indexes": []}
37253742
assert SomeKind.foo._to_datastore(entity, data) == ("foo",)
3743+
assert data.pop("_exclude_from_indexes") == ["foo"]
37263744
ds_entity = model._entity_to_ds_entity(entity.foo, set_key=False)
37273745
assert data == {"foo": ds_entity}
37283746

0 commit comments

Comments
 (0)