Remix.run Logo
charliermarsh 5 days ago

To clarify, `ruff` and `uv` aren't being merged. They remain separate tools. This is more about providing a simpler experience for users that don't want to think about their formatter as a separate tool.

The analogy would be to Cargo: `cargo fmt` just runs `rustfmt`, but you can also run `rustfmt` separately if you want.

WD-42 5 days ago | parent | next [-]

Thank you for writing software for all of us Python day-jobbers who wish we were writing Rust instead.

weakfish 4 days ago | parent | next [-]

Never seen someone put my feeling so succinctly

echelon 4 days ago | parent | prev [-]

You can advocate for using Rust at work.

If you're writing microservices, the Rust ecosystem sells itself at this point.

foxygen 4 days ago | parent [-]

What Rust has over other languages that makes it better for writing microservices?

mtndew4brkfst 4 days ago | parent [-]

API-first or API-only backends are a sweet spot for today's Rust, IMO, and its resource footprint, reduced maintenance long-tail, and performance properties are all super competitive. It's especially hard to find another language that can compete with Rust on all three of those at once.

simpaticoder 4 days ago | parent [-]

>reduced maintenance long-tail

I'd like to hear more about that. I'm also curious what makes Rust particularly suited to "API-first" backends. My understanding of the language is that it's concurrency primitives are excellent but difficult to learn and it's gc-less runtime.

echelon 4 days ago | parent [-]

> it's concurrency primitives are excellent but difficult to learn

They're actually incredibly easy to learn if your software paradigm is the request-response flow.

The borrow checker might kill your productivity if you're writing large, connected, multi-threaded data structures, but that simply isn't the nature of 90% of services.

If you want to keep around global state (db connectors, in-memory caches, etc.) Arc<Mutex<T>> is a simple recipe that works for most shared objects. It's dead simple.

You can think of Rust with Axum/Actix as a drop-in replacement for Go or Python/Flask. With the added benefits of (1) no GC / bare metal performance, (2) much lower defect rate as a consequence of the language ergonomics, (3) run it and forget it - no GC tuning, very simple scaling.

Rust has effectively made writing with the performance of C++ feel like writing Ruby, but with unparalleled low defect rates and safety on account of the type system.

aaronblohowiak 4 days ago | parent [-]

>Rust has effectively made writing with the performance of C++ feel like writing Ruby, but with unparalleled low defect rates and safety on account of the type system.

This is a little overblown.. speaking VERY HAND-WAVILY, sea_orm < active record by a factor of about 10x more mental overhead but is at least that much more performant...

but yea, vibe-coding rust micro services is pretty amazing lately, almost no interactions with borrow checker, and I'm even using cucumber specs...

echelon 4 days ago | parent [-]

You're right on that front.

I currently wouldn't recommend any Rust ORM, Diesel included. They're just not quite ready for prime time.

If you're not one to shy away from raw SQL, then SQLx is rock-solid. I actually prefer it over ORMs in general. It's type-checked at runtime or compile time against your schema, no matter how complex the query gets. It manages to do this with an incredibly simple design.

It's like an even nicer version of Java's popular jOOQ framework, which I always felt was incredibly ugly.

SQLx might be my very favorite SQL library of any language.

aaronblohowiak 3 days ago | parent [-]

I will give it another look, thanks!

drdaeman 5 days ago | parent | prev | next [-]

Isn’t there `uv tool run ruff` already for this? Or `uv run ruff` if it’s a proper dependency? I’m not sure what’s the point of a special shortcut command, unless there are plans to make it flexible so it’ll be an abstraction over formatters (unifying ruff, black, etc).

charliermarsh 5 days ago | parent | next [-]

Yeah, you can definitely use `uvx ruff` (an alias for `uv tool run ruff`) to invoke Ruff. That's what I've done in my own projects historically.

The goal here is to see if users like a more streamlined experience with an opinionated default, like you have in Rust or Go: install uv, use `uv init` to create a project, use `uv run` to run your code, `uv format` to format it, etc. Maybe they won't like it! TBD.

(Ruff is installed when you invoke `uv format`, rather than bundled with the uv binary, so if you never use `uv format`, there aren't any material downsides to the experiment.)

divbzero 5 days ago | parent | next [-]

> (Ruff is installed when you invoke `uv format`, rather than bundled with the uv binary, so if you never use `uv format`, there aren't any material downsides to the experiment.)

That’s thoughtful design and could be worth mentioning in the blog post.

RS-232 4 days ago | parent | prev [-]

Would you ever consider bundling ruff binaries with uv releases similar to uvx and uvw? It would benefit offline users and keep compatible uv/ruff versions in sync.

Perhaps even better… cargo-like commands such as uv check, uv doc, and uv test could subsume ruff, ty, and other tools that we haven’t seen yet ;)

A pyup command that installs python-build-standalone, uv, python docs, etc. would be totally clutch, as would standalone installers [0] that bundle it all together.

[0] https://forge.rust-lang.org/infra/other-installation-methods...

chippiewill 5 days ago | parent | prev | next [-]

It's part of the mission for uv to become "cargo for python". A one stop swiss-army knife for everything you need to manage a Python project. I think it'll get a `uv test` command at some point too.

The whole point is you just install `uv` and stop thinking about the pantheon of tools.

robertlagrant 5 days ago | parent [-]

It'll be interesting to see how the test is done. At the tox level, or the pytest level? (Or another level?) I can see all being useful and ergonomic, but tox's multi-environment setup might fit into it really well.

smohare 5 days ago | parent | prev [-]

[dead]

godelski 4 days ago | parent | prev | next [-]

Is `uv format` supposed to be an alias for `ruff check`?

Stupidly I ran `uv format` without `--check` (no harm done and I can `git diff` it) so I didn't see the changes it made but `ruff check` does still show things that can be fixed with `ruff check --fix`. If I'm guessing correctly the difference is coming down to the fact that I have (in my submodule where all changes were made) a pyproject.toml file with ruff rules (there's also a .flake8 file. Repo is being converted). Either way, I find this a bit confusing userside. Not sure what to expect.

I think one thing I would like is that by default `uv format` spits out what files were changed like `uv format --check` does (s/Would reformat/Reformatted/g). Fine for the actual changes not to be displayed but I think this could help with error reduction. Running it again I can see it knows 68 files were changed. Where is that information being stored? It's pretty hard to grep out a number like that (`grep -R \<68\>`) and there's a lot of candidates (honestly there's nothing that looks like a good candidate).

Also, there's a `--quiet` flag, but the output is already pretty quiet. As far as I can tell the only difference is that quiet suppresses the warning (does `--quiet` also suppress errors?)

  uv format
  warning: `uv format` is experimental and may change without warning. Pass `--preview-features format` to disable this warning.
  36 files reformatted, 31 files left unchanged

  uv format --quiet
  36 files reformatted, 31 files left unchanged
I like the result for `--quiet` but I have a strong preference that `uv format` match the verbosity of `uv format --check`. I can always throw information away but not recover. I have a strong bias that it is better to fail by displaying too much information than fail by displaying too little. The latter failure mode is more harmful as the former is much more easily addressed by existing tools. If you're taking votes, that's mine.

Anyways, looking forward to seeing how this matures. Loved everything so far!

akx 4 days ago | parent [-]

> Is `uv format` supposed to be an alias for `ruff check`?

I'd imagine not, since `ruff format` and `ruff check` are separate things too.

godelski 4 days ago | parent [-]

That makes some more sense. I think I just misunderstood what Charlie was saying above.

But I'll also add another suggestion/ask. I think this could be improved

  $ ruff format --help
  Run the Ruff formatter on the given files or directories
  $ uv format --help
  Format Python code in the project
I think just a little more can go a long way. When --help is the docs instead of man I think there needs to be a bit more description. Just something like this tells users a lot more

  $ ruff format --help
  Formats the specified files. Acts as a drop-in replacement for black. 
  $ uv format --help
  Experimental uv formatting. Alias to `ruff format`
I think man/help pages are underappreciated. I know I'm not the only one that discovers new capabilities by reading them. Or even the double tab because I can't remember the flag name but see something I didn't notice before. Or maybe I did notice before but since the tool was new I focused on main features first. Having the ability to read enough information to figure out what these things do then and there really speeds up usage. When the help lines don't say much I often never explore them (unless there's some gut feeling). I know the browser exists, but when I'm using the tool I'm not in the browser.
slightwinder 4 days ago | parent | prev | next [-]

> To clarify, `ruff` and `uv` aren't being merged.

ruff at least seems to be compiled into uv, as the format worked here without a local ruff. This is significant more than just an interface. Whether they are managed and developed as separate tools doesn't matter.

> This is more about providing a simpler experience for users that don't want to think about their formatter as a separate tool.

Then build a separate interface, some script/binary acting as a unified interface, maybe with its separate distribution of all tools. Pushing it into uv is just adding a burden to those who don't want this.

uv and ruff are poor names anyway, this could be used to at least introduce a good name for this everything-python-tool they seem to aim for.

woodruffw 4 days ago | parent [-]

ruff is not compiled into uv; it's bootstrapped from an independent build, much like how `cargo fmt` is bootstrapped from a separate toolchain component (rustfmt). You can see how that works in the PR[1]. Importantly, that means that you don't experience any build-, install-, or run-time burden if you don't use this subcommand.

[1]: https://github.com/astral-sh/uv/pull/15017

jgauth 5 days ago | parent | prev | next [-]

This is cool. Is there a way to call ruff’s linter? Like `uv lint`, which would call `ruff check`.

To your analogy, it’d be like `cargo clippy`

godelski 5 days ago | parent | next [-]

You can always use `uvx ruff check` or `uv tool run ruff check`. Though honestly I find just running `ruff check` much easier.

baggiponte 4 days ago | parent | prev [-]

uv ruffy sounds funny

rbits 4 days ago | parent | prev | next [-]

Does it have the capability to use a different formatter than ruff?

ZiiS 4 days ago | parent [-]

This is about providing an opinionated default. uv will still support installing and runing any formater as before.

4 days ago | parent | prev [-]
[deleted]