def add_entities_to_cache(model, entities, situation, namespace):
    from gcloudc.db.transaction import in_atomic_block

    if not CACHE_ENABLED:
        return None

    context = get_context()

    if not context.context_enabled:
        # Don't cache anything if caching is disabled
        return

    # Don't cache on Get if we are inside a transaction, even in the context
    # This is because transactions don't see the current state of the datastore
    # We can still cache in the context on Put()
    if situation == CachingSituation.DATASTORE_GET and in_atomic_block():
        return

    identifiers = [
        unique_identifiers_from_entity(model, entity) for entity in entities
    ]

    for ent_identifiers, entity in zip(identifiers, entities):
        get_context().stack.top.cache_entity(
            _apply_namespace(ent_identifiers, namespace), entity, situation)
    def test_non_atomic_context_manager(self):
        existing = TestUser.objects.create(username="******", field2="exists", first_name="one", second_name="one")

        with transaction.atomic():
            self.assertTrue(transaction.in_atomic_block())

            user = TestUser.objects.create(username="******", field2="bar", first_name="two", second_name="two")

            with transaction.non_atomic():
                # We're outside the transaction, so the user should not exist
                self.assertRaises(TestUser.DoesNotExist, TestUser.objects.get, pk=user.pk)
                self.assertFalse(transaction.in_atomic_block())

                with sleuth.watch("google.cloud.datastore.client.Client.get") as datastore_get:
                    TestUser.objects.get(pk=existing.pk)  # Should hit the cache, not the datastore

                self.assertFalse(datastore_get.called)

            with transaction.atomic(independent=True):
                user2 = TestUser.objects.create(username="******", field2="bar2", first_name="three", second_name="three")
                self.assertTrue(transaction.in_atomic_block())

                with transaction.non_atomic():
                    self.assertFalse(transaction.in_atomic_block())
                    self.assertRaises(TestUser.DoesNotExist, TestUser.objects.get, pk=user2.pk)

                    with transaction.non_atomic():
                        self.assertFalse(transaction.in_atomic_block())
                        self.assertRaises(TestUser.DoesNotExist, TestUser.objects.get, pk=user2.pk)

                        with sleuth.watch("google.cloud.datastore.client.Client.get") as datastore_get:
                            # Should hit the cache, not the Datastore
                            TestUser.objects.get(pk=existing.pk)
                            self.assertFalse(datastore_get.called)

                    self.assertFalse(transaction.in_atomic_block())
                    self.assertRaises(TestUser.DoesNotExist, TestUser.objects.get, pk=user2.pk)

                # Should hit the cache
                self.assertTrue(TestUser.objects.filter(pk=user2.pk).exists())
                self.assertTrue(transaction.in_atomic_block())

        self.assertFalse(transaction.in_atomic_block())
 def txn():
     TestUser.objects.create(username="******", field2="bar")
     self.assertTrue(transaction.in_atomic_block())
     raise ValueError()