Skip to content

Commit f7d5df0

Browse files
authored
Get Python 3.13 to work (#1692)
* Get debug launch working * Turn Cython support back on * Fix test failures * Fix gevent test to be skipped * Missed a version change in pipeline * Fix comment * Review feedback
1 parent 25955a0 commit f7d5df0

File tree

14 files changed

+7025
-6769
lines changed

14 files changed

+7025
-6769
lines changed

azure-pipelines/pipelines.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ jobs:
6565
python.version: "3.11"
6666
py312:
6767
python.version: "3.12"
68+
py313:
69+
python.version: "3.13"
6870

6971
steps:
7072

@@ -93,6 +95,8 @@ jobs:
9395
python.version: "3.11"
9496
py312:
9597
python.version: "3.12"
98+
py313:
99+
python.version: "3.13"
96100

97101
steps:
98102

@@ -124,6 +128,8 @@ jobs:
124128
python.version: "3.11"
125129
py312:
126130
python.version: "3.12"
131+
py313:
132+
python.version: "3.13"
127133

128134
steps:
129135

src/debugpy/_vendored/pydevd/_pydev_bundle/pydev_is_thread_alive.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# circumstances).
55
# It is required to debug threads started by start_new_thread in Python 3.4
66
_temp = threading.Thread()
7-
if hasattr(_temp, "_is_stopped"): # Python 3.x has this
7+
if hasattr(_temp, "_is_stopped"): # Python 3.12 and earlier has this
88

99
def is_thread_alive(t):
1010
return not t._is_stopped

src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_additional_thread_info_regular.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
)
1111
from _pydev_bundle import pydev_log
1212
from _pydev_bundle._pydev_saved_modules import threading
13+
from _pydev_bundle.pydev_is_thread_alive import is_thread_alive
1314
import weakref
1415

1516
version = 11
@@ -135,7 +136,7 @@ def _get_related_thread(self):
135136
if thread is None:
136137
return False
137138

138-
if thread._is_stopped:
139+
if not is_thread_alive(thread):
139140
return None
140141

141142
if thread._ident is None: # Can this happen?

src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_constants.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,11 @@ def _current_frames():
173173
IS_PY310_OR_GREATER = sys.version_info >= (3, 10)
174174
IS_PY311_OR_GREATER = sys.version_info >= (3, 11)
175175
IS_PY312_OR_GREATER = sys.version_info >= (3, 12)
176+
IS_PY313_OR_GREATER = sys.version_info >= (3, 13)
177+
IS_PY314_OR_GREATER = sys.version_info >= (3, 14)
176178

177-
# Not currently supported in Python 3.12.
178-
SUPPORT_ATTACH_TO_PID = not IS_PY312_OR_GREATER
179+
# Not currently supported in Python 3.14.
180+
SUPPORT_ATTACH_TO_PID = not IS_PY314_OR_GREATER
179181

180182

181183
def version_str(v):

src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_cython.c

Lines changed: 3858 additions & 3819 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_cython.pyx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ from _pydevd_bundle.pydevd_constants import (
1616
)
1717
from _pydev_bundle import pydev_log
1818
from _pydev_bundle._pydev_saved_modules import threading
19+
from _pydev_bundle.pydev_is_thread_alive import is_thread_alive
1920
import weakref
2021

2122
version = 11
@@ -141,7 +142,7 @@ cdef class PyDBAdditionalThreadInfo:
141142
if thread is None:
142143
return False
143144

144-
if thread._is_stopped:
145+
if not is_thread_alive(thread):
145146
return None
146147

147148
if thread._ident is None: # Can this happen?

src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_frame_utils.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@ def add_exception_to_frame(frame, exception_info):
3535

3636

3737
def remove_exception_from_frame(frame):
38-
frame.f_locals.pop("__exception__", None)
38+
# In 3.13 frame.f_locals became a proxy for a dict, so we need to copy it to a real dict
39+
# so we can call the defined update method. Just deleting the entry throws in 3.13.
40+
items = {key: value for key, value in frame.f_locals.items()}
41+
if "__exception__" in items:
42+
del items["__exception__"]
43+
frame.f_locals.update(items)
3944

4045

4146
FILES_WITH_IMPORT_HOOKS = ["pydev_monkey_qt.py", "pydev_import_hook.py"]
@@ -140,6 +145,7 @@ def map_columns_to_line(self, original_line: str):
140145
def _utf8_byte_offset_to_character_offset(s: str, offset: int):
141146
byte_offset = 0
142147
char_offset = 0
148+
offset = offset or 0
143149

144150
for char_offset, character in enumerate(s):
145151
byte_offset += 1

src/debugpy/_vendored/pydevd/_pydevd_sys_monitoring/_pydevd_sys_monitoring.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from os.path import basename, splitext
1414

1515
from _pydev_bundle import pydev_log
16+
from _pydev_bundle.pydev_is_thread_alive import is_thread_alive
1617
from _pydevd_bundle import pydevd_dont_trace
1718
from _pydevd_bundle.pydevd_constants import (
1819
GlobalDebuggerHolder,
@@ -459,9 +460,10 @@ def _get_code_line_info(code_obj, _cache={}):
459460
last_line = None
460461

461462
for offset, line in dis.findlinestarts(code_obj):
462-
line_to_offset[line] = offset
463+
if offset is not None and line is not None:
464+
line_to_offset[line] = offset
463465

464-
if line_to_offset:
466+
if len(line_to_offset):
465467
first_line = min(line_to_offset)
466468
last_line = max(line_to_offset)
467469
ret = _CodeLineInfo(line_to_offset, first_line, last_line)
@@ -837,7 +839,7 @@ def _unwind_event(code, instruction, exc):
837839
if py_db is None or py_db.pydb_disposed:
838840
return
839841

840-
if not thread_info.trace or thread_info.thread._is_stopped:
842+
if not thread_info.trace or not is_thread_alive(thread_info.thread):
841843
# For thread-related stuff we can't disable the code tracing because other
842844
# threads may still want it...
843845
return
@@ -911,7 +913,7 @@ def _raise_event(code, instruction, exc):
911913
if py_db is None or py_db.pydb_disposed:
912914
return
913915

914-
if not thread_info.trace or thread_info.thread._is_stopped:
916+
if not thread_info.trace or not is_thread_alive(thread_info.thread):
915917
# For thread-related stuff we can't disable the code tracing because other
916918
# threads may still want it...
917919
return
@@ -1029,7 +1031,7 @@ def _return_event(code, instruction, retval):
10291031
if py_db is None or py_db.pydb_disposed:
10301032
return monitor.DISABLE
10311033

1032-
if not thread_info.trace or thread_info.thread._is_stopped:
1034+
if not thread_info.trace or not is_thread_alive(thread_info.thread):
10331035
# For thread-related stuff we can't disable the code tracing because other
10341036
# threads may still want it...
10351037
return
@@ -1340,7 +1342,7 @@ def _jump_event(code, from_offset, to_offset):
13401342
if py_db is None or py_db.pydb_disposed:
13411343
return monitor.DISABLE
13421344

1343-
if not thread_info.trace or thread_info.thread._is_stopped:
1345+
if not thread_info.trace or not is_thread_alive(thread_info.thread):
13441346
# For thread-related stuff we can't disable the code tracing because other
13451347
# threads may still want it...
13461348
return
@@ -1397,7 +1399,7 @@ def _line_event(code, line):
13971399
if py_db is None or py_db.pydb_disposed:
13981400
return monitor.DISABLE
13991401

1400-
if not thread_info.trace or thread_info.thread._is_stopped:
1402+
if not thread_info.trace or not is_thread_alive(thread_info.thread):
14011403
# For thread-related stuff we can't disable the code tracing because other
14021404
# threads may still want it...
14031405
return
@@ -1644,7 +1646,7 @@ def _start_method_event(code, instruction_offset):
16441646
if py_db is None or py_db.pydb_disposed:
16451647
return monitor.DISABLE
16461648

1647-
if not thread_info.trace or thread_info.thread._is_stopped:
1649+
if not thread_info.trace or not is_thread_alive(thread_info.thread):
16481650
# For thread-related stuff we can't disable the code tracing because other
16491651
# threads may still want it...
16501652
return

0 commit comments

Comments
 (0)