FR version is available. Content is displayed in original English for accuracy.
Advertisement
Advertisement
⚡ Community Insights
Discussion Sentiment
69% Positive
Analyzed from 4839 words in the discussion.
Trending Topics
#code#ruff#tools#line#more#rules#should#linters#don#python

Discussion (228 Comments)Read Original on HackerNews
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...
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 is what it is, everyone gets the same, shut up and work on what matters.
I'm surprised you consider it a lot of energy spent, I tend not to spend any on this, it just runs automatically on my code and I drop out of pretty much every discussions about linting as it's good enough with automated tools.
I also used to work in places where there was no such tools, and there I had to actually spend time discussing and thinking about linting.
Edit: one could also use single or double quotes in strings, and it didn't anger the grammar nazi bots as there were none.
That's why I like Go, every piece of code looks the same, there's one default enforced linter and this discussion (or discussion if discussion should be allowed or prohibited) doesn't even cross anyones mind.
Afterwards it will affect production code everywhere on the planet. :)
And yet, as per the example, the bot force worse linting decisions, and even pushes towards more bugs (e.g. future readers missing the comment intention since it now applies to all 3).
That's because everybody uses linters nowadays, which was the original point.
(I think that in their case it was partially because uniformity made correcting faster.)
I can believe the latter, and I can assure you this was a Big Deal back in the day. There's a reason Go ships with gofmt, and gofmt was somewhat revolutionary for being a built-in "you gotta do it like this" back in the day.
Tokens are burnt, that's the most important part. And with more of the generated shitty code there will be more tokens spent in the future.
In short, you seem to have a grievance against linters that goes way past reasonable. You assert this example you give is "perfect" below. You also complain linters waste time and commits despite able evidence in the field they do the opposite.
You seem willing to add drama, grievance, and personal bias to what could have been a rather straightforward technical discussion. The sum of which is: linters sometimes make changes to code that I don't like.
I'd encourage you to reconsider what's really important when it comes to team development and try listening more to those around you. You seem overly focused on asserting your opinion instead of having a discussion.
These types of exchanges are usually very unproductive and stressful in a team environment. They are evidence, IMO, of a dev having the wrong priorities. I'd encourage you to step back and really consider how you view craftsmanship in a team dynamic and whether or not you are fighting the right battles.
In a thread where I complain about the de-humanisation of my profession by the bots, the irony of having a bot's psychological advice (and so, de-humanising the discussion too) is not lost on me.
Edit: I once had someone apply for a job and their written communication was pretty caustic. After rejecting their application, I wrote and explained how unprofessional I found their interactions, encouraging them to step back and reconsider how their communication appears from the other side.
To my great surprise, they wrote back and said they had never had anyone give them such feedback and they agreed with my assessment of their interactions. They just had never seen it before. They thanked me for the feedback.
Such interactions are exceedingly rare. But I sometimes offer unsolicited advice on the off chance that said advice can make a difference.
Taking that as a reason to not have those rules in the first place seems like a logical fallacy that intelligent people should not make.
Another option would be to leave both topics alone and go on with our lives, improving the product, fixing bugs, implementing new features, and generally giving customers a better product and shareholders more value, while respectfully agreeing to disagree on the issues of style.
That is why gofmt is so great. As the saying goes: gofmt’s style is nobody’s favorite, yet gofmt is everybody’s favorite.
It boggles me that anyone would argue against standardization, or believe that “just get hundreds of people to agree today and tomorrow and every future day” is a better solution.
With regards to your example, adding a comma to the final element should preserve multi-line. You just don’t know the formatting rules yet apparently
I find that people who argue against automatic linting and formatting tend to be the same that would argue incessantly about style. So much wasted energy, I want none of that.
Also, in your example above, if you put the comment on the line _above_ instead of inline the formatter will most likely do the right thing.
-- Ralph Waldo Emerson
By the way, you have the exact energy of someone who would argue about code style: a prima donna who quotes Emerson when confronted with disagreement.
100%. Almost all of my time burned navigating code is not hung up on stylistic conventions but on nasty services with inconsistent abstractions and patterns.
BUT, conventions and consistency make code easier to read and write, period. If you’re debating over single or double quotes that’s almost a fireable offense IMO.
Additionally, when you have a culture that delegates to tools as much as possible, the focus sharpens in a healthy way.
I feel for you both working with straw men day to day. I’ve worked mainly in Python for two decades and have neither seen such a thing nor considered, even to be a bastard, doing such a thing.
But one thing I bring to every team is this: “I don’t want to look at a file and say that is Tom’s code or that is your code. What I want to see is [project name] code.”
I, too, want to be an artist. For me, the flow of data through my work is the artistry, not the typography of the code.
I’m also not sure I understand the “ My place used pylint, flake8, black, ruff -- with hundreds of commits on every change”. These tools don’t add extra commits. You run them prior to your PR, get them aligned with the linting, and then commit the change you were already going to make. Thats 0 extra commits.
For someone ultimately arguing that there is too much effort spent on people’s coding styles, you are spending a lot of effort arguing about people’s coding styles. These tools are some of the most set it and forget it things around.
When you replace tool x with tool y, you need to fix your code, because these tools do not agree on what your code should look like, and what was acceptable for tool x simply isn't for tool y.
One of these changes I mentioned brought a massive reformatting of all code base, as the new tool failed 'import' statements unless they were in alphabetical order.
A single commit after a tool change. I don't see the problem.
At $WORK we have "code guardians" whose responsibility is do to this kind of migrations strategically in the background. The intent is that most other developers should not need to do any (or very little) extra work beyond the task they are actively working on.
I also need something to save me from my regexps, the verbose flag helps a lot. but what would be really nice is some sort of python subset that could compile to the state machine. I would also like composable expressions, that is, composable at the graph level not the string composition we are forced to use. And a pony, I would also like a pony.
As you can tell I am not a fan of APL, not because of what it can do but because of the super compressed syntax it adopts. see also: perl
This seems like a case where the tooling is compensating for unclear conventions. Collaboration tools are useful, but it may be more effective to strengthen the code specifications and documentation practices first, so intent lives in a predictable place instead of being scattered through implementation details.
Nobody even addressed the other issue you expressed about uncomprehensible code being fine for linters as long as it conforms to the style guide or low-hanging fruit of "don't use this deprecated method". Who knows, maybe soon enough someone will make a dev tool which runs per file, acknowledges your clever little piece of code and then yells at you that nowadays programming is a team sport called software engineering.
Personally it saddens me that I must agree with the other commenters even if I see where you're coming from. The mass produced, assembly-line with snazzy pipelines took over from the workshop in a wood shed style approach and code linters among other dev tools slot in much better in the former type of workflows than the latter. On one hand I want to be trusted to format my own code according to my intentions but it seems the majority has decided that this is a waste of time, needless bikeshedding and so on. I've begrudgingly gave in for the sake of collaboration which is more important to me in the grand scheme of things.
I guess the upside remains we're still free to do as we please on our own projects. Now to find similar thinking people huddling around Sublime Text shunning linters is not gonna be a cakewalk these days.
It is fairly new so not well known but it is what powers go fix and go vet under the hood. And I believe the Go team is currently working on making it possible for module authors to easily describe their own custom analysis passes that would run automatically when running go fix.
It is extremely easy to define your own analysis.Analyzer struct that describes your own static analysis pass. You get access to all sorts of useful information such as the AST, types, even SSA info and you can even compose the information between analyzers. Then you can easily compile it into a binary and run it by passing that binary to go fix with a command line flag. The go toolchain itself handles all the complex caching logic so that your analyzers run fast.
Since it is made by the go team itself and part of the toolchain it should slowly become the unified standard you are looking for. So hopefully golangci-lint and others should eventually all unify under this framework.
You can easily give it a go by telling some AI agent to write some Go Analysis analyzers and telling them to drive them with go fix. My Go projects tend to accumulate a bunch of these to enforce all sorts of rules deterministically and automatically instead of some imprecise markdown file.
Gofmt is great but it's still not very strict, the amount of times my colleagues have argued about formatting in Go is still too great, stuff like consts, types, funcs, methods order, struct initialziation newlines and other details that do matter, but they should be decided one and then applied everywhere like that.
Let's spread the word
Granted, this is a linter, not a formatter, but my larger point is I am glad that Python ecosystem evolved like it did recently.
Go can get there, but like I said, I think everyone is building some partial tools that solve some problems, but there is not that one player building that one great tool.
Compare that to Python or TypeScript which are Wild West languages without opinionated first-party tooling, and it’s clear why Ruff/Biome feel great.
You just wouldn’t get that same high with Go.
Gofmt is a great idea but it isn't strict enough for my taste. Go does not have any first party static analyzers, closest is Staticcheck which is even sponsored by Google themselves
(Honestly go's distributing itself has covered a lot of it)
Not sure what you're talking about.
That's not the fault of golangci-lint, it's just the concept of bringing together a bunch of different linters and keeping it fast is impossible. And the configuration is a bit wild too, because every linter obviously has their own decisions on how it wants to be configured.
Ruff can lint in seconds or even sub second.
Don't get me wrong, the new level of details coming from Ruff is much appreciated and a good thing :)
Generally gets you 90% there.
Good thing we have LLM:s that can do the tedious work of checking each case and applying local annotations or updating the config globally! If I was stuck doing this manually, I would have just gotten rid of ruff and went back to black+pylint.
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.
Not unlike that experience, I also saw coding agents spend lots of tokens trying to fix a benign issue, as well as doing the opposite - like disabling the tests !!! when they don't pass. :facepalm:
I grew to trust AI results in terms of overall correctness, but I still have hard time trusting their *judgement* on the *code quality*.
It's really annoying how many people think that if you enforce stupidly strict rules about formatting, more strict that those of Fortran in 70s, you'll automatically get good code.
I've seen companies that enable 100% of ruff rules, use several other linters, and enforce other rules (like every variable name should be at least 20 characters long to fully describe its purpose). And they have awful buggy unmaintainable code. But it is nicely formatted (although reading code where half of the screen estate is consumed by the variable name is a bit difficult) and has no "dreadful" `except Exception`. Or every mutable class attribute variable is annotated with `typing.ClassVar` (RUF012 - the most idiotic rule I've ever seen). Nevermind that it doesn't really stop anyone from changing value of that attribute. You must annotate it with `ClassVar`!
It's an idiotic cargo-cult.
Anyway I have definitely had linters like Ruff catch bugs. Probably the most common is the mutable default argument gotcha.
Also, mutable default argument is not a bug. It is a bug only if mutable default argument is mutated inside the body of a function/method. Which is almost never the case.
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
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
It is fully according to their versioning policy:
https://docs.astral.sh/ruff/versioning/
But also compliant with semver:
Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable.
https://semver.org/
(Maybe I misinterpreted your remark, but semver does not get hurt.)
What's really tiring is reading such facile "critiques", especially when they are not even applicable.