[HN Gopher] Pyrefly: Python type checker and language server in ...
       ___________________________________________________________________
        
       Pyrefly: Python type checker and language server in Rust
        
       Author : brianzelip
       Score  : 177 points
       Date   : 2025-10-14 12:33 UTC (10 hours ago)
        
 (HTM) web link (pyrefly.org)
 (TXT) w3m dump (pyrefly.org)
        
       | zelphirkalt wrote:
       | 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 wrote:
         | 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.
        
           | jerrygenser wrote:
           | Basedpyright is not rust but it's a fork of pyright with
           | added features that are otherwise locked in vscode
        
             | f311a wrote:
             | It's written in Typescript, which is a super weird choice.
        
               | wiseowise wrote:
               | Wasn't pyright made specifically for VSCode? That would
               | explain TS.
        
               | f311a wrote:
               | 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 wrote:
               | Because they wanted it to be usable on the web, and I
               | guess WASM wasn't where it is right now when they
               | started.
        
             | drcongo wrote:
             | 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 wrote:
               | 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
        
               | kstrauser wrote:
               | Eww, what? I hadn't seen that before. Yikes, I hope the
               | situation's improved. I'd be butting into that
               | continually.
        
               | maleldil wrote:
               | 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 wrote:
               | 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 wrote:
               | 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")`).
        
             | jon-wood wrote:
             | 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.
        
               | cruffle_duffle wrote:
               | 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!
        
               | wiseowise wrote:
               | Definitely this. I commend author of BPyright, but clown
               | (?) avatar, unknown identity of maintainer, and name of
               | the fork rub me off wrong way.
        
           | arccy wrote:
           | it'll be like python package managers and js web
           | frameworks.... a new one every quarter
        
             | vovavili wrote:
             | 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.
        
               | insane_dreamer wrote:
               | it still needs to add handling for binaries (the one
               | thing conda can do that uv can't)
        
               | arccy wrote:
               | 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 wrote:
               | 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.
        
           | tialaramex wrote:
           | 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.
        
             | f311a wrote:
             | 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 wrote:
               | 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 wrote:
               | 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 wrote:
               | 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.
        
             | kibwen wrote:
             | _> 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.
        
       | scosman wrote:
       | Anyone know how this compares to 'ty': a new typechecker from
       | Astral (uv/ruff team), also written in Rust and super fast. I had
       | been waiting on it to reach beta, but would love to move to
       | something faster than pyright sooner if possible.
        
         | emddudley wrote:
         | Pyrefly vs. ty: Comparing Python's Two New Rust-Based Type
         | Checkers (2025-05-27) https://blog.edward-
         | li.com/tech/comparing-pyrefly-vs-ty/
         | 
         | HN discussion of above:
         | https://news.ycombinator.com/item?id=44107655
         | 
         | How Well Do New Python Type Checkers Conform? A Deep Dive into
         | Ty, Pyrefly, and Zuban (2025-08-29)
         | https://sinon.github.io/future-python-type-checkers/
        
           | scosman wrote:
           | amazing reply. Thanks!
        
             | underdeserver wrote:
             | A note - the second link talks mostly about conformance
             | with a standard suite of tests, only briefly touching on
             | real-world use.
             | 
             | I would very much like to understand how good Zuban is
             | today compared to the competition.
        
       | pawelkobojek wrote:
       | I love the speed advantage of pyrefly over (based)pyright but so
       | far it doesn't seem to highlight as much as pyright does, for
       | example it doesn't catch unreachable code like this:
       | def fn(x: str):         if x is None:           x = "123"  #
       | pyright flags that as unreachable code, pyrefly does not
       | 
       | Autocomplete for modules also doesn't work for me yet:
       | import os       os.  # I'll get `ABC, `Any`, `AnyStr`,
       | `AnyStr_co`, `BinaryIO`, ...
       | 
       | Looking forward to have a fast language server for python though,
       | pyright is way too slow for large projects.
        
         | veber-alex wrote:
         | Yeah I have a similar experience with ty.
         | 
         | Looks like none of these new type checkers are ready yet.
        
           | f311a wrote:
           | Ty has autocomplete for imports, but it's hidden behind a
           | toggle right now. They are still working on it. They index
           | all the modules and functions, so you can just type the
           | function name and it will suggest the correct import and
           | insert it.
        
         | parhamn wrote:
         | Whats the expected error in the example you gave? That x can't
         | be none because it was received as a str?
        
           | boxed wrote:
           | Or that x is unused?
        
           | pawelkobojek wrote:
           | Exactly - something along the lines of "Statement is
           | unreachable".
        
           | robertlagrant wrote:
           | Yes, exactly. x would have to be str | None to be reachable.
        
           | wiz21c wrote:
           | isn't it perfectly valid to pass None to that function ? It's
           | not like python enforces types at runtime nor at compile
           | time. Right ?
        
             | Austizzle wrote:
             | It's not valid from a typing perspective, but python will
             | let you. If you want to disregard types though then none of
             | this matters anyway and you won't get much benefit from
             | these tools
        
             | yesb wrote:
             | Sure, it's valid python to do that. By that logic you could
             | also pass an int. But the context of this post is that
             | you're using a static type checker.
        
         | giancarlostoro wrote:
         | It's funny because in other typed languages a string can be
         | null because of string being a reference type as opposed to a
         | value type. I think Python type hints make more sense than C#
         | does in this respect, which gives me a chuckle (two of my
         | favorite languages and the untyped one makes more sense with
         | types). That said, not sure if you already have but I would add
         | a github issue / ticket reporting your issue to raise awareness
         | to the devs.
        
           | _flux wrote:
           | In _some_ other typed languages, that is. E.g. in C++, OCaml,
           | Haskell, F#, Kotlin, and Rust (a non-exhaustive list) you can
           | have non-nullable strings, and other objects.
        
             | asplake wrote:
             | It's worth noting that even though the runtime allows nulls
             | (i.e. None) anywhere, Python type checkers do distinguish
             | between optional and mandatory types.
        
           | Scarblac wrote:
           | All Python types are reference types. The reference to None
           | isn't included in the str type.
           | 
           | There's no way to get an actual null reference, afaik.
           | Variables always have _some_ value, possibly None.
           | 
           | (not sure what happens if you set a reference to null from C
           | - a crash, probably?)
        
           | kstrauser wrote:
           | A quibble: Python is strongly typed. It's not _un_ -typed in
           | any reasonable sense of the word. It's _dynamically_ typed,
           | though: type information is on objects, not on the names
           | referring to them.
        
           | seabrookmx wrote:
           | If you use the nullable types compiler option in C# (which
           | defaults to enabled for new projects) then you need to
           | declare you string as string? for it to be nullable :)
        
           | mixmastamyk wrote:
           | The billion dollar mistake.
        
         | kinto wrote:
         | Hey, Pyrefly developer here, thanks for trying us out! Thanks
         | for bearing with us with these issues you're experiencing while
         | we're still in alpha.
         | 
         | We're planning on adding unreachable code diagnostics soon
         | (github issue
         | [here](https://github.com/facebook/pyrefly/issues/1292)). These
         | come for free with Pyright so we don't want to regress
         | features.
         | 
         | I'm happy to help diagnose/fix your autocomplete issue: it
         | should work on modules. If you want to provide details here, on
         | [discord](https://discord.gg/Cf7mFQtW7W), or as a Github issue
         | (github/discord preferred) we'll fix it for you + anyone else
         | with the problem.
        
           | pawelkobojek wrote:
           | I absolutely understand this is still alpha so I kind of
           | assumed these are expected. Frankly, that's why I haven't
           | submitted an issue -- I assumed it's going to be fixed at
           | some point. I'll go ahead and make an issue on GitHub,
           | thanks.
        
       | whalesalad wrote:
       | 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.
        
         | strangescript wrote:
         | "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 wrote:
           | 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.
        
         | parhamn wrote:
         | 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
        
           | WesolyKubeczek wrote:
           | The fact that you even didn't mention webpack, once a
           | champion, is especially sad.
        
             | koakuma-chan wrote:
             | Doesn't Next.js still use webpack?
        
               | elsigh wrote:
               | It's turbopack time: https://nextjs.org/blog/next-16-beta
        
           | koakuma-chan wrote:
           | 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 wrote:
             | 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 wrote:
           | 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 wrote:
             | Next.js has been called infuriating here recently:
             | https://news.ycombinator.com/item?id=45099922
        
               | pjmlp wrote:
               | I know, search for my nickname and you'll get my point of
               | view across several comments.
        
         | pjmlp wrote:
         | 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.
        
         | notatallshaw wrote:
         | 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 wrote:
         | "There can be only one" - just need to wait till the
         | deathmatches are over.
        
         | IshKebab wrote:
         | 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.
        
         | dev_l1x_be wrote:
         | Is there any meaningful difference between TS and Python?
        
       | bobajeff wrote:
       | Though, I'm happy with basedpyright and usually disable type
       | checking. It's great to have so many options in language servers
       | for Python now that pylance is locked to vscode.
        
       | brianzelip wrote:
       | See the recent Talk Python podcast featuring some Pyrefly team
       | members, https://talkpython.fm/episodes/show/523/pyrefly-fast-
       | ide-fri...
        
       | insane_dreamer wrote:
       | 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).
        
         | giancarlostoro wrote:
         | 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.
        
         | f311a wrote:
         | 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 wrote:
         | 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)
        
         | IshKebab wrote:
         | 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.
        
         | unmotivated-hmn wrote:
         | 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.
        
       | rasulkireev wrote:
       | This looks interesting. But I decided to go with ty in my
       | projects, for the incremental approach.
        
         | codethief wrote:
         | 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 wrote:
           | 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.
        
       | flanked-evergl wrote:
       | 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.
        
         | phailhaus wrote:
         | 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 wrote:
           | 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 wrote:
             | > 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 wrote:
           | 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/
        
             | kitotik wrote:
             | 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 =)
        
             | phailhaus wrote:
             | 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 wrote:
               | 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#d
               | ataclass...
               | 
               | [2]: https://docs.python.org/3/library/dataclasses.html#d
               | ataclass...
        
         | ocamoss wrote:
         | Pyrefly actually does have (experimental) support for Pydantic!
         | https://pyrefly.org/en/docs/pydantic/
        
           | flanked-evergl wrote:
           | Nice, did not know.
        
         | mixmastamyk wrote:
         | 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 wrote:
           | 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/
        
       | sirfz wrote:
       | I've decided to to try out Pyrefly, Ty and Zuban for their
       | language server features (type checking disabled where possible)
       | last week and found that Zuban is the fastest (but unfortunately
       | doesn't currently have the option to disable type checking). Ty
       | comes next and Pyrefly was surprisingly slow to load (have to
       | wait a few seconds before I can goto definition for example).
       | 
       | They all lack certain features vs basedpyright (what I was using)
       | such as auto imports (Ty has experimental support), showing
       | signature/doc when selecting autocomplete options (I think Ty
       | does have this one) and some other features that I can't
       | remember.
       | 
       | One feature that always existed in Jedi (and now also Zuban) is
       | "goto declaration" in Python. It allowed me to goto the "import"
       | instead of the original definition of a function/class which I'm
       | surprised either isn't supported at all (pyright?) or would just
       | do the same thing as "goto definition" (Ty), seems like an
       | obvious oversight imho.
       | 
       | Edit: Also, I wish all these new tools give more importance to
       | such IDE features as much as they do for type checking.
        
         | jswny wrote:
         | At least for Ty, not sure about the others, it is explicitly
         | for type checking, exposed as an LSP. It's not trying to
         | compete with full LSP implementations. Most modern editors let
         | you combine multiple LSPs, you shouldn't think of them as using
         | only one at a time
        
           | ehsanu1 wrote:
           | Do you assign different responsibilities to different LSP
           | servers when there multiple I suppose?
        
           | charliermarsh wrote:
           | We actually do want ty to be a first-class LSP (i.e., a
           | complete alternative to Pylance and others), and it already
           | supports nearly all of the features you'd expect. I use it as
           | my primary LSP today in lieu of Pylance!
        
           | sirfz wrote:
           | I understand your confusion because at first look it seems
           | like it's just a type checker (same issue with pyrefly and
           | zuban) hence my comment about bringing forward the fact it's
           | a fully featured lsp
        
         | screye wrote:
         | If ruff & uv have proved anything, it's that a tool that's
         | effortless, a net-positive and fast will get adopted.
         | 
         | New typecheckers don't need to be perfect. They need to be good
         | enough, easy to integrate and have low false positives. Sure,
         | they will improve with time, but if feels like a pain then no
         | one will pick it up. Python users are famously averse to tools
         | that slow down their dev cycles, even if it means better long
         | term stability
         | 
         | BasedPyright is popular because it comes built-in with Cursor
         | and disappears into the background. I have a positive bias
         | towards Astral figuring it out given their track record. But,
         | none of these tools have reached the point of effortlessness
         | just yet.
        
           | phplovesong wrote:
           | If typechecking is tongue on cheek, why even bother?
        
             | atoav wrote:
             | If car crashes still kill people, why wear safety belts?
        
               | tremon wrote:
               | I don't think that's an accurate metaphor. Seatbelts are
               | expressly a runtime solution to car crashes, whereas
               | Python's type checking is a) only done during development
               | (not even during build), and b) completely reliant on
               | third-party tools.
               | 
               | If you're looking for a car analogy, I would suggest
               | comparing Python type checking to installing speed
               | cameras on the factory floor.
        
               | ObscureScience wrote:
               | The analogy would be mandatory inspections of certain
               | components or manufacturing processes to see that rules
               | and specs are followed while assembling.
        
             | coldtea wrote:
             | Because "all or nothing" is a bad idea.
        
           | alfalfasprout wrote:
           | > New typecheckers don't need to be perfect. They need to be
           | good enough, easy to integrate and have low false positives.
           | Sure, they will improve with time, but if feels like a pain
           | then no one will pick it up. Python users are famously averse
           | to tools that slow down their dev cycles, even if it means
           | better long term stability
           | 
           | I really don't agree. Sure, they don't need to be perfect but
           | also keep in mind many codebases have already standardized on
           | something like (based)pyright or mypy. So there's a migration
           | cost. If your analysis has a lot of false positives or misses
           | a lot of what those type checkers miss then there's little
           | incentive to migrate. Sure, ty and pyrefly are much faster,
           | but at the end of the day speed is only one consideration for
           | a type checker.
        
             | fragmede wrote:
             | No, I'm pretty sure they need to be perfect. If the tool's
             | telling me bad information about types, first I'm going to
             | lose a stupid amount of time debugging to that wrong info,
             | and then swear off the tool forever after I realize it was
             | the tool that was wrong.
        
               | dmurray wrote:
               | Type checking in Python involves guessing. Take a program
               | like
               | 
               | x = [3]
               | 
               | Should the type checker guess that the type of x is
               | list[Any], or list[int], or list[Literal[3]], or
               | something else? Libraries you depend on will pose more
               | difficult versions of this question.
               | 
               | So it's not possible to expect the tool to be "perfect",
               | whatever that means - usually people think of it as
               | meaning it allows all code that they think is idiomatic
               | and reasonable, and disallows all code that could raise a
               | TypeError at runtime. You can only expect the tool to be
               | reasonably good and perhaps to have an opinionated design
               | that matches the way you would like to write Python.
        
               | fragmede wrote:
               | Arguably it's the job of a linter and not a type checker,
               | but if your code just assigns random things to random
               | variables that never get used again, I hope _something_
               | would point that out to you before it passes code review
               | and merged to main, ideally before it even gets sent for
               | review.
               | 
               | Ignoring the question of why there's some random
               | assignment to x in the first place, where are its type
               | hints? Those were added starting with Python 3.5 via PEP
               | 484 just over 10 years ago and have been added to since
               | then. If our goal is maintainable code at scale, the
               | first thing I'd expect of a type checker is for it to
               | communicate with the user, stating that a) the variable
               | in file foo.py on line 43 is missing a type hint and
               | couldn't be guessed with confidence, and that it's just
               | gonna guess it's a list[int]. For bonus points, the tool
               | could run in interactive mode and ask the user directly.
               | But even without a hint, assuming the variable actually
               | is used later, how does it get used?
               | 
               | It seems like you'd just start with the most strict
               | interpretation, list[Literal[3]], and relax it as it gets
               | used. If it gets fed into a function that doesn't have
               | hints and can't be introspected for whatever reason,
               | relax it to list[int] and then further relax it to
               | list[Any] as necessary. Then depending on the mode the
               | user configured the tool to run in, print nothing, or a
               | warning, or error out or ask the user what to do if
               | running interactively. Some of the config options could
               | be strict, tolerant, and loose. Or maybe enforcing,
               | permissive, and loose. Whatever color we want this bike
               | shed to be.
               | 
               | More advanced tools let the user configure individual
               | issues and their corresponding levels, but that may be
               | considered too many options to give the user,
               | overwhelming the user who then doesn't use the tool.
               | 
               | As far as perfect typing goes, I mean, yeah, ideally,
               | after satisfying the type checker in strict mode, which
               | means no types need to be guessed at, as all variables
               | and other locations without type annotations that need
               | them were reported, or even annotated interactively, or
               | if we're real fancy, automatically with a comment. IMO
               | programs should feel free to edit code directly (as a
               | non-default option) That would mean the program could not
               | throw an an _uncaught_ TypeError, unexpectedly. That 's a
               | lot to ask of a dynamically strongly typed language, but
               | I'd settle for it never being utterly wrong.
               | 
               | What that means is if the type checker says the function
               | is returning a string, but of the 200 calls to that
               | function, the type checker throws an error and says ten
               | of those callsites expect it to return a dict, all I'm
               | saying is this hypothetical type checker had better be
               | right about that. Nothing worse than losing hours rooting
               | around in the code looking for something that isn't
               | actually there (or an errant semicolon, but this isn't C)
        
             | nickpsecurity wrote:
             | Also, in the past, many tools were dumped by users for too
             | many false positives. Tools like Astree and RV-Match got
             | adoption by having no or low false positives.
        
             | screye wrote:
             | Think of it this way. There are 2 groups. Group 1 has has
             | avoided typecheckers because they're a PITA and group 2 has
             | configured mypy/pyright despite the devx pain. Group 1 is a
             | lot bigger than group 2. Group 2 is more lucrative per unit
             | than group 1.
             | 
             | With enough time, ty and pyrefly will approach perfectness.
             | If they're easy enough to use today, group 1 should be able
             | to adopt them without any extra pain. (some typechecker is
             | better than no typechecker). This gives them momentum. In
             | couple of years, ty/pyrefly may finally be better than
             | mypy/pyright. Then, Group 2 can start their ports.
             | 
             | This way, no one misses out. Group 2 still gets their
             | perfect typechecker, just not immediately. But in that
             | time, Group 1 is getting familiar with using typecheckers
             | and their sheer size helps build institutional momentum
             | towards typecheckers as an essential piece of any python
             | dev flow.
             | 
             | If A. 'certain class of python problems are permanently
             | solved by typecheckers' and B. 'every python user has some
             | typechecker' become true, then that opens a lot of doors.
             | Today, B is a harder problem than A. I'm guessing that
             | compiled/JIT python will be the next frontier once python
             | typing is solved. Wide typechecker adoption is a blocking
             | requirement for that door to be opened.
        
         | kinto wrote:
         | Hey, Pyrefly developer here, thanks for trying us out!
         | 
         | We're dedicated to providing a great IDE experience, though it
         | does take some time. Please bother us on github / our discord
         | if you have features you want - bug reports / community asks
         | are our biggest priority.
         | 
         | - auto import is implemented in Pyrefly: it uses your
         | pyrefly.toml project structure or falls back to your VSCode
         | workspace (up to the first 2500 files). we're happy to fix it
         | for your situation if you want to provide a reproduction
         | 
         | - signature/doc when selecting autocomplete options is a known
         | bug [here](https://github.com/facebook/pyrefly/issues/1090)
         | 
         | - go to declaration: I've created an issue for that
         | [here](https://github.com/facebook/pyrefly/issues/1291), it
         | should be quick.
         | 
         | - speed: by far the biggest issue. your problem is likely
         | related to
         | [this](https://github.com/facebook/pyrefly/issues/360) but we
         | need more information to speed it up. we're happy to work with
         | you to to improve this if you're willing to provide a project
         | structure
        
           | sirfz wrote:
           | Hi, thanks for the links and for opening the goto declaration
           | issue (that's awesome). I will try to dedicate more time into
           | my setup and provide feedback where possible. Looking forward
           | for all the new updates!
        
       | sheepscreek wrote:
       | I much prefer the rigidity of pyrefly. It enforces a standard
       | expectation across the code base, which will lead to less
       | surprises IMO.
        
         | whilenot-dev wrote:
         | The weird Literal promotion makes pyrefly unusable for me,
         | except if I'd avoid Literal types:
         | https://github.com/facebook/pyrefly/issues/742
        
       | eqvinox wrote:
       | Hm, it doesn't seem to be dealing particularly well with imported
       | packages that don't have type annotations. Seeing a bunch of "has
       | no attribute" warnings. Some of the "substitute" annotations also
       | seem to be wrong (e.g. asyncio in CPython has no annotations [in
       | my installed version], but it's pulling some in from _somewhere_
       | and they 're not quite right...) It's also getting confused about
       | lists and tuples in __slots__.
        
         | notatallshaw wrote:
         | The standard library does not directly include type hints, they
         | are stored in typeshed: https://github.com/python/typeshed
         | 
         | You can take a look yourself if you think some of them are
         | wrong:
         | https://github.com/python/typeshed/tree/main/stdlib/asyncio
         | 
         | The advantage is type hints can be fixed without needing to
         | release a new version of Python. The disadvantage is there's a
         | lot of code in the standard library that doesn't really
         | consider how to represent it with type hints, and it can be
         | really tricky and not always possible.
         | 
         | I'm surprised to see so many people moving to pyrefly, ty, and
         | zuban so quickly. I was going to wait until some time in 2026
         | to see which has matured to the point I find useful, I guess
         | some users really find existing solutions actually unworkable.
        
           | eqvinox wrote:
           | > You can take a look yourself if you think some of them are
           | wrong:
           | https://github.com/python/typeshed/tree/main/stdlib/asyncio
           | 
           | Hmm. Presumably mypy and pyrefly use the same ones, but then
           | I don't understand why pyrefly is complaining and mypy isn't:
           | ERROR Argument `Future[list[BaseException | Any]]` is not
           | assignable to parameter `future` with type
           | `Awaitable[tuple[Any]]` in function
           | `asyncio.events.AbstractEventLoop.run_until_complete` [bad-
           | argument-type]          --> xxx/xxx.py:513:33           |
           | 513 |         loop.run_until_complete(tasks.gather(*x,
           | return_exceptions=True))           |
           | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
           | 
           | The definition in typeshed is this:                 def
           | run_until_complete(self, future: _AwaitableLike[_T]) -> _T:
           | ...
           | 
           | ...where is it even puling "tuple[Any]" from...
           | 
           | (tbh this is rather insignificant compared to the noise from
           | external packages without type annotations, or with
           | incomplete ones... pyrefly's inferences at the existence of
           | attributes and their types are extremely conservative...)
        
             | notatallshaw wrote:
             | > Hmm. Presumably mypy and pyrefly use the same ones, but
             | then I don't understand why pyrefly is complaining and mypy
             | isn't:
             | 
             | > ...where is it even puling "tuple[Any]" from...
             | 
             | Perhaps it's a bug in pyrefly, perhaps mypy or pyrefly is
             | able to infer something about the types that the other
             | isn't. I would strongly suggest checking their issues page,
             | and if not seeing a report already report it yourself.
             | 
             | While there is an ongoing push to more consistently
             | document the typing spec: https://typing.python.org/. It
             | does not actually cover all the things you can infer from
             | type hints, and different type hint checkers have decided
             | to take different design choices compared to mypy and will
             | produce different errors even in the most ideal situation.
             | 
             | This is one of the reasons why I am waiting for these
             | libraries to mature a little more.
        
               | eqvinox wrote:
               | > it does not actually cover what rules you can check or
               | infer from type hints
               | 
               | Indeed this is the cause of maybe 30% of the warnings I'm
               | seeing... items being added to lists or dicts in some
               | place (or something else making it infer a container
               | type), and pyrefly then refusing other types getting
               | added elsewhere. The most "egregious" one I saw was:
               | def something(x: list[str]) -> str:           foo = []
               | for i in x:               foo.append(i)           return
               | "".join(foo)
               | 
               | Where it complains:                 ERROR Argument `str`
               | is not assignable to parameter `object` with type
               | `LiteralString` in function `list.append` [bad-argument-
               | type]        --> test.py:4:20       4 |
               | foo.append(i)
               | 
               | Edit: now that I have posted it, this might actually be a
               | bug in the .join type annotation... or something
               | 
               | Edit: nah, it's the loop (and the LiteralString variant
               | of .join is just the first overload listed in the type
               | hints)... https://github.com/facebook/pyrefly/issues/1107
               | - this is kinda important, I don't think I can use it
               | before this is improved :/
        
               | notatallshaw wrote:
               | I assume in your example if you update the foo
               | declaration to the following it solves the complaint:
               | foo: list[str] = []
               | 
               | If so this a type checking design choice:
               | * What can I infer from an empty collection declaration?
               | * What do I allow further down the code to update
               | inferences further up the code?
               | 
               | I don't know Pyrefly's philosophy here, but I _assume_ it
               | 's guided by opinionated coding guidelines inside Meta,
               | not what is perhaps the easiest for users to understand.
        
               | eqvinox wrote:
               | Yes, annotating the type explicitly fixes it; but tbh I'd
               | consider that type annotation "unnecessary/distracting
               | code litter".
               | 
               | As far as their philosophy goes, it's an open issue
               | they're working on, so their philosophy seems to agree
               | this particular pattern should work :)
        
               | notatallshaw wrote:
               | I agree, but as a type checker it is a subjective choice,
               | whether to be explicit and not make assumptions or
               | whether to infer from certain certain patterns as
               | probably correct and not be noisy to the user. Very glad
               | to see they plan to fix this.
        
       | Too wrote:
       | Anyone struggling with slow mypy should really update to latest
       | version. This years releases has focused on performance and it
       | has payed off. Add the boost from latest Python versions to that
       | and you can see 50% type checking improvements. Still far from a
       | rust based tool, always something, all without changing your tool
       | chain.
        
       | natdempk wrote:
       | Anyone here know what the ideal/best setup is for typechecking +
       | LSPing Django these days?
       | 
       | I've been leaning on pyright + django-stubs, but wondering if I'm
       | missing something better with fewer gaps and pain points.
        
         | kinto wrote:
         | (Pyrefly dev here)
         | 
         | We've seen a lot of people have success with the mypy plugin +
         | django-stubs.
         | 
         | Full out-of-the-box support is being actively worked on in
         | Pyrefly: we will have specialized django enum support in the
         | next release and we expect real experimental support by the end
         | of the year. At that time we'll likely post a blog post to
         | announce it [here](https://pyrefly.org/blog/).
        
         | nprateem wrote:
         | Just started trying ty with django-types. I got the models
         | typed in a day or so. Still wading through the other 200+
         | errors in my codebase. But it's fast at least.
        
       | cadamsdotcom wrote:
       | Been using pyrefly since July on a big python build.
       | 
       | It has some things it can't pick up on - no return after a catch
       | block when all code paths are covered for example - but it's
       | speedy and the error messages are good enough for Claude to
       | understand and ignore or resolve.
       | 
       | Recommended!
        
       ___________________________________________________________________
       (page generated 2025-10-14 23:00 UTC)