I will be a happy clam when it can check `Protocol`s.
> What is the difference from Ruff?
Ruff, like pylyzer, is a static code analysis tool for Python written in Rust, but Ruff is a linter and pylyzer is a type checker & language server. pylyzer does not perform linting, and Ruff does not perform type checking.
I wonder if a better use of time would be to just focus on making mypy faster. We already have too many tools, and it's often better to just focus on making the existing stuff better rather than developing a new tool (relevant XKCD [1]). There's gotta be ways to make mypy faster, even if it takes some breaking changes.
One consideration there would probably be how many committal decisions mypy has made. One of the main reasons a new tool might be better than an old one is that it can be built fresh, with all the lessons learned but (essentially) none of the baggage of bad design decisions.
Another thing I've also weighed is that developing any kind of static analysis tool whose source code is not in the language it analyzes (such as Ruff) immediately blocks you off from a large portion of maintainers. Your maintainers cannot be your end users unless they work with both Python and Rust. While Python is definitely one or more magnitudes slower than Rust, I can't imagine that mypy is at the point where the language choice itself is the only bottleneck.
In the interim, check out basedpyright [1]. It's an up-to-date fork of pyright with some improvements, less arbitrary limitations, and does not require npm to install.
I was thrilled to learn about basedpyright recently. It does a great job of filling in some of the missing parts of pyright that MS deemed a better fit for pylance – which is a vs code exclusive.
Easy to install with pipx.
As with pyright, I’ve noticed `--createstubs` helps against slowness when working in modules that import large untyped packages.
Which is a very sensible decision given that VSCode is Typescript, and also it means it can run on the web. Also Typescript is a much nicer and faster language than Python.
This unfortunately has `docstring-to-markdown` as one of its dependencies, which is a pain to install behind corporate pip proxies because it's under GPL.
Hopefully it can be used easily as a library. I have multiple use cases for programmatically operating on typed ASTs. MyPy plugins are very limited and most other analyzers have no such extensibility.
> Limitations [...] pylyzer (= Erg's type system) has its own type declarations for the Python standard APIs
I haven't actually tried it out, but have done a bit of research in the name of scoping a competing product, and my verdict is that it's probably too immature to be worth production usage. It also makes the design decision to delegate most of the actual hard work (the type checking) to the type checker of Erg, a strongly typed superset of Python, which leaves a lot of decisions and agency out of the purview of Pylyzer itself. There will always be limitations that can only be resolved upstream.
Granted, maybe there's value in this just being a wrapper, and it's best to just deduplicate the work. However, it just sits a little wrong to me that it's not type checking Python, it's doing a transpilation step of sorts and type checking that.
"Ruff, like pylyzer, is a static code analysis tool for Python written in Rust, but Ruff is a linter and pylyzer is a type checker & language server. pylyzer does not perform linting, and Ruff does not perform type checking."
Looking through the code, Pylyzer seems to be a thin wrapper around Erg [1]. To typecheck, it converts your Python AST to an Erg AST, then runs its through the Erg typechecker and returns the errors.
Faster typechecking for Python is very much needed. But this project seems like it was built in a hackathon -- it is not a true standalone typechecker.
I dug into Pylyzer a few weeks back when scoping out alternatives for faster type checkers, as we have a lot of brittle Python code that we are gradually migrating in at $DAYJOB. I got the idea in my head to basically build mypy but in Rust, similar to what Ruff has done.
My research agrees with your assessment. While I'm sure it's a lot faster (I think the README implies it's one or two magnitudes faster) it just doesn't sit right to me that it's essentially just transpiles to Erg and delegates the actual hard work to the Erg typechecker. This works, but I feel like it fundamentally limits what Pylyzer is capable of, and how much control it really has over the underlying type checking process, as to it, the Erg type checker is essentially a black box.
It's a wrapper (a non-trivial one, to its credit -- especially considering everything is a wrapper if you look at it the right way -- but still a wrapper) rather than an actual full solution.
There's also really only one maintainer (who seems to do a decent job, but I don't seem to recall much more than just bug fixes). Makes me hesitant to really depend on it sticking around long-term or having features that meaningfully progress in the future.
26 comments
[ 1.9 ms ] story [ 71.8 ms ] thread> What is the difference from Ruff? Ruff, like pylyzer, is a static code analysis tool for Python written in Rust, but Ruff is a linter and pylyzer is a type checker & language server. pylyzer does not perform linting, and Ruff does not perform type checking.
One consideration there would probably be how many committal decisions mypy has made. One of the main reasons a new tool might be better than an old one is that it can be built fresh, with all the lessons learned but (essentially) none of the baggage of bad design decisions.
Another thing I've also weighed is that developing any kind of static analysis tool whose source code is not in the language it analyzes (such as Ruff) immediately blocks you off from a large portion of maintainers. Your maintainers cannot be your end users unless they work with both Python and Rust. While Python is definitely one or more magnitudes slower than Rust, I can't imagine that mypy is at the point where the language choice itself is the only bottleneck.
[1] https://xkcd.com/927/
Yes, pyright is fast enough, 99% of the time. But the install story, requiring npm etc, is a bit of a pain.
A rust based version with similar install ease as ruff would be great.
Additionally, if it is a lot faster, I think it should unlock more possibilities for eager search to improve the lsp.
Quite often the pyright lsp doesn't find auto imports - there's just too much many places to search.
I'm following this with great interest!
[1] https://github.com/detachhead/basedpyright
Easy to install with pipx.
As with pyright, I’ve noticed `--createstubs` helps against slowness when working in modules that import large untyped packages.
But it does cause some awkwardness.
https://github.com/python-lsp/python-lsp-server
> Limitations [...] pylyzer (= Erg's type system) has its own type declarations for the Python standard APIs
I wonder why https://github.com/python/typeshed could not be used
Now that I have ruff giving me a bunch of instant feedback, pyright has become a bit of a distraction due to the lag.
Granted, maybe there's value in this just being a wrapper, and it's best to just deduplicate the work. However, it just sits a little wrong to me that it's not type checking Python, it's doing a transpilation step of sorts and type checking that.
"Ruff, like pylyzer, is a static code analysis tool for Python written in Rust, but Ruff is a linter and pylyzer is a type checker & language server. pylyzer does not perform linting, and Ruff does not perform type checking."
Faster typechecking for Python is very much needed. But this project seems like it was built in a hackathon -- it is not a true standalone typechecker.
[1] https://github.com/erg-lang/erg
My research agrees with your assessment. While I'm sure it's a lot faster (I think the README implies it's one or two magnitudes faster) it just doesn't sit right to me that it's essentially just transpiles to Erg and delegates the actual hard work to the Erg typechecker. This works, but I feel like it fundamentally limits what Pylyzer is capable of, and how much control it really has over the underlying type checking process, as to it, the Erg type checker is essentially a black box.
It's a wrapper (a non-trivial one, to its credit -- especially considering everything is a wrapper if you look at it the right way -- but still a wrapper) rather than an actual full solution.
There's also really only one maintainer (who seems to do a decent job, but I don't seem to recall much more than just bug fixes). Makes me hesitant to really depend on it sticking around long-term or having features that meaningfully progress in the future.
https://github.com/facebook/pyre-check
If you're already making that then building a type checker wrapper on top of it makes perfect sense.
So I just continued using pylsp with the ruff extension.
This would increase the value as the results would be easier to integrate with other tools (for example, you can post SARIF to GitHub).