Bot releases are visible (Hide)
Big releases always carry the risk of regressions, but never did I expect to break Python 3.14’s CI! On the plus side, attrs runs on 3.14 now.
Full changelog below!
This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!
Variomedia AG (@variomedia), Tidelift (@tidelift), FilePreviews (@filepreviews), Klaviyo (@klaviyo), Daniel Fortunov (@asqui), and Kevin P. Fleming (@kpfleming).
Adam Hill (@adamghill), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Moving Content AG (@moving-content), ProteinQure (@ProteinQure), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), The Westervelt Company (@westerveltco), Philippe Galvan (@PhilippeGalvan), Birk Jernström (@birkjernstrom), Chris Withers (@cjw296), Christopher Dignam (@chdsbd), Stefan Hagen (@sthagen), Sławomir Ehlert (@slafs), Mostafa Khalil (@khadrawy), Filip Mularczyk (@mukiblejlok), Mike Fiedler (@miketheman), Thomas Klinger (@thmsklngr), Duncan Hill (@cricalix), Colin Marquardt (@cmarqu), and Andreas Poehlmann (@ap--).
Not to forget 7 more amazing humans who chose to be generous but anonymous!
@define
/ @attr.s
. Please don't use it in new code, but we don't intend to remove it anymore. #1330
attrs.converters.pipe()
(and its syntactic sugar of passing a list for attrs.field()
's / attr.ib()
's converter argument) works again when passing attrs.setters.convert
to on_setattr (which is default for attrs.define
). #1328
This release contains contributions from @hynek.
You can verify this release's artififact attestions using GitHub's CLI tool by downloading the sdist and wheel from PyPI and running:
$ gh attestation verify --owner python-attrs attrs-24.2.0.tar.gz
and
$ gh attestation verify --owner python-attrs attrs-24.2.0-py3-none-any.whl
Published by hynek 3 months ago
This release comes severely delayed, but comes with many exciting new features, bugfixes, and performance optimizations!
The most notable is probably the possibility to receive self
and field definitions in your converters by wrapping them into a attrs.Converter.
The other big thing is our own replacement for __init_subclass__
called (you guessed it) __attrs_init_subclass__
. Check out the docs, if you're not sure what this is good for.
Finally, we've made more important steps to promote our "new" APIs (can you believe they're 4 years old!?) in the docs. If we missed anything, please let us know.
Full changelog below!
This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!
Variomedia AG (@variomedia), Tidelift (@tidelift), FilePreviews (@filepreviews), Klaviyo (@klaviyo), Daniel Fortunov (@asqui), and Kevin P. Fleming (@kpfleming).
Adam Hill (@adamghill), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Moving Content AG (@moving-content), ProteinQure (@ProteinQure), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), The Westervelt Company (@westerveltco), Philippe Galvan (@PhilippeGalvan), Birk Jernström (@birkjernstrom), Chris Withers (@cjw296), Christopher Dignam (@chdsbd), Stefan Hagen (@sthagen), Sławomir Ehlert (@slafs), Mostafa Khalil (@khadrawy), Filip Mularczyk (@mukiblejlok), Mike Fiedler (@miketheman), Thomas Klinger (@thmsklngr), Duncan Hill (@cricalix), Colin Marquardt (@cmarqu), and Andreas Poehlmann (@ap--).
Not to forget 7 more amazing humans who chose to be generous but anonymous!
attrs.evolve()
doesn't accept the inst argument as a keyword argument anymore. Pass it as the first positional argument instead. #1264
attrs.validators.provides()
has been removed. The removed code is available as a gist for convenient copy and pasting. #1265
All packaging metadata except from __version__
and __version_info__
has been removed from the attr
and attrs
modules (for example, attrs.__url__
).
Please use importlib.metadata
or importlib_metadata instead. #1268
Speed up the generated __eq__
methods significantly by generating a chain of attribute comparisons instead of constructing and comparing tuples. This change arguably makes the behavior more correct, but changes it if an attribute compares equal by identity but not value, like float('nan')
. #1310
attr.s
is now deprecated. It was a workaround for nested classes in Python 2 and is pointless in Python 3. #1263
@attr.s
, @attrs.define
, and make_class()
is now deprecated in favor of unsafe_hash, as defined by PEP 681. #1323
Allow original slotted functools.cached_property
classes to be cleaned by garbage collection. Allow super()
calls in slotted cached properties. #1221
Our type stubs now use modern type notation and are organized such that VS Code's quick-fix prefers the attrs
namespace. #1234
Preserve AttributeError
raised by properties of slotted classes with functools.cached_properties
. #1253
It is now possible to wrap a converter into an attrs.Converter
and get the current instance and/or the current field definition passed into the converter callable.
Note that this is not supported by any type checker, yet. #1267
attrs.make_class()
now populates the __annotations__
dict of the generated class, so that attrs.resolve_types()
can resolve them. #1285
Added the attrs.validators.or_()
validator. #1303
The combination of a __attrs_pre_init__
that takes arguments, a kw-only field, and a default on that field does not crash anymore. #1319
attrs.validators.in_()
now transforms certain unhashable options to tuples to keep the field hashable.
This allows fields that use this validator to be used with, for example, attrs.filters.include()
. #1320
If a class has an inherited method called __attrs_init_subclass__
, it is now called once the class is done assembling.
This is a replacement for Python's __init_subclass__
and useful for registering classes, and similar. #1321
This release contains contributions from @bibajz, @carltongibson, @diabolo-dan, @dlax, @econchick, @frenzymadness, @hynek, @koenigdavidmj, @mikejturner, @moto-timo, @my1e5, @richardsheridan, @sscherfke, @tdsmith, and @Tinche.
You can verify this release's artififact attestions using GitHub's CLI tool by downloading the sdist and wheel from PyPI and running:
$ gh attestation verify --owner python-attrs attrs-24.1.0.tar.gz
and
$ gh attestation verify --owner python-attrs attrs-24.1.0-py3-none-any.whl
Mostly typing fixes in this release, but I'm excited that we found a workaround to make functools.cached_property
work with slotted classes! Also, I'm sure there's gonna be fans of the new behavior of __attrs_pre_init__
where it receives all arguments passed to __init__
if it accepts more than self
.
This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!
Variomedia AG (@variomedia), Tidelift (@tidelift), FilePreviews (@filepreviews), Daniel Fortunov (@asqui), and Kevin P. Fleming (@kpfleming).
Adam Hill (@adamghill), Dan Groshev (@si14), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Moving Content AG (@moving-content), ProteinQure (@ProteinQure), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), Ionel Cristian Mărieș (@ionelmc), The Westervelt Company (@westerveltco), Philippe Galvan (@PhilippeGalvan), Birk Jernström (@birkjernstrom), Tim Schilling (@tim-schilling), Chris Withers (@cjw296), Christopher Dignam (@chdsbd), Stefan Hagen (@sthagen), Sławomir Ehlert (@slafs), Mostafa Khalil (@khadrawy), Filip Mularczyk (@mukiblejlok), and Mike Fiedler (@miketheman).
Not to forget 6 more amazing humans who chose to be generous but anonymous!
attrs.resolve_types()
is now correct. #1141
typing.dataclass_transform
to decorate dataclass-like decorators, instead of the non-standard __dataclass_transform__
special form, which is only supported by Pyright. #1158
attrs.asdict/astuple()
with retain_collection_types=True
. #1165
attrs.AttrsInstance
is now a typing.Protocol
in both type hints and code. This allows you to subclass it along with another Protocol
. #1172
__attrs_pre_init__
accepts more than just self
, it will call it with the same arguments as __init__
was called. This allows you to, for example, pass arguments to super().__init__()
. #1187
functools.cached_property
decorated methods to support equivalent semantics. #1200
attrs.make_class()
to provide additional attributes for newly created classes. It is, for example, now possible to attach methods. #1203
Published by hynek over 1 year ago
A lot of features and smaller bug fixes! But also with a heavy heart, we're leaving the last dataclass
-less Python version (3.6) behind, but don't worry: the old versions aren't going anywhere and thanks to the magic of package metadata, pip install attrs
should still work on Python 3.6 as if nothing happened.
This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!
Variomedia AG (@variomedia), Tidelift (@tidelift), Sentry (@getsentry), HiredScore (@HiredScore), FilePreviews (@filepreviews), and Daniel Fortunov (@asqui).
Adam Hill (@adamghill), Dan Groshev (@si14), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Moving Content AG (@moving-content), Stein Magnus Jodal (@jodal), ProteinQure (@ProteinQure), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), Tom Ballinger (@thomasballinger), @medecau, Ionel Cristian Mărieș (@ionelmc), The Westervelt Company (@westerveltco), Philippe Galvan (@PhilippeGalvan), Birk Jernström (@birkjernstrom), Tim Schilling (@tim-schilling), Chris Withers (@cjw296), Christopher Dignam (@chdsbd), and Stefan Hagen (@sthagen).
Not to forget 3 more amazing humans who chose to be generous but anonymous!
The support for zope-interface via the attrs.validators.provides
validator is now deprecated and will be removed in, or after, April 2024.
The presence of a C-based package in our developement dependencies has caused headaches and we're not under the impression it's used a lot.
Let us know if you're using it and we might publish it as a separate package. #1120
attrs.filters.exclude()
and attrs.filters.include()
now support the passing of attribute names as strings. #1068
attrs.has()
and attrs.fields()
now handle generic classes correctly. #1079
Fix frozen exception classes when raised within e.g. contextlib.contextmanager
, which mutates their __traceback__
attributes. #1081
@frozen
now works with type checkers that implement PEP-681 (ex. pyright). #1084
Restored ability to unpickle instances pickled before 22.2.0. #1085
attrs.asdict()
's and attrs.astuple()
's type stubs now accept the attrs.AttrsInstance
protocol. #1090
Fix slots class cellvar updating closure in CPython 3.8+ even when __code__
introspection is unavailable. #1092
attrs.resolve_types()
can now pass include_extras
to typing.get_type_hints()
on Python 3.9+, and does so by default. #1099
Added instructions for pull request workflow to CONTRIBUTING.md
. #1105
Added type parameter to attrs.field()
function for use with attrs.make_class()
.
Please note that type checkers ignore type metadata passed into make_class()
, but it can be useful if you're wrapping attrs. #1107
It is now possible for attrs.evolve()
(and attr.evolve()
) to change fields named inst
if the instance is passed as a positional argument.
Passing the instance using the inst
keyword argument is now deprecated and will be removed in, or after, April 2024. #1117
attrs.validators.optional()
now also accepts a tuple of validators (in addition to lists of validators). #1122
Published by hynek almost 2 years ago
It's been a lot busier than the changelog indicates, but a lot of the work happened under the hood (like some impressive performance improvements). But we've got still one big new feature that's are worthy the holidays:
Fields now have an alias argument that allows you to set the field's name in the generated __init__
method. This is especially useful for those who aren't fans of attrs's behavior of stripping underscores from private attribute names.
This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!
Variomedia AG (@variomedia), Tidelift (@tidelift), Sentry (@getsentry), HiredScore (@HiredScore), FilePreviews (@filepreviews), and Daniel Fortunov (@asqui).
@rzijp, Adam Hill (@adamghill), Dan Groshev (@si14), Tamir Bahar (@tmr232), Adi Roiban (@adiroiban), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Moving Content AG (@moving-content), Stein Magnus Jodal (@jodal), Iwan Aucamp (@aucampia), ProteinQure (@ProteinQure), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), Thomas Ballinger (@thomasballinger), @medecau, Ionel Cristian Mărieș (@ionelmc), The Westervelt Company (@westerveltco), Philippe Galvan (@PhilippeGalvan), Birk Jernström (@birkjernstrom), Jannis Leidel (@jezdez), Tim Schilling (@tim-schilling), Chris Withers (@cjw296), and Christopher Dignam (@chdsbd).
Not to forget 2 more amazing humans who chose to be generous but anonymous!
attrs.field()
now supports an alias option for explicit __init__
argument names.
Get __init__
signatures matching any taste, peculiar or plain! The PEP 681 compatible alias option can be use to override private attribute name mangling, or add other arbitrary field argument name overrides. #950
attrs.NOTHING
is now an enum value, making it possible to use with e.g. typing.Literal
. #983
Added missing re-import of attr.AttrsInstance
to the attrs
namespace. #987
Fix slight performance regression in classes with custom __setattr__
and speedup even more. #991
Class-creation performance improvements by switching performance-sensitive templating operations to f-strings.
You can expect an improvement of about 5% -- even for very simple classes. #995
attrs.has()
is now a TypeGuard
for AttrsInstance
. That means that type checkers know a class is an instance of an attrs
class if you check it using attrs.has()
(or attr.has()
) first. #997
Made attrs.AttrsInstance
stub available at runtime and fixed type errors related to the usage of attrs.AttrsInstance
in Pyright. #999
On Python 3.10 and later, call abc.update_abstractmethods()
on dict classes after creation. This improves the detection of abstractness. #1001
attrs's pickling methods now use dicts instead of tuples. That is safer and more robust across different versions of a class. #1009
Added attrs.validators.not_(wrapped_validator)
to logically invert wrapped_validator by accepting only values where wrapped_validator rejects the value with a ValueError
or TypeError
(by default, exception types configurable). #1010
The type stubs for attrs.cmp_using()
now have default values. #1027
To conform with PEP 681, attr.s()
and attrs.define()
now accept unsafe_hash in addition to hash. #1065
Published by hynek about 2 years ago
The main features of this release are:
We had loftier goals feature-wise, but didn't want to block others embracing Python 3.11.
❤️ Huge thanks to my GitHub sponsors, Tidelift subscribers, and Ko-fi buyers! ❤️
None of my projects would exist in their current form without you!
Python 2.7 is not supported anymore.
Dealing with Python 2.7 tooling has become too difficult for a volunteer-run project.
We have supported Python 2 more than 2 years after it was officially discontinued and feel that we have paid our dues. All version up to 21.4.0 from December 2021 remain fully functional, of course. #936
The deprecated cmp
attribute of attrs.Attribute
has been removed. This does not affect the cmp argument to attr.s
that can be used as a shortcut to set eq and order at the same time. #939
eq
key is defined, it is also used before hashing the attribute. #909
attrs.validators.min_len()
. #916
attrs.validators.deep_iterable()
's member_validator argument now also accepts a list of validators and wraps them in an attrs.validators.and_()
. #925
attrs.converters
and attrs.filters
. #931
attr(s).cmp_using()
. #949
attrs.validators._in()
's ValueError
is not missing the attribute, expected options, and the value it got anymore. #951
Published by hynek almost 3 years ago
Published by hynek almost 3 years ago
This is a big release in the history of attrs
and finishes an arc that took way too long and also delayed this very overdue release. But it's done: import attrs
that has been talked about for years[^issue], but fell victim to “just this one more thing” has finally landed.
From now on, modern attrs
code looks like this:
from attrs import define
@define
class HelloWorld:
modern: bool = True
The define
/field
APIs have been around for over a year and were very popular, now the rest of the package followed suit. I'm very excited that attrs
remains relevant and keeps evolving over now more than half a decade. If you're curious about some of the background, the docs now contain a short explanation and history lesson. As long as our users keep pushing us, we will keep pushing forward class generation in Python!
Big thanks to my GitHub Sponsors, Tidelift subscribers, and Ko-fi buyers that help me mustering the motivation for such long-running project!
Since the release took so long, there's more highlights than we can enumerate here, we'd just like to point out a breaking change in the new APIs: converters now run on setting attributes by default. If this is causing problems to you, you can disable that behavior by setting @define(on_setattr=[])
.
[^issue]: I have an issue from 2018 that I wanted to "come back the moment this lands".
When using @define
, converters are now run by default when setting an attribute on an instance -- additionally to validators. I.e. the new default is on_setattr=[attrs.setters.convert, attrs.setters.validate]
.
This is unfortunately a breaking change, but it was an oversight, impossible to raise a DeprecationWarning
about, and it's better to fix it now while the APIs are very fresh with few users. #835, #886
import attrs
has finally landed! As of this release, you can finally import attrs
using its proper name.
Not all names from the attr
namespace have been transferred; most notably attr.s
and attr.ib
are missing. See attrs.define
and attrs.field
if you haven't seen our next-generation APIs yet. A more elaborate explanation can be found On The Core API Names
This feature is at least for one release provisional. We don't plan on changing anything, but such a big change is unlikely to go perfectly on the first strike.
The API docs have been mostly updated, but it will be an ongoing effort to change everything to the new APIs. Please note that we have not moved -- or even removed -- anything from attr
!
Please do report any bugs or documentation inconsistencies! #887
attr.asdict(retain_collection_types=False)
(default) dumps collection-esque keys as tuples. #646, #888
__match_args__
are now generated to support Python 3.10's Structural Pattern Matching. This can be controlled by the match_args
argument to the class decorators on Python 3.10 and later. On older versions, it is never added and the argument is ignored. #815
attrs.setters.validate
(default in @define
and @mutable
) but no field defines a validator, pretend that it's not set. #817
__repr__
is significantly faster on Pythons with f-strings. #819
field_transformer
are wrapped with AttrsClass
again. #824
attrs.converters.to_bool()
. #830
attrs.resolve_types()
now resolves types of subclasses after the parents are resolved. #842 #843
lt(val)
(< val), le(va)
(≤ val), ge(val)
(≥ val), gt(val)
(> val), and maxlen(n)
. #845
attrs
classes are now fully compatible with cloudpickle (no need to disable repr
anymore). #857
attrs.validators.disabled()
and functions attrs.validators.(set|get)_disabled()
. They deprecate attrs.(set|get)_run_validators()
. All functions are interoperable and modify the same internal state. They are not – and never were – thread-safe, though. #859
attrs.validators.matches_re()
now accepts pre-compiled regular expressions in addition to pattern strings. #877
Published by hynek over 3 years ago
Yesterday's 21.1.0 has unfortunately two regressions that we're fixing with today's 21.2.0 release:
attr.evolve()
broke some use cases.attrs
is not importable under Python 3.4 anymore. While 3.4 hasn't been supported for a while now, we don't want it throw errors after installation.We've reverted the changes to attr.evolve()
and added packaging metadata blocking Python 3.4.
Additionally, we are yanking 21.1.0 from PyPI. If you've pinned attrs
to 21.1.0, this does not affect you in any way.
Published by hynek over 3 years ago
I am extremely excited to announce the release of attrs 21.1.0.
attrs is the direct ancestor of – and the inspiration for – dataclasses in the standard library and remains the more powerful option for creating regular classes without getting bogged down with writing identical boilerplate again and again: https://www.attrs.org/
Heartfelt thanks go to my generous GitHub sponsors, companies subscribing to attrs on Tidelift, and people who bought me a coffee on Ko-fi! Support like that makes me work on FOSS on a Saturday afternoon – especially when a release drags itself like this one! <3
While this release took a bit longer than I wished for, it comes with many exciting changes. The highlights alone are longer than a usual changelog:
The next-generation APIs (@attr.define
, @attr.mutable
, @attr.frozen
, @attr.field
) are deemed stable now. The old ones aren't going anywhere, but I encourage you to check the new ones out – they're much nicer!
pyright and pylance support: Eric Traut of Microsoft was kind enough to involve me in their work on the dataclass_transforms spec.
As a result, Microsoft's type checker pyright will work with this attrs release, and so will their Python language server pylance which should be exciting to VS Code users.
Currently it only supports a subset of attrs's features, but it's the most important ones and more will most likely follow. Some of the limitations are documented in our documentation on type annotations.
Customization of field comparison. This is something especially NumPy users have been asking for for a long time: you can now fully customize how a field is compared. We also ship a helper to avoid boilerplate code. So if you'd like to have an object with a NumPy array that compares correctly, this is the way:
import attr
import numpy
@attr.define
class C:
an_array = attr.field(eq=attr.cmp_using(eq=numpy.array_equal))
Check out the new documentation on comparison for details.
To make it more ergonomic, I've decided to un-deprecate the cmp
argument again, so you can customize eq
and order
in one go. Sorry about the trouble! The cmp
attribute remains deprecated.
New powerful __init__
helpers:
__init__
for you, it will create an __attrs_init__
instead that you can call from your custom __init__
.__attrs_pre_init__
, it will call it without any arguments before doing any initializations. This is really only useful if you want to run super().__init__()
, but that's a use-case people have asked for for years!See Hooking Yourself Into Initialization for details.
In preparation for the (rescinded) plan to make from __future__ import annotations
the default in Python 3.10, attr.resolve_types()
can now also be used to resolve types inside of field_transformer
s.
For the next release we've got even bigger plans! By stabilizing the next-generation APIs we can finally go the last step, I've been talking for years (yeah, sorry): import attrs
.
attrs's playful APIs (@attr.s
, @attr.ib
) lost a bit of their charm as the scope of the package grew – especially after the introduction of type annotations.
While the old APIs aren't going anywhere, in the next feature release there will be additionally an attrs
package that you can use as an alternative to attr
. No more attr.Factory
!
The new package gives us the opportunity to rethink the defaults of some functions. So if you have any pet peeves, please air them on #487.
The long-awaited, much-talked-about, little-delivered import attrs
is finally upon us!
Since the NG APIs have now been proclaimed stable, the next release of attrs
will allow you to actually import attrs
. We're taking this opportunity to replace some defaults in our APIs that made sense in 2015, but don't in 2021.
So please, if you have any pet peeves about defaults in attrs
's APIs, now is the time to air your grievances in #487! We're not gonna get such a chance for a second time, without breaking our backward-compatibility guarantees, or long deprecation cycles. Therefore, speak now or forever hold you peace! #487
The cmp argument to attr.s()
and attr.ib() has been undeprecated It will continue to be supported as syntactic sugar to set eq and order in one go.
I'm terribly sorry for the hassle around this argument! The reason we're bringing it back is it's usefulness regarding customization of equality/ordering.
The cmp
attribute and argument on attr.Attribute
remains deprecated and will be removed later this year. #773
It's now possible to customize the behavior of eq
and order
by passing in a callable. #435, #627
The instant favorite next-generation APIs are not provisional anymore!
They are also officially supported by Mypy as of their 0.800 release.
We hope the next release will already contain an (additional) importable package called attrs
. #668, #786
If an attribute defines a converter, the type of its parameter is used as type annotation for its corresponding __init__
parameter.
If an attr.converters.pipe
is used, the first one's is used. #710
Fixed the creation of an extra slot for an attr.ib
when the parent class already has a slot with the same name. #718
__attrs__init__()
will now be injected if init=False
, or if auto_detect=True
and a user-defined __init__()
exists.
This enables users to do "pre-init" work in their __init__()
(such as super().__init__()
).
__init__()
can then delegate constructor argument processing to self.__attrs_init__(*args, **kwargs)
. #731
bool(attr.NOTHING)
is now False
. #732
It's now possible to use super()
inside of properties of slotted classes. #747
Allow for a __attrs_pre_init__()
method that -- if defined -- will get called at the beginning of the attrs
-generated __init__()
method. #750
Added forgotten attr.Attribute.evolve()
to type stubs. #752
attrs.evolve()
now works recursively with nested attrs
classes. #759
Python 3.10 is now officially supported. #763
attr.resolve_types()
now takes an optional attrib argument to work inside a field_transformer
. #774
ClassVar
s are now also detected if they come from typing-extensions. #782
To make it easier to customize attribute comparison (#435), we have added the attr.cmp_with()
helper.
See the new docs on comparison for more details. #787
Added provisional support for static typing in pyright
via the dataclass_transforms specification. Both the pyright
specification and attrs
implementation may change in future versions of both projects.
Your constructive feedback is welcome in both attrs#795 and pyright#1782. #796
Published by hynek almost 4 years ago
attr.define()
, attr.frozen()
, attr.mutable()
, and attr.field()
remain provisional.
This release does not change change anything about them and they are already used widely in production though.
If you wish to use them together with mypy, you can simply drop this plugin into your project.
Feel free to provide feedback to them in the linked issue #668.
We will release the attrs
namespace once we have the feeling that the APIs have properly settled. #668
attr.s()
now has a field_transformer hook that is called for all Attribute
s and returns a (modified or updated) list of Attribute
instances. attr.asdict()
has a value_serializer hook that can change the way values are converted. Both hooks are meant to help with data (de-)serialization workflows. #653
kw_only=True
now works on Python 2. #700
raise from
now works on frozen classes on PyPy. #703, #712
attr.asdict()
and attr.astuple()
now treat frozenset
s like set
s with regards to the retain_collection_types argument. #704
attr.s()
and attr.make_class()
are not missing the collect_by_mro argument anymore. #711
Published by hynek about 4 years ago
attr.define()
, attr.frozen()
, attr.mutable()
, and attr.field()
remain provisional.
This release fixes a bunch of bugs and ergonomics but they remain mostly unchanged.
If you wish to use them together with mypy, you can simply drop this plugin into your project.
Feel free to provide feedback to them in the linked issue #668.
We will release the attrs
namespace once we have the feeling that the APIs have properly settled. #668
attr.define()
et al now correct detect __eq__
and __ne__
. #671
attr.define()
et al's hybrid behavior now also works correctly when arguments are passed. #675
It's possible to define custom __setattr__
methods on slotted classes again. #681
In 20.1.0 we introduced the inherited
attribute on the attr.Attribute
class to differentiate attributes that have been inherited and those that have been defined directly on the class.
It has shown to be problematic to involve that attribute when comparing instances of attr.Attribute
though, because when sub-classing, attributes from base classes are suddenly not equal to themselves in a super class.
Therefore the inherited
attribute will now be ignored when hashing and comparing instances of attr.Attribute
. #684
zope.interface
is now a "soft dependency" when running the test suite; if zope.interface
is not installed when running the test suite, the interface-related tests will be automatically skipped. #685
The ergonomics of creating frozen classes using @define(frozen=True)
and sub-classing frozen classes has been improved: you don't have to set on_setattr=None
anymore. #687
Published by hynek about 4 years ago
Python 3.4 is not supported anymore. It has been unsupported by the Python core team for a while now, its PyPI downloads are negligible, and our CI provider removed it as a supported option.
It's very unlikely that attrs
will break under 3.4 anytime soon, which is why we do not block its installation on Python 3.4. But we don't test it anymore and will block it once someone reports breakage. #608
Less of a deprecation and more of a heads up: the next release of attrs
will introduce an attrs
namespace. That means that you'll finally be able to run import attrs
with new functions that aren't cute abbreviations and that will carry better defaults.
This should not break any of your code, because project-local packages have priority before installed ones. If this is a problem for you for some reason, please report it to our bug tracker and we'll figure something out.
The old attr
namespace isn't going anywhere and its defaults are not changing -- this is a purely additive measure. Please check out the linked issue for more details.
These new APIs have been added provisionally as part of #666 so you can try them out today and provide feedback. Learn more in the API docs. #408
Added attr.resolve_types()
. It ensures that all forward-references and types in string form are resolved into concrete types.
You need this only if you need concrete types at runtime. That means that if you only use types for static type checking, you do not need this function. #288, #302
Added @attr.s(collect_by_mro=False)
argument that if set to True
fixes the collection of attributes from base classes.
It's only necessary for certain cases of multiple-inheritance but is kept off for now for backward-compatibility reasons. It will be turned on by default in the future.
As a side-effect, attr.Attribute
now always has an inherited
attribute indicating whether an attribute on a class was directly defined or inherited. #428, #635
On Python 3, all generated methods now have a docstring explaining that they have been created by attrs
. #506
It is now possible to prevent attrs
from auto-generating the __setstate__
and __getstate__
methods that are required for pickling of slotted classes.
Either pass @attr.s(getstate_setstate=False)
or pass @attr.s(auto_detect=True)
and implement them yourself: if attrs
finds either of the two methods directly on the decorated class, it assumes implicitly getstate_setstate=False
(and implements neither).
This option works with dict classes but should never be necessary. #512, #513, #642
Fixed a ValueError: Cell is empty
bug that could happen in some rare edge cases. #590
attrs
can now automatically detect your own implementations and infer init=False
, repr=False
, eq=False
, order=False
, and hash=False
if you set @attr.s(auto_detect=True)
. attrs
will ignore inherited methods. If the argument implies more than one method (e.g. eq=True
creates both __eq__
and __ne__
), it's enough for one of them to exist and attrs
will create neither.
This feature requires Python 3. #607
Added attr.converters.pipe()
. The feature allows combining multiple conversion callbacks into one by piping the value through all of them, and retuning the last result.
As part of this feature, we had to relax the type information for converter callables. #618
Fixed serialization behavior of non-slots classes with cache_hash=True
. The hash cache will be cleared on operations which make "deep copies" of instances of classes with hash caching, though the cache will not be cleared with shallow copies like those made by copy.copy()
.
Previously, copy.deepcopy()
or serialization and deserialization with pickle
would result in an un-initialized object.
This change also allows the creation of cache_hash=True
classes with a custom __setstate__
, which was previously forbidden (#494). #620
It is now possible to specify hooks that are called whenever an attribute is set after a class has been instantiated.
You can pass on_setattr
both to @attr.s()
to set the default for all attributes on a class, and to @attr.ib()
to overwrite it for individual attributes.
attrs
also comes with a new module attr.setters
that brings helpers that run validators, converters, or allow to freeze a subset of attributes. #645, #660
Provisional APIs called attr.define()
, attr.mutable()
, and attr.frozen()
have been added.
They are only available on Python 3.6 and later, and call attr.s()
with different default values.
If nothing comes up, they will become the official way for creating classes in 20.2.0 (see above).
Please note that it may take some time until mypy -- and other tools that have dedicated support for attrs
-- recognize these new APIs. Please do not open issues on our bug tracker, there is nothing we can do about it. #666
We have also provisionally added attr.field()
that supplants attr.ib()
. It also requires at least Python 3.6 and is keyword-only. Other than that, it only dropped a few arguments, but changed no defaults.
As with attr.s()
: attr.ib()
is not going anywhere. #669
Published by hynek almost 5 years ago
Published by hynek about 5 years ago
Published by hynek about 5 years ago
Published by hynek about 5 years ago
Published by hynek about 5 years ago
Published by hynek about 5 years ago
Published by hynek about 5 years ago