diff --git a/0003-fix-tests-Fix-exception-on-copying-frame.f_locals-Py.patch b/0003-fix-tests-Fix-exception-on-copying-frame.f_locals-Py.patch new file mode 100644 index 0000000..cdf8dd4 --- /dev/null +++ b/0003-fix-tests-Fix-exception-on-copying-frame.f_locals-Py.patch @@ -0,0 +1,78 @@ +From 7defd4e239cd4fe1749b74487bf5b52328e2c23e Mon Sep 17 00:00:00 2001 +From: Roman Inflianskas +Date: Thu, 4 Jul 2024 22:34:14 +0300 +Subject: [PATCH] fix(tests): Fix exception on copying `frame.f_locals` (Python + 3.13) + +Starting from Python 3.13, `frame.f_locals` is not `dict` anymore, but +`FrameLocalsProxy`, that cannot be copied using `copy.copy()`. In Python +3.13 and later, it should be copied using a method `.copy()`. The new way +of copying works the same as the old one for versions of Python prior to +3.13, according to the documentation (both copying methods produce a +shallow copy). + +Since Python 3.13, `FrameLocalsProxy` skips items of `locals()` that have +non-`str` keys; this is a CPython implementation detail. Disable +`test_non_string_variables` test on Python 3.13. + +See: +https://peps.python.org/pep-0667/ +https://github.com/python/cpython/issues/118921 +https://github.com/python/cpython/pull/118923 +https://docs.python.org/3.13/whatsnew/3.13.html#porting-to-python-3-13 +https://docs.python.org/3/library/copy.html +https://github.com/python/cpython/blame/7b413952e817ae87bfda2ac85dd84d30a6ce743b/Objects/frameobject.c#L148 +--- + sentry_sdk/utils.py | 3 +-- + tests/test_client.py | 7 +++++++ + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/sentry_sdk/utils.py b/sentry_sdk/utils.py +index a84f2eb3..64bbd383 100644 +--- a/sentry_sdk/utils.py ++++ b/sentry_sdk/utils.py +@@ -11,7 +11,6 @@ import sys + import threading + import time + from collections import namedtuple +-from copy import copy + from datetime import datetime + from decimal import Decimal + from functools import partial, partialmethod, wraps +@@ -618,7 +617,7 @@ def serialize_frame( + ) + + if include_local_variables: +- rv["vars"] = copy(frame.f_locals) ++ rv["vars"] = frame.f_locals.copy() + + return rv + +diff --git a/tests/test_client.py b/tests/test_client.py +index 0464f32b..447359a1 100644 +--- a/tests/test_client.py ++++ b/tests/test_client.py +@@ -31,6 +31,12 @@ if TYPE_CHECKING: + from sentry_sdk._types import Event + + ++maximum_python_312 = pytest.mark.skipif( ++ sys.version_info > (3, 12), ++ reason="Since Python 3.13, `FrameLocalsProxy` skips items of `locals()` that have non-`str` keys; this is a CPython implementation detail: https://github.com/python/cpython/blame/7b413952e817ae87bfda2ac85dd84d30a6ce743b/Objects/frameobject.c#L148", ++) ++ ++ + class EnvelopeCapturedError(Exception): + pass + +@@ -879,6 +885,7 @@ def test_errno_errors(sentry_init, capture_events): + assert exception["mechanism"]["meta"]["errno"]["number"] == 69 + + ++@maximum_python_312 + def test_non_string_variables(sentry_init, capture_events): + """There is some extremely terrible code in the wild that + inserts non-strings as variable names into `locals()`.""" +-- +2.45.2 + diff --git a/0004-fix-utils-Handle-partialmethod-in-qualname_from_func.patch b/0004-fix-utils-Handle-partialmethod-in-qualname_from_func.patch new file mode 100644 index 0000000..152f154 --- /dev/null +++ b/0004-fix-utils-Handle-partialmethod-in-qualname_from_func.patch @@ -0,0 +1,43 @@ +From a87d055571b0ae496b60d4e833f64b925e5f9563 Mon Sep 17 00:00:00 2001 +From: Roman Inflianskas +Date: Fri, 5 Jul 2024 16:38:32 +0300 +Subject: [PATCH] fix(utils): Handle `partialmethod` in qualname_from_function + (CPython 3.13) + +`_partialmethod` attribute of methods wrapped with `partialmethod()` was +renamed to `__partialmethod__` in CPython 3.13: +https://github.com/python/cpython/pull/16600 +--- + sentry_sdk/utils.py | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/sentry_sdk/utils.py b/sentry_sdk/utils.py +index 64bbd383..262f4f97 100644 +--- a/sentry_sdk/utils.py ++++ b/sentry_sdk/utils.py +@@ -1329,14 +1329,16 @@ def qualname_from_function(func): + + prefix, suffix = "", "" + +- if hasattr(func, "_partialmethod") and isinstance( +- func._partialmethod, partialmethod +- ): +- prefix, suffix = "partialmethod()" +- func = func._partialmethod.func +- elif isinstance(func, partial) and hasattr(func.func, "__name__"): ++ if isinstance(func, partial) and hasattr(func.func, "__name__"): + prefix, suffix = "partial()" + func = func.func ++ else: ++ # _partialmethod attribute of methods wrapped with partialmethod() was renamed to __partialmethod__ in CPython 3.13: ++ # https://github.com/python/cpython/pull/16600 ++ partial_method = getattr(func, "_partialmethod", None) or getattr(func, "__partialmethod__", None) ++ if isinstance(partial_method, partialmethod): ++ prefix, suffix = "partialmethod()" ++ func = partial_method.func + + if hasattr(func, "__qualname__"): + func_qualname = func.__qualname__ +-- +2.45.2 + diff --git a/python-sentry-sdk.spec b/python-sentry-sdk.spec index 2f7739e..e900268 100644 --- a/python-sentry-sdk.spec +++ b/python-sentry-sdk.spec @@ -61,6 +61,11 @@ Patch0: 0001-Reorder-forked-tests.patch # Tests fail because they are expected to be executed in a clean environment. # Upstream PR: https://github.com/getsentry/sentry-python/pull/3240 Patch1: 0002-ref-tests-Unhardcode-integration-list.patch +# Patches for Python 3.13 support +# Upstream PR: https://github.com/getsentry/sentry-python/pull/3271 +Patch2: 0003-fix-tests-Fix-exception-on-copying-frame.f_locals-Py.patch +# Upstream PR: https://github.com/getsentry/sentry-python/pull/3272 +Patch3: 0004-fix-utils-Handle-partialmethod-in-qualname_from_func.patch BuildArch: noarch BuildRequires: python3-devel