1.. _api:
2
3API Reference
4=============
5
6.. currentmodule:: attr
7
8``attrs`` works by decorating a class using :func:`attr.s` and then optionally defining attributes on the class using :func:`attr.ib`.
9
10.. note::
11
12   When this documentation speaks about "``attrs`` attributes" it means those attributes that are defined using :func:`attr.ib` in the class body.
13
14What follows is the API explanation, if you'd like a more hands-on introduction, have a look at :doc:`examples`.
15
16
17
18Core
19----
20
21.. autofunction:: attr.s(these=None, repr_ns=None, repr=True, cmp=True, hash=None, init=True, slots=False, frozen=False, str=False)
22
23   .. note::
24
25      ``attrs`` also comes with a serious business alias ``attr.attrs``.
26
27   For example:
28
29   .. doctest::
30
31      >>> import attr
32      >>> @attr.s
33      ... class C(object):
34      ...     _private = attr.ib()
35      >>> C(private=42)
36      C(_private=42)
37      >>> class D(object):
38      ...     def __init__(self, x):
39      ...         self.x = x
40      >>> D(1)
41      <D object at ...>
42      >>> D = attr.s(these={"x": attr.ib()}, init=False)(D)
43      >>> D(1)
44      D(x=1)
45
46
47.. autofunction:: attr.ib
48
49   .. note::
50
51      ``attrs`` also comes with a serious business alias ``attr.attrib``.
52
53   The object returned by :func:`attr.ib` also allows for setting the default and the validator using decorators:
54
55   .. doctest::
56
57      >>> @attr.s
58      ... class C(object):
59      ...     x = attr.ib()
60      ...     y = attr.ib()
61      ...     @x.validator
62      ...     def name_can_be_anything(self, attribute, value):
63      ...         if value < 0:
64      ...             raise ValueError("x must be positive")
65      ...     @y.default
66      ...     def name_does_not_matter(self):
67      ...         return self.x + 1
68      >>> C(1)
69      C(x=1, y=2)
70      >>> C(-1)
71      Traceback (most recent call last):
72          ...
73      ValueError: x must be positive
74
75.. autoclass:: attr.Attribute
76
77   Instances of this class are frequently used for introspection purposes like:
78
79   - :func:`fields` returns a tuple of them.
80   - Validators get them passed as the first argument.
81
82   .. warning::
83
84       You should never instantiate this class yourself!
85
86   .. doctest::
87
88      >>> import attr
89      >>> @attr.s
90      ... class C(object):
91      ...     x = attr.ib()
92      >>> attr.fields(C).x
93      Attribute(name='x', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}), type=None)
94
95
96.. autofunction:: attr.make_class
97
98   This is handy if you want to programmatically create classes.
99
100   For example:
101
102   .. doctest::
103
104      >>> C1 = attr.make_class("C1", ["x", "y"])
105      >>> C1(1, 2)
106      C1(x=1, y=2)
107      >>> C2 = attr.make_class("C2", {"x": attr.ib(default=42),
108      ...                             "y": attr.ib(default=attr.Factory(list))})
109      >>> C2()
110      C2(x=42, y=[])
111
112
113.. autoclass:: attr.Factory
114
115   For example:
116
117   .. doctest::
118
119      >>> @attr.s
120      ... class C(object):
121      ...     x = attr.ib(default=attr.Factory(list))
122      ...     y = attr.ib(default=attr.Factory(
123      ...         lambda self: set(self.x),
124      ...         takes_self=True)
125      ...     )
126      >>> C()
127      C(x=[], y=set())
128      >>> C([1, 2, 3])
129      C(x=[1, 2, 3], y={1, 2, 3})
130
131
132.. autoexception:: attr.exceptions.FrozenInstanceError
133.. autoexception:: attr.exceptions.AttrsAttributeNotFoundError
134.. autoexception:: attr.exceptions.NotAnAttrsClassError
135.. autoexception:: attr.exceptions.DefaultAlreadySetError
136.. autoexception:: attr.exceptions.UnannotatedAttributeError
137
138   For example::
139
140       @attr.s(auto_attribs=True)
141       class C:
142           x: int
143           y = attr.ib()
144
145
146Influencing Initialization
147++++++++++++++++++++++++++
148
149Generally speaking, it's best to keep logic out of your ``__init__``.
150The 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>`_.
151
152However, sometimes you need to do that one quick thing after your class is initialized.
153And for that ``attrs`` offers the ``__attrs_post_init__`` hook that is automatically detected and run after ``attrs`` is done initializing your instance:
154
155.. doctest::
156
157   >>> @attr.s
158   ... class C(object):
159   ...     x = attr.ib()
160   ...     y = attr.ib(init=False)
161   ...     def __attrs_post_init__(self):
162   ...         self.y = self.x + 1
163   >>> C(1)
164   C(x=1, y=2)
165
166Please note that you can't directly set attributes on frozen classes:
167
168.. doctest::
169
170   >>> @attr.s(frozen=True)
171   ... class FrozenBroken(object):
172   ...     x = attr.ib()
173   ...     y = attr.ib(init=False)
174   ...     def __attrs_post_init__(self):
175   ...         self.y = self.x + 1
176   >>> FrozenBroken(1)
177   Traceback (most recent call last):
178      ...
179   attr.exceptions.FrozenInstanceError: can't set attribute
180
181If 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__`:
182
183.. doctest::
184
185   >>> @attr.s(frozen=True)
186   ... class Frozen(object):
187   ...     x = attr.ib()
188   ...     y = attr.ib(init=False)
189   ...     def __attrs_post_init__(self):
190   ...         object.__setattr__(self, "y", self.x + 1)
191   >>> Frozen(1)
192   Frozen(x=1, y=2)
193
194
195.. _helpers:
196
197Helpers
198-------
199
200``attrs`` comes with a bunch of helper methods that make working with it easier:
201
202.. autofunction:: attr.fields
203
204   For example:
205
206   .. doctest::
207
208      >>> @attr.s
209      ... class C(object):
210      ...     x = attr.ib()
211      ...     y = attr.ib()
212      >>> attr.fields(C)
213      (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))
214      >>> attr.fields(C)[1]
215      Attribute(name='y', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}), type=None)
216      >>> attr.fields(C).y is attr.fields(C)[1]
217      True
218
219
220.. autofunction:: attr.has
221
222   For example:
223
224   .. doctest::
225
226      >>> @attr.s
227      ... class C(object):
228      ...     pass
229      >>> attr.has(C)
230      True
231      >>> attr.has(object)
232      False
233
234
235.. autofunction:: attr.asdict
236
237   For example:
238
239   .. doctest::
240
241      >>> @attr.s
242      ... class C(object):
243      ...     x = attr.ib()
244      ...     y = attr.ib()
245      >>> attr.asdict(C(1, C(2, 3)))
246      {'x': 1, 'y': {'x': 2, 'y': 3}}
247
248
249.. autofunction:: attr.astuple
250
251   For example:
252
253   .. doctest::
254
255      >>> @attr.s
256      ... class C(object):
257      ...     x = attr.ib()
258      ...     y = attr.ib()
259      >>> attr.astuple(C(1,2))
260      (1, 2)
261
262``attrs`` includes some handy helpers for filtering:
263
264.. autofunction:: attr.filters.include
265
266.. autofunction:: attr.filters.exclude
267
268See :ref:`asdict` for examples.
269
270.. autofunction:: attr.evolve
271
272   For example:
273
274   .. doctest::
275
276      >>> @attr.s
277      ... class C(object):
278      ...     x = attr.ib()
279      ...     y = attr.ib()
280      >>> i1 = C(1, 2)
281      >>> i1
282      C(x=1, y=2)
283      >>> i2 = attr.evolve(i1, y=3)
284      >>> i2
285      C(x=1, y=3)
286      >>> i1 == i2
287      False
288
289   ``evolve`` creates a new instance using ``__init__``.
290   This fact has several implications:
291
292   * private attributes should be specified without the leading underscore, just like in ``__init__``.
293   * attributes with ``init=False`` can't be set with ``evolve``.
294   * the usual ``__init__`` validators will validate the new values.
295
296.. autofunction:: validate
297
298   For example:
299
300   .. doctest::
301
302      >>> @attr.s
303      ... class C(object):
304      ...     x = attr.ib(validator=attr.validators.instance_of(int))
305      >>> i = C(1)
306      >>> i.x = "1"
307      >>> attr.validate(i)
308      Traceback (most recent call last):
309         ...
310      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')
311
312
313Validators 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:
314
315.. autofunction:: set_run_validators
316
317.. autofunction:: get_run_validators
318
319
320.. _api_validators:
321
322Validators
323----------
324
325``attrs`` comes with some common validators in the ``attrs.validators`` module:
326
327
328.. autofunction:: attr.validators.instance_of
329
330
331   For example:
332
333   .. doctest::
334
335      >>> @attr.s
336      ... class C(object):
337      ...     x = attr.ib(validator=attr.validators.instance_of(int))
338      >>> C(42)
339      C(x=42)
340      >>> C("42")
341      Traceback (most recent call last):
342         ...
343      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')
344      >>> C(None)
345      Traceback (most recent call last):
346         ...
347      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)
348
349.. autofunction:: attr.validators.in_
350
351   For example:
352
353   .. doctest::
354
355       >>> import enum
356       >>> class State(enum.Enum):
357       ...     ON = "on"
358       ...     OFF = "off"
359       >>> @attr.s
360       ... class C(object):
361       ...     state = attr.ib(validator=attr.validators.in_(State))
362       ...     val = attr.ib(validator=attr.validators.in_([1, 2, 3]))
363       >>> C(State.ON, 1)
364       C(state=<State.ON: 'on'>, val=1)
365       >>> C("on", 1)
366       Traceback (most recent call last):
367          ...
368       ValueError: 'state' must be in <enum 'State'> (got 'on')
369       >>> C(State.ON, 4)
370       Traceback (most recent call last):
371          ...
372       ValueError: 'val' must be in [1, 2, 3] (got 4)
373
374.. autofunction:: attr.validators.provides
375
376.. autofunction:: attr.validators.and_
377
378   For convenience, it's also possible to pass a list to :func:`attr.ib`'s validator argument.
379
380   Thus the following two statements are equivalent::
381
382      x = attr.ib(validator=attr.validators.and_(v1, v2, v3))
383      x = attr.ib(validator=[v1, v2, v3])
384
385.. autofunction:: attr.validators.optional
386
387   For example:
388
389   .. doctest::
390
391      >>> @attr.s
392      ... class C(object):
393      ...     x = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(int)))
394      >>> C(42)
395      C(x=42)
396      >>> C("42")
397      Traceback (most recent call last):
398         ...
399      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')
400      >>> C(None)
401      C(x=None)
402
403
404Converters
405----------
406
407.. autofunction:: attr.converters.optional
408
409   For example:
410
411   .. doctest::
412
413      >>> @attr.s
414      ... class C(object):
415      ...     x = attr.ib(convert=attr.converters.optional(int))
416      >>> C(None)
417      C(x=None)
418      >>> C(42)
419      C(x=42)
420
421
422Deprecated APIs
423---------------
424
425The serious business aliases used to be called ``attr.attributes`` and ``attr.attr``.
426There are no plans to remove them but they shouldn't be used in new code.
427
428.. autofunction:: assoc
429