Skip to content

Commit

Permalink
refactor: slightly more helpful error messages and early error if inc…
Browse files Browse the repository at this point in the history
…omaptible py version
  • Loading branch information
williamboman committed Jun 1, 2024
1 parent e0d3374 commit b3c760a
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 24 deletions.
27 changes: 18 additions & 9 deletions lua/mason-core/installer/managers/pypi.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ local function pep440_check_version(version, specifiers)
local ok, result = pcall(pep440.check_version, version, specifiers)
if not ok then
log.fmt_warn(
"Failed to check version compatibility for version %s with specifiers %s: %s",
"Failed to check PEP440 version compatibility for version %s with specifiers %s: %s",
version,
specifiers,
result
Expand Down Expand Up @@ -91,12 +91,11 @@ local function create_venv(pkg)
local target = resolve_python3(versioned_candidates) or stock_target

if not target then
ctx.stdio_sink.stderr(
("Unable to find python3 installation. Tried the following candidates: %s.\n"):format(
return Result.failure(
("Unable to find python3 installation in PATH. Tried the following candidates: %s."):format(
_.join(", ", _.concat(stock_candidates, versioned_candidates))
)
)
return Result.failure "Failed to find python3 installation."
end

-- 3. If a versioned python3 installation was not found, warn the user if the stock python3 installation is outside
Expand All @@ -106,12 +105,22 @@ local function create_venv(pkg)
and supported_python_versions ~= nil
and not pep440_check_version(tostring(target.version), supported_python_versions)
then
ctx.stdio_sink.stderr(
("Warning: The resolved Python version %s is not compatible with the required Python versions: %s.\n"):format(
target.version,
supported_python_versions
if ctx.opts.force then
ctx.stdio_sink.stderr(
("Warning: The resolved python3 version %s is not compatible with the required Python versions: %s.\n"):format(
target.version,
supported_python_versions
)
)
)
else
ctx.stdio_sink.stderr "Run with :MasonInstall --force to bypass this version validation.\n"
return Result.failure(
("Failed to find a python3 installation in PATH that meets the required versions (%s). Found version: %s."):format(
supported_python_versions,
target.version
)
)
end
end

log.fmt_debug("Found python3 installation version=%s, executable=%s", target.version, target.executable)
Expand Down
65 changes: 50 additions & 15 deletions tests/mason-core/installer/managers/pypi_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ describe("pypi manager", function()
installer.exec_in_context(ctx, function()
pypi.init {
package = { name = "cmake-language-server", version = "0.1.10" },
upgrade_pip = true,
install_extra_args = { "--proxy", "http://localhost" },
upgrade_pip = false,
install_extra_args = {},
}
end)

Expand All @@ -104,7 +104,7 @@ describe("pypi manager", function()
}
end)

it("should default to stock version if unable to find suitable versioned candidate during init", function()
it("should error if unable to find a suitable python3 version", function()
local ctx = create_dummy_context()
spy.on(ctx.stdio_sink, "stderr")
stub(ctx, "promote_cwd")
Expand All @@ -119,26 +119,61 @@ describe("pypi manager", function()
stub(spawn, "python3", mockx.returns(Result.success()))
spawn.python3.on_call_with({ "--version" }).returns(Result.success { stdout = "Python 3.5.0" })

installer.exec_in_context(ctx, function()
pypi.init {
local result = installer.exec_in_context(ctx, function()
return pypi.init {
package = { name = "cmake-language-server", version = "0.1.10" },
upgrade_pip = true,
install_extra_args = { "--proxy", "http://localhost" },
upgrade_pip = false,
install_extra_args = {},
}
end)

assert.spy(ctx.promote_cwd).was_called(1)
assert.spy(ctx.spawn.python3).was_called(1)
assert.spy(ctx.spawn.python3).was_called_with {
"-m",
"venv",
"venv",
}
assert.same(
Result.failure "Failed to find a python3 installation in PATH that meets the required versions (>=3.8). Found version: 3.5.0.",
result
)
assert
.spy(ctx.stdio_sink.stderr)
.was_called_with "Warning: The resolved Python version 3.5.0 is not compatible with the required Python versions: >=3.8.\n"
.was_called_with "Run with :MasonInstall --force to bypass this version validation.\n"
end)

it(
"should default to stock version if unable to find suitable versioned candidate during init and when force=true",
function()
local ctx = create_dummy_context { force = true }
spy.on(ctx.stdio_sink, "stderr")
stub(ctx, "promote_cwd")
stub(ctx.fs, "file_exists")
stub(providers.pypi, "get_supported_python_versions", mockx.returns(Result.success ">=3.8"))
stub(vim.fn, "executable")
vim.fn.executable.on_call_with("python3.12").returns(0)
vim.fn.executable.on_call_with("python3.11").returns(0)
vim.fn.executable.on_call_with("python3.10").returns(0)
vim.fn.executable.on_call_with("python3.9").returns(0)
vim.fn.executable.on_call_with("python3.8").returns(0)
stub(spawn, "python3", mockx.returns(Result.success()))
spawn.python3.on_call_with({ "--version" }).returns(Result.success { stdout = "Python 3.5.0" })

installer.exec_in_context(ctx, function()
pypi.init {
package = { name = "cmake-language-server", version = "0.1.10" },
upgrade_pip = true,
install_extra_args = { "--proxy", "http://localhost" },
}
end)

assert.spy(ctx.promote_cwd).was_called(1)
assert.spy(ctx.spawn.python3).was_called(1)
assert.spy(ctx.spawn.python3).was_called_with {
"-m",
"venv",
"venv",
}
assert
.spy(ctx.stdio_sink.stderr)
.was_called_with "Warning: The resolved python3 version 3.5.0 is not compatible with the required Python versions: >=3.8.\n"
end
)

it("should install", function()
local ctx = create_dummy_context()
stub(ctx.fs, "file_exists")
Expand Down

0 comments on commit b3c760a

Please sign in to comment.