Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add decorator option for converters #404

Draft
wants to merge 35 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
bbc3d09
Add decorator option for converters
altendky Jul 2, 2018
3132bb5
Quickly fix coverage
altendky Jul 2, 2018
a7535a9
Merge branch 'master' into t240-converter_decorator
altendky Jul 6, 2018
6a8b98a
Always replace converter with a Converter()
altendky Jul 6, 2018
1a82b45
Leave .converter alone but always store a Converter into names_for_gl…
altendky Jul 6, 2018
a92be06
Return Converter to being an @attrs class
altendky Jul 6, 2018
1d3c96f
Rearrange new converter tests
altendky Jul 6, 2018
2dcaaad
Add changelog.d/404.change.rst for converter decorator PR
altendky Jul 6, 2018
eee1825
Add more test docstrings
altendky Jul 6, 2018
9cf3110
Correct rst errors in changelog.d/404.change.rst
altendky Jul 7, 2018
5ac916d
Try to make black happy
altendky Jul 7, 2018
040f2b9
Add test_fields_converter_is_passed_converter
altendky Jul 7, 2018
f5451dc
Merge branch 'master' into t240-converter_decorator
altendky Jul 12, 2018
c09bdb1
Merge branch 'master' into t240-converter_decorator
altendky Aug 30, 2020
7217396
black
altendky Aug 30, 2020
9b88784
add docs for Converter and @x.converter
altendky Aug 30, 2020
1f01603
semantic newlines in newsfragment
altendky Aug 30, 2020
4e7d71a
.. versionadded:: TODO
altendky Aug 30, 2020
add80c4
Set version to 20.2.0 for new versionadded and versionchanged directives
altendky Aug 31, 2020
72fbad6
Merge branch 'master' into t240-converter_decorator
altendky Aug 31, 2020
5c68106
Merge branch 'master' into t240-converter_decorator
hynek Oct 19, 2020
d023f8d
Merge branch 'master' into t240-converter_decorator
altendky Oct 19, 2020
5e0d073
Merge branch 'master' into t240-converter_decorator
hynek Oct 26, 2020
75e1f81
update to .. versionadded:: 20.3.0
altendky Oct 26, 2020
92763a1
Tests passing with converter taking attr too
altendky Oct 30, 2020
502808f
Simplify Converter() down to nothing more than a 'marker' class
altendky Oct 30, 2020
2236ca0
Catch up examples in docs
altendky Oct 30, 2020
76e980c
More doc example catch ups
altendky Oct 31, 2020
2e28f0e
Update tests
altendky Oct 31, 2020
937be69
black
altendky Oct 31, 2020
5a7381a
Add tests for Converter used with on_setattr
altendky Nov 1, 2020
cc750f2
black
altendky Nov 1, 2020
346c175
a temporary workaround for the circular import
altendky Nov 1, 2020
c581957
black
altendky Nov 1, 2020
341897f
lint
altendky Nov 1, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelog.d/404.change.rst
@@ -0,0 +1,2 @@
Allow converters to be specified via a decorator including getting access to the partially initialized instance.
``self`` is also available via ``Converter()`` which can be passed when calling ``attr.ib(converter=...)``.
32 changes: 26 additions & 6 deletions docs/api.rst
Expand Up @@ -70,24 +70,28 @@ Core

``attrs`` also comes with a serious business alias ``attr.attrib``.

The object returned by `attr.ib` also allows for setting the default and the validator using decorators:
The object returned by `attr.ib` also allows for setting the default, the validator, and the converter using decorators:

.. doctest::

>>> @attr.s
... class C(object):
... x = attr.ib()
... y = attr.ib()
... z = attr.ib()
... @x.validator
... def _any_name_except_a_name_of_an_attribute(self, attribute, value):
... if value < 0:
... raise ValueError("x must be positive")
... @y.default
... @y.converter
... def _any_name_except_a_name_of_an_attribute(self, attr, value):
... return int(value)
... @z.default
... def _any_name_except_a_name_of_an_attribute(self):
... return self.x + 1
>>> C(1)
C(x=1, y=2)
>>> C(-1)
... return self.x + 2
>>> C(1, "2")
C(x=1, y=2, z=3)
>>> C(-1, "2")
Traceback (most recent call last):
...
ValueError: x must be positive
Expand Down Expand Up @@ -141,6 +145,22 @@ Core
C(x=[1, 2, 3], y={1, 2, 3})


.. autoclass:: attr.Converter

For example:

.. doctest::

>>> @attr.s
... class C(object):
... x = attr.ib(converter=int)
... y = attr.ib(converter=attr.Converter(
... lambda self, attr, value: self.x + value,
... ))
>>> C("1", 2)
C(x=1, y=3)


Exceptions
----------

Expand Down
14 changes: 11 additions & 3 deletions docs/examples.rst
Expand Up @@ -454,9 +454,17 @@ This can be useful for doing type-conversions on values that you don't want to f
>>> @attr.s
... class C(object):
... x = attr.ib(converter=int)
>>> o = C("1")
>>> o.x
1
... y = attr.ib(
... converter=attr.Converter(
... lambda self, attr, value: self.x + value,
... ),
... )
... z = attr.ib()
... @z.converter
... def z_converter(self, attr, value):
... return self.x + value
>>> C("10", 2, 3)
C(x=10, y=12, z=13)

Check out `converters` for more details.

Expand Down
14 changes: 14 additions & 0 deletions docs/init.rst
Expand Up @@ -301,6 +301,20 @@ Arguably, you can abuse converters as one-argument validators:
ValueError: invalid literal for int() with base 10: 'x'


Similar to validators, converters can be specified with a decorator.

.. doctest::

>>> @attr.s
... class C(object):
... x = attr.ib()
... @x.converter
... def int(self, attr, value):
... return int(value)
>>> o = C("1")
>>> o
C(x=1)

Post-Init Hook
--------------

Expand Down
2 changes: 2 additions & 0 deletions src/attr/__init__.py
Expand Up @@ -10,6 +10,7 @@
from ._make import (
NOTHING,
Attribute,
Converter,
Factory,
attrib,
attrs,
Expand Down Expand Up @@ -43,6 +44,7 @@

__all__ = [
"Attribute",
"Converter",
"Factory",
"NOTHING",
"asdict",
Expand Down