feat(scopes): Explicit scopes (#633) · gitcommit90/sentry-python@e680a75 · GitHub
Skip to content

Commit e680a75

Browse files
authored
feat(scopes): Explicit scopes (getsentry#633)
1 parent 4112000 commit e680a75

4 files changed

Lines changed: 133 additions & 7 deletions

File tree

sentry_sdk/api.py

Lines changed: 9 additions & 3 deletions

sentry_sdk/hub.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from typing import Any
2424
from typing import Optional
2525
from typing import Tuple
26+
from typing import Dict
2627
from typing import List
2728
from typing import Callable
2829
from typing import Generator
@@ -47,6 +48,24 @@ def overload(x):
4748
_local = ContextVar("sentry_current_hub")
4849

4950

51+
def _update_scope(base, scope_change, scope_kwargs):
52+
# type: (Scope, Optional[Any], Dict[str, Any]) -> Scope
53+
if scope_change and scope_kwargs:
54+
raise TypeError("cannot provide scope and kwargs")
55+
if scope_change is not None:
56+
final_scope = copy.copy(base)
57+
if callable(scope_change):
58+
scope_change(final_scope)
59+
else:
60+
final_scope.update_from_scope(scope_change)
61+
elif scope_kwargs:
62+
final_scope = copy.copy(base)
63+
final_scope.update_from_kwargs(scope_kwargs)
64+
else:
65+
final_scope = base
66+
return final_scope
67+
68+
5069
def _should_send_default_pii():
5170
# type: () -> bool
5271
client = Hub.current.client
@@ -285,11 +304,14 @@ def capture_event(
285304
self,
286305
event, # type: Event
287306
hint=None, # type: Optional[Hint]
307+
scope=None, # type: Optional[Any]
308+
**scope_args # type: Dict[str, Any]
288309
):
289310
# type: (...) -> Optional[str]
290311
"""Captures an event. Alias of :py:meth:`sentry_sdk.Client.capture_event`.
291312
"""
292-
client, scope = self._stack[-1]
313+
client, top_scope = self._stack[-1]
314+
scope = _update_scope(top_scope, scope, scope_args)
293315
if client is not None:
294316
rv = client.capture_event(event, hint, scope)
295317
if rv is not None:
@@ -301,6 +323,8 @@ def capture_message(
301323
self,
302324
message, # type: str
303325
level=None, # type: Optional[str]
326+
scope=None, # type: Optional[Any]
327+
**scope_args # type: Dict[str, Any]
304328
):
305329
# type: (...) -> Optional[str]
306330
"""Captures a message. The message is just a string. If no level
@@ -312,10 +336,15 @@ def capture_message(
312336
return None
313337
if level is None:
314338
level = "info"
315-
return self.capture_event({"message": message, "level": level})
339+
return self.capture_event(
340+
{"message": message, "level": level}, scope=scope, **scope_args
341+
)
316342

317343
def capture_exception(
318-
self, error=None # type: Optional[Union[BaseException, ExcInfo]]
344+
self,
345+
error=None, # type: Optional[Union[BaseException, ExcInfo]]
346+
scope=None, # type: Optional[Any]
347+
**scope_args # type: Dict[str, Any]
319348
):
320349
# type: (...) -> Optional[str]
321350
"""Captures an exception.
@@ -334,7 +363,7 @@ def capture_exception(
334363

335364
event, hint = event_from_exception(exc_info, client_options=client.options)
336365
try:
337-
return self.capture_event(event, hint=hint)
366+
return self.capture_event(event, hint=hint, scope=scope, **scope_args)
338367
except Exception:
339368
self._capture_internal_exception(sys.exc_info())
340369

sentry_sdk/scope.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,50 @@ def _drop(event, cause, ty):
323323

324324
return event
325325

326+
def update_from_scope(self, scope):
327+
# type: (Scope) -> None
328+
if scope._level is not None:
329+
self._level = scope._level
330+
if scope._fingerprint is not None:
331+
self._fingerprint = scope._fingerprint
332+
if scope._transaction is not None:
333+
self._transaction = scope._transaction
334+
if scope._user is not None:
335+
self._user = scope._user
336+
if scope._tags:
337+
self._tags.update(scope._tags)
338+
if scope._contexts:
339+
self._contexts.update(scope._contexts)
340+
if scope._extras:
341+
self._extras.update(scope._extras)
342+
if scope._breadcrumbs:
343+
self._breadcrumbs.extend(scope._breadcrumbs)
344+
if scope._span:
345+
self._span = scope._span
346+
347+
def update_from_kwargs(
348+
self,
349+
user=None, # type: Optional[Any]
350+
level=None, # type: Optional[str]
351+
extras=None, # type: Optional[Dict[str, Any]]
352+
contexts=None, # type: Optional[Dict[str, Any]]
353+
tags=None, # type: Optional[Dict[str, str]]
354+
fingerprint=None, # type: Optional[List[str]]
355+
):
356+
# type: (...) -> None
357+
if level is not None:
358+
self._level = level
359+
if user is not None:
360+
self._user = user
361+
if extras is not None:
362+
self._extras.update(extras)
363+
if contexts is not None:
364+
self._contexts.update(contexts)
365+
if tags is not None:
366+
self._tags.update(tags)
367+
if fingerprint is not None:
368+
self._fingerprint = fingerprint
369+
326370
def __copy__(self):
327371
# type: () -> Scope
328372
rv = object.__new__(self.__class__) # type: Scope

tests/test_scope.py

Lines changed: 47 additions & 0 deletions

0 commit comments

Comments
 (0)