* Pass args from `__init__` to `__attrs_pre_init__` if requested
Detect if `__attrs_pre_init__` has arguments besides `self`
using `inspect.signature`. If so, pass `__attrs_pre_init__`
the same arguments that `__init__` (or `__attrs_init__`)
expects.
* Add changelog entry for `__attrs_pre_init__` args changes
* Don't use monkeypatch in new code
* Clarify docs
* Missed one monkeypatching
---------
Co-authored-by: Hynek Schlawack <hs@ox.cx>
* Use enum for typing NOTHING.
This will allow those extending attrs
to type NOTHING as Literal[NOTHING].
* Make test_dunders test `NOTHING` directly
* Reflect NOTHING enum typing in __init__.pyi
* Fix docs for NOTHING
* Add changelog entry
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
Co-authored-by: Hynek Schlawack <hs@ox.cx>
Co-authored-by: Tin Tvrtković <tinchester@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* Drop Python 2.7
The tooling situation around Python 2 has deteriorate to such a degree that
upholding compatibility is not tenable anymore for a volunteer-run project.
Signed-off-by: Hynek Schlawack <hs@ox.cx>
* Add newsfragment
* Run Python 3.5 under coverage to make up for Python 2.7
* Wait for py35 in parallel
* Remove fullmatch kludge
* Remove Python 2-specific code
* Revert empty slot test
Also disable pyupgrade on that file.
Signed-off-by: Hynek Schlawack <hs@ox.cx>
* We DO run under 3.5
* Remove __qualname__ workarounds
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Update changelog.d/936.breaking.rst
Co-authored-by: Tin Tvrtković <tinchester@gmail.com>
* Compare methods using is
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Tin Tvrtković <tinchester@gmail.com>
Because cloudpickle tries to pickle a function's globals, when it
pickled an attrs instance, it would try to pickle the `__repr__` method
and its globals, which included a `threading.local`. This broke
cloudpickle for all attrs classes unless they explicitly specified
`repr=False`. Modules, however, are pickled by reference, not by value,
so moving the repr into a different module means we can put `_compat`
into the function's globals and not worry about direct references.
Includes a test to ensure that attrs and cloudpickle remain compatible.
Also adds an explanation of the reason we even *have* that global
thread-local variable. It wasn't completely obvious to a reader why
the thread-local was needed to track reference cycles in `__repr__`
calls, and the test did not previously contain a cycle that touched
a non-attrs value. This change adds a comment explaining the need
and tests a cycle that contains non-attrs values.
Fixes:
- https://github.com/python-attrs/attrs/issues/458
- https://github.com/cloudpipe/cloudpickle/issues/320
* Optimize the case of on_setattr=validate & no validators
This is important because define/mutable have on_setattr=setters.validate on
default.
Fixes#816
Signed-off-by: Hynek Schlawack <hs@ox.cx>
* Grammar
* Add Python 3.10 support
Python 3.10 has string types everywhere and that has unmasked a bunch of
bugs/edge cases in our code.
Especially the hooks code need a resolving helper for string types. I'm leaving
that for a separate PR.
Fixes#716
* More robust quote handling
* Use resolve_types decorator where possible
* Use a helper for __init__ annotations
* Add test for various ClassVars
* Add on_setattr hooks to attr.s and attr.ib
Signed-off-by: Hynek Schlawack <hs@ox.cx>
* Add PR newsfragment
* Fix attr.s doc sig
* Make _DisableType private
* Mark setters.frozen as NoReturn
* Rename setters.DISABLE to setters.NO_OP to clarify its purpose
DISABLE sounds less purposeful and doesn't convey its meaning as well.
* Fix type
* Loosen up type for convert even further
* Tighten type a tiny bit
* Use an self-clearing subclass to store hash cache
Rather than attempting to remove the hash cache from the object state on
deserialization or serialization, instead we store the hash cache in an
object that reduces to None, thus clearing itself when pickled or
copied.
This fixes GH #494 and #613.
Co-authored-by: Matt Wozniski <godlygeek@gmail.com>
* Add test for two-argument __reduce__
I couldn't think of any way to make a useful and meaningful class that
has no state and also has no custom __reduce__ method, so I went
minimalist with it.
* Improve test for hash clearing behavior.
Previously, there was some miniscule risk of hash collision, and also it
was relying on the implementation details of `pickle` (the assumption
that `hash()` is never called as part of `pickle.loads`).
* Add improved testing around cache_hash
* Update src/attr/_make.py
Co-Authored-By: Ryan Gabbard <gabbard@isi.edu>
* Update comment in slots_setstate
Since the cached hash value is not actually serialized in __getstate__,
__setstate__ is not actually "clearing" it on deserialization - it's
initializing the value to None.
* Add changelog entry
* Remove changelog for #611
This change was overshadowed by a more fundamental change in #620.
Co-authored-by: Matt Wozniski <godlygeek@gmail.com>
Co-authored-by: Ryan Gabbard <gabbard@isi.edu>
* Split cmp into eq and order
Fixes#170
* Fix tests on old pypy3 versions
Old as in: currently on AP.
* Fix issue number and clarify newsfragment
* Clarify behavior and interaction between cmp/eq/order
* This sounds better
* Address Julian's review comments
* Missed a cmp
* Test the behavior of Attribute.cmp
* Make test more idiomatic
* Explain assumptions
* Clarify comment
* Grammar
* One more cmp!
* wip: support custom repr() callable for attributes
see #567
* extend ‘repr=...’ arg type in .pyi stubs
* expand docstring for attr.ib()
* add changelog entry
* add docs with example
* improve my copy/paste skills 🙈
* fix grammar
* fix typo in changelog entry
* fix and improve attrib() docstring
* detect custom repr() once, not per call. be strict about bool.
* use rst syntax, not markdown
* apply hynek's suggestions for changelog entry
* add ‘versionchanged’ note in docstring
* add custom attribute repr= to typing example
* simplify comment
* Make unique_filename not depend on repr.
For debugging purposes, when a method is created it needs to be put
into a "filename". This filename was generated using `repr(attrs)`
however this meant that the filename could change every time the
program was loaded depending on the whims of repr. (In particular
free functions and lambdas would include ids)
This solves the problem by changing the name to be <attrs generated
{method} {module}.{qualname}> If it should happen that the name is
taken then -2 will be appended and incremented until a free filename
is found.
* Add tests
* Fix tests and changelog
* Don't cache hash codes across deserialization.
Because the hash code cache field gets serialized and deserialized by
Pickle, previously when you deserialize a cache_hash=True attrs object, the
hashcode will be the hashcode the object had at serialization-time.
However, if your object had fields with hash codes which were not
deterministic between interpreter runs, then on a new interpreter run
your deserialized object would have a hash code which differs from a
newly created identical object.
This commit fixes that by clearing the cache on deserialization. It
needs to override the __setstate__ method to do so, so this commit
also forbids using a custom __setstate__ on a cache_hash=True object.
Closes#482 .
* Improve exception type
* Minor tweaks to comments formatting
* Fix test for Python 2.7
* Fix error in comment
* Make nomenclature consistent for slotted/dict classes
* Remove hasattr()
* Improve comments and error message for custom __setstate__ + cache_hash=True
* Drop use of for test classes for cache hash serialization
* Make changelog note this is a breaking change
* Make exception message point to tracking issue
* Fix test classes for Python 2.7
* First stab at implementing hashcode caching (#423)
Currently all existing tests pass but no cache_hash tests have yet
been added.
* Existing hash tests now pass on cache_hash classes
* Add towncrier change log
* Add documentation for cache_hash
* Fixes bug with check that init=True if cache_hash=True
* Fix long lines
* Fix documentation issues
* Add test for cache_hash requiring init
* Improve test coverage
* Remove now unnecessary 'pass'
* Add periods to the end of exception strings
* Add test docstrings for cache_hash tests
* Clarify documentation of cache_hash
* Recommend that hashable classes be frozen
* Fix test references for exception messages
* Stop setting attributes on class bodies
This behavior has been deprecated since 16.1 and can now be removed in
accordance with our backward-compatibility policy.
* We don't need iterkeys anymore
Previously:
```pycon
>>> import attr
>>> @attr.s(str=True, slots=True)
... class A(object):
... a = attr.ib()
...
>>> a = A(1)
>>> str(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method repr_() must be called with A instance as first argument (got nothing instead)
```
Fixes#198.