Skip to content

Commit 5083585

Browse files
authored
Make sure correct namespace is used when creating keys (#62)
1 parent cc5f6ae commit 5083585

File tree

6 files changed

+80
-4
lines changed

6 files changed

+80
-4
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ class Key:
137137
138138
from unittest import mock
139139
from google.cloud.ndb import context as context_module
140-
client = mock.Mock(project="testing", spec=("project",))
140+
client = mock.Mock(project="testing", spec=("project",), namespace="")
141141
context = context_module.Context(client, stub=mock.Mock(spec=())).use()
142142
context.__enter__()
143143
kind1, id1 = "Parent", "C"
@@ -274,6 +274,11 @@ class Key:
274274
def __new__(cls, *path_args, **kwargs):
275275
_constructor_handle_positional(path_args, kwargs)
276276
instance = super(Key, cls).__new__(cls)
277+
# Make sure to pass in the namespace if it's not explicitly set.
278+
if "namespace" not in kwargs:
279+
client = context_module.get_context().client
280+
if client.namespace:
281+
kwargs["namespace"] = client.namespace
277282
if (
278283
"reference" in kwargs
279284
or "serialized" in kwargs

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from google.cloud import ndb
2121
from google.cloud.ndb import context as context_module
2222
23-
client = mock.Mock(project="testing", spec=("project",))
23+
client = mock.Mock(project="testing", spec=("project",), namespace="")
2424
context = context_module.Context(client, stub=mock.Mock(spec=())).use()
2525
context.__enter__()
2626

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,12 @@ def delete_entity(ds_key):
104104

105105

106106
@pytest.fixture
107-
def client_context():
108-
client = ndb.Client()
107+
def namespace():
108+
return ""
109+
110+
111+
@pytest.fixture
112+
def client_context(namespace):
113+
client = ndb.Client(namespace=namespace)
109114
with client.context():
110115
yield

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,36 @@ class AnyKind(ndb.Model):
229229
assert properties == ["foo"]
230230

231231

232+
@pytest.mark.usefixtures("client_context")
233+
@pytest.mark.parametrize("namespace", ["DiffNamespace"])
234+
def test_get_properties_of_kind_different_namespace(dispose_of, namespace):
235+
from google.cloud.ndb.metadata import get_properties_of_kind
236+
237+
class AnyKind(ndb.Model):
238+
foo = ndb.IntegerProperty()
239+
bar = ndb.StringProperty()
240+
baz = ndb.IntegerProperty()
241+
qux = ndb.StringProperty()
242+
243+
entity1 = AnyKind(
244+
foo=1, bar="x", baz=3, qux="y", namespace="DiffNamespace"
245+
)
246+
entity1.put()
247+
dispose_of(entity1.key._key)
248+
249+
properties = get_properties_of_kind("AnyKind")
250+
assert properties == ["bar", "baz", "foo", "qux"]
251+
252+
properties = get_properties_of_kind("AnyKind", start="c")
253+
assert properties == ["foo", "qux"]
254+
255+
properties = get_properties_of_kind("AnyKind", end="e")
256+
assert properties == ["bar", "baz"]
257+
258+
properties = get_properties_of_kind("AnyKind", start="c", end="p")
259+
assert properties == ["foo"]
260+
261+
232262
@pytest.mark.usefixtures("client_context")
233263
def test_get_representations_of_kind(dispose_of):
234264
from google.cloud.ndb.metadata import get_representations_of_kind

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ def test_constructor_default():
4545
assert key._reference is None
4646

4747
@staticmethod
48+
@pytest.mark.usefixtures("in_context")
49+
def test_constructor_with_different_namespace(context):
50+
context.client.namespace = "DiffNamespace"
51+
key = key_module.Key("Kind", 42)
52+
53+
assert key._key == google.cloud.datastore.Key(
54+
"Kind", 42, project="testing", namespace="DiffNamespace"
55+
)
56+
assert key._reference is None
57+
58+
@staticmethod
59+
@pytest.mark.usefixtures("in_context")
4860
def test_constructor_empty_path():
4961
with pytest.raises(TypeError):
5062
key_module.Key(pairs=())
@@ -63,13 +75,15 @@ def test_constructor_partial():
6375
assert key._reference is None
6476

6577
@staticmethod
78+
@pytest.mark.usefixtures("in_context")
6679
def test_constructor_invalid_id_type():
6780
with pytest.raises(TypeError):
6881
key_module.Key("Kind", object())
6982
with pytest.raises(exceptions.BadArgumentError):
7083
key_module.Key("Kind", None, "Also", 10)
7184

7285
@staticmethod
86+
@pytest.mark.usefixtures("in_context")
7387
def test_constructor_invalid_kind_type():
7488
with pytest.raises(TypeError):
7589
key_module.Key(object(), 47)
@@ -89,6 +103,7 @@ class Simple(model.Model):
89103
assert key._reference is None
90104

91105
@staticmethod
106+
@pytest.mark.usefixtures("in_context")
92107
def test_constructor_with_reference():
93108
reference = make_reference()
94109
key = key_module.Key(reference=reference)
@@ -104,6 +119,7 @@ def test_constructor_with_reference():
104119
assert key._reference is reference
105120

106121
@staticmethod
122+
@pytest.mark.usefixtures("in_context")
107123
def test_constructor_with_serialized():
108124
serialized = (
109125
b"j\x18s~sample-app-no-locationr\n\x0b\x12\x04Zorp\x18X\x0c"
@@ -119,6 +135,7 @@ def test_constructor_with_serialized():
119135
namespace=None,
120136
)
121137

138+
@pytest.mark.usefixtures("in_context")
122139
def test_constructor_with_urlsafe(self):
123140
key = key_module.Key(urlsafe=self.URLSAFE)
124141

@@ -152,11 +169,13 @@ def test_constructor_with_flat():
152169
assert key._reference is None
153170

154171
@staticmethod
172+
@pytest.mark.usefixtures("in_context")
155173
def test_constructor_with_flat_and_pairs():
156174
with pytest.raises(TypeError):
157175
key_module.Key(pairs=[("Kind", 1)], flat=["Kind", 1])
158176

159177
@staticmethod
178+
@pytest.mark.usefixtures("in_context")
160179
def test_constructor_with_app():
161180
key = key_module.Key("Kind", 10, app="s~foo")
162181

@@ -175,6 +194,7 @@ def test_constructor_with_namespace():
175194
)
176195
assert key._reference is None
177196

197+
@pytest.mark.usefixtures("in_context")
178198
def test_constructor_with_parent(self):
179199
parent = key_module.Key(urlsafe=self.URLSAFE)
180200
key = key_module.Key("Zip", 10, parent=parent)
@@ -184,16 +204,19 @@ def test_constructor_with_parent(self):
184204
)
185205
assert key._reference is None
186206

207+
@pytest.mark.usefixtures("in_context")
187208
def test_constructor_with_parent_bad_type(self):
188209
parent = unittest.mock.sentinel.parent
189210
with pytest.raises(exceptions.BadValueError):
190211
key_module.Key("Zip", 10, parent=parent)
191212

192213
@staticmethod
214+
@pytest.mark.usefixtures("in_context")
193215
def test_constructor_insufficient_args():
194216
with pytest.raises(TypeError):
195217
key_module.Key(app="foo")
196218

219+
@pytest.mark.usefixtures("in_context")
197220
def test_no_subclass_for_reference(self):
198221
class KeySubclass(key_module.Key):
199222
pass
@@ -202,10 +225,12 @@ class KeySubclass(key_module.Key):
202225
KeySubclass(urlsafe=self.URLSAFE)
203226

204227
@staticmethod
228+
@pytest.mark.usefixtures("in_context")
205229
def test_invalid_argument_combination():
206230
with pytest.raises(TypeError):
207231
key_module.Key(flat=["a", "b"], urlsafe=b"foo")
208232

233+
@pytest.mark.usefixtures("in_context")
209234
def test_colliding_reference_arguments(self):
210235
urlsafe = self.URLSAFE
211236
padding = b"=" * (-len(urlsafe) % 4)
@@ -390,6 +415,7 @@ def test_namespace():
390415
assert key.namespace() == namespace
391416

392417
@staticmethod
418+
@pytest.mark.usefixtures("in_context")
393419
def test_app():
394420
app = "s~example"
395421
key = key_module.Key("X", 100, app=app)
@@ -452,6 +478,7 @@ def test_kind():
452478
assert key.kind() == "c"
453479

454480
@staticmethod
481+
@pytest.mark.usefixtures("in_context")
455482
def test_reference():
456483
key = key_module.Key("This", "key", app="fire")
457484
assert key.reference() == make_reference(
@@ -466,6 +493,7 @@ def test_reference_cached():
466493
assert key.reference() is unittest.mock.sentinel.reference
467494

468495
@staticmethod
496+
@pytest.mark.usefixtures("in_context")
469497
def test_reference_bad_kind():
470498
too_long = "a" * (key_module._MAX_KEYPART_BYTES + 1)
471499
for kind in ("", too_long):
@@ -474,6 +502,7 @@ def test_reference_bad_kind():
474502
key.reference()
475503

476504
@staticmethod
505+
@pytest.mark.usefixtures("in_context")
477506
def test_reference_bad_string_id():
478507
too_long = "a" * (key_module._MAX_KEYPART_BYTES + 1)
479508
for id_ in ("", too_long):
@@ -482,18 +511,21 @@ def test_reference_bad_string_id():
482511
key.reference()
483512

484513
@staticmethod
514+
@pytest.mark.usefixtures("in_context")
485515
def test_reference_bad_integer_id():
486516
for id_ in (-10, 0, 2 ** 64):
487517
key = key_module.Key("kind", id_, app="app")
488518
with pytest.raises(ValueError):
489519
key.reference()
490520

491521
@staticmethod
522+
@pytest.mark.usefixtures("in_context")
492523
def test_serialized():
493524
key = key_module.Key("a", 108, app="c")
494525
assert key.serialized() == b"j\x01cr\x07\x0b\x12\x01a\x18l\x0c"
495526

496527
@staticmethod
528+
@pytest.mark.usefixtures("in_context")
497529
def test_urlsafe():
498530
key = key_module.Key("d", None, app="f")
499531
assert key.urlsafe() == b"agFmcgULEgFkDA"

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2992,6 +2992,7 @@ class XModel(model.Model):
29922992

29932993
class Test_entity_from_protobuf:
29942994
@staticmethod
2995+
@pytest.mark.usefixtures("in_context")
29952996
def test_standard_case():
29962997
class ThisKind(model.Model):
29972998
a = model.IntegerProperty()
@@ -3048,6 +3049,7 @@ class ThisKind(model.Model):
30483049

30493050
class Test_entity_to_protobuf:
30503051
@staticmethod
3052+
@pytest.mark.usefixtures("in_context")
30513053
def test_standard_case():
30523054
class ThisKind(model.Model):
30533055
a = model.IntegerProperty()
@@ -3084,6 +3086,7 @@ class ThisKind(model.Model):
30843086
assert "__key__" not in entity_pb.properties
30853087

30863088
@staticmethod
3089+
@pytest.mark.usefixtures("in_context")
30873090
def test_property_named_key():
30883091
class ThisKind(model.Model):
30893092
key = model.StringProperty()
@@ -3097,6 +3100,7 @@ class ThisKind(model.Model):
30973100
assert entity_pb.key.path[0].id == 123
30983101

30993102
@staticmethod
3103+
@pytest.mark.usefixtures("in_context")
31003104
def test_override_property():
31013105
class ThatKind(model.Model):
31023106
a = model.StringProperty()

0 commit comments

Comments
 (0)