Skip to content

Commit

Permalink
fix(pypi): support MSYS2 virtual environments on Windows (#1547)
Browse files Browse the repository at this point in the history
  • Loading branch information
williamboman committed Nov 8, 2023
1 parent eabf6d3 commit 3e2432a
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 18 deletions.
43 changes: 26 additions & 17 deletions lua/mason-core/installer/managers/pypi.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,32 @@ local function create_venv(py_executables)
end, py_executables)):ok_or "Failed to create python3 virtual environment."
end

---@param ctx InstallContext
---@param executable string
local function find_venv_executable(ctx, executable)
local candidates = _.filter(_.identity, {
platform.is.unix and path.concat { VENV_DIR, "bin", executable },
-- MSYS2
platform.is.win and path.concat { VENV_DIR, "bin", ("%s.exe"):format(executable) },
-- Stock Windows
platform.is.win and path.concat { VENV_DIR, "Scripts", ("%s.exe"):format(executable) },
})

for _, candidate in ipairs(candidates) do
if ctx.fs:file_exists(candidate) then
return Result.success(candidate)
end
end
return Result.failure(("Failed to find executable %q in Python virtual environment."):format(executable))
end

---@async
---@param args SpawnArgs
local function venv_python(args)
local ctx = installer.context()
local python_path = path.concat {
ctx.cwd:get(),
VENV_DIR,
platform.is.win and "Scripts" or "bin",
platform.is.win and "python.exe" or "python",
}
return ctx.spawn[python_path](args)
return find_venv_executable(ctx, "python"):and_then(function(python_path)
return ctx.spawn[path.concat { ctx.cwd:get(), python_path }](args)
end)
end

---@async
Expand Down Expand Up @@ -93,16 +108,10 @@ function M.install(pkg, version, opts)
}, opts.install_extra_args)
end

---@param exec string
function M.bin_path(exec)
return Result.pcall(platform.when, {
unix = function()
return path.concat { "venv", "bin", exec }
end,
win = function()
return path.concat { "venv", "Scripts", ("%s.exe"):format(exec) }
end,
})
---@param executable string
function M.bin_path(executable)
local ctx = installer.context()
return find_venv_executable(ctx, executable)
end

return M
13 changes: 13 additions & 0 deletions tests/mason-core/installer/managers/pypi_spec.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local installer = require "mason-core.installer"
local match = require "luassert.match"
local path = require "mason-core.path"
local pypi = require "mason-core.installer.managers.pypi"
local spy = require "luassert.spy"
Expand Down Expand Up @@ -35,6 +36,9 @@ describe("pypi manager", function()
it("should init venv and upgrade pip", function()
local ctx = create_dummy_context()
stub(ctx, "promote_cwd")
stub(ctx.fs, "file_exists")
ctx.fs.file_exists.on_call_with(match.ref(ctx.fs), "venv/bin/python").returns(true)

installer.exec_in_context(ctx, function()
pypi.init { upgrade_pip = true, install_extra_args = { "--proxy", "http://localhost" } }
end)
Expand All @@ -60,6 +64,8 @@ describe("pypi manager", function()

it("should install", function()
local ctx = create_dummy_context()
stub(ctx.fs, "file_exists")
ctx.fs.file_exists.on_call_with(match.ref(ctx.fs), "venv/bin/python").returns(true)
installer.exec_in_context(ctx, function()
pypi.install("pypi-package", "1.0.0")
end)
Expand All @@ -81,6 +87,8 @@ describe("pypi manager", function()

it("should write output", function()
local ctx = create_dummy_context()
stub(ctx.fs, "file_exists")
ctx.fs.file_exists.on_call_with(match.ref(ctx.fs), "venv/bin/python").returns(true)
spy.on(ctx.stdio_sink, "stdout")

installer.exec_in_context(ctx, function()
Expand All @@ -92,6 +100,9 @@ describe("pypi manager", function()

it("should install extra specifier", function()
local ctx = create_dummy_context()
stub(ctx.fs, "file_exists")
ctx.fs.file_exists.on_call_with(match.ref(ctx.fs), "venv/bin/python").returns(true)

installer.exec_in_context(ctx, function()
pypi.install("pypi-package", "1.0.0", {
extra = "lsp",
Expand All @@ -115,6 +126,8 @@ describe("pypi manager", function()

it("should install extra packages", function()
local ctx = create_dummy_context()
stub(ctx.fs, "file_exists")
ctx.fs.file_exists.on_call_with(match.ref(ctx.fs), "venv/bin/python").returns(true)
installer.exec_in_context(ctx, function()
pypi.install("pypi-package", "1.0.0", {
extra_packages = { "extra-package" },
Expand Down
2 changes: 1 addition & 1 deletion tests/mason-core/installer/registry/link_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ describe("registry linker", function()
["npm:executable"] = "node_modules/.bin/executable",
["nuget:executable"] = "executable",
["opam:executable"] = "bin/executable",
["pypi:executable"] = "venv/bin/executable",
-- ["pypi:executable"] = "venv/bin/executable",
}

for bin, path in pairs(matrix) do
Expand Down

0 comments on commit 3e2432a

Please sign in to comment.