| API Reference | |
| ============= | |
| .. module:: attrs | |
| *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. | |
| What follows is the dry API explanation for people who understand how *attrs* works. | |
| If you'd like a hands-on tutorial, have a look at `examples`. | |
| 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: | |
| - The classic ``attr`` that powers the venerable `attr.s` and `attr.ib`. | |
| - The newer ``attrs`` that only contains most modern APIs and relies on `attrs.define` and `attrs.field` to define your classes. | |
| Additionally, some of the APIs that also exist in ``attr`` have nicer defaults (for example, `attrs.asdict`). | |
| 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. | |
| To keep repetition low and this document at a reasonable size, the ``attr`` namespace is `documented on a separate page <api-attr>`. | |
| Core | |
| ---- | |
| .. autofunction:: attrs.define | |
| .. function:: mutable(same_as_define) | |
| Same as `attrs.define`. | |
| .. versionadded:: 20.1.0 | |
| .. function:: frozen(same_as_define) | |
| Behaves the same as `attrs.define` but sets *frozen=True* and *on_setattr=None*. | |
| .. versionadded:: 20.1.0 | |
| .. autofunction:: field | |
| .. autoclass:: Attribute | |
| :members: evolve | |
| For example: | |
| .. doctest:: | |
| >>> import attrs | |
| >>> from attrs import define, field | |
| >>> @define | |
| ... class C: | |
| ... x = field() | |
| >>> attrs.fields(C).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') | |
| .. autofunction:: make_class | |
| This is handy if you want to programmatically create classes. | |
| For example: | |
| .. doctest:: | |
| >>> C1 = attrs.make_class("C1", ["x", "y"]) | |
| >>> C1(1, 2) | |
| C1(x=1, y=2) | |
| >>> C2 = attrs.make_class("C2", { | |
| ... "x": field(default=42), | |
| ... "y": field(factory=list) | |
| ... }) | |
| >>> C2() | |
| C2(x=42, y=[]) | |
| .. autoclass:: Factory | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field(default=attrs.Factory(list)) | |
| ... y = field(default=attrs.Factory( | |
| ... lambda self: set(self.x), | |
| ... takes_self=True) | |
| ... ) | |
| >>> C() | |
| C(x=[], y=set()) | |
| >>> C([1, 2, 3]) | |
| C(x=[1, 2, 3], y={1, 2, 3}) | |
| .. autodata:: attrs.NOTHING | |
| :no-value: | |
| Exceptions | |
| ---------- | |
| .. module:: attrs.exceptions | |
| All exceptions are available from both ``attr.exceptions`` and ``attrs.exceptions`` and are the same thing. | |
| That means that it doesn't matter from from which namespace they've been raised and/or caught: | |
| .. doctest:: | |
| >>> import attrs, attr | |
| >>> try: | |
| ... raise attrs.exceptions.FrozenError() | |
| ... except attr.exceptions.FrozenError: | |
| ... print("this works!") | |
| this works! | |
| .. autoexception:: PythonTooOldError | |
| .. autoexception:: FrozenError | |
| .. autoexception:: FrozenInstanceError | |
| .. autoexception:: FrozenAttributeError | |
| .. autoexception:: AttrsAttributeNotFoundError | |
| .. autoexception:: NotAnAttrsClassError | |
| .. autoexception:: DefaultAlreadySetError | |
| .. autoexception:: NotCallableError | |
| .. autoexception:: UnannotatedAttributeError | |
| For example:: | |
| @attr.s(auto_attribs=True) | |
| class C: | |
| x: int | |
| y = attr.ib() # <- ERROR! | |
| .. _helpers: | |
| Helpers | |
| ------- | |
| *attrs* comes with a bunch of helper methods that make working with it easier: | |
| .. currentmodule:: attrs | |
| .. autofunction:: attrs.cmp_using | |
| .. autofunction:: attrs.fields | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field() | |
| ... y = field() | |
| >>> attrs.fields(C) | |
| (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')) | |
| >>> attrs.fields(C(1, 2)) is attrs.fields(C) | |
| True | |
| >>> attrs.fields(C)[1] | |
| 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') | |
| >>> attrs.fields(C).y is attrs.fields(C)[1] | |
| True | |
| .. autofunction:: attrs.fields_dict | |
| For example: | |
| .. doctest:: | |
| >>> @attr.s | |
| ... class C: | |
| ... x = attr.ib() | |
| ... y = attr.ib() | |
| >>> attrs.fields_dict(C) | |
| {'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')} | |
| >>> attr.fields_dict(C)['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') | |
| >>> attrs.fields_dict(C)['y'] is attrs.fields(C).y | |
| True | |
| .. autofunction:: attrs.has | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... pass | |
| >>> attrs.has(C) | |
| True | |
| >>> attrs.has(object) | |
| False | |
| .. autofunction:: attrs.inspect | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class CInspect: | |
| ... pass | |
| >>> attrs.inspect(CInspect) # doctest: +ELLIPSIS | |
| ClassProps(is_exception=False, is_slotted=True, has_weakref_slot=True, is_frozen=False, kw_only=<KeywordOnly.NO: 'no'>, collected_fields_by_mro=True, added_init=True, added_repr=True, added_eq=True, added_ordering=False, hashability=<Hashability.UNHASHABLE: 'unhashable'>, added_match_args=True, added_str=False, added_pickling=True, on_setattr_hook=<function pipe.<locals>.wrapped_pipe at ...>, field_transformer=None) | |
| .. autoclass:: attrs.ClassProps | |
| .. autoclass:: attrs.ClassProps.Hashability | |
| :members: HASHABLE, HASHABLE_CACHED, UNHASHABLE, LEAVE_ALONE | |
| .. autoclass:: attrs.ClassProps.KeywordOnly | |
| :members: NO, YES, FORCE | |
| .. autofunction:: attrs.resolve_types | |
| For example: | |
| .. doctest:: | |
| >>> import typing | |
| >>> @define | |
| ... class A: | |
| ... a: typing.List['A'] | |
| ... b: 'B' | |
| ... | |
| >>> @define | |
| ... class B: | |
| ... a: A | |
| ... | |
| >>> attrs.fields(A).a.type | |
| typing.List[ForwardRef('A')] | |
| >>> attrs.fields(A).b.type | |
| 'B' | |
| >>> attrs.resolve_types(A, globals(), locals()) | |
| <class 'A'> | |
| >>> attrs.fields(A).a.type | |
| typing.List[A] | |
| >>> attrs.fields(A).b.type | |
| <class 'B'> | |
| .. autofunction:: attrs.asdict | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x: int | |
| ... y: int | |
| >>> attrs.asdict(C(1, C(2, 3))) | |
| {'x': 1, 'y': {'x': 2, 'y': 3}} | |
| .. autofunction:: attrs.astuple | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field() | |
| ... y = field() | |
| >>> attrs.astuple(C(1,2)) | |
| (1, 2) | |
| .. module:: attrs.filters | |
| *attrs* includes helpers for filtering the attributes in `attrs.asdict` and `attrs.astuple`: | |
| .. autofunction:: include | |
| .. autofunction:: exclude | |
| See :func:`attrs.asdict` for examples. | |
| All objects from ``attrs.filters`` are also available from ``attr.filters`` (it's the same module in a different namespace). | |
| ---- | |
| .. currentmodule:: attrs | |
| .. autofunction:: attrs.evolve | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x: int | |
| ... y: int | |
| >>> i1 = C(1, 2) | |
| >>> i1 | |
| C(x=1, y=2) | |
| >>> i2 = attrs.evolve(i1, y=3) | |
| >>> i2 | |
| C(x=1, y=3) | |
| >>> i1 == i2 | |
| False | |
| ``evolve`` creates a new instance using ``__init__``. | |
| This fact has several implications: | |
| * 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. | |
| .. autofunction:: attrs.validate | |
| For example: | |
| .. doctest:: | |
| >>> @define(on_setattr=attrs.setters.NO_OP) | |
| ... class C: | |
| ... x = field(validator=attrs.validators.instance_of(int)) | |
| >>> i = C(1) | |
| >>> i.x = "1" | |
| >>> attrs.validate(i) | |
| Traceback (most recent call last): | |
| ... | |
| TypeError: ("'x' must be <class 'int'> (got '1' that is a <class 'str'>).", ...) | |
| .. _api-validators: | |
| Validators | |
| ---------- | |
| .. module:: attrs.validators | |
| *attrs* comes with some common validators in the ``attrs.validators`` module. | |
| All objects from ``attrs.validators`` are also available from ``attr.validators`` (it's the same module in a different namespace). | |
| .. autofunction:: attrs.validators.lt | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field(validator=attrs.validators.lt(42)) | |
| >>> C(41) | |
| C(x=41) | |
| >>> C(42) | |
| Traceback (most recent call last): | |
| ... | |
| ValueError: ("'x' must be < 42: 42") | |
| .. autofunction:: attrs.validators.le | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field(validator=attrs.validators.le(42)) | |
| >>> C(42) | |
| C(x=42) | |
| >>> C(43) | |
| Traceback (most recent call last): | |
| ... | |
| ValueError: ("'x' must be <= 42: 43") | |
| .. autofunction:: attrs.validators.ge | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = attrs.field(validator=attrs.validators.ge(42)) | |
| >>> C(42) | |
| C(x=42) | |
| >>> C(41) | |
| Traceback (most recent call last): | |
| ... | |
| ValueError: ("'x' must be => 42: 41") | |
| .. autofunction:: attrs.validators.gt | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field(validator=attrs.validators.gt(42)) | |
| >>> C(43) | |
| C(x=43) | |
| >>> C(42) | |
| Traceback (most recent call last): | |
| ... | |
| ValueError: ("'x' must be > 42: 42") | |
| .. autofunction:: attrs.validators.ne | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field(validator=attrs.validators.ne(42)) | |
| >>> C(43) | |
| C(x=43) | |
| >>> C(42) | |
| Traceback (most recent call last): | |
| ... | |
| ValueError: ("'x' must be != 42: 42") | |
| .. autofunction:: attrs.validators.max_len | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field(validator=attrs.validators.max_len(4)) | |
| >>> C("spam") | |
| C(x='spam') | |
| >>> C("bacon") | |
| Traceback (most recent call last): | |
| ... | |
| ValueError: ("Length of 'x' must be <= 4: 5") | |
| .. autofunction:: attrs.validators.min_len | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field(validator=attrs.validators.min_len(1)) | |
| >>> C("bacon") | |
| C(x='bacon') | |
| >>> C("") | |
| Traceback (most recent call last): | |
| ... | |
| ValueError: ("Length of 'x' must be => 1: 0") | |
| .. autofunction:: attrs.validators.instance_of | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field(validator=attrs.validators.instance_of(int)) | |
| >>> C(42) | |
| C(x=42) | |
| >>> C("42") | |
| Traceback (most recent call last): | |
| ... | |
| 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') | |
| >>> C(None) | |
| Traceback (most recent call last): | |
| ... | |
| 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) | |
| .. autofunction:: attrs.validators.in_ | |
| For example: | |
| .. doctest:: | |
| >>> import enum | |
| >>> class State(enum.Enum): | |
| ... ON = "on" | |
| ... OFF = "off" | |
| >>> @define | |
| ... class C: | |
| ... state = field(validator=attrs.validators.in_(State)) | |
| ... val = field(validator=attrs.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'), 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') | |
| >>> C(State.ON, 4) | |
| Traceback (most recent call last): | |
| ... | |
| 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) | |
| .. autofunction:: attrs.validators.and_ | |
| For convenience, it's also possible to pass a list to `attrs.field`'s validator argument. | |
| Thus the following two statements are equivalent:: | |
| x = field(validator=attrs.validators.and_(v1, v2, v3)) | |
| x = field(validator=[v1, v2, v3]) | |
| .. autofunction:: attrs.validators.or_ | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... val: int | list[int] = field( | |
| ... validator=attrs.validators.or_( | |
| ... attrs.validators.instance_of(int), | |
| ... attrs.validators.deep_iterable(attrs.validators.instance_of(int)), | |
| ... ) | |
| ... ) | |
| >>> C(42) | |
| C(val=42) | |
| >>> C([1, 2, 3]) | |
| C(val=[1, 2, 3]) | |
| >>> C(val='42') | |
| Traceback (most recent call last): | |
| ... | |
| ValueError: None of (<instance_of validator for type <class 'int'>>, <deep_iterable validator for iterables of <instance_of validator for type <class 'int'>>>) satisfied for value '42' | |
| .. autofunction:: attrs.validators.not_ | |
| For example: | |
| .. doctest:: | |
| >>> reserved_names = {"id", "time", "source"} | |
| >>> @define | |
| ... class Measurement: | |
| ... tags = field( | |
| ... validator=attrs.validators.deep_mapping( | |
| ... key_validator=attrs.validators.not_( | |
| ... attrs.validators.in_(reserved_names), | |
| ... msg="reserved tag key", | |
| ... ), | |
| ... value_validator=attrs.validators.instance_of((str, int)), | |
| ... ) | |
| ... ) | |
| >>> Measurement(tags={"source": "universe"}) | |
| Traceback (most recent call last): | |
| ... | |
| 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'>)) | |
| >>> Measurement(tags={"source_": "universe"}) | |
| Measurement(tags={'source_': 'universe'}) | |
| .. autofunction:: attrs.validators.optional | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field( | |
| ... validator=attrs.validators.optional( | |
| ... attrs.validators.instance_of(int) | |
| ... )) | |
| >>> C(42) | |
| C(x=42) | |
| >>> C("42") | |
| Traceback (most recent call last): | |
| ... | |
| 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') | |
| >>> C(None) | |
| C(x=None) | |
| .. autofunction:: attrs.validators.is_callable | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field(validator=attrs.validators.is_callable()) | |
| >>> C(isinstance) | |
| C(x=<built-in function isinstance>) | |
| >>> C("not a callable") | |
| Traceback (most recent call last): | |
| ... | |
| attr.exceptions.NotCallableError: 'x' must be callable (got 'not a callable' that is a <class 'str'>). | |
| .. autofunction:: attrs.validators.matches_re | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class User: | |
| ... email = field(validator=attrs.validators.matches_re( | |
| ... r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)")) | |
| >>> User(email="user@example.com") | |
| User(email='user@example.com') | |
| >>> User(email="user@example.com@test.com") | |
| Traceback (most recent call last): | |
| ... | |
| 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') | |
| .. autofunction:: attrs.validators.deep_iterable | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field(validator=attrs.validators.deep_iterable( | |
| ... member_validator=attrs.validators.instance_of(int), | |
| ... iterable_validator=attrs.validators.instance_of(list) | |
| ... )) | |
| >>> C(x=[1, 2, 3]) | |
| C(x=[1, 2, 3]) | |
| >>> C(x=set([1, 2, 3])) | |
| Traceback (most recent call last): | |
| ... | |
| 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}) | |
| >>> C(x=[1, 2, "3"]) | |
| Traceback (most recent call last): | |
| ... | |
| 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') | |
| .. autofunction:: attrs.validators.deep_mapping | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field(validator=attrs.validators.deep_mapping( | |
| ... key_validator=attrs.validators.instance_of(str), | |
| ... value_validator=attrs.validators.instance_of(int), | |
| ... mapping_validator=attrs.validators.instance_of(dict) | |
| ... )) | |
| >>> C(x={"a": 1, "b": 2}) | |
| C(x={'a': 1, 'b': 2}) | |
| >>> C(x=None) | |
| Traceback (most recent call last): | |
| ... | |
| 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) | |
| >>> C(x={"a": 1.0, "b": 2}) | |
| Traceback (most recent call last): | |
| ... | |
| 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) | |
| >>> C(x={"a": 1, 7: 2}) | |
| Traceback (most recent call last): | |
| ... | |
| 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) | |
| Validators can be both globally and locally disabled: | |
| .. autofunction:: attrs.validators.set_disabled | |
| .. autofunction:: attrs.validators.get_disabled | |
| .. autofunction:: attrs.validators.disabled | |
| Converters | |
| ---------- | |
| .. autoclass:: attrs.Converter | |
| For example: | |
| .. doctest:: | |
| >>> def complicated(value, self_, field): | |
| ... return int(value) * self_.factor + field.metadata["offset"] | |
| >>> @define | |
| ... class C: | |
| ... factor = 5 # not an *attrs* field | |
| ... x = field( | |
| ... metadata={"offset": 200}, | |
| ... converter=attrs.Converter( | |
| ... complicated, | |
| ... takes_self=True, takes_field=True | |
| ... )) | |
| >>> C("42") | |
| C(x=410) | |
| .. module:: attrs.converters | |
| All objects from ``attrs.converters`` are also available from ``attr.converters`` (it's the same module in a different namespace). | |
| .. autofunction:: attrs.converters.pipe | |
| For convenience, it's also possible to pass a list to `attrs.field` / `attr.ib`'s converter arguments. | |
| Thus the following two statements are equivalent:: | |
| x = attrs.field(converter=attrs.converter.pipe(c1, c2, c3)) | |
| x = attrs.field(converter=[c1, c2, c3]) | |
| .. autofunction:: attrs.converters.optional | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field(converter=attrs.converters.optional(int)) | |
| >>> C(None) | |
| C(x=None) | |
| >>> C(42) | |
| C(x=42) | |
| .. autofunction:: attrs.converters.default_if_none | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field( | |
| ... converter=attrs.converters.default_if_none("") | |
| ... ) | |
| >>> C(None) | |
| C(x='') | |
| .. autofunction:: attrs.converters.to_bool(val) | |
| For example: | |
| .. doctest:: | |
| >>> @define | |
| ... class C: | |
| ... x = field( | |
| ... converter=attrs.converters.to_bool | |
| ... ) | |
| >>> C("yes") | |
| C(x=True) | |
| >>> C(0) | |
| C(x=False) | |
| >>> C("norway") | |
| Traceback (most recent call last): | |
| File "<stdin>", line 1, in <module> | |
| ValueError: Cannot convert value to bool: norway | |
| .. _api_setters: | |
| Setters | |
| ------- | |
| .. module:: attrs.setters | |
| These are helpers that you can use together with `attrs.define`'s and `attrs.field`'s ``on_setattr`` arguments. | |
| All setters in ``attrs.setters`` are also available from ``attr.setters`` (it's the same module in a different namespace). | |
| .. autofunction:: frozen | |
| .. autofunction:: validate | |
| .. autofunction:: convert | |
| .. autofunction:: pipe | |
| .. data:: NO_OP | |
| Sentinel for disabling class-wide *on_setattr* hooks for certain attributes. | |
| Does not work in `attrs.setters.pipe` or within lists. | |
| .. versionadded:: 20.1.0 | |
| For example, only ``x`` is frozen here: | |
| .. doctest:: | |
| >>> @define(on_setattr=attr.setters.frozen) | |
| ... class C: | |
| ... x = field() | |
| ... y = field(on_setattr=attr.setters.NO_OP) | |
| >>> c = C(1, 2) | |
| >>> c.y = 3 | |
| >>> c.y | |
| 3 | |
| >>> c.x = 4 | |
| Traceback (most recent call last): | |
| ... | |
| attrs.exceptions.FrozenAttributeError: () | |
| .. tip:: | |
| Use `attrs.define`'s *frozen* argument (or `attrs.frozen`) to freeze whole classes; it is more efficient. |