Line length is such a hard problem to solve. I wish there was a way to be like don’t allow more than 95% percent of my lines to be longer than X.
I run into this in Django a lot with my chained ORM queries. The usually tend to be like 10-15 chars to long. And in this case you have to line break on the parameters or on a ‘.’ which is ugly as well.
While not related to Python, I feel like whenever I write JS code, especially Vue I have a terrible time with line length.
God made the VT52 with 80 columns for a reason. ;-)
Now, seriously, that's a matter of taste. I like 80 because it allows me to have two files open side by side on my laptop with a readable font size. As we grow older, what's "readable" changes.
I keep hearing these arguments but to me they sound like a romantic attachment to the past. There's no intrinsic quality in using 80 columns besides historical legacy. But hey we can also keep using the size of body parts as measurement units as well, or we can evolve. :)
The 2 column use case is useful, but to be honest, rare. I just tested it here and I still need a big monitor and a "medium" font size for 2x80 to work (not too bad on the vision side, but not too great neither). But it is easy for that point to become moot ;)
> I keep hearing these arguments but to me they sound like a romantic attachment to the past.
If you think that "I like 80 because it allows me to have two files open side by side on my laptop with a readable font size." sounds like a romantic attachment to the past you should probably just read it over and over again until it doesn't.
Just to be sure, I just tested on my notebook screen (13"): 2x80 doesn't fit with a comfortable font size for me, so maybe we should start using 70 chars?
I did read the second paragraph, which makes the first paragraph all the more confusing. First you utterly dismiss the argument on an unreasonable basis, and then in the second paragraph you acknowledge that it's useful to be able to do that.
> Just to be sure, I just tested on my notebook screen (13"): 2x80 doesn't fit with a comfortable font size for me, so maybe we should start using 70 chars?
Sure, YMMV. Even when that turns out to be too small for you, less text per line in the editor leaves more horizontal space for something else, for example a file browser sidebar or a terminal. I've done 2x80 on netbooks for what its worth, but the font size that required probably wouldn't be comfortable to me today.
On my 11 inch I use a single pane. On the 15" it works well when the laptop is on my lap, but less so when it's on the desk but, then, it has two larger monitors, one horizontal and one vertical, so I can still use the two-pane arrangement (typical use is program and test files side by side).
I cut my teeth on the Apple II+, with 40 columns. I agree that 40 columns would be silly, but keeping the text column narrow so that eyes don't need to move too much helps a lot. It's a readability trick used in print since ever. From my position, the horizontal screen spans about 60 degrees, which feels excessive. By the time my eyes marched from left margin to right margin, I already forgot what I was looking for.
My aim these days is usually around 70 chars, plus whatever the block indentation is. That way, I can always move the editor viewport to the right to keep the local region on the screen.
As a long time Python fan, I find the current state of the language frustrating. Tools like black and poetry are nice, but are not part of the standard library. Yet they seem to be required by every popular project out there. (Also, black’s formatting is quite ugly, as noted in this blog post)
Meanwhile, the language itself is increasingly baroque and complicated. Type-annotated, asyncio-enabled Python hardly resembles the easy-to-understand language I fell in love with back in 2006.
Perhaps this is just an “old man yells at cloud” moment...
> Tools like black and poetry are nice, but are not part of the standard library.
If black does non-PEP 8 formatting, as the article says, then I would not expect it to be in the standard library, since PEP 8 formatting is the Python standard.
> the language itself is increasingly baroque and complicated
I don't find current Python 3 any more baroque or complicated than Python 2.7. In fact I have plenty of Python code that runs just fine, unmodified, under both interpreters. And I have plenty of other Python code that only needs from __future__ import print_function to run unmodified under both interpreters.
That's not to say I think there are no issues with current Python 3; just that I wouldn't describe those issues as "the language is increasingly baroque and complicated". See further comments below.
> Type-annotated, asyncio-enabled Python hardly resembles the language I fell in love with back in 2006.
You don't have to use these features if you don't want or need them. Nobody uses 100% of any language's features, and the subset that is used can be very different from person to person. I don't see that as a problem.
I did see the way the Python 3 transition was handled as a big problem, but that's water under the bridge now and the issues that gave many people headaches during the transition were pretty much resolved by Python 3.3.
The two big problems I see with current Python 3 are memory usage and the GIL. Python 3 objects take more memory than Python 2 objects did; for programs that create a lot of objects that can be an issue. (To be fair, many such programs are numerical simulations that can take advantage of the many optimizations in the NumPy and SciPy libraries.) There seems to be work in progress on supporting multiple interpreters running in the same Python process, which would fix the GIL issue, but it's too soon to see if that will really address the issues surrounding the GIL.
There are massive differences between languages, though. I think I might use close to 70% of Objective-C's or Java's features regularly, while I can't even hope to use 50% of C++'s.
> You don't have to use these features if you don't want or need them. Nobody uses 100% of any language's features, and the subset that is used can be very different from person to person. I don't see that as a problem.
The problem is that other people might use those features and you also might have to read the code created by those people.
It's just one more thing you have to get to learn.
I have the same problem with classes in JavaScript. You can't ignore them and stick to prototypes nor ignore prototypes and stick to classes. What should have been a simplification has turned out to make things more complex.
Unlike ES6 classes, you absolutely can ignore type hints (and they're easy to ignore). In fact they're basically inline comments, and the interpreter ignores them too.
I have to disagree regarding asyncio. If existing code uses it that you need to interface with, your sensible options are basically to rewrite all of your code to use asyncio, or try a hacky third-party library that'll try to bridge them.
I'm personally not a fan of it (I'm still a gevent proponent; Go seems to be doing fine with a green thread model), but a lot of libraries I use are written with it, so it's pretty annoying for me. That and the dependency/package story are the two things that've made me seriously consider switching to a different language. (The article's complaints about things like pre-commit and isort are pretty silly and irrelevant, IMO, though it would be nice if there was something official like "go fmt".)
So far the benefits still outweigh the costs for me, compared to other languages, but I predict a better, cleaner, and more performant successor to Python may come this decade. If it does, I think I might become an early adopter.
> I have to disagree regarding asyncio. If existing code uses it that you need to interface with, your sensible options are basically to rewrite all of your code to use asyncio, or try a hacky third-party library that'll try to bridge them.
Yes, this is true. I don't think there's a lot of existing code using it at this point since it's still a fairly new feature. But of course that will change as time goes on.
> I'm personally not a fan of it
I haven't tried it yet in an actual project, but my initial reactions just looking at the specifications and examples were mixed. I like the idea of the await keyword to label call sites where your code might be suspended, but I don't like having "async" cluttering up function definitions, for loops, and with statements. The way generators were handled when they were first introduced in Python 2 was much cleaner IMO: one new keyword, yield, and any function that had that keyword in it automatically became a generator. I don't see why a similar rule couldn't have been implemented for the await keyword: any block with await in it automatically becomes an async block.
I do find the mandatory "async" peppering everywhere annoying, but I'm honestly not a fan of the whole paradigm. I don't actually think it's that important to explicitly specify "await" when you want to await. It's also extremely prone to obscure, frequently-missed errors; a missing await or unnecessary/incorrect await can affect performance or logic in a massive way.
> Type-annotated, asyncio-enabled Python hardly resembles the easy-to-understand language I fell in love with back in 2006.
true.
i am all for types in general and for types annotations in python. but i have seen some heavily type-annotated python code lately and i don't think that's where we want to be.
we are starting to look like a heavily templatized cpp code.
Don't mix things, guy!
- asyncio it's one thing: From my point of view it's amazing... makes python be able to compete with nodejs or go.. (not so hard, if you work also on the browser)
- mypy: that's another story, but it's also optional, use it if you want... (my opinion, like in typescript, if I want types I will do it with go or rust)
Honestly, after trying MyPy for a bit, I'm probably going to gradually type. There's some metaprogramming constructs (notably certain class decorators) that are not expressible in the type system, for one. This makes packages like environ-config unusable.
But most importantly, `def foo(lst: list, idx: int):` is fine in 95% of cases. Most of the time, you don't need to go full Java, full verbosity. Document the most important elements - you're taking in a list and an int - and move on.
(Though yeah templates in C++ turn the ugliness to 11)
Not to mention Python is "strongly-typed". But it doesn't require variables to have a pre-determined type and doesn't do compile time type checks by itself.
Type annotations help catch common errors, and they help humans. Maybe it's not as pretty but as someone who often have to read Python, it really helps me understand what the contract is of a function I'm looking at.
As a big fan of statically typed languages, I agree with you on the utility. Especially after having worked on a large Python projects a few years ago and having to spend a lot of time figuring out what, exactly I could do with a argument named “session”. But when you start turning your dynamically types languages into an ugly statically typed one, maybe we should just admit that we’re using the wrong tool for the job.
Is the point where your Python codebase needs type hinting to be readable a signal that you've hit the dynamic language/complexity impedance mismatch?
Or is it a sign that your code's readability could be better?
Your "session" remark reminds me of trying to understand the Ruby IMAP library when the only documentation was autogenerated API docs, I had to follow one variable through the entire stack to figure out what it's original type and thus capability, was.
I taught myself to code in Python, and find that well-written Python makes sense without types (tooling support aside), but then being honest, most of the Python code I meet professionally, is barely okay written.
I guess it's like Java, industrial programming code needs a type system to make code written averagely understandable, but not so much of a type system that you spend your time fighting obscure compiler errors.
I think this can be the curse of popularity. The demand from more and more users of different feature, especially backed by industries who rely on the language, means that slowly over time, all popular languages accumulate scope and feature creep to some extent.
But at the same time, for serious industry work, those features do come in handy when you do need them.
I think this is why to some extent you never hear that much good of the old tried and tested languages. They always feel bloated, disorganized, confusing, with too much cruft, and yet it's all that which make them what they are.
not the OP but I share the sentiment. On a syntax level simply because it adds types, and one of the joys of writing a dynamic language is that you don't have types filling so much of your code.
But much more important to me, on a semantic level. Late binding of all things is a feature of dynamic languages, not a bug. I have no idea why we're trying to force a static typing mindset onto a dynamic language.
I wish we could all remember that the original idea of OO is that objects interpret the messages they receive, not external typecheckers.
> On a syntax level simply because it adds types, and one of the joys of writing a dynamic language is that you don't have types filling so much of your code.
Then good that you don't have to do that. Type hinting in python is optional and it's unlikely that this will ever change.
> I have no idea why we're trying to force a static typing mindset onto a dynamic language.
Because python ist not a toy-language anymore. It's used for big projects too, and for them features like this are very neccessary.
>Because python ist not a toy-language anymore. It's used for big projects too, and for them features like this are very neccessary.
I've worked on multi-million line dynamic codebases in settings that require robustness and correctness (telecommunications/Erlang) and it's an absolute ridiculous idea that one needs type checking to build industry standard codebases and architecture.
The Java/C++ paradigm is not the only software paradigm to built correct software.
Perhaps this is just an “old man yells at cloud” moment...
Fellow "old man" reporting for duty.
I see a similar set of problems with both Python and JavaScript today (and with various other languages as well, but IME Python and JS are the worst offenders). Both have proven to be useful for various applications. Each started with quite a distinctive style. There were plenty of warts in each case, but overall the "feel" of each language was well understood, and there was a certain simplicity about them that made them accessible to new programmers or to programmers who primarily used other languages. However, over time, people have applied the kitchen sink approach to both language and tooling.
Functional programming is all the rage, and these languages have lambdas (albeit very clumsy ones), so let's all write lots of FP-style code in them! Except you can't, because they are horrible for writing FP-style code, because they lack FP features, they lack efficient and clear syntax for FP idioms, and they do not provide some of the guarantees that benefit FP.
Similarly, a lot of programmers are realising that static typing has its merits when you're trying to build serious software at scale, so let's all add type annotations and start marking up our code! Except that both the existing type systems and idiomatic use of these languages are built around dynamic behaviour, so they lack powerful tools for constructing new types, and they lack efficient and clear syntax for specifying static types, and they lack comprehensive type inference, and the continued presence of dynamic typing means you can't prove a lot of otherwise useful properties of your code anyway.
The amount of tooling expected to do even basic development with these languages today is absurd. Professional-quality programming ought to need no more than a compiler/interpreter, a decent editor and a decent source control system to be productive. On the next level, we might find a tool to automate running tests and reporting the results, a debugger and a profiler; I count these as secondary because it should really be possible to work reasonably well without them but they can make common tasks significantly more efficient and/or accurate. The lack of a package manager tool in both of these lists is not an accident.
I think just as much of today's programming industry has forgotten about the benefits of stability, backward and forward compatibility, and standardisation in the software we make, we have also forgotten about them in our own tools. Do we really need 27 new frameworks for building web apps this year? Is having 41 libraries to do basic unit testing that each use slightly different syntax and vary in <5% of the features they provide really worth the added complexity in the ecosystem? How on earth does JS not have a decent standard library yet?
Maybe it's time to slow down, and make carefully considered choices about the tools and libraries we use in our work, instead of instinctively reaching for that package manager and installing... well, let's be honest, most of the time we don't really know exactly what we're installing, do we?
> hardly resembles the easy-to-understand language I fell in love with back in 2006.
I used to love Python back in those days. Even did a big project with multiple developers in it.
Then I didn't use it for a while and came back for some easy scripting. I was absolutely horrified how complex things are right now. Ditched it and doing my scripting with node.js.
Seriously, how F(&#$%@ING complex can you make the thing?
This is Javascript:
JSON.parse(text[, reviver])
Ah, that's the way I like it :)
But hey, if you want all that argument power, no problem for me. I'm a simple programmer, liking simple things. And that was my point, Python has lost its simple ways. The JavaScript language might have some weird shit, but I don't care about that because I can stay far away from it. I care about simple programming.
ahahahah
now you are telling me that the node ecosystem and the tooling and pre/post compilation/translation phases are simpler than python? (and I'm not talking about the languages themself)
what do you call the various phases of bundling, minification, obfuscation...?
or using babel to use the latest version of the spec?
or the various passages of type/coffescript and whatnot...
or the jsx stuff...
or wasm, webassembly...
... and on and on...
> Type-annotated, asyncio-enabled Python hardly resembles the easy-to-understand language I fell in love with back in 2006.
I'm all with this, but you can pretty much use python without touching these at all. They have a niche business use cases. E.g., when you work on large projects and you want to catch some errors to not be in the runtime.
async was very needed to be able to write performant web servers such as nodejs.
I'm not using python as i used to, and i think the language is getting more complex, and i'd definitely vow for more fundamental changes to the runtime. But if you ignored all of that, python is still remain python. And when your business logic gets more complex, it is imperative your code becomes more complex and you get to discover and use more "language advanced features". The good thing they are available, they are not perfect, but they can be of a good help.
print as a function and headache-inducing string handling hardly resemble the python I came to like either. those two things bring python3 down from great to meh for me. biggest language change blunders I've ever seen. I feel a wave of disappointment every time I have to type a paren on a print call in python3.
yessss... because a pair of parentesys are too much... I always hated that I couldn't pass "print" as a callback, or the weird >> syntax to write on stderr
Piles and piles of red tape specific to python, but the same theme seems to manifest itself in other mainstream programming ecosystems: .net and java, node and so on. This unfriendly affliction isn't tied to a specific programming language, any programming language could be abused in different ways and the same goes with the ecosystem. I think young ecosystems tend to be attractive just because there isn't too much noise. It's just like starting on a new project versus joining one, unless the existing project is very well organized and maintained and properly tradeoff balanced. This is an art too.
> As I adventured in this petty task, it’s worth nothing the amount of red tape required to setup a python project today. You need:
I have never used most of those tools and I've been knee deep in Python for ~4 years. Go look at some of your favorite pypi libraries, chances are they are using a small fraction of those tools as well.
The author is making things overly complicated, but it's all self-inflicted. Just code and be happy.
It's ironic that discussions about formatting are taking up so much mindshare in the python community. For years all you'd hear was that whitespace significance was a sign of the lowliness of python. Meanwhile, tons of people were ignoring the bikeshedding and getting things done. Now it's one of the most widely used languages in existence.
The kinds of people that are focused on issues like formatting never seem to be focused on the things that actually matter - being productive and being able to get things done. That's what has always mattered about python, and what has always made it excellent.
From other comments it looks like the author can be quite vitriolic, so it is possible that a lot of the criticism he receives here is fair in tone. But to me this looks a bit premature, the article sounded like a declaration of intent (especially regarding refactoring the code per se).
In particular I understand that there are wrong ways to complain (and possibly the author is guilty of them), but this specific blog felt over the top and emotional (something I sympathize after unrelated experiences in failing to understand how to organize an Poly/ML project) but not unfair.
Python has always cared about formatting. If you feel like you never needed to worry about things like that, it's because someone else already thought long and hard about it, and encoded it in pep8. No need for debates.
Frankly, after having been out of the Python ecosystem for a long time, I'm surprised that something like black ever gained traction, if it really has strayed in any significant sense from pep8.
The entire reason you have been able to ignore stupid formatting debates like this for so long is because of things like pep8 and strict definitions of what entails "Pythonic" code.
Contra the complaints in the article it is not about black ignoring pep8, it is that pep8 has always had some grey areas and some parts that are simply wrong for modern python code. Black has become the defacto gofmt in the python world by just getting the job done. It is strongly opinionated, but most of the areas of contention were either open-ended before or not worth arguing about; at this point most people are willing to relent on the annoyances or minor non-standard bits for the sake of the benefits black brings to a project.
The author starts by criticising a bike-shedding mentality and then goes on to make bike-shedding arguments. They complain about the non-pep8 compliance, show what pep8 would look like and then argue that there's a better way..
As another commenter pointed out: This is all self-inflicted.
Personally, I don't care how things are formatted, I just want it to be consistent.
> They complain about the non-pep8 compliance, show what pep8 would look like and then argue that there's a better way..
It did not suggest a "better" way, just the PEP-8 way.
It first complains about the non-PEP-8-compliance formatting, then shows a simpler PEP-8 example, and finally shows what will the initial code look like according to PEP-8.
Line count can be a misleading way to measure C# length given there are so many braces on their own lines. But also, the thing is, if you're coding in like Visual Studio, you often don't even type so many of the characters -- the IDE does it for you. So I guess the question I would instead ask is: which one did you feel more productive in? (Including everything from IDE startup time to debugging.)
Honestly, this is one of the things I really appreciate about the development workflow at $dayjob. Our Python build process is fairly custom for what amounts to historical reasons, but when you create a new Python project, you get automated builds and tests on all the OSes you care about (through our central build and test farm), a way of declaring dependencies (that has nothing to do with pipenv/poetry/etc., but whatever), flake8 enabled by default easy toggles for mypy and black if you want them, a standard way of doing code reviews, a standard way of doing releases, etc. - simply because it's possible to assume shared infrastructure and shared defaults.
When you're writing open-source code, you don't have any shared infrastructure or defaults to assume, so you have to find some infrastructure (e.g. GitHub + Travis) and you have to basically include all the infrastructure configuration in your project, possibly through adding a bunch of dev-dependencies that set things up the way you want. It'd be interesting to think about how to abstract this further so you don't have to think about that many things.
Some possible inspirations:
- https://travis.debian.net/ - if you have a Debian package on GitHub, and you want automated tests, you just grab the .travis.yml file from here and a script written by someone else will set up builds and tests in Docker containers. It does rely on Debian having a standardized way of specifying build rules, dependencies, and tests and a standardized layout of packages, though. But most Python packages have a pretty standard layout, too, and you can imagine having things like isort/flake8/nose/etc. be installed only in CI and not explicitly listed in your code.
- Rust, I think, makes this a little easier because there's a high-quality packaging system, test runner, formatter, and doc generator all in the standard Rust tools. While Rust-the-language has a standard library that's much emptier than, say, Python's, rustc comes with way more developer tools than Python does. That means that you don't need to install custom tools to handle most of this because it's assumed that people are using the standard ones. (This does, of course, rely on the tools actually being high-quality, and as a young language, Rust has an unfair advantage in watching Python and so many other languages try to figure out what works well and what doesn't. You'd have an easier time in Python if you stuck to distutils and easy_install, but on the other hand, you'd have to use distutils and easy_install.)
Yes, Poetry is best-in-class package manager. I liked the idea of Pipenv, but in practice it just didn't work well. FYI, Poetry is just a fancy tool for managing your virtualenvs
Every two years I've looked at Python again and been told that the horrible mess I saw last time is obsolete, there's a good tool now that fixes all the problems. Every time it's just been an even bigger mess with one more tool on top.
Pretty much, but Poetry is slowly emerging as the winner, I think. There is no good solution, but if you're starting a new project, Poetry is probably your best bet.
Its behaviour isn't reproducible unless you've frozen your dependencies, and once you've frozen them it becomes very difficult to upgrade any of them. And if your project is itself a library then freezing is basically not viable, so every developer is testing with a slightly different set of dependency versions.
This combines poorly with the fact that venvs are stateful and easy to get mixed up. If you accidentally run the pip install for project A in the terminal window for project B, then you have quite possibly permanently fucked up that venv - there's no reliable way to roll back to the previous state - and if you regenerate it from scratch then, per the previous point, you'll probably get different versions of your transitive dependencies. If your tests were previously passing and now fail - or, worse, were previously failing and now pass - then you're gonna have to abandon whatever you were previously doing for an unknown length of time and deal with this.
Beyond that, those two commands (already twice as many as I'd like) don't tell you anything about how to run unit tests or package up your application for distribution, so you've got a bunch more commands to memorise, which tend to vary between one project and another because how to do those things also changes every two years. And since venv and pip were only included in quite recent versions of Python, if you've got some projects that are using older versions too then you have to memorise a couple more sets of commands for that stuff as well. The whole thing's such a mess that it almost makes docker seem like a sensible idea.
In order to reproducibly package a project with venv, you need to manage venv, requirements.in, requirements.lock, setup.py, pip-tools, MANIFEST.in, and maybe some other things that I'm forgetting. It's just unmanageable.
How long will that last for though? If I invest time to learn it and set it up and apply it to all my projects is it going to all be wasted because someone will have a new idea 6 months from now because of clear and obvious problems with poetry?
There's only so many iterations you can have through the cycle before "no this is the last one!" isn't plausible any more.
Python runs the gamut. You can make small scripts that automate simple tasks and you can make huge websites that service millions of people a day. As projects get bigger, they can adopt tools to help them manage the complexity of the project.
These tools make complex projects simpler without complicating simple things. Personally, I wouldn't want to use Python on a large project without these tools.
I don’t love black’s formatting, but this article is just wrong.
1. Black’s formatting of function arguments does not break PEP8, because the closing parenthesis is one level of indentation back, breaking the continuation. (I don’t even need to check linked threads. Dude is wrong and must have been told so. He doesn’t want to listen, fine. Fork as he wishes, but it’s not like I’m gonna use his fork over Łukasz Langa’s just because he’s tired arguing.)
2. “Piles and piles of red tape”: half are generic project or generic GitHub project stuff, optional of course (oh and black is there so that you don’t need editorconfig).
The Python specific stuff?
- mypy? If you drank the koolaid and now dogmatically type check all your code whether warranted or not. Me? Still enjoying dynamic typing. (Don’t get me wrong, I use mypy judiciously.)
- nose, pytest, unittest, etc.? Sorry you have a choice!
- Finally, I haven’t even heard of bumpversion and setuptools_scm and I’ve been scraping by pushing out releases after releases. I guess you’ll always find a way to pile on the red tapes if you’re enamored with stupid tooling to begin with.
3. Don’t see any “My experience with forking black”, only saw a few talking points, including useless ones like “Remove the ‘for humans’ garbage”. Guess it’s not written yet.
Btw, if a “massive” 3000 line module (lol) chokes up your editor, maybe it’s time to get a better one.
mypy kept python viable for me. I was working on a pretty complicated hw interface, which also used a lot of async/await. Even without what was basically my own coroutine implementation, there were just complicated (but not unusually so!) types in general. You know, just dicts of tuples of lists of tuples and the like.
At what felt like the 1000th runtime problem because of some type confusion somewhere (or just forgetting "await", which is essentially a no-op, since you got a promise that you threw away), and a lot of these problems happening much later than where the actual bug in the code was, I was ready to throw in the towel and bid python--and all other dynamic languages--good bye.
So I decided to try out mypy as some kind of last hurrah, and it paid out immediately. Adding the types went pretty quickly, and after that numerous problems were caught by the type checker, instead of manifesting as some obscure runtime problem down the way.
Most of the problems you mention could also be solved with a good test suit...
I'm not against mypy.. but after working near two years with typescript.. if I have to type I prefer to do it with compiled things...
Probably shouldn't no, no use: the article is from february 3, meanwhile the fork https://github.com/stefanoborini/black is 40 commits behind and 0 ahead. Meaning the OP didn't do any public work yet.
Interestingly, the question whether this particular choice of code formatting in black adheres to pep8 is still an ongoing discussion[1][2][3][4]. Guido, for example, thinks that black's choice is not compatible with pep8 and I think he described the situation quite well on Python's Discourse[5]:
> So the root of this argument is that Black produces code that isn’t always in compliance with PEP 8. I say this is fine – if you use Black you don’t need PEP 8 to tell you how to format your code. (PEP 8 is still useful for other things like naming things.)
> Black optimizes for a different goal than PEP 8; PEP 8 optimizes for readability while Black sometimes compromises readability in order to satisfy other goals such as minimizing lines changed as code evolves.
Thanks for the pointers, I stand corrected. OP could continue this debate if that’s his passion. I bow out.
Meanwhile, I’ll happily enforce black where I can so that I don’t need to have these pointless arguments, although I personally strongly disagree with many of its decisions. I also have no problem contributing to whatever non-blackened projects, including CPython itself (contributed quite a few patches over the years), which is probably the final word on PEP8.
> so that I don’t need to have these pointless arguments
This. I can't believe how much time is lost in such discussions. To paraphrase cjbprime from 11 months ago [1], "nobody likes what the code-formatter does to their code, but everybody likes what it does to their coworker's."
To be fair, it's a giant 4100 line file. That's ridiculous and should be broken up in some way. Let's not try to defend ridiculous behavior just because we don't like the tone of this article, as he's spot on in this regard regarding the organization of this library. I've encountered similar "libraries" that are next to impossible to alter in behavior without forking precisely because they're giant single-file messes.
Personally I like black's style in function argument formatting better than PEP8, assuming the example given is representative of both styles; I find black's to be much more readable.
But that's of course a bikeshed.
At any rate, if black's formatting does break PEP8 (as a downthread commenter rebuts), I would think it's weird that black doesn't have a --pep8-correct flag or something for people who do want PEP-compliant stuff. Certainly black can go its own way, but if people are going to consider it "the blessed python code formatter", it should have a mode that actually conforms to the python standard for formatting.
But hey, ultimately it's the black maintainer's choice.
I have felt like it is way to complicated to do certain things in python... primarily relating to building and packaging large scale code. But, for what I use it for (mostly scripting) it is wonderful. I use it locally, right from the IDE mostly. I almost never call things I make with it from the command line because they are usually single use or low use scripts. Things that I like enough to build into more usually get re-written in c++.
> My problem with the above formatting is that the list of arguments and the body of the function are now at the same indentation level.
OP weirdly complains here that equal scopes shouldn't be equally indented, and, let's be clear, declared function arguments are the same scope as the function body.
> My point is that the proper way to indent the above code is...
OP is dumb and wrong and should feel bad for missing the first section of PEP8 right after the introduction. It's titled "A Foolish Consistency is the Hobgoblin of Little Minds".
OP's proposed "correct" way is to arbitrarily leapfrog an indentation level and then backtrack. Personally I think that makes OP a bad person. As an adherent of The One True Brace Style (K&R), I find OP's proposal to be super ugly and much harder to read than Black's style.
> PEP8 recommends
PEP8 can recommend anything it wants. That particular recommendation is bad and not based on anything other than Guido's personal preference. It's fine for Guido to have preferences, but OP should feel bad for _demanding_ it.
> I decided to do the unthinkable: fork it
It's open source software on github. Forkability is literally the point.
> *I don’t know if you ever saw the code of black. It..."
...gets the job done well and is therefore extremely popular? Yes.
Hard forking a project to make use of the hard work the maintainers put in to it, then writing a post doing nothing but insulting those maintainer's decisions / preferences, is not a good look. Neither is throwing temper tantrums in issue threads: https://github.com/psf/black/issues/1178#issuecomment-565383...
Also if this developer wasn't so obsessed with bikeshedding, they could just edit the one bit of formatting code and republish. That way they could even rebase off of upstream if they wanted.
Personally, I much prefer black's indentation scheme. I also like spending as little time as possible agonizing over minutia like this.
The dude writes "Black violates pep8 recommendation" in his title (notice recommendation), yet, feels strong enough to say "This is a bug. Period." after threatening with a fork (lol?).
Not to bring back that whole maintainer vs contributors discussion, but this is a solid example of entitlement some contributes feel.
It seems like they had an issue, they came up against a fairly standard response from an open source community, and then had several public hissy fits about it.
> Personally, I much prefer black's indentation scheme. I also like spending as little time as possible agonizing over minutia like this.
The strain of bothering over this stuff just isn't worth my time either - I have actual work to do, and the tools tend to just do what I need them to. If they don't, I move on.
I remember using PyCharm and I believe it had a better formatter. On the other hand, I don't really like black. But, as the article said it's recommended by the Python guys.
> a CODE_OF_CONDUCT, because we assume preemptively that you are a racist homophobic asshole, and we have to cover our bases.
This one is a new personal pet peeve. I'm not a racist homophobe--I'm a good person. And though it doesn't give me any authority to speak on the matter, I'm bi and I've dated all sorts of people.
I don't like to be presumed to be an asshole (or presume that others may be), and I'm offended that we have to treat adults like this as part of a new social contract. Can't we just be good to one another? And when there are assholes, can't we handle everything on a case-by-case basis, as it arises?
By putting this into every single project, it feels like we're building an ivory tower that ignores the social progress we've made in the last century. It's disrespectful and patronizing to mature adults to presume how they might behave. I don't like to think of people as great ape descendants, but this kind of thing reminds me we're just animals, fighting and name calling. I don't like that. I don't like how it makes me feel. Software is an achievement of human intellect, and I don't like to be reminded of our flaws. Not in the root of every software project I want to grok or contribute to.
I'm not so close-minded to rule out changing my mind on this matter, but I'm perplexed and, as I admitted before, slightly annoyed. I really want to hear others' opinions on this.
I'm not trying to trivialize anyone's experiences. I missed whatever original conversations there were on this matter and I want to express both how I feel and that I want to know more.
edit: I'm going to be downvoted for even admitting this? That's why I debated even posting. I don't like operating like this.
I feel the opposite: these Codes are just boilerplate nobody cares about.
I once attended a tech meetup held at the headquarters of a FAANG. As we were waiting for the presentation to start, they projected their a link to their code on conduct for the meeting.
I tried to visit the link. It gave a 404. Apparently it hasn’t been working for some time. Nobody noticed.
Ironically, the meetup was about site reliability engineering.
Edit: in all fairness I’ve seen a good tech group destroyed over a dumb battle about their code of conduct.
The 1. assumes that engineers like going to meetings to have 'easy' work and I honestly never met one that would prefer spending a month in meetings and writing docs over almost anything else.
I think it's there not because people are generally expected to behave this way, but to have a framework of rules for when someone occasionally does, so that you can say that moderation decisions aren't completely arbitrary when you kick them out, or so you can say that someone that was arbitrarily kicked out was kicked out for the wrong reasons.
It seems like it could be useful for large and socially important projects with many contributors IMO but I'm not sure why <10 contributor projects pick up on the habit.
Just think of it like a license. If you publish code, you should stick a license on it, so it's clear if/how other people can use it. If you publish a project, you should stick a code of conduct on it, so if any assholes show up, you can link them to something as you tell them to go away. For most developers, these can be glanced at and ignored "yeah, BSD again, great" / "contributors covenant again, blah blah". Having things like this is basically a requirement for getting N>5 when N is the number of developers working on the project, so just pick something sane.
I do find conversations about codes of conduct particularly exhausting, akin to GPLv2 vs GLPv3 licensing debates. And usually an excessive interest in these things is a red flag.
> And when there are assholes, can't we handle everything on a case-by-case basis, as it arises?
Don't interpret this comment as support or lack of support for codes of conduct (I honestly don't have an opinion about the topic). This is just an observation: there are multiple species of attention-seeking internet troll who want very, very much for you to treat their absurd behavior "on a case by case basis."
> I'm going to be downvoted for even admitting this? That's why I debated even posting. I don't like operating like this.
The mob is handling our comments on a case by case basis!
>This is just an observation: there are multiple species of attention-seeking internet troll who want very, very much for you to treat their absurd behavior "on a case by case basis."
In my experience the exact opposite is true. Most trolls want to argue the finer language of a CoC, and waste everyone's time in a pseudo-legal battle.
"Case-by-case" doesn't mean you have to spend a lot of time. It just means you're asking yourself "is this person being disruptive" as opposed to being compelled to argue technicalities in order to justify your actions as a moderator.
I'm talking beyond my expertise here - I've never been involved in a CoC argument, but I have witnessed a lot of trolling - but it seems to me like the same guy who would be happy to argue endlessly about the trouble he's caused and the punishment or censorship that's being meted out on a case by case basis would also be happy to argue endlessly about a code of conduct and its application. Just please pay attention to him!
I sort of suspect the same applies to the third parties who like to whinge about how moderation is being done.
> "Case-by-case" doesn't mean you have to spend a lot of time. It just means you're asking yourself "is this person being disruptive" as opposed to being compelled to argue technicalities in order to justify your actions as a moderator.
Even I have seen the "you handled this one way last month, why are you treating this guy differently today?" arguments. I imagine if you're willing to discuss your decisions at all, you're going to be forced to argue technicalities, if you're infested by the kind of people who like to argue technicalities.
>I'm talking beyond my expertise here - I've never been involved in a CoC argument, but I have witnessed a lot of trolling
If by "argument" you mean "flame-war", then I suppose I'm right there with you. I've seen many, but participated in zero.
Still, I think I've observed some regularities. One such regularity is that flame-wars and CoC-trolling almost always take place in communities that treat their CoCs as some sort of constitution, and believe these conflicts should be resolved in a simili-court-of-law.
This is why I continue to oppose CoCs on the grounds that they're ideological tools, in practice. In my estimation, the whole point of pushing CoCs on open source projects is to get them to think in terms of legal process, at which point they can be harassed into behaving a certain way. This is all done on the false premise that internet communities should be run like first-world democracies.
>Even I have seen the "you handled this one way last month, why are you treating this guy differently today?" arguments.
>I imagine if you're willing to discuss your decisions at all, you're going to be forced to argue technicalities.
That's the brilliant thing - you're not forced to argue technicalities. In fact, you're not forced to give any explanation (though that's rarely the best policy, in practice). This isn't a court of law.
Anyway this is just ... like ... my opinion, man. Others can
disagree with me and still be reasonable. As I said in another comment, I don't run any popular OSS communities, but if I do, I don't think I'll use a CoC. And I don't think that will prevent me from enforcing good behavior.
(P.S.: I've just reread this comment and it struck me as a bit abrasive and argumentative. I've made a few changes, but please be assured of my courteous intent!)
Codes of conduct have come about because apparently we need them. The before-time, when adults were meant to just get on with each other like adults, resulted in some marginalised people feeling very pushed out. So, as usual, a handful of unkind people ruined it for everyone. I don't love having to spell out that racism or transphobia or whatever isn't acceptable, but experience has shown that we do have to say it. So it's a choice between feeling a bit bad about some humans being mean, or projects tending towards a monoculture of big-ego masculine types and hardly anyone else feeling like it's worth the hassle.
>I'm going to be downvoted for even admitting this? That's why I debated even posting. I don't like operating like this.
I think this is a case where a minority of people care very deeply, both about the core issue and about proselytizing it. The rest of us are a silent majority who, like you, are rubbed the wrong way by the whole situation but don't care enough to make a fuss.
To add to your point, here's what boggles my mind with this new CoC frenzy: you can enforce good behavior, even without a CoC.
I don't have any popular open source projects under my stewardship, but if that ever happens, I don't think I'm going to add add a CoC. This is because, in my estimation:
1. They're political tools. The people who visibly push for their widespread use tend to have a revanchist attitude with respect to diversity, inclusion and social equality. They see CoCs as a symbolic action in a turf war, not unlike spray-painting a gang symbol in an alley.
2. As you yourself have noted, it puts people on the defensive. It makes them think before posting...but for all the wrong things. It's stifling.
3. I can still ban disruptive or toxic assholes. I don't need a fake constitution to grant me those powers. See point #1.
I put COC because I use boilerplates that comes with it or because github nags me. It's not like I lose anything by pushing it to the repo. On the contrary, I can use the vagueness to shut down some cases.
Hello,
I received a complaint from an important member that you were not following the CoC and they have given me sufficient evidence of your inappropriate behaviour. For anonymity reasons, I can't provide information on who it was or what the evidence is but as of now, you have been ...xyz
"black can kick and scream and its proponent can say that the frowny face is all they need but they are wrong. They are wrong visually, and they are wrong according to pep8. End of story."
The "frowny face" is ): which in Python is all over the place, but hopefully you don't notice it, and if you do, you don't care.
I find it to be sufficient separation between the arguments and the code. It's too bad the author doesn't, but that doesn't change it for me or other devs that are comfortable with it.
This:
def very_important_function(
template: str,
*variables,
file: os.PathLike,
engine: str,
header: bool = True,
debug: bool = False,
):
"""Applies `variables` to the `template` and writes to `file`."""
with open(file, "w") as f:
is similar to this, which has caught on in React with Prettier:
The current project I'm working on is Python+Black for backend and React+Prettier for frontend and I've really enjoyed the consistency / not worrying about formatting.
Long-time python programmer: we could do a better job with bootstrapping projects. `create-react-app` and `create-probot-app` set up complete projects for ya. How great would it be to have a project skeleton with black + poetry + mypy with everything hooked together?
At the risk of flinging ad hominems, reading his history with the maintainers of black he comes across as quite demented. Even if he were right - which I don’t think he is - I wouldn’t use software maintained by someone that unstable.
182 comments
[ 4.8 ms ] story [ 227 ms ] threadI run into this in Django a lot with my chained ORM queries. The usually tend to be like 10-15 chars to long. And in this case you have to line break on the parameters or on a ‘.’ which is ugly as well.
While not related to Python, I feel like whenever I write JS code, especially Vue I have a terrible time with line length.
My personal preference regarding line lengths: 80 chars are not enough. And even pep8 says that "foolish consistency is the hobgoblin of little minds"
So try being under 80 chars but sometimes you can't. Also don't break a line that's like 85 chars if it will just make it more ugly
I'm glad Prospector by default doesn't enforce "the cult of 80 chars" dogma
Now, seriously, that's a matter of taste. I like 80 because it allows me to have two files open side by side on my laptop with a readable font size. As we grow older, what's "readable" changes.
The 2 column use case is useful, but to be honest, rare. I just tested it here and I still need a big monitor and a "medium" font size for 2x80 to work (not too bad on the vision side, but not too great neither). But it is easy for that point to become moot ;)
If you think that "I like 80 because it allows me to have two files open side by side on my laptop with a readable font size." sounds like a romantic attachment to the past you should probably just read it over and over again until it doesn't.
Just to be sure, I just tested on my notebook screen (13"): 2x80 doesn't fit with a comfortable font size for me, so maybe we should start using 70 chars?
> Just to be sure, I just tested on my notebook screen (13"): 2x80 doesn't fit with a comfortable font size for me, so maybe we should start using 70 chars?
Sure, YMMV. Even when that turns out to be too small for you, less text per line in the editor leaves more horizontal space for something else, for example a file browser sidebar or a terminal. I've done 2x80 on netbooks for what its worth, but the font size that required probably wouldn't be comfortable to me today.
I cut my teeth on the Apple II+, with 40 columns. I agree that 40 columns would be silly, but keeping the text column narrow so that eyes don't need to move too much helps a lot. It's a readability trick used in print since ever. From my position, the horizontal screen spans about 60 degrees, which feels excessive. By the time my eyes marched from left margin to right margin, I already forgot what I was looking for.
https://stackoverflow.com/a/11920726
Meanwhile, the language itself is increasingly baroque and complicated. Type-annotated, asyncio-enabled Python hardly resembles the easy-to-understand language I fell in love with back in 2006.
Perhaps this is just an “old man yells at cloud” moment...
If black does non-PEP 8 formatting, as the article says, then I would not expect it to be in the standard library, since PEP 8 formatting is the Python standard.
> the language itself is increasingly baroque and complicated
I don't find current Python 3 any more baroque or complicated than Python 2.7. In fact I have plenty of Python code that runs just fine, unmodified, under both interpreters. And I have plenty of other Python code that only needs from __future__ import print_function to run unmodified under both interpreters.
That's not to say I think there are no issues with current Python 3; just that I wouldn't describe those issues as "the language is increasingly baroque and complicated". See further comments below.
> Type-annotated, asyncio-enabled Python hardly resembles the language I fell in love with back in 2006.
You don't have to use these features if you don't want or need them. Nobody uses 100% of any language's features, and the subset that is used can be very different from person to person. I don't see that as a problem.
I did see the way the Python 3 transition was handled as a big problem, but that's water under the bridge now and the issues that gave many people headaches during the transition were pretty much resolved by Python 3.3.
The two big problems I see with current Python 3 are memory usage and the GIL. Python 3 objects take more memory than Python 2 objects did; for programs that create a lot of objects that can be an issue. (To be fair, many such programs are numerical simulations that can take advantage of the many optimizations in the NumPy and SciPy libraries.) There seems to be work in progress on supporting multiple interpreters running in the same Python process, which would fix the GIL issue, but it's too soon to see if that will really address the issues surrounding the GIL.
There are massive differences between languages, though. I think I might use close to 70% of Objective-C's or Java's features regularly, while I can't even hope to use 50% of C++'s.
The problem is that other people might use those features and you also might have to read the code created by those people.
I have the same problem with classes in JavaScript. You can't ignore them and stick to prototypes nor ignore prototypes and stick to classes. What should have been a simplification has turned out to make things more complex.
You can only read the code and guess the type yourself.
I'm personally not a fan of it (I'm still a gevent proponent; Go seems to be doing fine with a green thread model), but a lot of libraries I use are written with it, so it's pretty annoying for me. That and the dependency/package story are the two things that've made me seriously consider switching to a different language. (The article's complaints about things like pre-commit and isort are pretty silly and irrelevant, IMO, though it would be nice if there was something official like "go fmt".)
So far the benefits still outweigh the costs for me, compared to other languages, but I predict a better, cleaner, and more performant successor to Python may come this decade. If it does, I think I might become an early adopter.
Yes, this is true. I don't think there's a lot of existing code using it at this point since it's still a fairly new feature. But of course that will change as time goes on.
> I'm personally not a fan of it
I haven't tried it yet in an actual project, but my initial reactions just looking at the specifications and examples were mixed. I like the idea of the await keyword to label call sites where your code might be suspended, but I don't like having "async" cluttering up function definitions, for loops, and with statements. The way generators were handled when they were first introduced in Python 2 was much cleaner IMO: one new keyword, yield, and any function that had that keyword in it automatically became a generator. I don't see why a similar rule couldn't have been implemented for the await keyword: any block with await in it automatically becomes an async block.
true.
i am all for types in general and for types annotations in python. but i have seen some heavily type-annotated python code lately and i don't think that's where we want to be.
we are starting to look like a heavily templatized cpp code.
- mypy: that's another story, but it's also optional, use it if you want... (my opinion, like in typescript, if I want types I will do it with go or rust)
Long term goal is to create a lightweight Pandas equivalent by and for the Rust community, but with slight differences in focus..."
https://docs.rs/black-jack/0.1.0/blackjack/
EDIT: That one looks like it's not being worked on actively. Here's a reddit thread with more ideas. Weld looks interesting.
https://www.reddit.com/r/rust/comments/apo66e/dataframes_wha...
https://www.weld.rs/
And Arrow looks like a new project Wes McKinney is contributing to.
http://arrow.apache.org/
But most importantly, `def foo(lst: list, idx: int):` is fine in 95% of cases. Most of the time, you don't need to go full Java, full verbosity. Document the most important elements - you're taking in a list and an int - and move on.
Which was my main concern when type-hints were added
Give a hand to the strong-typed people and they will take the whole arm.
They will take Python as "now it's like Java" and will push it all the way through.
(Though yeah templates in C++ turn the ugliness to 11)
Not to mention Python is "strongly-typed". But it doesn't require variables to have a pre-determined type and doesn't do compile time type checks by itself.
Is the point where your Python codebase needs type hinting to be readable a signal that you've hit the dynamic language/complexity impedance mismatch?
Or is it a sign that your code's readability could be better?
Your "session" remark reminds me of trying to understand the Ruby IMAP library when the only documentation was autogenerated API docs, I had to follow one variable through the entire stack to figure out what it's original type and thus capability, was.
I taught myself to code in Python, and find that well-written Python makes sense without types (tooling support aside), but then being honest, most of the Python code I meet professionally, is barely okay written.
I guess it's like Java, industrial programming code needs a type system to make code written averagely understandable, but not so much of a type system that you spend your time fighting obscure compiler errors.
Since I started using them, the number of runtime errors coming out from my own code has been drastically reduced.
Of course one can always go overboard with those `Generic[T]` hints. Though this is a problem of the tool user, not the tool.
But at the same time, for serious industry work, those features do come in handy when you do need them.
I think this is why to some extent you never hear that much good of the old tried and tested languages. They always feel bloated, disorganized, confusing, with too much cruft, and yet it's all that which make them what they are.
But much more important to me, on a semantic level. Late binding of all things is a feature of dynamic languages, not a bug. I have no idea why we're trying to force a static typing mindset onto a dynamic language.
I wish we could all remember that the original idea of OO is that objects interpret the messages they receive, not external typecheckers.
Then good that you don't have to do that. Type hinting in python is optional and it's unlikely that this will ever change.
> I have no idea why we're trying to force a static typing mindset onto a dynamic language.
Because python ist not a toy-language anymore. It's used for big projects too, and for them features like this are very neccessary.
I've worked on multi-million line dynamic codebases in settings that require robustness and correctness (telecommunications/Erlang) and it's an absolute ridiculous idea that one needs type checking to build industry standard codebases and architecture.
The Java/C++ paradigm is not the only software paradigm to built correct software.
Fellow "old man" reporting for duty.
I see a similar set of problems with both Python and JavaScript today (and with various other languages as well, but IME Python and JS are the worst offenders). Both have proven to be useful for various applications. Each started with quite a distinctive style. There were plenty of warts in each case, but overall the "feel" of each language was well understood, and there was a certain simplicity about them that made them accessible to new programmers or to programmers who primarily used other languages. However, over time, people have applied the kitchen sink approach to both language and tooling.
Functional programming is all the rage, and these languages have lambdas (albeit very clumsy ones), so let's all write lots of FP-style code in them! Except you can't, because they are horrible for writing FP-style code, because they lack FP features, they lack efficient and clear syntax for FP idioms, and they do not provide some of the guarantees that benefit FP.
Similarly, a lot of programmers are realising that static typing has its merits when you're trying to build serious software at scale, so let's all add type annotations and start marking up our code! Except that both the existing type systems and idiomatic use of these languages are built around dynamic behaviour, so they lack powerful tools for constructing new types, and they lack efficient and clear syntax for specifying static types, and they lack comprehensive type inference, and the continued presence of dynamic typing means you can't prove a lot of otherwise useful properties of your code anyway.
The amount of tooling expected to do even basic development with these languages today is absurd. Professional-quality programming ought to need no more than a compiler/interpreter, a decent editor and a decent source control system to be productive. On the next level, we might find a tool to automate running tests and reporting the results, a debugger and a profiler; I count these as secondary because it should really be possible to work reasonably well without them but they can make common tasks significantly more efficient and/or accurate. The lack of a package manager tool in both of these lists is not an accident.
I think just as much of today's programming industry has forgotten about the benefits of stability, backward and forward compatibility, and standardisation in the software we make, we have also forgotten about them in our own tools. Do we really need 27 new frameworks for building web apps this year? Is having 41 libraries to do basic unit testing that each use slightly different syntax and vary in <5% of the features they provide really worth the added complexity in the ecosystem? How on earth does JS not have a decent standard library yet?
Maybe it's time to slow down, and make carefully considered choices about the tools and libraries we use in our work, instead of instinctively reaching for that package manager and installing... well, let's be honest, most of the time we don't really know exactly what we're installing, do we?
I used to love Python back in those days. Even did a big project with multiple developers in it.
Then I didn't use it for a while and came back for some easy scripting. I was absolutely horrified how complex things are right now. Ditched it and doing my scripting with node.js.
> chooses NodeJS
Congratulations on picking a language with even more weird pitfalls and edge cases?
JS is not what I’d call a simple, straightforward language.
I had that same feeling in the 2.4-2.5 days of Python. But now it was really hard to find simple API's.
Let me give you an example about parsing JSON. This is the Python way:
json.load(fp, , cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, kw)
Seriously, how F(&#$%@ING complex can you make the thing?
This is Javascript:
JSON.parse(text[, reviver])
Ah, that's the way I like it :)
But hey, if you want all that argument power, no problem for me. I'm a simple programmer, liking simple things. And that was my point, Python has lost its simple ways. The JavaScript language might have some weird shit, but I don't care about that because I can stay far away from it. I care about simple programming.
It looks like you copied that from https://docs.python.org/3/library/json.html
Those are all optional parameters, if you don't need them it's just:
json.load(fp)
Which, to the best of my knowledge will behave just like the JS version.
Perhaps I'm just ignorant as to why you would use what's typically a web server for the purposes of scripting
I'm all with this, but you can pretty much use python without touching these at all. They have a niche business use cases. E.g., when you work on large projects and you want to catch some errors to not be in the runtime.
async was very needed to be able to write performant web servers such as nodejs.
I'm not using python as i used to, and i think the language is getting more complex, and i'd definitely vow for more fundamental changes to the runtime. But if you ignored all of that, python is still remain python. And when your business logic gets more complex, it is imperative your code becomes more complex and you get to discover and use more "language advanced features". The good thing they are available, they are not perfect, but they can be of a good help.
yessss... because a pair of parentesys are too much... I always hated that I couldn't pass "print" as a callback, or the weird >> syntax to write on stderr
I have never used most of those tools and I've been knee deep in Python for ~4 years. Go look at some of your favorite pypi libraries, chances are they are using a small fraction of those tools as well.
The author is making things overly complicated, but it's all self-inflicted. Just code and be happy.
My reaction exactly.
“When applying the guideline would make the code less readable, even for someone who is used to reading code that follows this PEP.”
https://www.python.org/dev/peps/pep-0008/
It's ironic that discussions about formatting are taking up so much mindshare in the python community. For years all you'd hear was that whitespace significance was a sign of the lowliness of python. Meanwhile, tons of people were ignoring the bikeshedding and getting things done. Now it's one of the most widely used languages in existence.
The kinds of people that are focused on issues like formatting never seem to be focused on the things that actually matter - being productive and being able to get things done. That's what has always mattered about python, and what has always made it excellent.
That is what this post is advocating for, his own fork of black.
In particular I understand that there are wrong ways to complain (and possibly the author is guilty of them), but this specific blog felt over the top and emotional (something I sympathize after unrelated experiences in failing to understand how to organize an Poly/ML project) but not unfair.
Frankly, after having been out of the Python ecosystem for a long time, I'm surprised that something like black ever gained traction, if it really has strayed in any significant sense from pep8.
The entire reason you have been able to ignore stupid formatting debates like this for so long is because of things like pep8 and strict definitions of what entails "Pythonic" code.
What happened?
As another commenter pointed out: This is all self-inflicted.
Personally, I don't care how things are formatted, I just want it to be consistent.
It did not suggest a "better" way, just the PEP-8 way.
It first complains about the non-PEP-8-compliance formatting, then shows a simpler PEP-8 example, and finally shows what will the initial code look like according to PEP-8.
When you're writing open-source code, you don't have any shared infrastructure or defaults to assume, so you have to find some infrastructure (e.g. GitHub + Travis) and you have to basically include all the infrastructure configuration in your project, possibly through adding a bunch of dev-dependencies that set things up the way you want. It'd be interesting to think about how to abstract this further so you don't have to think about that many things.
Some possible inspirations:
- https://travis.debian.net/ - if you have a Debian package on GitHub, and you want automated tests, you just grab the .travis.yml file from here and a script written by someone else will set up builds and tests in Docker containers. It does rely on Debian having a standardized way of specifying build rules, dependencies, and tests and a standardized layout of packages, though. But most Python packages have a pretty standard layout, too, and you can imagine having things like isort/flake8/nose/etc. be installed only in CI and not explicitly listed in your code.
- Rust, I think, makes this a little easier because there's a high-quality packaging system, test runner, formatter, and doc generator all in the standard Rust tools. While Rust-the-language has a standard library that's much emptier than, say, Python's, rustc comes with way more developer tools than Python does. That means that you don't need to install custom tools to handle most of this because it's assumed that people are using the standard ones. (This does, of course, rely on the tools actually being high-quality, and as a young language, Rust has an unfair advantage in watching Python and so many other languages try to figure out what works well and what doesn't. You'd have an easier time in Python if you stuck to distutils and easy_install, but on the other hand, you'd have to use distutils and easy_install.)
For packaging a Python project, that tool is Poetry. Pipenv, virtualenv, setup.py, venv, setup.cfg, are all outmoded.
A bit to the topic - what's wrong with good old:
This combines poorly with the fact that venvs are stateful and easy to get mixed up. If you accidentally run the pip install for project A in the terminal window for project B, then you have quite possibly permanently fucked up that venv - there's no reliable way to roll back to the previous state - and if you regenerate it from scratch then, per the previous point, you'll probably get different versions of your transitive dependencies. If your tests were previously passing and now fail - or, worse, were previously failing and now pass - then you're gonna have to abandon whatever you were previously doing for an unknown length of time and deal with this.
Beyond that, those two commands (already twice as many as I'd like) don't tell you anything about how to run unit tests or package up your application for distribution, so you've got a bunch more commands to memorise, which tend to vary between one project and another because how to do those things also changes every two years. And since venv and pip were only included in quite recent versions of Python, if you've got some projects that are using older versions too then you have to memorise a couple more sets of commands for that stuff as well. The whole thing's such a mess that it almost makes docker seem like a sensible idea.
There's only so many iterations you can have through the cycle before "no this is the last one!" isn't plausible any more.
These tools make complex projects simpler without complicating simple things. Personally, I wouldn't want to use Python on a large project without these tools.
1. Black’s formatting of function arguments does not break PEP8, because the closing parenthesis is one level of indentation back, breaking the continuation. (I don’t even need to check linked threads. Dude is wrong and must have been told so. He doesn’t want to listen, fine. Fork as he wishes, but it’s not like I’m gonna use his fork over Łukasz Langa’s just because he’s tired arguing.)
2. “Piles and piles of red tape”: half are generic project or generic GitHub project stuff, optional of course (oh and black is there so that you don’t need editorconfig).
The Python specific stuff?
- mypy? If you drank the koolaid and now dogmatically type check all your code whether warranted or not. Me? Still enjoying dynamic typing. (Don’t get me wrong, I use mypy judiciously.)
- nose, pytest, unittest, etc.? Sorry you have a choice!
- Finally, I haven’t even heard of bumpversion and setuptools_scm and I’ve been scraping by pushing out releases after releases. I guess you’ll always find a way to pile on the red tapes if you’re enamored with stupid tooling to begin with.
3. Don’t see any “My experience with forking black”, only saw a few talking points, including useless ones like “Remove the ‘for humans’ garbage”. Guess it’s not written yet.
Btw, if a “massive” 3000 line module (lol) chokes up your editor, maybe it’s time to get a better one.
- The formatting he is proposing for multiple args on a function with double tabs it's wired... O_O
- Same argument on mypy, if I want to type all variables, I perhaps will be happy doing it in go or rust.. python is dynamic :)
- pytest
- balck works so fine with vscode (pycharm will work if he disables linting code on every keystroke... )haha
At what felt like the 1000th runtime problem because of some type confusion somewhere (or just forgetting "await", which is essentially a no-op, since you got a promise that you threw away), and a lot of these problems happening much later than where the actual bug in the code was, I was ready to throw in the towel and bid python--and all other dynamic languages--good bye.
So I decided to try out mypy as some kind of last hurrah, and it paid out immediately. Adding the types went pretty quickly, and after that numerous problems were caught by the type checker, instead of manifesting as some obscure runtime problem down the way.
Probably shouldn't no, no use: the article is from february 3, meanwhile the fork https://github.com/stefanoborini/black is 40 commits behind and 0 ahead. Meaning the OP didn't do any public work yet.
> So the root of this argument is that Black produces code that isn’t always in compliance with PEP 8. I say this is fine – if you use Black you don’t need PEP 8 to tell you how to format your code. (PEP 8 is still useful for other things like naming things.)
> Black optimizes for a different goal than PEP 8; PEP 8 optimizes for readability while Black sometimes compromises readability in order to satisfy other goals such as minimizing lines changed as code evolves.
> I don’t want to compromise PEP 8 though.
[1]: https://github.com/psf/black/issues/48
[2]: https://github.com/psf/black/issues/1178
[3]: https://github.com/psf/black/issues/1336
[4]: https://github.com/PyCQA/pylint/issues/289
[5]: https://discuss.python.org/t/pep-8-clarify-if-multiline-argu...
Meanwhile, I’ll happily enforce black where I can so that I don’t need to have these pointless arguments, although I personally strongly disagree with many of its decisions. I also have no problem contributing to whatever non-blackened projects, including CPython itself (contributed quite a few patches over the years), which is probably the final word on PEP8.
This. I can't believe how much time is lost in such discussions. To paraphrase cjbprime from 11 months ago [1], "nobody likes what the code-formatter does to their code, but everybody likes what it does to their coworker's."
[1] https://news.ycombinator.com/item?id=19941119
But that's of course a bikeshed.
At any rate, if black's formatting does break PEP8 (as a downthread commenter rebuts), I would think it's weird that black doesn't have a --pep8-correct flag or something for people who do want PEP-compliant stuff. Certainly black can go its own way, but if people are going to consider it "the blessed python code formatter", it should have a mode that actually conforms to the python standard for formatting.
But hey, ultimately it's the black maintainer's choice.
Therefore...
> My problem with the above formatting is that the list of arguments and the body of the function are now at the same indentation level.
OP weirdly complains here that equal scopes shouldn't be equally indented, and, let's be clear, declared function arguments are the same scope as the function body.
> My point is that the proper way to indent the above code is...
OP is dumb and wrong and should feel bad for missing the first section of PEP8 right after the introduction. It's titled "A Foolish Consistency is the Hobgoblin of Little Minds".
OP's proposed "correct" way is to arbitrarily leapfrog an indentation level and then backtrack. Personally I think that makes OP a bad person. As an adherent of The One True Brace Style (K&R), I find OP's proposal to be super ugly and much harder to read than Black's style.
> PEP8 recommends
PEP8 can recommend anything it wants. That particular recommendation is bad and not based on anything other than Guido's personal preference. It's fine for Guido to have preferences, but OP should feel bad for _demanding_ it.
> I decided to do the unthinkable: fork it
It's open source software on github. Forkability is literally the point.
> *I don’t know if you ever saw the code of black. It..."
...gets the job done well and is therefore extremely popular? Yes.
Notable examples include mini packages from npm, lint and styling configs for eslint and prettier.
Some of those[0] enforce no semicolon rule which can introduce edge cases and errors because [1]js parser will automatically insert semicolons.
0] https://standardjs.com/
1] http://www.bradoncode.com/blog/2015/08/26/javascript-semi-co...
Black is popular because it is good.
I personally use black but I wouldn't mind other standards as long as I don't have to pick and choose anymore.
Also if this developer wasn't so obsessed with bikeshedding, they could just edit the one bit of formatting code and republish. That way they could even rebase off of upstream if they wanted.
Personally, I much prefer black's indentation scheme. I also like spending as little time as possible agonizing over minutia like this.
This is comic gold.
Not to bring back that whole maintainer vs contributors discussion, but this is a solid example of entitlement some contributes feel.
EDIT: It also gives "I code stuff and try to crash in creative ways." in his profile a somewhat different meaning.
> Personally, I much prefer black's indentation scheme. I also like spending as little time as possible agonizing over minutia like this.
The strain of bothering over this stuff just isn't worth my time either - I have actual work to do, and the tools tend to just do what I need them to. If they don't, I move on.
This one is a new personal pet peeve. I'm not a racist homophobe--I'm a good person. And though it doesn't give me any authority to speak on the matter, I'm bi and I've dated all sorts of people.
I don't like to be presumed to be an asshole (or presume that others may be), and I'm offended that we have to treat adults like this as part of a new social contract. Can't we just be good to one another? And when there are assholes, can't we handle everything on a case-by-case basis, as it arises?
By putting this into every single project, it feels like we're building an ivory tower that ignores the social progress we've made in the last century. It's disrespectful and patronizing to mature adults to presume how they might behave. I don't like to think of people as great ape descendants, but this kind of thing reminds me we're just animals, fighting and name calling. I don't like that. I don't like how it makes me feel. Software is an achievement of human intellect, and I don't like to be reminded of our flaws. Not in the root of every software project I want to grok or contribute to.
I'm not so close-minded to rule out changing my mind on this matter, but I'm perplexed and, as I admitted before, slightly annoyed. I really want to hear others' opinions on this.
I'm not trying to trivialize anyone's experiences. I missed whatever original conversations there were on this matter and I want to express both how I feel and that I want to know more.
edit: I'm going to be downvoted for even admitting this? That's why I debated even posting. I don't like operating like this.
I must live under a bush.
I once attended a tech meetup held at the headquarters of a FAANG. As we were waiting for the presentation to start, they projected their a link to their code on conduct for the meeting.
I tried to visit the link. It gave a 404. Apparently it hasn’t been working for some time. Nobody noticed.
Ironically, the meetup was about site reliability engineering.
Edit: in all fairness I’ve seen a good tech group destroyed over a dumb battle about their code of conduct.
1) At least one month of meetings, drafts and otherwise easy "work".
2) Increasing one's personal brand and marketability inside the corporation and on Twitter.
3) Increasing one's non-meritocratic influence inside the project.
So we are back to the title of this submission: Red tape is introduced in "open" source because corporate money destroys it.
It seems like it could be useful for large and socially important projects with many contributors IMO but I'm not sure why <10 contributor projects pick up on the habit.
I do find conversations about codes of conduct particularly exhausting, akin to GPLv2 vs GLPv3 licensing debates. And usually an excessive interest in these things is a red flag.
Don't interpret this comment as support or lack of support for codes of conduct (I honestly don't have an opinion about the topic). This is just an observation: there are multiple species of attention-seeking internet troll who want very, very much for you to treat their absurd behavior "on a case by case basis."
> I'm going to be downvoted for even admitting this? That's why I debated even posting. I don't like operating like this.
The mob is handling our comments on a case by case basis!
In my experience the exact opposite is true. Most trolls want to argue the finer language of a CoC, and waste everyone's time in a pseudo-legal battle.
"Case-by-case" doesn't mean you have to spend a lot of time. It just means you're asking yourself "is this person being disruptive" as opposed to being compelled to argue technicalities in order to justify your actions as a moderator.
I sort of suspect the same applies to the third parties who like to whinge about how moderation is being done.
> "Case-by-case" doesn't mean you have to spend a lot of time. It just means you're asking yourself "is this person being disruptive" as opposed to being compelled to argue technicalities in order to justify your actions as a moderator.
Even I have seen the "you handled this one way last month, why are you treating this guy differently today?" arguments. I imagine if you're willing to discuss your decisions at all, you're going to be forced to argue technicalities, if you're infested by the kind of people who like to argue technicalities.
If by "argument" you mean "flame-war", then I suppose I'm right there with you. I've seen many, but participated in zero.
Still, I think I've observed some regularities. One such regularity is that flame-wars and CoC-trolling almost always take place in communities that treat their CoCs as some sort of constitution, and believe these conflicts should be resolved in a simili-court-of-law.
This is why I continue to oppose CoCs on the grounds that they're ideological tools, in practice. In my estimation, the whole point of pushing CoCs on open source projects is to get them to think in terms of legal process, at which point they can be harassed into behaving a certain way. This is all done on the false premise that internet communities should be run like first-world democracies.
>Even I have seen the "you handled this one way last month, why are you treating this guy differently today?" arguments.
>I imagine if you're willing to discuss your decisions at all, you're going to be forced to argue technicalities.
That's the brilliant thing - you're not forced to argue technicalities. In fact, you're not forced to give any explanation (though that's rarely the best policy, in practice). This isn't a court of law.
Anyway this is just ... like ... my opinion, man. Others can disagree with me and still be reasonable. As I said in another comment, I don't run any popular OSS communities, but if I do, I don't think I'll use a CoC. And I don't think that will prevent me from enforcing good behavior.
(P.S.: I've just reread this comment and it struck me as a bit abrasive and argumentative. I've made a few changes, but please be assured of my courteous intent!)
I think this is a case where a minority of people care very deeply, both about the core issue and about proselytizing it. The rest of us are a silent majority who, like you, are rubbed the wrong way by the whole situation but don't care enough to make a fuss.
To add to your point, here's what boggles my mind with this new CoC frenzy: you can enforce good behavior, even without a CoC.
I don't have any popular open source projects under my stewardship, but if that ever happens, I don't think I'm going to add add a CoC. This is because, in my estimation:
1. They're political tools. The people who visibly push for their widespread use tend to have a revanchist attitude with respect to diversity, inclusion and social equality. They see CoCs as a symbolic action in a turf war, not unlike spray-painting a gang symbol in an alley.
2. As you yourself have noted, it puts people on the defensive. It makes them think before posting...but for all the wrong things. It's stifling.
3. I can still ban disruptive or toxic assholes. I don't need a fake constitution to grant me those powers. See point #1.
Note that you're not downvoted anymore. Early downvotes are usually balanced out quite quickly if your comment is sincere and thoughtful.
Hello, I received a complaint from an important member that you were not following the CoC and they have given me sufficient evidence of your inappropriate behaviour. For anonymity reasons, I can't provide information on who it was or what the evidence is but as of now, you have been ...xyz
Sincerely, thrwaway69
(/s)
The "frowny face" is ): which in Python is all over the place, but hopefully you don't notice it, and if you do, you don't care.
I find it to be sufficient separation between the arguments and the code. It's too bad the author doesn't, but that doesn't change it for me or other devs that are comfortable with it.
This:
is similar to this, which has caught on in React with Prettier: The fact that people like it in multiple languages means it's definitely an uphill battle to go back to indenting it further.