Skip to content

Support 3.13 in PyDev.Debugger #293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
43b8520
Port changes made in debugpy for 3.13 and updating to latest pydevd
rchiodo Oct 21, 2024
bec5512
Forgot the native attach code
rchiodo Oct 21, 2024
0c8ee4f
More fixes specific to 3.13
rchiodo Oct 21, 2024
b287174
Fix thread id test case
rchiodo Oct 21, 2024
f315b5b
Fix thread watching for 3.13 and fix some more tests
rchiodo Oct 22, 2024
5049e11
Get thread logging working in multithreaded scenario
rchiodo Oct 22, 2024
1a5acb5
Remove the skipping of jump events, just always skip when jumping to …
rchiodo Oct 22, 2024
c5549a5
Get 3.13 tests passing
rchiodo Oct 22, 2024
fa17ca2
Fix 3.12 failure for get_main_thread_id
rchiodo Oct 23, 2024
140bf65
Add new condition for is_thread_alive
rchiodo Oct 23, 2024
f7c2846
Remove some logging and exclude failing tests
rchiodo Oct 23, 2024
7a77191
Fix linter
rchiodo Oct 23, 2024
bd81fb6
Remove unused file
rchiodo Oct 23, 2024
98cafdb
Fix workflow?
rchiodo Oct 23, 2024
3db96dc
Fix cython files
rchiodo Oct 23, 2024
41f0c49
Skip 3.13 on ubuntu
rchiodo Oct 23, 2024
c6d9886
Update install and 3.13 to release
rchiodo Oct 23, 2024
7e9ca5a
add 3.13 to matrix
rchiodo Oct 23, 2024
22de0cf
Skip flakey test
rchiodo Oct 23, 2024
96315ff
setuptools not found?
rchiodo Oct 23, 2024
2d7f1c0
Actually skip flakey test
rchiodo Oct 23, 2024
9dd32c5
Skip ubuntu flakey test
rchiodo Oct 23, 2024
bb9a128
Workaround extra thread events
rchiodo Oct 23, 2024
b258eab
Up verbosity on wheel creation
rchiodo Oct 23, 2024
044504e
Use latest CPython 3.13 in building wheels
rchiodo Oct 23, 2024
b956dba
Make sure we have setupttools in the cibuildwheel
rchiodo Oct 23, 2024
251098d
Port binskim fixes from debugpy
rchiodo Oct 23, 2024
26c1df9
Andother spot where co_lines are used and not checked for none
rchiodo Oct 24, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/pydevd-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
fail-fast: false
matrix:
os: [macos-latest, windows-latest]
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
steps:
- uses: actions/checkout@v3
- name: Set up Python
Expand Down
19 changes: 15 additions & 4 deletions .github/workflows/pydevd-tests-python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ jobs:
"ubuntu-py311-cython",
"ubuntu-py312-cython-checkbin",
"windows-py312-cython-checkbin",
"ubuntu-py313-cython",
"windows-py313-cython",
]

include:
Expand Down Expand Up @@ -64,6 +66,14 @@ jobs:
python: "3.12"
os: windows-latest
PYDEVD_USE_CYTHON: YES
- name: "ubuntu-py313-cython"
python: "3.13"
os: ubuntu-20.04
PYDEVD_USE_CYTHON: YES
- name: "windows-py313-cython"
python: "3.13"
os: windows-latest
PYDEVD_USE_CYTHON: YES

steps:
- uses: actions/checkout@v1
Expand Down Expand Up @@ -95,7 +105,7 @@ jobs:
pip install untangle --no-warn-script-location
pip install importlib-metadata --no-warn-script-location
- name: Install Python 3.x deps
if: contains(matrix.name, 'py3') && !contains(matrix.name, 'pypy') && !contains(matrix.name, 'py312') && !contains(matrix.name, 'py311')
if: contains(matrix.name, 'py3') && !contains(matrix.name, 'pypy') && !contains(matrix.name, 'py312') && !contains(matrix.name, 'py311') && !contains(matrix.name, 'py313')
run: |
pip install PySide2 --no-warn-script-location
pip install "numpy<2" --force --no-warn-script-location
Expand All @@ -118,13 +128,14 @@ jobs:
- name: Check that wheels can be built
if: contains(matrix.name, 'checkbin') && contains(matrix.name, 'ubuntu')
run: |
python -m pip install cibuildwheel==2.21.2
python -m pip install setuptools --no-warn-script-location
python -m pip install cibuildwheel==2.21.3
# Remove these .so files (will be rebuilt)
rm pydevd_attach_to_process/*.so
python -m cibuildwheel --output-dir wheelhouse
env:
CIBW_BUILD: cp310-*manylinux*x86_64 cp311-*manylinux*x86_64 cp312-*manylinux*x86_64
CIBW_BUILD_VERBOSITY: 1
CIBW_BUILD: cp310-*manylinux*x86_64 cp311-*manylinux*x86_64 cp312-*manylinux*x86_64 cp313-*manylinux*x86_64
CIBW_BUILD_VERBOSITY: 3

- name: Rebuild .so
if: contains(matrix.name, 'checkbin') && contains(matrix.name, 'ubuntu')
Expand Down
6 changes: 5 additions & 1 deletion _pydev_bundle/pydev_is_thread_alive.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
# 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, "_handle") and hasattr(_temp, "_started"):
# Python 3.13 and later has this
def is_thread_alive(t):
return not t._handle.is_done() and t._started.is_set()
if hasattr(_temp, "_is_stopped"): # Python 3.12 and earlier has this

def is_thread_alive(t):
return not t._is_stopped
Expand Down
25 changes: 21 additions & 4 deletions _pydev_bundle/pydev_monkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import sys
from _pydev_bundle._pydev_saved_modules import threading
from _pydevd_bundle.pydevd_constants import (
IS_PY313_OR_GREATER,
get_global_debugger,
IS_WINDOWS,
IS_JYTHON,
Expand Down Expand Up @@ -1173,11 +1174,13 @@ def _get_threading_modules_to_patch():


def patch_thread_module(thread_module):
attr = "_start_joinable_thread" if IS_PY313_OR_GREATER else "_start_new_thread"
is_start_joinable = thread_module is threading and IS_PY313_OR_GREATER
if getattr(thread_module, "_original_start_new_thread", None) is None:
if thread_module is threading:
if not hasattr(thread_module, "_start_new_thread"):
if not hasattr(thread_module, attr):
return # Jython doesn't have it.
_original_start_new_thread = thread_module._original_start_new_thread = thread_module._start_new_thread
_original_start_new_thread = thread_module._original_start_new_thread = getattr(thread_module, attr)
else:
_original_start_new_thread = thread_module._original_start_new_thread = thread_module.start_new_thread
else:
Expand All @@ -1191,6 +1194,16 @@ def pydev_start_new_thread(self, function, args=(), kwargs={}):
"""
return _original_start_new_thread(_UseNewThreadStartup(function, args, kwargs), ())

class ClassWithPydevStartJoinableThread:
def pydev_start_joinable_thread(self, function, *args, **kwargs):
"""
We need to replace the original thread_module._start_joinable_thread with this function so that threads started
through it and not through the threading module are properly traced.
"""
handle = kwargs.pop("handle", None)
daemon = kwargs.pop("daemon", True)
return _original_start_new_thread(_UseNewThreadStartup(function, args, kwargs), handle=handle, daemon=daemon)

# This is a hack for the situation where the thread_module.start_new_thread is declared inside a class, such as the one below
# class F(object):
# start_new_thread = thread_module.start_new_thread
Expand All @@ -1199,13 +1212,17 @@ def pydev_start_new_thread(self, function, args=(), kwargs={}):
# self.start_new_thread(self.function, args, kwargs)
# So, if it's an already bound method, calling self.start_new_thread won't really receive a different 'self' -- it
# does work in the default case because in builtins self isn't passed either.
pydev_start_new_thread = ClassWithPydevStartNewThread().pydev_start_new_thread
pydev_start_new_thread = (
ClassWithPydevStartJoinableThread().pydev_start_joinable_thread
if is_start_joinable
else ClassWithPydevStartNewThread().pydev_start_new_thread
)

try:
# We need to replace the original thread_module.start_new_thread with this function so that threads started through
# it and not through the threading module are properly traced.
if thread_module is threading:
thread_module._start_new_thread = pydev_start_new_thread
setattr(thread_module, attr, pydev_start_new_thread)
else:
thread_module.start_new_thread = pydev_start_new_thread
thread_module.start_new = pydev_start_new_thread
Expand Down
3 changes: 2 additions & 1 deletion _pydevd_bundle/pydevd_additional_thread_info_regular.py
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
2 changes: 2 additions & 0 deletions _pydevd_bundle/pydevd_collect_bytecode_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,8 @@ def _create_msg_part(self, instruction, tok=None, line=None):
argrepr = instruction.argrepr
if isinstance(argrepr, str) and argrepr.startswith("NULL + "):
argrepr = argrepr[7:]
if isinstance(argrepr, str) and argrepr.endswith("+ NULL"):
argrepr = argrepr[:-7]
return _MsgPart(line, tok if tok is not None else dec(instruction, argrepr))

def _next_instruction_to_str(self, line_to_contents):
Expand Down
3 changes: 2 additions & 1 deletion _pydevd_bundle/pydevd_comm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1140,7 +1140,8 @@ def internal_get_next_statement_targets(dbg, seq, thread_id, frame_id):
xml += "<line>%d</line>" % (frame.f_lineno,)
else:
for _, line in linestarts:
xml += "<line>%d</line>" % (line,)
if line is not None:
xml += "<line>%d</line>" % (line,)
del frame
xml += "</xml>"
cmd = dbg.cmd_factory.make_get_next_statement_targets_message(seq, xml)
Expand Down
3 changes: 2 additions & 1 deletion _pydevd_bundle/pydevd_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,10 @@ def _current_frames():
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_PY313_OR_GREATER
SUPPORT_ATTACH_TO_PID = not IS_PY314_OR_GREATER


def version_str(v):
Expand Down
Loading
Loading