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