feat(pytest): use python_functions config option (#100)
This commit is contained in:
@@ -52,6 +52,7 @@ return function(config)
|
|||||||
|
|
||||||
---@type neotest.Adapter
|
---@type neotest.Adapter
|
||||||
return {
|
return {
|
||||||
|
|
||||||
name = "neotest-python",
|
name = "neotest-python",
|
||||||
root = base.get_root,
|
root = base.get_root,
|
||||||
filter_dir = function(name)
|
filter_dir = function(name)
|
||||||
@@ -64,7 +65,7 @@ return function(config)
|
|||||||
local python_command = config.get_python_command(root)
|
local python_command = config.get_python_command(root)
|
||||||
local runner = config.get_runner(python_command)
|
local runner = config.get_runner(python_command)
|
||||||
|
|
||||||
local positions = lib.treesitter.parse_positions(path, base.treesitter_queries, {
|
local positions = lib.treesitter.parse_positions(path, base.treesitter_queries(runner, config, python_command), {
|
||||||
require_namespaces = runner == "unittest",
|
require_namespaces = runner == "unittest",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -92,18 +92,56 @@ function M.get_python_command(root)
|
|||||||
return python_command_mem[root]
|
return python_command_mem[root]
|
||||||
end
|
end
|
||||||
|
|
||||||
M.treesitter_queries = [[
|
---@return string
|
||||||
|
function M.get_script_path()
|
||||||
|
local paths = vim.api.nvim_get_runtime_file("neotest.py", true)
|
||||||
|
for _, path in ipairs(paths) do
|
||||||
|
if vim.endswith(path, ("neotest-python%sneotest.py"):format(lib.files.sep)) then
|
||||||
|
return path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
error("neotest.py not found")
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param python_command string[]
|
||||||
|
---@param config neotest-python._AdapterConfig
|
||||||
|
---@param runner string
|
||||||
|
---@return string
|
||||||
|
local function scan_test_function_pattern(runner, config, python_command)
|
||||||
|
local test_function_pattern = "^test"
|
||||||
|
if runner == "pytest" and config.pytest_discovery then
|
||||||
|
local cmd = vim.tbl_flatten({ python_command, M.get_script_path(), "--pytest-extract-test-name-template" })
|
||||||
|
local _, data = lib.process.run(cmd, { stdout = true, stderr = true })
|
||||||
|
|
||||||
|
for line in vim.gsplit(data.stdout, "\n", true) do
|
||||||
|
if string.sub(line, 1, 1) == "{" and string.find(line, "python_functions") ~= nil then
|
||||||
|
local pytest_option = vim.json.decode(line)
|
||||||
|
test_function_pattern = pytest_option.python_functions
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return test_function_pattern
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param python_command string[]
|
||||||
|
---@param config neotest-python._AdapterConfig
|
||||||
|
---@param runner string
|
||||||
|
---@return string
|
||||||
|
M.treesitter_queries = function(runner, config, python_command)
|
||||||
|
local test_function_pattern = scan_test_function_pattern(runner, config, python_command)
|
||||||
|
return string.format([[
|
||||||
;; Match undecorated functions
|
;; Match undecorated functions
|
||||||
((function_definition
|
((function_definition
|
||||||
name: (identifier) @test.name)
|
name: (identifier) @test.name)
|
||||||
(#match? @test.name "^test"))
|
(#match? @test.name "%s"))
|
||||||
@test.definition
|
@test.definition
|
||||||
|
|
||||||
;; Match decorated function, including decorators in definition
|
;; Match decorated function, including decorators in definition
|
||||||
(decorated_definition
|
(decorated_definition
|
||||||
((function_definition
|
((function_definition
|
||||||
name: (identifier) @test.name)
|
name: (identifier) @test.name)
|
||||||
(#match? @test.name "^test")))
|
(#match? @test.name "%s")))
|
||||||
@test.definition
|
@test.definition
|
||||||
|
|
||||||
;; Match decorated classes, including decorators in definition
|
;; Match decorated classes, including decorators in definition
|
||||||
@@ -120,23 +158,12 @@ M.treesitter_queries = [[
|
|||||||
@namespace.definition
|
@namespace.definition
|
||||||
(#not-has-parent? @namespace.definition decorated_definition)
|
(#not-has-parent? @namespace.definition decorated_definition)
|
||||||
)
|
)
|
||||||
]]
|
]], test_function_pattern, test_function_pattern)
|
||||||
|
end
|
||||||
|
|
||||||
M.get_root =
|
M.get_root =
|
||||||
lib.files.match_root_pattern("pyproject.toml", "setup.cfg", "mypy.ini", "pytest.ini", "setup.py")
|
lib.files.match_root_pattern("pyproject.toml", "setup.cfg", "mypy.ini", "pytest.ini", "setup.py")
|
||||||
|
|
||||||
---@return string
|
|
||||||
function M.get_script_path()
|
|
||||||
local paths = vim.api.nvim_get_runtime_file("neotest.py", true)
|
|
||||||
for _, path in ipairs(paths) do
|
|
||||||
if vim.endswith(path, ("neotest-python%sneotest.py"):format(lib.files.sep)) then
|
|
||||||
return path
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
error("neotest.py not found")
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.create_dap_config(python_path, script_path, script_args, dap_args)
|
function M.create_dap_config(python_path, script_path, script_args, dap_args)
|
||||||
return vim.tbl_extend("keep", {
|
return vim.tbl_extend("keep", {
|
||||||
type = "python",
|
type = "python",
|
||||||
|
@@ -58,6 +58,13 @@ def main(argv: List[str]):
|
|||||||
collect(argv)
|
collect(argv)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if "--pytest-extract-test-name-template" in argv:
|
||||||
|
argv.remove("--pytest-extract-test-name-template")
|
||||||
|
from .pytest import extract_test_name_template
|
||||||
|
|
||||||
|
extract_test_name_template(argv)
|
||||||
|
return
|
||||||
|
|
||||||
args = parser.parse_args(argv)
|
args = parser.parse_args(argv)
|
||||||
adapter = get_adapter(TestRunner(args.runner), args.emit_parameterized_ids)
|
adapter = get_adapter(TestRunner(args.runner), args.emit_parameterized_ids)
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Callable, Dict, List, Optional, Union
|
from typing import Callable, Dict, List, Optional, Union
|
||||||
|
|
||||||
@@ -205,5 +206,16 @@ class NeotestDebugpyPlugin:
|
|||||||
additional_info.is_tracing -= 1
|
additional_info.is_tracing -= 1
|
||||||
|
|
||||||
|
|
||||||
|
class TestNameTemplateExtractor:
|
||||||
|
@staticmethod
|
||||||
|
def pytest_collection_modifyitems(config):
|
||||||
|
config = {"python_functions": config.getini("python_functions")[0]}
|
||||||
|
print(f"\n{json.dumps(config)}\n")
|
||||||
|
|
||||||
|
|
||||||
|
def extract_test_name_template(args):
|
||||||
|
pytest.main(args=["-k", "neotest_none"], plugins=[TestNameTemplateExtractor])
|
||||||
|
|
||||||
|
|
||||||
def collect(args):
|
def collect(args):
|
||||||
pytest.main(["--collect-only", "--verbosity=0", "-q"] + args)
|
pytest.main(["--collect-only", "--verbosity=0", "-q"] + args)
|
||||||
|
Reference in New Issue
Block a user