Skip to content

Allow EXE001 & EXE002 on WSL, fix issues with other cases of mounting non-unix filesystems#17584

Open
MusicalNinjaDad wants to merge 6 commits intoastral-sh:mainfrom
MusicalNinjaDad:wsl_shebang
Open

Allow EXE001 & EXE002 on WSL, fix issues with other cases of mounting non-unix filesystems#17584
MusicalNinjaDad wants to merge 6 commits intoastral-sh:mainfrom
MusicalNinjaDad:wsl_shebang

Conversation

@MusicalNinjaDad
Copy link
Copy Markdown

@MusicalNinjaDad MusicalNinjaDad commented Apr 23, 2025

Summary

EXE001 & EXE002 lints require a file-system which supports unix-like filemodes. Users mounting projects from USB sticks (#12941) and users mounting windows file-systems (#3110, #5445) will receive false positives from lint EXE002.

There is nothing inherent to WSL which is related to this issue. WSL users following recommended usage will not be storing files on a windows file-system. #5735 introduced a check which unnecessarily disables these lints for all WSL users (#10084).

This change implements a heuristic check to identify whether the filesystem supports unix-like filemodes and additionally improves performance of these lints.

fixes #10084, fixes #12941, fixes #5445, fixes astral-sh/ruff-action#307

Reviewers Guide

Changes have been squashed into 5 molecular commits, which can be reviewed independently:

  • c40cea0 Extend tests to cover additional file-systems & windows
  • f717218 Add github workflows to validate EXE001 & EXE002 on WSL & windows
  • f419d92 Select relevant tests to run in each test environment
  • 6b02f75 Replace is_wsl check with file-system heuristic
  • fe1f437 Add tests for case where pyproject.toml exists

Why not just remove is_wsl checks?

We can realistically expect that users who store their project on their windows file-system will mainly be less experienced and newer coders. Introducing a situation where they receive false positives for every file is unreasonable from a UX perspective.

What's this got to do with WSL?

Fundamentally, nothing. The current code disable lints for WSL users, where it does not need to. A key user group who use windows file-systems will be relatively inexperienced WSL users, not following Microsoft's recommendations on file locations.

Performance

This change improves performance of these lints by approx 3% in almost all cases and does not reduce performance in any cases. (Bench results available, if wanted)

Testing

Given the need to run tests on multiple OS & file-system combinations, this PR provides a dedicated github workflow to avoid future regression. The workflow is only triggered on relevant changes.

@MusicalNinjaDad MusicalNinjaDad marked this pull request as ready for review April 25, 2025 11:56
@MichaReiser
Copy link
Copy Markdown
Member

Thank you. Your test setup is very impressive.

There's a lot happening right now. I'm not sure when I'll get the time to review this PR.

@MusicalNinjaDad
Copy link
Copy Markdown
Author

Thanks - I fully understand and that quick note was really valuable.

I'd also personally much rather have red-knot available than this included in ruff ;)

I'll probably hang back on taking up other topics until I do get feedback on this (unless I get bored or randomly motivated) - so I can include any feedback on style etc from the start.

@MusicalNinjaDad
Copy link
Copy Markdown
Author

Is there something I could do to make this approach easier to maintain? I understand if you are reluctant to take over the additional test infrastructure. (@ntBre, @MichaReiser, @amyreese)

The logic change itself is simple and shouldn't add maintenance burden, particularly with CI-based tests in place. I could remove the testing and just provide the logic, although personally I dislike the idea ;)

@ntBre
Copy link
Copy Markdown
Contributor

ntBre commented Jan 12, 2026

Thanks again for your work on this!

Taking a quick look back at the diff, the main things that make this look hard to review to me are:

  • the changes to the nextest config
  • the added CI workflows
  • the added benchmarks
  • the modified build script
  • the platform-dependent test_matrix changes

These all raise the bar of how closely I feel I need to review the changes compared to modifying the rule's Rust code or normal test fixtures.

Beyond that, I'm just not that familiar with Windows and don't have a Windows machine (easily) available for testing. The core change does look straightforward, but it's also a bit surprising to create a temporary file and check its permissions (assuming I'm understanding correctly) instead of calling is_wsl from a third-party crate.

Hopefully that gives some context. That's why the PR looks complicated to review to me in its current form and why I haven't found a chance to prioritize it yet.

@MusicalNinjaDad
Copy link
Copy Markdown
Author

MusicalNinjaDad commented Jan 14, 2026

Fully understand, and I sort of expected that answer ;)

I'll restructure to make it easier to review.

The core change does look straightforward, but it's also a bit surprising to create a temporary file and check its permissions (assuming I'm understanding correctly) instead of calling is_wsl from a third-party crate.

Correct - that's what the logic change does. Reason: is_wsl() returns true for all WSL users, the majority of whom use a normal ext4 filesystem, and therefore do not need the lints disabled. For all these users disabling the lints leads to nasty surprises if they assume that they are active (#10084). Doing it this way covers both types of WSL user, as well as linux users who are storing code on USB sticks etc. (#12941)

@MusicalNinjaDad MusicalNinjaDad marked this pull request as draft February 4, 2026 10:55
 - Update existing EXE001 & EXE002 test fixture contents to make failure analysis easier
 - Also run EXE001 & EXE002 tests on windows
 - Add specific tests for current failure cases on alternative filesystems (NTFS etc.)
- Add dedicated github workflow to run flake8_executable lints on multiple
operating systems & filesystems
- Add github action to install & cache WSL on windows runner. This is a
resource & time intensive activity. Cache key is based upon selected
distro version & hash of action.yml.
- Add a `ci-short` nextest profile. Standard CI profile lists all skipped
tests, this list is very long for this workflow.
- Run standard EXE001 & EXE002 tests by default on unix
- Run NTFS tests on windows
- Create a cfg option `test_environment` to override default unix behaviour
- Run NTFS tests on unix if `test_environment` is set to `ntfs`

At this point test results in CI accurately reflect current status quo
before implementing and logic changes:

- Standard WSL case fails
- Linux, Windows & WSL-on-NTFS all pass
- Remove all checks from EXE001. All files are always executable on NTFS
filesystems, therefore the EXE001 lint will never fail. Running any logic
here simply slows down performance for ALL unix users.
- Add a helper function to identify whether files are executable by default.
    1. Using a `OnceLock` to avoid repeated checks improves performance
    vs previous repeated is_wsl checks for ALL users
    2. If `pyproject.toml` exists and is not executable we know that this
    filesystem supports `is_executable`.
    3. If no `pyproject.toml` is available we create a `NamedTempFile` in
    the project root and check whether `is_executable`.
- If files are executable by default EXE002 lint is not viable. Replace
`is_wsl` with `executable_by_default`
- Remove dependency on `is_wsl` crate. No longer needed.
- Update documentation to reflect improved logic and link to WSL
documentation regarding filesystem recommendations.
@MusicalNinjaDad MusicalNinjaDad marked this pull request as ready for review February 9, 2026 15:47
@MusicalNinjaDad
Copy link
Copy Markdown
Author

@ntBre - I've simplified a few things when rebasing this onto current main; and tried to simplify the review by packaging it into 5 distinct and easily reviewable commits (see new description). Happy to answer any questions that are still open ...

Thanks!

Copy link
Copy Markdown
Member

@amyreese amyreese left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this changing nextest config and github actions?

@ntBre
Copy link
Copy Markdown
Contributor

ntBre commented Feb 9, 2026

Why is this changing nextest config and github actions?

It's changing the test setup to test the changes, but I think I agree with the sentiment. It doesn't feel worth it to me to introduce two new CI workflows among the other complexity to test these relatively niche rules. I'm still trying to decide how best to proceed here.

Thanks again for working on it!

@MusicalNinjaDad
Copy link
Copy Markdown
Author

Why is this changing nextest config and github actions?

It's changing the test setup to test the changes, but I think I agree with the sentiment. It doesn't feel worth it to me to introduce two new CI workflows among the other complexity to test these relatively niche rules. I'm still trying to decide how best to proceed here.

Thanks again for working on it!

I can remove them if you prefer. It's a single commit to revert.

I needed them for testing during development as the easiest way to cover all the necessary OS & FS combinations.
Thought I'd leave them there to help catch any future regression.

@ntBre ntBre added the rule Implementing or modifying a lint rule label Feb 10, 2026
@ntBre
Copy link
Copy Markdown
Contributor

ntBre commented Feb 12, 2026

Thanks again for working on this and for your patience with all the back and forth. I'd be curious to get Micha's thoughts when he's back from PTO at the end of the month, but then I think we should make a decision here one way or the other. I'm always hesitant to say this because it's nice to have regression tests, like you said, but my current thinking is that I would be okay landing this without the testing setup, which seems to be the most contentious part.

@MusicalNinjaDad
Copy link
Copy Markdown
Author

Thanks again for working on this and for your patience with all the back and forth. I'd be curious to get Micha's thoughts when he's back from PTO at the end of the month, but then I think we should make a decision here one way or the other. I'm always hesitant to say this because it's nice to have regression tests, like you said, but my current thinking is that I would be okay landing this without the testing setup, which seems to be the most contentious part.

Thanks for the update.
Just let me know once you're ready and have discussed internally.

@MichaReiser
Copy link
Copy Markdown
Member

I don't understand WSL enough to say whether this change is correct and works in all situations. My understanding after participating in #21724 is that there will still be cases where this heuristic fails, which can be frustrating for users, especially because it "used to work".

To move this forward, I'd have to spend some time familiarizing myself with WSL, but it never felt pressing enough to put on top of my tasks. I'm more than happy if someone else wants to take a look.

From what I understand today (and I might be completely wrong on this), I'm leaning towards checking the permission bits on WSL by default, extending the rule documentation with some examples where the permission checks might fail and why, and introducing an option that brings back the existing behavior to skip the check on WSL.

@MusicalNinjaDad
Copy link
Copy Markdown
Author

It's unfortunate that someone bringing up random, hypothetical edge cases can torpedo a change that would benefit 3 different, reasonably sized, groups of users. Even more so, given that the fix works for the author of that other PR. 😢

The reasoning behind my suggestion not to simply remove the WSL checks is in the updated description.

So far, no actual, real-world use case has been reported which this change doesn't catch.

Of course, no heuristic will be 100% accurate; but I would have thought a change was worthwhile if it:

  1. fixes multiple existing issues for a range of users
  2. does not make things worse for anyone, and
  3. replaces a workaround with a faster, proper fix of the actual issue. (?)

If you want someone from astral to take a look at this, I'd suggest someone who knows their way around filesystems - the whole topic of WSL is a red herring which is just causing noise. (FWIW @ntBre previously suggested "my current thinking is that I would be okay landing this without the testing setup, which seems to be the most contentious part.")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rule Implementing or modifying a lint rule

Projects

None yet

4 participants