diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index ad4aeb5c..2b22ab6f 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -176,15 +176,15 @@ But it's way more comfortable to run it locally and *git* catching avoidable err If your change is noteworthy, there needs to be a changelog entry so our users can learn about it! To avoid merge conflicts, we use the [*Towncrier*](https://pypi.org/project/towncrier) package to manage our changelog. -*towncrier* uses independent files for each pull request – so called *news fragments* – instead of one monolithic changelog file. -On release, those news fragments are compiled into our [`CHANGELOG.rst`](https://github.com/python-attrs/attrs/blob/main/CHANGELOG.rst). +*towncrier* uses independent *Markdown* files for each pull request – so called *news fragments* – instead of one monolithic changelog file. +On release, those news fragments are compiled into our [`CHANGELOG.md`](https://github.com/python-attrs/attrs/blob/main/CHANGELOG.md). -You don't need to install *towncrier* yourself, you just have to abide by a few simple rules: +You don't need to install *Towncrier* yourself, you just have to abide by a few simple rules: -- For each pull request, add a new file into `changelog.d` with a filename adhering to the `pr#.(change|deprecation|breaking).rst` schema: - For example, `changelog.d/42.change.rst` for a non-breaking change that is proposed in pull request #42. +- For each pull request, add a new file into `changelog.d` with a filename adhering to the `pr#.(change|deprecation|breaking).md` schema: + For example, `changelog.d/42.change.md` for a non-breaking change that is proposed in pull request #42. - As with other docs, please use [semantic newlines] within news fragments. -- Wrap symbols like modules, functions, or classes into double backticks so they are rendered in a `monospace font`. +- Wrap symbols like modules, functions, or classes into backticks so they are rendered in a `monospace font`. - Wrap arguments into asterisks like in docstrings: `Added new argument *an_argument*.` - If you mention functions or other callables, add parentheses at the end of their names: @@ -196,19 +196,19 @@ You don't need to install *towncrier* yourself, you just have to abide by a few + Added `attrs.validators.func()`. + `attrs.func()` now doesn't crash the Large Hadron Collider anymore when passed the *foobar* argument. - If you want to reference multiple issues, copy the news fragment to another filename. - *towncrier* will merge all news fragments with identical contents into one entry with multiple links to the respective pull requests. + *Towncrier* will merge all news fragments with identical contents into one entry with multiple links to the respective pull requests. Example entries: - ```rst - Added ``attrs.validators.func()``. + ```md + Added `attrs.validators.func()`. The feature really *is* awesome. ``` or: - ```rst - ``attrs.func()`` now doesn't crash the Large Hadron Collider anymore when passed the *foobar* argument. + ```md + `attrs.func()` now doesn't crash the Large Hadron Collider anymore when passed the *foobar* argument. The bug really *was* nasty. ``` diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..ffd13942 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,1021 @@ +# Changelog + +Versions follow [CalVer](https://calver.org) with a strict backwards-compatibility policy. + +The **first number** of the version is the year. +The **second number** is incremented with each release, starting at 1 for each year. +The **third number** is when we need to start branches for older releases (only for emergencies). + +Put simply, you shouldn't ever be afraid to upgrade `attrs` if you're only using its public APIs. +Whenever there is a need to break compatibility, it is announced here in the changelog, and raises a `DeprecationWarning` for a year (if possible) before it's finally really broken. + +> **Warning** +> The structure of the `attrs.Attribute` class is exempt from this rule. +> It *will* change in the future, but since it should be considered read-only, that shouldn't matter. +> +> However if you intend to build extensions on top of `attrs` you have to anticipate that. + + +Changes for the upcoming release can be found in the ["changelog.d" directory](https://github.com/python-attrs/attrs/tree/main/changelog.d) in our repository. + + + +## [22.1.0](https://github.com/python-attrs/attrs/tree/22.1.0) - 2022-07-28 + +### Backwards-incompatible Changes + +- 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](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/939) + + +### Changes + +- Instantiation of frozen slotted classes is now faster. + [#898](https://github.com/python-attrs/attrs/issues/898) +- If an `eq` key is defined, it is also used before hashing the attribute. + [#909](https://github.com/python-attrs/attrs/issues/909) +- Added `attrs.validators.min_len()`. + [#916](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/925) +- Added missing type stub re-imports for `attrs.converters` and `attrs.filters`. + [#931](https://github.com/python-attrs/attrs/issues/931) +- Added missing stub for `attr(s).cmp_using()`. + [#949](https://github.com/python-attrs/attrs/issues/949) +- `attrs.validators._in()`'s `ValueError` is not missing the attribute, expected options, and the value it got anymore. + [#951](https://github.com/python-attrs/attrs/issues/951) +- Python 3.11 is now officially supported. + [#969](https://github.com/python-attrs/attrs/issues/969) + + +## [21.4.0](https://github.com/python-attrs/attrs/tree/21.4.0) - 2021-12-29 + +### Changes + +- Fixed the test suite on PyPy3.8 where `cloudpickle` does not work. + [#892](https://github.com/python-attrs/attrs/issues/892) +- Fixed `coverage report` for projects that use `attrs` and don't set a `--source`. + [#895](https://github.com/python-attrs/attrs/issues/895), + [#896](https://github.com/python-attrs/attrs/issues/896) + + +## [21.3.0](https://github.com/python-attrs/attrs/tree/21.3.0) - 2021-12-28 + +### Backward-incompatible Changes + +- 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](https://github.com/python-attrs/attrs/issues/835), + [#886](https://github.com/python-attrs/attrs/issues/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](https://www.attrs.org/en/latest/names.html) + + 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](https://github.com/python-attrs/attrs/issues/887) + + +### Changes + +- `attr.asdict(retain_collection_types=False)` (default) dumps collection-esque keys as tuples. + [#646](https://github.com/python-attrs/attrs/issues/646), + [#888](https://github.com/python-attrs/attrs/issues/888) +- `__match_args__` are now generated to support Python 3.10's + [Structural Pattern Matching](https://docs.python.org/3.10/whatsnew/3.10.html#pep-634-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](https://github.com/python-attrs/attrs/issues/815) +- If the class-level *on_setattr* is set to `attrs.setters.validate` (default in `@define` and `@mutable`) but no field defines a validator, pretend that it's not set. + [#817](https://github.com/python-attrs/attrs/issues/817) +- The generated `__repr__` is significantly faster on Pythons with f-strings. + [#819](https://github.com/python-attrs/attrs/issues/819) +- Attributes transformed via `field_transformer` are wrapped with `AttrsClass` again. + [#824](https://github.com/python-attrs/attrs/issues/824) +- Generated source code is now cached more efficiently for identical classes. + [#828](https://github.com/python-attrs/attrs/issues/828) +- Added `attrs.converters.to_bool()`. + [#830](https://github.com/python-attrs/attrs/issues/830) +- `attrs.resolve_types()` now resolves types of subclasses after the parents are resolved. + [#842](https://github.com/python-attrs/attrs/issues/842) + [#843](https://github.com/python-attrs/attrs/issues/843) +- Added new validators: `lt(val)` (\< val), `le(va)` (≤ val), `ge(val)` (≥ val), `gt(val)` (> val), and `maxlen(n)`. + [#845](https://github.com/python-attrs/attrs/issues/845) +- `attrs` classes are now fully compatible with [cloudpickle](https://github.com/cloudpipe/cloudpickle) (no need to disable `repr` anymore). + [#857](https://github.com/python-attrs/attrs/issues/857) +- Added new context manager `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](https://github.com/python-attrs/attrs/issues/859) +- `attrs.validators.matches_re()` now accepts pre-compiled regular expressions in addition to pattern strings. + [#877](https://github.com/python-attrs/attrs/issues/877) + +--- + +## [21.2.0](https://github.com/python-attrs/attrs/tree/21.2.0) - 2021-05-07 + +### Backward-incompatible Changes + +- We had to revert the recursive feature for `attr.evolve()` because it broke some use-cases -- sorry! + [#806](https://github.com/python-attrs/attrs/issues/806) +- Python 3.4 is now blocked using packaging metadata because `attrs` can't be imported on it anymore. + To ensure that 3.4 users can keep installing `attrs` easily, we will [yank](https://pypi.org/help/#yanked) 21.1.0 from PyPI. + This has **no** consequences if you pin `attrs` to 21.1.0. + [#807](https://github.com/python-attrs/attrs/issues/807) + + +## [21.1.0](https://github.com/python-attrs/attrs/tree/21.1.0) - 2021-05-06 + +### Deprecations + +- 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](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/773) + + +### Changes + +- It's now possible to customize the behavior of `eq` and `order` by passing in a callable. + [#435](https://github.com/python-attrs/attrs/issues/435), + [#627](https://github.com/python-attrs/attrs/issues/627) + +- The instant favorite next-generation APIs are not provisional anymore! + + They are also officially supported by Mypy as of their [0.800 release](https://mypy-lang.blogspot.com/2021/01/mypy-0800-released.html). + + We hope the next release will already contain an (additional) importable package called `attrs`. + [#668](https://github.com/python-attrs/attrs/issues/668), + [#786](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/731) + +- `bool(attr.NOTHING)` is now `False`. + [#732](https://github.com/python-attrs/attrs/issues/732) + +- It's now possible to use `super()` inside of properties of slotted classes. + [#747](https://github.com/python-attrs/attrs/issues/747) + +- Allow for a `__attrs_pre_init__()` method that -- if defined -- will get called at the beginning of the `attrs`-generated `__init__()` method. + [#750](https://github.com/python-attrs/attrs/issues/750) + +- Added forgotten `attr.Attribute.evolve()` to type stubs. + [#752](https://github.com/python-attrs/attrs/issues/752) + +- `attrs.evolve()` now works recursively with nested `attrs` classes. + [#759](https://github.com/python-attrs/attrs/issues/759) + +- Python 3.10 is now officially supported. + [#763](https://github.com/python-attrs/attrs/issues/763) + +- `attr.resolve_types()` now takes an optional *attrib* argument to work inside a `field_transformer`. + [#774](https://github.com/python-attrs/attrs/issues/774) + +- `ClassVar`s are now also detected if they come from [typing-extensions](https://pypi.org/project/typing-extensions/). + [#782](https://github.com/python-attrs/attrs/issues/782) + +- To make it easier to customize attribute comparison (#435), we have added the `attr.cmp_with()` helper. + + See the [new docs on comparison](https://www.attrs.org/en/stable/comparison.html) for more details. + [#787](https://github.com/python-attrs/attrs/issues/787) + +- Added **provisional** support for static typing in `pyright` via the [dataclass_transforms specification](https://github.com/microsoft/pyright/blob/main/specs/dataclass_transforms.md). + Both the `pyright` specification and `attrs` implementation may change in future versions of both projects. + + Your constructive feedback is welcome in both [attrs#795](https://github.com/python-attrs/attrs/issues/795) and [pyright#1782](https://github.com/microsoft/pyright/discussions/1782). + [#796](https://github.com/python-attrs/attrs/issues/796) + + +## [20.3.0](https://github.com/python-attrs/attrs/tree/20.3.0) - 2020-11-05 + +### Backward-incompatible Changes + +- `attr.define()`, `attr.frozen()`, `attr.mutable()`, and `attr.field()` remain **provisional**. + + This release does **not** 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](https://gist.github.com/hynek/1e3844d0c99e479e716169034b5fa963#file-attrs_ng_plugin-py) 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](https://github.com/python-attrs/attrs/issues/668) + +### Changes + +- `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](https://github.com/python-attrs/attrs/issues/653) +- `kw_only=True` now works on Python 2. + [#700](https://github.com/python-attrs/attrs/issues/700) +- `raise from` now works on frozen classes on PyPy. + [#703](https://github.com/python-attrs/attrs/issues/703), + [#712](https://github.com/python-attrs/attrs/issues/712) +- `attr.asdict()` and `attr.astuple()` now treat `frozenset`s like `set`s with regards to the *retain_collection_types* argument. + [#704](https://github.com/python-attrs/attrs/issues/704) +- The type stubs for `attr.s()` and `attr.make_class()` are not missing the *collect_by_mro* argument anymore. + [#711](https://github.com/python-attrs/attrs/issues/711) + +--- + +## [20.2.0](https://github.com/python-attrs/attrs/tree/20.2.0) - 2020-09-05 + +### Backward-incompatible Changes + +- `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](https://gist.github.com/hynek/1e3844d0c99e479e716169034b5fa963#file-attrs_ng_plugin-py) 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](https://github.com/python-attrs/attrs/issues/668) + +### Changes + +- `attr.define()` et al now correctly detect `__eq__` and `__ne__`. + [#671](https://github.com/python-attrs/attrs/issues/671) + +- `attr.define()` et al's hybrid behavior now also works correctly when arguments are passed. + [#675](https://github.com/python-attrs/attrs/issues/675) + +- It's possible to define custom `__setattr__` methods on slotted classes again. + [#681](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/687) + +--- + +## [20.1.0](https://github.com/python-attrs/attrs/tree/20.1.0) - 2020-08-20 + +### Backward-incompatible Changes + +- 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](https://github.com/python-attrs/attrs/issues/608) + +### Deprecations + +- 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](https://www.attrs.org/en/stable/api.html). + [#408](https://github.com/python-attrs/attrs/issues/408) + +### Changes + +- 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](https://github.com/python-attrs/attrs/issues/288), + [#302](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/428), + [#635](https://github.com/python-attrs/attrs/issues/635) + +- On Python 3, all generated methods now have a docstring explaining that they have been created by `attrs`. + [#506](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/512), + [#513](https://github.com/python-attrs/attrs/issues/513), + [#642](https://github.com/python-attrs/attrs/issues/642) + +- Fixed a `ValueError: Cell is empty` bug that could happen in some rare edge cases. + [#590](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/494)). + [#620](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/645), + [#660](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/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](https://github.com/python-attrs/attrs/issues/669) + +--- + +## [19.3.0](https://github.com/python-attrs/attrs/tree/19.3.0) - 2019-10-15 + +### Changes + +- Fixed `auto_attribs` usage when default values cannot be compared directly with `==`, such as `numpy` arrays. + [#585](https://github.com/python-attrs/attrs/issues/585) + +--- + +## [19.2.0](https://github.com/python-attrs/attrs/tree/19.2.0) - 2019-10-01 + +### Backward-incompatible Changes + +- Removed deprecated `Attribute` attribute `convert` per scheduled removal on 2019/1. + This planned deprecation is tracked in issue [#307](https://github.com/python-attrs/attrs/issues/307). + [#504](https://github.com/python-attrs/attrs/issues/504) + +- `__lt__`, `__le__`, `__gt__`, and `__ge__` do not consider subclasses comparable anymore. + + This has been deprecated since 18.2.0 and was raising a `DeprecationWarning` for over a year. + [#570](https://github.com/python-attrs/attrs/issues/570) + +### Deprecations + +- The `cmp` argument to `attr.s()` and `attr.ib()` is now deprecated. + + Please use `eq` to add equality methods (`__eq__` and `__ne__`) and `order` to add ordering methods (`__lt__`, `__le__`, `__gt__`, and `__ge__`) instead – just like with [dataclasses](https://docs.python.org/3/library/dataclasses.html). + + Both are effectively `True` by default but it's enough to set `eq=False` to disable both at once. + Passing `eq=False, order=True` explicitly will raise a `ValueError` though. + + Since this is arguably a deeper backward-compatibility break, it will have an extended deprecation period until 2021-06-01. + After that day, the `cmp` argument will be removed. + + `attr.Attribute` also isn't orderable anymore. + [#574](https://github.com/python-attrs/attrs/issues/574) + +### Changes + +- Updated `attr.validators.__all__` to include new validators added in [#425]. + [#517](https://github.com/python-attrs/attrs/issues/517) +- Slotted classes now use a pure Python mechanism to rewrite the `__class__` cell when rebuilding the class, so `super()` works even on environments where `ctypes` is not installed. + [#522](https://github.com/python-attrs/attrs/issues/522) +- When collecting attributes using `@attr.s(auto_attribs=True)`, attributes with a default of `None` are now deleted too. + [#523](https://github.com/python-attrs/attrs/issues/523), + [#556](https://github.com/python-attrs/attrs/issues/556) +- Fixed `attr.validators.deep_iterable()` and `attr.validators.deep_mapping()` type stubs. + [#533](https://github.com/python-attrs/attrs/issues/533) +- `attr.validators.is_callable()` validator now raises an exception `attr.exceptions.NotCallableError`, a subclass of `TypeError`, informing the received value. + [#536](https://github.com/python-attrs/attrs/issues/536) +- `@attr.s(auto_exc=True)` now generates classes that are hashable by ID, as the documentation always claimed it would. + [#543](https://github.com/python-attrs/attrs/issues/543), + [#563](https://github.com/python-attrs/attrs/issues/563) +- Added `attr.validators.matches_re()` that checks string attributes whether they match a regular expression. + [#552](https://github.com/python-attrs/attrs/issues/552) +- Keyword-only attributes (`kw_only=True`) and attributes that are excluded from the `attrs`'s `__init__` (`init=False`) now can appear before mandatory attributes. + [#559](https://github.com/python-attrs/attrs/issues/559) +- The fake filename for generated methods is now more stable. + It won't change when you restart the process. + [#560](https://github.com/python-attrs/attrs/issues/560) +- The value passed to `@attr.ib(repr=…)` can now be either a boolean (as before) or a callable. + That callable must return a string and is then used for formatting the attribute by the generated `__repr__()` method. + [#568](https://github.com/python-attrs/attrs/issues/568) +- Added `attr.__version_info__` that can be used to reliably check the version of `attrs` and write forward- and backward-compatible code. + Please check out the [section on deprecated APIs](https://www.attrs.org/en/stable/api.html#deprecated-apis) on how to use it. + [#580](https://github.com/python-attrs/attrs/issues/580) + +> + +--- + +## [19.1.0](https://github.com/python-attrs/attrs/tree/19.1.0) - 2019-03-03 + +### Backward-incompatible Changes + +- Fixed a bug where deserialized objects with `cache_hash=True` could have incorrect hash code values. + This change breaks classes with `cache_hash=True` when a custom `__setstate__` is present. + An exception will be thrown when applying the `attrs` annotation to such a class. + This limitation is tracked in issue [#494](https://github.com/python-attrs/attrs/issues/494). + [#482](https://github.com/python-attrs/attrs/issues/482) + +### Changes + +- Add `is_callable`, `deep_iterable`, and `deep_mapping` validators. + + - `is_callable`: validates that a value is callable + - `deep_iterable`: Allows recursion down into an iterable, + applying another validator to every member in the iterable + as well as applying an optional validator to the iterable itself. + - `deep_mapping`: Allows recursion down into the items in a mapping object, + applying a key validator and a value validator to the key and value in every item. + Also applies an optional validator to the mapping object itself. + + You can find them in the `attr.validators` package. + [#425] + +- Fixed stub files to prevent errors raised by mypy's `disallow_any_generics = True` option. + [#443](https://github.com/python-attrs/attrs/issues/443) + +- Attributes with `init=False` now can follow after `kw_only=True` attributes. + [#450](https://github.com/python-attrs/attrs/issues/450) + +- `attrs` now has first class support for defining exception classes. + + If you define a class using `@attr.s(auto_exc=True)` and subclass an exception, the class will behave like a well-behaved exception class including an appropriate `__str__` method, and all attributes additionally available in an `args` attribute. + [#500](https://github.com/python-attrs/attrs/issues/500) + +- Clarified documentation for hashing to warn that hashable objects should be deeply immutable (in their usage, even if this is not enforced). + [#503](https://github.com/python-attrs/attrs/issues/503) + +--- + +## [18.2.0](https://github.com/python-attrs/attrs/tree/18.2.0) - 2018-09-01 + +### Deprecations + +- Comparing subclasses using `<`, `>`, `<=`, and `>=` is now deprecated. + The docs always claimed that instances are only compared if the types are identical, so this is a first step to conform to the docs. + + Equality operators (`==` and `!=`) were always strict in this regard. + [#394](https://github.com/python-attrs/attrs/issues/394) + +### Changes + +- `attrs` now ships its own [PEP 484](https://peps.python.org/pep-0484/) type hints. + Together with [mypy](http://mypy-lang.org)'s `attrs` plugin, you've got all you need for writing statically typed code in both Python 2 and 3! + + At that occasion, we've also added [narrative docs](https://www.attrs.org/en/stable/types.html) about type annotations in `attrs`. + [#238](https://github.com/python-attrs/attrs/issues/238) + +- Added *kw_only* arguments to `attr.ib` and `attr.s`, and a corresponding *kw_only* attribute to `attr.Attribute`. + This change makes it possible to have a generated `__init__` with keyword-only arguments on Python 3, relaxing the required ordering of default and non-default valued attributes. + [#281](https://github.com/python-attrs/attrs/issues/281), + [#411](https://github.com/python-attrs/attrs/issues/411) + +- The test suite now runs with `hypothesis.HealthCheck.too_slow` disabled to prevent CI breakage on slower computers. + [#364](https://github.com/python-attrs/attrs/issues/364), + [#396](https://github.com/python-attrs/attrs/issues/396) + +- `attr.validators.in_()` now raises a `ValueError` with a useful message even if the options are a string and the value is not a string. + [#383](https://github.com/python-attrs/attrs/issues/383) + +- `attr.asdict()` now properly handles deeply nested lists and dictionaries. + [#395](https://github.com/python-attrs/attrs/issues/395) + +- Added `attr.converters.default_if_none()` that allows to replace `None` values in attributes. + For example `attr.ib(converter=default_if_none(""))` replaces `None` by empty strings. + [#400](https://github.com/python-attrs/attrs/issues/400), + [#414](https://github.com/python-attrs/attrs/issues/414) + +- Fixed a reference leak where the original class would remain live after being replaced when `slots=True` is set. + [#407](https://github.com/python-attrs/attrs/issues/407) + +- Slotted classes can now be made weakly referenceable by passing `@attr.s(weakref_slot=True)`. + [#420](https://github.com/python-attrs/attrs/issues/420) + +- Added *cache_hash* option to `@attr.s` which causes the hash code to be computed once and stored on the object. + [#426](https://github.com/python-attrs/attrs/issues/426) + +- Attributes can be named `property` and `itemgetter` now. + [#430](https://github.com/python-attrs/attrs/issues/430) + +- It is now possible to override a base class' class variable using only class annotations. + [#431](https://github.com/python-attrs/attrs/issues/431) + +--- + +## [18.1.0](https://github.com/python-attrs/attrs/tree/18.1.0) - 2018-05-03 + +### Changes + +- `x=X(); x.cycle = x; repr(x)` will no longer raise a `RecursionError`, and will instead show as `X(x=...)`. + + [#95](https://github.com/python-attrs/attrs/issues/95) + +- `attr.ib(factory=f)` is now syntactic sugar for the common case of `attr.ib(default=attr.Factory(f))`. + + [#178](https://github.com/python-attrs/attrs/issues/178), + [#356](https://github.com/python-attrs/attrs/issues/356) + +- Added `attr.field_dict()` to return an ordered dictionary of `attrs` attributes for a class, whose keys are the attribute names. + + [#290](https://github.com/python-attrs/attrs/issues/290), + [#349](https://github.com/python-attrs/attrs/issues/349) + +- The order of attributes that are passed into `attr.make_class()` or the *these* argument of `@attr.s()` is now retained if the dictionary is ordered (i.e. `dict` on Python 3.6 and later, `collections.OrderedDict` otherwise). + + Before, the order was always determined by the order in which the attributes have been defined which may not be desirable when creating classes programmatically. + + [#300](https://github.com/python-attrs/attrs/issues/300), + [#339](https://github.com/python-attrs/attrs/issues/339), + [#343](https://github.com/python-attrs/attrs/issues/343) + +- In slotted classes, `__getstate__` and `__setstate__` now ignore the `__weakref__` attribute. + + [#311](https://github.com/python-attrs/attrs/issues/311), + [#326](https://github.com/python-attrs/attrs/issues/326) + +- Setting the cell type is now completely best effort. + This fixes `attrs` on Jython. + + We cannot make any guarantees regarding Jython though, because our test suite cannot run due to dependency incompatibilities. + + [#321](https://github.com/python-attrs/attrs/issues/321), + [#334](https://github.com/python-attrs/attrs/issues/334) + +- If `attr.s` is passed a *these* argument, it will no longer attempt to remove attributes with the same name from the class body. + + [#322](https://github.com/python-attrs/attrs/issues/322), + [#323](https://github.com/python-attrs/attrs/issues/323) + +- The hash of `attr.NOTHING` is now vegan and faster on 32bit Python builds. + + [#331](https://github.com/python-attrs/attrs/issues/331), + [#332](https://github.com/python-attrs/attrs/issues/332) + +- The overhead of instantiating frozen dict classes is virtually eliminated. + [#336](https://github.com/python-attrs/attrs/issues/336) + +- Generated `__init__` methods now have an `__annotations__` attribute derived from the types of the fields. + + [#363](https://github.com/python-attrs/attrs/issues/363) + +- We have restructured the documentation a bit to account for `attrs`' growth in scope. + Instead of putting everything into the [examples](https://www.attrs.org/en/stable/examples.html) page, we have started to extract narrative chapters. + + So far, we've added chapters on [initialization](https://www.attrs.org/en/stable/init.html) and [hashing](https://www.attrs.org/en/stable/hashing.html). + + Expect more to come! + + [#369](https://github.com/python-attrs/attrs/issues/369), + [#370](https://github.com/python-attrs/attrs/issues/370) + +--- + +## [17.4.0](https://github.com/python-attrs/attrs/tree/17.4.0) - 2017-12-30 + +### Backward-incompatible Changes + +- The traversal of MROs when using multiple inheritance was backward: + If you defined a class `C` that subclasses `A` and `B` like `C(A, B)`, `attrs` would have collected the attributes from `B` *before* those of `A`. + + This is now fixed and means that in classes that employ multiple inheritance, the output of `__repr__` and the order of positional arguments in `__init__` changes. + Because of the nature of this bug, a proper deprecation cycle was unfortunately impossible. + + Generally speaking, it's advisable to prefer `kwargs`-based initialization anyways – *especially* if you employ multiple inheritance and diamond-shaped hierarchies. + + [#298](https://github.com/python-attrs/attrs/issues/298), + [#299](https://github.com/python-attrs/attrs/issues/299), + [#304](https://github.com/python-attrs/attrs/issues/304) + +- The `__repr__` set by `attrs` no longer produces an `AttributeError` when the instance is missing some of the specified attributes (either through deleting or after using `init=False` on some attributes). + + This can break code that relied on `repr(attr_cls_instance)` raising `AttributeError` to check if any `attrs`-specified members were unset. + + If you were using this, you can implement a custom method for checking this: + + ``` + def has_unset_members(self): + for field in attr.fields(type(self)): + try: + getattr(self, field.name) + except AttributeError: + return True + return False + ``` + + [#308](https://github.com/python-attrs/attrs/issues/308) + +### Deprecations + +- The `attr.ib(convert=callable)` option is now deprecated in favor of `attr.ib(converter=callable)`. + + This is done to achieve consistency with other noun-based arguments like *validator*. + + *convert* will keep working until at least January 2019 while raising a `DeprecationWarning`. + + [#307](https://github.com/python-attrs/attrs/issues/307) + +### Changes + +- Generated `__hash__` methods now hash the class type along with the attribute values. + Until now the hashes of two classes with the same values were identical which was a bug. + + The generated method is also *much* faster now. + + [#261](https://github.com/python-attrs/attrs/issues/261), + [#295](https://github.com/python-attrs/attrs/issues/295), + [#296](https://github.com/python-attrs/attrs/issues/296) + +- `attr.ib`’s *metadata* argument now defaults to a unique empty `dict` instance instead of sharing a common empty `dict` for all. + The singleton empty `dict` is still enforced. + + [#280](https://github.com/python-attrs/attrs/issues/280) + +- `ctypes` is optional now however if it's missing, a bare `super()` will not work in slotted classes. + This should only happen in special environments like Google App Engine. + + [#284](https://github.com/python-attrs/attrs/issues/284), + [#286](https://github.com/python-attrs/attrs/issues/286) + +- The attribute redefinition feature introduced in 17.3.0 now takes into account if an attribute is redefined via multiple inheritance. + In that case, the definition that is closer to the base of the class hierarchy wins. + + [#285](https://github.com/python-attrs/attrs/issues/285), + [#287](https://github.com/python-attrs/attrs/issues/287) + +- Subclasses of `auto_attribs=True` can be empty now. + + [#291](https://github.com/python-attrs/attrs/issues/291), + [#292](https://github.com/python-attrs/attrs/issues/292) + +- Equality tests are *much* faster now. + + [#306](https://github.com/python-attrs/attrs/issues/306) + +- All generated methods now have correct `__module__`, `__name__`, and (on Python 3) `__qualname__` attributes. + + [#309](https://github.com/python-attrs/attrs/issues/309) + +--- + +## [17.3.0](https://github.com/python-attrs/attrs/tree/17.3.0) - 2017-11-08 + +### Backward-incompatible Changes + +- Attributes are no longer defined on the class body. + + This means that if you define a class `C` with an attribute `x`, the class will *not* have an attribute `x` for introspection. + Instead of `C.x`, use `attr.fields(C).x` or look at `C.__attrs_attrs__`. + The old behavior has been deprecated since version 16.1. + ([#253](https://github.com/python-attrs/attrs/issues/253)) + +### Changes + +- `super()` and `__class__` now work with slotted classes on Python 3. + ([#102](https://github.com/python-attrs/attrs/issues/102), [#226](https://github.com/python-attrs/attrs/issues/226), [#269](https://github.com/python-attrs/attrs/issues/269), [#270](https://github.com/python-attrs/attrs/issues/270), [#272](https://github.com/python-attrs/attrs/issues/272)) + +- Added *type* argument to `attr.ib()` and corresponding `type` attribute to `attr.Attribute`. + + This change paves the way for automatic type checking and serialization (though as of this release `attrs` does not make use of it). + In Python 3.6 or higher, the value of `attr.Attribute.type` can alternately be set using variable type annotations + (see [PEP 526](https://peps.python.org/pep-0526/)). + ([#151](https://github.com/python-attrs/attrs/issues/151), [#214](https://github.com/python-attrs/attrs/issues/214), [#215](https://github.com/python-attrs/attrs/issues/215), [#239](https://github.com/python-attrs/attrs/issues/239)) + +- The combination of `str=True` and `slots=True` now works on Python 2. + ([#198](https://github.com/python-attrs/attrs/issues/198)) + +- `attr.Factory` is hashable again. + ([#204](https://github.com/python-attrs/attrs/issues/204)) + +- Subclasses now can overwrite attribute definitions of their base classes. + + That means that you can -- for example -- change the default value for an attribute by redefining it. + ([#221](https://github.com/python-attrs/attrs/issues/221), [#229](https://github.com/python-attrs/attrs/issues/229)) + +- Added new option *auto_attribs* to `@attr.s` that allows to collect annotated fields without setting them to `attr.ib()`. + + Setting a field to an `attr.ib()` is still possible to supply options like validators. + Setting it to any other value is treated like it was passed as `attr.ib(default=value)` -- passing an instance of `attr.Factory` also works as expected. + ([#262](https://github.com/python-attrs/attrs/issues/262), [#277](https://github.com/python-attrs/attrs/issues/277)) + +- Instances of classes created using `attr.make_class()` can now be pickled. + ([#282](https://github.com/python-attrs/attrs/issues/282)) + +--- + +## [17.2.0](https://github.com/python-attrs/attrs/tree/17.2.0) - 2017-05-24 + +### Changes: + +- Validators are hashable again. + Note that validators may become frozen in the future, pending availability of no-overhead frozen classes. + [#192](https://github.com/python-attrs/attrs/issues/192) + +--- + +## [17.1.0](https://github.com/python-attrs/attrs/tree/17.1.0) - 2017-05-16 + +To encourage more participation, the project has also been moved into a [dedicated GitHub organization](https://github.com/python-attrs/) and everyone is most welcome to join! + +`attrs` also has a logo now! + +```{image} https://www.attrs.org/en/latest/_static/attrs_logo.png +:alt: attrs logo +``` + +### Backward-incompatible Changes: + +- `attrs` will set the `__hash__()` method to `None` by default now. + The way hashes were handled before was in conflict with [Python's specification](https://docs.python.org/3/reference/datamodel.html#object.__hash__). + This *may* break some software although this breakage is most likely just surfacing of latent bugs. + You can always make `attrs` create the `__hash__()` method using `@attr.s(hash=True)`. + See [#136] for the rationale of this change. + + :::{warning} + Please *do not* upgrade blindly and *do* test your software! + *Especially* if you use instances as dict keys or put them into sets! + ::: + +- Correspondingly, `attr.ib`'s *hash* argument is `None` by default too and mirrors the *cmp* argument as it should. + +### Deprecations: + +- `attr.assoc()` is now deprecated in favor of `attr.evolve()` and will stop working in 2018. + +### Changes: + +- Fix default hashing behavior. + Now *hash* mirrors the value of *cmp* and classes are unhashable by default. + [#136] + [#142](https://github.com/python-attrs/attrs/issues/142) +- Added `attr.evolve()` that, given an instance of an `attrs` class and field changes as keyword arguments, will instantiate a copy of the given instance with the changes applied. + `evolve()` replaces `assoc()`, which is now deprecated. + `evolve()` is significantly faster than `assoc()`, and requires the class have an initializer that can take the field values as keyword arguments (like `attrs` itself can generate). + [#116](https://github.com/python-attrs/attrs/issues/116) + [#124](https://github.com/python-attrs/attrs/pull/124) + [#135](https://github.com/python-attrs/attrs/pull/135) +- `FrozenInstanceError` is now raised when trying to delete an attribute from a frozen class. + [#118](https://github.com/python-attrs/attrs/pull/118) +- Frozen-ness of classes is now inherited. + [#128](https://github.com/python-attrs/attrs/pull/128) +- `__attrs_post_init__()` is now run if validation is disabled. + [#130](https://github.com/python-attrs/attrs/pull/130) +- Added `attr.validators.in_(options)` that, given the allowed `options`, checks whether the attribute value is in it. + This can be used to check constants, enums, mappings, etc. + [#181](https://github.com/python-attrs/attrs/pull/181) +- Added `attr.validators.and_()` that composes multiple validators into one. + [#161](https://github.com/python-attrs/attrs/issues/161) +- For convenience, the *validator* argument of `@attr.s` now can take a list of validators that are wrapped using `and_()`. + [#138](https://github.com/python-attrs/attrs/issues/138) +- Accordingly, `attr.validators.optional()` now can take a list of validators too. + [#161](https://github.com/python-attrs/attrs/issues/161) +- Validators can now be defined conveniently inline by using the attribute as a decorator. + Check out the [validator examples](https://www.attrs.org/en/stable/init.html#decorator) to see it in action! + [#143](https://github.com/python-attrs/attrs/issues/143) +- `attr.Factory()` now has a *takes_self* argument that makes the initializer to pass the partially initialized instance into the factory. + In other words you can define attribute defaults based on other attributes. + [#165] + [#189](https://github.com/python-attrs/attrs/issues/189) +- Default factories can now also be defined inline using decorators. + They are *always* passed the partially initialized instance. + [#165] +- Conversion can now be made optional using `attr.converters.optional()`. + [#105](https://github.com/python-attrs/attrs/issues/105) + [#173](https://github.com/python-attrs/attrs/pull/173) +- `attr.make_class()` now accepts the keyword argument `bases` which allows for subclassing. + [#152](https://github.com/python-attrs/attrs/pull/152) +- Metaclasses are now preserved with `slots=True`. + [#155](https://github.com/python-attrs/attrs/pull/155) + +--- + +## [16.3.0](https://github.com/python-attrs/attrs/tree/16.3.0) - 2016-11-24 + +### Changes: + +- Attributes now can have user-defined metadata which greatly improves `attrs`'s extensibility. + [#96](https://github.com/python-attrs/attrs/pull/96) + +- Allow for a `__attrs_post_init__()` method that -- if defined -- will get called at the end of the `attrs`-generated `__init__()` method. + [#111](https://github.com/python-attrs/attrs/pull/111) + +- Added `@attr.s(str=True)` that will optionally create a `__str__()` method that is identical to `__repr__()`. + This is mainly useful with `Exception`s and other classes that rely on a useful `__str__()` implementation but overwrite the default one through a poor own one. + Default Python class behavior is to use `__repr__()` as `__str__()` anyways. + + If you tried using `attrs` with `Exception`s and were puzzled by the tracebacks: this option is for you. + +- `__name__` is no longer overwritten with `__qualname__` for `attr.s(slots=True)` classes. + [#99](https://github.com/python-attrs/attrs/issues/99) + +--- + +## [16.2.0](https://github.com/python-attrs/attrs/tree/16.2.0) - 2016-09-17 + +### Changes: + +- Added `attr.astuple()` that -- similarly to `attr.asdict()` -- returns the instance as a tuple. + [#77](https://github.com/python-attrs/attrs/issues/77) +- Converters now work with frozen classes. + [#76](https://github.com/python-attrs/attrs/issues/76) +- Instantiation of `attrs` classes with converters is now significantly faster. + [#80](https://github.com/python-attrs/attrs/pull/80) +- Pickling now works with slotted classes. + [#81](https://github.com/python-attrs/attrs/issues/81) +- `attr.assoc()` now works with slotted classes. + [#84](https://github.com/python-attrs/attrs/issues/84) +- The tuple returned by `attr.fields()` now also allows to access the `Attribute` instances by name. + Yes, we've subclassed `tuple` so you don't have to! + Therefore `attr.fields(C).x` is equivalent to the deprecated `C.x` and works with slotted classes. + [#88](https://github.com/python-attrs/attrs/issues/88) + +--- + +## [16.1.0](https://github.com/python-attrs/attrs/tree/16.1.0) - 2016-08-30 + +### Backward-incompatible Changes: + +- All instances where function arguments were called `cl` have been changed to the more Pythonic `cls`. + Since it was always the first argument, it's doubtful anyone ever called those function with in the keyword form. + If so, sorry for any breakage but there's no practical deprecation path to solve this ugly wart. + +### Deprecations: + +- Accessing `Attribute` instances on class objects is now deprecated and will stop working in 2017. + If you need introspection please use the `__attrs_attrs__` attribute or the `attr.fields()` function that carry them too. + In the future, the attributes that are defined on the class body and are usually overwritten in your `__init__` method are simply removed after `@attr.s` has been applied. + + This will remove the confusing error message if you write your own `__init__` and forget to initialize some attribute. + Instead you will get a straightforward `AttributeError`. + In other words: decorated classes will work more like plain Python classes which was always `attrs`'s goal. + +- The serious-business aliases `attr.attributes` and `attr.attr` have been deprecated in favor of `attr.attrs` and `attr.attrib` which are much more consistent and frankly obvious in hindsight. + They will be purged from documentation immediately but there are no plans to actually remove them. + +### Changes: + +- `attr.asdict()`'s `dict_factory` arguments is now propagated on recursion. + [#45](https://github.com/python-attrs/attrs/issues/45) +- `attr.asdict()`, `attr.has()` and `attr.fields()` are significantly faster. + [#48](https://github.com/python-attrs/attrs/issues/48) + [#51](https://github.com/python-attrs/attrs/issues/51) +- Add `attr.attrs` and `attr.attrib` as a more consistent aliases for `attr.s` and `attr.ib`. +- Add *frozen* option to `attr.s` that will make instances best-effort immutable. + [#60](https://github.com/python-attrs/attrs/issues/60) +- `attr.asdict()` now takes `retain_collection_types` as an argument. + If `True`, it does not convert attributes of type `tuple` or `set` to `list`. + [#69](https://github.com/python-attrs/attrs/issues/69) + +--- + +## [16.0.0](https://github.com/python-attrs/attrs/tree/16.0.0) - 2016-05-23 + +### Backward-incompatible Changes: + +- Python 3.3 and 2.6 are no longer supported. + They may work by chance but any effort to keep them working has ceased. + + The last Python 2.6 release was on October 29, 2013 and is no longer supported by the CPython core team. + Major Python packages like Django and Twisted dropped Python 2.6 a while ago already. + + Python 3.3 never had a significant user base and wasn't part of any distribution's LTS release. + +### Changes: + +- `__slots__` have arrived! + Classes now can automatically be [slotted](https://docs.python.org/3/reference/datamodel.html#slots)-style (and save your precious memory) just by passing `slots=True`. + [#35](https://github.com/python-attrs/attrs/issues/35) +- Allow the case of initializing attributes that are set to `init=False`. + This allows for clean initializer parameter lists while being able to initialize attributes to default values. + [#32](https://github.com/python-attrs/attrs/issues/32) +- `attr.asdict()` can now produce arbitrary mappings instead of Python `dict`s when provided with a `dict_factory` argument. + [#40](https://github.com/python-attrs/attrs/issues/40) +- Multiple performance improvements. + +--- + +## [15.2.0](https://github.com/python-attrs/attrs/tree/15.2.0) - 2015-12-08 + +### Changes: + +- Added a `convert` argument to `attr.ib`, which allows specifying a function to run on arguments. + This allows for simple type conversions, e.g. with `attr.ib(convert=int)`. + [#26](https://github.com/python-attrs/attrs/issues/26) +- Speed up object creation when attribute validators are used. + [#28](https://github.com/python-attrs/attrs/issues/28) + +--- + +## [15.1.0](https://github.com/python-attrs/attrs/tree/15.1.0) - 2015-08-20 + +### Changes: + +- Added `attr.validators.optional()` that wraps other validators allowing attributes to be `None`. + [#16](https://github.com/python-attrs/attrs/issues/16) +- Multi-level inheritance now works. + [#24](https://github.com/python-attrs/attrs/issues/24) +- `__repr__()` now works with non-redecorated subclasses. + [#20](https://github.com/python-attrs/attrs/issues/20) + +--- + +## [15.0.0](https://github.com/python-attrs/attrs/tree/15.0.0) - 2015-04-15 + +### Changes: + +Initial release. + +[#136]: https://github.com/python-attrs/attrs/issues/136 +[#165]: https://github.com/python-attrs/attrs/issues/165 +[#425]: https://github.com/python-attrs/attrs/issues/425 diff --git a/CHANGELOG.rst b/CHANGELOG.rst deleted file mode 100644 index 6a8d02fd..00000000 --- a/CHANGELOG.rst +++ /dev/null @@ -1,1078 +0,0 @@ -Changelog -========= - -Versions follow `CalVer `_ with a strict backwards-compatibility policy. - -The **first number** of the version is the year. -The **second number** is incremented with each release, starting at 1 for each year. -The **third number** is when we need to start branches for older releases (only for emergencies). - -Put simply, you shouldn't ever be afraid to upgrade ``attrs`` if you're only using its public APIs. -Whenever there is a need to break compatibility, it is announced here in the changelog, and raises a ``DeprecationWarning`` for a year (if possible) before it's finally really broken. - -.. warning:: - - The structure of the `attrs.Attribute` class is exempt from this rule. - It *will* change in the future, but since it should be considered read-only, that shouldn't matter. - - However if you intend to build extensions on top of ``attrs`` you have to anticipate that. - -Changes for the upcoming release can be found in the `"changelog.d" directory `_ in our repository. - -.. - Do *NOT* add changelog entries here! - - This changelog is managed by towncrier and is compiled at release time. - - See https://github.com/python-attrs/attrs/blob/main/.github/CONTRIBUTING.md#changelog for details. - -.. towncrier release notes start - -22.1.0 (2022-07-28) -------------------- - -Backwards-incompatible Changes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- 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 `_ - - -Changes -^^^^^^^ - -- Instantiation of frozen slotted classes is now faster. - `#898 `_ -- If an ``eq`` key is defined, it is also used before hashing the attribute. - `#909 `_ -- Added ``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 `_ -- Added missing type stub re-imports for ``attrs.converters`` and ``attrs.filters``. - `#931 `_ -- Added missing stub for ``attr(s).cmp_using()``. - `#949 `_ -- ``attrs.validators._in()``'s ``ValueError`` is not missing the attribute, expected options, and the value it got anymore. - `#951 `_ -- Python 3.11 is now officially supported. - `#969 `_ - - ----- - - -21.4.0 (2021-12-29) -------------------- - -Changes -^^^^^^^ - -- Fixed the test suite on PyPy3.8 where ``cloudpickle`` does not work. - `#892 `_ -- Fixed ``coverage report`` for projects that use ``attrs`` and don't set a ``--source``. - `#895 `_, - `#896 `_ - - ----- - - -21.3.0 (2021-12-28) -------------------- - -Backward-incompatible Changes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- 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 `_ - - -Changes -^^^^^^^ - -- ``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 `_ -- If the class-level *on_setattr* is set to ``attrs.setters.validate`` (default in ``@define`` and ``@mutable``) but no field defines a validator, pretend that it's not set. - `#817 `_ -- The generated ``__repr__`` is significantly faster on Pythons with f-strings. - `#819 `_ -- Attributes transformed via ``field_transformer`` are wrapped with ``AttrsClass`` again. - `#824 `_ -- Generated source code is now cached more efficiently for identical classes. - `#828 `_ -- Added ``attrs.converters.to_bool()``. - `#830 `_ -- ``attrs.resolve_types()`` now resolves types of subclasses after the parents are resolved. - `#842 `_ - `#843 `_ -- Added new validators: ``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 `_ -- Added new context manager ``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 `_ - - ----- - - -21.2.0 (2021-05-07) -------------------- - -Backward-incompatible Changes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- We had to revert the recursive feature for ``attr.evolve()`` because it broke some use-cases -- sorry! - `#806 `_ -- Python 3.4 is now blocked using packaging metadata because ``attrs`` can't be imported on it anymore. - To ensure that 3.4 users can keep installing ``attrs`` easily, we will `yank `_ 21.1.0 from PyPI. - This has **no** consequences if you pin ``attrs`` to 21.1.0. - `#807 `_ - - ----- - - -21.1.0 (2021-05-06) -------------------- - -Deprecations -^^^^^^^^^^^^ - -- 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 `_ - - -Changes -^^^^^^^ - -- 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 `_ - - ----- - - -20.3.0 (2020-11-05) -------------------- - -Backward-incompatible Changes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- ``attr.define()``, ``attr.frozen()``, ``attr.mutable()``, and ``attr.field()`` remain **provisional**. - - This release does **not** 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 `_ - - -Changes -^^^^^^^ - -- ``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 `_ -- The type stubs for ``attr.s()`` and ``attr.make_class()`` are not missing the *collect_by_mro* argument anymore. - `#711 `_ - - ----- - - -20.2.0 (2020-09-05) -------------------- - -Backward-incompatible Changes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- ``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 `_ - - -Changes -^^^^^^^ - -- ``attr.define()`` et al now correctly 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 `_ - - ----- - - -20.1.0 (2020-08-20) -------------------- - -Backward-incompatible Changes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- 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 `_ - - -Deprecations -^^^^^^^^^^^^ - -- 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 `_ - - -Changes -^^^^^^^ - -- 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 `_ - - ----- - - -19.3.0 (2019-10-15) -------------------- - -Changes -^^^^^^^ - -- Fixed ``auto_attribs`` usage when default values cannot be compared directly with ``==``, such as ``numpy`` arrays. - `#585 `_ - - ----- - - -19.2.0 (2019-10-01) -------------------- - -Backward-incompatible Changes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- Removed deprecated ``Attribute`` attribute ``convert`` per scheduled removal on 2019/1. - This planned deprecation is tracked in issue `#307 `_. - `#504 `_ -- ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` do not consider subclasses comparable anymore. - - This has been deprecated since 18.2.0 and was raising a ``DeprecationWarning`` for over a year. - `#570 `_ - - -Deprecations -^^^^^^^^^^^^ - -- The ``cmp`` argument to ``attr.s()`` and ``attr.ib()`` is now deprecated. - - Please use ``eq`` to add equality methods (``__eq__`` and ``__ne__``) and ``order`` to add ordering methods (``__lt__``, ``__le__``, ``__gt__``, and ``__ge__``) instead – just like with `dataclasses `_. - - Both are effectively ``True`` by default but it's enough to set ``eq=False`` to disable both at once. - Passing ``eq=False, order=True`` explicitly will raise a ``ValueError`` though. - - Since this is arguably a deeper backward-compatibility break, it will have an extended deprecation period until 2021-06-01. - After that day, the ``cmp`` argument will be removed. - - ``attr.Attribute`` also isn't orderable anymore. - `#574 `_ - - -Changes -^^^^^^^ - -- Updated ``attr.validators.__all__`` to include new validators added in `#425`_. - `#517 `_ -- Slotted classes now use a pure Python mechanism to rewrite the ``__class__`` cell when rebuilding the class, so ``super()`` works even on environments where ``ctypes`` is not installed. - `#522 `_ -- When collecting attributes using ``@attr.s(auto_attribs=True)``, attributes with a default of ``None`` are now deleted too. - `#523 `_, - `#556 `_ -- Fixed ``attr.validators.deep_iterable()`` and ``attr.validators.deep_mapping()`` type stubs. - `#533 `_ -- ``attr.validators.is_callable()`` validator now raises an exception ``attr.exceptions.NotCallableError``, a subclass of ``TypeError``, informing the received value. - `#536 `_ -- ``@attr.s(auto_exc=True)`` now generates classes that are hashable by ID, as the documentation always claimed it would. - `#543 `_, - `#563 `_ -- Added ``attr.validators.matches_re()`` that checks string attributes whether they match a regular expression. - `#552 `_ -- Keyword-only attributes (``kw_only=True``) and attributes that are excluded from the ``attrs``'s ``__init__`` (``init=False``) now can appear before mandatory attributes. - `#559 `_ -- The fake filename for generated methods is now more stable. - It won't change when you restart the process. - `#560 `_ -- The value passed to ``@attr.ib(repr=…)`` can now be either a boolean (as before) or a callable. - That callable must return a string and is then used for formatting the attribute by the generated ``__repr__()`` method. - `#568 `_ -- Added ``attr.__version_info__`` that can be used to reliably check the version of ``attrs`` and write forward- and backward-compatible code. - Please check out the `section on deprecated APIs `_ on how to use it. - `#580 `_ - - .. _`#425`: https://github.com/python-attrs/attrs/issues/425 - - ----- - - -19.1.0 (2019-03-03) -------------------- - -Backward-incompatible Changes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- Fixed a bug where deserialized objects with ``cache_hash=True`` could have incorrect hash code values. - This change breaks classes with ``cache_hash=True`` when a custom ``__setstate__`` is present. - An exception will be thrown when applying the ``attrs`` annotation to such a class. - This limitation is tracked in issue `#494 `_. - `#482 `_ - - -Changes -^^^^^^^ - -- Add ``is_callable``, ``deep_iterable``, and ``deep_mapping`` validators. - - * ``is_callable``: validates that a value is callable - * ``deep_iterable``: Allows recursion down into an iterable, - applying another validator to every member in the iterable - as well as applying an optional validator to the iterable itself. - * ``deep_mapping``: Allows recursion down into the items in a mapping object, - applying a key validator and a value validator to the key and value in every item. - Also applies an optional validator to the mapping object itself. - - You can find them in the ``attr.validators`` package. - `#425`_ -- Fixed stub files to prevent errors raised by mypy's ``disallow_any_generics = True`` option. - `#443 `_ -- Attributes with ``init=False`` now can follow after ``kw_only=True`` attributes. - `#450 `_ -- ``attrs`` now has first class support for defining exception classes. - - If you define a class using ``@attr.s(auto_exc=True)`` and subclass an exception, the class will behave like a well-behaved exception class including an appropriate ``__str__`` method, and all attributes additionally available in an ``args`` attribute. - `#500 `_ -- Clarified documentation for hashing to warn that hashable objects should be deeply immutable (in their usage, even if this is not enforced). - `#503 `_ - - ----- - - -18.2.0 (2018-09-01) -------------------- - -Deprecations -^^^^^^^^^^^^ - -- Comparing subclasses using ``<``, ``>``, ``<=``, and ``>=`` is now deprecated. - The docs always claimed that instances are only compared if the types are identical, so this is a first step to conform to the docs. - - Equality operators (``==`` and ``!=``) were always strict in this regard. - `#394 `_ - - -Changes -^^^^^^^ - -- ``attrs`` now ships its own `PEP 484 `_ type hints. - Together with `mypy `_'s ``attrs`` plugin, you've got all you need for writing statically typed code in both Python 2 and 3! - - At that occasion, we've also added `narrative docs `_ about type annotations in ``attrs``. - `#238 `_ -- Added *kw_only* arguments to ``attr.ib`` and ``attr.s``, and a corresponding *kw_only* attribute to ``attr.Attribute``. - This change makes it possible to have a generated ``__init__`` with keyword-only arguments on Python 3, relaxing the required ordering of default and non-default valued attributes. - `#281 `_, - `#411 `_ -- The test suite now runs with ``hypothesis.HealthCheck.too_slow`` disabled to prevent CI breakage on slower computers. - `#364 `_, - `#396 `_ -- ``attr.validators.in_()`` now raises a ``ValueError`` with a useful message even if the options are a string and the value is not a string. - `#383 `_ -- ``attr.asdict()`` now properly handles deeply nested lists and dictionaries. - `#395 `_ -- Added ``attr.converters.default_if_none()`` that allows to replace ``None`` values in attributes. - For example ``attr.ib(converter=default_if_none(""))`` replaces ``None`` by empty strings. - `#400 `_, - `#414 `_ -- Fixed a reference leak where the original class would remain live after being replaced when ``slots=True`` is set. - `#407 `_ -- Slotted classes can now be made weakly referenceable by passing ``@attr.s(weakref_slot=True)``. - `#420 `_ -- Added *cache_hash* option to ``@attr.s`` which causes the hash code to be computed once and stored on the object. - `#426 `_ -- Attributes can be named ``property`` and ``itemgetter`` now. - `#430 `_ -- It is now possible to override a base class' class variable using only class annotations. - `#431 `_ - - ----- - - -18.1.0 (2018-05-03) -------------------- - -Changes -^^^^^^^ - -- ``x=X(); x.cycle = x; repr(x)`` will no longer raise a ``RecursionError``, and will instead show as ``X(x=...)``. - - `#95 `_ -- ``attr.ib(factory=f)`` is now syntactic sugar for the common case of ``attr.ib(default=attr.Factory(f))``. - - `#178 `_, - `#356 `_ -- Added ``attr.field_dict()`` to return an ordered dictionary of ``attrs`` attributes for a class, whose keys are the attribute names. - - `#290 `_, - `#349 `_ -- The order of attributes that are passed into ``attr.make_class()`` or the *these* argument of ``@attr.s()`` is now retained if the dictionary is ordered (i.e. ``dict`` on Python 3.6 and later, ``collections.OrderedDict`` otherwise). - - Before, the order was always determined by the order in which the attributes have been defined which may not be desirable when creating classes programmatically. - - `#300 `_, - `#339 `_, - `#343 `_ -- In slotted classes, ``__getstate__`` and ``__setstate__`` now ignore the ``__weakref__`` attribute. - - `#311 `_, - `#326 `_ -- Setting the cell type is now completely best effort. - This fixes ``attrs`` on Jython. - - We cannot make any guarantees regarding Jython though, because our test suite cannot run due to dependency incompatibilities. - - `#321 `_, - `#334 `_ -- If ``attr.s`` is passed a *these* argument, it will no longer attempt to remove attributes with the same name from the class body. - - `#322 `_, - `#323 `_ -- The hash of ``attr.NOTHING`` is now vegan and faster on 32bit Python builds. - - `#331 `_, - `#332 `_ -- The overhead of instantiating frozen dict classes is virtually eliminated. - `#336 `_ -- Generated ``__init__`` methods now have an ``__annotations__`` attribute derived from the types of the fields. - - `#363 `_ -- We have restructured the documentation a bit to account for ``attrs``' growth in scope. - Instead of putting everything into the `examples `_ page, we have started to extract narrative chapters. - - So far, we've added chapters on `initialization `_ and `hashing `_. - - Expect more to come! - - `#369 `_, - `#370 `_ - - ----- - - -17.4.0 (2017-12-30) -------------------- - -Backward-incompatible Changes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- The traversal of MROs when using multiple inheritance was backward: - If you defined a class ``C`` that subclasses ``A`` and ``B`` like ``C(A, B)``, ``attrs`` would have collected the attributes from ``B`` *before* those of ``A``. - - This is now fixed and means that in classes that employ multiple inheritance, the output of ``__repr__`` and the order of positional arguments in ``__init__`` changes. - Because of the nature of this bug, a proper deprecation cycle was unfortunately impossible. - - Generally speaking, it's advisable to prefer ``kwargs``-based initialization anyways – *especially* if you employ multiple inheritance and diamond-shaped hierarchies. - - `#298 `_, - `#299 `_, - `#304 `_ -- The ``__repr__`` set by ``attrs`` no longer produces an ``AttributeError`` when the instance is missing some of the specified attributes (either through deleting or after using ``init=False`` on some attributes). - - This can break code that relied on ``repr(attr_cls_instance)`` raising ``AttributeError`` to check if any ``attrs``-specified members were unset. - - If you were using this, you can implement a custom method for checking this:: - - def has_unset_members(self): - for field in attr.fields(type(self)): - try: - getattr(self, field.name) - except AttributeError: - return True - return False - - `#308 `_ - - -Deprecations -^^^^^^^^^^^^ - -- The ``attr.ib(convert=callable)`` option is now deprecated in favor of ``attr.ib(converter=callable)``. - - This is done to achieve consistency with other noun-based arguments like *validator*. - - *convert* will keep working until at least January 2019 while raising a ``DeprecationWarning``. - - `#307 `_ - - -Changes -^^^^^^^ - -- Generated ``__hash__`` methods now hash the class type along with the attribute values. - Until now the hashes of two classes with the same values were identical which was a bug. - - The generated method is also *much* faster now. - - `#261 `_, - `#295 `_, - `#296 `_ -- ``attr.ib``\ ’s *metadata* argument now defaults to a unique empty ``dict`` instance instead of sharing a common empty ``dict`` for all. - The singleton empty ``dict`` is still enforced. - - `#280 `_ -- ``ctypes`` is optional now however if it's missing, a bare ``super()`` will not work in slotted classes. - This should only happen in special environments like Google App Engine. - - `#284 `_, - `#286 `_ -- The attribute redefinition feature introduced in 17.3.0 now takes into account if an attribute is redefined via multiple inheritance. - In that case, the definition that is closer to the base of the class hierarchy wins. - - `#285 `_, - `#287 `_ -- Subclasses of ``auto_attribs=True`` can be empty now. - - `#291 `_, - `#292 `_ -- Equality tests are *much* faster now. - - `#306 `_ -- All generated methods now have correct ``__module__``, ``__name__``, and (on Python 3) ``__qualname__`` attributes. - - `#309 `_ - - ----- - - -17.3.0 (2017-11-08) -------------------- - -Backward-incompatible Changes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- Attributes are no longer defined on the class body. - - This means that if you define a class ``C`` with an attribute ``x``, the class will *not* have an attribute ``x`` for introspection. - Instead of ``C.x``, use ``attr.fields(C).x`` or look at ``C.__attrs_attrs__``. - The old behavior has been deprecated since version 16.1. - (`#253 `_) - - -Changes -^^^^^^^ - -- ``super()`` and ``__class__`` now work with slotted classes on Python 3. - (`#102 `_, `#226 `_, `#269 `_, `#270 `_, `#272 `_) -- Added *type* argument to ``attr.ib()`` and corresponding ``type`` attribute to ``attr.Attribute``. - - This change paves the way for automatic type checking and serialization (though as of this release ``attrs`` does not make use of it). - In Python 3.6 or higher, the value of ``attr.Attribute.type`` can alternately be set using variable type annotations - (see `PEP 526 `_). - (`#151 `_, `#214 `_, `#215 `_, `#239 `_) -- The combination of ``str=True`` and ``slots=True`` now works on Python 2. - (`#198 `_) -- ``attr.Factory`` is hashable again. - (`#204 `_) -- Subclasses now can overwrite attribute definitions of their base classes. - - That means that you can -- for example -- change the default value for an attribute by redefining it. - (`#221 `_, `#229 `_) -- Added new option *auto_attribs* to ``@attr.s`` that allows to collect annotated fields without setting them to ``attr.ib()``. - - Setting a field to an ``attr.ib()`` is still possible to supply options like validators. - Setting it to any other value is treated like it was passed as ``attr.ib(default=value)`` -- passing an instance of ``attr.Factory`` also works as expected. - (`#262 `_, `#277 `_) -- Instances of classes created using ``attr.make_class()`` can now be pickled. - (`#282 `_) - - ----- - - -17.2.0 (2017-05-24) -------------------- - - -Changes: -^^^^^^^^ - -- Validators are hashable again. - Note that validators may become frozen in the future, pending availability of no-overhead frozen classes. - `#192 `_ - - ----- - - -17.1.0 (2017-05-16) -------------------- - -To encourage more participation, the project has also been moved into a `dedicated GitHub organization `_ and everyone is most welcome to join! - -``attrs`` also has a logo now! - -.. image:: https://www.attrs.org/en/latest/_static/attrs_logo.png - :alt: attrs logo - - -Backward-incompatible Changes: -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- ``attrs`` will set the ``__hash__()`` method to ``None`` by default now. - The way hashes were handled before was in conflict with `Python's specification `_. - This *may* break some software although this breakage is most likely just surfacing of latent bugs. - You can always make ``attrs`` create the ``__hash__()`` method using ``@attr.s(hash=True)``. - See `#136`_ for the rationale of this change. - - .. warning:: - - Please *do not* upgrade blindly and *do* test your software! - *Especially* if you use instances as dict keys or put them into sets! - -- Correspondingly, ``attr.ib``'s *hash* argument is ``None`` by default too and mirrors the *cmp* argument as it should. - - -Deprecations: -^^^^^^^^^^^^^ - -- ``attr.assoc()`` is now deprecated in favor of ``attr.evolve()`` and will stop working in 2018. - - -Changes: -^^^^^^^^ - -- Fix default hashing behavior. - Now *hash* mirrors the value of *cmp* and classes are unhashable by default. - `#136`_ - `#142 `_ -- Added ``attr.evolve()`` that, given an instance of an ``attrs`` class and field changes as keyword arguments, will instantiate a copy of the given instance with the changes applied. - ``evolve()`` replaces ``assoc()``, which is now deprecated. - ``evolve()`` is significantly faster than ``assoc()``, and requires the class have an initializer that can take the field values as keyword arguments (like ``attrs`` itself can generate). - `#116 `_ - `#124 `_ - `#135 `_ -- ``FrozenInstanceError`` is now raised when trying to delete an attribute from a frozen class. - `#118 `_ -- Frozen-ness of classes is now inherited. - `#128 `_ -- ``__attrs_post_init__()`` is now run if validation is disabled. - `#130 `_ -- Added ``attr.validators.in_(options)`` that, given the allowed ``options``, checks whether the attribute value is in it. - This can be used to check constants, enums, mappings, etc. - `#181 `_ -- Added ``attr.validators.and_()`` that composes multiple validators into one. - `#161 `_ -- For convenience, the *validator* argument of ``@attr.s`` now can take a list of validators that are wrapped using ``and_()``. - `#138 `_ -- Accordingly, ``attr.validators.optional()`` now can take a list of validators too. - `#161 `_ -- Validators can now be defined conveniently inline by using the attribute as a decorator. - Check out the `validator examples `_ to see it in action! - `#143 `_ -- ``attr.Factory()`` now has a *takes_self* argument that makes the initializer to pass the partially initialized instance into the factory. - In other words you can define attribute defaults based on other attributes. - `#165`_ - `#189 `_ -- Default factories can now also be defined inline using decorators. - They are *always* passed the partially initialized instance. - `#165`_ -- Conversion can now be made optional using ``attr.converters.optional()``. - `#105 `_ - `#173 `_ -- ``attr.make_class()`` now accepts the keyword argument ``bases`` which allows for subclassing. - `#152 `_ -- Metaclasses are now preserved with ``slots=True``. - `#155 `_ - -.. _`#136`: https://github.com/python-attrs/attrs/issues/136 -.. _`#165`: https://github.com/python-attrs/attrs/issues/165 - - ----- - - -16.3.0 (2016-11-24) -------------------- - -Changes: -^^^^^^^^ - -- Attributes now can have user-defined metadata which greatly improves ``attrs``'s extensibility. - `#96 `_ -- Allow for a ``__attrs_post_init__()`` method that -- if defined -- will get called at the end of the ``attrs``-generated ``__init__()`` method. - `#111 `_ -- Added ``@attr.s(str=True)`` that will optionally create a ``__str__()`` method that is identical to ``__repr__()``. - This is mainly useful with ``Exception``\ s and other classes that rely on a useful ``__str__()`` implementation but overwrite the default one through a poor own one. - Default Python class behavior is to use ``__repr__()`` as ``__str__()`` anyways. - - If you tried using ``attrs`` with ``Exception``\ s and were puzzled by the tracebacks: this option is for you. -- ``__name__`` is no longer overwritten with ``__qualname__`` for ``attr.s(slots=True)`` classes. - `#99 `_ - - ----- - - -16.2.0 (2016-09-17) -------------------- - -Changes: -^^^^^^^^ - -- Added ``attr.astuple()`` that -- similarly to ``attr.asdict()`` -- returns the instance as a tuple. - `#77 `_ -- Converters now work with frozen classes. - `#76 `_ -- Instantiation of ``attrs`` classes with converters is now significantly faster. - `#80 `_ -- Pickling now works with slotted classes. - `#81 `_ -- ``attr.assoc()`` now works with slotted classes. - `#84 `_ -- The tuple returned by ``attr.fields()`` now also allows to access the ``Attribute`` instances by name. - Yes, we've subclassed ``tuple`` so you don't have to! - Therefore ``attr.fields(C).x`` is equivalent to the deprecated ``C.x`` and works with slotted classes. - `#88 `_ - - ----- - - -16.1.0 (2016-08-30) -------------------- - -Backward-incompatible Changes: -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- All instances where function arguments were called ``cl`` have been changed to the more Pythonic ``cls``. - Since it was always the first argument, it's doubtful anyone ever called those function with in the keyword form. - If so, sorry for any breakage but there's no practical deprecation path to solve this ugly wart. - - -Deprecations: -^^^^^^^^^^^^^ - -- Accessing ``Attribute`` instances on class objects is now deprecated and will stop working in 2017. - If you need introspection please use the ``__attrs_attrs__`` attribute or the ``attr.fields()`` function that carry them too. - In the future, the attributes that are defined on the class body and are usually overwritten in your ``__init__`` method are simply removed after ``@attr.s`` has been applied. - - This will remove the confusing error message if you write your own ``__init__`` and forget to initialize some attribute. - Instead you will get a straightforward ``AttributeError``. - In other words: decorated classes will work more like plain Python classes which was always ``attrs``'s goal. -- The serious-business aliases ``attr.attributes`` and ``attr.attr`` have been deprecated in favor of ``attr.attrs`` and ``attr.attrib`` which are much more consistent and frankly obvious in hindsight. - They will be purged from documentation immediately but there are no plans to actually remove them. - - -Changes: -^^^^^^^^ - -- ``attr.asdict()``\ 's ``dict_factory`` arguments is now propagated on recursion. - `#45 `_ -- ``attr.asdict()``, ``attr.has()`` and ``attr.fields()`` are significantly faster. - `#48 `_ - `#51 `_ -- Add ``attr.attrs`` and ``attr.attrib`` as a more consistent aliases for ``attr.s`` and ``attr.ib``. -- Add *frozen* option to ``attr.s`` that will make instances best-effort immutable. - `#60 `_ -- ``attr.asdict()`` now takes ``retain_collection_types`` as an argument. - If ``True``, it does not convert attributes of type ``tuple`` or ``set`` to ``list``. - `#69 `_ - - ----- - - -16.0.0 (2016-05-23) -------------------- - -Backward-incompatible Changes: -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- Python 3.3 and 2.6 are no longer supported. - They may work by chance but any effort to keep them working has ceased. - - The last Python 2.6 release was on October 29, 2013 and is no longer supported by the CPython core team. - Major Python packages like Django and Twisted dropped Python 2.6 a while ago already. - - Python 3.3 never had a significant user base and wasn't part of any distribution's LTS release. - -Changes: -^^^^^^^^ - -- ``__slots__`` have arrived! - Classes now can automatically be `slotted `_-style (and save your precious memory) just by passing ``slots=True``. - `#35 `_ -- Allow the case of initializing attributes that are set to ``init=False``. - This allows for clean initializer parameter lists while being able to initialize attributes to default values. - `#32 `_ -- ``attr.asdict()`` can now produce arbitrary mappings instead of Python ``dict``\ s when provided with a ``dict_factory`` argument. - `#40 `_ -- Multiple performance improvements. - - ----- - - -15.2.0 (2015-12-08) -------------------- - -Changes: -^^^^^^^^ - -- Added a ``convert`` argument to ``attr.ib``, which allows specifying a function to run on arguments. - This allows for simple type conversions, e.g. with ``attr.ib(convert=int)``. - `#26 `_ -- Speed up object creation when attribute validators are used. - `#28 `_ - - ----- - - -15.1.0 (2015-08-20) -------------------- - -Changes: -^^^^^^^^ - -- Added ``attr.validators.optional()`` that wraps other validators allowing attributes to be ``None``. - `#16 `_ -- Multi-level inheritance now works. - `#24 `_ -- ``__repr__()`` now works with non-redecorated subclasses. - `#20 `_ - - ----- - - -15.0.0 (2015-04-15) -------------------- - -Changes: -^^^^^^^^ - -Initial release. diff --git a/MANIFEST.in b/MANIFEST.in index 6dbe985e..5424fea1 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ -include LICENSE *.rst *.toml *.yml *.yaml *.ini CITATION.cff +include LICENSE *.md *.toml *.yml *.yaml *.ini CITATION.cff graft .github # Stubs @@ -16,9 +16,10 @@ recursive-include docs *.png recursive-include docs *.svg recursive-include docs *.py recursive-include docs *.rst +recursive-include docs *.md prune docs/_build # Just to keep check-manifest happy; on releases those files are gone. # Last rule wins! -exclude changelog.d/*.rst -include changelog.d/towncrier_template.rst +exclude changelog.d/*.md +include changelog.d/towncrier_template.md.jinja diff --git a/changelog.d/1001.change.md b/changelog.d/1001.change.md new file mode 100644 index 00000000..919f8407 --- /dev/null +++ b/changelog.d/1001.change.md @@ -0,0 +1,2 @@ +On Python 3.10 and later, call [`abc.update_abstractmethods()`](https://docs.python.org/3/library/abc.html#abc.update_abstractmethods) on dict classes after creation. +This improves the detection of abstractness. diff --git a/changelog.d/1001.change.rst b/changelog.d/1001.change.rst deleted file mode 100644 index d983888d..00000000 --- a/changelog.d/1001.change.rst +++ /dev/null @@ -1,2 +0,0 @@ -On Python 3.10 and later, call `abc.update_abstractmethods() `_ on dict classes after creation. -This improves the detection of abstractness. diff --git a/changelog.d/1009.change.rst b/changelog.d/1009.change.md similarity index 52% rename from changelog.d/1009.change.rst rename to changelog.d/1009.change.md index 0b06ae44..0608a8ab 100644 --- a/changelog.d/1009.change.rst +++ b/changelog.d/1009.change.md @@ -1,2 +1,2 @@ -``attrs``'s pickling methods now use dicts instead of tuples. +*attrs*'s pickling methods now use dicts instead of tuples. That is safer and more robust across different versions of a class. diff --git a/changelog.d/1010.change.md b/changelog.d/1010.change.md new file mode 100644 index 00000000..acb84f8a --- /dev/null +++ b/changelog.d/1010.change.md @@ -0,0 +1 @@ +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). diff --git a/changelog.d/1010.change.rst b/changelog.d/1010.change.rst deleted file mode 100644 index ac398e24..00000000 --- a/changelog.d/1010.change.rst +++ /dev/null @@ -1 +0,0 @@ -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). diff --git a/changelog.d/1017.deprecation.rst b/changelog.d/1017.deprecation.md similarity index 100% rename from changelog.d/1017.deprecation.rst rename to changelog.d/1017.deprecation.md diff --git a/changelog.d/1027.change.md b/changelog.d/1027.change.md new file mode 100644 index 00000000..693280bb --- /dev/null +++ b/changelog.d/1027.change.md @@ -0,0 +1 @@ +The type stubs for `attrs.cmp_using()` now have default values. diff --git a/changelog.d/1027.change.rst b/changelog.d/1027.change.rst deleted file mode 100644 index a546427e..00000000 --- a/changelog.d/1027.change.rst +++ /dev/null @@ -1 +0,0 @@ -The type stubs for ``attrs.cmp_using()`` now have default values. diff --git a/changelog.d/1065.change.md b/changelog.d/1065.change.md new file mode 100644 index 00000000..de7a80b2 --- /dev/null +++ b/changelog.d/1065.change.md @@ -0,0 +1 @@ +To conform with [PEP 681](https://peps.python.org/pep-0681/), `attr.s()` and `attrs.define()` now accept *unsafe_hash* in addition to *hash*. diff --git a/changelog.d/1065.change.rst b/changelog.d/1065.change.rst deleted file mode 100644 index 575de5fb..00000000 --- a/changelog.d/1065.change.rst +++ /dev/null @@ -1 +0,0 @@ -To conform with `PEP 681 `_, ``attr.s()` and ``attrs.define()`` now accept *unsafe_hash* in addition to *hash*. diff --git a/changelog.d/950.change.md b/changelog.d/950.change.md new file mode 100644 index 00000000..6cef2097 --- /dev/null +++ b/changelog.d/950.change.md @@ -0,0 +1,4 @@ +`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](https://peps.python.org/pep-0681/#field-specifier-parameters) *alias* option can be use to override private attribute name mangling, or add other arbitrary field argument name overrides. diff --git a/changelog.d/950.change.rst b/changelog.d/950.change.rst deleted file mode 100644 index 714623fc..00000000 --- a/changelog.d/950.change.rst +++ /dev/null @@ -1,5 +0,0 @@ -``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. diff --git a/changelog.d/983.change.md b/changelog.d/983.change.md new file mode 100644 index 00000000..5349cf60 --- /dev/null +++ b/changelog.d/983.change.md @@ -0,0 +1 @@ +`attrs.NOTHING` is now an enum value, making it possible to use with e.g. [`typing.Literal`](https://docs.python.org/3/library/typing.html#typing.Literal). diff --git a/changelog.d/983.change.rst b/changelog.d/983.change.rst deleted file mode 100644 index bb1a9684..00000000 --- a/changelog.d/983.change.rst +++ /dev/null @@ -1 +0,0 @@ -``attrs.NOTHING`` is now an enum value, making it possible to use with f.e. ``typing.Literal``. diff --git a/changelog.d/987.change.md b/changelog.d/987.change.md new file mode 100644 index 00000000..f2748727 --- /dev/null +++ b/changelog.d/987.change.md @@ -0,0 +1 @@ +Added missing re-import of `attr.AttrsInstance` to the `attrs` namespace. diff --git a/changelog.d/987.change.rst b/changelog.d/987.change.rst deleted file mode 100644 index 3ae9699f..00000000 --- a/changelog.d/987.change.rst +++ /dev/null @@ -1 +0,0 @@ -Added missing re-import of ``attr.AttrsInstance`` to the ``attrs`` namespace. diff --git a/changelog.d/988.breaking.rst b/changelog.d/988.breaking.md similarity index 100% rename from changelog.d/988.breaking.rst rename to changelog.d/988.breaking.md diff --git a/changelog.d/991.change.md b/changelog.d/991.change.md new file mode 100644 index 00000000..8007bf90 --- /dev/null +++ b/changelog.d/991.change.md @@ -0,0 +1 @@ +Fix slight performance regression in classes with custom `__setattr__` and speedup even more. diff --git a/changelog.d/991.change.rst b/changelog.d/991.change.rst deleted file mode 100644 index bc9487d1..00000000 --- a/changelog.d/991.change.rst +++ /dev/null @@ -1 +0,0 @@ -Fix slight performance regression in classes with custom ``__setattr__`` and speedup even more. diff --git a/changelog.d/995.change.rst b/changelog.d/995.change.md similarity index 100% rename from changelog.d/995.change.rst rename to changelog.d/995.change.md diff --git a/changelog.d/997.change.md b/changelog.d/997.change.md new file mode 100644 index 00000000..e8509922 --- /dev/null +++ b/changelog.d/997.change.md @@ -0,0 +1,2 @@ +`attrs.has()` is now a [`TypeGuard`](https://docs.python.org/3/library/typing.html#typing.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. diff --git a/changelog.d/997.change.rst b/changelog.d/997.change.rst deleted file mode 100644 index bc4b3de5..00000000 --- a/changelog.d/997.change.rst +++ /dev/null @@ -1,2 +0,0 @@ -``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. diff --git a/changelog.d/999.change.md b/changelog.d/999.change.md new file mode 100644 index 00000000..fee02574 --- /dev/null +++ b/changelog.d/999.change.md @@ -0,0 +1 @@ +Made `attrs.AttrsInstance` stub available at runtime and fixed type errors related to the usage of `attrs.AttrsInstance` in *Pyright*. diff --git a/changelog.d/999.change.rst b/changelog.d/999.change.rst deleted file mode 100644 index 167a2627..00000000 --- a/changelog.d/999.change.rst +++ /dev/null @@ -1 +0,0 @@ -Made ``attrs.AttrsInstance`` stub available at runtime and fixed type errors related to the usage of ``attrs.AttrsInstance`` in Pyright. diff --git a/changelog.d/towncrier_template.md.jinja b/changelog.d/towncrier_template.md.jinja new file mode 100644 index 00000000..d9ae7c10 --- /dev/null +++ b/changelog.d/towncrier_template.md.jinja @@ -0,0 +1,28 @@ +{%- if versiondata["version"] == "main" -%} +## Changes for the Upcoming Release + +:::{warning} +These changes reflect the current [development progress](https://github.com/python-attrs/attrs/tree/main) and have **not** been part of a PyPI release yet. +::: +{% else -%} +## [{{ versiondata["version"] }}](https://github.com/python-attrs/attrs/tree/{{ versiondata["version"] }}) - {{ versiondata["date"] }} +{%- endif %} + +{% for section, _ in sections.items() %} +{% if sections[section] %} +{% for category, val in definitions.items() if category in sections[section] %} + +### {{ definitions[category]['name'] }} + +{% for text, values in sections[section][category].items() %} +- {{ text }} + {{ values|join(',\n ') }} +{% endfor %} + +{% endfor %} +{% else %} +No significant changes. + + +{% endif %} +{% endfor %} diff --git a/changelog.d/towncrier_template.rst b/changelog.d/towncrier_template.rst deleted file mode 100644 index 30b84f64..00000000 --- a/changelog.d/towncrier_template.rst +++ /dev/null @@ -1,36 +0,0 @@ -{% for section, _ in sections.items() %} - -{% set underline = underlines[0] %}{% if section %}{{section}} -{{ underline * section|length }}{% set underline = underlines[1] %} - -{% endif %} - -{% if sections[section] %} -{% for category, val in definitions.items() if category in sections[section]%} -{{ definitions[category]['name'] }} -{{ underline * definitions[category]['name']|length }} - -{% if definitions[category]['showcontent'] %} -{% for text, values in sections[section][category].items() %} -- {{ text }} - {{ values|join(',\n ') }} -{% endfor %} - -{% else %} -- {{ sections[section][category]['']|join(', ') }} - -{% endif %} -{% if sections[section][category]|length == 0 %} -No significant changes. - -{% else %} -{% endif %} - -{% endfor %} -{% else %} -No significant changes. - - -{% endif %} -{% endfor %} ----- diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 00000000..3c8d4d8b --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1,11 @@ +```{include} ../CHANGELOG.md +:end-before: Changes for the upcoming release can be found +``` + + ```{towncrier-draft-entries} +main + ``` + +```{include} ../CHANGELOG.md +:start-after: towncrier release notes start --> +``` diff --git a/docs/changelog.rst b/docs/changelog.rst deleted file mode 100644 index ebec9cea..00000000 --- a/docs/changelog.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. include:: ../CHANGELOG.rst - :end-before: Changes for the upcoming release can be found - -.. towncrier-draft-entries:: Unreleased - -.. include:: ../CHANGELOG.rst - :start-after: .. towncrier release notes start diff --git a/docs/index.md b/docs/index.md index 88eb13e3..bd599ddd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,18 +1,12 @@ -```{eval-rst} -.. module:: attr -.. module:: attrs -``` - # *attrs*: Classes Without Boilerplate -Release **{sub-ref}`release`** ([What's new?](changelog)) +Release **{sub-ref}`release`** ([What's new?](changelog.md)) ```{eval-rst} .. include:: ../README.md :parser: myst_parser.sphinx_ :start-after: teaser-begin --> :end-before: ", 1)[1] + .strip() + .split("\n## ", 1)[0] + .strip() + .split("\n", 1)[1] + + "\n\n---\n\n[Full changelog]" + "(https://www.attrs.org/en/stable/changelog.html)\n" +) if __name__ == "__main__": setup( diff --git a/tox.ini b/tox.ini index 2a2dfdaf..b6308ad1 100644 --- a/tox.ini +++ b/tox.ini @@ -93,7 +93,7 @@ commands = basepython = python3.8 deps = towncrier skip_install = true -commands = towncrier build --version UNRELEASED --draft +commands = towncrier build --version main --draft [testenv:mypy]