Skip to content
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

Breakpoints not respected when invoked using debugpy #250

Open
ReggieMarr opened this issue Apr 6, 2023 · 1 comment
Open

Breakpoints not respected when invoked using debugpy #250

ReggieMarr opened this issue Apr 6, 2023 · 1 comment

Comments

@ReggieMarr
Copy link

Environment data

~ [ python3.9 -m debugpy --version                                                                                                                 ] 10:11 AM
Unable to load extension: pydevd_plugins.extensions.types.pydevd_plugin_pandas_types
1.5.1
~ [ python3.9 --version                                                                                                                            ] 10:11 AM
Python 3.9.12
~ [ uname -a                                                                                                                                       ] 10:12 AM
Linux fedora 6.2.8-100.fc36.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Mar 22 19:14:19 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
~ [ emacs --version                                                                                                                                ] 10:12 AM
emacsclient 28.2

Using dap-mode with the following template:

(dap-register-debug-template
  "Python :: Run file (buffer)"
  (list :type "python"
        :args ""
        :cwd nil
        :module nil
        :program nil
        :request "launch"
        :name "Python :: Run file (buffer)"))

My python test script is defined as such (with breakpoint at line 10).

#!/usr/bin/env python3
from datetime import datetime

if __name__ == "__main__":
    now = datetime.now()
    now_str = now.strftime("%d-%m-%Y_%H-%M-%S")
    print("Starting test script")

    for i in range(10):
        print(f"Printing {i} {now_str}")

    print("Completed Start script")

Actual behavior

Debugger does not stop at the desired breakpoint, instead runs application until completion with the following error/output:

Unable to load extension: pydevd_plugins.extensions.types.pydevd_plugin_pandas_types
Starting test script
Traceback (most recent call last):
  File "/home/reggiemarr/anaconda3/lib/python3.9/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py", line 267, in _on_run
    self.process_net_command_json(self.py_db, json_contents)
  File "/home/reggiemarr/anaconda3/lib/python3.9/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py", line 193, in process_net_command_json
    cmd = on_request(py_db, request)
  File "/home/reggiemarr/anaconda3/lib/python3.9/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_process_net_command_json.py", line 926, in on_stacktrace_request
    self.api.request_stack(py_db, request.seq, thread_id, fmt=fmt, start_frame=start_frame, levels=levels)
  File "/home/reggiemarr/anaconda3/lib/python3.9/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_api.py", line 202, in request_stack
    if internal_get_thread_stack.can_be_executed_by(get_current_thread_id(threading.current_thread())):
  File "/home/reggiemarr/anaconda3/lib/python3.9/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py", line 672, in can_be_executed_by
    self._cmd = py_db.cmd_factory.make_get_thread_stack_message(
  File "/home/reggiemarr/anaconda3/lib/python3.9/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_net_command_factory_json.py", line 275, in make_get_thread_stack_message
    end = min(start + levels, total_frames)
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
Printing 0 06-04-2023_09-59-42
Printing 1 06-04-2023_09-59-42
Printing 2 06-04-2023_09-59-42
Printing 3 06-04-2023_09-59-42
Printing 4 06-04-2023_09-59-42
Printing 5 06-04-2023_09-59-42
Printing 6 06-04-2023_09-59-42
Printing 7 06-04-2023_09-59-42
Printing 8 06-04-2023_09-59-42
Printing 9 06-04-2023_09-59-42
Completed Start script

Expected behavior

Run without error/stop at breakpoints (for example this stops at each iteration and was run until 3 occurred:

Unable to load extension: pydevd_plugins.extensions.types.pydevd_plugin_pandas_types
Starting test script
Printing 0 06-04-2023_09-56-37
Printing 1 06-04-2023_09-56-37
Printing 2 06-04-2023_09-56-37
Printing 3 06-04-2023_09-56-37

Steps to reproduce:

Create breakpoint at line 10, run debugger using dap mode/similar application.

Solution:

I managed to figure out what the problem is. For some reason when running the test program the start_frame is None. I found I was able to fix this with the following change to pydevd::pydevd_net_command_factory_json.py

    @overrides(NetCommandFactory.make_get_thread_stack_message)
    def make_get_thread_stack_message(self, py_db, seq, thread_id, topmost_frame, fmt, must_be_suspended=False, start_frame=0, levels=0):
        frames = []
        module_events = []

        try:
            # : :type suspended_frames_manager: SuspendedFramesManager
            suspended_frames_manager = py_db.suspended_frames_manager
            frames_list = suspended_frames_manager.get_frames_list(thread_id)
            if frames_list is None:
                # Could not find stack of suspended frame...
                if must_be_suspended:
                    return None
                else:
                    frames_list = pydevd_frame_utils.create_frames_list_from_frame(topmost_frame)

            for frame_id, frame, method_name, original_filename, filename_in_utf8, lineno, applied_mapping, show_as_current_frame in self._iter_visible_frames_info(
                    py_db, frames_list
                ):

                try:
                    module_name = str(frame.f_globals.get('__name__', ''))
                except:
                    module_name = '<unknown>'

                module_events.extend(self.modules_manager.track_module(filename_in_utf8, module_name, frame))

                presentation_hint = None
                if not getattr(frame, 'IS_PLUGIN_FRAME', False):  # Never filter out plugin frames!
                    if py_db.is_files_filter_enabled and py_db.apply_files_filter(frame, original_filename, False):
                        continue

                    if not py_db.in_project_scope(frame):
                        presentation_hint = 'subtle'

                formatted_name = self._format_frame_name(fmt, method_name, module_name, lineno, filename_in_utf8)
                if show_as_current_frame:
                    formatted_name += ' (Current frame)'
                source_reference = pydevd_file_utils.get_client_filename_source_reference(filename_in_utf8)

                if not source_reference and not applied_mapping and not os.path.exists(original_filename):
                    if getattr(frame.f_code, 'co_lnotab', None):
                        # Create a source-reference to be used where we provide the source by decompiling the code.
                        # Note: When the time comes to retrieve the source reference in this case, we'll
                        # check the linecache first (see: get_decompiled_source_from_frame_id).
                        source_reference = pydevd_file_utils.create_source_reference_for_frame_id(frame_id, original_filename)
                    else:
                        # Check if someone added a source reference to the linecache (Python attrs does this).
                        if linecache.getline(original_filename, 1):
                            source_reference = pydevd_file_utils.create_source_reference_for_linecache(
                                original_filename)

                frames.append(pydevd_schema.StackFrame(
                    frame_id, formatted_name, lineno, column=1, source={
                        'path': filename_in_utf8,
                        'sourceReference': source_reference,
                    },
                    presentationHint=presentation_hint).to_dict())
        finally:
            topmost_frame = None

        for module_event in module_events:
            py_db.writer.add_command(module_event)

        total_frames = len(frames)
        stack_frames = frames
        if bool(levels):
            start = start_frame
            # This is my fix
            if start is None:
                start = 0
            print("start:", start, "total_frames:", total_frames, " + levels:", levels)
            end = min(start + levels, total_frames)
            stack_frames = frames[start:end]

        response = pydevd_schema.StackTraceResponse(
            request_seq=seq,
            success=True,
            command='stackTrace',
            body=pydevd_schema.StackTraceResponseBody(stackFrames=stack_frames, totalFrames=total_frames))
        return NetCommand(CMD_RETURN, 0, response, is_json=True)
@ReggieMarr
Copy link
Author

Note I've also made an issue in the debugpy repo here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant