This is great news! With the advent of agentic coding, strong linting is more important than ever. What I'd really like to see is forbidigo for more languages.
Tbh I was super enthusiastic about Ty but it’s just so far behind basedpyright I had to switch off it. The lack of checks wasn’t the issue, it was the false positives which were the real dealbreaker. That and it doesn’t have support for baselining, which is such an insanely awesome feature for larger codebases. uv and ruff are incredible though. Maybe someday on Ty.
I sorta kinda get why `ty` is pre v1.0.0 -- it's a typechecker that doesn't check a huge number of types. But what are we waiting for with `ruff`? Surely it's eaten whatever the old options were (black? maybe a few takes on py+lint?) by now many times over, and is even more dominant than `uv`.
I run this program hundreds of times a day so I'm generally excited for new features, but I guess the OAI acquisition has made me ornery when it comes to these folks. Apologies to kindly nerds who made this release happen, and congrats <3
I wish Go had something like Ruff! A lot of languages are getting amazing tool but Go has a very fragmented ecosystem with a lot of tools but none of them feel as high quality has the likes of Ruff, Oxc, Biome or even PHP's Mago
The amount of fascination that people have with these "grammar nazi" bots -- some of them implementing completely arbitrary "rules" and some of them disagreeing with others on what "good" Python code should look like -- doesn't stop to amaze me.
Here's "bad" code:
important_numbers = {
'x': 3,
'y': 42, # Answer to the Ultimate Question!
'z': 2
}
Here's what "good" code should look like:
important_numbers = {"x": 3, "y": 42, "z": 2} # Answer to the Ultimate Question!
Which completely misses the writer's intent. But did you notice that there are two spaces before the pound now? Also, the quotes are now double because apparently it's somehow more kosher! So much improvement!
The actual problems in the code I work with are not the spaces at the end of line or imports in non-alphabetic order, it's the 10-line list comprehensions that are so long that they're impossible for me to parse. None of these tools catch that. My place used pylint, flake8, black, ruff -- with hundreds of commits on every change. All that energy could be better spent elsewhere.
(I intentionally switched to double quotes since that really is a stylistic choice in Python, you can escape in both, and if you use double quotes inside of single quotes ruff leaves it as-is)
Yep. So far I have found every auto-formatter tool to be hopelessly naive in its workings. No, sorry, I do not want my logger call to stretch over 5 lines of screen real estate, just because the silly tool doesn't allow to distinguish between logger calls and other stuff, and a log message can be > 80 characters. They often make code less readable than before. I am still traumatized from adding trailing comma to every multi-line call, due to black being "opinionated" and always moving things back to one line, making them less readable, if they are not longer than some limit. It's silly.
I updated a ~3k line Python project with this the other day. I was using v0.15.x beforehand. It didn't take too long and the new rules do improve code quality. It caught quite a few things previous versions didn't.
Default on lint is good for agent fleets. fwiw, I watched one agent "fix" an unfamiliar rule by deleting the test; perfect compliance, tiny misunderstanding.
I really wish Ruff would introduce something similar to Nix’s stateVersion, which is used to determine the set of defaults that will be applied. Updating Ruff at a scale beyond a single repo is a bit of a crapshoot currently, with every version introducing a bunch of new default rules which you then have to deal with immediately (either by turning them off or fixing them).
I’m aware we could have an allowlist in place which specifies all rules that are turned on but I’d much rather have a simpler config file, and be able to bump the state version at a good time for everyone to spend a few hours fixing new violations.
30 comments
[ 3.8 ms ] story [ 18.0 ms ] threadI sorta kinda get why `ty` is pre v1.0.0 -- it's a typechecker that doesn't check a huge number of types. But what are we waiting for with `ruff`? Surely it's eaten whatever the old options were (black? maybe a few takes on py+lint?) by now many times over, and is even more dominant than `uv`.
I run this program hundreds of times a day so I'm generally excited for new features, but I guess the OAI acquisition has made me ornery when it comes to these folks. Apologies to kindly nerds who made this release happen, and congrats <3
Here's "bad" code:
Here's what "good" code should look like: Which completely misses the writer's intent. But did you notice that there are two spaces before the pound now? Also, the quotes are now double because apparently it's somehow more kosher! So much improvement!The actual problems in the code I work with are not the spaces at the end of line or imports in non-alphabetic order, it's the 10-line list comprehensions that are so long that they're impossible for me to parse. None of these tools catch that. My place used pylint, flake8, black, ruff -- with hundreds of commits on every change. All that energy could be better spent elsewhere.
It also does not collapse lines when there’s a trailing comma.
Your output seems to be from black. IMO it’s insane to collapse lines when there are line comments.
(I intentionally switched to double quotes since that really is a stylistic choice in Python, you can escape in both, and if you use double quotes inside of single quotes ruff leaves it as-is)If you add an extra dangling comma at the end of the last item, ruff/black will auto-format to the line-by-line style you like.
Here's a few commits of changes:
(A whole bunch of manual changes based on its suggestions) https://github.com/nickjj/plutus/commit/9af66d31f98bef841588...
(Re-enable line length) https://github.com/nickjj/plutus/commit/21789f89bbcee37913c1...
(Force _ prefix for unused variables) https://github.com/nickjj/plutus/commit/a272c77b932e1c78558a...
(Auto-corrected by Ruff) https://github.com/nickjj/plutus/commit/6fe69cf88385ebdf9b8c...
I’m aware we could have an allowlist in place which specifies all rules that are turned on but I’d much rather have a simpler config file, and be able to bump the state version at a good time for everyone to spend a few hours fixing new violations.
According to the original post
> Ruff's default rule set was last modified in v0.1.0
Which was over 2 years ago.
https://github.com/astral-sh/ruff/releases/tag/v0.1.0
Two approaches:
You can pin the version of `ruff` in `pyproject.toml`.
You, to let ruff command version advance but pin the settings to a prior version:
The `flat2toml` script is left as an exercise. Then in `ruff.toml`:LibCST can modify the AST/CST to do python codemod, now in Rust too;
rustpython-ruff_python_parser: https://crates.io/crates/rustpython-ruff_python_parser .. https://github.com/astral-sh/ruff
LibCST: https://github.com/Instagram/LibCST