Uh Ruff is developed by a VC-funded startup. That usually ends up in misaligned incentives between what’s good for VC and what’s good for the community.
Not really an issue, it’s MIT licensed, worst case there can just be a community fork.
I guess that already happened to Rome, when the company behind Rome dissolved, the domain name was shut down and the project was abandoned. Thankfully some people forked it under a new name: https://biomejs.dev/blog/annoucing-biome/
The guy who created Rome was hired to work on Ruff apparently, after his company dissolved. I guess it’s tough out there trying to make profit in the unified linter space.
now it just needs iSort
Ok I’ll ask it: does it have the option to not use magic commas?
Wow, I’m the opposite - trailing commas are a must
Yeah I get it that it’s one of -those- issues. I can live with the trailing comma at the end of a line, but a trailing comma on its own line triggers me badly, it tells my subconscious that “something is missing here”.
I understand the argument around diffs, but I spend way longer looking at code than I do diffs of code.
(Replying just for the chit chat - no criticism of opposite views implied)
For me it’s not even about the diffs, but like if you want to bulk edit the lines with a multi cursor, or copy and paste to add some new lines, it helps if they’re all uniform
I’d not really considered the copy and paste thing.
I’m sorry you got downvoted, I totally get that trailing commas are ‘grammatically’ wrong and would look weird.
But I find these kind of common edits a bit of a pain in formats like JSON or SQL which don’t allow trailing comma. So I was happy to use a linter which enforces them, and then I got very used to them being there.
Trailing commas:
- generate cleaner diffs,
- facilitate reordering,
- facilitate adding a new item at the end without needing to edit the previous one,
- are visually consistent,
I know some people love Black for its lack of configuration, but if Ruff adds a couple more config, then it’ll definitely be my go to formatter.
I’m not about to fuck up my entire projects formatting to match one persons opinion.
Hmm. It’s not clear that it won’t generate magic commas though, which is what I’m after. I guess I’ll just have to try it.
Now make it do package management and I’m fully in
I’m personally using pixi and ruff. Pixi is the first tool in the python ecosystem to solve all my package management woes (and runs fast). They’re conda based though (but they’re working on doing solves across pypi and conda).
Dependency resolution is mostly limited by network afaik. I really like pdm
I would like a fast type-checker, but it’s a really hard tool to do
While we are wishing, it should generate a single file executable.
I don’t think that’s significantly CPU-bound, although you can certainly slow it down with a bad dependency-resolution algorithm (as pipenv did).
It definitely is.
It’s not about the speed, which is trivial. It’s about having an unified tool like cargo
The question isn’t a matter of creating a unified tool but of figuring out why past attempts (e.g. poetry) haven’t taken off more and if those problems can be avoided.
The only thing holding poetry back is still not supporting the standardized pyproject.toml. That’s the closest thing to cargo that we have. And issues related to various ML libraries
I see typechecking as the next natural extension to this. Won’t be easy, it’s probably the trickiest thing to do well, but it would be the ultimate python tool if it did that. It’s a natural extension point as well, since they have the parsing down.
There’s pylyzer for a Rust-based type checking LSP alternative to Pyright, but I couldn’t really get it to work with Neovim.
For me, a big problem with poetry is the author’s insistence on being as strict as cargo on dependency resolution when the Python ecosystem doesn’t have the culture to go with it. You need to be able to override bad transitive dependencies.
It’s not about the speed, which is trivial
Tell that to Anaconda/Poetry. If I remember correctly, there’s some deficiency with Python packaging that makes dependency solving harder for than it is for other languages.
I believe it’s because when the metadata is missing, you need to download the entire package and try installing it to check compatibility.
Of course, this could still be mitigated by generating metadata / precomputing dependencies, or creating and hosting “mini” package proxies for dependency resolution only for the big packages, or many other engineering solutions, if the poetry devs were sufficiently motivated.
No one’s saying that we have to solve the Halting Problem (or similar) to get massive speedups in many cases.
I believe it’s because when the metadata is missing, you need to download each version of an entire massive package and try installing it to check compatibility. Repeated for every possible version, backwards until one works.
I think you’re right; that definitely seems to be poetry’s behaviour. So that’s clearly IO-bound. On the other hand, Anaconda got massive speedups by switching to a better dependency solver. Dependency resolution is basically SAT, after all.
I have (or at least, have had) modest poetry projects that took 10 minutes to resolve on a top end CPU.
That’s because it is network bound. Python dependency resolution is a mess, poetry has to download a bunch of stuff to resolve things properly.
Judging by the tweets from Charlie Marsh, I think it’s being done 👀
Wtf no don’t do package management, lol.
It would be great to see something like refurb in ruff.
Ruff already support some refurb rules under the FURB name.
DAMN I’m going off
Faster Black with single quotes? The original Black could be a history soon.
I’ve been largely avoiding Black for years, purely because I’m obsessive about coding style and I love how clean Python looks with single quotes (I understand why they made the choice to enforce one style, but I’ve discovered I can be very stubborn!). I would always use linters to check for PEP8 violations, but I’d then fix the style myself.
Unironically the fact that the Ruff autoformatter allows single quotes has made the difference in convincing me to adopt it (although it also helps that Ruff is already my preferred linter!).
I got so used to double quotes now RIP angry me from Years ago
I use Black with quote normalisation disabled. My projects have a rule about string quotes:
-
Single quotes for symbols that must be an exact match for a symbol elsewhere. Dict hashes, equality match, etc. These will be in API contracts (think JSON APIs), so any change will require care.
-
Double quotes for user-facing strings, including friendly error/warning messages and i18n strings. These are meant to be periodically revised to improve usability.
-
Exceptions are allowed when a string contains quote characters. Backslash escapes are uglier.
Quote normalisation makes it harder for developers to recognise the purpose of a string.
-
I have a question for all of you fine folks here. I use a library (aws-cdk-lib) that has objects that take many many keyword arguments. We usually put each argument on its own line. I’ve found that these are much easier to read with spaces around the equal sign. But I’ve never seen this mentioned anywhere when looking at formatters. Is this just me? Or is this something that some formatters support?
I agree and haven’t found a formatter to do it for me.
Never seen it in ten years but it actually does sound more readable
It’s against PEP8
Don’t use spaces around the = sign when used to indicate a keyword argument, or when used to indicate a default value for an unannotated function parameter
I’ve been using black for years and years and, just like that, it’s now gone. There’s no reason not to use this.
I am very tempted to adopt this
Question: Black has Darker for formatting just the code in a diff. Does Ruff have something similar? I want to start using it in my CI pipelines, but I don’t too much noise when changing just a small part of a large module.
I asked a similar question on Twitter. Check their GitHub, they’re developing “range formatting”, maybe they are also doing the diff thing
Genuine question, do you have a reason for not just formatting the entire codebase in a single commit and adding that commit to the a .git-blame-ignore-revs file for maintaining a still useful ability to blame through your history?
Anyone in a decent size company that wants to start improving their code formatting without going through the steps to get permission to change “everyone else’s code”.
Similarly, it bothers me that Black doesn’t support range formatting (Darker is an independent project). They’ve basically told everyone to format the whole file or leave.
They’ve basically told everyone to format the whole file or leave.
Which is totally understandable, if you know how Black works. The Darker authors themselves cite “good reasons” why black doesn’t in their README.
There are several reasons:
- As many people are working on the same codebase simultaneously, reformatting the whole thing will create many conflicts
- There are still some places where Black’s formatting in undesired (especially in DS/ML code where you may find data structures formatted as a matrix) and we’d want to exclude those either via configuration, or with the
fmt: off/on
comment directives, but I’ll only see those when I review them in a PR. If I reformat the entire project in one commit it will be harder to spot. - As Black is evolving so may the formatting, or maybe we’ll change some default configuration in the future (like string normalization) and then I’d have to reformat the whole thing again.
Surely, no one would do a change like adding
black
to an existing project without checking that everything still works afterwards?Works, yes. But I’m talking about formatting that just looks wrong with black. Try format something like a long enough numpy matrix, pandas dataframe, or just a list of lists, and you’ll see how black just makes things unreadable.
Anyone got a tutorial? Probably time I learned how to integrate this kind of tool into my workflow.
This is awesome. Ruff is quickly becoming one tool that will cover 80% of projects just with the defaults. I know a lot of people need other very fancy rules and a ton of config, but a lot of projects don’t.
I am the 80%
Everything I make is stupid side projects that never go anywhere, and shit that needs to be standardized for work. If ruff can replace black for me I’m 200% down
*you are the 160%
TBH, I’ve worked with people who have very fancy rules and a ton of config, but I’ve never been convinced they need them. It usually either stems from the tools they’re using not having good defaults, or from the people themselves being total control freaks. Black’s superpower is its ability to completely shut down discussions with control freaks.
I have to admit… compared to some older ruff I had on disk it now reports like double of “errors”. 99% of them irrelevant to actual issues. It’s over reporting silly things so much it has become useless to use. It may or may not report something critical between all the noise, but it’s hard to see the tree because of the forest, so to speak.
I guess this is that new “black” stuff?
If I was to make my code compatible to what it wants I couldn’t use/read it anymore. :) Probably my programs would stop working too:
T201 `print` found
I guess I have to comment that out.
ERA001 Found commented-out code
Oups. I guess I just
rm *.py
to fix the madness. 😎most linting suggestions are pointless that’s nothing unusual
sounds like you haven’t learned most of what is being taught by the greats such as Uncle Bob and his clean code talks.
print() in almost every case should probably be logger.log() if it is important.
comments, doc strings aside, are usually (almost always?) a “code smell”.
“Clean code” is always about preference. I like code I can read and understand. If I want extra comments or keep some commented code to make a thought process about a coding decision more clear then that’s not a bad thing, IMHO.
And if
print()
is such a bad thing, why wasn’t it deprecated for Python 3? Again this probably just comes down to preference again. I just print a final result of a program to stdout (which can be binary data, or some SVG, or just some lines of information). That has nothing to do with “logging”, IMHO.I don’t know who Uncle Bob is. 😳
Or you can just configure it in your pyproject.toml if you don’t want certain lints
My projects are usually just standalone scripts, so no pyproject.toml.
I use a global “.pylintrc” in my home directory for pylint, which I occasionally copy over to project folders that get synced to public github repositories, but that’s it.
Personally I would prefer this to be just the .py file, not all the other fluff one needs to add: https://github.com/the-real-tokai/grablinks
I think that one off standalone scripts are probably not the use case linters (especially ones like ruff that prioritize speed on large code bases) have in mind
You enable all Rules on a personal project? Why?
Anyway time for you to get some humbleness and realize the fault lies with the person in the chair. You. Not even reading the first page of the documentation or following it learning best practices to pick or not pick. Then coming a making an obviously uninformed comment.
https://en.m.wiktionary.org/wiki/PEBCAK
Btw both of those seem like useful errors.
If your project has a significant enough scope that a tool like ruff is warranted, you really should have proposer logging setup instead of print statement, and you should be relying on your version control instead of commenting out code.
It sounds like you’re running it with all the rules enabled, which you don’t have to do and IIRC isn’t the default
I only experimented with it briefly (the old version and the new version I downloaded today). I don’t remember configuring anything, so I assume it runs like that by default:
$ ruff config allowed-confusables builtins cache-dir dummy-variable-rgx exclude extend extend-exclude extend-ignore extend-select external fix fix-only fixable format force-exclude ignore ignore-init-module-imports line-length required-version respect-gitignore select show-source show-fixes src namespace-packages target-version task-tags typing-modules unfixable update-check flake8-annotations flake8-bandit flake8-bugbear flake8-builtins flake8-comprehensions flake8-errmsg flake8-quotes flake8-self flake8-tidy-imports flake8-type-checking flake8-gettext flake8-implicit-str-concat flake8-import-conventions flake8-pytest-style flake8-unused-arguments isort mccabe pep8-naming pycodestyle pydocstyle pylint pyupgrade per-file-ignores
Certainly this will become more useful toned down to sane limits, but it needs time/ research/ reading lots of documentation(?) to sort that out. A more sane default would be nice, IMHO.
This is not the default at all the default is very few corrections by default
That’s interesting.
After some digging I found a “ruff.toml” in an unusual place for a unix’y command line tool (
~/Library/Application Support/ruff/ruff.toml
)select = ["ALL"] ignore = [] fixable = [] unfixable = []
I don’t know what put it there, certainly not my doing as far as I can remember. But that explains some things, I guess. 😱