Top
Best
New

Posted by brianzelip 11 hours ago

Pyrefly: Python type checker and language server in Rust(pyrefly.org)
157 points | 117 commentspage 2
rasulkireev 10 hours ago|
This looks interesting. But I decided to go with ty in my projects, for the incremental approach.
codethief 9 hours ago|
How well does ty work these days? Last time I checked it still produced a lot of false positives and false negatives. (Which was very much expected, given its alpha/WIP status.)
rasulkireev 9 hours ago||
Honestly i barely use it, just started to give it a try by adding types where it makes most sense and running with pre-commit. No issues so far. But, again, I'm a very light user.
whalesalad 10 hours ago||
Python is starting to feel a bit like JavaScript circa 2014. Remember grunt, gulp, webpack, coffeescript, babel? Now we've got pyright, mypy, pyrefly, black, ruff, ty, flake8, poetry, uv...

I used to find this kind of tooling explosion exhausting (and back then with JS it truly was), but generally speaking it's a good sign that the community is hungry to push things forward. Choice is good, as long as we keep the Unix spirit alive: small, composable tools that play nicely together and can be interchanged.

parhamn 10 hours ago||
Interestingly besides typescript, javascript in 2025 is still super fragmeneted but by a bunch of well-polished tools that all do approximately the same thing. esbuild/vite(rollup)/trubopack(swc), prettier/biome/oxc, npm/bun/pnpm/yarn, bun/node/deno/worker-runtimes
koakuma-chan 8 hours ago|||
It's just people refusing to use new tools. Prettier is so much slower than any Rust formatter, it's painful. `yarn install` takes forever. Why not switch to Bun? It's 5 minutes.
koakuma-chan 8 hours ago||
I interviewed at one company a few months ago and they said they don't use TypeScript because the compiler gets in their way, jesus chirst.
pjmlp 8 hours ago||||
For me it is easy, Spring/Quarkus/ASP.NET, if it has to be a JavaScript framework, Next.js the way Vercel intended.

Anything whatever the FE team feels like using, and the less I know about it, the better.

mixmastamyk 6 hours ago||
Next.js has been called infuriating here recently: https://news.ycombinator.com/item?id=45099922
pjmlp 6 hours ago||
I know, search for my nickname and you'll get my point of view across several comments.
WesolyKubeczek 9 hours ago|||
The fact that you even didn't mention webpack, once a champion, is especially sad.
koakuma-chan 8 hours ago||
Doesn't Next.js still use webpack?
elsigh 5 hours ago||
It's turbopack time: https://nextjs.org/blog/next-16-beta
notatallshaw 8 hours ago|||
A lot of the tools you list here are composable, mypy checks type hints, black formats code, because of the purpose and design ethos of those two tools they would never think to merge.

So which is it that you want, to just reach for one tool or have tools that have specific design goals and then have to reach for many tools in a full workflow?

FWIW Astral's long term goal appears to be to just reach for one tool, hence why you can now do "uv format".

lenkite 8 hours ago|||
"There can be only one" - just need to wait till the deathmatches are over.
dev_l1x_be 4 hours ago|||
Is there any meaningful difference between TS and Python?
pjmlp 9 hours ago|||
Pity that is all looking like Rewrite in Rust looking for solution, instead of actually improving JIT tooling capabilities.

There is a reason us old timers mostly wait on the sidelines until the dust settles.

We have seen this movie already too many times.

strangescript 10 hours ago|||
"grunt, gulp, webpack, coffeescript, babel" --- except no one uses these anymore and they are dead outside of legacy software.

The problem with the python tooling is no one can get it right. There aren't clear winners for a lot of the tooling.

jon-wood 10 hours ago||
I think that's the point. Every now and then a language will have a small explosion of new tooling, and all you can really do is wait for it to blow over and see what tools people adopted afterwards, it feels like Python is going through a period like that at the moment.
IshKebab 5 hours ago||
It's not really that bad. Unless you want to be adventurous you need these tools:

* uv: project management, formatting

* Pyright: type checking

* Pylint: linting (this is probably optional though I would strongly recommend it). Ruff is an option but I don't think it is quite as comprehensive yet.

There are alternatives for those tools but they are pretty clearly the best options at the moment. There's nothing in uv's league, and the only alternatives in Pyright's league is BasedPyright. Hopefully Ty and Pyrefly will be good options in future but I don't think they're ready for production use just yet.

insane_dreamer 10 hours ago||
I've tried pyrefly, ty, pyright, and basedpyright, with a large complex code base written using PyCharm, and _none_ of them do as good a job as PyCharm, particularly in discovering more complex type inheritances. It's a pity because in other respects Zed (which relies on these) is a worthy competitor to PyCharm (and much faster!) -- but the endless squiggly lines because pyrefly can't figure out the type, is annoying (and turning off the warnings is unhelpful). Hopefully one of these will get up to PyCharm's level (my money would be on ty as Astral is kicking a* these days).
f311a 10 hours ago||
PyCharm has very basic type checking, though. It's not strict.

> pyrefly, ty, pyright, and basedpyright

All of them will complain 2-4x more about your code than PyCharm. I had more than 300 typing errors when I first opened my 20k LOC project in pyright that I wrote in Pycharm.

PyCharm works great when your code is not annotated. It infers types very well. But it won't complain in a lot of cases when your code is annotated.

Related reddit post https://old.reddit.com/r/Python/comments/1ajnikt/to_pycharm_...

olejorgenb 9 hours ago|||
I don't think these are designed to "discovering" complex type inheritances.

They are designed for code which are more or less fully typed, as opposed to PyCharm which cobbles together a bunch of heuristics to try to make sense out of untyped code. An admirable quest, but not one I'm personally interested in.

And their insistence on only supporting this approach drove my entire team away from using PyCharm.

(From shallowly observing notifications on the 20+ typehint related issues I'm subscribed to, they seem to have kinda turned around and working toward fully supporting the python type system finally - possibly by integrating with one of the third-party type-checkers)

giancarlostoro 10 hours ago|||
I think the 2nd best IDE for Python for me is Visual Studio proper, not Code. I know it sounds crazy, but Microsoft actually put some effort into their Python integration. Again, its a 2nd best, but that still says a lot about everyone else's editors.

Nowadays I'm finding myself using Zed a lot more, so maybe the story will be that all these nice Rust based tools become baked in giving it super powers for Python.

unmotivated-hmn 5 hours ago|||
That's interesting. In my experience basedpyright has been better than pyCharm at every turn. Yes, a lot more warnings but generally sensible. One specific thing I remember pissing me off: https://youtrack.jetbrains.com/issue/PY-58665 Still open 2 years later.
IshKebab 5 hours ago||
Are you talking about with code that has proper type annotations? As I recall PyCharm is about the best you can get if you are working with code that has no type annotations but ... you shouldn't be doing that in 2025! With type annotations I've found Pyright to be 100% rock solid.
zelphirkalt 11 hours ago||
Another one I recently discovered and that has a very active maintainer is "zuban" or zuban-ls. It has replaced jedi-language-server for me, and aims to replace mypy as well.
f311a 11 hours ago|
Yeah, there are now 3 competitors and they all written in Rust:

- zuban

- ty (from ruff team)

- pyrefly

One year ago, we had none of them, only slow options.

tialaramex 10 hours ago|||
Speed is one of those "Quantity has a quality all its own" things. We use very fast tools in a qualitatively different way, even though all that changed was how long it takes in seconds.

It is interesting that nobody was writing these tools in C or in C++. There are obvious ergonomic reasons, but perhaps also it matters that Rust cares a lot more about types than either of those languages.

kibwen 9 hours ago|||
> It is interesting that nobody was writing these tools in C or in C++

This one's easier to explain. People interested in tooling for a specific language probably want to write that tooling in that language (hence pip, poetry, mypy, jedi, etc). Normally that would be the end if it, if Python wasn't 10-100x slower than a natively compiled language. And going from Python to Rust is an order of magnitude easier than going from Python to C or Python to C++, because the compiler is so good at identifying silly mistakes. Rust is just a friendlier language.

f311a 10 hours ago|||
It's just very hard to write such systems in C/C++. Even all these Rust versions are segfaulting and panicking quite a lot. So many corner and edge cases that can be found in Python code, and the memory handling is also hard.

The author of Zuban started writing it back in 2020 or 2021, so it took him more than 4 years to complete it. And he is the author of Jedi, so he had prior experience already.

tialaramex 10 hours ago||
I get why they'd panic, but why have enough segfaults that you noticed? So, I went and read the code.

Zuban seems to have a bunch of scary "I'm not sure if this is correct" unsafe blocks, which to me would be a red flag. I mean, it's better that there's a comment expressing the doubt, but my experience is that if you're not sure whether it's correct, it's probably not correct.

estebank 6 hours ago||
While acknowledging the risk of causing a pile-on (which I don't want!), would it be possible to have a link to them or a description of what the unsafe blocks accomplish? I'm intrigued if they are for performance or API ergonomics, if they are due to limitations of the borrow checker, the stdlib or crate dependencies.

For anyone reaching for unsafe, there are in many cases either an existing API (split_at_mut comes to mind). For others, using zero-copy or bytemuck instead of unsafe is a good idea too.

None of that is to say "never write unsafe", unsafe existing is pretty much one of the reasons for Rust to be :)

tialaramex 5 hours ago||
I skimmed these, so this is nothing close to a survey, much less a comprehensive review of the software, however

For example in crates/zuban_python/src/file/diagnostics.rs:

"TODO this unsafe feels very wrong, because a bit lower we might modify the complex/ points."

or crates/zuban_python/src/database.rs:

"Points are guarded by specific logic and if they are overwritten by something that shouldn't it should not be that tragic."

I saw nothing where I was like "ZOMG this is definitely busted" but I definitely did not get the robust "Oh, I see now why this is correct" that I like from a good unsafe rationale comment, and these aren't tiny things like the small unsafe bit twiddling transmutes which are probably either actually correct or in any case will do what you expected at compile time and so any surprises are priced in without a rationale text.

jerrygenser 11 hours ago||||
Basedpyright is not rust but it's a fork of pyright with added features that are otherwise locked in vscode
f311a 11 hours ago|||
It's written in Typescript, which is a super weird choice.
wiseowise 8 hours ago|||
Wasn’t pyright made specifically for VSCode? That would explain TS.
f311a 8 hours ago||
Yes, but why they did not write it in a compiled language? Pyright is pretty slow in large code bases and takes a lot of RAM. Javascript can be faster than python in some cases, but Python is so easily extendable with C,C++, Cython, Rust. They could use Python with one of the compiled language.
IshKebab 5 hours ago||
Because they wanted it to be usable on the web, and I guess WASM wasn't where it is right now when they started.
huflungdung 10 hours ago|||
[dead]
jon-wood 10 hours ago||||
I'm sorry, I can't take seriously any piece of software which decided to prefix the previous version's name with "based". I'm aware this is a me problem.
wiseowise 8 hours ago|||
Definitely this. I commend author of BPyright, but clown (?) avatar, unknown identity of maintainer, and name of the fork rub me off wrong way.
cruffle_duffle 9 hours ago|||
Hah. I love the name. It implies that whatever the original “pyright” was doing wasn’t keepin’ it real. This new version, it’s “based” so it must be somehow more “real” and “grounded” and “legit”.

All I know is it is much more strict about stuff than pylance was.

Also a me problem!

drcongo 11 hours ago|||
It's also horrible for fasle positives unless your project happens to be the exact same setup as the maintainers' - I had to turn off the actual type checking on it. I've since moved wholesale to the Ty alpha and it feels a hell of a lot smarter.
JimDabell 11 hours ago||
It also inherits the unfortunate attitude of Pyright that it will warn against idiomatic Python (EAFP) in favour of non-idiomatic Python (LBYL):

https://github.com/microsoft/pyright/issues/1739

https://docs.python.org/3/glossary.html#term-EAFP

https://docs.python.org/3/glossary.html#term-LBYL

maleldil 8 hours ago|||
Sometimes dynamic Python idioms are incompatible with typed Python. I personally think that's fine, since I consider static typing a significant improvement overall.
JimDabell 8 hours ago||
This isn’t. They actually fixed that bug. Then they changed their minds and backed the fix back out again because they don’t think you should write Python that way:

> I think EAFP is a very unfortunate and ill-advised practice.

They want you to not write the idiomatic Python:

    try:
        foo = bar["baz"]["qux"]
        ...
    except KeyError:
        ...
…and instead write the non-idiomatic version:

    if "baz" in bar and "qux" in bar["baz"]:
        foo = bar["baz"]["qux"]
        ...
    else:
        ...
If this were a linter then I would accept that it is going to be opinionated. But this is not a linter, it’s a type checker. Their opinions about EAFP are irrelevant. That’s idiomatic Python.
IshKebab 5 hours ago||
Well I agree with them. The second code is clearly better. Exceptions should be used for error handling and if those keys are actually optional then you should explicitly check if they exist (or use something like `bar.get("baz")`).
kstrauser 9 hours ago||||
Eww, what? I hadn’t seen that before. Yikes, I hope the situation’s improved. I’d be butting into that continually.
arccy 11 hours ago|||
it'll be like python package managers and js web frameworks.... a new one every quarter
vovavili 10 hours ago||
uv works so well for the vast majority of scenarios that I don't really see a demand for further innovation in the Python package manager domain.
arccy 9 hours ago|||
yeah we all heard that story every 3 months with all the previous package managers. until there's adoption by an overwhelming majority of projects, it isn't really settled yet.
wiseowise 8 hours ago||
I’ve literally never heard that much buzz and excitement about Python tool before. And I’ve seen them all.

All of them had some big issue that prevented it from getting mainstream. Either it was slow, or didn’t work with existing workflow, or had complex configuration, or something that prevented gradual adoption.

uv is universally praised as the second coming Christ in Python world (and for a good reason). So no, I doubt there will be something else. Not only you need to be better than uv, you also need to have community momentum.

insane_dreamer 10 hours ago|||
it still needs to add handling for binaries (the one thing conda can do that uv can't)
flanked-evergl 10 hours ago||
Sadly, the question with both this and ty is: Does it support pydantic? If not, then it's not really helpful for many people, and right now AFAIK neither supports pydantic.

Pydantic is probably the problem here, but it is what it is.

ocamoss 9 hours ago||
Pyrefly actually does have (experimental) support for Pydantic! https://pyrefly.org/en/docs/pydantic/
flanked-evergl 8 hours ago||
Nice, did not know.
mixmastamyk 6 hours ago|||
Why would they need to support pydantic when it uses standard annotations? I tried it with ty yesterday and it flagged issues as expected.
flanked-evergl 1 hour ago||
Pydantic does some pretty strange stuff which works as expected but confuses the type checker unless you use the pydantic plugin. https://docs.pydantic.dev/latest/integrations/mypy/
phailhaus 9 hours ago||
Python's type system is the problem here, which cannot support even the native dataclass pattern and needs custom plugins written for each type checker.
kstrauser 9 hours ago|||
The type system’s alright. It just gets especially tricky when you’re trying to check code which won’t exist until you run it. For instance, suppose you wanted to load your own module from a database with something like

  foo = eval(result)
It can’t know what you’re going to load until it actually does it.

Things which lean heavily into metaprogramming, typically ORMs or things like Pydantic, fall into that category. I can’t hold that against the type system.

phailhaus 3 hours ago||
> I can’t hold that against the type system.

I think we should. Dataclasses have existed in Python for an extremely long time, and yet the type system doesn't support defining your own similar classes. Kwargs have also existed forever, but they forgot to support that and had to add TypedDict's much later. And it still doesn't properly support optional fields. There's a lot of stuff like this in the language which are unbelievably frustrating, because for some reason they implemented the syntax before implementing a typechecker. Everything has been hacked in ever since. I consider python's type system to be a lost cause, just hoping for someone to make the Typescript equivalent for Python.

flanked-evergl 52 minutes ago||
Dataclasses support optional fields and kwargs perfectly. Not sure what you are talking about.

I don't think you understand what Pydantic brings to the table or why people use it. It has lots more to do with serialization, complex validation and data mapping.

flanked-evergl 9 hours ago|||
I don't think this is really true, I think native data classes can do just about everything you need, it's just that you need some tooling around them to get the same as Pydantic offers. I'm pretty sure we are going to see better native dataclass support in Pydantic going forward.

Already there is some support in Pydantic for native dataclasses: https://docs.pydantic.dev/latest/concepts/dataclasses/

phailhaus 4 hours ago|||
There is no facility in the type system to express the idea that "whatever class attributes are defined, those are kwargs to the init function". That's hacked in using extra typechecker plugins. That's why we're sitting around talking about if a particular typechecker "supports pydantic", rather than it just working.
flanked-evergl 1 hour ago||
There is a way to indicate whatever class attributes are defined, those are kwargs to the init function. For one, you can use `kw_only` on the dataclass decorator [1], alternatively you can use the `kw_only` arg on the field function [2].

[1]: https://docs.python.org/3/library/dataclasses.html#dataclass...

[2]: https://docs.python.org/3/library/dataclasses.html#dataclass...

kitotik 9 hours ago|||
I have used native dataclasses with pydantic starting with v1.5 and it’s only improved with the the newer 2.x releases.

Aside from basic inheritance and complex nested types, the pydantic ‘TypeAdapter’ is awesome for simply validating native dataclasses. It’s a little slow, but everything pydantic is =)

rana762 11 hours ago|
[dead]