From 2d3883392e69e3c988127b6873ffeeaf0e4ccb99 Mon Sep 17 00:00:00 2001 From: w0rp Date: Sat, 28 Feb 2026 09:39:23 +0000 Subject: [PATCH] wip --- AGENTS.md | 2 + ale_linters/python/ty.vim | 1 + doc/ale-html.txt | 6 ++ doc/ale-python.txt | 86 +++++++++++++++++++++++ doc/ale-supported-languages-and-tools.txt | 1 + doc/ale.txt | 2 + opencode.json | 28 ++++++++ supported-tools.md | 1 + test/handler/test_ty_handler.vader | 37 ++++++++++ test/linter/test_ty.vader | 72 +++++++++++++++++++ 10 files changed, 236 insertions(+) create mode 100644 AGENTS.md create mode 100644 opencode.json create mode 100644 test/handler/test_ty_handler.vader create mode 100644 test/linter/test_ty.vader diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..8a0a4644 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,2 @@ +- For `doc/ale-*.txt` help docs, right-align Vim help tags (`*...*`) to the right margin so tag lines meet ALE's alignment check. +- Keep integration/tool headings in ALE docs sorted in the expected order (alphabetical within each section), and update the corresponding table of contents entries in `doc/ale.txt` when adding/removing headings. diff --git a/ale_linters/python/ty.vim b/ale_linters/python/ty.vim index fb58ffa4..0a4d8908 100644 --- a/ale_linters/python/ty.vim +++ b/ale_linters/python/ty.vim @@ -51,6 +51,7 @@ function! ale_linters#python#ty#Handle(buffer, lines) abort let l:output = [] let l:items = json_decode(join(a:lines, '')) + if empty(l:items) return l:output endif diff --git a/doc/ale-html.txt b/doc/ale-html.txt index 84babc30..cef51755 100644 --- a/doc/ale-html.txt +++ b/doc/ale-html.txt @@ -283,6 +283,12 @@ g:ale_html_tidy_use_global See |ale-integrations-local-executables| +=============================================================================== +ty *ale-html-ty* + +`ty` is a Python type checker. See |ale-python-ty| for configuration options. + + =============================================================================== vscodehtml *ale-html-vscode* diff --git a/doc/ale-python.txt b/doc/ale-python.txt index eeea36d5..3c79bfe6 100644 --- a/doc/ale-python.txt +++ b/doc/ale-python.txt @@ -2106,6 +2106,92 @@ g:ale_python_ruff_format_auto_uv executable. +=============================================================================== +ty *ale-python-ty* + +`ty` will be run from a detected project root, per |ale-python-root|. + + *ale-options.python_ty_change_directory* + *g:ale_python_ty_change_directory* + *b:ale_python_ty_change_directory* +python_ty_change_directory +g:ale_python_ty_change_directory + Type: |Number| + Default: `1` + + If set to `1`, `ty` will be run from a detected project root, per + |ale-python-root|. If no project root is detected, `ty` will be run from the + buffer's directory. + + *ale-options.python_ty_executable* + *g:ale_python_ty_executable* + *b:ale_python_ty_executable* +python_ty_executable +g:ale_python_ty_executable + Type: |String| + Default: `'ty'` + + See |ale-integrations-local-executables| + + Set this to `'pipenv'` to invoke `'pipenv` `run` `ty` `check'`. + Set this to `'poetry'` to invoke `'poetry` `run` `ty` `check'`. + Set this to `'uv'` to invoke `'uv` `run` `ty` `check'`. + + *ale-options.python_ty_options* + *g:ale_python_ty_options* + *b:ale_python_ty_options* +python_ty_options +g:ale_python_ty_options + Type: |String| + Default: `''` + + This variable can be changed to add command-line arguments to the ty + invocation. + + *ale-options.python_ty_use_global* + *g:ale_python_ty_use_global* + *b:ale_python_ty_use_global* +python_ty_use_global +g:ale_python_ty_use_global + Type: |Number| + Default: `get(g:, 'ale_use_global_executables', 1)` + + See |ale-integrations-local-executables| + + *ale-options.python_ty_auto_pipenv* + *g:ale_python_ty_auto_pipenv* + *b:ale_python_ty_auto_pipenv* +python_ty_auto_pipenv +g:ale_python_ty_auto_pipenv + Type: |Number| + Default: `0` + + Detect whether the file is inside a pipenv, and set the executable to `pipenv` + if true. This is overridden by a manually-set executable. + + *ale-options.python_ty_auto_poetry* + *g:ale_python_ty_auto_poetry* + *b:ale_python_ty_auto_poetry* +python_ty_auto_poetry +g:ale_python_ty_auto_poetry + Type: |Number| + Default: `0` + + Detect whether the file is inside a poetry, and set the executable to `poetry` + if true. This is overridden by a manually-set executable. + + *ale-options.python_ty_auto_uv* + *g:ale_python_ty_auto_uv* + *b:ale_python_ty_auto_uv* +python_ty_auto_uv +g:ale_python_ty_auto_uv + Type: |Number| + Default: `0` + + Set the executable to `uv` if true. This is overridden by a manually-set + executable. + + =============================================================================== unimport *ale-python-unimport* diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index 5c3e3e54..4b59c0d5 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -557,6 +557,7 @@ Notes: * `reorder-python-imports` * ruff * ruff-format + * `ty` * `unimport` * `vulture`!! * `yapf` diff --git a/doc/ale.txt b/doc/ale.txt index da9bd7fe..3e9d422a 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -3589,6 +3589,7 @@ documented in additional help files. stylelint.............................|ale-html-stylelint| superhtml.............................|ale-html-superhtml| tidy..................................|ale-html-tidy| + ty....................................|ale-html-ty| vscodehtml............................|ale-html-vscode| write-good............................|ale-html-write-good| html angular template...................|ale-htmlangular-options| @@ -3831,6 +3832,7 @@ documented in additional help files. reorder-python-imports................|ale-python-reorder_python_imports| ruff..................................|ale-python-ruff| ruff-format...........................|ale-python-ruff-format| + ty....................................|ale-python-ty| unimport..............................|ale-python-unimport| vulture...............................|ale-python-vulture| yapf..................................|ale-python-yapf| diff --git a/opencode.json b/opencode.json new file mode 100644 index 00000000..dc961bab --- /dev/null +++ b/opencode.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://opencode.ai/config.json", + "keybinds": { + "app_exit": "q" + }, + "permission": { + "bash": { + "*": "deny", + "ls *": "allow", + "grep *": "allow", + "rg *": "allow", + "git diff *": "allow", + "git show *": "allow", + "git status *": "allow", + "git log *": "allow", + "git blame *": "allow", + "git reflog show *": "allow", + "./run-tests *": "allow" + }, + "read": { + "*": "allow" + }, + "edit": { + "*": "allow", + "opencode.json": "deny" + } + } +} diff --git a/supported-tools.md b/supported-tools.md index 74cf59f0..6d0ca0d0 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -567,6 +567,7 @@ formatting. * [reorder-python-imports](https://github.com/asottile/reorder_python_imports) * [ruff](https://github.com/charliermarsh/ruff) * [ruff-format](https://docs.astral.sh/ruff/formatter/) + * [ty](https://github.com/astral-sh/ty) :warning: * [unimport](https://github.com/hakancelik96/unimport) * [vulture](https://github.com/jendrikseipp/vulture) :warning: :floppy_disk: * [yapf](https://github.com/google/yapf) diff --git a/test/handler/test_ty_handler.vader b/test/handler/test_ty_handler.vader new file mode 100644 index 00000000..8130c0e7 --- /dev/null +++ b/test/handler/test_ty_handler.vader @@ -0,0 +1,37 @@ +Before: + runtime! ale_linters/python/ty.vim + +After: + call ale#linter#Reset() + +Execute(We should handle basic output from ty correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 3, + \ 'col': 2, + \ 'end_lnum': 3, + \ 'end_col': 10, + \ 'code': 'TY001', + \ 'text': 'Type check failed', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 6, + \ 'col': 4, + \ 'end_lnum': 6, + \ 'end_col': 7, + \ 'code': 'TY002', + \ 'text': 'Potential issue', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#python#ty#Handle(bufnr(''), [ + \ '[', + \ '{"check_name":"TY001","description":"Type check failed","severity":"major","location":{"positions":{"begin":{"line":3,"column":2},"end":{"line":3,"column":10}}}},', + \ '{"check_name":"TY002","description":"Potential issue","severity":"minor","location":{"positions":{"begin":{"line":6,"column":4},"end":{"line":6,"column":7}}}}', + \ ']', + \ ]) + +Execute(We should handle empty output from ty correctly): + AssertEqual [], ale_linters#python#ty#Handle(bufnr(''), ['[]']) diff --git a/test/linter/test_ty.vader b/test/linter/test_ty.vader new file mode 100644 index 00000000..ea8aa53f --- /dev/null +++ b/test/linter/test_ty.vader @@ -0,0 +1,72 @@ +Before: + call ale#assert#SetUpLinterTest('python', 'ty') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The ty command callback should return the correct default values): + call ale#test#SetFilename('./foo.py') + + AssertLinterCwd expand('%:p:h') + AssertLinter 'ty', ale#Escape('ty') . ' check --output-format gitlab %s' + +Execute(The option for disabling changing directories should work): + let g:ale_python_ty_change_directory = 0 + + AssertLinterCwd '' + AssertLinter 'ty', ale#Escape('ty') . ' check --output-format gitlab %s' + +Execute(The ty executable should be configurable, and escaped properly): + let g:ale_python_ty_executable = 'executable with spaces' + + AssertLinter 'executable with spaces', ale#Escape('executable with spaces') . ' check --output-format gitlab %s' + +Execute(The ty command callback should let you set options): + let g:ale_python_ty_options = '--some-option value' + + AssertLinter 'ty', ale#Escape('ty') . ' check --output-format gitlab --some-option value %s' + +Execute(The ty command callback should switch to project root when available): + call ale#test#SetFilename('../test-files/python/no_virtualenv/subdir/foo/bar.py') + + AssertLinterCwd ale#path#Simplify(g:dir . '/../test-files/python/no_virtualenv/subdir') + AssertLinter 'ty', ale#Escape('ty') . ' check --output-format gitlab %s' + +Execute(The ty command callback should use the global executable by default): + call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py') + + AssertLinter 'ty', ale#Escape('ty') . ' check --output-format gitlab %s' + +Execute(The ty command callback should fall back to global ty when no virtualenv executable is found): + let g:ale_python_ty_use_global = 0 + call ale#test#SetFilename('../test-files/python/with_virtualenv/subdir/foo/bar.py') + + AssertLinter 'ty', ale#Escape('ty') . ' check --output-format gitlab %s' + +Execute(Setting executable to 'pipenv' should append 'run ty'): + let g:ale_python_ty_executable = 'path/to/pipenv' + + AssertLinter 'path/to/pipenv', ale#Escape('path/to/pipenv') . ' run ty check --output-format gitlab %s' + +Execute(Pipenv is detected when python_ty_auto_pipenv is set): + let g:ale_python_ty_auto_pipenv = 1 + call ale#test#SetFilename('../test-files/python/pipenv/whatever.py') + + AssertLinter 'pipenv', ale#Escape('pipenv') . ' run ty check --output-format gitlab %s' + +Execute(Setting executable to 'poetry' should append 'run ty'): + let g:ale_python_ty_executable = 'path/to/poetry' + + AssertLinter 'path/to/poetry', ale#Escape('path/to/poetry') . ' run ty check --output-format gitlab %s' + +Execute(poetry is detected when python_ty_auto_poetry is set): + let g:ale_python_ty_auto_poetry = 1 + call ale#test#SetFilename('../test-files/python/poetry/whatever.py') + + AssertLinter 'poetry', ale#Escape('poetry') . ' run ty check --output-format gitlab %s' + +Execute(uv is detected when python_ty_auto_uv is set): + let g:ale_python_ty_auto_uv = 1 + call ale#test#SetFilename('../test-files/python/uv/whatever.py') + + AssertLinter 'uv', ale#Escape('uv') . ' run ty check --output-format gitlab %s'