Skip to content

Commit 78ab52f

Browse files
author
Chris Rossi
authored
fix: ignore datastore properties that are not mapped to NDB properties (#470)
During deserialization from Datastore, since NDB properties can be arbitrarily mapped to Datastore properties of different names, it is possible for a Datastore entity to have a property with the same name as an NDB property, but that isn't the Datastore property mapped to that NDB property. This fix prevents the unmapped Datastore property from accidentally clobbering the NDB property of the same name. Fixes #461.
1 parent f9ca7bc commit 78ab52f

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5964,8 +5964,27 @@ def _code_name_from_stored_name(cls, name):
59645964
"""Return the code name from a property when it's different from the
59655965
stored name. Used in deserialization from datastore."""
59665966
if name in cls._properties:
5967-
if name != cls._properties[name]._code_name:
5968-
name = cls._properties[name]._code_name
5967+
return cls._properties[name]._code_name
5968+
5969+
# If name isn't in cls._properties but there is a property with that
5970+
# name, it means that property has a different codename, and returning
5971+
# this name will potentially clobber the real property. Take for
5972+
# example:
5973+
#
5974+
# class SomeKind(ndb.Model):
5975+
# foo = ndb.IntegerProperty(name="bar")
5976+
#
5977+
# If we are passed "bar", we know to translate that to "foo", becasue
5978+
# the datastore property, "bar", is the NDB property, "foo". But if we
5979+
# are passed "foo", here, then that must be the datastore property,
5980+
# "foo", which isn't even mapped to anything in the NDB model.
5981+
#
5982+
prop = getattr(cls, name, None)
5983+
if prop:
5984+
# Won't map to a property, so this datastore property will be
5985+
# effectively ignored.
5986+
return " "
5987+
59695988
return name
59705989

59715990
@classmethod

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020

2121
import pytest
2222

23+
import test_utils.system
24+
2325
from google.cloud import ndb
2426

25-
from . import eventually, length_equals
27+
from . import eventually, length_equals, KIND
2628

2729
USE_REDIS_CACHE = bool(os.environ.get("REDIS_CACHE_URL"))
2830

@@ -295,3 +297,21 @@ def save_entity():
295297

296298
assert retrieved.foo == 42
297299
assert retrieved.bar == "none"
300+
301+
302+
@pytest.mark.usefixtures("client_context")
303+
def test_crosswired_property_names(ds_entity):
304+
"""Regression test for #461.
305+
306+
https://github.com/googleapis/python-ndb/issues/461
307+
"""
308+
entity_id = test_utils.system.unique_resource_id()
309+
ds_entity(KIND, entity_id, foo=42, bar=43)
310+
311+
class SomeKind(ndb.Model):
312+
bar = ndb.IntegerProperty(name="foo")
313+
314+
key = ndb.Key(KIND, entity_id)
315+
entity = key.get()
316+
317+
assert entity.bar == 42

0 commit comments

Comments
 (0)