Skip to content

Commit 091e4ae

Browse files
committed
Detect virtualenv by probing for venv, .venv, env and .env
Extends the automatic python path detection by probing for some common virtualenv locations. Tries all - cwd/lcwd and lsp clients' root_dir as possible project roots and uses the first that exists.
1 parent e0be843 commit 091e4ae

1 file changed

Lines changed: 46 additions & 6 deletions

File tree

lua/dap-python.lua

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
local api = vim.api
44
local M = {}
5+
local uv = vim.uv or vim.loop
56

67
--- Test runner to use by default.
78
--- The default value is dynamic and depends on `pytest.ini` or `manage.py` markers.
@@ -22,9 +23,9 @@ M.resolve_python = nil
2223

2324

2425
local function default_runner()
25-
if vim.loop.fs_stat('pytest.ini') then
26+
if uv.fs_stat('pytest.ini') then
2627
return 'pytest'
27-
elseif vim.loop.fs_stat('manage.py') then
28+
elseif uv.fs_stat('manage.py') then
2829
return 'django'
2930
else
3031
return 'unittest'
@@ -47,13 +48,41 @@ local is_windows = function()
4748
end
4849

4950

51+
---@param venv string
52+
---@return string
53+
local function python_exe(venv)
54+
if is_windows() then
55+
return venv .. '\\Scripts\\python.exe'
56+
end
57+
return venv .. '/bin/python'
58+
end
59+
60+
61+
local function roots()
62+
return coroutine.wrap(function()
63+
local cwd = vim.fn.getcwd()
64+
coroutine.yield(cwd)
65+
66+
local wincwd = vim.fn.getcwd(0)
67+
if wincwd ~= cwd then
68+
coroutine.yield(wincwd)
69+
end
70+
71+
---@diagnostic disable-next-line: deprecated
72+
local get_clients = vim.lsp.get_clients or vim.lsp.get_active_clients
73+
for _, client in ipairs(get_clients()) do
74+
if client.config.root_dir then
75+
coroutine.yield(client.config.root_dir)
76+
end
77+
end
78+
end)
79+
end
80+
81+
5082
local get_python_path = function()
5183
local venv_path = os.getenv('VIRTUAL_ENV')
5284
if venv_path then
53-
if is_windows() then
54-
return venv_path .. '\\Scripts\\python.exe'
55-
end
56-
return venv_path .. '/bin/python'
85+
return python_exe(venv_path)
5786
end
5887

5988
venv_path = os.getenv("CONDA_PREFIX")
@@ -68,6 +97,17 @@ local get_python_path = function()
6897
assert(type(M.resolve_python) == "function", "resolve_python must be a function")
6998
return M.resolve_python()
7099
end
100+
101+
for root in roots() do
102+
for _, folder in ipairs({"venv", ".venv", "env", ".env"}) do
103+
local path = root .. "/" .. folder
104+
local stat = uv.fs_stat(path)
105+
if stat then
106+
return python_exe(path)
107+
end
108+
end
109+
end
110+
71111
return nil
72112
end
73113

0 commit comments

Comments
 (0)