feat: async build_spec

This commit is contained in:
Rónán Carrigan
2022-02-06 21:18:33 +00:00
parent 1323c5ff09
commit a02e6d5acb
4 changed files with 64 additions and 56 deletions

View File

@@ -1,40 +1,49 @@
local async = require("plenary.async")
local lib = require("neotest.lib") local lib = require("neotest.lib")
local Path = require("plenary.path") local Path = require("plenary.path")
local M = {} local M = {}
function M.is_test_file(file_path) function M.is_test_file(file_path)
if not vim.endswith(file_path, ".py") then if not vim.endswith(file_path, ".py") then
return false return false
end end
local elems = vim.split(file_path, Path.path.sep) local elems = vim.split(file_path, Path.path.sep)
local file_name = elems[#elems] local file_name = elems[#elems]
return vim.startswith(file_name, "test_") return vim.startswith(file_name, "test_")
end
M.module_exists = function(module, python_command)
return lib.process.run(vim.tbl_flatten({
python_command,
"-c",
"import imp; imp.find_module('"..module.."')",
})) == 0
end end
---@return string[] ---@return string[]
function M.get_python_command(root) function M.get_python_command(root)
-- Use activated virtualenv. -- Use activated virtualenv.
if vim.env.VIRTUAL_ENV then if vim.env.VIRTUAL_ENV then
return { Path:new(vim.env.VIRTUAL_ENV, "bin", "python").filename } return { Path:new(vim.env.VIRTUAL_ENV, "bin", "python").filename }
end end
for _, pattern in ipairs({ "*", ".*" }) do for _, pattern in ipairs({ "*", ".*" }) do
local match = vim.fn.glob(Path:new(root or vim.fn.getcwd(), pattern, "pyvenv.cfg").filename) local match = async.fn.glob(Path:new(root or async.fn.getcwd(), pattern, "pyvenv.cfg").filename)
if match ~= "" then if match ~= "" then
return { (Path:new(match):parent() / "bin" / "python").filename } return { (Path:new(match):parent() / "bin" / "python").filename }
end end
end end
if lib.files.exists("Pipfile") then if lib.files.exists("Pipfile") then
return { "pipenv", "run", "python" } return { "pipenv", "run", "python" }
end end
-- Fallback to system Python. -- Fallback to system Python.
return { vim.fn.exepath("python3") or vim.fn.exepath("python") or "python" } return { async.fn.exepath("python3") or async.fn.exepath("python") or "python" }
end end
function M.parse_positions(file_path) function M.parse_positions(file_path)
local query = [[ local query = [[
((function_definition ((function_definition
name: (identifier) @test.name) name: (identifier) @test.name)
(#match? @test.name "^test_")) (#match? @test.name "^test_"))
@@ -44,18 +53,19 @@ function M.parse_positions(file_path)
name: (identifier) @namespace.name) name: (identifier) @namespace.name)
@namespace.definition @namespace.definition
]] ]]
return lib.treesitter.parse_positions(file_path, query) return lib.treesitter.parse_positions(file_path, query)
end end
function M.get_strategy_config(strategy, python_script, args) function M.get_strategy_config(strategy, python, python_script, args)
local config = { local config = {
dap = function() dap = function()
return { return {
type = "python", type = "python",
name = "Neotest Debugger", name = "Neotest Debugger",
request = "launch", request = "launch",
python = python,
program = python_script, program = python_script,
cwd = vim.fn.getcwd(), cwd = async.fn.getcwd(),
args = args, args = args,
justMyCode= false, justMyCode= false,
} }
@@ -67,3 +77,4 @@ function M.get_strategy_config(strategy, python_script, args)
end end
return M return M

View File

@@ -1,4 +1,4 @@
local logger = require("neotest.logging") local async = require("plenary.async")
local Path = require("plenary.path") local Path = require("plenary.path")
local lib = require("neotest.lib") local lib = require("neotest.lib")
local base = require("neotest-python.base") local base = require("neotest-python.base")
@@ -17,7 +17,13 @@ local get_args = function(runner, position)
return lib.vim_test.collect_args("python", runner, position) return lib.vim_test.collect_args("python", runner, position)
end end
local get_runner = function() local stored_runners = {}
local get_runner = function(python_command)
local command_str = table.concat(python_command, " ")
if stored_runners[command_str] then
return stored_runners[command_str]
end
local vim_test_runner = vim.g["test#python#runner"] local vim_test_runner = vim.g["test#python#runner"]
if vim_test_runner == "pyunit" then if vim_test_runner == "pyunit" then
return "unittest" return "unittest"
@@ -25,16 +31,21 @@ local get_runner = function()
if vim_test_runner and lib.func_util.index({ "unittest", "pytest" }, vim_test_runner) then if vim_test_runner and lib.func_util.index({ "unittest", "pytest" }, vim_test_runner) then
return vim_test_runner return vim_test_runner
end end
if vim.fn.executable("pytest") == 1 then local runner = base.module_exists("pytest", python_command) and "pytest" or "unittest"
return "pytest" stored_runners[command_str] = runner
end return runner
return "unittest"
end end
---@type NeotestAdapter ---@type NeotestAdapter
local PythonNeotestAdapter = { name = "neotest-python" } local PythonNeotestAdapter = { name = "neotest-python" }
PythonNeotestAdapter.root = lib.files.match_root_pattern("pyproject.toml", "setup.cfg", "mypy.ini", "pytest.ini", "setup.py") PythonNeotestAdapter.root = lib.files.match_root_pattern(
"pyproject.toml",
"setup.cfg",
"mypy.ini",
"pytest.ini",
"setup.py"
)
function PythonNeotestAdapter.is_test_file(file_path) function PythonNeotestAdapter.is_test_file(file_path)
return base.is_test_file(file_path) return base.is_test_file(file_path)
@@ -53,18 +64,23 @@ function PythonNeotestAdapter.discover_positions(path)
name: (identifier) @namespace.name) name: (identifier) @namespace.name)
@namespace.definition @namespace.definition
]] ]]
local root = PythonNeotestAdapter.root(path)
local python = base.get_python_command(root)
local runner = get_runner(python)
return lib.treesitter.parse_positions(path, query, { return lib.treesitter.parse_positions(path, query, {
require_namespaces = get_runner() == "unittest", require_namespaces = runner == "unittest",
}) })
end end
---@async
---@param args NeotestRunArgs ---@param args NeotestRunArgs
---@return NeotestRunSpec ---@return NeotestRunSpec
function PythonNeotestAdapter.build_spec(args) function PythonNeotestAdapter.build_spec(args)
local position = args.tree:data() local position = args.tree:data()
local results_path = vim.fn.tempname() local results_path = async.fn.tempname()
local runner = get_runner() local root = PythonNeotestAdapter.root(position.path)
local python = base.get_python_command(vim.fn.getcwd()) local python = base.get_python_command(root)
local runner = get_runner(python)
local script_args = vim.tbl_flatten({ local script_args = vim.tbl_flatten({
"--results-file", "--results-file",
results_path, results_path,
@@ -86,7 +102,7 @@ function PythonNeotestAdapter.build_spec(args)
context = { context = {
results_path = results_path, results_path = results_path,
}, },
strategy = base.get_strategy_config(args.strategy, python_script, script_args), strategy = base.get_strategy_config(args.strategy, python, python_script, script_args),
} }
end end

View File

@@ -76,19 +76,8 @@ class PytestNeotestAdapter(NeotestAdapter):
"errors": errors, "errors": errors,
}, },
) )
results[abs_path] = self.update_result(
results.get(abs_path),
{
"short": None,
"status": NeotestResultStatus(report.outcome),
"errors": errors,
},
)
import pytest import pytest
pytest.main(args=args, plugins=[NeotestResultCollector]) pytest.main(args=args, plugins=[NeotestResultCollector])
return results return results
def update_report(self, report: Optional[Dict], update: Dict):
...

View File

@@ -76,14 +76,6 @@ class UnittestNeotestAdapter(NeotestAdapter):
"short": None, "short": None,
}, },
) )
results[case_file] = self.update_result(
results.get(case_file),
{
"status": NeotestResultStatus.FAILED,
"errors": [{"message": message, "line": error_line}],
"short": None,
},
)
for case, message in result.skipped: for case, message in result.skipped:
results[self.case_id(case)] = self.update_result( results[self.case_id(case)] = self.update_result(
results[self.case_id(case)], results[self.case_id(case)],