Bringing uv and ty together
astral.sh
astral.sh
Of note though, ty doesn't NEED to be integrated into uv, nor vice-versa; keeping them as standalone tools seems most natural.
Ty's original pitch was that it would have strong inference and be useful for gradually typing existing, untyped codebases, but AI made that moot. Adding types to existing code is now trivial.
Not sure if that's true.
Use whatever tools you want, but don't kid yourself. There's a reason Google adopted Pyrefly.
The uv workflow is better but if the day comes when it becomes a problem due to astral lock-in or whatever may happen it’s ok (as long as those old tools exist..)
(Note: I work on both uv and Python packaging standards.)
It's natural to us, purists, but I doubt people care. Everyone wants a single tool that allows them to `uv check` and `uv run` in every project without having to install anything.
Are they rarely used because most software runs on even older versions?
- Now, ty is integrated into uv, while ty is technically being part of ruff [1], but ruff is not integrated into uv.
- The formatter is part of ruff, but uv also have an undocumented "format" command, which does not produce the same results.
- Actually, ruff is integrated into uv, but you must call it through "uv tool run ruff".
I guess I'd like "uv format" and "uv lint" to become the standard commands.
[1] https://github.com/zed-extensions/pyrefly/issues/26#issuecom...
rustfmt is what implements Rust formating. However rustfmt is also distributed via rustup (Rust's toolchain manager). There it is also exposed under the alias cargo-fmt, which makes it work as cargo subcommand `cargo fmt` (a mechanism that's available to any crate). So it's technically not "part of cargo".
Of course the nature of all of this is a bit different, as Rust maintains cargo, rustfmt and a lot more dev tooling as part of it's official teams in comparison to other language ecosystems, where focus is on the compiler only.
the type check is background process for lsp and a quality gate in your process.
formatting likewise with a stronger Fokus on pre-commit
packaging (and build for packaging) may or may not be gated with the former two but it's a (pre)release and deployment activity.
I think it's safe to say most of us who use `uv` use it as a package manager.
Note that `uv format` does exist (in an experimental state) and does what you expect w/r/t invoking Ruff. And `uv check` is the equivalent for ty.
(ty is "part of" Ruff in the sense that it shares a lot of the same machinery, so the two are closely joined in terms of source trees. But it's an entirely separate binary from Ruff's.)
I want my type checker to check types and to scream at me when it can't. I don't want it to do "gradual typing", if it is unsure about what type something is, I want that to be a failure instead of it modeling the unsureness and not showing potential errors. We live in the age of agents, having to add an extra annotation here and there is not so much of a problem any more.
Meta's Pyrefly largely does what I want. I don't quite love Pyrefly either; I don't like the fact that it edge-cases and gives monopoly status to some popular packages (Pydantic, Django, attrs) instead of offering generalized mechanisms that less popular packages could also utilize, but purely on a type checking front, it's excellent.
A good goal, but a hard sell for a tool when the underlying typing spec is very flexible and designed to allow for gradual typing. And of course there are all sorts of python codebases with everything from no types to very tightly specified types.
This seems like astral realizing they lost the type checker race and now fold it into their popular project so people have a reason to use it.
If it is already installed with uv, people have less reason to look for a type checker and will just stay with the default option.
It's somewhat ironic that they're only just getting around to it actually. The predecessor to `uv`, `rye`, had integration for `ruff` fairly early on - but Astral have really dragged their heels on putting it into `uv` (presumably because `ruff` had already won) and even now aren't adding support until after `ty` is integrated.
They did the same thing with ruff too. A totally optional interface through the uv command. Use it or not.
I am tasked with creating a new baseline for python projects. My first hunch was uv, ty, ruff as I've had a good time with them in the past.
What would you recommend?
These days all my project use uv for project management and ruff for linting and formatting.
I believe there is no obvious default for type checking yet. I use whatever my IDE provides. So e.g. pylance in VSCode, which is build on pyright.
There are currently pretty much 3 projects that I look out for: ty, zuban and pyrefly.
At this point, pyrefly seems to me to be the furthest along with support for many common libraries like pytest, pydantic, django, pandas/polars. And meta actually positions it as a production ready system and not a (pre?)beta. Which is why I decided to test drive it.
I have not directly compared the type checkers, I cannot give you a recommendation. For all I know zuban or ty could be the better choice.
uv and ruff took over because they were in many ways simpler and much faster than the competition. ty does not have that luxury.
However, it remains to be seen to what degree that speed difference is due to ty's smaller feature footprint. It just doesn't seem to check the same things. I found it too permissive, personally.
With AI able to quickly solve the adoption and migration, it just became a matter of picking the best tool - pyrefly has everything and is faster than ty.
They could have just said uv now has type chancing capabilities (or whatever it is ..) ty afaik isn't a super popular brand so the post makes people first understand what ty is ..
There is clearly a gap in tooling. We have had a cambrian explosion of tools and we have tried many options. Now it is time for core Python folks to step in and consolidate the ecosystem.
I loved the idea on paper, but without manually creating a matching venv & installing my deps, I wouldn't get in-editor completions during development. That was fine for small things, but intolerable as the script grew. So it's still not a feature I've used much, since it made more sense to just make a real dev environment.
I'm glad to see there'll be improvements here!
...Just how much do your single-file scripts grow that this becomes a problem?
IMO, part of the problem is that people just don’t know that linters or tools like this exist at all. This is the best type of product marketing where the product gets meaningfully better, while educating the users for free.
Has the world shifted so much in the last years? I remember when I switched to Linux, many years ago, I worked through LFS (Linux from Scratch) within, say, one or two years. Back then that was kind of exciting; since then I expanded my own scripts for compiling or installing things, including versioned AppDirs, which to me are a lot more logical and elegant too. Why would I need or use uv? Does uv even support versioned AppDirs? How about multiple different glibc on the same system (hint: that works though you have to take care of how things are setup; think of an extended NixOS-like system, with guarantees).
uv seems to be hyped a lot and I still do not understand why.
In the Python ecosystem, uv is great for "project management" - lock files, project dependency environments ("venv"s) etc (similar to npm for js). In the Python ecosystem it's considered best practice to bundle binary dependencies with Python libraries, and then there'll be a binary distribution for each platform (os, libc).
> AppDirs are the “source” of AppImages. When building an AppImage, a file system image is built from such a directory, to which a runtime is prepended.
(Cargo does, however, contain a small list of those official subcommands so that if you try to use one that's missing, it can remind you to install the corresponding component.)
Vite+ is making it easier to use their linting, formatting (, and more) together though they can still operate fully independently.
I had claude run ty via this new "uv check" on a moderately sized Python package (cli+tui to a multi-transport messaging system) and it found 67 things. Claude checked each finding for bugginess and found 1 is marginally worth fixing. A large fraction of the findings were ty guessing the type and being wrong. Hinting would I guess remove those wrong guesses but hinting is a PITA and greatly increases code size, both of which is bad for human and LLM.
Do people really get benefit from going all-in with type hinting?
An issue you run into these days is that even if you have excellent type checking on your own code, some libraries don't. You of course want to avoid such libraries, or see if you can find type stubs. Gradual typing can suck, but well-typed Python is a bliss.
Annotations are ignored by the compiler (except insofar as they require adding some attributes to objects) and do not guide the bytecode-compilation process or empower any kind of optimization (without a dedicated third-party system like mypyc). Nor are they relevant to PyPy. They are not even free abstractions: as mentioned some objects gain additional attributes (in case you want to introspect something at runtime, but you usually don't), and e.g. calls to `typing.cast` still have to be looked up and made even though it's explicitly intended as a no-op. Plus, expecting annotations to reflect types that can be statically checked gets in the way of other interesting uses of annotations (and the original PEP explicitly designed with other use cases in mind).
I have been using Python for over 20 years. If anything, my attitude has become further against type annotations in the last few.
If you ever had to maintain anything in prod, they're a must.
I would understand the view of some people thinking "why even use python then" but that's a whole other conversation.