tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

api.rst (22686B)


      1 API Reference
      2 =============
      3 
      4 .. module:: attrs
      5 
      6 *attrs* works by decorating a class using `attrs.define` or `attr.s` and then defining attributes on the class using `attrs.field`, `attr.ib`, or type annotations.
      7 
      8 What follows is the API explanation, if you'd like a more hands-on tutorial, have a look at `examples`.
      9 
     10 If you're confused by the many names, please check out `names` for clarification, but the `TL;DR <https://en.wikipedia.org/wiki/TL;DR>`_ is that as of version 21.3.0, *attrs* consists of **two** top-level package names:
     11 
     12 - The classic ``attr`` that powers the venerable `attr.s` and `attr.ib`.
     13 - The newer ``attrs`` that only contains most modern APIs and relies on `attrs.define` and `attrs.field` to define your classes.
     14  Additionally it offers some ``attr`` APIs with nicer defaults (e.g. `attrs.asdict`).
     15 
     16 The ``attrs`` namespace is built *on top of* ``attr`` -- which will *never* go away -- and is just as stable, since it doesn't constitute a rewrite.
     17 To keep repetition low and this document at a reasonable size, the ``attr`` namespace is `documented on a separate page <api-attr>`, though.
     18 
     19 
     20 Core
     21 ----
     22 
     23 .. autodata:: attrs.NOTHING
     24   :no-value:
     25 
     26 .. autofunction:: attrs.define
     27 
     28 .. function:: mutable(same_as_define)
     29 
     30   Same as `attrs.define`.
     31 
     32   .. versionadded:: 20.1.0
     33 
     34 .. function:: frozen(same_as_define)
     35 
     36   Behaves the same as `attrs.define` but sets *frozen=True* and *on_setattr=None*.
     37 
     38   .. versionadded:: 20.1.0
     39 
     40 .. autofunction:: field
     41 
     42 .. autoclass:: Attribute
     43   :members: evolve
     44 
     45   For example:
     46 
     47   .. doctest::
     48 
     49      >>> import attrs
     50      >>> from attrs import define, field
     51 
     52      >>> @define
     53      ... class C:
     54      ...     x = field()
     55      >>> attrs.fields(C).x
     56      Attribute(name='x', default=NOTHING, validator=None, repr=True, eq=True, eq_key=None, order=True, order_key=None, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False, inherited=False, on_setattr=None, alias='x')
     57 
     58 
     59 .. autofunction:: make_class
     60 
     61   This is handy if you want to programmatically create classes.
     62 
     63   For example:
     64 
     65   .. doctest::
     66 
     67      >>> C1 = attrs.make_class("C1", ["x", "y"])
     68      >>> C1(1, 2)
     69      C1(x=1, y=2)
     70      >>> C2 = attrs.make_class("C2", {
     71      ...     "x": field(default=42),
     72      ...     "y": field(factory=list)
     73      ... })
     74      >>> C2()
     75      C2(x=42, y=[])
     76 
     77 
     78 .. autoclass:: Factory
     79 
     80   For example:
     81 
     82   .. doctest::
     83 
     84      >>> @define
     85      ... class C:
     86      ...     x = field(default=attrs.Factory(list))
     87      ...     y = field(default=attrs.Factory(
     88      ...         lambda self: set(self.x),
     89      ...         takes_self=True)
     90      ...     )
     91      >>> C()
     92      C(x=[], y=set())
     93      >>> C([1, 2, 3])
     94      C(x=[1, 2, 3], y={1, 2, 3})
     95 
     96 
     97 Exceptions
     98 ----------
     99 
    100 .. module:: attrs.exceptions
    101 
    102 All exceptions are available from both ``attr.exceptions`` and ``attrs.exceptions`` and are the same thing.
    103 That means that it doesn't matter from from which namespace they've been raised and/or caught:
    104 
    105 .. doctest::
    106 
    107   >>> import attrs, attr
    108   >>> try:
    109   ...     raise attrs.exceptions.FrozenError()
    110   ... except attr.exceptions.FrozenError:
    111   ...     print("this works!")
    112   this works!
    113 
    114 .. autoexception:: PythonTooOldError
    115 .. autoexception:: FrozenError
    116 .. autoexception:: FrozenInstanceError
    117 .. autoexception:: FrozenAttributeError
    118 .. autoexception:: AttrsAttributeNotFoundError
    119 .. autoexception:: NotAnAttrsClassError
    120 .. autoexception:: DefaultAlreadySetError
    121 .. autoexception:: NotCallableError
    122 .. autoexception:: UnannotatedAttributeError
    123 
    124   For example::
    125 
    126       @attr.s(auto_attribs=True)
    127       class C:
    128           x: int
    129           y = attr.ib()  # <- ERROR!
    130 
    131 
    132 .. _helpers:
    133 
    134 Helpers
    135 -------
    136 
    137 *attrs* comes with a bunch of helper methods that make working with it easier:
    138 
    139 .. currentmodule:: attrs
    140 
    141 .. autofunction:: attrs.cmp_using
    142 
    143 .. autofunction:: attrs.fields
    144 
    145   For example:
    146 
    147   .. doctest::
    148 
    149      >>> @define
    150      ... class C:
    151      ...     x = field()
    152      ...     y = field()
    153      >>> attrs.fields(C)
    154      (Attribute(name='x', default=NOTHING, validator=None, repr=True, eq=True, eq_key=None, order=True, order_key=None, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False, inherited=False, on_setattr=None, alias='x'), Attribute(name='y', default=NOTHING, validator=None, repr=True, eq=True, eq_key=None, order=True, order_key=None, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False, inherited=False, on_setattr=None, alias='y'))
    155      >>> attrs.fields(C)[1]
    156      Attribute(name='y', default=NOTHING, validator=None, repr=True, eq=True, eq_key=None, order=True, order_key=None, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False, inherited=False, on_setattr=None, alias='y')
    157      >>> attrs.fields(C).y is attrs.fields(C)[1]
    158      True
    159 
    160 .. autofunction:: attrs.fields_dict
    161 
    162   For example:
    163 
    164   .. doctest::
    165 
    166      >>> @attr.s
    167      ... class C:
    168      ...     x = attr.ib()
    169      ...     y = attr.ib()
    170      >>> attrs.fields_dict(C)
    171      {'x': Attribute(name='x', default=NOTHING, validator=None, repr=True, eq=True, eq_key=None, order=True, order_key=None, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False, inherited=False, on_setattr=None, alias='x'), 'y': Attribute(name='y', default=NOTHING, validator=None, repr=True, eq=True, eq_key=None, order=True, order_key=None, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False, inherited=False, on_setattr=None, alias='y')}
    172      >>> attr.fields_dict(C)['y']
    173      Attribute(name='y', default=NOTHING, validator=None, repr=True, eq=True, eq_key=None, order=True, order_key=None, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False, inherited=False, on_setattr=None, alias='y')
    174      >>> attrs.fields_dict(C)['y'] is attrs.fields(C).y
    175      True
    176 
    177 .. autofunction:: attrs.has
    178 
    179   For example:
    180 
    181   .. doctest::
    182 
    183      >>> @attr.s
    184      ... class C:
    185      ...     pass
    186      >>> attr.has(C)
    187      True
    188      >>> attr.has(object)
    189      False
    190 
    191 .. autofunction:: attrs.resolve_types
    192 
    193    For example:
    194 
    195    .. doctest::
    196 
    197        >>> import typing
    198        >>> @define
    199        ... class A:
    200        ...     a: typing.List['A']
    201        ...     b: 'B'
    202        ...
    203        >>> @define
    204        ... class B:
    205        ...     a: A
    206        ...
    207        >>> attrs.fields(A).a.type
    208        typing.List[ForwardRef('A')]
    209        >>> attrs.fields(A).b.type
    210        'B'
    211        >>> attrs.resolve_types(A, globals(), locals())
    212        <class 'A'>
    213        >>> attrs.fields(A).a.type
    214        typing.List[A]
    215        >>> attrs.fields(A).b.type
    216        <class 'B'>
    217 
    218 .. autofunction:: attrs.asdict
    219 
    220   For example:
    221 
    222   .. doctest::
    223 
    224      >>> @define
    225      ... class C:
    226      ...     x: int
    227      ...     y: int
    228      >>> attrs.asdict(C(1, C(2, 3)))
    229      {'x': 1, 'y': {'x': 2, 'y': 3}}
    230 
    231 .. autofunction:: attrs.astuple
    232 
    233   For example:
    234 
    235   .. doctest::
    236 
    237      >>> @define
    238      ... class C:
    239      ...     x = field()
    240      ...     y = field()
    241      >>> attrs.astuple(C(1,2))
    242      (1, 2)
    243 
    244 .. module:: attrs.filters
    245 
    246 *attrs* includes helpers for filtering the attributes in `attrs.asdict` and `attrs.astuple`:
    247 
    248 .. autofunction:: include
    249 
    250 .. autofunction:: exclude
    251 
    252 See :func:`attrs.asdict` for examples.
    253 
    254 All objects from ``attrs.filters`` are also available from ``attr.filters`` (it's the same module in a different namespace).
    255 
    256 ----
    257 
    258 .. currentmodule:: attrs
    259 
    260 .. autofunction:: attrs.evolve
    261 
    262   For example:
    263 
    264   .. doctest::
    265 
    266      >>> @define
    267      ... class C:
    268      ...     x: int
    269      ...     y: int
    270      >>> i1 = C(1, 2)
    271      >>> i1
    272      C(x=1, y=2)
    273      >>> i2 = attrs.evolve(i1, y=3)
    274      >>> i2
    275      C(x=1, y=3)
    276      >>> i1 == i2
    277      False
    278 
    279   ``evolve`` creates a new instance using ``__init__``.
    280   This fact has several implications:
    281 
    282   * private attributes should be specified without the leading underscore, just like in ``__init__``.
    283   * attributes with ``init=False`` can't be set with ``evolve``.
    284   * the usual ``__init__`` validators will validate the new values.
    285 
    286 .. autofunction:: attrs.validate
    287 
    288   For example:
    289 
    290   .. doctest::
    291 
    292      >>> @define(on_setattr=attrs.setters.NO_OP)
    293      ... class C:
    294      ...     x = field(validator=attrs.validators.instance_of(int))
    295      >>> i = C(1)
    296      >>> i.x = "1"
    297      >>> attrs.validate(i)
    298      Traceback (most recent call last):
    299         ...
    300      TypeError: ("'x' must be <class 'int'> (got '1' that is a <class 'str'>).", ...)
    301 
    302 
    303 .. _api-validators:
    304 
    305 Validators
    306 ----------
    307 
    308 .. module:: attrs.validators
    309 
    310 *attrs* comes with some common validators in the ``attrs.validators`` module.
    311 All objects from ``attrs.validators`` are also available from ``attr.validators`` (it's the same module in a different namespace).
    312 
    313 .. autofunction:: attrs.validators.lt
    314 
    315   For example:
    316 
    317   .. doctest::
    318 
    319      >>> @define
    320      ... class C:
    321      ...     x = field(validator=attrs.validators.lt(42))
    322      >>> C(41)
    323      C(x=41)
    324      >>> C(42)
    325      Traceback (most recent call last):
    326         ...
    327      ValueError: ("'x' must be < 42: 42")
    328 
    329 .. autofunction:: attrs.validators.le
    330 
    331   For example:
    332 
    333   .. doctest::
    334 
    335      >>> @define
    336      ... class C:
    337      ...     x = field(validator=attrs.validators.le(42))
    338      >>> C(42)
    339      C(x=42)
    340      >>> C(43)
    341      Traceback (most recent call last):
    342         ...
    343      ValueError: ("'x' must be <= 42: 43")
    344 
    345 .. autofunction:: attrs.validators.ge
    346 
    347   For example:
    348 
    349   .. doctest::
    350 
    351      >>> @define
    352      ... class C:
    353      ...     x = attrs.field(validator=attrs.validators.ge(42))
    354      >>> C(42)
    355      C(x=42)
    356      >>> C(41)
    357      Traceback (most recent call last):
    358         ...
    359      ValueError: ("'x' must be => 42: 41")
    360 
    361 .. autofunction:: attrs.validators.gt
    362 
    363   For example:
    364 
    365   .. doctest::
    366 
    367      >>> @define
    368      ... class C:
    369      ...     x = field(validator=attrs.validators.gt(42))
    370      >>> C(43)
    371      C(x=43)
    372      >>> C(42)
    373      Traceback (most recent call last):
    374         ...
    375      ValueError: ("'x' must be > 42: 42")
    376 
    377 .. autofunction:: attrs.validators.max_len
    378 
    379   For example:
    380 
    381   .. doctest::
    382 
    383      >>> @define
    384      ... class C:
    385      ...     x = field(validator=attrs.validators.max_len(4))
    386      >>> C("spam")
    387      C(x='spam')
    388      >>> C("bacon")
    389      Traceback (most recent call last):
    390         ...
    391      ValueError: ("Length of 'x' must be <= 4: 5")
    392 
    393 .. autofunction:: attrs.validators.min_len
    394 
    395   For example:
    396 
    397   .. doctest::
    398 
    399      >>> @define
    400      ... class C:
    401      ...     x = field(validator=attrs.validators.min_len(1))
    402      >>> C("bacon")
    403      C(x='bacon')
    404      >>> C("")
    405      Traceback (most recent call last):
    406         ...
    407      ValueError: ("Length of 'x' must be => 1: 0")
    408 
    409 .. autofunction:: attrs.validators.instance_of
    410 
    411   For example:
    412 
    413   .. doctest::
    414 
    415      >>> @define
    416      ... class C:
    417      ...     x = field(validator=attrs.validators.instance_of(int))
    418      >>> C(42)
    419      C(x=42)
    420      >>> C("42")
    421      Traceback (most recent call last):
    422         ...
    423      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, kw_only=False), <type 'int'>, '42')
    424      >>> C(None)
    425      Traceback (most recent call last):
    426         ...
    427      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, kw_only=False), <type 'int'>, None)
    428 
    429 .. autofunction:: attrs.validators.in_
    430 
    431   For example:
    432 
    433   .. doctest::
    434 
    435      >>> import enum
    436      >>> class State(enum.Enum):
    437      ...     ON = "on"
    438      ...     OFF = "off"
    439      >>> @define
    440      ... class C:
    441      ...     state = field(validator=attrs.validators.in_(State))
    442      ...     val = field(validator=attrs.validators.in_([1, 2, 3]))
    443      >>> C(State.ON, 1)
    444      C(state=<State.ON: 'on'>, val=1)
    445      >>> C("On", 1)
    446      Traceback (most recent call last):
    447         ...
    448      ValueError: 'state' must be in <enum 'State'> (got 'On'), Attribute(name='state', default=NOTHING, validator=<in_ validator with options <enum 'State'>>, repr=True, eq=True, eq_key=None, order=True, order_key=None, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False, inherited=False, on_setattr=None), <enum 'State'>, 'on')
    449      >>> C(State.ON, 4)
    450      Traceback (most recent call last):
    451      ...
    452      ValueError: 'val' must be in [1, 2, 3] (got 4), Attribute(name='val', default=NOTHING, validator=<in_ validator with options [1, 2, 3]>, repr=True, eq=True, eq_key=None, order=True, order_key=None, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False, inherited=False, on_setattr=None), [1, 2, 3], 4)
    453 
    454 .. autofunction:: attrs.validators.provides
    455 
    456 .. autofunction:: attrs.validators.and_
    457 
    458   For convenience, it's also possible to pass a list to `attrs.field`'s validator argument.
    459 
    460   Thus the following two statements are equivalent::
    461 
    462      x = field(validator=attrs.validators.and_(v1, v2, v3))
    463      x = field(validator=[v1, v2, v3])
    464 
    465 .. autofunction:: attrs.validators.not_
    466 
    467   For example:
    468 
    469   .. doctest::
    470 
    471      >>> reserved_names = {"id", "time", "source"}
    472      >>> @define
    473      ... class Measurement:
    474      ...     tags = field(
    475      ...         validator=attrs.validators.deep_mapping(
    476      ...             key_validator=attrs.validators.not_(
    477      ...                 attrs.validators.in_(reserved_names),
    478      ...                 msg="reserved tag key",
    479      ...             ),
    480      ...             value_validator=attrs.validators.instance_of((str, int)),
    481      ...         )
    482      ...     )
    483      >>> Measurement(tags={"source": "universe"})
    484      Traceback (most recent call last):
    485         ...
    486      ValueError: ("reserved tag key", Attribute(name='tags', default=NOTHING, validator=<not_ validator wrapping <in_ validator with options {'id', 'time', 'source'}>, capturing (<class 'ValueError'>, <class 'TypeError'>)>, type=None, kw_only=False), <in_ validator with options {'id', 'time', 'source'}>, {'source_': 'universe'}, (<class 'ValueError'>, <class 'TypeError'>))
    487      >>> Measurement(tags={"source_": "universe"})
    488      Measurement(tags={'source_': 'universe'})
    489 
    490 
    491 .. autofunction:: attrs.validators.optional
    492 
    493   For example:
    494 
    495   .. doctest::
    496 
    497      >>> @define
    498      ... class C:
    499      ...     x = field(
    500      ...         validator=attrs.validators.optional(
    501      ...             attrs.validators.instance_of(int)
    502      ...         ))
    503      >>> C(42)
    504      C(x=42)
    505      >>> C("42")
    506      Traceback (most recent call last):
    507         ...
    508      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, kw_only=False), <type 'int'>, '42')
    509      >>> C(None)
    510      C(x=None)
    511 
    512 
    513 .. autofunction:: attrs.validators.is_callable
    514 
    515    For example:
    516 
    517    .. doctest::
    518 
    519        >>> @define
    520        ... class C:
    521        ...     x = field(validator=attrs.validators.is_callable())
    522        >>> C(isinstance)
    523        C(x=<built-in function isinstance>)
    524        >>> C("not a callable")
    525        Traceback (most recent call last):
    526            ...
    527        attr.exceptions.NotCallableError: 'x' must be callable (got 'not a callable' that is a <class 'str'>).
    528 
    529 
    530 .. autofunction:: attrs.validators.matches_re
    531 
    532    For example:
    533 
    534    .. doctest::
    535 
    536        >>> @define
    537        ... class User:
    538        ...     email = field(validator=attrs.validators.matches_re(
    539        ...         r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)"))
    540        >>> User(email="user@example.com")
    541        User(email='user@example.com')
    542        >>> User(email="user@example.com@test.com")
    543        Traceback (most recent call last):
    544            ...
    545        ValueError: ("'email' must match regex '(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\\\.[a-zA-Z0-9-.]+$)' ('user@example.com@test.com' doesn't)", Attribute(name='email', default=NOTHING, validator=<matches_re validator for pattern re.compile('(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$)')>, repr=True, cmp=True, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False), re.compile('(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$)'), 'user@example.com@test.com')
    546 
    547 
    548 .. autofunction:: attrs.validators.deep_iterable
    549 
    550    For example:
    551 
    552    .. doctest::
    553 
    554        >>> @define
    555        ... class C:
    556        ...     x = field(validator=attrs.validators.deep_iterable(
    557        ...             member_validator=attrs.validators.instance_of(int),
    558        ...             iterable_validator=attrs.validators.instance_of(list)
    559        ...     ))
    560        >>> C(x=[1, 2, 3])
    561        C(x=[1, 2, 3])
    562        >>> C(x=set([1, 2, 3]))
    563        Traceback (most recent call last):
    564            ...
    565        TypeError: ("'x' must be <class 'list'> (got {1, 2, 3} that is a <class 'set'>).", Attribute(name='x', default=NOTHING, validator=<deep_iterable validator for <instance_of validator for type <class 'list'>> iterables of <instance_of validator for type <class 'int'>>>, repr=True, cmp=True, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False), <class 'list'>, {1, 2, 3})
    566        >>> C(x=[1, 2, "3"])
    567        Traceback (most recent call last):
    568            ...
    569        TypeError: ("'x' must be <class 'int'> (got '3' that is a <class 'str'>).", Attribute(name='x', default=NOTHING, validator=<deep_iterable validator for <instance_of validator for type <class 'list'>> iterables of <instance_of validator for type <class 'int'>>>, repr=True, cmp=True, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False), <class 'int'>, '3')
    570 
    571 
    572 .. autofunction:: attrs.validators.deep_mapping
    573 
    574    For example:
    575 
    576    .. doctest::
    577 
    578        >>> @define
    579        ... class C:
    580        ...     x = field(validator=attrs.validators.deep_mapping(
    581        ...             key_validator=attrs.validators.instance_of(str),
    582        ...             value_validator=attrs.validators.instance_of(int),
    583        ...             mapping_validator=attrs.validators.instance_of(dict)
    584        ...     ))
    585        >>> C(x={"a": 1, "b": 2})
    586        C(x={'a': 1, 'b': 2})
    587        >>> C(x=None)
    588        Traceback (most recent call last):
    589            ...
    590        TypeError: ("'x' must be <class 'dict'> (got None that is a <class 'NoneType'>).", Attribute(name='x', default=NOTHING, validator=<deep_mapping validator for objects mapping <instance_of validator for type <class 'str'>> to <instance_of validator for type <class 'int'>>>, repr=True, cmp=True, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False), <class 'dict'>, None)
    591        >>> C(x={"a": 1.0, "b": 2})
    592        Traceback (most recent call last):
    593            ...
    594        TypeError: ("'x' must be <class 'int'> (got 1.0 that is a <class 'float'>).", Attribute(name='x', default=NOTHING, validator=<deep_mapping validator for objects mapping <instance_of validator for type <class 'str'>> to <instance_of validator for type <class 'int'>>>, repr=True, cmp=True, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False), <class 'int'>, 1.0)
    595        >>> C(x={"a": 1, 7: 2})
    596        Traceback (most recent call last):
    597            ...
    598        TypeError: ("'x' must be <class 'str'> (got 7 that is a <class 'int'>).", Attribute(name='x', default=NOTHING, validator=<deep_mapping validator for objects mapping <instance_of validator for type <class 'str'>> to <instance_of validator for type <class 'int'>>>, repr=True, cmp=True, hash=None, init=True, metadata=mappingproxy({}), type=None, converter=None, kw_only=False), <class 'str'>, 7)
    599 
    600 Validators can be both globally and locally disabled:
    601 
    602 .. autofunction:: attrs.validators.set_disabled
    603 
    604 .. autofunction:: attrs.validators.get_disabled
    605 
    606 .. autofunction:: attrs.validators.disabled
    607 
    608 
    609 Converters
    610 ----------
    611 
    612 .. module:: attrs.converters
    613 
    614 All objects from ``attrs.converters`` are also available from ``attr.converters`` (it's the same module in a different namespace).
    615 
    616 .. autofunction:: attrs.converters.pipe
    617 
    618   For convenience, it's also possible to pass a list to `attrs.field` / `attr.ib`'s converter arguments.
    619 
    620   Thus the following two statements are equivalent::
    621 
    622      x = attrs.field(converter=attrs.converter.pipe(c1, c2, c3))
    623      x = attrs.field(converter=[c1, c2, c3])
    624 
    625 .. autofunction:: attrs.converters.optional
    626 
    627   For example:
    628 
    629   .. doctest::
    630 
    631      >>> @define
    632      ... class C:
    633      ...     x = field(converter=attrs.converters.optional(int))
    634      >>> C(None)
    635      C(x=None)
    636      >>> C(42)
    637      C(x=42)
    638 
    639 
    640 .. autofunction:: attrs.converters.default_if_none
    641 
    642   For example:
    643 
    644   .. doctest::
    645 
    646      >>> @define
    647      ... class C:
    648      ...     x = field(
    649      ...         converter=attrs.converters.default_if_none("")
    650      ...     )
    651      >>> C(None)
    652      C(x='')
    653 
    654 
    655 .. autofunction:: attrs.converters.to_bool
    656 
    657   For example:
    658 
    659   .. doctest::
    660 
    661      >>> @define
    662      ... class C:
    663      ...     x = field(
    664      ...         converter=attrs.converters.to_bool
    665      ...     )
    666      >>> C("yes")
    667      C(x=True)
    668      >>> C(0)
    669      C(x=False)
    670      >>> C("foo")
    671      Traceback (most recent call last):
    672         File "<stdin>", line 1, in <module>
    673      ValueError: Cannot convert value to bool: foo
    674 
    675 
    676 
    677 .. _api_setters:
    678 
    679 Setters
    680 -------
    681 
    682 .. module:: attrs.setters
    683 
    684 These are helpers that you can use together with `attrs.define`'s and `attrs.fields`'s ``on_setattr`` arguments.
    685 All setters in ``attrs.setters`` are also available from ``attr.setters`` (it's the same module in a different namespace).
    686 
    687 .. autofunction:: frozen
    688 .. autofunction:: validate
    689 .. autofunction:: convert
    690 .. autofunction:: pipe
    691 
    692 .. data:: NO_OP
    693 
    694   Sentinel for disabling class-wide *on_setattr* hooks for certain attributes.
    695 
    696   Does not work in `attrs.setters.pipe` or within lists.
    697 
    698   .. versionadded:: 20.1.0
    699 
    700   For example, only ``x`` is frozen here:
    701 
    702   .. doctest::
    703 
    704     >>> @define(on_setattr=attr.setters.frozen)
    705     ... class C:
    706     ...     x = field()
    707     ...     y = field(on_setattr=attr.setters.NO_OP)
    708     >>> c = C(1, 2)
    709     >>> c.y = 3
    710     >>> c.y
    711     3
    712     >>> c.x = 4
    713     Traceback (most recent call last):
    714         ...
    715     attrs.exceptions.FrozenAttributeError: ()
    716 
    717   N.B. Please use `attrs.define`'s *frozen* argument (or `attrs.frozen`) to freeze whole classes; it is more efficient.