Skip to content

Commit a75d517

Browse files
committed
Correct semantics to use isolation scope and not current scope
Previously this library was based on hubs which maps to the isolation scope now.
1 parent 9871391 commit a75d517

File tree

6 files changed

+38
-39
lines changed

6 files changed

+38
-39
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,12 @@ extreme lenghts to keep its own SDK setup separate from the SDK setup of the
153153
tested code.
154154

155155
`pytest-sentry` exposes the `sentry_test_scope` fixture whose return value is
156-
the `Scope` being used to send events to Sentry. Use `with use_scope(entry_test_scope):`
156+
the isolation `Scope` being used to send events to Sentry. Use `with use_isolation_scope(sentry_test_scope)`:
157157
to temporarily switch context. You can use this to set custom tags like so::
158158

159159
```python
160160
def test_foo(sentry_test_scope):
161-
with use_scope(sentry_test_scope):
161+
with use_isolation_scope(sentry_test_scope):
162162
sentry_sdk.set_tag("pull_request", os.environ['EXAMPLE_CI_PULL_REQUEST'])
163163
```
164164

pytest_sentry/fixtures.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
@pytest.fixture
77
def sentry_test_scope(request):
88
"""
9-
Gives back the current scope.
9+
Gives back the isolation Scope.
1010
"""
1111

1212
item = request.node

pytest_sentry/helpers.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
11
import sentry_sdk
2+
from sentry_sdk.scope import ScopeType
3+
from sentry_sdk.opentelemetry.scope import setup_scope_context_management
24

35
from pytest_sentry.client import Client
46

57

6-
DEFAULT_SCOPE = sentry_sdk.Scope(client=Client())
8+
setup_scope_context_management()
9+
DEFAULT_ISOLATION_SCOPE = sentry_sdk.Scope(ty=ScopeType.ISOLATION)
10+
DEFAULT_ISOLATION_SCOPE.set_client(Client())
711

8-
_scope_cache = {}
12+
_isolation_scope_cache = {}
913

1014

1115
def _resolve_scope_marker_value(marker_value):
12-
if id(marker_value) not in _scope_cache:
13-
_scope_cache[id(marker_value)] = rv = _resolve_scope_marker_value_uncached(
16+
if id(marker_value) not in _isolation_scope_cache:
17+
_isolation_scope_cache[id(marker_value)] = rv = _resolve_scope_marker_value_uncached(
1418
marker_value
1519
)
1620
return rv
1721

18-
return _scope_cache[id(marker_value)]
22+
return _isolation_scope_cache[id(marker_value)]
1923

2024

2125
def _resolve_scope_marker_value_uncached(marker_value):
2226
if marker_value is None:
2327
# If no special configuration is provided
2428
# (like pytestmark or @pytest.mark.sentry_client() decorator)
2529
# use the default scope
26-
marker_value = DEFAULT_SCOPE
30+
marker_value = DEFAULT_ISOLATION_SCOPE
2731
else:
2832
marker_value = marker_value.args[0]
2933

@@ -37,25 +41,25 @@ def _resolve_scope_marker_value_uncached(marker_value):
3741

3842
if isinstance(marker_value, str):
3943
# If a DSN string is provided, create a new client and use that
40-
scope = sentry_sdk.get_current_scope()
44+
scope = sentry_sdk.get_isolation_scope()
4145
scope.set_client(Client(marker_value))
4246
return scope
4347

4448
if isinstance(marker_value, dict):
4549
# If a dict is provided, create a new client using the dict as Client options
46-
scope = sentry_sdk.get_current_scope()
50+
scope = sentry_sdk.get_isolation_scope()
4751
scope.set_client(Client(**marker_value))
4852
return scope
4953

5054
if isinstance(marker_value, Client):
5155
# If a Client instance is provided, use that
52-
scope = sentry_sdk.get_current_scope()
56+
scope = sentry_sdk.get_isolation_scope()
5357
scope.set_client(marker_value)
5458
return scope
5559

5660
if isinstance(marker_value, sentry_sdk.Scope):
5761
# If a Scope instance is provided, use the client from it
58-
scope = sentry_sdk.get_current_scope()
62+
scope = sentry_sdk.get_isolation_scope()
5963
scope.set_client(marker_value.client)
6064
return marker_value
6165

pytest_sentry/hooks.py

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,31 +27,26 @@ def hookwrapper(itemgetter, **kwargs):
2727
"""
2828

2929
@wrapt.decorator
30-
def _with_scope(wrapped, instance, args, kwargs):
30+
def _with_isolation_scope(wrapped, instance, args, kwargs):
3131
item = itemgetter(*args, **kwargs)
32-
scope = _resolve_scope_marker_value(item.get_closest_marker("sentry_client"))
32+
isolation_scope = _resolve_scope_marker_value(item.get_closest_marker("sentry_client"))
3333

34-
if scope.client.get_integration(PytestIntegration) is None:
34+
if isolation_scope.client.get_integration(PytestIntegration) is None:
3535
yield
3636
else:
37-
with sentry_sdk.use_scope(scope):
37+
with sentry_sdk.use_isolation_scope(isolation_scope):
3838
gen = wrapped(*args, **kwargs)
3939

40-
while True:
41-
try:
42-
with sentry_sdk.use_scope(scope):
40+
while True:
41+
try:
4342
chunk = next(gen)
44-
45-
y = yield chunk
46-
47-
with sentry_sdk.use_scope(scope):
43+
y = yield chunk
4844
gen.send(y)
49-
50-
except StopIteration:
51-
break
45+
except StopIteration:
46+
break
5247

5348
def inner(f):
54-
return pytest.hookimpl(hookwrapper=True, **kwargs)(_with_scope(f))
49+
return pytest.hookimpl(hookwrapper=True, **kwargs)(_with_isolation_scope(f))
5550

5651
return inner
5752

@@ -89,7 +84,7 @@ def pytest_runtest_call(item):
8984

9085
# We use the full name including parameters because then we can identify
9186
# how often a single test has run as part of the same GITHUB_RUN_ID.
92-
with sentry_sdk.continue_trace(dict(sentry_sdk.get_current_scope().iter_trace_propagation_headers())):
87+
with sentry_sdk.continue_trace(dict(sentry_sdk.get_isolation_scope().iter_trace_propagation_headers())):
9388
with sentry_sdk.start_span(op=op, name=name) as span:
9489
span.set_attribute("pytest-sentry.rerun", is_rerun)
9590
if is_rerun:
@@ -107,7 +102,7 @@ def pytest_fixture_setup(fixturedef, request):
107102
op = "pytest.fixture.setup"
108103
name = "{} {}".format(op, fixturedef.argname)
109104

110-
with sentry_sdk.continue_trace(dict(sentry_sdk.get_current_scope().iter_trace_propagation_headers())):
105+
with sentry_sdk.continue_trace(dict(sentry_sdk.get_isolation_scope().iter_trace_propagation_headers())):
111106
with sentry_sdk.start_span(op=op, name=name) as root_span:
112107
root_span.set_tag("pytest.fixture.scope", fixturedef.scope)
113108
yield
@@ -135,8 +130,8 @@ def pytest_runtest_makereport(item, call):
135130
call.excinfo
136131
]
137132

138-
scope = _resolve_scope_marker_value(item.get_closest_marker("sentry_client"))
139-
integration = scope.client.get_integration(PytestIntegration)
133+
isolation_scope = _resolve_scope_marker_value(item.get_closest_marker("sentry_client"))
134+
integration = isolation_scope.client.get_integration(PytestIntegration)
140135

141136
if (cur_exc_chain and call.excinfo is None) or (integration is not None and integration.always_report):
142137
for exc_info in cur_exc_chain:

tests/test_envvars.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def capture_envelope(self, envelope):
3232

3333

3434
def test_basic(sentry_test_scope):
35-
with sentry_sdk.use_scope(sentry_test_scope):
35+
with sentry_sdk.use_isolation_scope(sentry_test_scope):
3636
sentry_test_scope.capture_message("hi")
3737

3838
(event,) = events

tests/test_scope.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,25 @@
99

1010
pytestmark = pytest.mark.sentry_client(GLOBAL_CLIENT)
1111

12-
_DEFAULT_GLOBAL_SCOPE = sentry_sdk.Scope.get_global_scope()
13-
_DEFAULT_ISOLATION_SCOPE = sentry_sdk.Scope.get_isolation_scope()
12+
_DEFAULT_GLOBAL_SCOPE = sentry_sdk.get_global_scope()
13+
_DEFAULT_ISOLATION_SCOPE = sentry_sdk.get_isolation_scope()
1414

1515

1616
def _assert_right_scopes():
17-
global_scope = sentry_sdk.Scope.get_global_scope()
17+
global_scope = sentry_sdk.get_global_scope()
1818
assert global_scope is _DEFAULT_GLOBAL_SCOPE
1919

20-
isolation_scope = sentry_sdk.Scope.get_isolation_scope()
20+
isolation_scope = sentry_sdk.get_isolation_scope()
2121
assert isolation_scope is _DEFAULT_ISOLATION_SCOPE
2222

2323

2424
def test_basic():
2525
_assert_right_scopes()
2626

2727

28-
def test_sentry_test_scope(sentry_test_scope):
28+
def test_correct_span():
2929
# Ensure that we are within a root span (started by the pytest_runtest_call hook)
30-
assert sentry_test_scope.span is not None
30+
assert sentry_sdk.get_current_scope().span is not None
3131

3232

3333
class TestSimpleClass(object):

0 commit comments

Comments
 (0)