1919import functools
2020import operator
2121import os
22+ import random
2223import threading
2324import zlib
2425
@@ -118,7 +119,7 @@ class SomeKind(ndb.Model):
118119
119120
120121@pytest .mark .skipif (not USE_REDIS_CACHE , reason = "Redis is not configured" )
121- def test_retrieve_entity_with_redis_cache (ds_entity , client_context ):
122+ def test_retrieve_entity_with_redis_cache (ds_entity , redis_context ):
122123 entity_id = test_utils .system .unique_resource_id ()
123124 ds_entity (KIND , entity_id , foo = 42 , bar = "none" , baz = b"night" )
124125
@@ -127,29 +128,25 @@ class SomeKind(ndb.Model):
127128 bar = ndb .StringProperty ()
128129 baz = ndb .StringProperty ()
129130
130- global_cache = global_cache_module .RedisCache .from_environment ()
131- with client_context .new (global_cache = global_cache ).use () as context :
132- context .set_global_cache_policy (None ) # Use default
131+ key = ndb .Key (KIND , entity_id )
132+ entity = key .get ()
133+ assert isinstance (entity , SomeKind )
134+ assert entity .foo == 42
135+ assert entity .bar == "none"
136+ assert entity .baz == "night"
133137
134- key = ndb .Key (KIND , entity_id )
138+ cache_key = _cache .global_cache_key (key ._key )
139+ assert redis_context .global_cache .redis .get (cache_key ) is not None
140+
141+ patch = mock .patch ("google.cloud.ndb._datastore_api._LookupBatch.add" )
142+ patch .side_effect = Exception ("Shouldn't call this" )
143+ with patch :
135144 entity = key .get ()
136145 assert isinstance (entity , SomeKind )
137146 assert entity .foo == 42
138147 assert entity .bar == "none"
139148 assert entity .baz == "night"
140149
141- cache_key = _cache .global_cache_key (key ._key )
142- assert global_cache .redis .get (cache_key ) is not None
143-
144- patch = mock .patch ("google.cloud.ndb._datastore_api._LookupBatch.add" )
145- patch .side_effect = Exception ("Shouldn't call this" )
146- with patch :
147- entity = key .get ()
148- assert isinstance (entity , SomeKind )
149- assert entity .foo == 42
150- assert entity .bar == "none"
151- assert entity .baz == "night"
152-
153150
154151@pytest .mark .usefixtures ("client_context" )
155152def test_retrieve_entity_not_found (ds_entity ):
@@ -500,33 +497,29 @@ class SomeKind(ndb.Model):
500497
501498
502499@pytest .mark .skipif (not USE_REDIS_CACHE , reason = "Redis is not configured" )
503- def test_insert_entity_with_redis_cache (dispose_of , client_context ):
500+ def test_insert_entity_with_redis_cache (dispose_of , redis_context ):
504501 class SomeKind (ndb .Model ):
505502 foo = ndb .IntegerProperty ()
506503 bar = ndb .StringProperty ()
507504
508- global_cache = global_cache_module .RedisCache .from_environment ()
509- with client_context .new (global_cache = global_cache ).use () as context :
510- context .set_global_cache_policy (None ) # Use default
511-
512- entity = SomeKind (foo = 42 , bar = "none" )
513- key = entity .put ()
514- dispose_of (key ._key )
515- cache_key = _cache .global_cache_key (key ._key )
516- assert global_cache .redis .get (cache_key ) is None
505+ entity = SomeKind (foo = 42 , bar = "none" )
506+ key = entity .put ()
507+ dispose_of (key ._key )
508+ cache_key = _cache .global_cache_key (key ._key )
509+ assert redis_context .global_cache .redis .get (cache_key ) is None
517510
518- retrieved = key .get ()
519- assert retrieved .foo == 42
520- assert retrieved .bar == "none"
511+ retrieved = key .get ()
512+ assert retrieved .foo == 42
513+ assert retrieved .bar == "none"
521514
522- assert global_cache .redis .get (cache_key ) is not None
515+ assert redis_context . global_cache .redis .get (cache_key ) is not None
523516
524- entity .foo = 43
525- entity .put ()
517+ entity .foo = 43
518+ entity .put ()
526519
527- # This is py27 behavior. I can see a case being made for caching the
528- # entity on write rather than waiting for a subsequent lookup.
529- assert global_cache .redis .get (cache_key ) is None
520+ # This is py27 behavior. I can see a case being made for caching the
521+ # entity on write rather than waiting for a subsequent lookup.
522+ assert redis_context . global_cache .redis .get (cache_key ) is None
530523
531524
532525@pytest .mark .usefixtures ("client_context" )
@@ -671,7 +664,7 @@ class SomeKind(ndb.Model):
671664
672665
673666@pytest .mark .skipif (not USE_REDIS_CACHE , reason = "Redis is not configured" )
674- def test_delete_entity_with_redis_cache (ds_entity , client_context ):
667+ def test_delete_entity_with_redis_cache (ds_entity , redis_context ):
675668 entity_id = test_utils .system .unique_resource_id ()
676669 ds_entity (KIND , entity_id , foo = 42 )
677670
@@ -680,19 +673,17 @@ class SomeKind(ndb.Model):
680673
681674 key = ndb .Key (KIND , entity_id )
682675 cache_key = _cache .global_cache_key (key ._key )
683- global_cache = global_cache_module .RedisCache .from_environment ()
684676
685- with client_context .new (global_cache = global_cache ).use ():
686- assert key .get ().foo == 42
687- assert global_cache .redis .get (cache_key ) is not None
677+ assert key .get ().foo == 42
678+ assert redis_context .global_cache .redis .get (cache_key ) is not None
688679
689- assert key .delete () is None
690- assert global_cache .redis .get (cache_key ) is None
680+ assert key .delete () is None
681+ assert redis_context . global_cache .redis .get (cache_key ) is None
691682
692- # This is py27 behavior. Not entirely sold on leaving _LOCKED value for
693- # Datastore misses.
694- assert key .get () is None
695- assert global_cache .redis .get (cache_key ) == b"0"
683+ # This is py27 behavior. Not entirely sold on leaving _LOCKED value for
684+ # Datastore misses.
685+ assert key .get () is None
686+ assert redis_context . global_cache .redis .get (cache_key ) == b"0"
696687
697688
698689@pytest .mark .usefixtures ("client_context" )
@@ -1113,3 +1104,30 @@ class SomeKind(ndb.Model):
11131104
11141105 retreived = key .get ()
11151106 assert retreived .foo == ["" , "" ]
1107+
1108+
1109+ @pytest .mark .usefixtures ("redis_context" )
1110+ def test_multi_get_weirdness_with_redis (dispose_of ):
1111+ """Regression test for issue #294.
1112+
1113+ https://github.com/googleapis/python-ndb/issues/294
1114+ """
1115+
1116+ class SomeKind (ndb .Model ):
1117+ foo = ndb .StringProperty ()
1118+
1119+ objects = [SomeKind (foo = str (i )) for i in range (10 )]
1120+ keys = ndb .put_multi (objects )
1121+ for key in keys :
1122+ dispose_of (key ._key )
1123+ ndb .get_multi (keys )
1124+
1125+ one_object = random .choice (keys ).get ()
1126+ one_object .foo = "CHANGED"
1127+ one_object .put ()
1128+
1129+ objects_upd = ndb .get_multi (keys )
1130+ keys_upd = [obj .key for obj in objects_upd ]
1131+ assert len (keys_upd ) == len (keys )
1132+ assert len (set (keys_upd )) == len (set (keys ))
1133+ assert set (keys_upd ) == set (keys )
0 commit comments