Ruff: Python linter and code formatter written in Rust

2025-01-210:49200150github.com

An extremely fast Python linter and code formatter, written in Rust. - astral-sh/ruff

Ruff image image image Actions status Discord

Docs | Playground

An extremely fast Python linter and code formatter, written in Rust.

Shows a bar chart with benchmark results.

Linting the CPython codebase from scratch.

  • ⚡️ 10-100x faster than existing linters (like Flake8) and formatters (like Black)
  • 🐍 Installable via pip
  • 🛠️ pyproject.toml support
  • 🤝 Python 3.13 compatibility
  • ⚖️ Drop-in parity with Flake8, isort, and Black
  • 📦 Built-in caching, to avoid re-analyzing unchanged files
  • 🔧 Fix support, for automatic error correction (e.g., automatically remove unused imports)
  • 📏 Over 800 built-in rules, with native re-implementations of popular Flake8 plugins, like flake8-bugbear
  • ⌨️ First-party editor integrations for VS Code and more
  • 🌎 Monorepo-friendly, with hierarchical and cascading configuration

Ruff aims to be orders of magnitude faster than alternative tools while integrating more functionality behind a single, common interface.

Ruff can be used to replace Flake8 (plus dozens of plugins), Black, isort, pydocstyle, pyupgrade, autoflake, and more, all while executing tens or hundreds of times faster than any individual tool.

Ruff is extremely actively developed and used in major open-source projects like:

...and many more.

Ruff is backed by Astral. Read the launch post, or the original project announcement.

Sebastián Ramírez, creator of FastAPI:

Ruff is so fast that sometimes I add an intentional bug in the code just to confirm it's actually running and checking the code.

Nick Schrock, founder of Elementl, co-creator of GraphQL:

Why is Ruff a gamechanger? Primarily because it is nearly 1000x faster. Literally. Not a typo. On our largest module (dagster itself, 250k LOC) pylint takes about 2.5 minutes, parallelized across 4 cores on my M1. Running ruff against our entire codebase takes .4 seconds.

Bryan Van de Ven, co-creator of Bokeh, original author of Conda:

Ruff is ~150-200x faster than flake8 on my machine, scanning the whole repo takes ~0.2s instead of ~20s. This is an enormous quality of life improvement for local dev. It's fast enough that I added it as an actual commit hook, which is terrific.

Timothy Crosley, creator of isort:

Just switched my first project to Ruff. Only one downside so far: it's so fast I couldn't believe it was working till I intentionally introduced some errors.

Tim Abbott, lead developer of Zulip:

This is just ridiculously fast... ruff is amazing.

For more, see the documentation.

For more, see the documentation.

Ruff is available as ruff on PyPI.

Invoke Ruff directly with uvx:

uvx ruff check # Lint all files in the current directory.
uvx ruff format # Format all files in the current directory.

Or install Ruff with uv (recommended), pip, or pipx:

# With uv.
uv tool install ruff@latest # Install Ruff globally.
uv add --dev ruff # Or add Ruff to your project. # With pip.
pip install ruff # With pipx.
pipx install ruff

Starting with version 0.5.0, Ruff can be installed with our standalone installers:

# On macOS and Linux.
curl -LsSf https://astral.sh/ruff/install.sh | sh # On Windows.
powershell -c "irm https://astral.sh/ruff/install.ps1 | iex" # For a specific version.
curl -LsSf https://astral.sh/ruff/0.9.2/install.sh | sh
powershell -c "irm https://astral.sh/ruff/0.9.2/install.ps1 | iex"

You can also install Ruff via Homebrew, Conda, and with a variety of other package managers.

To run Ruff as a linter, try any of the following:

ruff check # Lint all files in the current directory (and any subdirectories).
ruff check path/to/code/ # Lint all files in `/path/to/code` (and any subdirectories).
ruff check path/to/code/*.py # Lint all `.py` files in `/path/to/code`.
ruff check path/to/code/to/file.py # Lint `file.py`.
ruff check @arguments.txt # Lint using an input file, treating its contents as newline-delimited command-line arguments.

Or, to run Ruff as a formatter:

ruff format # Format all files in the current directory (and any subdirectories).
ruff format path/to/code/ # Format all files in `/path/to/code` (and any subdirectories).
ruff format path/to/code/*.py # Format all `.py` files in `/path/to/code`.
ruff format path/to/code/to/file.py # Format `file.py`.
ruff format @arguments.txt # Format using an input file, treating its contents as newline-delimited command-line arguments.

Ruff can also be used as a pre-commit hook via ruff-pre-commit:

- repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. rev: v0.9.2 hooks: # Run the linter. - id: ruff args: [ --fix ] # Run the formatter. - id: ruff-format

Ruff can also be used as a VS Code extension or with various other editors.

Ruff can also be used as a GitHub Action via ruff-action:

name: Ruff
on: [ push, pull_request ]
jobs: ruff: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: astral-sh/ruff-action@v3

Ruff can be configured through a pyproject.toml, ruff.toml, or .ruff.toml file (see: Configuration, or Settings for a complete list of all configuration options).

If left unspecified, Ruff's default configuration is equivalent to the following ruff.toml file:

# Exclude a variety of commonly ignored directories.
exclude = [ ".bzr", ".direnv", ".eggs", ".git", ".git-rewrite", ".hg", ".ipynb_checkpoints", ".mypy_cache", ".nox", ".pants.d", ".pyenv", ".pytest_cache", ".pytype", ".ruff_cache", ".svn", ".tox", ".venv", ".vscode", "__pypackages__", "_build", "buck-out", "build", "dist", "node_modules", "site-packages", "venv",
] # Same as Black.
line-length = 88
indent-width = 4 # Assume Python 3.9
target-version = "py39" [lint]
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
select = ["E4", "E7", "E9", "F"]
ignore = [] # Allow fix for all enabled rules (when `--fix`) is provided.
fixable = ["ALL"]
unfixable = [] # Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" [format]
# Like Black, use double quotes for strings.
quote-style = "double" # Like Black, indent with spaces, rather than tabs.
indent-style = "space" # Like Black, respect magic trailing commas.
skip-magic-trailing-comma = false # Like Black, automatically detect the appropriate line ending.
line-ending = "auto"

Note that, in a pyproject.toml, each section header should be prefixed with tool.ruff. For example, [lint] should be replaced with [tool.ruff.lint].

Some configuration options can be provided via dedicated command-line arguments, such as those related to rule enablement and disablement, file discovery, and logging level:

ruff check --select F401 --select F403 --quiet

The remaining configuration options can be provided through a catch-all --config argument:

ruff check --config "lint.per-file-ignores = {'some_file.py' = ['F841']}"

To opt in to the latest lint rules, formatter style changes, interface updates, and more, enable preview mode by setting preview = true in your configuration file or passing --preview on the command line. Preview mode enables a collection of unstable features that may change prior to stabilization.

See ruff help for more on Ruff's top-level commands, or ruff help check and ruff help format for more on the linting and formatting commands, respectively.

Ruff supports over 800 lint rules, many of which are inspired by popular tools like Flake8, isort, pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in Rust as a first-party feature.

By default, Ruff enables Flake8's F rules, along with a subset of the E rules, omitting any stylistic rules that overlap with the use of a formatter, like ruff format or Black.

If you're just getting started with Ruff, the default rule set is a great place to start: it catches a wide variety of common errors (like unused imports) with zero configuration.

Beyond the defaults, Ruff re-implements some of the most popular Flake8 plugins and related code quality tools, including:

For a complete enumeration of the supported rules, see Rules.

Contributions are welcome and highly appreciated. To get started, check out the contributing guidelines.

You can also join us on Discord.

Having trouble? Check out the existing issues on GitHub, or feel free to open a new one.

You can also ask for help on Discord.

Ruff's linter draws on both the APIs and implementation details of many other tools in the Python ecosystem, especially Flake8, Pyflakes, pycodestyle, pydocstyle, pyupgrade, and isort.

In some cases, Ruff includes a "direct" Rust port of the corresponding tool. We're grateful to the maintainers of these tools for their work, and for all the value they've provided to the Python community.

Ruff's formatter is built on a fork of Rome's rome_formatter, and again draws on both API and implementation details from Rome, Prettier, and Black.

Ruff's import resolver is based on the import resolution algorithm from Pyright.

Ruff is also influenced by a number of tools outside the Python ecosystem, like Clippy and ESLint.

Ruff is the beneficiary of a large number of contributors.

Ruff is released under the MIT license.

Ruff is used by a number of major open-source projects and companies, including:

If you're using Ruff, consider adding the Ruff badge to your project's README.md:

[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)

...or README.rst:

.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json :target: https://github.com/astral-sh/ruff :alt: Ruff

...or, as HTML:

<a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff" style="max-width:100%;"></a>

This repository is licensed under the MIT License


Read the original article

Comments

  • By scosman 2025-01-213:0610 reply

    Being new to python, the astral stuff is such a relief.

    I don’t think experienced python folks realize how much the flexible tooling slows people down, and creates friction for adopters. Setting up my project I tried 3 environment managers, 2 type checkers, 3 formatters/linters, 3 packagers/dependancy/project managers.

    I know this is kinda the n+1 issue where astral is just adding another. But it feels like a complete and well designed stack, not a box of parts encouraging me to build my own. Reminds me a bit of go tooling.

    I am a convert. I’ll happily jump on their type checker and packager when ready.

    • By zahlman 2025-01-216:155 reply

      >Setting up my project I tried 3 environment managers, 2 type checkers, 3 formatters/linters, 3 packagers/dependancy/project managers.

      I've been using Python for right about 20 years now. I've been through various prior iterations of the "standard" packaging tools. But I've never found myself wanting a type checker, formatter or linter; and aside from a brief period with Poetry (in which I used barely any of its functionality), I've had no interest in dependency management tools, either. What I have found myself wanting is fixes for the problems in Pip.

      Different people work on different kinds of projects, and approach the language differently, and have radically different needs as a result.

      • By pansa2 2025-01-217:371 reply

        > I've never found myself wanting a type checker

        Do you still write type hints, but not check them? Or just use dynamic typing as in Python 2?

        Actually, I guess the first case is really type-hints-as-comments, so isn't substantially different from the second.

        > I've been using Python for right about 20 years now

        Either way, I've found it quite common among long-time Python users to stick with Python's traditional dynamic typing, whereas newcomers to the language tend to really dislike it in favour of strict static typing. (One exception is GvR himself, who seems to be very pro-type-checking.)

        As the second group continue to add increasingly complex typing features to the language, I wonder if Python is becoming less desirable for those in the first group.

        • By zahlman 2025-01-2113:031 reply

          >Do you still write type hints, but not check them? Or just use dynamic typing

          I occasionally write them as a form of documentation - when it would be more concise than explaining in prose.

          There is nothing specifically 2.x-style about making use of dynamic typing - it's a core property of the language. While 3.0 introduced the annotation feature, it wasn't even specifically intended for typing (https://peps.python.org/pep-3107/) and standard library support wasn't added until 3.5 (https://docs.python.org/3/library/typing.html).

          >As the second group continue to add increasingly complex typing features to the language, I wonder if Python is becoming less desirable for those in the first group.

          Some new changes have been missteps, in my view. There's still nobody forcing my hand when it comes to typing, really; I just shake my head when I see people trying to make it do things it really wasn't designed for. On the other hand, there are definitely things I'd love to see improved about the language.

          • By vram22 2025-01-2121:051 reply

            What new changes do you think have been missteps?

            • By zahlman 2025-01-229:10

              Mmh - that's difficult. I should dedicate a blog article to that topic. Probably can't get to it until next month, though.

      • By ubercore 2025-01-217:513 reply

        Working on a team in a larger python application, type checkers and linters are such a time saver. It's so nice not to think about how I'd like to format my code any longer. We've made some tweaks to our ruff rules to suit the team's opinion, and now even when I don't _love_ the way it formats a particular part of code, I just move on and get something productive done instead.

        And type checking is so great for both preventing bugs (which it does all the time) and self-documenting code. Can't recommend them enough.

        • By Dries007 2025-01-218:49

          It takes out so much frustration too. No more nitpicking about style/... in merge requests, the pre-commit hook will fix it and CI will catch it if you don't.

          The more of this you can automate, the more you get to spend on "real work".

        • By E_Bfx 2025-01-218:12

          In my organisation, some co-workers used to write def func(*args,**kwargs) all the time. That was so tiring to look for what you should put as argument. Type checking is mandatory for well organized large project.*

        • By scosman 2025-01-2112:27

          Yes yes yes.

          I have my own formatting preferences, but my desire to not have to think about them or go to meetings debating them is much much greater.

      • By emblaegh 2025-01-218:19

        I’ve been using it for around the same time, and never cared much about formatters. Linting is useful but wouldn’t call it essential. But type checking is a non negotiable on any project I lead. It’s not perfect by any means, but beats having to crawl my way through a call stack trying to figure out what the hell a function is expected to take and why it’s getting a None instead.

        I have yet to find a single drawback of adopting mypy (or similars) that isn’t completely eclipsed by the benefits.

      • By matsemann 2025-01-2112:22

        > I've been using Python for right about 20 years now.

        That's actually the biggest issue I've seen when a bit back joined a python-shop. Everyone there had mostly done python their whole careers. Fell in love with language during studies, then applied for jobs using that language. Stuck in the old ways, perhaps python felt nimble and nice 20 years ago compared to other things at the time, but with little progress (from its users) in using modern tooling it felt so arcane coming to this shop. And it wasn't the job's fault, it was a state of the art python stack, just a decade behind what other languages have.

      • By coldtea 2025-01-218:382 reply

        >I've never found myself wanting a type checker, formatter or linter;

        I guess that makes one of us.

        https://en.wikipedia.org/wiki/The_Fox_and_the_Grapes

        • By GasVeteran 2025-01-219:081 reply

          The point he is making is that a lot of stuff that you are told you need. You actually don't. Especially if you are working by yourself or in a very small team.

          Getting stuff working is much more important. I'd rather people concentrate on stuff like CI, Unit Tests and Deployments.

          • By ben_w 2025-01-2118:052 reply

            I've seen plenty of projects where people had that attitude except the thing they saw as time-wasting was the CI and Unit Tests.

            Those projects weren't even dumpster fires.

            You can, genuinely, do without all of this stuff — but they're just helpful tools, not silver bullets or the only way to do things, but helpful.

            • By zahlman 2025-01-229:17

              I like unit tests, and I would happily adopt a CI system if my project included non-Python code and had to build multiple wheels. But formatting code properly in my editor is second nature by now; the functions I write are typically so short that it'd be hard to do anything a linter would object to; and type-checking doesn't just introduce busy-work, it works against part of the reason I'm using Python in the first place. I actively don't want to tell people not to call my code with a perfectly compatible type just because I hadn't considered it as within the range of possible compatible types.

            • By GasVeteran 2025-01-2123:091 reply

              Never said it was a silver bullet. I said I would rather people concentrate on more important things than configuring a linter. Half the time this stuff gives you weird errors that don't make a lot of sense (especially with JavaScript/TypeScript), sometimes you are literally making the compiler warning go away because there is literally nothing wrong with the code.

              I do use eslint/prettier btw, but other collegues can never seem to get this working so I've just given up on it and then fix the linter issues whenever I come across them.

              • By ben_w 2025-01-229:551 reply

                > Never said it was a silver bullet.

                Between this and your other comment*, you seem to be simultaneously expecting me to be more and also less literal in how I read your comments.

                * https://news.ycombinator.com/item?id=42786325

                • By GasVeteran 2025-01-2213:541 reply

                  I expect you to be able to use your brain to distinguish obvious hyperbole (it was absolutely obvious) with a matter of fact statement.

                  I am starting to suspect that this playing dumb is entirely disingenuous.

                  • By ben_w 2025-01-2214:281 reply

                    You've never met people who take what you now call obvious hyperbole absolutely seriously and literally?

                    I guess you're going to continue to get surprised by how often you get criticised in this specific way, by many, many other people.

                    Hint: when someone doesn't understand you, you were in fact not obvious, no matter what you think — communication is a multiplayer game, not a single-player endeavour.

        • By zahlman 2025-01-2113:05

          No. On the occasions where I've tried to use an IDE for other programming languages, I've felt like it got in my way more than it helped; and Python is if anything designed more for IDE-less development (due to its overall elegance), and opposed to straightforward IDE guidance (due to its dynamicity).

    • By kstrauser 2025-01-213:23

      I’ve been writing Python for 25 years and I love love love ruff and uv and friends.

    • By coldtea 2025-01-218:37

      Experienced Python folks have Stockholm Syndrome about its tooling, even rejoice at all the "options" for things like dependency managers.

    • By kibwen 2025-01-214:023 reply

      > I know this is kinda the n+1 issue where astral is just adding another.

      My bugbear with that XKCD is that even if it's true, it's also how progress is made. By this point I'm so annoyed whenever anyone links it that I kinda just wish Randall would take it down.

      • By tubthumper8 2025-01-214:20

        Yeah, and that comic is about standards anyways, not tools, so it's doubly annoying when it's linked out of context

      • By earnestinger 2025-01-2111:13

        > it's also how progress is made

        Introducing n+1 solution/ standard may be the necessary cost of making progress, but it is possible to incur that cost without gaining anything

        (at the extreme, trolling is fun activity with net negative on bigger scale)

      • By scosman 2025-01-230:37

        Yeah but still seems relevant when complaining there are too many options and praising the n+1 option

    • By giancarlostoro 2025-01-215:58

      I used to use any standard editor but these days I use PyCharm or Visual Studio (not Code) otherwise, I just use Sublime Text or any adjacent reasonable editor.

      Elementary OS has the nicest editor that other Distros have not snatched up yet not sure why. Its fast, and fits the bill where KATE and Sublime Text are for me.

    • By jmorenoamor 2025-01-215:191 reply

      I started with python dependency management just executing pip install and thinking wow that's cool. No envs, no linters or formatters.

      The point is, if you are learning to code, you can skip nearly all the ecosystem tools. Their need will arise when the time comes.

      • By scosman 2025-01-2112:321 reply

        Yeah but a global environment is a really bad idea. It’s going to trip up those beginners when second project that requires a different version of pytorch.

        • By Hackbraten 2025-01-2410:34

          And when they try to revisit their project one year later only to find it broken.

    • By globular-toast 2025-01-219:131 reply

      People just need a mentor. Could you imagine getting into plumbing and just trying to work out what kind of tools you need by looking at the pipes? Of course not. You'd learn from someone else.

      • By scosman 2025-01-2112:35

        I’ve been coding for 25 years. I don’t need a mentor. I want nice tools when I try yet another language.

    • By nosefurhairdo 2025-01-215:09

      I primarily work on typescript projects, little bit of go. Never enjoyed working with python until I found uv. Glad to see folks rally around astral's tools.

    • By ubercore 2025-01-217:49

      `uv` really is amazing.

    • By atkailash 2025-01-215:30

      This is why I tried ruff, managing the different settings and stuff and an experienced Python person was getting tedious. Now I have one tool.

      I moved to poetry for things a bit ago until I found out about uv recently, it’s so fast I thought it didn’t even do what it asked a couple times.

  • By danpalmer 2025-01-212:059 reply

    I'm a little sad that Ruff took off as a re-implementation of a whole bunch of work that was already done, rather than as a project to improve the work that was already done.

    It was nice to be able to write little extra linters or flake8 plugins in the language I was linting. Plus decades of effort had gone into making those plugins pretty great, finding the right separation of linting codes so that the right things could be linted/ignored per codebase.

    I understand why they did it, and they have done it remarkably well, but "rewrite it from scratch" is almost never the best answer and part of me wonders if this result could have been even better achieved another way.

    • By thrdbndndn 2025-01-212:253 reply

      I'm also sad but from a different perspective.

      If something can be rewritten from scratch fairly quickly and ends up being much faster, it makes you wonder what we (the general “we”) might have done “wrong” with the “decades of effort” before.

      To be clear: there was nothing wrong with the old toolchains (hence the quotes). And of course, Ruff/uv can do what they do because they build on all that earlier knowledge. My point is just that sometimes it's easier to start over than to fix the old, and that fact itself feels kind of sad to me.

      • By nicoburns 2025-01-214:56

        > If something can be rewritten from scratch fairly quickly and ends up being much faster, it makes you wonder what we (the general “we”) might have done “wrong” with the “decades of effort” before.

        I think the impact of Rust (and Go) shouldn't be underestimated here. Prior to these languages if you wanted fast runtime you were either using C or C++ with all their associated footguns, tricky build systems, and poor support for exposing and consuming libraries. Or you were using something like Java or C# which meant managing another runtime just for tools, which is especially bad for something like UV which manages runtimes - imagine if you were using a python tool to manage your Java versions and a Java tool to manage you Python versions, it would be a mess!

        With both Go and Rust you have fast languages without memory safety issues that compile to a single, easily-installable binary and have a broad ecosystem of libraries available that mean that half the time you don't even need to write any difficult code and can just glue some modules together, and the other half of the time you only need to write the code you actually want to write and not all the support code for general pupose stuff like reading config files, file watching, etc.

      • By lmm 2025-01-214:471 reply

        > there was nothing wrong with the old toolchains (hence the quotes). And of course, Ruff/uv can do what they do because they build on all that earlier knowledge

        I don't think that's true. I think the old toolchains really were bad, partly because the Python community was uniquely resistant to building on what worked in other ecosystems, and uv in particular largely succeeds because it's the first tool in this space to finally just ignore the nonsense that had somehow become accepted wisdom in Python-land and apply a little bit of outside experience.

        • By zahlman 2025-01-216:571 reply

          > I think the old toolchains really were bad, partly because the Python community was uniquely resistant to building on what worked in other ecosystems

          I mostly attribute it to backwards compatibility concerns (which I in turn attribute to the traumatic 3.x migration). PyPI continued to accept egg uploads until August 2023 (https://packaging.python.org/en/latest/discussions/package-f...). The easy_install program, along the direct command-line use of `setup.py` (as opposed to having Setuptools invoke it behind the scenes), have been deprecated since October 2021 (https://setuptools.pypa.io/en/latest/history.html#v58-3-0); but not only are they still supported, Setuptools can't even remove support for `setup.py test` (as they tried to in 72.0 and immediately reverted - https://github.com/pypa/setuptools/issues/4519) without causing major disruption to the ecosystem. One of the packages affected was Requests, which: a) is one of the most downloaded packages on PyPI; b) is pure Python (aside from dependencies) with nothing particular complicated about its metadata (I see no reason it couldn't be done in pyproject.toml and/or setup.cfg); c) wasn't even reliant on that interface to run tests (they use Tox).

          (For that matter: Requests has been maintained by the PSF since mid-2019 (https://www.reddit.com/r/Python/comments/cgtp87/seems_like_r...) and the problem could have easily been avoided once the deprecation was announced, but nobody did anything about it. The project still defines most of its metadata in `setup.py`; `pyproject.toml` exists but is only used for pytest and isort config, while `setup.cfg` is used for flake8 config and some requirements metadata that's completely redundant with `setup.py`.)

          A lot of it also just has to do with lack of attention and focus. https://peps.python.org/pep-0427/ (defining the wheel format) was proposed in September 2012, and accepted in February 2013. But Setuptools itself wasn't available as a wheel until November 2013 (https://setuptools.pypa.io/en/latest/history.html#id1646), and in 2017 there were still reports of people having outdated versions of Pip and not being able to install Setuptools from that wheel (https://setuptools.pypa.io/en/latest/history.html#v34-0-0). Setuptools relied on a separate package to actually make wheels until July of last year (https://setuptools.pypa.io/en/latest/history.html#v70-1-0) - an effort which was initially proposed in June 2018 (https://github.com/pypa/setuptools/issues/1386). It also took years to notice that Pip and Setuptools had separate implementations for the code that understands the "tags" in wheel filenames and factor it out into `packaging` (https://github.com/pypa/packaging/pull/156).

      • By zahlman 2025-01-212:32

        > My point is just that sometimes it's easier to start over than to fix the old, and that fact itself feels kind of sad to me.

        Sad, but also liberating. There are surely more projects out there that would benefit from breaking with conventional wisdom to start over.

    • By n8henrie 2025-01-212:36

      I am quite grateful that they rewrote so many tools that I had been using. Upgrades were super painful with them split into a dozen separate packages, I routinely ran into incompatibilities and had to pin to specific versions to deal with transitive dependencies.

      Given the state of python packaging and tooling, I'd say that consolidating the tooling is a big win in and of itself, and with the tremendous speed wins on top...

    • By FreakLegion 2025-01-212:241 reply

      Whenever Ruff comes up, I reflexively go and check https://github.com/astral-sh/ruff/issues/970, since Pylint is the one tool whose performance I find to be egregiously bad. Looks like Ruff is still very far from being able to replace it.

      • By orra 2025-01-219:32

        What about ruff + pyright? From a skim it seems like a lot of the missing features would be covered by a type checker?

        (Pyright isn't written in Rust, but adequate performance is still a design goal)

    • By hobofan 2025-01-216:36

      Rewrite from scratch is exactly what the Python ecosystem needs more of.

      The strong push to always contribute to the existing projects rather than starting new ones in the Python community is what caused the previous subpar state of tooling. I think Astral is also picking a good middle-ground where they still aim to build as much as possible on existing Python standards (and help contributing to new ones), so it's still building on what has been done in the past.

    • By VagabundoP 2025-01-216:44

      There was probably a lot of engineering that went into those designs and that took time.

      Having a clean process to rewrite from is what made it so fast. They knew exactly what outcome they wanted and they had access to the internal implementations on how to do it.

      All that effort was not wasted at all.

    • By eviks 2025-01-213:32

      > this result could have been even better achieved another way.

      Don't you have "decades of effort" to resolve this wonder?

    • By searealist 2025-01-212:222 reply

      Your argument seems ideological. There is no chance they could have improved Flake8 to be as good as Ruff is.

      • By burntsushi 2025-01-212:255 reply

        Folks said the same thing to me about grep 8.5 years ago when I released ripgrep.

        • By danpalmer 2025-01-214:30

          FWIW, I think the reason I'm conflicted is probably a similar reason to why you made a separate new thing. Overcoming the inertia and ways of doing things, or proposing widespread changes, often doesn't go down well with existing maintainers – for very valid reasons. I probably wouldn't want to go into the grep project and suggest rearchitecting it, and I can see why the Ruff developers didn't want to go into projects like Flake8 and Pylint to do the same.

          But that doesn't stop me from feeling that there were things lost in this process and wishing for a better outcome.

        • By tialaramex 2025-01-219:33

          A huge advantage of going your own way is that you don't need to address an audience you think are just wrong.

          When this happens periodically (rather than, every other week) you also get the original GNU advantage which is you can revisit an old tool but knowing what you know now, for example today "everybody" has DVCS, and so ripgrep checks for the .gitignore file.

        • By JelteF 2025-01-212:441 reply

          Wait... Did you misunderstand this comment? Or are you saying grep caught up with ripgrep now?

          • By burntsushi 2025-01-212:58

            I'm agreeing with them. Some folks told me I should have improved grep instead of building my own thing.

        • By oguz-ismail 2025-01-212:41

          And you think you've done it?

      • By danpalmer 2025-01-212:38

        Yeah it's somewhat ideological, I think open source software is better for society when built as a community project than built and controlled by a VC funded company.

        I don't think you could get flake8 to be as fast as Ruff, but I think you could improve it to be within an order of magnitude, and honestly that's plenty good enough. There are a lot of low hanging fruit, particularly around caching. I'd push back on there being no chance of being "as good as" Ruff, because "good" is not just speed. Ruff is _not complete_, if you want all the features and linters, you still need Flake8, or you have to sacrifice some. It's also not publicly extensible, and not written in Python, both of which are fair choices but I think deviate from the ideal scenario here.

    • By Onavo 2025-01-212:14

      Blame Guido. Until recently when he was bought out by Microsoft, he had been the primary blocker of higher Python performance. There were a bunch of attempts at adding a JIT to Python but Guido was more interested in splitting hairs over syntax than any real heavy lifting. Python could have been as performant as LuaJIT or V8 but their dictator ruined it. Python need more Mike Palls.

    • By fydorm 2025-01-2219:48

      Flake8 and Black would never have matched the performance of a Rust-based tool, even if they had 10 years of dedicated focus.

  • By rikthevik 2025-01-212:005 reply

    I'm very impressed by the recent developer experience improvements in the python ecosystem. Between ruff, uv, and https://github.com/gauge-sh/tach we'll be able to keep our django monolith going for a long time.

    Any opinions about the current state of the art type checker?

    • By Mehdi2277 2025-01-212:07

      I'm very happy with pyright. Most bug reports are fixed within a week and new peps/features are added very rapidly usually before pep is accepted (under experimental flag). Enough that I ended up dropping pylint and consider pyright enough for lint purposes as well. The most valuable lints for my work require good multi-file/semantic analysis and pylint had various false positives.

      Main tradeoff is this only works if your codebase/core dependencies are typed. For a while that was not true and we used pylint + pyright. Eventually most of our code is typed and we added type stubs for our main untyped dependencies.

      edit: Also on pylint, it did work well mostly. tensorflow was main library that created most false positives. Other thing I found awkward was occasionally pylint produces non-deterministic lints on my codebase.

    • By optionalsquid 2025-01-217:301 reply

      Everyone is already recommending pyright, but I'll suggest checking the "based" community fork: https://github.com/detachhead/basedpyright

      Besides re-adding features that Microsoft makes exclusive to pylance, it tweaks a number of features that IMO makes pyright work better out the box:

      https://docs.basedpyright.com/latest/benefits-over-pyright/p...

      • By orra 2025-01-219:431 reply

        Thanks for linking this. I wasn't surprised Microsoft made their AI auto completion proprietary (they did similar for C# in VSCode). But it grated me that semantic highlighting wasn't open source.

        • By neonsunset 2025-01-2112:241 reply

          What did they do for C#?

          • By dagw 2025-01-2113:371 reply

            They added some closed source features to the C# developer extension in VSCode. So anybody using a non-Microsoft fork of VSCode can't use those features.

            • By neonsunset 2025-01-2113:431 reply

              If you are referring to the debugger, they did not "add" it - it was like that from the start. The C# extension is MIT, but the 'vsdbg' it ships with isn't because it's a debugger Visual Studio uses made into a standalone cross-platform component.

              You can use an extension fork which swaps it with NetCoreDbg maintained by Samsung instead. This is what VSCodium uses.

              Also note that both of these essentially consume the debugger API exposed by the runtime itself, you can easily make one yourself in a weekend but no one bothered because there isn't much need for another one.

              • By dagw 2025-01-2114:181 reply

                Personally the thing that annoys me isn't so much the open vs closed source of (parts of) these extensions, but the blocking of using these extensions on VSCode forks.

                • By neonsunset 2025-01-2114:41

                  Extensions are not blocked. It's the redistribution restriction the 'vsdbg' component specifically comes with. But you can easily use the fork if it's an issue :)

    • By tylerhillery 2025-01-212:072 reply

      I have always used MyPy but I have noticed some large open source projects adopt Pyright as of late. The folks behind ruff and uv are currently working on a type checker as well but haven't heard when they plan on releasing it.

    • By ducdetronquito 2025-01-2113:201 reply

      First thanks for mentioning tach, I wished this tool existed for a long time and I'm happy to give in a try in the following days!

      For typechecker, I also vouch for Pyright which is what we use for all our django backends at work.

      Just be aware that you will have hard time to typecheck part of your code where you rely heavily on django's magic (magic strings, auto-generated properties/methods, etc...).

      In these cases, it's sometimes better to avoid these features entirely or accept that some part of your code will not be typechecked.

      • By rikthevik 2025-01-2115:14

        I haven't dug into tach yet, but I'm very optimistic on this one.

    • By catlover76 2025-01-215:14

      Pyright is pretty good. It's easy to setup, and has first-class VSCode support, if that's what your team uses.

HackerNews