Skip to content

Commit 45fa423

Browse files
author
Chris Rossi
authored
Check context (#211)
When creating a top level context, check to make sure there isn't already a running context for this thread. This is an attempt to root a possible weird concurrency problem. Related to #182.
1 parent 1f74265 commit 45fa423

File tree

3 files changed

+24
-3
lines changed

3 files changed

+24
-3
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ def context(
161161
legacy_data (bool): Set to ``True`` (the default) to write data in
162162
a way that can be read by the legacy version of NDB.
163163
"""
164+
context = context_module.get_context(False)
165+
if context is not None:
166+
raise RuntimeError("Context is already created for this thread.")
167+
164168
context = context_module.Context(
165169
self,
166170
cache_policy=cache_policy,

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,24 +45,32 @@ def __init__(self):
4545
_state = _LocalState()
4646

4747

48-
def get_context():
48+
def get_context(raise_context_error=True):
4949
"""Get the current context.
5050
5151
This function should be called within a context established by
5252
:meth:`google.cloud.ndb.client.Client.context`.
5353
54+
Args:
55+
raise_context_error (bool): If set to :data:`True`, will raise an
56+
exception if called outside of a context. Set this to :data:`False`
57+
in order to have it just return :data:`None` if called outside of a
58+
context. Default: :data:`True`
59+
5460
Returns:
5561
Context: The current context.
5662
5763
Raises:
5864
.ContextError: If called outside of a context
59-
established by :meth:`google.cloud.ndb.client.Client.context`.
65+
established by :meth:`google.cloud.ndb.client.Client.context` and
66+
``raise_context_error`` is :data:`True`.
6067
"""
6168
context = _state.context
6269
if context:
6370
return context
6471

65-
raise exceptions.ContextError()
72+
if raise_context_error:
73+
raise exceptions.ContextError()
6674

6775

6876
def _default_policy(attr_name, value_type):

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ def test_context():
104104
context = context_module.get_context()
105105
assert context.client is client
106106

107+
@staticmethod
108+
def test_context_double_jeopardy():
109+
with patch_credentials("testing"):
110+
client = client_module.Client()
111+
112+
with client.context():
113+
with pytest.raises(RuntimeError):
114+
client.context().__enter__()
115+
107116
@staticmethod
108117
def test_context_unfinished_business():
109118
"""Regression test for #213.

0 commit comments

Comments
 (0)