Hacker News new | past | comments | ask | show | jobs | submit

Ruff v0.16.0 – Significant new updates – 413 default rules up from 59

https://astral.sh/blog/ruff-v0.16.0
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.

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...

Great to see ruff, ty and uv being actively developed, even after Astral was acquired by OpenAI.
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.

The point of the "grammar nazi" bots is to focus on the actual problems: if a bot is deciding about linting, you don't have to waste brain power to discuss it in PRs.

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.

In my previous place, discussions on coding style were forbidden in PRs. It worked just fine.

Edit: one could also use single or double quotes in strings, and it didn't anger the grammar nazi bots as there were none.

Which gets rid of the discussion, but not the problem coding style rules are supposed to fix: Code looks the same, regardless of who wrote it. That's the whole point of code style guidelines like that as there's no functional reason for them.

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.

loading story #49059739
loading story #49057299
loading story #49059137
loading story #49058558
loading story #49057538
loading story #49058427
loading story #49057144
loading story #49059494
loading story #49059119
I've never had discussions about code formatting in PRs, this seems like a made up problem or something that predates my career.
loading story #49059450
loading story #49056899
loading story #49056902
loading story #49056957
loading story #49057673
loading story #49058601
loading story #49056802
loading story #49056927
loading story #49057286
loading story #49057304
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
It does and it is even better. It is called the Go Analysis Framework (https://pkg.go.dev/golang.org/x/tools/go/analysis).

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.

That sounds amazing! I do hope golangci-lint and the likes pick it up, I'm a big fan of the strict by default approach that Ruff and other linters have taken.

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.

Oh wow, not so long ago the sentiment was exactly opposite. Python community was struggling with tools and everyone wished to have `gofmt` for Python.

Granted, this is a linter, not a formatter, but my larger point is I am glad that Python ecosystem evolved like it did recently.

Yeah, that's how much Astral changed python. UV and Ruff are amazing tools.

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.

Ruff is actually a formatter too
I’m not entirely sure what you mean by a fragmented ecosystem? Go has first-party formatting and linting and the language is deliberately restricted to ensure it is written in a certain way, even when written by complete novices.

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.

Go has a good start for that, but It's not enough for me.

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

go vet, plus all the ones in gopls?
{"deleted":true,"id":49056952,"parent":49056727,"time":1785064902,"type":"comment"}
What? I feel go has one of the best language tooling out there without requiring a bully ide to do stuff. golangci-lint is quite comprehensive. What do you miss otherwise?

(Honestly go's distributing itself has covered a lot of it)

golangci-lint is good, but you have to glue together a bunch of linters, and it adds up. You can easily get runtimes of several minutes, there are caches etc but the main problem is that golangci-lint doesn't own the lints, so it will never be as fast as something like Ruff.
Golang-ci exists for a while and everyone is using it.

Not sure what you're talking about.

loading story #49057309
feel free to build it
I have actually tried. But I'm not very knowledgable in the area, so it's more LLM slop than my good ideas. And I'm not sure I have the energy and passion to maintain it long term.

https://github.com/gempir/strider

It's definitely possible, if Google would put like one or two smart minds on the problem full time they could easily solve this problem and make the ecosystem so much stronger. But I'm guessing they already have something like this in-house and no interest in open sourcing it.

Good news. enabling 413 rules by default means most projects get useful linting without touching the config at all!
loading story #49056618
loading story #49058869
loading story #49057472
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.
loading story #49056554
413 rules and somehow every codebase I join still has the same three arguments about import sorting
{"deleted":true,"id":49056691,"parent":49056112,"time":1785062542,"type":"comment"}
Looks like it's recommended to use zero-config now, which is great! My new .ruff.toml is just:

  line-length = 300
loading story #49061166
loading story #49057551
ran 0.16 on a file with no config, it flags unsorted imports and `except Exception` by default now

  Ruff v0.16 has a small number of breaking changes
Why. Why must my poor semver be hurt so!

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

loading story #49056924
loading story #49056744
{"deleted":true,"id":49056955,"parent":49056112,"time":1785064920,"type":"comment"}
I find it somehow interesting that a tool for Python is written in Rust.
loading story #49057302
loading story #49058335
loading story #49059110
loading story #49058523
loading story #49058274