* 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 3.5
Less than 0.5% of our downloads are 3.5 and it allows us to simplify A LOT of code.
Fixes#965
Signed-off-by: Hynek Schlawack <hs@ox.cx>
* Run 3.6 under coverage
* Add newsfragment
* Probably don't need 3.7 for coverage
* Everything is ordered!
* pre-commit autoupdate, add yesqa
The docstring of _in() says the ValueError would contain these, however
it didn't. Adding said arguments enables uniform processing of
ValueErrors raised by validators. One might for example want to extract
the attr.name and the value that raised the error to show a custom, more
user-friendly error message.
* Drop the deprecated Attribute.cmp
This has nothing to do with the cmp argument to attr.s/define which have been
undeprecated.
* Add newsfragment
* Add test for attr.ib(cmp=)
* 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>
* Add Multiple Validators to deep iterable
* Add Tests + Fix some doc strings
* Update typing
* Limit this PR to only accepting a list of member validators
* Respond to PR comments
* Commit missing file
* Apply suggestions from code review
Co-authored-by: Hynek Schlawack <hs@ox.cx>
* Split other test too
* Fix CI + Remove Weird parens
* Use and_ instead of And_
* Add tuple to list of tests
Co-authored-by: Hynek Schlawack <hs@ox.cx>
* Added attrs.validators.min_len()
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Rename foo.change.rst to 916.change.rst
* Update src/attr/validators.py
Co-authored-by: nativ <nativi@spotnix.io>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Hynek Schlawack <hs@ox.cx>
* Do not require cloudpickle for PyPy
The cloudpickle package relies on CPython implementation details,
and does not even import on PyPy:
```
ImportError while importing test module '/tmp/attrs/tests/test_3rd_party.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/pypy3.8/importlib/__init__.py:127: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
tests/test_3rd_party.py:7: in <module>
import cloudpickle
.tox/pypy3/lib/pypy3.8/site-packages/cloudpickle/__init__.py:4: in <module>
from cloudpickle.cloudpickle import * # noqa
.tox/pypy3/lib/pypy3.8/site-packages/cloudpickle/cloudpickle.py:57: in <module>
from .compat import pickle
.tox/pypy3/lib/pypy3.8/site-packages/cloudpickle/compat.py:13: in <module>
from _pickle import Pickler # noqa: F401
E ModuleNotFoundError: No module named '_pickle'
```
Disable the dependency for PyPy and make the test handle missing
cloudpickle gracefully.
* Enable testing on pypy-3.8
* add a news entry
Co-authored-by: Hynek Schlawack <hs@ox.cx>
* Add tuple_keys to asdict
See #646
* Add typing example
* Add newsfragments
* Add missing test
* Switch it on by default
* Let's not make buggy behavior configurable
* NG: convert on setattr by default
Not doing that from the get-go was an oversight.
Fixes#835
* Add optimization for default on_setattr w/ no work to do
Otherwise we'd end up with an explicit setattr every time.
* Fix optimization for NG default & j/ convert
* NG is actually 3.6+
* Add test for convert optimization for good measure
Fixes#875.
This adds support for pre-compiled regular expressions to
attr.validators.matches_re(). This cannot be combined with flags since
the pre-compiled pattern already has those.
Detailed changes:
- attr.validators.matches_re() now accepts re.Pattern in addition to
strings; update type annotations accordingly.
- Convert percent-formatting into str.format() for an error message
- Simplify (private) _MatchesReValidator helper class a bit: use the
actual compiled pattern, and drop the unused .flags attribute.
- Simplify control flow a bit; add pointer about fullmatch emulation.
- Add tests
- Tweak existing test to ensure that .fullmatch() actually works
correctly by matching a pattern that also matches (but not
‘full-matches’) a shorter substring.
Co-authored-by: Hynek Schlawack <hs@ox.cx>
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
* 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>
* 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
* 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>
* 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>