I’m thrilled to finally present attrs 20.1.0 with the following changes:
- bug fixes
- performance improvements
JUST KIDDING!
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.
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 on_setattr
argument.
It takes a callable and runs it whenever the user tries to assign a new value to the attribute.
See #660.
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 @attr.s(auto_detect=True)
, 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).
See #607.
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.
See #635.
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.s
and 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 import attrs
.
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.ib()
called 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 attr
with attrs
.
N.B.:
- All these APIs require at least Python 3.6. While
attrs
will 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.
you MUST use type annotations.
I just tried this and it failed: