attrs 20.1.0 released!
I’m thrilled to finally present attrs 20.1.0 with the following changes:
- bug fixes
- performance improvements
This release is HUGE and I'm stoked we can finally get it to you! It’s the result of more than a year of development and not only does it come with many great features that users desired for a long time, it also lays the foundation for the future evolution of this package.
The final push has only been possible thanks to
attrs’s Tidelift subscribers and my generous GitHub Sponsors. If you want to speed up the development for the forthcoming 20.2.0 release (You do! There’s a lot of great stuff coming up!), please consider supporting my work by either sponsoring me, or convincing your boss to subscribe to my projects on Tidelift.
Hooks on Setting Attributes
You could always use validators for when a class is instantiated and you could always make classes immutable.
Now you can also freeze specific attributes and validate attribute values on assignment using the new
It takes a callable and runs it whenever the user tries to assign a new value to the attribute.
Automatic Detection of Own Methods
If you want to write your own dunder method – say
__init__ – you have to remember to tell
attrs to not generate an own version (e.g.
@attr.s(init=False)) otherwise it will happily overwrite it.
Not anymore! If you pass
attrs will look for your own methods automatically – but only in the current class. In other words: inherited methods don’t count. It’s still a bit of hassle to set it to
True, but that will be remedied in the future (see below).
Attribute Collection and the MRO
attrs’s collection of attributes was slightly wrong in very specific situations involving multiple inheritance (editor’s note: don’t use multiple inheritance). Most people won't notice, but some do we like to do things the right way.
The Road Ahead
attrs started out in February 2015. The Python landscape was very different back then and lots of things changed since. We also got some things subtly wrong that need to be fixed by passing arguments. And finally the cute
attr.ib function names didn't age as
attrs gained more and more features over the years.
Therefore, we intend to add a new
attrs namespace in 20.2.0 later this year, allowing you to
But there’s more than an extra “s” planned. We want to free people from having to pass all kinds of arguments to get the “good behavior” of
attrs and therefore we want to introduce new APIs that have better defaults. Thanks to the new namespace, we don’t have to break backward compatibility and the old APIs aren’t going anywhere: in fact, the new ones build on them.
To get the new APIs just right, we’ve added them to
attrs 20.1.0 provisionally for you to test and give us with feedback.
The APIs are
attr.define() which is supposed to become the default way to decorate classes in the future,
attr.frozen() that’s the same thing as
attr.define(frozen=True) and finally
attr.mutable() that is an alias for
define() and was wished for by immutability fans.
There’s also a new alias for
attr.field() since that seems to be the nomenclature the Python community has agreed on. It carries no changes except that it’s keyword-only.
To give you a taste, this is an example for a class defined using the new APIs:
import attr @attr.define class C: x: int y: str = attr.field(default="foo") def __repr__(self) -> str: return "attrs will not overwrite this method."
If everything goes according to plan, in 20.2.0 you’ll be able to substitute
- All these APIs require at least Python 3.6. While
attrswill be Python 2-compatible as long as we can, the new APIs are not.
- mypy's attrs plugin doesn't know about these APIs yet and has to be updated first! Please check out the next file on how to work around this limitation for now!
Check out the API documentation for provisional APIs and please use issue #668 for feedback! Relevant discussions happened in #408, #487, and finally #666 (yep).
The full (looong) changelog with many more features and fixes can be found at https://www.attrs.org/en/stable/changelog.html.
Ah sorry I misunderstood. Yeah I figured it was too good to be true.
Edit: fixed in python-attrs/attrs#675