Giter Site home page Giter Site logo

mfussenegger / nvim-dap-python Goto Github PK

View Code? Open in Web Editor NEW
456.0 6.0 43.0 41 KB

An extension for nvim-dap, providing default configurations for python and methods to debug individual test methods or classes.

License: GNU General Public License v3.0

Lua 98.28% Python 0.69% Vim Script 0.40% Shell 0.62%
neovim nvim-dap neovim-plugin debugging debugger debug-adapter-protocol

nvim-dap-python's Introduction

nvim-dap-python

An extension for nvim-dap providing default configurations for python and methods to debug individual test methods or classes.

Installation

  • Requires Neovim >= 0.5
  • Requires nvim-dap
  • Requires debugpy
  • Install like any other neovim plugin:
    • If using vim-plug: Plug 'mfussenegger/nvim-dap-python'
    • If using packer.nvim: use 'mfussenegger/nvim-dap-python'

If you want to use the test runner functionality, it additionally requires a tree sitter parser for Python.

Debugpy

It is recommended to install debugpy into a dedicated virtualenv. To do so:

mkdir .virtualenvs
cd .virtualenvs
python -m venv debugpy
debugpy/bin/python -m pip install debugpy

The debugger will automatically pick-up another virtual environment if it is activated before neovim is started.

Tree-sitter

Install either:

  • Via :TSInstall python of nvim-treesitter
  • Compile the parser from tree-sitter-python and copy it into .config/nvim/parser/:
    • git clone https://github.com/tree-sitter/tree-sitter-python.git
    • cd tree-sitter-python
    • cc -O2 -o ~/.config/nvim/parser/python}.so -I./src src/parser.c src/scanner.cc -shared -Os -lstdc++ -fPIC

Usage

  1. Call setup in your init.vim to register the adapter and configurations:
lua require('dap-python').setup('~/.virtualenvs/debugpy/bin/python')

The argument to setup is the path to the python installation which contains the debugpy module.

  1. Use nvim-dap as usual.
  • Call :lua require('dap').continue() to start debugging.
  • See :help dap-mappings and :help dap-api.
  • Use :lua require('dap-python').test_method() to debug the closest method above the cursor.

Supported test frameworks are unittest, pytest and django. By default it tries to detect the runner by probing for pytest.ini and manage.py, if neither are present it defaults to unittest.

To configure a different runner, change the test_runner variable. For example to configure pytest set the test runner like this in vimL:

lua require('dap-python').test_runner = 'pytest'

You can also add custom runners. An example in Lua:

local test_runners = require('dap-python').test_runners

-- `test_runners` is a table. The keys are the runner names like `unittest` or `pytest`.
-- The value is a function that takes three arguments:
-- The classname, a methodname and the opts
-- (The `opts` are coming passed through from either `test_method` or `test_class`)
-- The function must return a module name and the arguments passed to the module as list.
test_runners.your_runner = function(classname, methodname, opts)
  local args = {classname, methodname}
  return 'modulename', args
end

Documentation

See :help dap-python

Mappings

nnoremap <silent> <leader>dn :lua require('dap-python').test_method()<CR>
nnoremap <silent> <leader>df :lua require('dap-python').test_class()<CR>
vnoremap <silent> <leader>ds <ESC>:lua require('dap-python').debug_selection()<CR>

Custom configuration

If you call the require('dap-python').setup method it will create a few nvim-dap configuration entries. These configurations are general purpose configurations suitable for many use cases, but you may need to customize the configurations - for example if you want to use Docker containers.

To add your own entries, you can extend the dap.configurations.python list after calling the setup function:

lua << EOF
require('dap-python').setup('/path/to/python')
table.insert(require('dap').configurations.python, {
  type = 'python',
  request = 'launch',
  name = 'My custom launch configuration',
  program = '${file}',
  -- ... more options, see https://github.com/microsoft/debugpy/wiki/Debug-configuration-settings
})
EOF

An alternative is to use project specific .vscode/launch.json files, see :help dap-launch.json.

The Debugpy Wiki contains a list of all supported configuration options.

Python dependencies and virtualenv

nvim-dap-python by default tries to detect a virtual environment and uses it when debugging your application. It looks for:

  • The environment variables VIRTUAL_ENV and CONDA_PREFIX
  • The folders venv, .venv, env, .env relative to either the current working directory or the root_dir of a active language server client. See :h lsp.txt for more information about the latter.

If you're using another way to manage virtual environments, you can set a custom resolve_python function:

require('dap-python').resolve_python = function()
  return '/absolute/path/to/python'
end

Or explicitly set the pythonPath property within your debugpy/nvim-dap configurations. See :h dap-configuration and Launch/Attach Settings

Alternatives

A test runner building upon vim-test with nvim-dap support. Aims to work for all python runners.

nvim-dap-python's People

Contributors

andmis avatar bahugo avatar bartste avatar hudsonmc16 avatar joshbode avatar languitar avatar lkhphuc avatar meijieru avatar mfussenegger avatar moosbruggerj avatar nonsleepr avatar rcarriga avatar rhinoxi avatar thehamsta avatar wuestengecko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

nvim-dap-python's Issues

Extending python launch config not working as expected

Hey,

First of all: Thank you very much for the great package. I really enjoy debugging with this.

However, the manual configuration of my launch config (as mentioned here) does not work for me.

I set it like this:

require('dap-python').setup('python')
require('dap-python').test_runner = 'pytest'

table.insert(require('dap').configurations.python, {
  justMyCode = false
})

But the debugger still mentions that frames have been skipped from debugging during step-in and that this may be due to the "justMyCode" option still being the default (true).
With trying to print that value, I specifically get nil. The documentations says, that I can extend the config. Does that mean, I need to provide a whole config or can I just extend this with single arguments like intended above?
Do you have any idea on why this argument is not loaded?

Thanks a lot!

unittest ValueError: Empty module name

Hi,
I'm using unittest and have a project with following structure:

.
├── proj
│   ├── __init__.py
│   ├── some_func.py
└── tests
    ├── __init__.py
    ├── test_some_func.py

When I open test_some_func.py and run :lua require('dap-python').test_method(), it works fine.
But If I open some other file first, then switch to test_some_func.py file, and run :lua require('dap-python').test_method(), it said ValueError: Empty module name.

So I looked into the code.

local path = vim.fn.expand('%:r:gs?/?.?')

the code above returns tests.test_some_func if I open test_some_func.py directly.
but returns .Path.To.Project.tests.test_some_func if I switch to test_some_func.py from other file.

So I googled a bit, and found changing the code to the following works fine for me

local path = vim.fn.expand('%:p:~:.:r:gs?/?.?')

Since I'm not so familiar with the vim/nvim plugin thing, can you guys confirm this or if I'm doing anything wrong?

Thanks.

Execute test in a class in pytest

When running a test mehod which is inside a test class in pytest, the test is not found by the executor.
Here is an example:

class TestFoo:
    def test_one(self):
        a = 1
        assert a == 1

When launching debugging on this method, I get the following output:

ERROR: not found: test.py::test_one_eq_one
(no name 'test.py::test_one_eq_one' in any of [<Module test.py>])

Locally I could solve this by uncommenting the line 166 of dap-python.lua and adding a condition:

      if classname then
        fqn = table.concat({path, classname, closest_function}, '::')
      else
        fqn = table.concat({path, closest_function}, '::')
      end

It works for my use case, however it is not perfect. Here is a failing example:

class TestFoo:
    def test_one(self):
        assert 1 == 1

def test_two():
    assert 2 == 2

When running on test_two, here is the error:

Error: not found: test_class.py::TestFoo::test_two

setting option justMyCode

Hello, I am probably looking for the obvious but
my google skills do not seem to bring an answer to my problem:
I would like to set justMyCode=false in order to debug external packages.

My init.lua contains the following:

require('dap-python').setup('/usr/bin/python3')
local dap, dapui =require("dap"),require("dapui")
 require('dap').set_exception_breakpoints({"raised", "uncaught"})
table.insert(require('dap').configurations.python, {
type = 'python',
request = 'launch',
 program = '${file}',
 -- ... more options, see https://github.com/microsoft/debugpy/wiki/Debug-configuration-settings
 justMyCode = false
 })

I tried putting some breakpoints in the __init__.py of numpy but I get the message:
Frame skipped from debugging during step-in. Note: may have been skipped because of "justMyCode" option (default == true). Try setting "justMyCode": false in the debug configuration (e.g., launch.json).

Does this option nead the launch.json ? I think everything should be configurable from lua....

Debugging a python module

Hey I'm new to using nvim-dap-python and am wondering how I should go about debugging a module in python that I typically launch via the python -m module_name command. Basically how to debug code run via the init file while retaining the path of the superseding directory.

Thanks :)

Test runner "unittest" not working on windows.

The regex depicted in yellow does not parse the backward slashed used by windows into periods:

IMG_20230302_161248.jpg

As a result, no tests can be executed using dap. A workaround is to replace the line by:

local path = vim.fn.expand('%:.:r:gs?\\(/\\|\\\\\\)?.?')

continue() restarts execution

Everything else works (halting at breakpoints, inspecting variables) but continue() starts execution again instead of continuing. I'm using the default config from the README.

Bug: test_method issues wrong test path for tests with >1 level of nesting

Hi!

Here's my keybinding:

vim.api.nvim_set_keymap('n', '<leader>ds', ':lua require("dap-python").test_method()<CR>', { noremap = true, silent = true })

Top-level test

If I run it on a test like this, it works fine:

def test_a():
  assert True

Issues path::test_a correctly

Nested (n=1) test

class TestB:
  def test_b(self):
    assert True

Issues path::TestB::test_b correctly

Nested (n>1) test

class TestC:
  class TestC1:
    def test_c(self):
      assert True

Issues path::TestC::test_c incorrectly: notice the missing ::TestC1

Expected vs actual

- path::TestC::TestC1::test_c
+ path::TestC::test_c

Error reads:

ERROR: not found: path::TestC::test_c
(no name 'path::TestC::test_c' in any of [<Module path>])

Pytest tests do not break on error

Hi,

When debugging pytest tests and the test contains an error than the debugger does not stop there but the test just results in a fail and exits. I think it would be much better to let the debugger stop and the point of failure such that it can be debugged correctly.

A possible solution is mentioned here: https://stackoverflow.com/questions/62419998/how-can-i-get-pytest-to-not-catch-exceptions/62563106#62563106

There I think you basically tell pytest to not raise exceptions such that the debugger can handle them.
For this you need to add the following to your conftest.py:

import os
import pytest

if os.getenv('_PYTEST_RAISE', "0") != "0":

    @pytest.hookimpl(tryfirst=True)
    def pytest_exception_interact(call):
        raise call.excinfo.value

    @pytest.hookimpl(tryfirst=True)
    def pytest_internalerror(excinfo):
        raise excinfo.value

And then also add the env dict in the test configuration in dap-python.lua

load_dap().run({                                                                                                                                                                       
name = table.concat(prune_nil({classname, methodname}), '.'),                                                                                                                        
type = 'python',                                                                                                                                                                     
request = 'launch',                                                                                                                                                                  
module = test_runner,                                                                                                                                                                
args = args,                                                                                                                                                                         
console = opts.console,                                                                                                                                                              
env = {                                                                                                                                                                              
       ["_PYTEST_RAISE"] = "1",                                                                                                                                                         
     },                                                                                                                                                                                   
})    

This seems to be not the best solutions but are there alternatives?

closing dap-terminal and relaunching file does not spawn dap-terminal

I have encountered an issue where closing the dap-terminal (buffer where all program output is written) does not relaunch it afterward. The program is running, and breakpoints are working, but the output buffer is not visible.

Config

require('dap-python').setup('~/.virtualenvs/debugpy/bin/python')

Nothing else only some remaps.

Steps to reproduce

  1. Launch any python program
  2. Enter debugging mode with lua require'dap'.continue()
  3. Finish executing program
  4. Close dap-terminal with :q
  5. Enter debugging mode again with lua require'dap'.continue()

If I leave the dap-terminal open debugging session outputs everything correctly the second time this seems to be caused by the suspended buffer.

Not sure if this is related to nvim-dap-python or nvim-dap itself.

Can't cleanly exit debugging

nvim-dap-python is great but -- while I'm sure this is user ignorance rather than a real issue -- I'm unable to stop debugging and continue to edit my source file. The debugger window closes, but then in my source file any simple normal mode command (e.g., 'j' to move the cursor down) executes but then goes into insert mode.

Thrashing around as we newbies do, I tried a keymap to function() require('dap').disconnect() end but using it doesn't seem to matter.

Docker Remote Attach -> Breakpoints not working

Hi,
I am trying to attach to a running docker session. I manage to attach to the docker container using DapContinue but it tells me:

Breakpoint in file that does not exist

my dap.lua looks like this

require('dap-python').setup('/usr/local/share/miniconda3/bin/python')
table.insert(require('dap').configurations.python, {
  type = 'python',
  request = 'attach',
  name = 'Remote Python: Attach',
  port = 5678,
  host = "127.0.0.1",
  mode = "remote",
  cwd = vim.fn.getcwd(),
  pathMappings = {
    {
      localRoot = function()
        return vim.fn.input("Local code folder > ", vim.fn.getcwd(), "file")
      
      end,
      remoteRoot = function()
        return vim.fn.input("Container code folder > ", "/", "file")
      end,
    },
  },
})

I think it is something to with the pathes within the docker container and my local directory but I just cannot get it to work :-(
the file I am trying to access is in /server in my local dir while it is in /backend in the docker. This is the logile for a attempt:

[ DEBUG ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:1115 ]	"Connecting to debug adapter"	{
  enrich_config = <function 1>,
  host = "127.0.0.1",
  options = {
    source_filetype = "python"
  },
  port = 5678,
  type = "server"
}
[ DEBUG ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:1450 ]	"request"	{
  arguments = {
    adapterID = "nvim-dap",
    clientId = "neovim",
    clientname = "neovim",
    columnsStartAt1 = true,
    linesStartAt1 = true,
    locale = "en_US.UTF-8",
    pathFormat = "path",
    supportsRunInTerminalRequest = true,
    supportsVariableType = true
  },
  command = "initialize",
  seq = 0,
  type = "request"
}
[ DEBUG ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:915 ]	{
  body = {
    category = "telemetry",
    data = {
      packageVersion = "1.6.4"
    },
    output = "ptvsd"
  },
  event = "output",
  seq = 1,
  type = "event"
}
[ INFO ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:710 ]	"Telemetry"	"ptvsd"
[ DEBUG ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:915 ]	{
  body = {
    category = "telemetry",
    data = {
      packageVersion = "1.6.4"
    },
    output = "debugpy"
  },
  event = "output",
  seq = 2,
  type = "event"
}
[ INFO ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:710 ]	"Telemetry"	"debugpy"
[ DEBUG ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:915 ]	{
  body = {
    exceptionBreakpointFilters = { {
        default = false,
        description = "Break whenever any exception is raised.",
        filter = "raised",
        label = "Raised Exceptions"
      }, {
        default = true,
        description = "Break when the process is exiting due to unhandled exception.",
        filter = "uncaught",
        label = "Uncaught Exceptions"
      }, {
        default = false,
        description = "Break when exception escapes into library code.",
        filter = "userUnhandled",
        label = "User Uncaught Exceptions"
      } },
    supportsClipboardContext = true,
    supportsCompletionsRequest = true,
    supportsConditionalBreakpoints = true,
    supportsConfigurationDoneRequest = true,
    supportsDebuggerProperties = true,
    supportsDelayedStackTraceLoading = true,
    supportsEvaluateForHovers = true,
    supportsExceptionInfoRequest = true,
    supportsExceptionOptions = true,
    supportsFunctionBreakpoints = true,
    supportsGotoTargetsRequest = true,
    supportsHitConditionalBreakpoints = true,
    supportsLogPoints = true,
    supportsModulesRequest = true,
    supportsSetExpression = true,
    supportsSetVariable = true,
    supportsStepInTargetsRequest = true,
    supportsTerminateRequest = true,
    supportsValueFormattingOptions = true
  },
  command = "initialize",
  request_seq = 0,
  seq = 3,
  success = true,
  type = "response"
}
[ DEBUG ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:1450 ]	"request"	{
  arguments = {
    cwd = "/home/laudanum/projects/toniebox-audio-match",
    host = "127.0.0.1",
    mode = "remote",
    name = "Remote Python: Attach",
    pathMappings = { {
        localRoot = "/home/laudanum/projects/toniebox-audio-match/server",
        remoteRoot = "/backend"
      } },
    port = 5678,
    pythonPath = "/home/laudanum/.conda/envs/tonie/bin/python",
    request = "attach",
    subProcess = false,
    type = "python"
  },
  command = "attach",
  seq = 1,
  type = "request"
}
[ DEBUG ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:915 ]	{
  body = {
    host = "127.0.0.1",
    port = 58227
  },
  event = "debugpyWaitingForServer",
  seq = 4,
  type = "event"
}
[ WARN ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:965 ]	"No event handler for "	{
  body = {
    host = "127.0.0.1",
    port = 58227
  },
  event = "debugpyWaitingForServer",
  seq = 4,
  type = "event"
}
[ DEBUG ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:915 ]	{
  event = "initialized",
  seq = 5,
  type = "event"
}
[ DEBUG ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:1450 ]	"request"	{
  arguments = {
    breakpoints = { {
        line = 27
      }, {
        line = 29
      }, {
        line = 35
      } },
    lines = { 27, 29, 35 },
    source = {
      name = "app.py",
      path = "/home/laudanum/projects/toniebox-audio-match/server/app.py"
    },
    sourceModified = false
  },
  command = "setBreakpoints",
  seq = 2,
  type = "request"
}
[ DEBUG ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:915 ]	{
  body = {
    breakpoints = { {
        id = 10,
        line = 27,
        message = "Breakpoint in file that does not exist.",
        source = {
          name = "app.py",
          path = "/home/laudanum/projects/toniebox-audio-match/server/app.py"
        },
        verified = false
      }, {
        id = 11,
        line = 29,
        message = "Breakpoint in file that does not exist.",
        source = {
          name = "app.py",
          path = "/home/laudanum/projects/toniebox-audio-match/server/app.py"
        },
        verified = false
      }, {
        id = 12,
        line = 35,
        message = "Breakpoint in file that does not exist.",
        source = {
          name = "app.py",
          path = "/home/laudanum/projects/toniebox-audio-match/server/app.py"
        },
        verified = false
      } }
  },
  command = "setBreakpoints",
  request_seq = 2,
  seq = 6,
  success = true,
  type = "response"
}
[ INFO ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:851 ]	"Server rejected breakpoint"	{
  id = 10,
  line = 27,
  message = "Breakpoint in file that does not exist.",
  source = {
    name = "app.py",
    path = "/home/laudanum/projects/toniebox-audio-match/server/app.py"
  },
  verified = false
}
[ INFO ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:851 ]	"Server rejected breakpoint"	{
  id = 11,
  line = 29,
  message = "Breakpoint in file that does not exist.",
  source = {
    name = "app.py",
    path = "/home/laudanum/projects/toniebox-audio-match/server/app.py"
  },
  verified = false
}
[ INFO ] 2022-12-11T23:18:04Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:851 ]	"Server rejected breakpoint"	{
  id = 12,
  line = 35,
  message = "Breakpoint in file that does not exist.",
  source = {
    name = "app.py",
    path = "/home/laudanum/projects/toniebox-audio-match/server/app.py"
  },
  verified = false
}
[ DEBUG ] 2022-12-11T23:18:07Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:1450 ]	"request"	{
  arguments = {
    filters = { "uncaught" }
  },
  command = "setExceptionBreakpoints",
  seq = 3,
  type = "request"
}
[ DEBUG ] 2022-12-11T23:18:07Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:915 ]	{
  command = "setExceptionBreakpoints",
  request_seq = 3,
  seq = 7,
  success = true,
  type = "response"
}
[ DEBUG ] 2022-12-11T23:18:07Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:1450 ]	"request"	{
  command = "configurationDone",
  seq = 4,
  type = "request"
}
[ DEBUG ] 2022-12-11T23:18:07Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:915 ]	{
  command = "configurationDone",
  request_seq = 4,
  seq = 8,
  success = true,
  type = "response"
}
[ DEBUG ] 2022-12-11T23:18:07Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:915 ]	{
  command = "attach",
  request_seq = 1,
  seq = 9,
  success = true,
  type = "response"
}
[ DEBUG ] 2022-12-11T23:18:07Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:915 ]	{
  body = {
    isLocalProcess = true,
    name = "/backend/app.py",
    startMethod = "attach",
    systemProcessId = 264
  },
  event = "process",
  seq = 10,
  type = "event"
}
[ DEBUG ] 2022-12-11T23:18:07Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:915 ]	{
  body = {
    reason = "started",
    threadId = 1
  },
  event = "thread",
  seq = 11,
  type = "event"
}
[ DEBUG ] 2022-12-11T23:18:07Z+0100 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:915 ]	{
  body = {
    reason = "started",
    threadId = 2
  },
  event = "thread",
  seq = 12,
  type = "event"
}

Breakpoints not working (with pytest-cov)

I set a breakpoint in my test file and it seems to pop up in the DAP logs:

[ DEBUG ] 2022-12-11T12:13:01Z-0800 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:1450 ]    "request"   {
  arguments = {
    breakpoints = { {
        line = 8
      } },
    lines = { 8 },
    source = {
      name = "waiter_test.py",
      path = "/home/jeanluc/Code/waiter_test.py"
    },
    sourceModified = false
  },
  command = "setBreakpoints",
  seq = 3,
  type = "request"
}
[ DEBUG ] 2022-12-11T12:13:01Z-0800 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:915 ] {
  body = {
    breakpoints = { {
        id = 0,
        line = 8,
        source = {
          name = "waiter_test.py",
          path = "/home/jeanluc/Code/waiter_test.py"
        },
        verified = true
      } }
  },
  command = "setBreakpoints",
  request_seq = 3,
  seq = 6,
  success = true,
  type = "response"
}

But when I launch via the test_method() function, the program runs but never breaks.

I looked at #17 and tried to change my python version. At first I was using /usr/bin/python (Python 3.10.8) since my global install had debugpy. Then I created custom virtual env with Python 3.9.2 but the problem persists.

My setup for the plugin:

    use {
        'mfussenegger/nvim-dap-python',
        requires = {'mfussenegger/nvim-dap'},
        config = function()
            require'dap-python'.setup('~/.virtualenv/debug/bin/python')
            require'dap-python'.test_runner = 'pytest'
        end
    }

How to set current working directory ?

In my python file I am opening a file , the file path contains my_tool/input.yaml

/workspaces
|__ my_tool
|__ tool.py
|__ input.yaml

I opened the file in neovim and execute the tool.py

f __name__ == "__main__":
    filepath = "my_tool/input.yml"
    with open(filepath, "r") as f:
        input_data = yaml.load(f, Loader=yaml.SafeLoader)

it fails as
Thread stopped due to exception of type FileNotFoundError

But if i change the filepath to 'input.yml' then it works. Seems like current working directory is set to file path.
Can I modify the cwd? How to do it? Is there an option available for it?

Cannot set console to nil

default_test_opts and default_setup_opts both set console to integratedTerminal. When calling setup or test_method and passing in {console = nil} as options, integratedTerminal is still used. This is because vim.tbl_extend seems to overwrite the passed in option only if it is not nil.

Run django and celery.

Hello guys. Is there a way to launch two processes at once? In this case Django server and the celery application. I've seen it been done in vscode but could not configure my nvim to work that way.

jupyter integration

I have a question about the python debugger. I want to setup my working environment in VIM. To code in jupyter I am using vim-slime to connect to an ipython session and use ipdb to debug. However it is not the best debugging experience and I would love to be able to use dap (it has a beautiful integration with AstronVIM).

Is this possible right now? Or is it easy to implement?

This is the only thing keeping me using VS Code, since it manages jupyter debugging pretty well.

Regards!

Error message has no line breaks

Hello,
just set up your plugin and it was pretty easy. Now I have the problem that within a simple test program, where I just have an IndexError, the according error message goes right out of screen. Hence for example the stack trace is not readable.

Is there a configuration I can change for that? Is there a desired behavior for that?

It would be pretty nice to be able to read the error "inlined" in the code. Otherwise I just start the program normally and check the error message, which does not feel right.

Duplicate entries after reloading configuration

After reloading my Neovim configuration file (:so $MYVIMRC), the debugger entries begin to duplicate - another whole set of entries after each reload.

(apologies for the weird lines, scrot is acting up)

  • no reloads: 4 options (default)
    no reloads: 4 options
  • after reload: 8 options (each option appears twice)
    after reload: 8 options (each option appears twice)
  • after one more reload: 12 options
    after one more reload: 12 options

Remote Attach pathMappings support

Hello, I was trying to configure nvim-dap-python tonight to work with my docker project and came across some issues setting it up. After playing around it appears that the only setting that needs modified is dap's pathMapping option. Looking at the file this could be added here:

https://github.com/mfussenegger/nvim-dap-python/blob/master/lua/dap-python.lua#L93

just by making a simple copy of the host function.

If that's something that the Repo would be interested in adding, we'd be happy to fork and add a PR for this!

Can't work with gpu(cuda)

I meet the error No stopped threads. Cannot move in the line input.cuda() (3rd line)

 with torch.no_grad():
     for batch_idx, (input, _) in enumerate(loader):
         input  = input.cuda()
         guess = model(input)
         #topk = guess.topk(k)[1]
         prob.append( guess.cpu().numpy() )

         # measure elapsed time
         batch_time.update( time.time() - end )
         end = time.time()

But before that, the following line works well:

model = model.cuda()

How to add a few paths to PYTHONPATH when use test_method?

Case: I need to run my tests from source folder (they must be in PYTHONPATH), but add another workdirectory folder (cwd).
Is it right desicion below?

local envs = {}
envs['PYTHONPATH'] = '${PYTHONPATH}:/home/user/repos/some/tests'

local pythonConfig = {
    python = '/opt/python3.7/bin/python3.7',
    env = envs,
    cwd = '/tmp/tests/mega_project/tests/stateless/run',
}

local run_test = function()
    require('dap-python').test_method({
        config = pythonConfig
    })
end

vim.keymap.set('n', '<F3>', run_test)

Resolve python not taken into account

I've had an issue with resolve python using conda on windows.

The default setting is not working for me because python is not located in Scripts folder (it's located at the root of my env folder).

I've tried to use resolve_python argument but it wasn't taken into account in because it was overriden by venv_path

Here is what i think would work for both conda and virtual env :

l
local get_python_path_for_virtual_env= function (venv_path)
    if is_windows() then
        return venv_path .. '\\Scripts\\python.exe'
    end
    return venv_path .. '/bin/python'
end

local get_python_path_for_conda_env= function (venv_path)
    if is_windows() then
        return venv_path .. '\\python.exe'
    end
    return venv_path .. '/bin/python'
end

local get_python_path = function()

    if M.resolve_python then
        assert(type(M.resolve_python) == "function", "resolve_python must be a function")
        return M.resolve_python()
    end

    local venv_path = os.getenv('VIRTUAL_ENV')
    if venv_path then
        return get_python_path_for_virtual_env(venv_path)
    end

    venv_path = os.getenv('CONDA_PREFIX')
    if venv_path then
        return get_python_path_for_conda_env(venv_path)
    end

    return nil
end

Doesn't pick up conda environemt

Hi!

I am trying to use this with miniconda, however it doesn't pick up the environment.

This is the setup that I have:

require('dap-python').setup('/home/xxx/miniconda3/bin/python')
require("dapui").setup()
require("nvim-dap-virtual-text").setup()

vim.fn.sign_define('DapStopped', {
    text='▶', texthl='WarningMsg',linehl='DapUIBreakpointsCurrentLine', numhl='ModeMsg'})

vim.fn.sign_define('DapBreakpoint', {
    text='●', texthl='ErrorMsg', linehl='', numhl=''})

vim.fn.sign_define('DapBreakpointCondition', {
    text='⊕', texthl='ErrorMsg', linehl='', numhl=''})

vim.fn.sign_define('DapLogPoint', {
    text='!!', texthl='ErrorMsg', linehl='', numhl=''})

vim.fn.sign_define('DapBreakpointRejected', {
    text='⨷', texthl='ErrorMsg', linehl='', numhl=''})

I have debugpy installed in this environment. So, I create a file example.py, add two lines:

import numpy as np
print("example")  # <-- add breakpoint here

It doesn't work (as was expected), as the base environment doesn't have numpy installed.

Then I go to a project /home/xxx/Projects/project-1. This project has a conda environment project-1. I activate the environemnt.

I run the debugger and I get the same error -- numpy not found.

If I change the line in the config require('dap-python').setup('/home/xxx/miniconda3/bin/python') to require('dap-python').setup('/home/xxx/miniconda3/envs/project-1/bin/python') and install debugpy in this environment, then of course debugging does work - it finds the numpy installation.

However, my question is - shouldn't the debugger pick up the new environment by default? Why do I need to change the python interpreter path in the config?

Many thanks and please forgive my noob question

Are we supposed to install debugpy in the virtual environment?

I have a question regarding how to setup this properly. I am assuming I don't understand the author's intention, so I am asking here how it is supposed to be setup.

The doc says this

It is recommended to install debugpy into a dedicated virtualenv. To do so:

mkdir .virtualenvs
cd .virtualenvs
python -m venv debugpy
debugpy/bin/python -m pip install debugpy

The debugger will automatically pick-up another virtual environment if it is activated before neovim is started.

Later it states that

Call setup in your init.vim to register the adapter and configurations:

lua require('dap-python').setup('~/.virtualenvs/debugpy/bin/python')

If I set it up this way it is behaving quite strangely. I am assuming this last line will always run debugpy from the special "debugpy"-virtual environment using the python executable therein. This works, if no virtualenv is activated.

However, if a virtual environment in the shell is activated, it will try to run the debugpy library from the path ~/.virtualenvs/debugpy/site-packages/... with the python executable from the currently activated virtual env (which might be a completely incompatible version).

So if it detects the virtual env from the VIRTUAL_ENV variable, I would assume another viable route is to install debugpy into my virtual env. But it wont let me setup dap-python without providing the path in .setup().

So how is it supposed to work with virtual environments?

[Q] How to use this with Django?

I managed to make it work with a simple python file but I was wondering if it would be possible to use this with Django?

And if it is, what would be a sample configuration?

Thanks!

Execute test runners remotely in docker containers

I would like test_method() to execute the test runner in running a docker container and attach the debugger. I think that is a common workflow and it would be nice to have build in support for this.

A possible implementation would be to execute a docker command such as

CONTAINER_ID=$(docker ps --filter "name=$CONTAINER_NAME" --quiet)
docker exec $CONTAINER_ID $PYTHON_PATH -m debugpy --listen 0.0.0.0:$PORT --wait-for-client -m pytest -s $TEST_COMMAND

and then attach normally via DAP remote adapter. There are some other complications such as mapping workspace paths between host and container.

Breakpoints does not work

Steps:

  • set some breakepoint lua require'dap'.toggle_breakpoint()
  • start debugging lua require'dap'.continue()

Observed behaviors:
Breaking points are ignored the program goes to the end without interrupting

My dap configuration:

local dap_python = require('dap-python')
dap_python.setup('/home/gohm/.pyenv/versions/debugpy/bin/python')

local dap = require 'dap'

dap.adapters.c = {
    type = 'executable',
    attach = {pidProperty = "pid", pidSelect = "ask"},
    command = 'lldb-vscode', -- my binary was called 'lldb-vscode-11'
    env = {LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY = "YES"},
    name = "lldb"
}

dap.configurations.c = {
    {
        name = "moje",
        type = 'c',
        request = 'launch',
        program = 'main',
        --[[ args = {
     '--headless',
     '-c', 'echo getcompletion("vim.api.nvim_buf_", "lua")',
     '-c', 'qa!'
   }, ]]
        cwd = nil,
        environment = nil,
        externalConsole = false,
        MIMode = 'lldb'
    }
}

-- show virtual text for current frame (recommended)
-- vim.g.dap_virtual_text = true
-- request variable values for all frames (experimental)
vim.g.dap_virtual_text = 'all frames'

require('telescope').load_extension('dap')
require("dapui").setup()

C adapter working fine. And also I did try minimal configuration only with python but the effect is still the same.

Attach using config.connect.host/port?

I am trying to use a launch.json that has an attach config where the host/port are specified as subfields of a connect object in the configuration.

        {
            "name": "Attach to blah blah blah",
            "type": "python",
            "request": "attach",
            "connect": {
                "host": "localhost",
                "port": 5678
            }
            // other fields elided
        }

AIUI this config is generated by vscode-python which seems to use this schema since microsoft/vscode-python#12446.

The following patch makes this config work.

--- lua/dap-python.lua
+++ lua/dap-python.lua
@@ -57,8 +57,8 @@ function M.setup(adapter_python_path, opts)
     if config.request == 'attach' then
       cb({
         type = 'server';
-        port = config.port or 0;
-        host = config.host or '127.0.0.1';
+        port = (config.connect or config).port or 0;
+        host = (config.connect or config).host or '127.0.0.1';
         enrich_config = enrich_config;
       })
     else

Default configuration for remote attach with path mappings

My workflow usually involves docker containers, which its file structure doesn't match the one on the host machine. This forces me to add a custom configuration to define a path mapping between the host machine and the container in order to attach the debugger.

Currently this is my version of said configuration:

table.insert(require("dap").configurations.python, {
  type = 'python';
  request = 'attach';
  name = 'Attach remote (with path mapping)';
  connect = function()
    local host = vim.fn.input('Host [127.0.0.1]: ')
    host = host ~= '' and host or '127.0.0.1'
    local port = tonumber(vim.fn.input('Port [5678]: ')) or 5678
    return { host = host, port = port }
  end;
  pathMappings = function()
    local cwd = '${workspaceFolder}'
    local local_path = vim.fn.input('Local path mapping [' .. cwd .. ']: ')
    local_path = local_path ~= '' and local_path or cwd
    local remote_path = vim.fn.input('Remote path mapping [.]: ')
    remote_path = remote_path ~= '' and remote_path or '.'
    return {{ localRoot = local_path, remoteRoot = remote_path }, }
  end
})

Which defaults to mapping the current working directories of the host and container.

I think a similar config could be added or replace the current 'Attach remote' config with this one (maybe defaulting to an empty pathMapping).

I have very little experience with lua, but I could open a PR and do the necessary changes with some help.

Thanks for your awesome plugins, btw!

Docker + pytest example

I looked through the issues but could not find a recent enough example of setting dap up with pytest running in a Docker container. If someone has an example of how to set this up, it would be greatly appreciated!

Debug Interactive command doesn't work

The command like $continue doesn't work.

Here is my dap config for python

  local dbg_path = require("dap-install.config.settings").options["installation_path"] .. "python/bin/python"
  require("dap-python").setup(dbg_path)

[python] FastAPI debugging like vscode does

I tried to debug my FastAPI project but any configuration I tried never give me good result.
Does anyone successfully debug FastAPI with nvim-dap?

this is my nvim dap configuration:

dap.adapters.python = {
    type = 'executable';
    command = 'python';
    args = { '-m', 'debugpy.adapter' };
}

dap.configurations.python = {
    {
        name = 'FastAPI debugger',
        type = 'python',
        request = 'launch',
        module = 'uvicorn',
        args = {
            "index:app",
            "--reload",
            "--reload-dir=api",
            "--reload-dir=app",
            "--reload-dir=common",
            "--reload-dir=dependency",
            "--reload-dir=models",
            "--reload-dir=schemas",
            "--use-colors"
        },
        console = "integratedTerminal"
    },
    {
        name = 'Python attach',
        type = 'python',
        request = 'attach',
        connect = {
            host = '127.0.0.1',
            port = 5678,
        }
    }
}

and this what i got from dap.log


[ DEBUG ] 2021-06-21T23:24:43Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:728 ]	"request"	{
  arguments = {
    adapterID = "nvim-dap",
    clientId = "neovim",
    clientname = "neovim",
    columnsStartAt1 = true,
    linesStartAt1 = true,
    locale = "en_US.UTF-8",
    pathFormat = "path",
    supportsRunInTerminalRequest = true,
    supportsVariableType = true
  },
  command = "initialize",
  seq = 0,
  type = "request"
}
[ DEBUG ] 2021-06-21T23:24:43Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:496 ]	{
  body = {
    category = "telemetry",
    data = {
      packageVersion = "1.3.0"
    },
    output = "ptvsd"
  },
  event = "output",
  seq = 1,
  type = "event"
}
[ DEBUG ] 2021-06-21T23:24:43Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:496 ]	{
  body = {
    category = "telemetry",
    data = {
      packageVersion = "1.3.0"
    },
    output = "debugpy"
  },
  event = "output",
  seq = 2,
  type = "event"
}
[ DEBUG ] 2021-06-21T23:24:43Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:496 ]	{
  body = {
    exceptionBreakpointFilters = { {
        default = false,
        filter = "raised",
        label = "Raised Exceptions"
      }, {
        default = true,
        filter = "uncaught",
        label = "Uncaught Exceptions"
      } },
    supportsClipboardContext = true,
    supportsCompletionsRequest = true,
    supportsConditionalBreakpoints = true,
    supportsConfigurationDoneRequest = true,
    supportsDebuggerProperties = true,
    supportsDelayedStackTraceLoading = true,
    supportsEvaluateForHovers = true,
    supportsExceptionInfoRequest = true,
    supportsExceptionOptions = true,
    supportsGotoTargetsRequest = true,
    supportsHitConditionalBreakpoints = true,
    supportsLogPoints = true,
    supportsModulesRequest = true,
    supportsSetExpression = true,
    supportsSetVariable = true,
    supportsStepInTargetsRequest = true,
    supportsTerminateDebuggee = true,
    supportsValueFormattingOptions = true
  },
  command = "initialize",
  request_seq = 0,
  seq = 3,
  success = true,
  type = "response"
}
[ DEBUG ] 2021-06-21T23:24:43Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:728 ]	"request"	{
  arguments = {
    args = { "index:app", "--reload", "--reload-dir=api", "--reload-dir=app", "--reload-dir=common", "--reload-dir=dependency", "--reload-dir=models", "--reload-dir=schemas", "--use-colors" },
    console = "integratedTerminal",
    module = "uvicorn",
    name = "FastAPI debugger",
    request = "launch",
    type = "python"
  },
  command = "launch",
  seq = 1,
  type = "request"
}
[ DEBUG ] 2021-06-21T23:24:43Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:496 ]	{
  arguments = {
    args = { "/home/kasf/.virtualenvs/fastapi-sqlalchemy/bin/python", "/home/kasf/.virtualenvs/fastapi-sqlalchemy/lib/python3.9/site-packages/debugpy/launcher", "43675", "--", "-m", "uvicorn", "index:app", "--reload", "--reload-dir=api", "--reload-dir=app", "--reload-dir=common", "--reload-dir=dependency", "--reload-dir=models", "--reload-dir=schemas", "--use-colors" },
    env = {},
    kind = "integrated",
    title = "Python Debug Console"
  },
  command = "runInTerminal",
  seq = 4,
  type = "request"
}
[ DEBUG ] 2021-06-21T23:24:43Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:48 ]	"run_in_terminal"	{
  args = { "/home/kasf/.virtualenvs/fastapi-sqlalchemy/bin/python", "/home/kasf/.virtualenvs/fastapi-sqlalchemy/lib/python3.9/site-packages/debugpy/launcher", "43675", "--", "-m", "uvicorn", "index:app", "--reload", "--reload-dir=api", "--reload-dir=app", "--reload-dir=common", "--reload-dir=dependency", "--reload-dir=models", "--reload-dir=schemas", "--use-colors" },
  env = {},
  kind = "integrated",
  title = "Python Debug Console"
}
[ DEBUG ] 2021-06-21T23:24:43Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:748 ]	"response"	{
  body = {
    processId = 4143
  },
  command = "runInTerminal",
  request_seq = 4,
  seq = 2,
  success = true,
  type = "response"
}
[ DEBUG ] 2021-06-21T23:24:44Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:496 ]	{
  event = "initialized",
  seq = 5,
  type = "event"
}
[ DEBUG ] 2021-06-21T23:24:44Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:728 ]	"request"	{
  arguments = {
    breakpoints = { {
        line = 191
      } },
    lines = { 191 },
    source = {
      name = "authbearer.py",
      path = "/home/kasf/Pypr/fastapi-sqlalchemy/dependency/authbearer.py"
    }
  },
  command = "setBreakpoints",
  seq = 3,
  type = "request"
}
[ DEBUG ] 2021-06-21T23:24:44Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:496 ]	{
  body = {
    breakpoints = { {
        id = 0,
        line = 191,
        source = {
          name = "authbearer.py",
          path = "/home/kasf/Pypr/fastapi-sqlalchemy/dependency/authbearer.py"
        },
        verified = true
      } }
  },
  command = "setBreakpoints",
  request_seq = 3,
  seq = 6,
  success = true,
  type = "response"
}
[ DEBUG ] 2021-06-21T23:24:44Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:728 ]	"request"	{
  arguments = {
    filters = { "uncaught" }
  },
  command = "setExceptionBreakpoints",
  seq = 4,
  type = "request"
}
[ DEBUG ] 2021-06-21T23:24:44Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:496 ]	{
  command = "setExceptionBreakpoints",
  request_seq = 4,
  seq = 7,
  success = true,
  type = "response"
}
[ DEBUG ] 2021-06-21T23:24:44Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:728 ]	"request"	{
  command = "configurationDone",
  seq = 5,
  type = "request"
}
[ DEBUG ] 2021-06-21T23:24:44Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:496 ]	{
  command = "configurationDone",
  request_seq = 5,
  seq = 8,
  success = true,
  type = "response"
}
[ DEBUG ] 2021-06-21T23:24:44Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:496 ]	{
  command = "launch",
  request_seq = 1,
  seq = 9,
  success = true,
  type = "response"
}
[ DEBUG ] 2021-06-21T23:24:44Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:496 ]	{
  body = {
    isLocalProcess = true,
    name = "uvicorn",
    pointerSize = 64,
    startMethod = "launch",
    systemProcessId = 4151
  },
  event = "process",
  seq = 10,
  type = "event"
}
[ DEBUG ] 2021-06-21T23:24:44Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:496 ]	{
  body = {
    reason = "started",
    threadId = 1
  },
  event = "thread",
  seq = 11,
  type = "event"
}
[ DEBUG ] 2021-06-21T23:24:45Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:496 ]	{
  body = {
    connect = {
      host = "127.0.0.1",
      port = 46289
    },
    console = "integratedTerminal",
    module = "uvicorn",
    name = "Subprocess 4168",
    python = { "/home/kasf/.virtualenvs/fastapi-sqlalchemy/bin/python" },
    request = "attach",
    subProcessId = 4168,
    type = "python"
  },
  event = "debugpyAttach",
  seq = 12,
  type = "event"
}
[ WARN ] 2021-06-21T23:24:45Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:546 ]	"No event handler for "	{
  body = {
    connect = {
      host = "127.0.0.1",
      port = 46289
    },
    console = "integratedTerminal",
    module = "uvicorn",
    name = "Subprocess 4168",
    python = { "/home/kasf/.virtualenvs/fastapi-sqlalchemy/bin/python" },
    request = "attach",
    subProcessId = 4168,
    type = "python"
  },
  event = "debugpyAttach",
  seq = 12,
  type = "event"
}
[ DEBUG ] 2021-06-21T23:24:45Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:496 ]	{
  body = {
    connect = {
      host = "127.0.0.1",
      port = 46289
    },
    console = "integratedTerminal",
    module = "uvicorn",
    name = "Subprocess 4167",
    python = { "/home/kasf/.virtualenvs/fastapi-sqlalchemy/bin/python" },
    request = "attach",
    subProcessId = 4167,
    type = "python"
  },
  event = "debugpyAttach",
  seq = 13,
  type = "event"
}
[ WARN ] 2021-06-21T23:24:45Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:546 ]	"No event handler for "	{
  body = {
    connect = {
      host = "127.0.0.1",
      port = 46289
    },
    console = "integratedTerminal",
    module = "uvicorn",
    name = "Subprocess 4167",
    python = { "/home/kasf/.virtualenvs/fastapi-sqlalchemy/bin/python" },
    request = "attach",
    subProcessId = 4167,
    type = "python"
  },
  event = "debugpyAttach",
  seq = 13,
  type = "event"
}
[ DEBUG ] 2021-06-21T23:25:11Z+0700 ] ...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:496 ]	{
  event = "terminated",
  seq = 14,
  type = "event"
}

Highlight and sign ignored

When setting up the style of my breakpoints for nvim-dap like so:

vim.highlight.create("DapBreakpoint", { ctermbg = 0, guifg = "", guibg = "#4B1515" }, false)
vim.fn.sign_define(
	"DapBreakpoint",
	{ text = "", texthl = "DiagnosticSignError", linehl = "DapBreakpoint", numhl = "DapBreakpoint" }
)

My breakpoints are styled nicely. However, as soon as I activate nvim-dap-python, this style is ignored, and the initial style is applied (B sign and no line highlight). Any way to overcome this? I use the latest version of the plugin with Packer.

debugpy: Timed out waiting for debuggee to spawn

I'm trying to setup Neovim with nvim-dap, nvim-dap-python and debugpy. Since I have debugpy in my distribution packages I installed it not via a virtual environment but directly in the system. For Neovim, I use lazy as package manager.

For nvim-dap-python, I use this config:

require('dap-python').setup("/usr/bin/python")

My /usr/bin/python resolves to Python 3.11.

When starting a debugging session, it seems to work, but timeouts after a short time and both Neovim as well as debugpy seem to report that they didn't get a connection.

Here are the steps that I have done followed by the log.

Executed steps:

  1. Open a file test.py.
  2. Add this content:
#!/usr/bin/env python

print("hello")
  1. Save it.
  2. Set a breakpoint at the print line. -> a B appears at the left side.
  3. Execute: `:lua require('dap').set_log_level('TRACE')
  4. Start the debugger with F5 (require('dap').continue())
  5. Choose Launch file

A message appears:

Debug adapter didn't respond. Either the adapter is slow (then wait and ignore this) or there is a problem with your adapter or `python` configuration. Check the logs for errors (:help dap.set_log_level)

The log file


[ DEBUG ] 2023-04-05T01:41:51Z+0200 ] ...rion/.local/share/nvim/lazy/nvim-dap/lua/dap/session.lua:1239 ]	"Spawning debug adapter"	{
  args = { "-m", "debugpy.adapter" },
  command = "/usr/bin/python",
  enrich_config = <function 1>,
  options = {
    source_filetype = "python"
  },
  type = "executable"
}
[ DEBUG ] 2023-04-05T01:41:51Z+0200 ] ...rion/.local/share/nvim/lazy/nvim-dap/lua/dap/session.lua:1544 ]	"request"	{
  arguments = {
    adapterID = "nvim-dap",
    clientId = "neovim",
    clientname = "neovim",
    columnsStartAt1 = true,
    linesStartAt1 = true,
    locale = "de_DE.UTF-8",
    pathFormat = "path",
    supportsProgressReporting = true,
    supportsRunInTerminalRequest = true,
    supportsStartDebuggingRequest = true,
    supportsVariableType = true
  },
  command = "initialize",
  seq = 0,
  type = "request"
}
[ DEBUG ] 2023-04-05T01:41:51Z+0200 ] ...rion/.local/share/nvim/lazy/nvim-dap/lua/dap/session.lua:917 ]	1	{
  body = {
    category = "telemetry",
    data = {
      packageVersion = "1.6.6"
    },
    output = "ptvsd"
  },
  event = "output",
  seq = 1,
  type = "event"
}
[ DEBUG ] 2023-04-05T01:41:51Z+0200 ] ...rion/.local/share/nvim/lazy/nvim-dap/lua/dap/session.lua:917 ]	1	{
  body = {
    category = "telemetry",
    data = {
      packageVersion = "1.6.6"
    },
    output = "debugpy"
  },
  event = "output",
  seq = 2,
  type = "event"
}
[ INFO ] 2023-04-05T01:41:51Z+0200 ] ...rion/.local/share/nvim/lazy/nvim-dap/lua/dap/session.lua:711 ]	"Telemetry"	"ptvsd"
[ DEBUG ] 2023-04-05T01:41:51Z+0200 ] ...rion/.local/share/nvim/lazy/nvim-dap/lua/dap/session.lua:917 ]	1	{
  body = {
    exceptionBreakpointFilters = { {
        default = false,
        description = "Break whenever any exception is raised.",
        filter = "raised",
        label = "Raised Exceptions"
      }, {
        default = true,
        description = "Break when the process is exiting due to unhandled exception.",
        filter = "uncaught",
        label = "Uncaught Exceptions"
      }, {
        default = false,
        description = "Break when exception escapes into library code.",
        filter = "userUnhandled",
        label = "User Uncaught Exceptions"
      } },
    supportsClipboardContext = true,
    supportsCompletionsRequest = true,
    supportsConditionalBreakpoints = true,
    supportsConfigurationDoneRequest = true,
    supportsDebuggerProperties = true,
    supportsDelayedStackTraceLoading = true,
    supportsEvaluateForHovers = true,
    supportsExceptionInfoRequest = true,
    supportsExceptionOptions = true,
    supportsFunctionBreakpoints = true,
    supportsGotoTargetsRequest = true,
    supportsHitConditionalBreakpoints = true,
    supportsLogPoints = true,
    supportsModulesRequest = true,
    supportsSetExpression = true,
    supportsSetVariable = true,
    supportsStepInTargetsRequest = true,
    supportsTerminateRequest = true,
    supportsValueFormattingOptions = true
  },
  command = "initialize",
  request_seq = 0,
  seq = 3,
  success = true,
  type = "response"
}
[ INFO ] 2023-04-05T01:41:51Z+0200 ] ...rion/.local/share/nvim/lazy/nvim-dap/lua/dap/session.lua:711 ]	"Telemetry"	"debugpy"
[ DEBUG ] 2023-04-05T01:41:51Z+0200 ] ...rion/.local/share/nvim/lazy/nvim-dap/lua/dap/session.lua:1544 ]	"request"	{
  arguments = {
    console = "integratedTerminal",
    name = "Launch file",
    program = "/home/gerion/test/test.py",
    request = "launch",
    type = "python"
  },
  command = "launch",
  seq = 1,
  type = "request"
}
[ DEBUG ] 2023-04-05T01:41:51Z+0200 ] ...rion/.local/share/nvim/lazy/nvim-dap/lua/dap/session.lua:917 ]	1	{
  arguments = {
    args = { "/usr/lib/python-exec/python3.11/python", "/usr/lib/python3.11/site-packages/debugpy/launcher", "55627", "--", "/home/gerion/test/test.py" },
    cwd = "/home/gerion/test",
    env = vim.empty_dict(),
    kind = "integrated",
    title = "Python Debug Console"
  },
  command = "runInTerminal",
  seq = 4,
  type = "request"
}
[ DEBUG ] 2023-04-05T01:41:51Z+0200 ] ...rion/.local/share/nvim/lazy/nvim-dap/lua/dap/session.lua:203 ]	"run_in_terminal"	{
  args = { "/usr/lib/python-exec/python3.11/python", "/usr/lib/python3.11/site-packages/debugpy/launcher", "55627", "--", "/home/gerion/test/test.py" },
  cwd = "/home/gerion/test",
  env = vim.empty_dict(),
  kind = "integrated",
  title = "Python Debug Console"
}
[ DEBUG ] 2023-04-05T01:41:51Z+0200 ] ...rion/.local/share/nvim/lazy/nvim-dap/lua/dap/session.lua:1574 ]	"response"	{
  body = {
    processId = 239043
  },
  command = "runInTerminal",
  request_seq = 4,
  seq = 2,
  success = true,
  type = "response"
}
[ DEBUG ] 2023-04-05T01:42:32Z+0200 ] ...rion/.local/share/nvim/lazy/nvim-dap/lua/dap/session.lua:917 ]	1	{
  command = "launch",
  message = "Timed out waiting for debuggee to spawn",
  request_seq = 1,
  seq = 5,
  success = false,
  type = "response"
}
[ DEBUG ] 2023-04-05T01:42:32Z+0200 ] ...rion/.local/share/nvim/lazy/nvim-dap/lua/dap/session.lua:917 ]	1	{
  body = {
    exitCode = 1
  },
  event = "exited",
  seq = 6,
  type = "event"
}
[ DEBUG ] 2023-04-05T01:42:32Z+0200 ] ...rion/.local/share/nvim/lazy/nvim-dap/lua/dap/session.lua:917 ]	1	{
  event = "terminated",
  seq = 7,
  type = "event"
}

Especially the line Timed out waiting for debuggee to spawn seems to come from the debugpy, so it seems that they fail to communicate. Do you have an idea, why this happens? Or can you point out, how to debug the debugger? :)

Additional information

When I call the above command manually, this happens:

$ /usr/lib/python-exec/python3.11/python "/usr/lib/python3.11/site-packages/debugpy/launcher" 55627 -- /home/gerion/test/test.py
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/usr/lib/python3.11/site-packages/debugpy/launcher/__main__.py", line 91, in <module>
    main()
  File "/usr/lib/python3.11/site-packages/debugpy/launcher/__main__.py", line 47, in main
    launcher.connect(host, port)
  File "/usr/lib/python3.11/site-packages/debugpy/launcher/../../debugpy/launcher/__init__.py", line 27, in connect
    sock.connect((host, port))
ConnectionRefusedError: [Errno 111] Verbindungsaufbau abgelehnt

Probably Neovim/nvim-dap does not create the necessary socket for communication here, so that it fails. But the example shows that debugpy is installed and Python can call it.

Error when running a simple code

I just run

a, b = 1, 2

input()

and I have error in dapui console

0.51s - Error inserting pydevd breaks.
Traceback (most recent call last):
  File "/home/misha/.virtualenvs/debugpy/lib/python3.10/site-packages/debugpy/_vendored/pydevd/_py
devd_frame_eval/pydevd_modify_bytecode.py", line 328, in insert_pydevd_breaks
    for new_instruction in get_instructions_to_add(
  File "/home/misha/.virtualenvs/debugpy/lib/python3.10/site-packages/debugpy/_vendored/pydevd/_py
devd_frame_eval/pydevd_modify_bytecode.py", line 102, in get_instructions_to_add
    Instr("LOAD_CONST", _pydev_stop_at_break, lineno=stop_at_line - 1),
  File "/home/misha/.virtualenvs/debugpy/lib/python3.10/site-packages/debugpy/_vendored/pydevd/_py
devd_frame_eval/vendored/bytecode/instr.py", line 171, in __init__
    self._set(name, arg, lineno)
  File "/home/misha/.virtualenvs/debugpy/lib/python3.10/site-packages/debugpy/_vendored/pydevd/_py
devd_frame_eval/vendored/bytecode/instr.py", line 239, in _set
    _check_lineno(lineno)
  File "/home/misha/.virtualenvs/debugpy/lib/python3.10/site-packages/debugpy/_vendored/pydevd/_py
devd_frame_eval/vendored/bytecode/instr.py", line 74, in _check_lineno
    raise ValueError("invalid lineno")
ValueError: invalid lineno

Invalid/missing attach config behavior

While investigating #38 I found dap was failing to connect to the target on port 0 by default.

socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 35                                                              
connect(35, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress) 
getsockopt(35, SOL_SOCKET, SO_ERROR, [ECONNREFUSED], [4]) = 0                                                                         

This seems to come from the python adapter.

cb({
type = 'server';
port = config.port or 0;
host = config.host or '127.0.0.1';
enrich_config = enrich_config;
})

Maybe a default of 5678 would be better? I'd be happy to just get an error that the config is missing some required fields though.

How could I set up a configuration to debug a package?

I'm developing a Python package and would like to be able to run debugpy with this package, and debug it from within nvim, but I don't know how to do that.

I've got the package installed in a virtual environment (in editable mode) and can run it with python -m package_name. In PyCharm, I can set breakpoints in a file, run the package_name module, and debug from the breakpoints.

I don't know how to use debugpy, but I assume this is possible, and would love an example configuration for this behaviour. Thanks :)

Is pyenv supported?

Hi,

I've installed both nvim-dap and nvim-dap-python:

use 'mfussenegger/nvim-dap'
use 'mfussenegger/nvim-dap-python'

debugpy is installed in a separate pyenv - ~/.pyenv/versions/dap/bin/python.

When I open main.py of some Python project while being in a directory where pyenv is recognized/activated (and I can run python main.py and it will all work) and run :lua require'dap'.toggle_breakpoint()<cr> I see the prompt where I choose 1: Launch file, it will fail on importing first library that is not in standard lib (but is installed with pip) - it seems that dap didn't recognized the virtualenv created with pyenv.

Let me know if any other info is needed.

Thanks!

[Feature Request] Tox support

Is there any interest in integrating tox support?

Are there any technical blockers?

I'm considering writing my own custom runner, but if I'm going to do that anyways I might as well submit a PR so others may use it.

Maybe this has already been done this and is interested in submitting their work?

Please let me know your thoughts.

Error: Invalid Channel ID

This isn't a big deal for me as debugging seems to work fine for Python in spite of this error, but I just wanted to mention it in case it was indicative of a larger problem.

After running the DAP, when I exit nvim I see the following printed to the terminal:

...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:259: E900: Invalid channel id
stack traceback:
^I[C]: in function 'nvim_chan_send'
^I...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:259: in function <...nvim/site/pack/packer/start/nvim-dap/lua/dap/session.lua:258>%

My dap-python.lua config looks like:

local status_ok, dap_python = pcall(require, "dap-python")
if not status_ok then
  return
end

dap_python.setup('~/.virtualenvs/debugpy/bin/python')

And my dap.lua config looks like:

local dap_status_ok, dap = pcall(require, "dap")
if not dap_status_ok then
  return
end

local dap_ui_status_ok, dapui = pcall(require, "dapui")
if not dap_ui_status_ok then
  return
end

vim.fn.sign_define("DapBreakpoint", { text = "", texthl = "DiagnosticSignError", linehl = "", numhl = "" })

dapui.setup({
  icons = { expanded = "▾", collapsed = "▸" },
  mappings = {
    -- Use a table to apply multiple mappings
    expand = { "<CR>", "<2-LeftMouse>" },
    open = "o",
    remove = "d",
    edit = "e",
    repl = "r",
    toggle = "t",
  },
  -- Expand lines larger than the window
  -- Requires >= 0.7
  expand_lines = vim.fn.has("nvim-0.7"),
  -- Layouts define sections of the screen to place windows.
  -- The position can be "left", "right", "top" or "bottom".
  -- The size specifies the height/width depending on position. It can be an Int
  -- or a Float. Integer specifies height/width directly (i.e. 20 lines/columns) while
  -- Float value specifies percentage (i.e. 0.3 - 30% of available lines/columns)
  -- Elements are the elements shown in the layout (in order).
  -- Layouts are opened in order so that earlier layouts take priority in window sizing.
  layouts = {
    {
      elements = {
      -- Elements can be strings or table with id and size keys.
        { id = "scopes", size = 0.40 }, -- use 40% for scopes, evenly dividing the rest
        { id = "breakpoints", size = 0.20 },
        { id = "stacks", size = 0.20 },
        { id = "watches", size = 0.20 },
      },
      size = 60, -- 60 columns
      position = "left",
    },
    {
      elements = {
        "repl",
        -- "console",
      },
      size = 0.30, -- 30% of vertical lines
      position = "bottom",
    },
  },
  floating = {
    max_height = nil, -- These can be integers or a float between 0 and 1.
    max_width = nil, -- Floats will be treated as percentage of your screen.
    border = "single", -- Border style. Can be "single", "double" or "rounded"
    mappings = {
      close = { "q", "<Esc>" },
    },
  },
  windows = { indent = 1 },
  render = {
    max_type_length = nil, -- Can be integer or nil.
  }
})

dap.listeners.after.event_initialized["dapui_config"] = function()
  dapui.open()
end

dap.listeners.before.event_terminated["dapui_config"] = function()
  dapui.close()
end

dap.listeners.before.event_exited["dapui_config"] = function()
  dapui.close()
end

Flask application process closes after a few seconds

Hi everyone.

I'm trying to setup the debugger in my Flask application (using Poetry) but when I launch the configuration for some reason the Flask application closes after a few seconds.

Everything is working (besides that). The application is launching properly, but after it finishes bootstrapping the process is closed after a few seconds.

About my env:

  • I have one venv with debugpy and Poetry installed in it
  • This is my dap config:
local setup_ok_dap, dap = pcall(require, "dap")
local setup_ok_dap_python, dap_python = pcall(require, "dap-python")

if not setup_ok_dap_python then
	return
end

dap_python.setup("~/.python-venvs/bin/python")

table.insert(dap.configurations.python, {
	name = "Launch Flask server",
	type = "python",
	request = "launch",
	console = "integratedTerminal",
	cwd = "${workspaceFolder}",
	program = "${env:PYTHON_VENV_PATH}/bin/poetry",
	args = {
		"run",
		"flask",
		"--no-debug",
		"run",
	},
})

Note

python-venvs is where my Python venv is located (both Debugpy and Poetry are installed there)

When I run the application, this is what I get in the intergrated terminal:

 * Serving Flask app 'prprocessor'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit

[Process exited 247]

(the Process exited message takes a few seconds to appear)

Also, I've already tried to remove the --no-debug flag, the result is the same. And, of course, if I run the poetry run flask run outside of the debugger it works as expected (the server is launched and stays live)

nvim-dap-ui is crashing when opening at the start

Hello,

Many thanks for these fantastic DAP plugins. I am still pretty new to it and learning how it all works whilst setting it up for all languages that I am using.

I came across an issue, which may already be resolved elsewhere. I am looking for a good way integrating this plugin with nvim-dap-ui. For other languages I was using this remap to start my debugging session.

nnoremap("<F5>", function()
  dap.continue()
  dapui.open()
end)

When using the defaults of nvim-dap-python and pointing to the environment, I would get the following error:

E5108: Error executing lua: ...ck/packer/start/nvim-dap-ui/lua/dapui/windows/layout.lua:184: Invalid window id: 1007
stack traceback:
        [C]: in function 'nvim_win_set_option'
        ...ck/packer/start/nvim-dap-ui/lua/dapui/windows/layout.lua:184: in function '_init_win_settings'
        ...ck/packer/start/nvim-dap-ui/lua/dapui/windows/layout.lua:37: in function 'open'
        ...im/site/pack/packer/start/nvim-dap-ui/lua/dapui/init.lua:288: in function 'cb'
        ...im/site/pack/packer/start/nvim-dap-ui/lua/dapui/init.lua:214: in function 'keep_cmdheight'
        ...im/site/pack/packer/start/nvim-dap-ui/lua/dapui/init.lua:266: in function 'open'
        /home/rms/.config/nvim/after/plugin/debugger/init.lua:60: in function </home/rms/.config/nvim/after/plugin/debugger/init.lua:58>

This is probably caused by interaction with the menu, which asks whether to launch, launch with argument, attach remote etc. This is a very useful menu and I'd like to retain it, but is there a better way to integrate it with the UI after? If I comment dapui.open() and reopen manually whilst the session is running, it all works as expected.

Please let me know. For now, I am not opening the UI by default and just mapped a new binding for opening/closing it.

run dap with debugger disabled / bypassed?

Hi,
I posted about this on the neovim subreddit but got no responses so I will bother you here with this question. I would like to re-use the dap settings I have setup for python to run the code but without invoking the debugger. This is a common workflow for me in PyCharm, the run config and the debug config can have the same parameters and you use the same interface to invoke them. I think I can figure this out from reading the code but I would be grateful if someone could help me determine whether this is something I can configure without changing any code.

FileNotFoundError - no such file or directory

Hello, I am trying to debug a python application. I am using nvim-dap-python as the configuration for nvim-dap however I am getting this error when I try to start the debugger as shown in the image below.

image

The project is running in a virtual environment.
There should be only one src directory in the path: '/home/deandre/dev/DataVerse/src/src/main.py'
Any help will be appreciated, thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.