Skip to content

Fix flake8 per-file settings, the fallback interpreter, and the undocumented flake8 settings - #985

Open
ZayanKhan-12 wants to merge 2 commits into
palantir:developfrom
ZayanKhan-12:fix/flake8-stdin-and-fallback
Open

ZayanKhan-12 wants to merge 2 commits into
palantir:developfrom
ZayanKhan-12:fix/flake8-stdin-and-fallback

Conversation

@ZayanKhan-12

Copy link
Copy Markdown

Description

Refs #190.

The headline ask on #190 — run flake8 itself, so flake8 plugins work — was resolved by @youben11's #656. pyls/plugins/flake8_lint.py shells out to the real flake8, so flake8-isort and friends load normally. What is left is the second half of the title, configuration, and it is genuinely broken in three ways. All three are things people in this thread hit and worked around by guesswork.

1. per-file-ignores and exclude silently never apply

The document is piped to flake8 over stdin so unsaved changes get linted, but nothing tells flake8 what the file is called, so it sees the name stdin. Every setting flake8 resolves per filename then cannot match.

Verified against flake8 3.8.4 with a setup.cfg containing per-file-ignores = pkg/legacy.py: E501,F401:

invocation result
flake8 - (what pyls does today) F401 and E501 both reported
flake8 --stdin-display-name=pkg/legacy.py - clean — ignores applied

exclude behaves the same way: a file the user excluded is still linted today, and is correctly skipped once flake8 knows its name.

The plugin now passes --stdin-display-name, and omits it when the document has no path (unsaved, or a non-file URI).

To be precise about the limit of this fix: it does not change flake8's config discovery, which flake8 3.8 still does from the working directory. Passing an absolute display name from an unrelated cwd still failed to find the project config in my testing, so that is a separate problem and I have not claimed to fix it.

2. The fallback interpreter does not exist on Python 3 only systems

When the configured executable is not on PATH, the plugin fell back to python -m flake8. Bare python does not exist on a modern macOS or on most current Linux distributions. That second Popen was not guarded, so it raised too — and the error the user saw was FileNotFoundError: [Errno 2] No such file or directory: 'flake8', which names the wrong thing and suggests nothing.

This matters more than it looks, because installing pyls and flake8 into different environments is the normal case: pipx install python-language-server plus a project virtualenv. The fallback exists precisely for that, and it never worked.

It now falls back to sys.executable -m flake8, which is guaranteed to exist and is the interpreter that pip install python-language-server[flake8] put flake8 into. If that fails too it logs what to do rather than raising.

This fixes two tests that currently fail on develop: test_flake8_lint and test_flake8_unsaved fail on any machine without flake8 on PATH, for exactly this reason.

3. None of the flake8 settings were discoverable

The README says to see vscode-client/package.json for "the full set of supported configuration options". The flake8 plugin has been in the tree since #656 and had zero entries there, which is why this thread is mostly people guessing at names — and why @horseinthesky's max-line-length was ignored while maxLineLength worked.

The second commit adds the nine settings the plugin actually reads, recording that it is disabled by default.

It also corrects pyls.configurationSources, whose enum was wrong in both directions: it omitted flake8, the value the README tells people to use, and listed pyflakes, which is not a config source at all. pyls/config/config.py registers only flake8 and pycodestyle, and there is no pyflakes_conf.py.

Tests

Five new tests: the display name is passed with the document path; it is omitted when there is no path; the fallback uses sys.executable and not bare python; both attempts failing logs something actionable instead of raising; and an end-to-end test running the real flake8 against a project whose per-file-ignores should suppress a code.

I checked they hold the line by re-breaking each fix: removing --stdin-display-name fails 2 (including the end-to-end one), restoring the bare python fallback fails 3 — including the two pre-existing failures, which is direct evidence that bug caused them — and always sending a display name fails the no-path test.

Verification

Python 3.8 with jedi 0.17.2, matching the CI matrix.

baseline on develop with this change
pytest test/ 12 failed, 99 passed, 8 skipped 10 failed, 106 passed, 8 skipped
difference in failing set only test_flake8_lint and test_flake8_unsaved, both now passing
pycodestyle pyls test clean clean
pyflakes pyls test 1 pre-existing (_utils.py) unchanged
pylint pyls test 84 messages +1 consider-using-f-string, no new message types

That one added message is a .format() call, which Python 2.7 support requires; the baseline already has eleven. I fixed the one genuinely new message type I had introduced.

The package.json change is insert-only apart from the single enum line — I reverted a first attempt that round-tripped the JSON and reformatted unrelated entries.

Notes

I have not touched the README here. It already points at package.json, and that pointer becomes accurate with this change; my other open PR (#984) edits the README, and I did not want the two to conflict.

CLAUDE.md lives in #982 and is not duplicated here.

zk-khan and others added 2 commits September 16, 2026 16:44
Two bugs in the flake8 plugin, both of which make flake8 configuration silently
not apply.

The document is piped to flake8 over stdin so unsaved changes are linted, but
nothing told flake8 what the file is called, so it saw the name "stdin". Any
setting flake8 resolves per filename then cannot match, which silently disabled
per-file-ignores and exclude. Verified against flake8 3.8.4: with a setup.cfg
declaring "per-file-ignores = legacy.py: E501,F401", linting that file over
stdin reports both codes, and passing --stdin-display-name reports neither. The
same applies to exclude. The plugin now passes the document path, and omits it
for an unsaved or non-file document that has no path.

Separately, when the configured executable is not on PATH the plugin fell back
to running "python -m flake8". Bare "python" does not exist on a Python 3 only
system, so the fallback raised as well, and because it was not guarded the user
saw a FileNotFoundError naming flake8 rather than anything actionable. It now
falls back to sys.executable, which is both guaranteed to exist and the
interpreter that pip install python-language-server[flake8] installed flake8
into. If that also fails it logs what to do instead of raising.

That second fix makes test_flake8_lint and test_flake8_unsaved pass; they fail
on develop on any machine without flake8 on PATH.

Refs palantir#190

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The README points at vscode-client/package.json for "the full set of supported
configuration options", but the flake8 plugin added in palantir#656 was never listed
there, so none of its settings were discoverable. The thread on palantir#190 is largely
people guessing at setting names.

Adds the nine settings the plugin actually reads, recording that it is disabled
by default.

Also corrects the configurationSources enum, which was wrong in both
directions: it omitted flake8, which is a real source and the one the README
tells people to select, and listed pyflakes, which is not one. Config sources
are registered in pyls/config/config.py and only flake8 and pycodestyle exist.

Refs palantir#190

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@palantirtech

Copy link
Copy Markdown
Member

Thanks for your interest in palantir/python-language-server, @ZayanKhan-12! Before we can accept your pull request, you need to sign our contributor license agreement - just visit https://cla.palantir.com/ and follow the instructions. Once you sign, I'll automatically update this pull request.

ZayanKhan-12 pushed a commit to ZayanKhan-12/python-language-server that referenced this pull request Sep 16, 2026
…d-fallback

Fix flake8 per-file settings, the fallback interpreter, and the undocumented flake8 settings (refs palantir#190)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants