Skip to content

Commit 52e4e23

Browse files
feat(hub): Emit deprecation warnings from Hub API (#3280)
`sentry_sdk.Hub` has been deprecated since Sentry SDK version 2.0.0 per our docs; however, we waited with adding deprecation warnings because the SDK itself was still using `Hub` APIs until recently. Since we no longer use `Hub` APIs in the SDK (except in `Hub` APIs which are themselves deprecated), we can now start emitting deprecation warnings. Closes #3265
1 parent fbe8ecc commit 52e4e23

File tree

6 files changed

+85
-8
lines changed

6 files changed

+85
-8
lines changed

sentry_sdk/hub.py

+37-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import warnings
12
from contextlib import contextmanager
23

34
from sentry_sdk._compat import with_metaclass
@@ -55,6 +56,32 @@ def overload(x):
5556
return x
5657

5758

59+
class SentryHubDeprecationWarning(DeprecationWarning):
60+
"""
61+
A custom deprecation warning to inform users that the Hub is deprecated.
62+
"""
63+
64+
_MESSAGE = (
65+
"`sentry_sdk.Hub` is deprecated and will be removed in a future major release. "
66+
"Please consult our 1.x to 2.x migration guide for details on how to migrate "
67+
"`Hub` usage to the new API: "
68+
"https://docs.sentry.io/platforms/python/migration/1.x-to-2.x"
69+
)
70+
71+
def __init__(self, *_):
72+
# type: (*object) -> None
73+
super().__init__(self._MESSAGE)
74+
75+
76+
@contextmanager
77+
def _suppress_hub_deprecation_warning():
78+
# type: () -> Generator[None, None, None]
79+
"""Utility function to suppress deprecation warnings for the Hub."""
80+
with warnings.catch_warnings():
81+
warnings.filterwarnings("ignore", category=SentryHubDeprecationWarning)
82+
yield
83+
84+
5885
_local = ContextVar("sentry_current_hub")
5986

6087

@@ -63,16 +90,20 @@ class HubMeta(type):
6390
def current(cls):
6491
# type: () -> Hub
6592
"""Returns the current instance of the hub."""
93+
warnings.warn(SentryHubDeprecationWarning(), stacklevel=2)
6694
rv = _local.get(None)
6795
if rv is None:
68-
rv = Hub(GLOBAL_HUB)
96+
with _suppress_hub_deprecation_warning():
97+
# This will raise a deprecation warning; supress it since we already warned above.
98+
rv = Hub(GLOBAL_HUB)
6999
_local.set(rv)
70100
return rv
71101

72102
@property
73103
def main(cls):
74104
# type: () -> Hub
75105
"""Returns the main instance of the hub."""
106+
warnings.warn(SentryHubDeprecationWarning(), stacklevel=2)
76107
return GLOBAL_HUB
77108

78109

@@ -103,6 +134,7 @@ def __init__(
103134
scope=None, # type: Optional[Any]
104135
):
105136
# type: (...) -> None
137+
warnings.warn(SentryHubDeprecationWarning(), stacklevel=2)
106138

107139
current_scope = None
108140

@@ -689,7 +721,10 @@ def trace_propagation_meta(self, span=None):
689721
)
690722

691723

692-
GLOBAL_HUB = Hub()
724+
with _suppress_hub_deprecation_warning():
725+
# Suppress deprecation warning for the Hub here, since we still always
726+
# import this module.
727+
GLOBAL_HUB = Hub()
693728
_local.set(GLOBAL_HUB)
694729

695730

tests/conftest.py

+12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import json
22
import os
33
import socket
4+
import warnings
45
from threading import Thread
56
from contextlib import contextmanager
67
from http.server import BaseHTTPRequestHandler, HTTPServer
@@ -561,6 +562,17 @@ def teardown_profiling():
561562
teardown_continuous_profiler()
562563

563564

565+
@pytest.fixture()
566+
def suppress_deprecation_warnings():
567+
"""
568+
Use this fixture to suppress deprecation warnings in a test.
569+
Useful for testing deprecated SDK features.
570+
"""
571+
with warnings.catch_warnings():
572+
warnings.simplefilter("ignore", DeprecationWarning)
573+
yield
574+
575+
564576
class MockServerRequestHandler(BaseHTTPRequestHandler):
565577
def do_GET(self): # noqa: N802
566578
# Process an HTTP GET request and return a response with an HTTP 200 status.

tests/new_scopes_compat/conftest.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33

44

55
@pytest.fixture(autouse=True)
6-
def isolate_hub():
6+
def isolate_hub(suppress_deprecation_warnings):
77
with sentry_sdk.Hub(None):
88
yield

tests/profiler/test_transaction_profiler.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,7 @@ def test_profile_processing(
817817
assert processed["samples"] == expected["samples"]
818818

819819

820-
def test_hub_backwards_compatibility():
820+
def test_hub_backwards_compatibility(suppress_deprecation_warnings):
821821
hub = sentry_sdk.Hub()
822822

823823
with pytest.warns(DeprecationWarning):

tests/test_basics.py

+18
Original file line numberDiff line numberDiff line change
@@ -871,3 +871,21 @@ def test_last_event_id_scope(sentry_init):
871871
# Should not crash
872872
with isolation_scope() as scope:
873873
assert scope.last_event_id() is None
874+
875+
876+
def test_hub_constructor_deprecation_warning():
877+
with pytest.warns(sentry_sdk.hub.SentryHubDeprecationWarning):
878+
Hub()
879+
880+
881+
def test_hub_current_deprecation_warning():
882+
with pytest.warns(sentry_sdk.hub.SentryHubDeprecationWarning) as warning_records:
883+
Hub.current
884+
885+
# Make sure we only issue one deprecation warning
886+
assert len(warning_records) == 1
887+
888+
889+
def test_hub_main_deprecation_warnings():
890+
with pytest.warns(sentry_sdk.hub.SentryHubDeprecationWarning):
891+
Hub.main

tests/tracing/test_deprecated.py

+16-4
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,29 @@ def test_start_span_to_start_transaction(sentry_init, capture_events):
2727
assert events[1]["transaction"] == "/2/"
2828

2929

30-
@pytest.mark.parametrize("parameter_value", (sentry_sdk.Hub(), sentry_sdk.Scope()))
31-
def test_passing_hub_parameter_to_transaction_finish(parameter_value):
30+
@pytest.mark.parametrize(
31+
"parameter_value_getter",
32+
# Use lambda to avoid Hub deprecation warning here (will suppress it in the test)
33+
(lambda: sentry_sdk.Hub(), lambda: sentry_sdk.Scope()),
34+
)
35+
def test_passing_hub_parameter_to_transaction_finish(
36+
suppress_deprecation_warnings, parameter_value_getter
37+
):
38+
parameter_value = parameter_value_getter()
3239
transaction = sentry_sdk.tracing.Transaction()
3340
with pytest.warns(DeprecationWarning):
3441
transaction.finish(hub=parameter_value)
3542

3643

37-
def test_passing_hub_object_to_scope_transaction_finish():
44+
def test_passing_hub_object_to_scope_transaction_finish(suppress_deprecation_warnings):
3845
transaction = sentry_sdk.tracing.Transaction()
46+
47+
# Do not move the following line under the `with` statement. Otherwise, the Hub.__init__ deprecation
48+
# warning will be confused with the transaction.finish deprecation warning that we are testing.
49+
hub = sentry_sdk.Hub()
50+
3951
with pytest.warns(DeprecationWarning):
40-
transaction.finish(sentry_sdk.Hub())
52+
transaction.finish(hub)
4153

4254

4355
def test_no_warnings_scope_to_transaction_finish():

0 commit comments

Comments
 (0)