Skip to content

Commit 60650a4

Browse files
authored
Merge branch 'master' into master
2 parents 77e2ba3 + ce604f9 commit 60650a4

File tree

6 files changed

+67
-151
lines changed

6 files changed

+67
-151
lines changed

CHANGELOG.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,67 @@
11
# Changelog
22

3+
## 2.16.0
4+
5+
### Integrations
6+
7+
- Bottle: Add `failed_request_status_codes` (#3618) by @szokeasaurusrex
8+
9+
You can now define a set of integers that will determine which status codes
10+
should be reported to Sentry.
11+
12+
```python
13+
sentry_sdk.init(
14+
integrations=[
15+
BottleIntegration(
16+
failed_request_status_codes={403, *range(500, 600)},
17+
)
18+
]
19+
)
20+
```
21+
22+
Examples of valid `failed_request_status_codes`:
23+
24+
- `{500}` will only send events on HTTP 500.
25+
- `{400, *range(500, 600)}` will send events on HTTP 400 as well as the 5xx range.
26+
- `{500, 503}` will send events on HTTP 500 and 503.
27+
- `set()` (the empty set) will not send events for any HTTP status code.
28+
29+
The default is `{*range(500, 600)}`, meaning that all 5xx status codes are reported to Sentry.
30+
31+
- Bottle: Delete never-reached code (#3605) by @szokeasaurusrex
32+
- Redis: Remove flaky test (#3626) by @sentrivana
33+
- Django: Improve getting `psycopg3` connection info (#3580) by @nijel
34+
- Django: Add `SpotlightMiddleware` when Spotlight is enabled (#3600) by @BYK
35+
- Django: Open relevant error when `SpotlightMiddleware` is on (#3614) by @BYK
36+
- Django: Support `http_methods_to_capture` in ASGI Django (#3607) by @sentrivana
37+
38+
ASGI Django now also supports the `http_methods_to_capture` integration option. This is a configurable tuple of HTTP method verbs that should create a transaction in Sentry. The default is `("CONNECT", "DELETE", "GET", "PATCH", "POST", "PUT", "TRACE",)`. `OPTIONS` and `HEAD` are not included by default.
39+
40+
Here's how to use it:
41+
42+
```python
43+
sentry_sdk.init(
44+
integrations=[
45+
DjangoIntegration(
46+
http_methods_to_capture=("GET", "POST"),
47+
),
48+
],
49+
)
50+
```
51+
52+
### Miscellaneous
53+
54+
- Add 3.13 to setup.py (#3574) by @sentrivana
55+
- Add 3.13 to basepython (#3589) by @sentrivana
56+
- Fix type of `sample_rate` in DSC (and add explanatory tests) (#3603) by @antonpirker
57+
- Add `httpcore` based `HTTP2Transport` (#3588) by @BYK
58+
- Add opportunistic Brotli compression (#3612) by @BYK
59+
- Add `__notes__` support (#3620) by @szokeasaurusrex
60+
- Remove useless makefile targets (#3604) by @antonpirker
61+
- Simplify tox version spec (#3609) by @sentrivana
62+
- Consolidate contributing docs (#3606) by @antonpirker
63+
- Bump `codecov/codecov-action` from `4.5.0` to `4.6.0` (#3617) by @dependabot
64+
365
## 2.15.0
466

567
### Integrations
@@ -18,6 +80,7 @@
1880
),
1981
],
2082
)
83+
```
2184

2285
- Django: Allow ASGI to use `drf_request` in `DjangoRequestExtractor` (#3572) by @PakawiNz
2386
- Django: Don't let `RawPostDataException` bubble up (#3553) by @sentrivana

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
copyright = "2019-{}, Sentry Team and Contributors".format(datetime.now().year)
2929
author = "Sentry Team and Contributors"
3030

31-
release = "2.15.0"
31+
release = "2.16.0"
3232
version = ".".join(release.split(".")[:2]) # The short X.Y version.
3333

3434

sentry_sdk/consts.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,4 +574,4 @@ def _get_default_options():
574574
del _get_default_options
575575

576576

577-
VERSION = "2.15.0"
577+
VERSION = "2.16.0"

sentry_sdk/utils.py

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131
from typing import TYPE_CHECKING
3232

3333
if TYPE_CHECKING:
34-
from collections.abc import Awaitable
35-
3634
from types import FrameType, TracebackType
3735
from typing import (
3836
Any,
@@ -1731,12 +1729,6 @@ def _no_op(*_a, **_k):
17311729
pass
17321730

17331731

1734-
async def _no_op_async(*_a, **_k):
1735-
# type: (*Any, **Any) -> None
1736-
"""No-op function for ensure_integration_enabled_async."""
1737-
pass
1738-
1739-
17401732
if TYPE_CHECKING:
17411733

17421734
@overload
@@ -1803,59 +1795,6 @@ def runner(*args: "P.args", **kwargs: "P.kwargs"):
18031795
return patcher
18041796

18051797

1806-
if TYPE_CHECKING:
1807-
1808-
# mypy has some trouble with the overloads, hence the ignore[no-overload-impl]
1809-
@overload # type: ignore[no-overload-impl]
1810-
def ensure_integration_enabled_async(
1811-
integration, # type: type[sentry_sdk.integrations.Integration]
1812-
original_function, # type: Callable[P, Awaitable[R]]
1813-
):
1814-
# type: (...) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]
1815-
...
1816-
1817-
@overload
1818-
def ensure_integration_enabled_async(
1819-
integration, # type: type[sentry_sdk.integrations.Integration]
1820-
):
1821-
# type: (...) -> Callable[[Callable[P, Awaitable[None]]], Callable[P, Awaitable[None]]]
1822-
...
1823-
1824-
1825-
# The ignore[no-redef] also needed because mypy is struggling with these overloads.
1826-
def ensure_integration_enabled_async( # type: ignore[no-redef]
1827-
integration, # type: type[sentry_sdk.integrations.Integration]
1828-
original_function=_no_op_async, # type: Union[Callable[P, Awaitable[R]], Callable[P, Awaitable[None]]]
1829-
):
1830-
# type: (...) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]
1831-
"""
1832-
Version of `ensure_integration_enabled` for decorating async functions.
1833-
1834-
Please refer to the `ensure_integration_enabled` documentation for more information.
1835-
"""
1836-
1837-
if TYPE_CHECKING:
1838-
# Type hint to ensure the default function has the right typing. The overloads
1839-
# ensure the default _no_op function is only used when R is None.
1840-
original_function = cast(Callable[P, Awaitable[R]], original_function)
1841-
1842-
def patcher(sentry_patched_function):
1843-
# type: (Callable[P, Awaitable[R]]) -> Callable[P, Awaitable[R]]
1844-
async def runner(*args: "P.args", **kwargs: "P.kwargs"):
1845-
# type: (...) -> R
1846-
if sentry_sdk.get_client().get_integration(integration) is None:
1847-
return await original_function(*args, **kwargs)
1848-
1849-
return await sentry_patched_function(*args, **kwargs)
1850-
1851-
if original_function is _no_op_async:
1852-
return wraps(sentry_patched_function)(runner)
1853-
1854-
return wraps(original_function)(runner)
1855-
1856-
return patcher
1857-
1858-
18591798
if PY37:
18601799

18611800
def nanosecond_time():

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def get_file_text(file_name):
2121

2222
setup(
2323
name="sentry-sdk",
24-
version="2.15.0",
24+
version="2.16.0",
2525
author="Sentry Team and Contributors",
2626
author_email="[email protected]",
2727
url="https://github.com/getsentry/sentry-python",

tests/test_utils.py

Lines changed: 1 addition & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,12 @@
3131
_get_installed_modules,
3232
_generate_installed_modules,
3333
ensure_integration_enabled,
34-
ensure_integration_enabled_async,
3534
)
3635

3736

3837
class TestIntegration(Integration):
3938
"""
40-
Test integration for testing ensure_integration_enabled and
41-
ensure_integration_enabled_async decorators.
39+
Test integration for testing ensure_integration_enabled decorator.
4240
"""
4341

4442
identifier = "test"
@@ -783,90 +781,6 @@ def function_to_patch():
783781
assert patched_function.__name__ == "function_to_patch"
784782

785783

786-
@pytest.mark.asyncio
787-
async def test_ensure_integration_enabled_async_integration_enabled(sentry_init):
788-
# Setup variables and functions for the test
789-
async def original_function():
790-
return "original"
791-
792-
async def function_to_patch():
793-
return "patched"
794-
795-
sentry_init(integrations=[TestIntegration()])
796-
797-
# Test the decorator by applying to function_to_patch
798-
patched_function = ensure_integration_enabled_async(
799-
TestIntegration, original_function
800-
)(function_to_patch)
801-
802-
assert await patched_function() == "patched"
803-
assert patched_function.__name__ == "original_function"
804-
805-
806-
@pytest.mark.asyncio
807-
async def test_ensure_integration_enabled_async_integration_disabled(sentry_init):
808-
# Setup variables and functions for the test
809-
async def original_function():
810-
return "original"
811-
812-
async def function_to_patch():
813-
return "patched"
814-
815-
sentry_init(integrations=[]) # TestIntegration is disabled
816-
817-
# Test the decorator by applying to function_to_patch
818-
patched_function = ensure_integration_enabled_async(
819-
TestIntegration, original_function
820-
)(function_to_patch)
821-
822-
assert await patched_function() == "original"
823-
assert patched_function.__name__ == "original_function"
824-
825-
826-
@pytest.mark.asyncio
827-
async def test_ensure_integration_enabled_async_no_original_function_enabled(
828-
sentry_init,
829-
):
830-
shared_variable = "original"
831-
832-
async def function_to_patch():
833-
nonlocal shared_variable
834-
shared_variable = "patched"
835-
836-
sentry_init(integrations=[TestIntegration])
837-
838-
# Test the decorator by applying to function_to_patch
839-
patched_function = ensure_integration_enabled_async(TestIntegration)(
840-
function_to_patch
841-
)
842-
await patched_function()
843-
844-
assert shared_variable == "patched"
845-
assert patched_function.__name__ == "function_to_patch"
846-
847-
848-
@pytest.mark.asyncio
849-
async def test_ensure_integration_enabled_async_no_original_function_disabled(
850-
sentry_init,
851-
):
852-
shared_variable = "original"
853-
854-
async def function_to_patch():
855-
nonlocal shared_variable
856-
shared_variable = "patched"
857-
858-
sentry_init(integrations=[])
859-
860-
# Test the decorator by applying to function_to_patch
861-
patched_function = ensure_integration_enabled_async(TestIntegration)(
862-
function_to_patch
863-
)
864-
await patched_function()
865-
866-
assert shared_variable == "original"
867-
assert patched_function.__name__ == "function_to_patch"
868-
869-
870784
@pytest.mark.parametrize(
871785
"delta,expected_milliseconds",
872786
[

0 commit comments

Comments
 (0)