Skip to content

Commit a012fe4

Browse files
committed
Merge branch 'master' into potel-base
2 parents 5f3814e + 7cf4ee4 commit a012fe4

File tree

13 files changed

+130
-108
lines changed

13 files changed

+130
-108
lines changed

sentry_sdk/_types.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class SDKInfo(TypedDict):
129129
"contexts": dict[str, dict[str, object]],
130130
"dist": str,
131131
"duration": Optional[float],
132-
"environment": str,
132+
"environment": Optional[str],
133133
"errors": list[dict[str, Any]], # TODO: We can expand on this type
134134
"event_id": str,
135135
"exception": dict[
@@ -146,7 +146,7 @@ class SDKInfo(TypedDict):
146146
"monitor_slug": Optional[str],
147147
"platform": Literal["python"],
148148
"profile": object, # Should be sentry_sdk.profiler.Profile, but we can't import that here due to circular imports
149-
"release": str,
149+
"release": Optional[str],
150150
"request": dict[str, object],
151151
"sdk": Mapping[str, object],
152152
"server_name": str,

sentry_sdk/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def _get_options(*args, **kwargs):
107107
rv["environment"] = os.environ.get("SENTRY_ENVIRONMENT") or "production"
108108

109109
if rv["debug"] is None:
110-
rv["debug"] = env_to_bool(os.environ.get("SENTRY_DEBUG", "False"), strict=True)
110+
rv["debug"] = env_to_bool(os.environ.get("SENTRY_DEBUG"), strict=True) or False
111111

112112
if rv["server_name"] is None and hasattr(socket, "gethostname"):
113113
rv["server_name"] = socket.gethostname()

sentry_sdk/integrations/_asgi_common.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from sentry_sdk.scope import should_send_default_pii
44
from sentry_sdk.integrations._wsgi_common import _filter_headers
55

6-
from typing import TYPE_CHECKING
6+
from typing import TYPE_CHECKING, cast
77

88
if TYPE_CHECKING:
99
from typing import Any
@@ -37,8 +37,7 @@ def _get_url(asgi_scope, default_scheme=None, host=None):
3737
"""
3838
Extract URL from the ASGI scope, without also including the querystring.
3939
"""
40-
scheme = asgi_scope.get("scheme", default_scheme)
41-
40+
scheme = cast(str, asgi_scope.get("scheme", default_scheme))
4241
server = asgi_scope.get("server", None)
4342
path = asgi_scope.get("root_path", "") + asgi_scope.get("path", "")
4443

sentry_sdk/integrations/arq.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ def _sentry_create_worker(*args, **kwargs):
225225
]
226226
if hasattr(settings_cls, "cron_jobs"):
227227
settings_cls.cron_jobs = [
228-
_get_arq_cron_job(cron_job) for cron_job in settings_cls.cron_jobs
228+
_get_arq_cron_job(cron_job)
229+
for cron_job in (settings_cls.cron_jobs or [])
229230
]
230231

231232
if "functions" in kwargs:

sentry_sdk/integrations/django/asgi.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,9 @@ async def __acall__(self, *args, **kwargs):
241241
middleware_span = _check_middleware_span(old_method=f)
242242

243243
if middleware_span is None:
244-
return await f(*args, **kwargs)
244+
return await f(*args, **kwargs) # type: ignore
245245

246246
with middleware_span:
247-
return await f(*args, **kwargs)
247+
return await f(*args, **kwargs) # type: ignore
248248

249249
return SentryASGIMixin

sentry_sdk/integrations/grpc/__init__.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from grpc.aio import Server as AsyncServer
77

88
from sentry_sdk.integrations import Integration
9+
from sentry_sdk.utils import parse_version
910

1011
from .client import ClientInterceptor
1112
from .server import ServerInterceptor
@@ -41,6 +42,8 @@ def __getitem__(self, _):
4142

4243
P = ParamSpec("P")
4344

45+
GRPC_VERSION = parse_version(grpc.__version__)
46+
4447

4548
def _wrap_channel_sync(func: Callable[P, Channel]) -> Callable[P, Channel]:
4649
"Wrapper for synchronous secure and insecure channel."
@@ -127,7 +130,21 @@ def patched_aio_server( # type: ignore
127130
**kwargs: P.kwargs,
128131
) -> Server:
129132
server_interceptor = AsyncServerInterceptor()
130-
interceptors = (server_interceptor, *(interceptors or []))
133+
interceptors = [
134+
server_interceptor,
135+
*(interceptors or []),
136+
] # type: Sequence[grpc.ServerInterceptor]
137+
138+
try:
139+
# We prefer interceptors as a list because of compatibility with
140+
# opentelemetry https://github.com/getsentry/sentry-python/issues/4389
141+
# However, prior to grpc 1.42.0, only tuples were accepted, so we
142+
# have no choice there.
143+
if GRPC_VERSION is not None and GRPC_VERSION < (1, 42, 0):
144+
interceptors = tuple(interceptors)
145+
except Exception:
146+
pass
147+
131148
return func(*args, interceptors=interceptors, **kwargs) # type: ignore
132149

133150
return patched_aio_server # type: ignore

sentry_sdk/integrations/redis/_async_common.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,20 @@ async def _sentry_execute(self, *args, **kwargs):
4444
) as span:
4545
with capture_internal_exceptions():
4646
span_data = get_db_data_fn(self)
47+
48+
try:
49+
command_seq = self._execution_strategy._command_queue
50+
except AttributeError:
51+
if is_cluster:
52+
command_seq = self._command_stack
53+
else:
54+
command_seq = self.command_stack
55+
4756
pipeline_data = _get_pipeline_data(
4857
is_cluster=is_cluster,
4958
get_command_args_fn=get_command_args_fn,
5059
is_transaction=False if is_cluster else self.is_transaction,
51-
command_stack=(
52-
self._command_stack if is_cluster else self.command_stack
53-
),
60+
command_seq=command_seq,
5461
)
5562
_update_span(span, span_data, pipeline_data)
5663
_create_breadcrumb("redis.pipeline.execute", span_data, pipeline_data)

sentry_sdk/integrations/redis/_sync_common.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,17 @@ def sentry_patched_execute(self, *args, **kwargs):
4444
only_if_parent=True,
4545
) as span:
4646
with capture_internal_exceptions():
47+
try:
48+
command_seq = self._execution_strategy.command_queue
49+
except AttributeError:
50+
command_seq = self.command_stack
51+
4752
span_data = get_db_data_fn(self)
4853
pipeline_data = _get_pipeline_data(
4954
is_cluster=is_cluster,
5055
get_command_args_fn=get_command_args_fn,
5156
is_transaction=False if is_cluster else self.transaction,
52-
command_stack=self.command_stack,
57+
command_seq=command_seq,
5358
)
5459
_update_span(span, span_data, pipeline_data)
5560
_create_breadcrumb("redis.pipeline.execute", span_data, pipeline_data)

sentry_sdk/integrations/redis/redis_cluster.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,17 @@ def _get_async_cluster_db_data(async_redis_cluster_instance):
3737
def _get_async_cluster_pipeline_db_data(async_redis_cluster_pipeline_instance):
3838
# type: (AsyncClusterPipeline[Any]) -> dict[str, Any]
3939
with capture_internal_exceptions():
40-
return _get_async_cluster_db_data(
41-
# the AsyncClusterPipeline has always had a `_client` attr but it is private so potentially problematic and mypy
42-
# does not recognize it - see https://github.com/redis/redis-py/blame/v5.0.0/redis/asyncio/cluster.py#L1386
43-
async_redis_cluster_pipeline_instance._client, # type: ignore[attr-defined]
44-
)
40+
client = getattr(async_redis_cluster_pipeline_instance, "cluster_client", None)
41+
if client is None:
42+
# In older redis-py versions, the AsyncClusterPipeline had a `_client`
43+
# attr but it is private so potentially problematic and mypy does not
44+
# recognize it - see
45+
# https://github.com/redis/redis-py/blame/v5.0.0/redis/asyncio/cluster.py#L1386
46+
client = (
47+
async_redis_cluster_pipeline_instance._client # type: ignore[attr-defined]
48+
)
49+
50+
return _get_async_cluster_db_data(client)
4551

4652

4753
def _get_cluster_db_data(redis_cluster_instance):

sentry_sdk/integrations/redis/utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,22 +147,22 @@ def _parse_rediscluster_command(command):
147147
return command.args
148148

149149

150-
def _get_pipeline_data(is_cluster, get_command_args_fn, is_transaction, command_stack):
150+
def _get_pipeline_data(is_cluster, get_command_args_fn, is_transaction, command_seq):
151151
# type: (bool, Any, bool, Sequence[Any]) -> dict[str, Any]
152152
data = {
153153
"redis.is_cluster": is_cluster,
154154
"redis.transaction": is_transaction,
155155
} # type: dict[str, Any]
156156

157157
commands = []
158-
for i, arg in enumerate(command_stack):
158+
for i, arg in enumerate(command_seq):
159159
if i >= _MAX_NUM_COMMANDS:
160160
break
161161

162162
command = get_command_args_fn(arg)
163163
commands.append(_get_safe_command(command[0], command[1:]))
164164

165-
data["redis.commands.count"] = len(command_stack)
165+
data["redis.commands.count"] = len(command_seq)
166166
data["redis.commands.first_ten"] = commands
167167

168168
return data

sentry_sdk/integrations/tornado.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ async def sentry_execute_request_handler(self, *args, **kwargs):
8585
else:
8686

8787
@coroutine # type: ignore
88-
def sentry_execute_request_handler(self, *args, **kwargs): # type: ignore
88+
def sentry_execute_request_handler(self, *args, **kwargs):
8989
# type: (RequestHandler, *Any, **Any) -> Any
9090
with _handle_request_impl(self):
9191
result = yield from old_execute(self, *args, **kwargs)

tests/integrations/aiohttp/test_aiohttp.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,6 @@
66

77
import pytest
88

9-
try:
10-
import pytest_asyncio
11-
except ImportError:
12-
pytest_asyncio = None
13-
149
from aiohttp import web, ClientSession
1510
from aiohttp.client import ServerDisconnectedError
1611
from aiohttp.web_exceptions import (
@@ -26,14 +21,6 @@
2621
from tests.conftest import ApproxDict
2722

2823

29-
if pytest_asyncio is None:
30-
# `loop` was deprecated in `pytest-aiohttp`
31-
# in favor of `event_loop` from `pytest-asyncio`
32-
@pytest.fixture
33-
def event_loop(loop):
34-
yield loop
35-
36-
3724
@pytest.mark.asyncio
3825
async def test_basic(sentry_init, aiohttp_client, capture_events):
3926
sentry_init(integrations=[AioHttpIntegration()])
@@ -495,7 +482,7 @@ async def hello(request):
495482

496483
@pytest.mark.asyncio
497484
async def test_crumb_capture(
498-
sentry_init, aiohttp_raw_server, aiohttp_client, event_loop, capture_events
485+
sentry_init, aiohttp_raw_server, aiohttp_client, capture_events
499486
):
500487
def before_breadcrumb(crumb, hint):
501488
crumb["data"]["extra"] = "foo"
@@ -551,7 +538,6 @@ async def test_crumb_capture_client_error(
551538
sentry_init,
552539
aiohttp_raw_server,
553540
aiohttp_client,
554-
event_loop,
555541
capture_events,
556542
status_code,
557543
level,

0 commit comments

Comments
 (0)