Skip to content

Commit

Permalink
Updating PyDev.Debugger
Browse files Browse the repository at this point in the history
  • Loading branch information
fabioz committed Feb 18, 2024
1 parent a1b4ed4 commit f5f506c
Show file tree
Hide file tree
Showing 15 changed files with 2,897 additions and 2,153 deletions.
6 changes: 6 additions & 0 deletions features/org.python.pydev.p2-repo/.project
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.python.pydev.PyDevBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.UpdateSiteBuilder</name>
<arguments>
Expand All @@ -13,5 +18,6 @@
</buildSpec>
<natures>
<nature>org.eclipse.pde.UpdateSiteNature</nature>
<nature>org.python.pydev.pythonNature</nature>
</natures>
</projectDescription>
5 changes: 5 additions & 0 deletions features/org.python.pydev.p2-repo/.pydevproject
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?><pydev_project>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python interpreter</pydev_property>
</pydev_project>
24 changes: 15 additions & 9 deletions plugins/com.python.pydev.docs/release_email.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
PyDev 11.0.2 Released
PyDev 12.0.0 Released

PyDev 11.0.2 Release Highlights
PyDev 12.0.0 Release Highlights
-------------------------------

Continuing with the updates to Python 3.12, the new release integrates
the latest version of typeshed (so, **from typing import override** is
now properly recognized).
* **Debugger**
* **sys.monitoring** is now used in Python 3.12 (and it's **much** faster than any previous version).
* A new setting was added in the **Preferences > PyDev > Debug** to debug **just my code** (meaning that when stepping it will just step into files under PyDev source folders).
* Improved the step into function (activated with **Ctrl+Alt** then **Click function** to step into).
* Support for Python 3.6 and 3.7 was dropped (only Python 3.8 onwards is now supported).

Also, it's now possible to specify vmargs in the python interpreter
(and not just in the launch configuration).
* **Ruff**
* Ruff can now be used as a code formatter.
* The latest ruff (**0.1.x**) is now supported (as it broke backward compatibility in its **0.1.0** version).

For Python 3.11 onwards, **-Xfrozen_modules=off** is now
set in the vm arguments by default.
* **Code Analysis**
* Fixes in semantic analysis to better determine if strings in annotations should be checked for symbols or not.

Note: **Only Python 3.8 onwards is now supported**
* **Python 3.6** and **3.7** support is now **dropped** (please use **PyDev 11.0.3** if you still use it).

About PyDev
---------------------------
Expand Down
13 changes: 13 additions & 0 deletions plugins/org.python.pydev.core/pysrc/.github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# These are supported funding model platforms

github: [fabioz]
patreon: fabioz
#open_collective: # Replace with a single Open Collective username
#ko_fi: # Replace with a single Ko-fi username
#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
#liberapay: # Replace with a single Liberapay username
#issuehunt: # Replace with a single IssueHunt username
#otechie: # Replace with a single Otechie username
#lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: [https://www.pydev.org/about.html] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,17 @@ jobs:
pip install psutil --no-warn-script-location
pip install ipython --no-warn-script-location
pip install untangle --no-warn-script-location
pip install "django<=4.2" --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')
run: |
pip install PySide2 --no-warn-script-location
pip install cherrypy --no-warn-script-location
pip install gevent greenlet
- name: Install django
if: "!contains(matrix.name, 'py38')"
run: pip install "django<=4.2" --no-warn-script-location

- name: Install Pandas
if: contains(matrix.name, 'py310') && !contains(matrix.name, 'pypy')
# The pandas Styler also requires jinja2.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ def default(o):

properties = class_to_generate['properties']
class_to_generate['props'] = ' __props__ = %s' % _indent_lines(
json.dumps(properties, indent=4, default=default)).strip()
json.dumps(properties, indent=4, default=default).replace('true', 'True')).strip()


def update_class_to_generate_refs(class_to_generate):
Expand Down

Large diffs are not rendered by default.

3,808 changes: 2,148 additions & 1,660 deletions plugins/org.python.pydev.core/pysrc/_pydevd_bundle/_debug_adapter/pydevd_schema.py

Large diffs are not rendered by default.

18 changes: 16 additions & 2 deletions plugins/org.python.pydev.core/pysrc/_pydevd_bundle/pydevd_comm.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,9 @@
from _pydevd_bundle.pydevd_comm_constants import * # @UnusedWildImport

# Socket import aliases:
AF_INET, SOCK_STREAM, SHUT_WR, SOL_SOCKET, IPPROTO_TCP, socket = (
AF_INET, AF_INET6, SOCK_STREAM, SHUT_WR, SOL_SOCKET, IPPROTO_TCP, socket = (
socket_module.AF_INET,
socket_module.AF_INET6,
socket_module.SOCK_STREAM,
socket_module.SHUT_WR,
socket_module.SOL_SOCKET,
Expand Down Expand Up @@ -449,6 +450,9 @@ def start_server(port):

try:
s.listen(1)
# Let the user know it's halted waiting for the connection.
pydev_log.critical("pydevd: waiting for connection at: %s:%s\n", *s.getsockname())

new_socket, _addr = s.accept()
pydev_log.info("Connection accepted")
# closing server socket is not necessary but we don't need it
Expand All @@ -463,7 +467,17 @@ def start_client(host, port):
''' connects to a host/port '''
pydev_log.info("Connecting to %s:%s", host, port)

s = socket(AF_INET, SOCK_STREAM)
address_family = AF_INET
for res in socket_module.getaddrinfo(host, port, 0, SOCK_STREAM):
if res[0] == AF_INET:
address_family = res[0]
# Prefer IPv4 addresses for backward compat.
break
if res[0] == AF_INET6:
# Don't break after this - if the socket is dual-stack prefer IPv4.
address_family = res[0]

s = socket(address_family, SOCK_STREAM)

# Set TCP keepalive on an open socket.
# It activates after 1 second (TCP_KEEPIDLE,) of idleness,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
CMD_SET_NEXT_STATEMENT, CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION, \
CMD_THREAD_RESUME_SINGLE_NOTIFICATION, CMD_THREAD_KILL, CMD_STOP_ON_START, CMD_INPUT_REQUESTED, \
CMD_EXIT, CMD_STEP_INTO_COROUTINE, CMD_STEP_RETURN_MY_CODE, CMD_SMART_STEP_INTO, \
CMD_SET_FUNCTION_BREAK
CMD_SET_FUNCTION_BREAK, CMD_THREAD_RUN
from _pydevd_bundle.pydevd_constants import get_thread_id, ForkSafeLock, DebugInfoHolder
from _pydevd_bundle.pydevd_net_command import NetCommand, NULL_NET_COMMAND
from _pydevd_bundle.pydevd_net_command_factory_xml import NetCommandFactory
Expand Down Expand Up @@ -435,12 +435,62 @@ def after_send(socket):
return cmd

@overrides(NetCommandFactory.make_thread_suspend_message)
def make_thread_suspend_message(self, *args, **kwargs):
return NULL_NET_COMMAND # Not a part of the debug adapter protocol
def make_thread_suspend_message(self, py_db, thread_id, frames_list, stop_reason, message, trace_suspend_type, thread, info):
from _pydevd_bundle.pydevd_comm_constants import CMD_THREAD_SUSPEND
if py_db.multi_threads_single_notification:
pydev_log.debug("Skipping per-thread thread suspend notification.")
return NULL_NET_COMMAND # Don't send per-thread, send a single one.
pydev_log.debug("Sending per-thread thread suspend notification (stop_reason: %s)", stop_reason)

exc_desc = None
exc_name = None
preserve_focus_hint = False
if stop_reason in self._STEP_REASONS:
if info.pydev_original_step_cmd == CMD_STOP_ON_START:

# Just to make sure that's not set as the original reason anymore.
info.pydev_original_step_cmd = -1
stop_reason = 'entry'
else:
stop_reason = 'step'
elif stop_reason in self._EXCEPTION_REASONS:
stop_reason = 'exception'
elif stop_reason == CMD_SET_BREAK:
stop_reason = 'breakpoint'
elif stop_reason == CMD_SET_FUNCTION_BREAK:
stop_reason = 'function breakpoint'
elif stop_reason == CMD_SET_NEXT_STATEMENT:
stop_reason = 'goto'
else:
stop_reason = 'pause'
preserve_focus_hint = True

if stop_reason == 'exception':
exception_info_response = build_exception_info_response(
py_db, thread_id, thread, -1, set_additional_thread_info, self._iter_visible_frames_info, max_frames=-1)
exception_info_response

exc_name = exception_info_response.body.exceptionId
exc_desc = exception_info_response.body.description

body = pydevd_schema.StoppedEventBody(
reason=stop_reason,
description=exc_desc,
threadId=thread_id,
text=exc_name,
allThreadsStopped=False,
preserveFocusHint=preserve_focus_hint,
)
event = pydevd_schema.StoppedEvent(body)
return NetCommand(CMD_THREAD_SUSPEND, 0, event, is_json=True)

@overrides(NetCommandFactory.make_thread_run_message)
def make_thread_run_message(self, *args, **kwargs):
return NULL_NET_COMMAND # Not a part of the debug adapter protocol
def make_thread_run_message(self, py_db, thread_id, reason):
if py_db.multi_threads_single_notification:
return NULL_NET_COMMAND # Don't send per-thread, send a single one.
body = ContinuedEventBody(threadId=thread_id, allThreadsContinued=False)
event = pydevd_schema.ContinuedEvent(body)
return NetCommand(CMD_THREAD_RUN, 0, event, is_json=True)

@overrides(NetCommandFactory.make_reloaded_code_message)
def make_reloaded_code_message(self, *args, **kwargs):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ def make_thread_suspend_str(

return ''.join(cmd_text_list), thread_stack_str

def make_thread_suspend_message(self, py_db, thread_id, frames_list, stop_reason, message, trace_suspend_type):
def make_thread_suspend_message(self, py_db, thread_id, frames_list, stop_reason, message, trace_suspend_type, thread, additional_info):
try:
thread_suspend_str, thread_stack_str = self.make_thread_suspend_str(
py_db, thread_id, frames_list, stop_reason, message, trace_suspend_type)
Expand All @@ -307,7 +307,7 @@ def make_thread_resume_single_notification(self, thread_id):
except:
return self.make_error_message(0, get_exception_traceback_str())

def make_thread_run_message(self, thread_id, reason):
def make_thread_run_message(self, py_db, thread_id, reason):
try:
return NetCommand(CMD_THREAD_RUN, 0, "%s\t%s" % (thread_id, reason))
except:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -541,12 +541,21 @@ def on_resumed():
cmd = NetCommand(CMD_RETURN, 0, response, is_json=True)
py_db.writer.add_command(cmd)

# Only send resumed notification when it has actually resumed!
# (otherwise the user could send a continue, receive the notification and then
# request a new pause which would be paused without sending any notification as
# it didn't really run in the first place).
py_db.threads_suspended_single_notification.add_on_resumed_callback(on_resumed)
self.api.request_resume_thread(thread_id)
if py_db.multi_threads_single_notification:

# Only send resumed notification when it has actually resumed!
# (otherwise the user could send a continue, receive the notification and then
# request a new pause which would be paused without sending any notification as
# it didn't really run in the first place).
py_db.threads_suspended_single_notification.add_on_resumed_callback(on_resumed)
self.api.request_resume_thread(thread_id)
else:
# Only send resumed notification when it has actually resumed!
# (otherwise the user could send a continue, receive the notification and then
# request a new pause which would be paused without sending any notification as
# it didn't really run in the first place).
self.api.request_resume_thread(thread_id)
on_resumed()

def on_next_request(self, py_db, request):
'''
Expand Down Expand Up @@ -735,7 +744,7 @@ def on_setfunctionbreakpoints_request(self, py_db, request):

arguments = request.arguments # : :type arguments: SetFunctionBreakpointsArguments
function_breakpoints = []
suspend_policy = 'ALL'
suspend_policy = 'ALL' if py_db.multi_threads_single_notification else 'NONE'

# Not currently covered by the DAP.
is_logpoint = False
Expand Down Expand Up @@ -775,7 +784,7 @@ def on_setbreakpoints_request(self, py_db, request):
self.api.remove_all_breakpoints(py_db, filename)

btype = 'python-line'
suspend_policy = 'ALL'
suspend_policy = 'ALL' if py_db.multi_threads_single_notification else 'NONE'

if not filename.lower().endswith('.py'): # Note: check based on original file, not mapping.
if self._options.django_debug:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ def __init__(self, suspended_frames_manager, py_db):
self._untracked = False

# We need to be thread-safe!
self._lock = ForkSafeLock()
self._lock = ForkSafeLock(rlock=True)

self._variable_reference_to_variable = {}

Expand Down Expand Up @@ -433,13 +433,13 @@ def find_frame(self, thread_id, frame_id):
with self._lock:
return self._frame_id_to_frame.get(frame_id)

def create_thread_suspend_command(self, thread_id, stop_reason, message, trace_suspend_type):
def create_thread_suspend_command(self, thread_id, stop_reason, message, trace_suspend_type, thread, additional_info):
with self._lock:
# First one is topmost frame suspended.
frames_list = self._thread_id_to_frames_list[thread_id]

cmd = self.py_db.cmd_factory.make_thread_suspend_message(
self.py_db, thread_id, frames_list, stop_reason, message, trace_suspend_type)
self.py_db, thread_id, frames_list, stop_reason, message, trace_suspend_type, thread, additional_info)

frames_list = None
return cmd
Expand Down
12 changes: 7 additions & 5 deletions plugins/org.python.pydev.core/pysrc/pydevd.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,11 @@ def send_suspend_notification(self, thread_id, thread, stop_reason):
@contextmanager
def notify_thread_suspended(self, thread_id, thread, stop_reason):
if self.multi_threads_single_notification:
pydev_log.info('Thread suspend mode: single notification')
with AbstractSingleNotificationBehavior.notify_thread_suspended(self, thread_id, thread, stop_reason):
yield
else:
pydev_log.info('Thread suspend mode: NOT single notification')
yield


Expand Down Expand Up @@ -2096,7 +2098,7 @@ def do_wait_suspend(self, thread, frame, event, arg, exception_type=None): # @U

with self.suspended_frames_manager.track_frames(self) as frames_tracker:
frames_tracker.track(thread_id, frames_list)
cmd = frames_tracker.create_thread_suspend_command(thread_id, stop_reason, message, trace_suspend_type)
cmd = frames_tracker.create_thread_suspend_command(thread_id, stop_reason, message, trace_suspend_type, thread, thread.additional_info)
self.writer.add_command(cmd)

with CustomFramesContainer.custom_frames_lock: # @UndefinedVariable
Expand All @@ -2111,7 +2113,7 @@ def do_wait_suspend(self, thread, frame, event, arg, exception_type=None): # @U
frame_custom_thread_id, custom_frame.name))

self.writer.add_command(
frames_tracker.create_thread_suspend_command(frame_custom_thread_id, CMD_THREAD_SUSPEND, "", trace_suspend_type))
frames_tracker.create_thread_suspend_command(frame_custom_thread_id, CMD_THREAD_SUSPEND, "", trace_suspend_type, thread, thread.additional_info))

from_this_thread.append(frame_custom_thread_id)

Expand Down Expand Up @@ -2228,7 +2230,7 @@ def _do_wait_suspend(self, thread, frame, event, arg, trace_suspend_type, from_t
if stop:
# Uninstall the current frames tracker before running it.
frames_tracker.untrack_all()
cmd = self.cmd_factory.make_thread_run_message(get_current_thread_id(thread), info.pydev_step_cmd)
cmd = self.cmd_factory.make_thread_run_message(self, get_current_thread_id(thread), info.pydev_step_cmd)
self.writer.add_command(cmd)
info.pydev_state = STATE_SUSPEND
thread.stop_reason = CMD_SET_NEXT_STATEMENT
Expand Down Expand Up @@ -2287,7 +2289,7 @@ def _do_wait_suspend(self, thread, frame, event, arg, trace_suspend_type, from_t
del f

del frame
cmd = self.cmd_factory.make_thread_run_message(get_current_thread_id(thread), info.pydev_step_cmd)
cmd = self.cmd_factory.make_thread_run_message(self, get_current_thread_id(thread), info.pydev_step_cmd)
self.writer.add_command(cmd)

with CustomFramesContainer.custom_frames_lock:
Expand Down Expand Up @@ -2862,7 +2864,7 @@ def settrace(
port=5678,
suspend=True,
trace_only_current_thread=False,
overwrite_prev_trace=False,
overwrite_prev_trace=False, # Deprecated
patch_multiprocessing=False,
stop_at_frame=None,
block_until_connected=True,
Expand Down

0 comments on commit f5f506c

Please sign in to comment.