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
* Make `from attr import *` work again on recent python versions.
* Move import * test into a function and mark some flake8 exceptions.
* Please the linters.
* Update attr_import_star.py
test was renamed, rename it in the comment as well
* Convert transformed attrs to AttrsClass
Fixes: #821
* Add cangelog entry
* Only call AttrsClass once
* Calm mypy by inline the AttrsClass call
* Defer AttrsClass creation as long as possible
Co-authored-by: Hynek Schlawack <hs@ox.cx>
* Fix bug in resolve_types with subclasses
* lint
* changelog
* lint again, like we did last summer
* Moar coverage
* lint ... why
Co-authored-by: Hynek Schlawack <hs@ox.cx>
* Inline distutils.util.strtobool in tests (#813)
`distutils` is deprecated in Python 3.10 and slated for removal in
Python 3.12. Fortunately, `attrs` only uses `distutils` once and it's
trivial to remove.
As suggested by @sscherfke, add the `to_bool` converter to
`converters.py`.
Closes#813
Co-authored-by: Stefan Scherfke <stefan@sofa-rockers.org>
* Use :raises: directive in docstring
* Remove f-strings for Py2.7 and 3.5 support
* Add to_bool tests
Co-authored-by: Stefan Scherfke <stefan@sofa-rockers.org>
Co-authored-by: Hynek Schlawack <hs@ox.cx>
* 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
Since this warning is raised from the attr.ib/attr.field call, we cannot verify
whether order is on at all for the whole class. Fixing this would require to
check _after_ the class is assembled which is both additional complexity as
well as performance overhead. Unless we get inundated by bug reports, this
doesn't seem worth it.
* New attr.cmp_using helper function
* Updated cmp_using to use new_class instead of direct patching
* Removed stray annotation that make tests fail in PY2
* Skip test if PY2 because it won't raise TypeError when a method returns NotImplemented
* Skip test if PY2 because it won't raise TypeError when a method returns NotImplemented
* Fixed PY2 tests related to total_ordering
* Added tests to complete converage
* Moved class_name argument to definition and made it non-optional
* Fixed typo in variable name
* Revert accidental black formatting of __init__.pyi in commit 2b7970bf
Co-authored-by: Hynek Schlawack <hs@ox.cx>
* Narrower typing on Factory called with takes_self
* Make Literal annotation depend on Python version
* Fix linting error
Co-authored-by: Hynek Schlawack <hs@ox.cx>
* 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
* Clarify next-gen auto_attribs inference rules
The next-gen auto_attribs api documentation does not clearly describe
cases where (a) only a subset of attributes are annotated and (b)
`field` definitions are provided for a subset of fields. Update
docstring to reflect current, desirable, behavior.
Add tests to clarify `.define` behavior focused on fully-annotated
classes with partially-defined fields, which is commonly used to add
non-default behavior to a subset of a classes fields. For example:
```python
@attr.define
class NewSchool:
x: int
y: list = attr.field()
@y.validator
def _validate_y(self, attribute, value):
if value < 0:
raise ValueError("y must be positive")
```
The previous docstring *could* be read to imply that:
* The new-school API will not infer auto_attribs if there are any
unannotated attributes.
* The new-school API will not infer auto_attribs if *any* attr.ib are
defined, even if those attr.ibs are type annotated.
* Update test to match PR example
* Fix lint error
Co-authored-by: Hynek Schlawack <hs@ox.cx>
* Fixed slots inheritance
* Added changelog
* Added a separate test
* Restored backwards-compatibility and added a test for it
Co-authored-by: Hynek Schlawack <hs@ox.cx>
* Infer annotations from converters
* Use semantic newlines
* Add 787.change.rst
* Don't let type annotations override converters
* Make pipe() infer type annotations
* Use PY2 instead of sys.versioninfo >= (3, 3)
* Avert crashing with a nullary converter
* Small doc change
* Add type inference for optional()
* Make pipe() annotations actually work
Co-authored-by: Hynek Schlawack <hs@ox.cx>
* Ease Hypothesis shrinking
This is a tiny performance improvement for shrinking.
Unconditionally drawing and conditionally *using* these boolean flags minimises the impact of mutating other parts of an input on the structure here, which in turn means more attempts will be valid.
* Refactor Hypothesis strategy
Using the composite decorator allows for a much clearer imperative description of how the class is constructed.
* Added kw_only support for py2
* Docs update
* Added changelog
* Better exception message, moved code to function
* Moved py2-only functions under if PY2:
* Tested fancy error message for unexpected kw-only argument
* Tested fancy error message for unexpected kw-only argument
* Fixed line length
* Added versionchanged
* Updated docs
* Moved functions back under if PY2 - seems codecov doesn't like them in module scope
* Blacked
* Fixed changelog.d
* Removed redundant brackets in test
* Added assertion to the _unpack_kw_only_lines_py2 - hope it will increase code coverage
* List comprehension -> for loop
* lines.extend? I do not like for-loops
* Fix code
* Fixed style/added comment
* Fixed docs (removed python2 mention)
* Fix lint
* Better docstring
* Rewritten docstring and added example code
* Added quotes
Co-authored-by: Hynek Schlawack <hs@ox.cx>