Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions azure-pipelines/pipelines.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ jobs:
python.version: "3.11"
py312:
python.version: "3.12"
py313:
python.version: "3.13"

steps:

Expand Down Expand Up @@ -93,6 +95,8 @@ jobs:
python.version: "3.11"
py312:
python.version: "3.12"
py313:
python.version: "3.13"

steps:

Expand Down Expand Up @@ -124,6 +128,8 @@ jobs:
python.version: "3.11"
py312:
python.version: "3.12"
py313:
python.version: "3.13"

steps:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# circumstances).
# It is required to debug threads started by start_new_thread in Python 3.4
_temp = threading.Thread()
if hasattr(_temp, "_is_stopped"): # Python 3.x has this
if hasattr(_temp, "_is_stopped"): # Python 3.12 and earlier has this

def is_thread_alive(t):
return not t._is_stopped
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
)
from _pydev_bundle import pydev_log
from _pydev_bundle._pydev_saved_modules import threading
from _pydev_bundle.pydev_is_thread_alive import is_thread_alive
import weakref

version = 11
Expand Down Expand Up @@ -135,7 +136,7 @@ def _get_related_thread(self):
if thread is None:
return False

if thread._is_stopped:
if not is_thread_alive(thread):
return None

if thread._ident is None: # Can this happen?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,11 @@ def _current_frames():
IS_PY310_OR_GREATER = sys.version_info >= (3, 10)
IS_PY311_OR_GREATER = sys.version_info >= (3, 11)
IS_PY312_OR_GREATER = sys.version_info >= (3, 12)
IS_PY313_OR_GREATER = sys.version_info >= (3, 13)
IS_PY314_OR_GREATER = sys.version_info >= (3, 14)

# Not currently supported in Python 3.12.
SUPPORT_ATTACH_TO_PID = not IS_PY312_OR_GREATER
# Not currently supported in Python 3.14.
SUPPORT_ATTACH_TO_PID = not IS_PY314_OR_GREATER

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we know that attach doesn't work in 3.14 for some reason?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might work, but the code in the attach logic explicitly only allows up to 3.13. This is just matching that logic.



def version_str(v):
Expand Down
7,677 changes: 3,858 additions & 3,819 deletions src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_cython.c

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ from _pydevd_bundle.pydevd_constants import (
)
from _pydev_bundle import pydev_log
from _pydev_bundle._pydev_saved_modules import threading
from _pydev_bundle.pydev_is_thread_alive import is_thread_alive
import weakref

version = 11
Expand Down Expand Up @@ -141,7 +142,7 @@ cdef class PyDBAdditionalThreadInfo:
if thread is None:
return False

if thread._is_stopped:
if not is_thread_alive(thread):
return None

if thread._ident is None: # Can this happen?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ def add_exception_to_frame(frame, exception_info):


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


FILES_WITH_IMPORT_HOOKS = ["pydev_monkey_qt.py", "pydev_import_hook.py"]
Expand Down Expand Up @@ -140,6 +145,7 @@ def map_columns_to_line(self, original_line: str):
def _utf8_byte_offset_to_character_offset(s: str, offset: int):
byte_offset = 0
char_offset = 0
offset = offset or 0

for char_offset, character in enumerate(s):
byte_offset += 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from os.path import basename, splitext

from _pydev_bundle import pydev_log
from _pydev_bundle.pydev_is_thread_alive import is_thread_alive
from _pydevd_bundle import pydevd_dont_trace
from _pydevd_bundle.pydevd_constants import (
GlobalDebuggerHolder,
Expand Down Expand Up @@ -459,9 +460,10 @@ def _get_code_line_info(code_obj, _cache={}):
last_line = None

for offset, line in dis.findlinestarts(code_obj):
line_to_offset[line] = offset
if offset is not None and line is not None:
line_to_offset[line] = offset

if line_to_offset:
if len(line_to_offset):
first_line = min(line_to_offset)
last_line = max(line_to_offset)
ret = _CodeLineInfo(line_to_offset, first_line, last_line)
Expand Down Expand Up @@ -837,7 +839,7 @@ def _unwind_event(code, instruction, exc):
if py_db is None or py_db.pydb_disposed:
return

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

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

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

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

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

if not thread_info.trace or thread_info.thread._is_stopped:
if not thread_info.trace or not is_thread_alive(thread_info.thread):
# For thread-related stuff we can't disable the code tracing because other
# threads may still want it...
return
Expand Down
Loading