Skip to content

Commit 4cf238c

Browse files
author
Chris Rossi
authored
fix: correct inconsistent behavior with regards to namespaces (#662)
In the constructor for `Key`, `None` and the empty string `""` were being treated as distinct namespaces, despite both being synonyms for the default namespace. In ancestor queries, the namespace for the query is now taken properly from the ancestor key. Fixes #661
1 parent afa4fdb commit 4cf238c

File tree

4 files changed

+50
-2
lines changed

4 files changed

+50
-2
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,6 +1367,9 @@ def _parse_from_args(
13671367
# Offload verification of parent to ``google.cloud.datastore.Key()``.
13681368
parent_ds_key = parent._key
13691369

1370+
if namespace == "":
1371+
namespace = None
1372+
13701373
return google.cloud.datastore.Key(
13711374
*flat, parent=parent_ds_key, project=project, namespace=namespace
13721375
)

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1267,7 +1267,10 @@ def __init__(self, config=None, context=None, **kwargs):
12671267
self.project = context.client.project
12681268

12691269
if self.namespace is None:
1270-
self.namespace = context.get_namespace()
1270+
if self.ancestor is None:
1271+
self.namespace = context.get_namespace()
1272+
else:
1273+
self.namespace = self.ancestor.namespace()
12711274

12721275

12731276
class Query(object):

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,3 +501,27 @@ class SomeKind(ndb.Model):
501501
assert entity.children[1].bar is False
502502
assert entity.children[2].foo == "i'm in jail!"
503503
assert entity.children[2].bar is False
504+
505+
506+
@pytest.mark.usefixtures("client_context")
507+
def test_parent_and_child_in_default_namespace(dispose_of):
508+
"""Regression test for #661
509+
510+
https://github.com/googleapis/python-ndb/issues/661
511+
"""
512+
513+
class SomeKind(ndb.Model):
514+
pass
515+
516+
class OtherKind(ndb.Model):
517+
foo = ndb.IntegerProperty()
518+
519+
parent = SomeKind(namespace="")
520+
parent_key = parent.put()
521+
dispose_of(parent_key._key)
522+
523+
child = OtherKind(parent=parent_key, namespace="", foo=42)
524+
child_key = child.put()
525+
dispose_of(child_key._key)
526+
527+
assert OtherKind.query(ancestor=parent_key).get().foo == 42

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,25 @@ def test_constructor_with_namespace():
210210
assert key._key == google.cloud.datastore.Key(
211211
"Kind", 1337, project="testing", namespace="foo"
212212
)
213-
assert key._reference is None
213+
assert key.namespace() == "foo"
214+
215+
@staticmethod
216+
@pytest.mark.usefixtures("in_context")
217+
def test_constructor_with_default_namespace_as_empty_string(context):
218+
context.client.namespace = "DiffNamespace"
219+
key = key_module.Key("Kind", 1337, namespace="")
220+
221+
assert key._key == google.cloud.datastore.Key("Kind", 1337, project="testing")
222+
assert key.namespace() is None
223+
224+
@staticmethod
225+
@pytest.mark.usefixtures("in_context")
226+
def test_constructor_with_default_namespace_as_None(context):
227+
context.client.namespace = "DiffNamespace"
228+
key = key_module.Key("Kind", 1337, namespace=None)
229+
230+
assert key._key == google.cloud.datastore.Key("Kind", 1337, project="testing")
231+
assert key.namespace() is None
214232

215233
@pytest.mark.usefixtures("in_context")
216234
def test_constructor_with_parent(self):

0 commit comments

Comments
 (0)