Add patches for Python 3.13 support

This commit is contained in:
Roman Inflianskas 2024-07-16 22:05:26 +03:00
parent eca5339c25
commit 970ae4bf35
No known key found for this signature in database
3 changed files with 126 additions and 0 deletions

View file

@ -0,0 +1,78 @@
From 7defd4e239cd4fe1749b74487bf5b52328e2c23e Mon Sep 17 00:00:00 2001
From: Roman Inflianskas <rominf@pm.me>
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

View file

@ -0,0 +1,43 @@
From a87d055571b0ae496b60d4e833f64b925e5f9563 Mon Sep 17 00:00:00 2001
From: Roman Inflianskas <rominf@pm.me>
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(<function ", ">)"
- 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(<function ", ">)"
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(<function ", ">)"
+ func = partial_method.func
if hasattr(func, "__qualname__"):
func_qualname = func.__qualname__
--
2.45.2

View file

@ -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