2015-01-27 16:53:17 +00:00
.. _api:
2017-10-26 15:55:45 +00:00
API Reference
=============
2015-01-28 13:36:11 +00:00
.. currentmodule :: attr
`` attrs `` works by decorating a class using :func: `attr.s` and then optionally defining attributes on the class using :func: `attr.ib` .
2015-01-28 15:02:18 +00:00
.. note ::
When this documentation speaks about "`` attrs `` attributes" it means those attributes that are defined using :func: `attr.ib` in the class body.
2015-01-28 15:28:47 +00:00
What follows is the API explanation, if you'd like a more hands-on introduction, have a look at :doc: `examples` .
2015-01-28 13:36:11 +00:00
Core
----
2017-02-19 08:51:43 +00:00
.. autofunction :: attr.s(these=None, repr_ns=None, repr=True, cmp=True, hash=None, init=True, slots=False, frozen=False, str=False)
2015-01-28 13:36:11 +00:00
2015-01-29 09:17:08 +00:00
.. note ::
2016-08-16 10:18:03 +00:00
`` attrs `` also comes with a serious business alias `` attr.attrs `` .
2015-01-29 09:17:08 +00:00
2015-02-08 11:32:32 +00:00
For example:
.. doctest ::
>>> import attr
>>> @attr.s
... class C(object):
... _private = attr.ib()
>>> C(private=42)
C(_private=42)
>>> class D(object):
... def __init__(self, x):
... self.x = x
>>> D(1)
<D object at ...>
2015-02-20 12:29:47 +00:00
>>> D = attr.s(these={"x": attr.ib()}, init=False)(D)
2015-02-08 11:32:32 +00:00
>>> D(1)
D(x=1)
2015-01-28 13:36:11 +00:00
.. autofunction :: attr.ib
2015-01-29 09:17:08 +00:00
.. note ::
2016-08-16 10:18:03 +00:00
`` attrs `` also comes with a serious business alias `` attr.attrib `` .
2015-01-29 09:17:08 +00:00
2017-05-22 23:42:40 +00:00
The object returned by :func: `attr.ib` also allows for setting the default and the validator using decorators:
2017-02-11 15:55:39 +00:00
2017-05-22 23:42:40 +00:00
.. doctest ::
>>> @attr.s
... class C(object):
... x = attr.ib()
... y = attr.ib()
... @x.validator
... def name_can_be_anything(self, attribute, value):
... if value < 0:
... raise ValueError("x must be positive")
... @y.default
... def name_does_not_matter(self):
... return self.x + 1
>>> C(1)
C(x=1, y=2)
>>> C(-1)
Traceback (most recent call last):
...
ValueError: x must be positive
2015-01-28 13:36:11 +00:00
2015-01-29 11:20:17 +00:00
.. autoclass :: attr.Attribute
Instances of this class are frequently used for introspection purposes like:
2015-03-23 08:16:43 +00:00
- :func: `fields` returns a tuple of them.
2015-01-29 11:20:17 +00:00
- Validators get them passed as the first argument.
2015-01-30 07:57:33 +00:00
.. warning ::
You should never instantiate this class yourself!
2015-01-29 11:20:17 +00:00
.. doctest ::
>>> import attr
>>> @attr.s
... class C(object):
... x = attr.ib()
2017-10-02 10:14:37 +00:00
>>> attr.fields(C).x
2017-09-17 14:22:49 +00:00
Attribute(name='x', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}), type=None)
2015-01-29 22:10:56 +00:00
2015-01-30 07:57:33 +00:00
.. autofunction :: attr.make_class
This is handy if you want to programmatically create classes.
For example:
.. doctest ::
>>> C1 = attr.make_class("C1", ["x", "y"])
>>> C1(1, 2)
C1(x=1, y=2)
>>> C2 = attr.make_class("C2", {"x": attr.ib(default=42),
... "y": attr.ib(default=attr.Factory(list))})
>>> C2()
C2(x=42, y=[])
2015-02-20 12:29:47 +00:00
2015-01-29 22:10:56 +00:00
.. autoclass :: attr.Factory
For example:
.. doctest ::
>>> @attr.s
... class C(object):
... x = attr.ib(default=attr.Factory(list))
2017-05-16 07:36:39 +00:00
... y = attr.ib(default=attr.Factory(
... lambda self: set(self.x),
... takes_self=True)
... )
2015-01-29 22:10:56 +00:00
>>> C()
2017-05-16 07:36:39 +00:00
C(x=[], y=set())
>>> C([1, 2, 3])
C(x=[1, 2, 3], y={1, 2, 3})
2015-01-29 11:20:17 +00:00
2016-08-20 16:45:15 +00:00
.. autoexception :: attr.exceptions.FrozenInstanceError
2016-09-10 17:14:34 +00:00
.. autoexception :: attr.exceptions.AttrsAttributeNotFoundError
.. autoexception :: attr.exceptions.NotAnAttrsClassError
2017-05-16 07:36:39 +00:00
.. autoexception :: attr.exceptions.DefaultAlreadySetError
2016-08-20 16:45:15 +00:00
2017-08-18 18:43:38 +00:00
Influencing Initialization
++++++++++++++++++++++++++
Generally speaking, it's best to keep logic out of your `` __init__ `` .
The moment you need a finer control over how your class is instantiated, it's usually best to use a classmethod factory or to apply the `builder pattern <https://en.wikipedia.org/wiki/Builder_pattern> `_ .
However, sometimes you need to do that one quick thing after your class is initialized.
And for that `` attrs `` offers the `` __attrs_post_init__ `` hook that is automatically detected and run after `` attrs `` is done initializing your instance:
.. doctest ::
>>> @attr.s
... class C(object):
... x = attr.ib()
... y = attr.ib(init=False)
... def __attrs_post_init__(self):
... self.y = self.x + 1
>>> C(1)
C(x=1, y=2)
Please note that you can't directly set attributes on frozen classes:
.. doctest ::
>>> @attr.s(frozen=True)
... class FrozenBroken(object):
... x = attr.ib()
... y = attr.ib(init=False)
... def __attrs_post_init__(self):
... self.y = self.x + 1
>>> FrozenBroken(1)
Traceback (most recent call last):
...
attr.exceptions.FrozenInstanceError: can't set attribute
If you need to set attributes on a frozen class, you'll have to resort to the :ref: `same trick <how-frozen>` as `` attrs `` and use :meth: `object.__setattr__` :
.. doctest ::
>>> @attr.s(frozen=True)
... class Frozen(object):
... x = attr.ib()
... y = attr.ib(init=False)
... def __attrs_post_init__(self):
... object.__setattr__(self, "y", self.x + 1)
>>> Frozen(1)
Frozen(x=1, y=2)
2016-08-30 10:12:02 +00:00
.. _helpers:
2015-01-28 13:36:11 +00:00
Helpers
-------
2016-08-15 08:00:23 +00:00
`` attrs `` comes with a bunch of helper methods that make working with it easier:
2015-01-28 13:36:11 +00:00
2015-01-29 20:55:25 +00:00
.. autofunction :: attr.fields
2015-01-28 13:36:11 +00:00
For example:
.. doctest ::
>>> @attr.s
... class C(object):
... x = attr.ib()
... y = attr.ib()
2015-01-29 20:55:25 +00:00
>>> attr.fields(C)
2017-09-17 14:22:49 +00:00
(Attribute(name='x', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}), type=None), Attribute(name='y', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}), type=None))
2016-09-10 17:55:27 +00:00
>>> attr.fields(C)[1]
2017-09-17 14:22:49 +00:00
Attribute(name='y', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}), type=None)
2016-09-10 17:55:27 +00:00
>>> attr.fields(C).y is attr.fields(C)[1]
True
2015-01-28 13:36:11 +00:00
.. autofunction :: attr.has
For example:
.. doctest ::
>>> @attr.s
... class C(object):
... pass
>>> attr.has(C)
True
>>> attr.has(object)
False
2015-01-29 09:17:08 +00:00
2015-01-29 20:50:07 +00:00
.. autofunction :: attr.asdict
2015-01-28 13:36:11 +00:00
For example:
.. doctest ::
>>> @attr.s
... class C(object):
... x = attr.ib()
... y = attr.ib()
2015-01-29 20:50:07 +00:00
>>> attr.asdict(C(1, C(2, 3)))
2017-03-04 06:49:57 +00:00
{'x': 1, 'y': {'x': 2, 'y': 3}}
2015-01-28 13:36:11 +00:00
2015-01-29 09:17:08 +00:00
2016-09-11 06:54:39 +00:00
.. autofunction :: attr.astuple
For example:
.. doctest ::
>>> @attr.s
... class C(object):
... x = attr.ib()
... y = attr.ib()
>>> attr.astuple(C(1,2))
(1, 2)
2016-08-15 08:00:23 +00:00
`` attrs `` includes some handy helpers for filtering:
2015-02-20 15:34:21 +00:00
.. autofunction :: attr.filters.include
.. autofunction :: attr.filters.exclude
2016-09-10 17:14:34 +00:00
See :ref: `asdict` for examples.
2015-02-20 15:34:21 +00:00
2017-01-21 16:11:45 +00:00
.. autofunction :: attr.evolve
2017-05-22 23:23:18 +00:00
For example:
2017-01-21 16:11:45 +00:00
.. doctest ::
>>> @attr.s
... class C(object):
... x = attr.ib()
... y = attr.ib()
>>> i1 = C(1, 2)
>>> i1
C(x=1, y=2)
>>> i2 = attr.evolve(i1, y=3)
>>> i2
C(x=1, y=3)
>>> i1 == i2
False
2017-05-22 23:23:18 +00:00
`` evolve `` creates a new instance using `` __init__ `` .
This fact has several implications:
2017-05-04 11:20:39 +00:00
2017-05-22 23:23:18 +00:00
* private attributes should be specified without the leading underscore, just like in `` __init__ `` .
* attributes with `` init=False `` can't be set with `` evolve `` .
* the usual `` __init__ `` validators will validate the new values.
2017-05-04 11:20:39 +00:00
2015-02-02 13:04:47 +00:00
.. autofunction :: validate
2015-02-02 11:13:11 +00:00
For example:
.. doctest ::
>>> @attr.s
... class C(object):
... x = attr.ib(validator=attr.validators.instance_of(int))
>>> i = C(1)
>>> i.x = "1"
2015-02-02 13:04:47 +00:00
>>> attr.validate(i)
2015-02-02 11:13:11 +00:00
Traceback (most recent call last):
...
2017-09-17 14:22:49 +00:00
TypeError: ("'x' must be <type 'int'> (got '1' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, repr=True, cmp=True, hash=None, init=True, type=None), <type 'int'>, '1')
2015-02-02 11:13:11 +00:00
2015-02-20 10:30:46 +00:00
Validators can be globally disabled if you want to run them only in development and tests but not in production because you fear their performance impact:
.. autofunction :: set_run_validators
.. autofunction :: get_run_validators
2015-01-29 11:20:17 +00:00
.. _api_validators:
Validators
----------
2016-08-15 08:00:23 +00:00
`` attrs `` comes with some common validators in the `` attrs.validators `` module:
2015-01-29 11:20:17 +00:00
.. autofunction :: attr.validators.instance_of
2015-01-28 13:36:11 +00:00
2015-01-29 11:20:17 +00:00
For example:
.. doctest ::
>>> @attr.s
... class C(object):
... x = attr.ib(validator=attr.validators.instance_of(int))
>>> C(42)
C(x=42)
>>> C("42")
Traceback (most recent call last):
...
2017-09-17 14:22:49 +00:00
TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None), <type 'int'>, '42')
2015-07-09 23:14:32 +00:00
>>> C(None)
Traceback (most recent call last):
...
2017-09-17 14:22:49 +00:00
TypeError: ("'x' must be <type 'int'> (got None that is a <type 'NoneType'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, repr=True, cmp=True, hash=None, init=True, type=None), <type 'int'>, None)
2015-01-29 18:04:23 +00:00
2017-05-16 08:36:42 +00:00
.. autofunction :: attr.validators.in_
For example:
.. doctest ::
>>> import enum
>>> class State(enum.Enum):
... ON = "on"
... OFF = "off"
>>> @attr.s
... class C(object):
... state = attr.ib(validator=attr.validators.in_(State))
... val = attr.ib(validator=attr.validators.in_([1, 2, 3]))
>>> C(State.ON, 1)
C(state=<State.ON: 'on'>, val=1)
>>> C("on", 1)
Traceback (most recent call last):
...
ValueError: 'state' must be in <enum 'State'> (got 'on')
>>> C(State.ON, 4)
Traceback (most recent call last):
...
ValueError: 'val' must be in [1, 2, 3] (got 4)
.. autofunction :: attr.validators.provides
2017-05-12 21:02:07 +00:00
.. autofunction :: attr.validators.and_
For convenience, it's also possible to pass a list to :func: `attr.ib` 's validator argument.
Thus the following two statements are equivalent::
x = attr.ib(validator=attr.validators.and_(v1, v2, v3))
x = attr.ib(validator=[v1, v2, v3])
2015-01-29 18:04:23 +00:00
2015-07-09 23:14:32 +00:00
.. autofunction :: attr.validators.optional
For example:
.. doctest ::
>>> @attr.s
... class C(object):
... x = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(int)))
>>> C(42)
C(x=42)
>>> C("42")
Traceback (most recent call last):
...
2017-09-17 14:22:49 +00:00
TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None), <type 'int'>, '42')
2015-07-09 23:14:32 +00:00
>>> C(None)
C(x=None)
2016-08-16 10:18:03 +00:00
2017-05-10 13:37:50 +00:00
Converters
----------
.. autofunction :: attr.converters.optional
For example:
.. doctest ::
>>> @attr.s
... class C(object):
... x = attr.ib(convert=attr.converters.optional(int))
>>> C(None)
C(x=None)
>>> C(42)
C(x=42)
2016-08-16 10:18:03 +00:00
Deprecated APIs
---------------
The serious business aliases used to be called `` attr.attributes `` and `` attr.attr `` .
There are no plans to remove them but they shouldn't be used in new code.
2017-02-03 10:03:16 +00:00
.. autofunction :: assoc