mercurial/thirdparty/attr/_make.py
changeset 49643 e1c586b9a43c
parent 41833 89f01ea906ae
equal deleted inserted replaced
49642:7e6f3c69c0fb 49643:e1c586b9a43c
     1 from __future__ import absolute_import, division, print_function
     1 # SPDX-License-Identifier: MIT
     2 
     2 
     3 import hashlib
     3 import copy
     4 import linecache
     4 import linecache
       
     5 import sys
       
     6 import types
       
     7 import typing
     5 
     8 
     6 from operator import itemgetter
     9 from operator import itemgetter
     7 
    10 
     8 from . import _config
    11 # We need to import _compat itself in addition to the _compat members to avoid
     9 from ._compat import PY2, iteritems, isclass, iterkeys, metadata_proxy
    12 # having the thread-local in the globals here.
       
    13 from . import _compat, _config, setters
       
    14 from ._compat import (
       
    15     HAS_F_STRINGS,
       
    16     PY310,
       
    17     PYPY,
       
    18     _AnnotationExtractor,
       
    19     ordered_dict,
       
    20     set_closure_cell,
       
    21 )
    10 from .exceptions import (
    22 from .exceptions import (
    11     DefaultAlreadySetError,
    23     DefaultAlreadySetError,
    12     FrozenInstanceError,
    24     FrozenInstanceError,
    13     NotAnAttrsClassError,
    25     NotAnAttrsClassError,
       
    26     UnannotatedAttributeError,
    14 )
    27 )
    15 
    28 
    16 
    29 
    17 # This is used at least twice, so cache it here.
    30 # This is used at least twice, so cache it here.
    18 _obj_setattr = object.__setattr__
    31 _obj_setattr = object.__setattr__
    19 _init_convert_pat = "__attr_convert_{}"
    32 _init_converter_pat = "__attr_converter_%s"
    20 _init_factory_pat = "__attr_factory_{}"
    33 _init_factory_pat = "__attr_factory_{}"
    21 _tuple_property_pat = "    {attr_name} = property(itemgetter({index}))"
    34 _tuple_property_pat = (
    22 _empty_metadata_singleton = metadata_proxy({})
    35     "    {attr_name} = _attrs_property(_attrs_itemgetter({index}))"
    23 
    36 )
    24 
    37 _classvar_prefixes = (
    25 class _Nothing(object):
    38     "typing.ClassVar",
       
    39     "t.ClassVar",
       
    40     "ClassVar",
       
    41     "typing_extensions.ClassVar",
       
    42 )
       
    43 # we don't use a double-underscore prefix because that triggers
       
    44 # name mangling when trying to create a slot for the field
       
    45 # (when slots=True)
       
    46 _hash_cache_field = "_attrs_cached_hash"
       
    47 
       
    48 _empty_metadata_singleton = types.MappingProxyType({})
       
    49 
       
    50 # Unique object for unequivocal getattr() defaults.
       
    51 _sentinel = object()
       
    52 
       
    53 _ng_default_on_setattr = setters.pipe(setters.convert, setters.validate)
       
    54 
       
    55 
       
    56 class _Nothing:
    26     """
    57     """
    27     Sentinel class to indicate the lack of a value when ``None`` is ambiguous.
    58     Sentinel class to indicate the lack of a value when ``None`` is ambiguous.
    28 
    59 
    29     All instances of `_Nothing` are equal.
    60     ``_Nothing`` is a singleton. There is only ever one of it.
    30     """
    61 
    31     def __copy__(self):
    62     .. versionchanged:: 21.1.0 ``bool(NOTHING)`` is now False.
    32         return self
    63     """
    33 
    64 
    34     def __deepcopy__(self, _):
    65     _singleton = None
    35         return self
    66 
    36 
    67     def __new__(cls):
    37     def __eq__(self, other):
    68         if _Nothing._singleton is None:
    38         return other.__class__ == _Nothing
    69             _Nothing._singleton = super().__new__(cls)
    39 
    70         return _Nothing._singleton
    40     def __ne__(self, other):
       
    41         return not self == other
       
    42 
    71 
    43     def __repr__(self):
    72     def __repr__(self):
    44         return "NOTHING"
    73         return "NOTHING"
    45 
    74 
    46     def __hash__(self):
    75     def __bool__(self):
    47         return 0xdeadbeef
    76         return False
    48 
    77 
    49 
    78 
    50 NOTHING = _Nothing()
    79 NOTHING = _Nothing()
    51 """
    80 """
    52 Sentinel to indicate the lack of a value when ``None`` is ambiguous.
    81 Sentinel to indicate the lack of a value when ``None`` is ambiguous.
    53 """
    82 """
    54 
    83 
    55 
    84 
    56 def attr(default=NOTHING, validator=None,
    85 class _CacheHashWrapper(int):
    57          repr=True, cmp=True, hash=None, init=True,
    86     """
    58          convert=None, metadata={}):
    87     An integer subclass that pickles / copies as None
    59     r"""
    88 
       
    89     This is used for non-slots classes with ``cache_hash=True``, to avoid
       
    90     serializing a potentially (even likely) invalid hash value. Since ``None``
       
    91     is the default value for uncalculated hashes, whenever this is copied,
       
    92     the copy's value for the hash should automatically reset.
       
    93 
       
    94     See GH #613 for more details.
       
    95     """
       
    96 
       
    97     def __reduce__(self, _none_constructor=type(None), _args=()):
       
    98         return _none_constructor, _args
       
    99 
       
   100 
       
   101 def attrib(
       
   102     default=NOTHING,
       
   103     validator=None,
       
   104     repr=True,
       
   105     cmp=None,
       
   106     hash=None,
       
   107     init=True,
       
   108     metadata=None,
       
   109     type=None,
       
   110     converter=None,
       
   111     factory=None,
       
   112     kw_only=False,
       
   113     eq=None,
       
   114     order=None,
       
   115     on_setattr=None,
       
   116 ):
       
   117     """
    60     Create a new attribute on a class.
   118     Create a new attribute on a class.
    61 
   119 
    62     ..  warning::
   120     ..  warning::
    63 
   121 
    64         Does *not* do anything unless the class is also decorated with
   122         Does *not* do anything unless the class is also decorated with
    65         :func:`attr.s`!
   123         `attr.s`!
    66 
   124 
    67     :param default: A value that is used if an ``attrs``-generated ``__init__``
   125     :param default: A value that is used if an ``attrs``-generated ``__init__``
    68         is used and no value is passed while instantiating or the attribute is
   126         is used and no value is passed while instantiating or the attribute is
    69         excluded using ``init=False``.
   127         excluded using ``init=False``.
    70 
   128 
    71         If the value is an instance of :class:`Factory`, its callable will be
   129         If the value is an instance of `attrs.Factory`, its callable will be
    72         used to construct a new value (useful for mutable datatypes like lists
   130         used to construct a new value (useful for mutable data types like lists
    73         or dicts).
   131         or dicts).
    74 
   132 
    75         If a default is not set (or set manually to ``attr.NOTHING``), a value
   133         If a default is not set (or set manually to `attrs.NOTHING`), a value
    76         *must* be supplied when instantiating; otherwise a :exc:`TypeError`
   134         *must* be supplied when instantiating; otherwise a `TypeError`
    77         will be raised.
   135         will be raised.
    78 
   136 
    79         The default can also be set using decorator notation as shown below.
   137         The default can also be set using decorator notation as shown below.
    80 
   138 
    81     :type default: Any value.
   139     :type default: Any value
    82 
   140 
    83     :param validator: :func:`callable` that is called by ``attrs``-generated
   141     :param callable factory: Syntactic sugar for
       
   142         ``default=attr.Factory(factory)``.
       
   143 
       
   144     :param validator: `callable` that is called by ``attrs``-generated
    84         ``__init__`` methods after the instance has been initialized.  They
   145         ``__init__`` methods after the instance has been initialized.  They
    85         receive the initialized instance, the :class:`Attribute`, and the
   146         receive the initialized instance, the :func:`~attrs.Attribute`, and the
    86         passed value.
   147         passed value.
    87 
   148 
    88         The return value is *not* inspected so the validator has to throw an
   149         The return value is *not* inspected so the validator has to throw an
    89         exception itself.
   150         exception itself.
    90 
   151 
    91         If a ``list`` is passed, its items are treated as validators and must
   152         If a `list` is passed, its items are treated as validators and must
    92         all pass.
   153         all pass.
    93 
   154 
    94         Validators can be globally disabled and re-enabled using
   155         Validators can be globally disabled and re-enabled using
    95         :func:`get_run_validators`.
   156         `get_run_validators`.
    96 
   157 
    97         The validator can also be set using decorator notation as shown below.
   158         The validator can also be set using decorator notation as shown below.
    98 
   159 
    99     :type validator: ``callable`` or a ``list`` of ``callable``\ s.
   160     :type validator: `callable` or a `list` of `callable`\\ s.
   100 
   161 
   101     :param bool repr: Include this attribute in the generated ``__repr__``
   162     :param repr: Include this attribute in the generated ``__repr__``
   102         method.
   163         method. If ``True``, include the attribute; if ``False``, omit it. By
   103     :param bool cmp: Include this attribute in the generated comparison methods
   164         default, the built-in ``repr()`` function is used. To override how the
   104         (``__eq__`` et al).
   165         attribute value is formatted, pass a ``callable`` that takes a single
   105     :param hash: Include this attribute in the generated ``__hash__``
   166         value and returns a string. Note that the resulting string is used
   106         method.  If ``None`` (default), mirror *cmp*'s value.  This is the
   167         as-is, i.e. it will be used directly *instead* of calling ``repr()``
   107         correct behavior according the Python spec.  Setting this value to
   168         (the default).
   108         anything else than ``None`` is *discouraged*.
   169     :type repr: a `bool` or a `callable` to use a custom function.
   109     :type hash: ``bool`` or ``None``
   170 
       
   171     :param eq: If ``True`` (default), include this attribute in the
       
   172         generated ``__eq__`` and ``__ne__`` methods that check two instances
       
   173         for equality. To override how the attribute value is compared,
       
   174         pass a ``callable`` that takes a single value and returns the value
       
   175         to be compared.
       
   176     :type eq: a `bool` or a `callable`.
       
   177 
       
   178     :param order: If ``True`` (default), include this attributes in the
       
   179         generated ``__lt__``, ``__le__``, ``__gt__`` and ``__ge__`` methods.
       
   180         To override how the attribute value is ordered,
       
   181         pass a ``callable`` that takes a single value and returns the value
       
   182         to be ordered.
       
   183     :type order: a `bool` or a `callable`.
       
   184 
       
   185     :param cmp: Setting *cmp* is equivalent to setting *eq* and *order* to the
       
   186         same value. Must not be mixed with *eq* or *order*.
       
   187     :type cmp: a `bool` or a `callable`.
       
   188 
       
   189     :param Optional[bool] hash: Include this attribute in the generated
       
   190         ``__hash__`` method.  If ``None`` (default), mirror *eq*'s value.  This
       
   191         is the correct behavior according the Python spec.  Setting this value
       
   192         to anything else than ``None`` is *discouraged*.
   110     :param bool init: Include this attribute in the generated ``__init__``
   193     :param bool init: Include this attribute in the generated ``__init__``
   111         method.  It is possible to set this to ``False`` and set a default
   194         method.  It is possible to set this to ``False`` and set a default
   112         value.  In that case this attributed is unconditionally initialized
   195         value.  In that case this attributed is unconditionally initialized
   113         with the specified default value or factory.
   196         with the specified default value or factory.
   114     :param callable convert: :func:`callable` that is called by
   197     :param callable converter: `callable` that is called by
   115         ``attrs``-generated ``__init__`` methods to convert attribute's value
   198         ``attrs``-generated ``__init__`` methods to convert attribute's value
   116         to the desired format.  It is given the passed-in value, and the
   199         to the desired format.  It is given the passed-in value, and the
   117         returned value will be used as the new value of the attribute.  The
   200         returned value will be used as the new value of the attribute.  The
   118         value is converted before being passed to the validator, if any.
   201         value is converted before being passed to the validator, if any.
   119     :param metadata: An arbitrary mapping, to be used by third-party
   202     :param metadata: An arbitrary mapping, to be used by third-party
   120         components.  See :ref:`extending_metadata`.
   203         components.  See `extending_metadata`.
   121 
   204     :param type: The type of the attribute.  In Python 3.6 or greater, the
   122     ..  versionchanged:: 17.1.0 *validator* can be a ``list`` now.
   205         preferred method to specify the type is using a variable annotation
   123     ..  versionchanged:: 17.1.0
   206         (see :pep:`526`).
   124         *hash* is ``None`` and therefore mirrors *cmp* by default .
   207         This argument is provided for backward compatibility.
   125     """
   208         Regardless of the approach used, the type will be stored on
       
   209         ``Attribute.type``.
       
   210 
       
   211         Please note that ``attrs`` doesn't do anything with this metadata by
       
   212         itself. You can use it as part of your own code or for
       
   213         `static type checking <types>`.
       
   214     :param kw_only: Make this attribute keyword-only (Python 3+)
       
   215         in the generated ``__init__`` (if ``init`` is ``False``, this
       
   216         parameter is ignored).
       
   217     :param on_setattr: Allows to overwrite the *on_setattr* setting from
       
   218         `attr.s`. If left `None`, the *on_setattr* value from `attr.s` is used.
       
   219         Set to `attrs.setters.NO_OP` to run **no** `setattr` hooks for this
       
   220         attribute -- regardless of the setting in `attr.s`.
       
   221     :type on_setattr: `callable`, or a list of callables, or `None`, or
       
   222         `attrs.setters.NO_OP`
       
   223 
       
   224     .. versionadded:: 15.2.0 *convert*
       
   225     .. versionadded:: 16.3.0 *metadata*
       
   226     .. versionchanged:: 17.1.0 *validator* can be a ``list`` now.
       
   227     .. versionchanged:: 17.1.0
       
   228        *hash* is ``None`` and therefore mirrors *eq* by default.
       
   229     .. versionadded:: 17.3.0 *type*
       
   230     .. deprecated:: 17.4.0 *convert*
       
   231     .. versionadded:: 17.4.0 *converter* as a replacement for the deprecated
       
   232        *convert* to achieve consistency with other noun-based arguments.
       
   233     .. versionadded:: 18.1.0
       
   234        ``factory=f`` is syntactic sugar for ``default=attr.Factory(f)``.
       
   235     .. versionadded:: 18.2.0 *kw_only*
       
   236     .. versionchanged:: 19.2.0 *convert* keyword argument removed.
       
   237     .. versionchanged:: 19.2.0 *repr* also accepts a custom callable.
       
   238     .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01.
       
   239     .. versionadded:: 19.2.0 *eq* and *order*
       
   240     .. versionadded:: 20.1.0 *on_setattr*
       
   241     .. versionchanged:: 20.3.0 *kw_only* backported to Python 2
       
   242     .. versionchanged:: 21.1.0
       
   243        *eq*, *order*, and *cmp* also accept a custom callable
       
   244     .. versionchanged:: 21.1.0 *cmp* undeprecated
       
   245     """
       
   246     eq, eq_key, order, order_key = _determine_attrib_eq_order(
       
   247         cmp, eq, order, True
       
   248     )
       
   249 
   126     if hash is not None and hash is not True and hash is not False:
   250     if hash is not None and hash is not True and hash is not False:
   127         raise TypeError(
   251         raise TypeError(
   128             "Invalid value for hash.  Must be True, False, or None."
   252             "Invalid value for hash.  Must be True, False, or None."
   129         )
   253         )
       
   254 
       
   255     if factory is not None:
       
   256         if default is not NOTHING:
       
   257             raise ValueError(
       
   258                 "The `default` and `factory` arguments are mutually "
       
   259                 "exclusive."
       
   260             )
       
   261         if not callable(factory):
       
   262             raise ValueError("The `factory` argument must be a callable.")
       
   263         default = Factory(factory)
       
   264 
       
   265     if metadata is None:
       
   266         metadata = {}
       
   267 
       
   268     # Apply syntactic sugar by auto-wrapping.
       
   269     if isinstance(on_setattr, (list, tuple)):
       
   270         on_setattr = setters.pipe(*on_setattr)
       
   271 
       
   272     if validator and isinstance(validator, (list, tuple)):
       
   273         validator = and_(*validator)
       
   274 
       
   275     if converter and isinstance(converter, (list, tuple)):
       
   276         converter = pipe(*converter)
       
   277 
   130     return _CountingAttr(
   278     return _CountingAttr(
   131         default=default,
   279         default=default,
   132         validator=validator,
   280         validator=validator,
   133         repr=repr,
   281         repr=repr,
   134         cmp=cmp,
   282         cmp=None,
   135         hash=hash,
   283         hash=hash,
   136         init=init,
   284         init=init,
   137         convert=convert,
   285         converter=converter,
   138         metadata=metadata,
   286         metadata=metadata,
       
   287         type=type,
       
   288         kw_only=kw_only,
       
   289         eq=eq,
       
   290         eq_key=eq_key,
       
   291         order=order,
       
   292         order_key=order_key,
       
   293         on_setattr=on_setattr,
   139     )
   294     )
       
   295 
       
   296 
       
   297 def _compile_and_eval(script, globs, locs=None, filename=""):
       
   298     """
       
   299     "Exec" the script with the given global (globs) and local (locs) variables.
       
   300     """
       
   301     bytecode = compile(script, filename, "exec")
       
   302     eval(bytecode, globs, locs)
       
   303 
       
   304 
       
   305 def _make_method(name, script, filename, globs):
       
   306     """
       
   307     Create the method with the script given and return the method object.
       
   308     """
       
   309     locs = {}
       
   310 
       
   311     # In order of debuggers like PDB being able to step through the code,
       
   312     # we add a fake linecache entry.
       
   313     count = 1
       
   314     base_filename = filename
       
   315     while True:
       
   316         linecache_tuple = (
       
   317             len(script),
       
   318             None,
       
   319             script.splitlines(True),
       
   320             filename,
       
   321         )
       
   322         old_val = linecache.cache.setdefault(filename, linecache_tuple)
       
   323         if old_val == linecache_tuple:
       
   324             break
       
   325         else:
       
   326             filename = "{}-{}>".format(base_filename[:-1], count)
       
   327             count += 1
       
   328 
       
   329     _compile_and_eval(script, globs, locs, filename)
       
   330 
       
   331     return locs[name]
   140 
   332 
   141 
   333 
   142 def _make_attr_tuple_class(cls_name, attr_names):
   334 def _make_attr_tuple_class(cls_name, attr_names):
   143     """
   335     """
   144     Create a tuple subclass to hold `Attribute`s for an `attrs` class.
   336     Create a tuple subclass to hold `Attribute`s for an `attrs` class.
   154         "class {}(tuple):".format(attr_class_name),
   346         "class {}(tuple):".format(attr_class_name),
   155         "    __slots__ = ()",
   347         "    __slots__ = ()",
   156     ]
   348     ]
   157     if attr_names:
   349     if attr_names:
   158         for i, attr_name in enumerate(attr_names):
   350         for i, attr_name in enumerate(attr_names):
   159             attr_class_template.append(_tuple_property_pat.format(
   351             attr_class_template.append(
   160                 index=i,
   352                 _tuple_property_pat.format(index=i, attr_name=attr_name)
   161                 attr_name=attr_name,
   353             )
   162             ))
       
   163     else:
   354     else:
   164         attr_class_template.append("    pass")
   355         attr_class_template.append("    pass")
   165     globs = {"itemgetter": itemgetter}
   356     globs = {"_attrs_itemgetter": itemgetter, "_attrs_property": property}
   166     eval(compile("\n".join(attr_class_template), "", "exec"), globs)
   357     _compile_and_eval("\n".join(attr_class_template), globs)
   167     return globs[attr_class_name]
   358     return globs[attr_class_name]
   168 
   359 
   169 
   360 
   170 def _transform_attrs(cls, these):
   361 # Tuple class for extracted attributes from a class definition.
   171     """
   362 # `base_attrs` is a subset of `attrs`.
   172     Transforms all `_CountingAttr`s on a class into `Attribute`s and saves the
   363 _Attributes = _make_attr_tuple_class(
   173     list in `__attrs_attrs__`.
   364     "_Attributes",
       
   365     [
       
   366         # all attributes to build dunder methods for
       
   367         "attrs",
       
   368         # attributes that have been inherited
       
   369         "base_attrs",
       
   370         # map inherited attributes to their originating classes
       
   371         "base_attrs_map",
       
   372     ],
       
   373 )
       
   374 
       
   375 
       
   376 def _is_class_var(annot):
       
   377     """
       
   378     Check whether *annot* is a typing.ClassVar.
       
   379 
       
   380     The string comparison hack is used to avoid evaluating all string
       
   381     annotations which would put attrs-based classes at a performance
       
   382     disadvantage compared to plain old classes.
       
   383     """
       
   384     annot = str(annot)
       
   385 
       
   386     # Annotation can be quoted.
       
   387     if annot.startswith(("'", '"')) and annot.endswith(("'", '"')):
       
   388         annot = annot[1:-1]
       
   389 
       
   390     return annot.startswith(_classvar_prefixes)
       
   391 
       
   392 
       
   393 def _has_own_attribute(cls, attrib_name):
       
   394     """
       
   395     Check whether *cls* defines *attrib_name* (and doesn't just inherit it).
       
   396 
       
   397     Requires Python 3.
       
   398     """
       
   399     attr = getattr(cls, attrib_name, _sentinel)
       
   400     if attr is _sentinel:
       
   401         return False
       
   402 
       
   403     for base_cls in cls.__mro__[1:]:
       
   404         a = getattr(base_cls, attrib_name, None)
       
   405         if attr is a:
       
   406             return False
       
   407 
       
   408     return True
       
   409 
       
   410 
       
   411 def _get_annotations(cls):
       
   412     """
       
   413     Get annotations for *cls*.
       
   414     """
       
   415     if _has_own_attribute(cls, "__annotations__"):
       
   416         return cls.__annotations__
       
   417 
       
   418     return {}
       
   419 
       
   420 
       
   421 def _counter_getter(e):
       
   422     """
       
   423     Key function for sorting to avoid re-creating a lambda for every class.
       
   424     """
       
   425     return e[1].counter
       
   426 
       
   427 
       
   428 def _collect_base_attrs(cls, taken_attr_names):
       
   429     """
       
   430     Collect attr.ibs from base classes of *cls*, except *taken_attr_names*.
       
   431     """
       
   432     base_attrs = []
       
   433     base_attr_map = {}  # A dictionary of base attrs to their classes.
       
   434 
       
   435     # Traverse the MRO and collect attributes.
       
   436     for base_cls in reversed(cls.__mro__[1:-1]):
       
   437         for a in getattr(base_cls, "__attrs_attrs__", []):
       
   438             if a.inherited or a.name in taken_attr_names:
       
   439                 continue
       
   440 
       
   441             a = a.evolve(inherited=True)
       
   442             base_attrs.append(a)
       
   443             base_attr_map[a.name] = base_cls
       
   444 
       
   445     # For each name, only keep the freshest definition i.e. the furthest at the
       
   446     # back.  base_attr_map is fine because it gets overwritten with every new
       
   447     # instance.
       
   448     filtered = []
       
   449     seen = set()
       
   450     for a in reversed(base_attrs):
       
   451         if a.name in seen:
       
   452             continue
       
   453         filtered.insert(0, a)
       
   454         seen.add(a.name)
       
   455 
       
   456     return filtered, base_attr_map
       
   457 
       
   458 
       
   459 def _collect_base_attrs_broken(cls, taken_attr_names):
       
   460     """
       
   461     Collect attr.ibs from base classes of *cls*, except *taken_attr_names*.
       
   462 
       
   463     N.B. *taken_attr_names* will be mutated.
       
   464 
       
   465     Adhere to the old incorrect behavior.
       
   466 
       
   467     Notably it collects from the front and considers inherited attributes which
       
   468     leads to the buggy behavior reported in #428.
       
   469     """
       
   470     base_attrs = []
       
   471     base_attr_map = {}  # A dictionary of base attrs to their classes.
       
   472 
       
   473     # Traverse the MRO and collect attributes.
       
   474     for base_cls in cls.__mro__[1:-1]:
       
   475         for a in getattr(base_cls, "__attrs_attrs__", []):
       
   476             if a.name in taken_attr_names:
       
   477                 continue
       
   478 
       
   479             a = a.evolve(inherited=True)
       
   480             taken_attr_names.add(a.name)
       
   481             base_attrs.append(a)
       
   482             base_attr_map[a.name] = base_cls
       
   483 
       
   484     return base_attrs, base_attr_map
       
   485 
       
   486 
       
   487 def _transform_attrs(
       
   488     cls, these, auto_attribs, kw_only, collect_by_mro, field_transformer
       
   489 ):
       
   490     """
       
   491     Transform all `_CountingAttr`s on a class into `Attribute`s.
   174 
   492 
   175     If *these* is passed, use that and don't look for them on the class.
   493     If *these* is passed, use that and don't look for them on the class.
   176     """
   494 
   177     super_cls = []
   495     *collect_by_mro* is True, collect them in the correct MRO order, otherwise
   178     for c in reversed(cls.__mro__[1:-1]):
   496     use the old -- incorrect -- order.  See #428.
   179         sub_attrs = getattr(c, "__attrs_attrs__", None)
   497 
   180         if sub_attrs is not None:
   498     Return an `_Attributes`.
   181             super_cls.extend(a for a in sub_attrs if a not in super_cls)
   499     """
   182     if these is None:
   500     cd = cls.__dict__
   183         ca_list = [(name, attr)
   501     anns = _get_annotations(cls)
   184                    for name, attr
   502 
   185                    in cls.__dict__.items()
   503     if these is not None:
   186                    if isinstance(attr, _CountingAttr)]
   504         ca_list = [(name, ca) for name, ca in these.items()]
       
   505 
       
   506         if not isinstance(these, ordered_dict):
       
   507             ca_list.sort(key=_counter_getter)
       
   508     elif auto_attribs is True:
       
   509         ca_names = {
       
   510             name
       
   511             for name, attr in cd.items()
       
   512             if isinstance(attr, _CountingAttr)
       
   513         }
       
   514         ca_list = []
       
   515         annot_names = set()
       
   516         for attr_name, type in anns.items():
       
   517             if _is_class_var(type):
       
   518                 continue
       
   519             annot_names.add(attr_name)
       
   520             a = cd.get(attr_name, NOTHING)
       
   521 
       
   522             if not isinstance(a, _CountingAttr):
       
   523                 if a is NOTHING:
       
   524                     a = attrib()
       
   525                 else:
       
   526                     a = attrib(default=a)
       
   527             ca_list.append((attr_name, a))
       
   528 
       
   529         unannotated = ca_names - annot_names
       
   530         if len(unannotated) > 0:
       
   531             raise UnannotatedAttributeError(
       
   532                 "The following `attr.ib`s lack a type annotation: "
       
   533                 + ", ".join(
       
   534                     sorted(unannotated, key=lambda n: cd.get(n).counter)
       
   535                 )
       
   536                 + "."
       
   537             )
   187     else:
   538     else:
   188         ca_list = [(name, ca)
   539         ca_list = sorted(
   189                    for name, ca
   540             (
   190                    in iteritems(these)]
   541                 (name, attr)
   191 
   542                 for name, attr in cd.items()
   192     non_super_attrs = [
   543                 if isinstance(attr, _CountingAttr)
   193         Attribute.from_counting_attr(name=attr_name, ca=ca)
   544             ),
   194         for attr_name, ca
   545             key=lambda e: e[1].counter,
   195         in sorted(ca_list, key=lambda e: e[1].counter)
   546         )
       
   547 
       
   548     own_attrs = [
       
   549         Attribute.from_counting_attr(
       
   550             name=attr_name, ca=ca, type=anns.get(attr_name)
       
   551         )
       
   552         for attr_name, ca in ca_list
   196     ]
   553     ]
   197     attr_names = [a.name for a in super_cls + non_super_attrs]
   554 
   198 
   555     if collect_by_mro:
   199     AttrsClass = _make_attr_tuple_class(cls.__name__, attr_names)
   556         base_attrs, base_attr_map = _collect_base_attrs(
   200 
   557             cls, {a.name for a in own_attrs}
   201     cls.__attrs_attrs__ = AttrsClass(super_cls + [
   558         )
   202         Attribute.from_counting_attr(name=attr_name, ca=ca)
   559     else:
   203         for attr_name, ca
   560         base_attrs, base_attr_map = _collect_base_attrs_broken(
   204         in sorted(ca_list, key=lambda e: e[1].counter)
   561             cls, {a.name for a in own_attrs}
   205     ])
   562         )
   206 
   563 
       
   564     if kw_only:
       
   565         own_attrs = [a.evolve(kw_only=True) for a in own_attrs]
       
   566         base_attrs = [a.evolve(kw_only=True) for a in base_attrs]
       
   567 
       
   568     attrs = base_attrs + own_attrs
       
   569 
       
   570     # Mandatory vs non-mandatory attr order only matters when they are part of
       
   571     # the __init__ signature and when they aren't kw_only (which are moved to
       
   572     # the end and can be mandatory or non-mandatory in any order, as they will
       
   573     # be specified as keyword args anyway). Check the order of those attrs:
   207     had_default = False
   574     had_default = False
   208     for a in cls.__attrs_attrs__:
   575     for a in (a for a in attrs if a.init is not False and a.kw_only is False):
   209         if these is None and a not in super_cls:
   576         if had_default is True and a.default is NOTHING:
   210             setattr(cls, a.name, a)
       
   211         if had_default is True and a.default is NOTHING and a.init is True:
       
   212             raise ValueError(
   577             raise ValueError(
   213                 "No mandatory attributes allowed after an attribute with a "
   578                 "No mandatory attributes allowed after an attribute with a "
   214                 "default value or factory.  Attribute in question: {a!r}"
   579                 "default value or factory.  Attribute in question: %r" % (a,)
   215                 .format(a=a)
       
   216             )
   580             )
   217         elif had_default is False and \
   581 
   218                 a.default is not NOTHING and \
   582         if had_default is False and a.default is not NOTHING:
   219                 a.init is not False:
       
   220             had_default = True
   583             had_default = True
   221 
   584 
   222 
   585     if field_transformer is not None:
   223 def _frozen_setattrs(self, name, value):
   586         attrs = field_transformer(cls, attrs)
   224     """
   587 
   225     Attached to frozen classes as __setattr__.
   588     # Create AttrsClass *after* applying the field_transformer since it may
       
   589     # add or remove attributes!
       
   590     attr_names = [a.name for a in attrs]
       
   591     AttrsClass = _make_attr_tuple_class(cls.__name__, attr_names)
       
   592 
       
   593     return _Attributes((AttrsClass(attrs), base_attrs, base_attr_map))
       
   594 
       
   595 
       
   596 if PYPY:
       
   597 
       
   598     def _frozen_setattrs(self, name, value):
       
   599         """
       
   600         Attached to frozen classes as __setattr__.
       
   601         """
       
   602         if isinstance(self, BaseException) and name in (
       
   603             "__cause__",
       
   604             "__context__",
       
   605         ):
       
   606             BaseException.__setattr__(self, name, value)
       
   607             return
       
   608 
       
   609         raise FrozenInstanceError()
       
   610 
       
   611 else:
       
   612 
       
   613     def _frozen_setattrs(self, name, value):
       
   614         """
       
   615         Attached to frozen classes as __setattr__.
       
   616         """
       
   617         raise FrozenInstanceError()
       
   618 
       
   619 
       
   620 def _frozen_delattrs(self, name):
       
   621     """
       
   622     Attached to frozen classes as __delattr__.
   226     """
   623     """
   227     raise FrozenInstanceError()
   624     raise FrozenInstanceError()
   228 
   625 
   229 
   626 
   230 def _frozen_delattrs(self, name):
   627 class _ClassBuilder:
   231     """
   628     """
   232     Attached to frozen classes as __delattr__.
   629     Iteratively build *one* class.
   233     """
   630     """
   234     raise FrozenInstanceError()
   631 
   235 
   632     __slots__ = (
   236 
   633         "_attr_names",
   237 def attributes(maybe_cls=None, these=None, repr_ns=None,
   634         "_attrs",
   238                repr=True, cmp=True, hash=None, init=True,
   635         "_base_attr_map",
   239                slots=False, frozen=False, str=False):
   636         "_base_names",
       
   637         "_cache_hash",
       
   638         "_cls",
       
   639         "_cls_dict",
       
   640         "_delete_attribs",
       
   641         "_frozen",
       
   642         "_has_pre_init",
       
   643         "_has_post_init",
       
   644         "_is_exc",
       
   645         "_on_setattr",
       
   646         "_slots",
       
   647         "_weakref_slot",
       
   648         "_wrote_own_setattr",
       
   649         "_has_custom_setattr",
       
   650     )
       
   651 
       
   652     def __init__(
       
   653         self,
       
   654         cls,
       
   655         these,
       
   656         slots,
       
   657         frozen,
       
   658         weakref_slot,
       
   659         getstate_setstate,
       
   660         auto_attribs,
       
   661         kw_only,
       
   662         cache_hash,
       
   663         is_exc,
       
   664         collect_by_mro,
       
   665         on_setattr,
       
   666         has_custom_setattr,
       
   667         field_transformer,
       
   668     ):
       
   669         attrs, base_attrs, base_map = _transform_attrs(
       
   670             cls,
       
   671             these,
       
   672             auto_attribs,
       
   673             kw_only,
       
   674             collect_by_mro,
       
   675             field_transformer,
       
   676         )
       
   677 
       
   678         self._cls = cls
       
   679         self._cls_dict = dict(cls.__dict__) if slots else {}
       
   680         self._attrs = attrs
       
   681         self._base_names = {a.name for a in base_attrs}
       
   682         self._base_attr_map = base_map
       
   683         self._attr_names = tuple(a.name for a in attrs)
       
   684         self._slots = slots
       
   685         self._frozen = frozen
       
   686         self._weakref_slot = weakref_slot
       
   687         self._cache_hash = cache_hash
       
   688         self._has_pre_init = bool(getattr(cls, "__attrs_pre_init__", False))
       
   689         self._has_post_init = bool(getattr(cls, "__attrs_post_init__", False))
       
   690         self._delete_attribs = not bool(these)
       
   691         self._is_exc = is_exc
       
   692         self._on_setattr = on_setattr
       
   693 
       
   694         self._has_custom_setattr = has_custom_setattr
       
   695         self._wrote_own_setattr = False
       
   696 
       
   697         self._cls_dict["__attrs_attrs__"] = self._attrs
       
   698 
       
   699         if frozen:
       
   700             self._cls_dict["__setattr__"] = _frozen_setattrs
       
   701             self._cls_dict["__delattr__"] = _frozen_delattrs
       
   702 
       
   703             self._wrote_own_setattr = True
       
   704         elif on_setattr in (
       
   705             _ng_default_on_setattr,
       
   706             setters.validate,
       
   707             setters.convert,
       
   708         ):
       
   709             has_validator = has_converter = False
       
   710             for a in attrs:
       
   711                 if a.validator is not None:
       
   712                     has_validator = True
       
   713                 if a.converter is not None:
       
   714                     has_converter = True
       
   715 
       
   716                 if has_validator and has_converter:
       
   717                     break
       
   718             if (
       
   719                 (
       
   720                     on_setattr == _ng_default_on_setattr
       
   721                     and not (has_validator or has_converter)
       
   722                 )
       
   723                 or (on_setattr == setters.validate and not has_validator)
       
   724                 or (on_setattr == setters.convert and not has_converter)
       
   725             ):
       
   726                 # If class-level on_setattr is set to convert + validate, but
       
   727                 # there's no field to convert or validate, pretend like there's
       
   728                 # no on_setattr.
       
   729                 self._on_setattr = None
       
   730 
       
   731         if getstate_setstate:
       
   732             (
       
   733                 self._cls_dict["__getstate__"],
       
   734                 self._cls_dict["__setstate__"],
       
   735             ) = self._make_getstate_setstate()
       
   736 
       
   737     def __repr__(self):
       
   738         return "<_ClassBuilder(cls={cls})>".format(cls=self._cls.__name__)
       
   739 
       
   740     def build_class(self):
       
   741         """
       
   742         Finalize class based on the accumulated configuration.
       
   743 
       
   744         Builder cannot be used after calling this method.
       
   745         """
       
   746         if self._slots is True:
       
   747             return self._create_slots_class()
       
   748         else:
       
   749             return self._patch_original_class()
       
   750 
       
   751     def _patch_original_class(self):
       
   752         """
       
   753         Apply accumulated methods and return the class.
       
   754         """
       
   755         cls = self._cls
       
   756         base_names = self._base_names
       
   757 
       
   758         # Clean class of attribute definitions (`attr.ib()`s).
       
   759         if self._delete_attribs:
       
   760             for name in self._attr_names:
       
   761                 if (
       
   762                     name not in base_names
       
   763                     and getattr(cls, name, _sentinel) is not _sentinel
       
   764                 ):
       
   765                     try:
       
   766                         delattr(cls, name)
       
   767                     except AttributeError:
       
   768                         # This can happen if a base class defines a class
       
   769                         # variable and we want to set an attribute with the
       
   770                         # same name by using only a type annotation.
       
   771                         pass
       
   772 
       
   773         # Attach our dunder methods.
       
   774         for name, value in self._cls_dict.items():
       
   775             setattr(cls, name, value)
       
   776 
       
   777         # If we've inherited an attrs __setattr__ and don't write our own,
       
   778         # reset it to object's.
       
   779         if not self._wrote_own_setattr and getattr(
       
   780             cls, "__attrs_own_setattr__", False
       
   781         ):
       
   782             cls.__attrs_own_setattr__ = False
       
   783 
       
   784             if not self._has_custom_setattr:
       
   785                 cls.__setattr__ = _obj_setattr
       
   786 
       
   787         return cls
       
   788 
       
   789     def _create_slots_class(self):
       
   790         """
       
   791         Build and return a new class with a `__slots__` attribute.
       
   792         """
       
   793         cd = {
       
   794             k: v
       
   795             for k, v in self._cls_dict.items()
       
   796             if k not in tuple(self._attr_names) + ("__dict__", "__weakref__")
       
   797         }
       
   798 
       
   799         # If our class doesn't have its own implementation of __setattr__
       
   800         # (either from the user or by us), check the bases, if one of them has
       
   801         # an attrs-made __setattr__, that needs to be reset. We don't walk the
       
   802         # MRO because we only care about our immediate base classes.
       
   803         # XXX: This can be confused by subclassing a slotted attrs class with
       
   804         # XXX: a non-attrs class and subclass the resulting class with an attrs
       
   805         # XXX: class.  See `test_slotted_confused` for details.  For now that's
       
   806         # XXX: OK with us.
       
   807         if not self._wrote_own_setattr:
       
   808             cd["__attrs_own_setattr__"] = False
       
   809 
       
   810             if not self._has_custom_setattr:
       
   811                 for base_cls in self._cls.__bases__:
       
   812                     if base_cls.__dict__.get("__attrs_own_setattr__", False):
       
   813                         cd["__setattr__"] = _obj_setattr
       
   814                         break
       
   815 
       
   816         # Traverse the MRO to collect existing slots
       
   817         # and check for an existing __weakref__.
       
   818         existing_slots = dict()
       
   819         weakref_inherited = False
       
   820         for base_cls in self._cls.__mro__[1:-1]:
       
   821             if base_cls.__dict__.get("__weakref__", None) is not None:
       
   822                 weakref_inherited = True
       
   823             existing_slots.update(
       
   824                 {
       
   825                     name: getattr(base_cls, name)
       
   826                     for name in getattr(base_cls, "__slots__", [])
       
   827                 }
       
   828             )
       
   829 
       
   830         base_names = set(self._base_names)
       
   831 
       
   832         names = self._attr_names
       
   833         if (
       
   834             self._weakref_slot
       
   835             and "__weakref__" not in getattr(self._cls, "__slots__", ())
       
   836             and "__weakref__" not in names
       
   837             and not weakref_inherited
       
   838         ):
       
   839             names += ("__weakref__",)
       
   840 
       
   841         # We only add the names of attributes that aren't inherited.
       
   842         # Setting __slots__ to inherited attributes wastes memory.
       
   843         slot_names = [name for name in names if name not in base_names]
       
   844         # There are slots for attributes from current class
       
   845         # that are defined in parent classes.
       
   846         # As their descriptors may be overridden by a child class,
       
   847         # we collect them here and update the class dict
       
   848         reused_slots = {
       
   849             slot: slot_descriptor
       
   850             for slot, slot_descriptor in existing_slots.items()
       
   851             if slot in slot_names
       
   852         }
       
   853         slot_names = [name for name in slot_names if name not in reused_slots]
       
   854         cd.update(reused_slots)
       
   855         if self._cache_hash:
       
   856             slot_names.append(_hash_cache_field)
       
   857         cd["__slots__"] = tuple(slot_names)
       
   858 
       
   859         cd["__qualname__"] = self._cls.__qualname__
       
   860 
       
   861         # Create new class based on old class and our methods.
       
   862         cls = type(self._cls)(self._cls.__name__, self._cls.__bases__, cd)
       
   863 
       
   864         # The following is a fix for
       
   865         # <https://github.com/python-attrs/attrs/issues/102>.  On Python 3,
       
   866         # if a method mentions `__class__` or uses the no-arg super(), the
       
   867         # compiler will bake a reference to the class in the method itself
       
   868         # as `method.__closure__`.  Since we replace the class with a
       
   869         # clone, we rewrite these references so it keeps working.
       
   870         for item in cls.__dict__.values():
       
   871             if isinstance(item, (classmethod, staticmethod)):
       
   872                 # Class- and staticmethods hide their functions inside.
       
   873                 # These might need to be rewritten as well.
       
   874                 closure_cells = getattr(item.__func__, "__closure__", None)
       
   875             elif isinstance(item, property):
       
   876                 # Workaround for property `super()` shortcut (PY3-only).
       
   877                 # There is no universal way for other descriptors.
       
   878                 closure_cells = getattr(item.fget, "__closure__", None)
       
   879             else:
       
   880                 closure_cells = getattr(item, "__closure__", None)
       
   881 
       
   882             if not closure_cells:  # Catch None or the empty list.
       
   883                 continue
       
   884             for cell in closure_cells:
       
   885                 try:
       
   886                     match = cell.cell_contents is self._cls
       
   887                 except ValueError:  # ValueError: Cell is empty
       
   888                     pass
       
   889                 else:
       
   890                     if match:
       
   891                         set_closure_cell(cell, cls)
       
   892 
       
   893         return cls
       
   894 
       
   895     def add_repr(self, ns):
       
   896         self._cls_dict["__repr__"] = self._add_method_dunders(
       
   897             _make_repr(self._attrs, ns, self._cls)
       
   898         )
       
   899         return self
       
   900 
       
   901     def add_str(self):
       
   902         repr = self._cls_dict.get("__repr__")
       
   903         if repr is None:
       
   904             raise ValueError(
       
   905                 "__str__ can only be generated if a __repr__ exists."
       
   906             )
       
   907 
       
   908         def __str__(self):
       
   909             return self.__repr__()
       
   910 
       
   911         self._cls_dict["__str__"] = self._add_method_dunders(__str__)
       
   912         return self
       
   913 
       
   914     def _make_getstate_setstate(self):
       
   915         """
       
   916         Create custom __setstate__ and __getstate__ methods.
       
   917         """
       
   918         # __weakref__ is not writable.
       
   919         state_attr_names = tuple(
       
   920             an for an in self._attr_names if an != "__weakref__"
       
   921         )
       
   922 
       
   923         def slots_getstate(self):
       
   924             """
       
   925             Automatically created by attrs.
       
   926             """
       
   927             return tuple(getattr(self, name) for name in state_attr_names)
       
   928 
       
   929         hash_caching_enabled = self._cache_hash
       
   930 
       
   931         def slots_setstate(self, state):
       
   932             """
       
   933             Automatically created by attrs.
       
   934             """
       
   935             __bound_setattr = _obj_setattr.__get__(self, Attribute)
       
   936             for name, value in zip(state_attr_names, state):
       
   937                 __bound_setattr(name, value)
       
   938 
       
   939             # The hash code cache is not included when the object is
       
   940             # serialized, but it still needs to be initialized to None to
       
   941             # indicate that the first call to __hash__ should be a cache
       
   942             # miss.
       
   943             if hash_caching_enabled:
       
   944                 __bound_setattr(_hash_cache_field, None)
       
   945 
       
   946         return slots_getstate, slots_setstate
       
   947 
       
   948     def make_unhashable(self):
       
   949         self._cls_dict["__hash__"] = None
       
   950         return self
       
   951 
       
   952     def add_hash(self):
       
   953         self._cls_dict["__hash__"] = self._add_method_dunders(
       
   954             _make_hash(
       
   955                 self._cls,
       
   956                 self._attrs,
       
   957                 frozen=self._frozen,
       
   958                 cache_hash=self._cache_hash,
       
   959             )
       
   960         )
       
   961 
       
   962         return self
       
   963 
       
   964     def add_init(self):
       
   965         self._cls_dict["__init__"] = self._add_method_dunders(
       
   966             _make_init(
       
   967                 self._cls,
       
   968                 self._attrs,
       
   969                 self._has_pre_init,
       
   970                 self._has_post_init,
       
   971                 self._frozen,
       
   972                 self._slots,
       
   973                 self._cache_hash,
       
   974                 self._base_attr_map,
       
   975                 self._is_exc,
       
   976                 self._on_setattr,
       
   977                 attrs_init=False,
       
   978             )
       
   979         )
       
   980 
       
   981         return self
       
   982 
       
   983     def add_match_args(self):
       
   984         self._cls_dict["__match_args__"] = tuple(
       
   985             field.name
       
   986             for field in self._attrs
       
   987             if field.init and not field.kw_only
       
   988         )
       
   989 
       
   990     def add_attrs_init(self):
       
   991         self._cls_dict["__attrs_init__"] = self._add_method_dunders(
       
   992             _make_init(
       
   993                 self._cls,
       
   994                 self._attrs,
       
   995                 self._has_pre_init,
       
   996                 self._has_post_init,
       
   997                 self._frozen,
       
   998                 self._slots,
       
   999                 self._cache_hash,
       
  1000                 self._base_attr_map,
       
  1001                 self._is_exc,
       
  1002                 self._on_setattr,
       
  1003                 attrs_init=True,
       
  1004             )
       
  1005         )
       
  1006 
       
  1007         return self
       
  1008 
       
  1009     def add_eq(self):
       
  1010         cd = self._cls_dict
       
  1011 
       
  1012         cd["__eq__"] = self._add_method_dunders(
       
  1013             _make_eq(self._cls, self._attrs)
       
  1014         )
       
  1015         cd["__ne__"] = self._add_method_dunders(_make_ne())
       
  1016 
       
  1017         return self
       
  1018 
       
  1019     def add_order(self):
       
  1020         cd = self._cls_dict
       
  1021 
       
  1022         cd["__lt__"], cd["__le__"], cd["__gt__"], cd["__ge__"] = (
       
  1023             self._add_method_dunders(meth)
       
  1024             for meth in _make_order(self._cls, self._attrs)
       
  1025         )
       
  1026 
       
  1027         return self
       
  1028 
       
  1029     def add_setattr(self):
       
  1030         if self._frozen:
       
  1031             return self
       
  1032 
       
  1033         sa_attrs = {}
       
  1034         for a in self._attrs:
       
  1035             on_setattr = a.on_setattr or self._on_setattr
       
  1036             if on_setattr and on_setattr is not setters.NO_OP:
       
  1037                 sa_attrs[a.name] = a, on_setattr
       
  1038 
       
  1039         if not sa_attrs:
       
  1040             return self
       
  1041 
       
  1042         if self._has_custom_setattr:
       
  1043             # We need to write a __setattr__ but there already is one!
       
  1044             raise ValueError(
       
  1045                 "Can't combine custom __setattr__ with on_setattr hooks."
       
  1046             )
       
  1047 
       
  1048         # docstring comes from _add_method_dunders
       
  1049         def __setattr__(self, name, val):
       
  1050             try:
       
  1051                 a, hook = sa_attrs[name]
       
  1052             except KeyError:
       
  1053                 nval = val
       
  1054             else:
       
  1055                 nval = hook(self, a, val)
       
  1056 
       
  1057             _obj_setattr(self, name, nval)
       
  1058 
       
  1059         self._cls_dict["__attrs_own_setattr__"] = True
       
  1060         self._cls_dict["__setattr__"] = self._add_method_dunders(__setattr__)
       
  1061         self._wrote_own_setattr = True
       
  1062 
       
  1063         return self
       
  1064 
       
  1065     def _add_method_dunders(self, method):
       
  1066         """
       
  1067         Add __module__ and __qualname__ to a *method* if possible.
       
  1068         """
       
  1069         try:
       
  1070             method.__module__ = self._cls.__module__
       
  1071         except AttributeError:
       
  1072             pass
       
  1073 
       
  1074         try:
       
  1075             method.__qualname__ = ".".join(
       
  1076                 (self._cls.__qualname__, method.__name__)
       
  1077             )
       
  1078         except AttributeError:
       
  1079             pass
       
  1080 
       
  1081         try:
       
  1082             method.__doc__ = "Method generated by attrs for class %s." % (
       
  1083                 self._cls.__qualname__,
       
  1084             )
       
  1085         except AttributeError:
       
  1086             pass
       
  1087 
       
  1088         return method
       
  1089 
       
  1090 
       
  1091 def _determine_attrs_eq_order(cmp, eq, order, default_eq):
       
  1092     """
       
  1093     Validate the combination of *cmp*, *eq*, and *order*. Derive the effective
       
  1094     values of eq and order.  If *eq* is None, set it to *default_eq*.
       
  1095     """
       
  1096     if cmp is not None and any((eq is not None, order is not None)):
       
  1097         raise ValueError("Don't mix `cmp` with `eq' and `order`.")
       
  1098 
       
  1099     # cmp takes precedence due to bw-compatibility.
       
  1100     if cmp is not None:
       
  1101         return cmp, cmp
       
  1102 
       
  1103     # If left None, equality is set to the specified default and ordering
       
  1104     # mirrors equality.
       
  1105     if eq is None:
       
  1106         eq = default_eq
       
  1107 
       
  1108     if order is None:
       
  1109         order = eq
       
  1110 
       
  1111     if eq is False and order is True:
       
  1112         raise ValueError("`order` can only be True if `eq` is True too.")
       
  1113 
       
  1114     return eq, order
       
  1115 
       
  1116 
       
  1117 def _determine_attrib_eq_order(cmp, eq, order, default_eq):
       
  1118     """
       
  1119     Validate the combination of *cmp*, *eq*, and *order*. Derive the effective
       
  1120     values of eq and order.  If *eq* is None, set it to *default_eq*.
       
  1121     """
       
  1122     if cmp is not None and any((eq is not None, order is not None)):
       
  1123         raise ValueError("Don't mix `cmp` with `eq' and `order`.")
       
  1124 
       
  1125     def decide_callable_or_boolean(value):
       
  1126         """
       
  1127         Decide whether a key function is used.
       
  1128         """
       
  1129         if callable(value):
       
  1130             value, key = True, value
       
  1131         else:
       
  1132             key = None
       
  1133         return value, key
       
  1134 
       
  1135     # cmp takes precedence due to bw-compatibility.
       
  1136     if cmp is not None:
       
  1137         cmp, cmp_key = decide_callable_or_boolean(cmp)
       
  1138         return cmp, cmp_key, cmp, cmp_key
       
  1139 
       
  1140     # If left None, equality is set to the specified default and ordering
       
  1141     # mirrors equality.
       
  1142     if eq is None:
       
  1143         eq, eq_key = default_eq, None
       
  1144     else:
       
  1145         eq, eq_key = decide_callable_or_boolean(eq)
       
  1146 
       
  1147     if order is None:
       
  1148         order, order_key = eq, eq_key
       
  1149     else:
       
  1150         order, order_key = decide_callable_or_boolean(order)
       
  1151 
       
  1152     if eq is False and order is True:
       
  1153         raise ValueError("`order` can only be True if `eq` is True too.")
       
  1154 
       
  1155     return eq, eq_key, order, order_key
       
  1156 
       
  1157 
       
  1158 def _determine_whether_to_implement(
       
  1159     cls, flag, auto_detect, dunders, default=True
       
  1160 ):
       
  1161     """
       
  1162     Check whether we should implement a set of methods for *cls*.
       
  1163 
       
  1164     *flag* is the argument passed into @attr.s like 'init', *auto_detect* the
       
  1165     same as passed into @attr.s and *dunders* is a tuple of attribute names
       
  1166     whose presence signal that the user has implemented it themselves.
       
  1167 
       
  1168     Return *default* if no reason for either for or against is found.
       
  1169     """
       
  1170     if flag is True or flag is False:
       
  1171         return flag
       
  1172 
       
  1173     if flag is None and auto_detect is False:
       
  1174         return default
       
  1175 
       
  1176     # Logically, flag is None and auto_detect is True here.
       
  1177     for dunder in dunders:
       
  1178         if _has_own_attribute(cls, dunder):
       
  1179             return False
       
  1180 
       
  1181     return default
       
  1182 
       
  1183 
       
  1184 def attrs(
       
  1185     maybe_cls=None,
       
  1186     these=None,
       
  1187     repr_ns=None,
       
  1188     repr=None,
       
  1189     cmp=None,
       
  1190     hash=None,
       
  1191     init=None,
       
  1192     slots=False,
       
  1193     frozen=False,
       
  1194     weakref_slot=True,
       
  1195     str=False,
       
  1196     auto_attribs=False,
       
  1197     kw_only=False,
       
  1198     cache_hash=False,
       
  1199     auto_exc=False,
       
  1200     eq=None,
       
  1201     order=None,
       
  1202     auto_detect=False,
       
  1203     collect_by_mro=False,
       
  1204     getstate_setstate=None,
       
  1205     on_setattr=None,
       
  1206     field_transformer=None,
       
  1207     match_args=True,
       
  1208 ):
   240     r"""
  1209     r"""
   241     A class decorator that adds `dunder
  1210     A class decorator that adds `dunder
   242     <https://wiki.python.org/moin/DunderAlias>`_\ -methods according to the
  1211     <https://wiki.python.org/moin/DunderAlias>`_\ -methods according to the
   243     specified attributes using :func:`attr.ib` or the *these* argument.
  1212     specified attributes using `attr.ib` or the *these* argument.
   244 
  1213 
   245     :param these: A dictionary of name to :func:`attr.ib` mappings.  This is
  1214     :param these: A dictionary of name to `attr.ib` mappings.  This is
   246         useful to avoid the definition of your attributes within the class body
  1215         useful to avoid the definition of your attributes within the class body
   247         because you can't (e.g. if you want to add ``__repr__`` methods to
  1216         because you can't (e.g. if you want to add ``__repr__`` methods to
   248         Django models) or don't want to.
  1217         Django models) or don't want to.
   249 
  1218 
   250         If *these* is not ``None``, ``attrs`` will *not* search the class body
  1219         If *these* is not ``None``, ``attrs`` will *not* search the class body
   251         for attributes.
  1220         for attributes and will *not* remove any attributes from it.
   252 
  1221 
   253     :type these: :class:`dict` of :class:`str` to :func:`attr.ib`
  1222         If *these* is an ordered dict (`dict` on Python 3.6+,
       
  1223         `collections.OrderedDict` otherwise), the order is deduced from
       
  1224         the order of the attributes inside *these*.  Otherwise the order
       
  1225         of the definition of the attributes is used.
       
  1226 
       
  1227     :type these: `dict` of `str` to `attr.ib`
   254 
  1228 
   255     :param str repr_ns: When using nested classes, there's no way in Python 2
  1229     :param str repr_ns: When using nested classes, there's no way in Python 2
   256         to automatically detect that.  Therefore it's possible to set the
  1230         to automatically detect that.  Therefore it's possible to set the
   257         namespace explicitly for a more meaningful ``repr`` output.
  1231         namespace explicitly for a more meaningful ``repr`` output.
       
  1232     :param bool auto_detect: Instead of setting the *init*, *repr*, *eq*,
       
  1233         *order*, and *hash* arguments explicitly, assume they are set to
       
  1234         ``True`` **unless any** of the involved methods for one of the
       
  1235         arguments is implemented in the *current* class (i.e. it is *not*
       
  1236         inherited from some base class).
       
  1237 
       
  1238         So for example by implementing ``__eq__`` on a class yourself,
       
  1239         ``attrs`` will deduce ``eq=False`` and will create *neither*
       
  1240         ``__eq__`` *nor* ``__ne__`` (but Python classes come with a sensible
       
  1241         ``__ne__`` by default, so it *should* be enough to only implement
       
  1242         ``__eq__`` in most cases).
       
  1243 
       
  1244         .. warning::
       
  1245 
       
  1246            If you prevent ``attrs`` from creating the ordering methods for you
       
  1247            (``order=False``, e.g. by implementing ``__le__``), it becomes
       
  1248            *your* responsibility to make sure its ordering is sound. The best
       
  1249            way is to use the `functools.total_ordering` decorator.
       
  1250 
       
  1251 
       
  1252         Passing ``True`` or ``False`` to *init*, *repr*, *eq*, *order*,
       
  1253         *cmp*, or *hash* overrides whatever *auto_detect* would determine.
       
  1254 
       
  1255         *auto_detect* requires Python 3. Setting it ``True`` on Python 2 raises
       
  1256         an `attrs.exceptions.PythonTooOldError`.
       
  1257 
   258     :param bool repr: Create a ``__repr__`` method with a human readable
  1258     :param bool repr: Create a ``__repr__`` method with a human readable
   259         represantation of ``attrs`` attributes..
  1259         representation of ``attrs`` attributes..
   260     :param bool str: Create a ``__str__`` method that is identical to
  1260     :param bool str: Create a ``__str__`` method that is identical to
   261         ``__repr__``.  This is usually not necessary except for
  1261         ``__repr__``.  This is usually not necessary except for
   262         :class:`Exception`\ s.
  1262         `Exception`\ s.
   263     :param bool cmp: Create ``__eq__``, ``__ne__``, ``__lt__``, ``__le__``,
  1263     :param Optional[bool] eq: If ``True`` or ``None`` (default), add ``__eq__``
   264         ``__gt__``, and ``__ge__`` methods that compare the class as if it were
  1264         and ``__ne__`` methods that check two instances for equality.
   265         a tuple of its ``attrs`` attributes.  But the attributes are *only*
  1265 
   266         compared, if the type of both classes is *identical*!
  1266         They compare the instances as if they were tuples of their ``attrs``
   267     :param hash: If ``None`` (default), the ``__hash__`` method is generated
  1267         attributes if and only if the types of both classes are *identical*!
   268         according how *cmp* and *frozen* are set.
  1268     :param Optional[bool] order: If ``True``, add ``__lt__``, ``__le__``,
       
  1269         ``__gt__``, and ``__ge__`` methods that behave like *eq* above and
       
  1270         allow instances to be ordered. If ``None`` (default) mirror value of
       
  1271         *eq*.
       
  1272     :param Optional[bool] cmp: Setting *cmp* is equivalent to setting *eq*
       
  1273         and *order* to the same value. Must not be mixed with *eq* or *order*.
       
  1274     :param Optional[bool] hash: If ``None`` (default), the ``__hash__`` method
       
  1275         is generated according how *eq* and *frozen* are set.
   269 
  1276 
   270         1. If *both* are True, ``attrs`` will generate a ``__hash__`` for you.
  1277         1. If *both* are True, ``attrs`` will generate a ``__hash__`` for you.
   271         2. If *cmp* is True and *frozen* is False, ``__hash__`` will be set to
  1278         2. If *eq* is True and *frozen* is False, ``__hash__`` will be set to
   272            None, marking it unhashable (which it is).
  1279            None, marking it unhashable (which it is).
   273         3. If *cmp* is False, ``__hash__`` will be left untouched meaning the
  1280         3. If *eq* is False, ``__hash__`` will be left untouched meaning the
   274            ``__hash__`` method of the superclass will be used (if superclass is
  1281            ``__hash__`` method of the base class will be used (if base class is
   275            ``object``, this means it will fall back to id-based hashing.).
  1282            ``object``, this means it will fall back to id-based hashing.).
   276 
  1283 
   277         Although not recommended, you can decide for yourself and force
  1284         Although not recommended, you can decide for yourself and force
   278         ``attrs`` to create one (e.g. if the class is immutable even though you
  1285         ``attrs`` to create one (e.g. if the class is immutable even though you
   279         didn't freeze it programmatically) by passing ``True`` or not.  Both of
  1286         didn't freeze it programmatically) by passing ``True`` or not.  Both of
   280         these cases are rather special and should be used carefully.
  1287         these cases are rather special and should be used carefully.
   281 
  1288 
   282         See the `Python documentation \
  1289         See our documentation on `hashing`, Python's documentation on
   283         <https://docs.python.org/3/reference/datamodel.html#object.__hash__>`_
  1290         `object.__hash__`, and the `GitHub issue that led to the default \
   284         and the `GitHub issue that led to the default behavior \
  1291         behavior <https://github.com/python-attrs/attrs/issues/136>`_ for more
   285         <https://github.com/python-attrs/attrs/issues/136>`_ for more details.
  1292         details.
   286     :type hash: ``bool`` or ``None``
  1293     :param bool init: Create a ``__init__`` method that initializes the
   287     :param bool init: Create a ``__init__`` method that initialiazes the
  1294         ``attrs`` attributes. Leading underscores are stripped for the argument
   288         ``attrs`` attributes.  Leading underscores are stripped for the
  1295         name. If a ``__attrs_pre_init__`` method exists on the class, it will
   289         argument name.  If a ``__attrs_post_init__`` method exists on the
  1296         be called before the class is initialized. If a ``__attrs_post_init__``
   290         class, it will be called after the class is fully initialized.
  1297         method exists on the class, it will be called after the class is fully
   291     :param bool slots: Create a slots_-style class that's more
  1298         initialized.
   292         memory-efficient.  See :ref:`slots` for further ramifications.
  1299 
       
  1300         If ``init`` is ``False``, an ``__attrs_init__`` method will be
       
  1301         injected instead. This allows you to define a custom ``__init__``
       
  1302         method that can do pre-init work such as ``super().__init__()``,
       
  1303         and then call ``__attrs_init__()`` and ``__attrs_post_init__()``.
       
  1304     :param bool slots: Create a `slotted class <slotted classes>` that's more
       
  1305         memory-efficient. Slotted classes are generally superior to the default
       
  1306         dict classes, but have some gotchas you should know about, so we
       
  1307         encourage you to read the `glossary entry <slotted classes>`.
   293     :param bool frozen: Make instances immutable after initialization.  If
  1308     :param bool frozen: Make instances immutable after initialization.  If
   294         someone attempts to modify a frozen instance,
  1309         someone attempts to modify a frozen instance,
   295         :exc:`attr.exceptions.FrozenInstanceError` is raised.
  1310         `attr.exceptions.FrozenInstanceError` is raised.
   296 
  1311 
   297         Please note:
  1312         .. note::
   298 
  1313 
   299             1. This is achieved by installing a custom ``__setattr__`` method
  1314             1. This is achieved by installing a custom ``__setattr__`` method
   300                on your class so you can't implement an own one.
  1315                on your class, so you can't implement your own.
   301 
  1316 
   302             2. True immutability is impossible in Python.
  1317             2. True immutability is impossible in Python.
   303 
  1318 
   304             3. This *does* have a minor a runtime performance :ref:`impact
  1319             3. This *does* have a minor a runtime performance `impact
   305                <how-frozen>` when initializing new instances.  In other words:
  1320                <how-frozen>` when initializing new instances.  In other words:
   306                ``__init__`` is slightly slower with ``frozen=True``.
  1321                ``__init__`` is slightly slower with ``frozen=True``.
   307 
  1322 
   308             4. If a class is frozen, you cannot modify ``self`` in
  1323             4. If a class is frozen, you cannot modify ``self`` in
   309                ``__attrs_post_init__`` or a self-written ``__init__``. You can
  1324                ``__attrs_post_init__`` or a self-written ``__init__``. You can
   310                circumvent that limitation by using
  1325                circumvent that limitation by using
   311                ``object.__setattr__(self, "attribute_name", value)``.
  1326                ``object.__setattr__(self, "attribute_name", value)``.
   312 
  1327 
   313         ..  _slots: https://docs.python.org/3.5/reference/datamodel.html#slots
  1328             5. Subclasses of a frozen class are frozen too.
   314 
  1329 
   315     ..  versionadded:: 16.0.0 *slots*
  1330     :param bool weakref_slot: Make instances weak-referenceable.  This has no
   316     ..  versionadded:: 16.1.0 *frozen*
  1331         effect unless ``slots`` is also enabled.
   317     ..  versionadded:: 16.3.0 *str*, and support for ``__attrs_post_init__``.
  1332     :param bool auto_attribs: If ``True``, collect :pep:`526`-annotated
   318     ..  versionchanged::
  1333         attributes (Python 3.6 and later only) from the class body.
   319             17.1.0 *hash* supports ``None`` as value which is also the default
  1334 
   320             now.
  1335         In this case, you **must** annotate every field.  If ``attrs``
   321     """
  1336         encounters a field that is set to an `attr.ib` but lacks a type
       
  1337         annotation, an `attr.exceptions.UnannotatedAttributeError` is
       
  1338         raised.  Use ``field_name: typing.Any = attr.ib(...)`` if you don't
       
  1339         want to set a type.
       
  1340 
       
  1341         If you assign a value to those attributes (e.g. ``x: int = 42``), that
       
  1342         value becomes the default value like if it were passed using
       
  1343         ``attr.ib(default=42)``.  Passing an instance of `attrs.Factory` also
       
  1344         works as expected in most cases (see warning below).
       
  1345 
       
  1346         Attributes annotated as `typing.ClassVar`, and attributes that are
       
  1347         neither annotated nor set to an `attr.ib` are **ignored**.
       
  1348 
       
  1349         .. warning::
       
  1350            For features that use the attribute name to create decorators (e.g.
       
  1351            `validators <validators>`), you still *must* assign `attr.ib` to
       
  1352            them. Otherwise Python will either not find the name or try to use
       
  1353            the default value to call e.g. ``validator`` on it.
       
  1354 
       
  1355            These errors can be quite confusing and probably the most common bug
       
  1356            report on our bug tracker.
       
  1357 
       
  1358     :param bool kw_only: Make all attributes keyword-only (Python 3+)
       
  1359         in the generated ``__init__`` (if ``init`` is ``False``, this
       
  1360         parameter is ignored).
       
  1361     :param bool cache_hash: Ensure that the object's hash code is computed
       
  1362         only once and stored on the object.  If this is set to ``True``,
       
  1363         hashing must be either explicitly or implicitly enabled for this
       
  1364         class.  If the hash code is cached, avoid any reassignments of
       
  1365         fields involved in hash code computation or mutations of the objects
       
  1366         those fields point to after object creation.  If such changes occur,
       
  1367         the behavior of the object's hash code is undefined.
       
  1368     :param bool auto_exc: If the class subclasses `BaseException`
       
  1369         (which implicitly includes any subclass of any exception), the
       
  1370         following happens to behave like a well-behaved Python exceptions
       
  1371         class:
       
  1372 
       
  1373         - the values for *eq*, *order*, and *hash* are ignored and the
       
  1374           instances compare and hash by the instance's ids (N.B. ``attrs`` will
       
  1375           *not* remove existing implementations of ``__hash__`` or the equality
       
  1376           methods. It just won't add own ones.),
       
  1377         - all attributes that are either passed into ``__init__`` or have a
       
  1378           default value are additionally available as a tuple in the ``args``
       
  1379           attribute,
       
  1380         - the value of *str* is ignored leaving ``__str__`` to base classes.
       
  1381     :param bool collect_by_mro: Setting this to `True` fixes the way ``attrs``
       
  1382        collects attributes from base classes.  The default behavior is
       
  1383        incorrect in certain cases of multiple inheritance.  It should be on by
       
  1384        default but is kept off for backward-compatibility.
       
  1385 
       
  1386        See issue `#428 <https://github.com/python-attrs/attrs/issues/428>`_ for
       
  1387        more details.
       
  1388 
       
  1389     :param Optional[bool] getstate_setstate:
       
  1390        .. note::
       
  1391           This is usually only interesting for slotted classes and you should
       
  1392           probably just set *auto_detect* to `True`.
       
  1393 
       
  1394        If `True`, ``__getstate__`` and
       
  1395        ``__setstate__`` are generated and attached to the class. This is
       
  1396        necessary for slotted classes to be pickleable. If left `None`, it's
       
  1397        `True` by default for slotted classes and ``False`` for dict classes.
       
  1398 
       
  1399        If *auto_detect* is `True`, and *getstate_setstate* is left `None`,
       
  1400        and **either** ``__getstate__`` or ``__setstate__`` is detected directly
       
  1401        on the class (i.e. not inherited), it is set to `False` (this is usually
       
  1402        what you want).
       
  1403 
       
  1404     :param on_setattr: A callable that is run whenever the user attempts to set
       
  1405         an attribute (either by assignment like ``i.x = 42`` or by using
       
  1406         `setattr` like ``setattr(i, "x", 42)``). It receives the same arguments
       
  1407         as validators: the instance, the attribute that is being modified, and
       
  1408         the new value.
       
  1409 
       
  1410         If no exception is raised, the attribute is set to the return value of
       
  1411         the callable.
       
  1412 
       
  1413         If a list of callables is passed, they're automatically wrapped in an
       
  1414         `attrs.setters.pipe`.
       
  1415     :type on_setattr: `callable`, or a list of callables, or `None`, or
       
  1416         `attrs.setters.NO_OP`
       
  1417 
       
  1418     :param Optional[callable] field_transformer:
       
  1419         A function that is called with the original class object and all
       
  1420         fields right before ``attrs`` finalizes the class.  You can use
       
  1421         this, e.g., to automatically add converters or validators to
       
  1422         fields based on their types.  See `transform-fields` for more details.
       
  1423 
       
  1424     :param bool match_args:
       
  1425         If `True` (default), set ``__match_args__`` on the class to support
       
  1426         :pep:`634` (Structural Pattern Matching). It is a tuple of all
       
  1427         non-keyword-only ``__init__`` parameter names on Python 3.10 and later.
       
  1428         Ignored on older Python versions.
       
  1429 
       
  1430     .. versionadded:: 16.0.0 *slots*
       
  1431     .. versionadded:: 16.1.0 *frozen*
       
  1432     .. versionadded:: 16.3.0 *str*
       
  1433     .. versionadded:: 16.3.0 Support for ``__attrs_post_init__``.
       
  1434     .. versionchanged:: 17.1.0
       
  1435        *hash* supports ``None`` as value which is also the default now.
       
  1436     .. versionadded:: 17.3.0 *auto_attribs*
       
  1437     .. versionchanged:: 18.1.0
       
  1438        If *these* is passed, no attributes are deleted from the class body.
       
  1439     .. versionchanged:: 18.1.0 If *these* is ordered, the order is retained.
       
  1440     .. versionadded:: 18.2.0 *weakref_slot*
       
  1441     .. deprecated:: 18.2.0
       
  1442        ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` now raise a
       
  1443        `DeprecationWarning` if the classes compared are subclasses of
       
  1444        each other. ``__eq`` and ``__ne__`` never tried to compared subclasses
       
  1445        to each other.
       
  1446     .. versionchanged:: 19.2.0
       
  1447        ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` now do not consider
       
  1448        subclasses comparable anymore.
       
  1449     .. versionadded:: 18.2.0 *kw_only*
       
  1450     .. versionadded:: 18.2.0 *cache_hash*
       
  1451     .. versionadded:: 19.1.0 *auto_exc*
       
  1452     .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01.
       
  1453     .. versionadded:: 19.2.0 *eq* and *order*
       
  1454     .. versionadded:: 20.1.0 *auto_detect*
       
  1455     .. versionadded:: 20.1.0 *collect_by_mro*
       
  1456     .. versionadded:: 20.1.0 *getstate_setstate*
       
  1457     .. versionadded:: 20.1.0 *on_setattr*
       
  1458     .. versionadded:: 20.3.0 *field_transformer*
       
  1459     .. versionchanged:: 21.1.0
       
  1460        ``init=False`` injects ``__attrs_init__``
       
  1461     .. versionchanged:: 21.1.0 Support for ``__attrs_pre_init__``
       
  1462     .. versionchanged:: 21.1.0 *cmp* undeprecated
       
  1463     .. versionadded:: 21.3.0 *match_args*
       
  1464     """
       
  1465     eq_, order_ = _determine_attrs_eq_order(cmp, eq, order, None)
       
  1466     hash_ = hash  # work around the lack of nonlocal
       
  1467 
       
  1468     if isinstance(on_setattr, (list, tuple)):
       
  1469         on_setattr = setters.pipe(*on_setattr)
       
  1470 
   322     def wrap(cls):
  1471     def wrap(cls):
   323         if getattr(cls, "__class__", None) is None:
  1472         is_frozen = frozen or _has_frozen_base_class(cls)
   324             raise TypeError("attrs only works with new-style classes.")
  1473         is_exc = auto_exc is True and issubclass(cls, BaseException)
   325 
  1474         has_own_setattr = auto_detect and _has_own_attribute(
   326         if repr is False and str is True:
  1475             cls, "__setattr__"
   327             raise ValueError(
  1476         )
   328                 "__str__ can only be generated if a __repr__ exists."
  1477 
   329             )
  1478         if has_own_setattr and is_frozen:
   330 
  1479             raise ValueError("Can't freeze a class with a custom __setattr__.")
   331         if slots:
  1480 
   332             # Only need this later if we're using slots.
  1481         builder = _ClassBuilder(
   333             if these is None:
  1482             cls,
   334                 ca_list = [name
  1483             these,
   335                            for name, attr
  1484             slots,
   336                            in cls.__dict__.items()
  1485             is_frozen,
   337                            if isinstance(attr, _CountingAttr)]
  1486             weakref_slot,
   338             else:
  1487             _determine_whether_to_implement(
   339                 ca_list = list(iterkeys(these))
  1488                 cls,
   340         _transform_attrs(cls, these)
  1489                 getstate_setstate,
   341 
  1490                 auto_detect,
   342         # Can't just re-use frozen name because Python's scoping. :(
  1491                 ("__getstate__", "__setstate__"),
   343         # Can't compare function objects because Python 2 is terrible. :(
  1492                 default=slots,
   344         effectively_frozen = _has_frozen_superclass(cls) or frozen
  1493             ),
   345         if repr is True:
  1494             auto_attribs,
   346             cls = _add_repr(cls, ns=repr_ns)
  1495             kw_only,
       
  1496             cache_hash,
       
  1497             is_exc,
       
  1498             collect_by_mro,
       
  1499             on_setattr,
       
  1500             has_own_setattr,
       
  1501             field_transformer,
       
  1502         )
       
  1503         if _determine_whether_to_implement(
       
  1504             cls, repr, auto_detect, ("__repr__",)
       
  1505         ):
       
  1506             builder.add_repr(repr_ns)
   347         if str is True:
  1507         if str is True:
   348             cls.__str__ = cls.__repr__
  1508             builder.add_str()
   349         if cmp is True:
  1509 
   350             cls = _add_cmp(cls)
  1510         eq = _determine_whether_to_implement(
   351 
  1511             cls, eq_, auto_detect, ("__eq__", "__ne__")
       
  1512         )
       
  1513         if not is_exc and eq is True:
       
  1514             builder.add_eq()
       
  1515         if not is_exc and _determine_whether_to_implement(
       
  1516             cls, order_, auto_detect, ("__lt__", "__le__", "__gt__", "__ge__")
       
  1517         ):
       
  1518             builder.add_order()
       
  1519 
       
  1520         builder.add_setattr()
       
  1521 
       
  1522         if (
       
  1523             hash_ is None
       
  1524             and auto_detect is True
       
  1525             and _has_own_attribute(cls, "__hash__")
       
  1526         ):
       
  1527             hash = False
       
  1528         else:
       
  1529             hash = hash_
   352         if hash is not True and hash is not False and hash is not None:
  1530         if hash is not True and hash is not False and hash is not None:
       
  1531             # Can't use `hash in` because 1 == True for example.
   353             raise TypeError(
  1532             raise TypeError(
   354                 "Invalid value for hash.  Must be True, False, or None."
  1533                 "Invalid value for hash.  Must be True, False, or None."
   355             )
  1534             )
   356         elif hash is False or (hash is None and cmp is False):
  1535         elif hash is False or (hash is None and eq is False) or is_exc:
   357             pass
  1536             # Don't do anything. Should fall back to __object__'s __hash__
   358         elif hash is True or (hash is None and cmp is True and frozen is True):
  1537             # which is by id.
   359             cls = _add_hash(cls)
  1538             if cache_hash:
       
  1539                 raise TypeError(
       
  1540                     "Invalid value for cache_hash.  To use hash caching,"
       
  1541                     " hashing must be either explicitly or implicitly "
       
  1542                     "enabled."
       
  1543                 )
       
  1544         elif hash is True or (
       
  1545             hash is None and eq is True and is_frozen is True
       
  1546         ):
       
  1547             # Build a __hash__ if told so, or if it's safe.
       
  1548             builder.add_hash()
   360         else:
  1549         else:
   361             cls.__hash__ = None
  1550             # Raise TypeError on attempts to hash.
   362 
  1551             if cache_hash:
   363         if init is True:
  1552                 raise TypeError(
   364             cls = _add_init(cls, effectively_frozen)
  1553                     "Invalid value for cache_hash.  To use hash caching,"
   365         if effectively_frozen is True:
  1554                     " hashing must be either explicitly or implicitly "
   366             cls.__setattr__ = _frozen_setattrs
  1555                     "enabled."
   367             cls.__delattr__ = _frozen_delattrs
  1556                 )
   368             if slots is True:
  1557             builder.make_unhashable()
   369                 # slots and frozen require __getstate__/__setstate__ to work
  1558 
   370                 cls = _add_pickle(cls)
  1559         if _determine_whether_to_implement(
   371         if slots is True:
  1560             cls, init, auto_detect, ("__init__",)
   372             cls_dict = dict(cls.__dict__)
  1561         ):
   373             cls_dict["__slots__"] = tuple(ca_list)
  1562             builder.add_init()
   374             for ca_name in ca_list:
  1563         else:
   375                 # It might not actually be in there, e.g. if using 'these'.
  1564             builder.add_attrs_init()
   376                 cls_dict.pop(ca_name, None)
  1565             if cache_hash:
   377             cls_dict.pop("__dict__", None)
  1566                 raise TypeError(
   378 
  1567                     "Invalid value for cache_hash.  To use hash caching,"
   379             qualname = getattr(cls, "__qualname__", None)
  1568                     " init must be True."
   380             cls = type(cls)(cls.__name__, cls.__bases__, cls_dict)
  1569                 )
   381             if qualname is not None:
  1570 
   382                 cls.__qualname__ = qualname
  1571         if (
   383 
  1572             PY310
   384         return cls
  1573             and match_args
   385 
  1574             and not _has_own_attribute(cls, "__match_args__")
   386     # attrs_or class type depends on the usage of the decorator.  It's a class
  1575         ):
   387     # if it's used as `@attributes` but ``None`` if used # as `@attributes()`.
  1576             builder.add_match_args()
       
  1577 
       
  1578         return builder.build_class()
       
  1579 
       
  1580     # maybe_cls's type depends on the usage of the decorator.  It's a class
       
  1581     # if it's used as `@attrs` but ``None`` if used as `@attrs()`.
   388     if maybe_cls is None:
  1582     if maybe_cls is None:
   389         return wrap
  1583         return wrap
   390     else:
  1584     else:
   391         return wrap(maybe_cls)
  1585         return wrap(maybe_cls)
   392 
  1586 
   393 
  1587 
   394 if PY2:
  1588 _attrs = attrs
   395     def _has_frozen_superclass(cls):
  1589 """
   396         """
  1590 Internal alias so we can use it in functions that take an argument called
   397         Check whether *cls* has a frozen ancestor by looking at its
  1591 *attrs*.
   398         __setattr__.
  1592 """
   399         """
  1593 
   400         return (
  1594 
   401             getattr(
  1595 def _has_frozen_base_class(cls):
   402                 cls.__setattr__, "__module__", None
  1596     """
   403             ) == _frozen_setattrs.__module__ and
  1597     Check whether *cls* has a frozen ancestor by looking at its
   404             cls.__setattr__.__name__ == _frozen_setattrs.__name__
  1598     __setattr__.
   405         )
  1599     """
   406 else:
  1600     return cls.__setattr__ is _frozen_setattrs
   407     def _has_frozen_superclass(cls):
  1601 
   408         """
  1602 
   409         Check whether *cls* has a frozen ancestor by looking at its
  1603 def _generate_unique_filename(cls, func_name):
   410         __setattr__.
  1604     """
   411         """
  1605     Create a "filename" suitable for a function being generated.
   412         return cls.__setattr__ == _frozen_setattrs
  1606     """
   413 
  1607     unique_filename = "<attrs generated {} {}.{}>".format(
   414 
  1608         func_name,
   415 def _attrs_to_tuple(obj, attrs):
  1609         cls.__module__,
   416     """
  1610         getattr(cls, "__qualname__", cls.__name__),
   417     Create a tuple of all values of *obj*'s *attrs*.
  1611     )
   418     """
  1612     return unique_filename
   419     return tuple(getattr(obj, a.name) for a in attrs)
  1613 
   420 
  1614 
   421 
  1615 def _make_hash(cls, attrs, frozen, cache_hash):
   422 def _add_hash(cls, attrs=None):
  1616     attrs = tuple(
       
  1617         a for a in attrs if a.hash is True or (a.hash is None and a.eq is True)
       
  1618     )
       
  1619 
       
  1620     tab = "        "
       
  1621 
       
  1622     unique_filename = _generate_unique_filename(cls, "hash")
       
  1623     type_hash = hash(unique_filename)
       
  1624     # If eq is custom generated, we need to include the functions in globs
       
  1625     globs = {}
       
  1626 
       
  1627     hash_def = "def __hash__(self"
       
  1628     hash_func = "hash(("
       
  1629     closing_braces = "))"
       
  1630     if not cache_hash:
       
  1631         hash_def += "):"
       
  1632     else:
       
  1633         hash_def += ", *"
       
  1634 
       
  1635         hash_def += (
       
  1636             ", _cache_wrapper="
       
  1637             + "__import__('attr._make')._make._CacheHashWrapper):"
       
  1638         )
       
  1639         hash_func = "_cache_wrapper(" + hash_func
       
  1640         closing_braces += ")"
       
  1641 
       
  1642     method_lines = [hash_def]
       
  1643 
       
  1644     def append_hash_computation_lines(prefix, indent):
       
  1645         """
       
  1646         Generate the code for actually computing the hash code.
       
  1647         Below this will either be returned directly or used to compute
       
  1648         a value which is then cached, depending on the value of cache_hash
       
  1649         """
       
  1650 
       
  1651         method_lines.extend(
       
  1652             [
       
  1653                 indent + prefix + hash_func,
       
  1654                 indent + "        %d," % (type_hash,),
       
  1655             ]
       
  1656         )
       
  1657 
       
  1658         for a in attrs:
       
  1659             if a.eq_key:
       
  1660                 cmp_name = "_%s_key" % (a.name,)
       
  1661                 globs[cmp_name] = a.eq_key
       
  1662                 method_lines.append(
       
  1663                     indent + "        %s(self.%s)," % (cmp_name, a.name)
       
  1664                 )
       
  1665             else:
       
  1666                 method_lines.append(indent + "        self.%s," % a.name)
       
  1667 
       
  1668         method_lines.append(indent + "    " + closing_braces)
       
  1669 
       
  1670     if cache_hash:
       
  1671         method_lines.append(tab + "if self.%s is None:" % _hash_cache_field)
       
  1672         if frozen:
       
  1673             append_hash_computation_lines(
       
  1674                 "object.__setattr__(self, '%s', " % _hash_cache_field, tab * 2
       
  1675             )
       
  1676             method_lines.append(tab * 2 + ")")  # close __setattr__
       
  1677         else:
       
  1678             append_hash_computation_lines(
       
  1679                 "self.%s = " % _hash_cache_field, tab * 2
       
  1680             )
       
  1681         method_lines.append(tab + "return self.%s" % _hash_cache_field)
       
  1682     else:
       
  1683         append_hash_computation_lines("return ", tab)
       
  1684 
       
  1685     script = "\n".join(method_lines)
       
  1686     return _make_method("__hash__", script, unique_filename, globs)
       
  1687 
       
  1688 
       
  1689 def _add_hash(cls, attrs):
   423     """
  1690     """
   424     Add a hash method to *cls*.
  1691     Add a hash method to *cls*.
   425     """
  1692     """
   426     if attrs is None:
  1693     cls.__hash__ = _make_hash(cls, attrs, frozen=False, cache_hash=False)
   427         attrs = [a
       
   428                  for a in cls.__attrs_attrs__
       
   429                  if a.hash is True or (a.hash is None and a.cmp is True)]
       
   430 
       
   431     def hash_(self):
       
   432         """
       
   433         Automatically created by attrs.
       
   434         """
       
   435         return hash(_attrs_to_tuple(self, attrs))
       
   436 
       
   437     cls.__hash__ = hash_
       
   438     return cls
  1694     return cls
   439 
  1695 
   440 
  1696 
   441 def _add_cmp(cls, attrs=None):
  1697 def _make_ne():
   442     """
  1698     """
   443     Add comparison methods to *cls*.
  1699     Create __ne__ method.
   444     """
  1700     """
   445     if attrs is None:
  1701 
   446         attrs = [a for a in cls.__attrs_attrs__ if a.cmp]
  1702     def __ne__(self, other):
   447 
  1703         """
   448     def attrs_to_tuple(obj):
  1704         Check equality and either forward a NotImplemented or
   449         """
  1705         return the result negated.
   450         Save us some typing.
  1706         """
   451         """
  1707         result = self.__eq__(other)
   452         return _attrs_to_tuple(obj, attrs)
       
   453 
       
   454     def eq(self, other):
       
   455         """
       
   456         Automatically created by attrs.
       
   457         """
       
   458         if other.__class__ is self.__class__:
       
   459             return attrs_to_tuple(self) == attrs_to_tuple(other)
       
   460         else:
       
   461             return NotImplemented
       
   462 
       
   463     def ne(self, other):
       
   464         """
       
   465         Automatically created by attrs.
       
   466         """
       
   467         result = eq(self, other)
       
   468         if result is NotImplemented:
  1708         if result is NotImplemented:
   469             return NotImplemented
  1709             return NotImplemented
       
  1710 
       
  1711         return not result
       
  1712 
       
  1713     return __ne__
       
  1714 
       
  1715 
       
  1716 def _make_eq(cls, attrs):
       
  1717     """
       
  1718     Create __eq__ method for *cls* with *attrs*.
       
  1719     """
       
  1720     attrs = [a for a in attrs if a.eq]
       
  1721 
       
  1722     unique_filename = _generate_unique_filename(cls, "eq")
       
  1723     lines = [
       
  1724         "def __eq__(self, other):",
       
  1725         "    if other.__class__ is not self.__class__:",
       
  1726         "        return NotImplemented",
       
  1727     ]
       
  1728 
       
  1729     # We can't just do a big self.x = other.x and... clause due to
       
  1730     # irregularities like nan == nan is false but (nan,) == (nan,) is true.
       
  1731     globs = {}
       
  1732     if attrs:
       
  1733         lines.append("    return  (")
       
  1734         others = ["    ) == ("]
       
  1735         for a in attrs:
       
  1736             if a.eq_key:
       
  1737                 cmp_name = "_%s_key" % (a.name,)
       
  1738                 # Add the key function to the global namespace
       
  1739                 # of the evaluated function.
       
  1740                 globs[cmp_name] = a.eq_key
       
  1741                 lines.append(
       
  1742                     "        %s(self.%s),"
       
  1743                     % (
       
  1744                         cmp_name,
       
  1745                         a.name,
       
  1746                     )
       
  1747                 )
       
  1748                 others.append(
       
  1749                     "        %s(other.%s),"
       
  1750                     % (
       
  1751                         cmp_name,
       
  1752                         a.name,
       
  1753                     )
       
  1754                 )
       
  1755             else:
       
  1756                 lines.append("        self.%s," % (a.name,))
       
  1757                 others.append("        other.%s," % (a.name,))
       
  1758 
       
  1759         lines += others + ["    )"]
       
  1760     else:
       
  1761         lines.append("    return True")
       
  1762 
       
  1763     script = "\n".join(lines)
       
  1764 
       
  1765     return _make_method("__eq__", script, unique_filename, globs)
       
  1766 
       
  1767 
       
  1768 def _make_order(cls, attrs):
       
  1769     """
       
  1770     Create ordering methods for *cls* with *attrs*.
       
  1771     """
       
  1772     attrs = [a for a in attrs if a.order]
       
  1773 
       
  1774     def attrs_to_tuple(obj):
       
  1775         """
       
  1776         Save us some typing.
       
  1777         """
       
  1778         return tuple(
       
  1779             key(value) if key else value
       
  1780             for value, key in (
       
  1781                 (getattr(obj, a.name), a.order_key) for a in attrs
       
  1782             )
       
  1783         )
       
  1784 
       
  1785     def __lt__(self, other):
       
  1786         """
       
  1787         Automatically created by attrs.
       
  1788         """
       
  1789         if other.__class__ is self.__class__:
       
  1790             return attrs_to_tuple(self) < attrs_to_tuple(other)
       
  1791 
       
  1792         return NotImplemented
       
  1793 
       
  1794     def __le__(self, other):
       
  1795         """
       
  1796         Automatically created by attrs.
       
  1797         """
       
  1798         if other.__class__ is self.__class__:
       
  1799             return attrs_to_tuple(self) <= attrs_to_tuple(other)
       
  1800 
       
  1801         return NotImplemented
       
  1802 
       
  1803     def __gt__(self, other):
       
  1804         """
       
  1805         Automatically created by attrs.
       
  1806         """
       
  1807         if other.__class__ is self.__class__:
       
  1808             return attrs_to_tuple(self) > attrs_to_tuple(other)
       
  1809 
       
  1810         return NotImplemented
       
  1811 
       
  1812     def __ge__(self, other):
       
  1813         """
       
  1814         Automatically created by attrs.
       
  1815         """
       
  1816         if other.__class__ is self.__class__:
       
  1817             return attrs_to_tuple(self) >= attrs_to_tuple(other)
       
  1818 
       
  1819         return NotImplemented
       
  1820 
       
  1821     return __lt__, __le__, __gt__, __ge__
       
  1822 
       
  1823 
       
  1824 def _add_eq(cls, attrs=None):
       
  1825     """
       
  1826     Add equality methods to *cls* with *attrs*.
       
  1827     """
       
  1828     if attrs is None:
       
  1829         attrs = cls.__attrs_attrs__
       
  1830 
       
  1831     cls.__eq__ = _make_eq(cls, attrs)
       
  1832     cls.__ne__ = _make_ne()
       
  1833 
       
  1834     return cls
       
  1835 
       
  1836 
       
  1837 if HAS_F_STRINGS:
       
  1838 
       
  1839     def _make_repr(attrs, ns, cls):
       
  1840         unique_filename = _generate_unique_filename(cls, "repr")
       
  1841         # Figure out which attributes to include, and which function to use to
       
  1842         # format them. The a.repr value can be either bool or a custom
       
  1843         # callable.
       
  1844         attr_names_with_reprs = tuple(
       
  1845             (a.name, (repr if a.repr is True else a.repr), a.init)
       
  1846             for a in attrs
       
  1847             if a.repr is not False
       
  1848         )
       
  1849         globs = {
       
  1850             name + "_repr": r
       
  1851             for name, r, _ in attr_names_with_reprs
       
  1852             if r != repr
       
  1853         }
       
  1854         globs["_compat"] = _compat
       
  1855         globs["AttributeError"] = AttributeError
       
  1856         globs["NOTHING"] = NOTHING
       
  1857         attribute_fragments = []
       
  1858         for name, r, i in attr_names_with_reprs:
       
  1859             accessor = (
       
  1860                 "self." + name
       
  1861                 if i
       
  1862                 else 'getattr(self, "' + name + '", NOTHING)'
       
  1863             )
       
  1864             fragment = (
       
  1865                 "%s={%s!r}" % (name, accessor)
       
  1866                 if r == repr
       
  1867                 else "%s={%s_repr(%s)}" % (name, name, accessor)
       
  1868             )
       
  1869             attribute_fragments.append(fragment)
       
  1870         repr_fragment = ", ".join(attribute_fragments)
       
  1871 
       
  1872         if ns is None:
       
  1873             cls_name_fragment = (
       
  1874                 '{self.__class__.__qualname__.rsplit(">.", 1)[-1]}'
       
  1875             )
   470         else:
  1876         else:
   471             return not result
  1877             cls_name_fragment = ns + ".{self.__class__.__name__}"
   472 
  1878 
   473     def lt(self, other):
  1879         lines = [
   474         """
  1880             "def __repr__(self):",
   475         Automatically created by attrs.
  1881             "  try:",
   476         """
  1882             "    already_repring = _compat.repr_context.already_repring",
   477         if isinstance(other, self.__class__):
  1883             "  except AttributeError:",
   478             return attrs_to_tuple(self) < attrs_to_tuple(other)
  1884             "    already_repring = {id(self),}",
   479         else:
  1885             "    _compat.repr_context.already_repring = already_repring",
   480             return NotImplemented
  1886             "  else:",
   481 
  1887             "    if id(self) in already_repring:",
   482     def le(self, other):
  1888             "      return '...'",
   483         """
  1889             "    else:",
   484         Automatically created by attrs.
  1890             "      already_repring.add(id(self))",
   485         """
  1891             "  try:",
   486         if isinstance(other, self.__class__):
  1892             "    return f'%s(%s)'" % (cls_name_fragment, repr_fragment),
   487             return attrs_to_tuple(self) <= attrs_to_tuple(other)
  1893             "  finally:",
   488         else:
  1894             "    already_repring.remove(id(self))",
   489             return NotImplemented
  1895         ]
   490 
  1896 
   491     def gt(self, other):
  1897         return _make_method(
   492         """
  1898             "__repr__", "\n".join(lines), unique_filename, globs=globs
   493         Automatically created by attrs.
  1899         )
   494         """
  1900 
   495         if isinstance(other, self.__class__):
  1901 else:
   496             return attrs_to_tuple(self) > attrs_to_tuple(other)
  1902 
   497         else:
  1903     def _make_repr(attrs, ns, _):
   498             return NotImplemented
  1904         """
   499 
  1905         Make a repr method that includes relevant *attrs*, adding *ns* to the
   500     def ge(self, other):
  1906         full name.
   501         """
  1907         """
   502         Automatically created by attrs.
  1908 
   503         """
  1909         # Figure out which attributes to include, and which function to use to
   504         if isinstance(other, self.__class__):
  1910         # format them. The a.repr value can be either bool or a custom
   505             return attrs_to_tuple(self) >= attrs_to_tuple(other)
  1911         # callable.
   506         else:
  1912         attr_names_with_reprs = tuple(
   507             return NotImplemented
  1913             (a.name, repr if a.repr is True else a.repr)
   508 
  1914             for a in attrs
   509     cls.__eq__ = eq
  1915             if a.repr is not False
   510     cls.__ne__ = ne
  1916         )
   511     cls.__lt__ = lt
  1917 
   512     cls.__le__ = le
  1918         def __repr__(self):
   513     cls.__gt__ = gt
  1919             """
   514     cls.__ge__ = ge
  1920             Automatically created by attrs.
   515 
  1921             """
       
  1922             try:
       
  1923                 already_repring = _compat.repr_context.already_repring
       
  1924             except AttributeError:
       
  1925                 already_repring = set()
       
  1926                 _compat.repr_context.already_repring = already_repring
       
  1927 
       
  1928             if id(self) in already_repring:
       
  1929                 return "..."
       
  1930             real_cls = self.__class__
       
  1931             if ns is None:
       
  1932                 class_name = real_cls.__qualname__.rsplit(">.", 1)[-1]
       
  1933             else:
       
  1934                 class_name = ns + "." + real_cls.__name__
       
  1935 
       
  1936             # Since 'self' remains on the stack (i.e.: strongly referenced)
       
  1937             # for the duration of this call, it's safe to depend on id(...)
       
  1938             # stability, and not need to track the instance and therefore
       
  1939             # worry about properties like weakref- or hash-ability.
       
  1940             already_repring.add(id(self))
       
  1941             try:
       
  1942                 result = [class_name, "("]
       
  1943                 first = True
       
  1944                 for name, attr_repr in attr_names_with_reprs:
       
  1945                     if first:
       
  1946                         first = False
       
  1947                     else:
       
  1948                         result.append(", ")
       
  1949                     result.extend(
       
  1950                         (name, "=", attr_repr(getattr(self, name, NOTHING)))
       
  1951                     )
       
  1952                 return "".join(result) + ")"
       
  1953             finally:
       
  1954                 already_repring.remove(id(self))
       
  1955 
       
  1956         return __repr__
       
  1957 
       
  1958 
       
  1959 def _add_repr(cls, ns=None, attrs=None):
       
  1960     """
       
  1961     Add a repr method to *cls*.
       
  1962     """
       
  1963     if attrs is None:
       
  1964         attrs = cls.__attrs_attrs__
       
  1965 
       
  1966     cls.__repr__ = _make_repr(attrs, ns, cls)
   516     return cls
  1967     return cls
   517 
  1968 
   518 
  1969 
   519 def _add_repr(cls, ns=None, attrs=None):
       
   520     """
       
   521     Add a repr method to *cls*.
       
   522     """
       
   523     if attrs is None:
       
   524         attrs = [a for a in cls.__attrs_attrs__ if a.repr]
       
   525 
       
   526     def repr_(self):
       
   527         """
       
   528         Automatically created by attrs.
       
   529         """
       
   530         real_cls = self.__class__
       
   531         if ns is None:
       
   532             qualname = getattr(real_cls, "__qualname__", None)
       
   533             if qualname is not None:
       
   534                 class_name = qualname.rsplit(">.", 1)[-1]
       
   535             else:
       
   536                 class_name = real_cls.__name__
       
   537         else:
       
   538             class_name = ns + "." + real_cls.__name__
       
   539 
       
   540         return "{0}({1})".format(
       
   541             class_name,
       
   542             ", ".join(a.name + "=" + repr(getattr(self, a.name))
       
   543                       for a in attrs)
       
   544         )
       
   545     cls.__repr__ = repr_
       
   546     return cls
       
   547 
       
   548 
       
   549 def _add_init(cls, frozen):
       
   550     """
       
   551     Add a __init__ method to *cls*.  If *frozen* is True, make it immutable.
       
   552     """
       
   553     attrs = [a for a in cls.__attrs_attrs__
       
   554              if a.init or a.default is not NOTHING]
       
   555 
       
   556     # We cache the generated init methods for the same kinds of attributes.
       
   557     sha1 = hashlib.sha1()
       
   558     r = repr(attrs)
       
   559     if not isinstance(r, bytes):
       
   560         r = r.encode('utf-8')
       
   561     sha1.update(r)
       
   562     unique_filename = "<attrs generated init {0}>".format(
       
   563         sha1.hexdigest()
       
   564     )
       
   565 
       
   566     script, globs = _attrs_to_script(
       
   567         attrs,
       
   568         frozen,
       
   569         getattr(cls, "__attrs_post_init__", False),
       
   570     )
       
   571     locs = {}
       
   572     bytecode = compile(script, unique_filename, "exec")
       
   573     attr_dict = dict((a.name, a) for a in attrs)
       
   574     globs.update({
       
   575         "NOTHING": NOTHING,
       
   576         "attr_dict": attr_dict,
       
   577     })
       
   578     if frozen is True:
       
   579         # Save the lookup overhead in __init__ if we need to circumvent
       
   580         # immutability.
       
   581         globs["_cached_setattr"] = _obj_setattr
       
   582     eval(bytecode, globs, locs)
       
   583     init = locs["__init__"]
       
   584 
       
   585     # In order of debuggers like PDB being able to step through the code,
       
   586     # we add a fake linecache entry.
       
   587     linecache.cache[unique_filename] = (
       
   588         len(script),
       
   589         None,
       
   590         script.splitlines(True),
       
   591         unique_filename
       
   592     )
       
   593     cls.__init__ = init
       
   594     return cls
       
   595 
       
   596 
       
   597 def _add_pickle(cls):
       
   598     """
       
   599     Add pickle helpers, needed for frozen and slotted classes
       
   600     """
       
   601     def _slots_getstate__(obj):
       
   602         """
       
   603         Play nice with pickle.
       
   604         """
       
   605         return tuple(getattr(obj, a.name) for a in fields(obj.__class__))
       
   606 
       
   607     def _slots_setstate__(obj, state):
       
   608         """
       
   609         Play nice with pickle.
       
   610         """
       
   611         __bound_setattr = _obj_setattr.__get__(obj, Attribute)
       
   612         for a, value in zip(fields(obj.__class__), state):
       
   613             __bound_setattr(a.name, value)
       
   614 
       
   615     cls.__getstate__ = _slots_getstate__
       
   616     cls.__setstate__ = _slots_setstate__
       
   617     return cls
       
   618 
       
   619 
       
   620 def fields(cls):
  1970 def fields(cls):
   621     """
  1971     """
   622     Returns the tuple of ``attrs`` attributes for a class.
  1972     Return the tuple of ``attrs`` attributes for a class.
   623 
  1973 
   624     The tuple also allows accessing the fields by their names (see below for
  1974     The tuple also allows accessing the fields by their names (see below for
   625     examples).
  1975     examples).
   626 
  1976 
   627     :param type cls: Class to introspect.
  1977     :param type cls: Class to introspect.
   628 
  1978 
   629     :raise TypeError: If *cls* is not a class.
  1979     :raise TypeError: If *cls* is not a class.
   630     :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
  1980     :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
   631         class.
  1981         class.
   632 
  1982 
   633     :rtype: tuple (with name accesors) of :class:`attr.Attribute`
  1983     :rtype: tuple (with name accessors) of `attrs.Attribute`
   634 
  1984 
   635     ..  versionchanged:: 16.2.0 Returned tuple allows accessing the fields
  1985     ..  versionchanged:: 16.2.0 Returned tuple allows accessing the fields
   636         by name.
  1986         by name.
   637     """
  1987     """
   638     if not isclass(cls):
  1988     if not isinstance(cls, type):
   639         raise TypeError("Passed object must be a class.")
  1989         raise TypeError("Passed object must be a class.")
   640     attrs = getattr(cls, "__attrs_attrs__", None)
  1990     attrs = getattr(cls, "__attrs_attrs__", None)
   641     if attrs is None:
  1991     if attrs is None:
   642         raise NotAnAttrsClassError(
  1992         raise NotAnAttrsClassError(
   643             "{cls!r} is not an attrs-decorated class.".format(cls=cls)
  1993             "{cls!r} is not an attrs-decorated class.".format(cls=cls)
   644         )
  1994         )
   645     return attrs
  1995     return attrs
   646 
  1996 
   647 
  1997 
       
  1998 def fields_dict(cls):
       
  1999     """
       
  2000     Return an ordered dictionary of ``attrs`` attributes for a class, whose
       
  2001     keys are the attribute names.
       
  2002 
       
  2003     :param type cls: Class to introspect.
       
  2004 
       
  2005     :raise TypeError: If *cls* is not a class.
       
  2006     :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
       
  2007         class.
       
  2008 
       
  2009     :rtype: an ordered dict where keys are attribute names and values are
       
  2010         `attrs.Attribute`\\ s. This will be a `dict` if it's
       
  2011         naturally ordered like on Python 3.6+ or an
       
  2012         :class:`~collections.OrderedDict` otherwise.
       
  2013 
       
  2014     .. versionadded:: 18.1.0
       
  2015     """
       
  2016     if not isinstance(cls, type):
       
  2017         raise TypeError("Passed object must be a class.")
       
  2018     attrs = getattr(cls, "__attrs_attrs__", None)
       
  2019     if attrs is None:
       
  2020         raise NotAnAttrsClassError(
       
  2021             "{cls!r} is not an attrs-decorated class.".format(cls=cls)
       
  2022         )
       
  2023     return ordered_dict((a.name, a) for a in attrs)
       
  2024 
       
  2025 
   648 def validate(inst):
  2026 def validate(inst):
   649     """
  2027     """
   650     Validate all attributes on *inst* that have a validator.
  2028     Validate all attributes on *inst* that have a validator.
   651 
  2029 
   652     Leaves all exceptions through.
  2030     Leaves all exceptions through.
   660         v = a.validator
  2038         v = a.validator
   661         if v is not None:
  2039         if v is not None:
   662             v(inst, a, getattr(inst, a.name))
  2040             v(inst, a, getattr(inst, a.name))
   663 
  2041 
   664 
  2042 
   665 def _attrs_to_script(attrs, frozen, post_init):
  2043 def _is_slot_cls(cls):
       
  2044     return "__slots__" in cls.__dict__
       
  2045 
       
  2046 
       
  2047 def _is_slot_attr(a_name, base_attr_map):
       
  2048     """
       
  2049     Check if the attribute name comes from a slot class.
       
  2050     """
       
  2051     return a_name in base_attr_map and _is_slot_cls(base_attr_map[a_name])
       
  2052 
       
  2053 
       
  2054 def _make_init(
       
  2055     cls,
       
  2056     attrs,
       
  2057     pre_init,
       
  2058     post_init,
       
  2059     frozen,
       
  2060     slots,
       
  2061     cache_hash,
       
  2062     base_attr_map,
       
  2063     is_exc,
       
  2064     cls_on_setattr,
       
  2065     attrs_init,
       
  2066 ):
       
  2067     has_cls_on_setattr = (
       
  2068         cls_on_setattr is not None and cls_on_setattr is not setters.NO_OP
       
  2069     )
       
  2070 
       
  2071     if frozen and has_cls_on_setattr:
       
  2072         raise ValueError("Frozen classes can't use on_setattr.")
       
  2073 
       
  2074     needs_cached_setattr = cache_hash or frozen
       
  2075     filtered_attrs = []
       
  2076     attr_dict = {}
       
  2077     for a in attrs:
       
  2078         if not a.init and a.default is NOTHING:
       
  2079             continue
       
  2080 
       
  2081         filtered_attrs.append(a)
       
  2082         attr_dict[a.name] = a
       
  2083 
       
  2084         if a.on_setattr is not None:
       
  2085             if frozen is True:
       
  2086                 raise ValueError("Frozen classes can't use on_setattr.")
       
  2087 
       
  2088             needs_cached_setattr = True
       
  2089         elif has_cls_on_setattr and a.on_setattr is not setters.NO_OP:
       
  2090             needs_cached_setattr = True
       
  2091 
       
  2092     unique_filename = _generate_unique_filename(cls, "init")
       
  2093 
       
  2094     script, globs, annotations = _attrs_to_init_script(
       
  2095         filtered_attrs,
       
  2096         frozen,
       
  2097         slots,
       
  2098         pre_init,
       
  2099         post_init,
       
  2100         cache_hash,
       
  2101         base_attr_map,
       
  2102         is_exc,
       
  2103         has_cls_on_setattr,
       
  2104         attrs_init,
       
  2105     )
       
  2106     if cls.__module__ in sys.modules:
       
  2107         # This makes typing.get_type_hints(CLS.__init__) resolve string types.
       
  2108         globs.update(sys.modules[cls.__module__].__dict__)
       
  2109 
       
  2110     globs.update({"NOTHING": NOTHING, "attr_dict": attr_dict})
       
  2111 
       
  2112     if needs_cached_setattr:
       
  2113         # Save the lookup overhead in __init__ if we need to circumvent
       
  2114         # setattr hooks.
       
  2115         globs["_setattr"] = _obj_setattr
       
  2116 
       
  2117     init = _make_method(
       
  2118         "__attrs_init__" if attrs_init else "__init__",
       
  2119         script,
       
  2120         unique_filename,
       
  2121         globs,
       
  2122     )
       
  2123     init.__annotations__ = annotations
       
  2124 
       
  2125     return init
       
  2126 
       
  2127 
       
  2128 def _setattr(attr_name, value_var, has_on_setattr):
       
  2129     """
       
  2130     Use the cached object.setattr to set *attr_name* to *value_var*.
       
  2131     """
       
  2132     return "_setattr(self, '%s', %s)" % (attr_name, value_var)
       
  2133 
       
  2134 
       
  2135 def _setattr_with_converter(attr_name, value_var, has_on_setattr):
       
  2136     """
       
  2137     Use the cached object.setattr to set *attr_name* to *value_var*, but run
       
  2138     its converter first.
       
  2139     """
       
  2140     return "_setattr(self, '%s', %s(%s))" % (
       
  2141         attr_name,
       
  2142         _init_converter_pat % (attr_name,),
       
  2143         value_var,
       
  2144     )
       
  2145 
       
  2146 
       
  2147 def _assign(attr_name, value, has_on_setattr):
       
  2148     """
       
  2149     Unless *attr_name* has an on_setattr hook, use normal assignment. Otherwise
       
  2150     relegate to _setattr.
       
  2151     """
       
  2152     if has_on_setattr:
       
  2153         return _setattr(attr_name, value, True)
       
  2154 
       
  2155     return "self.%s = %s" % (attr_name, value)
       
  2156 
       
  2157 
       
  2158 def _assign_with_converter(attr_name, value_var, has_on_setattr):
       
  2159     """
       
  2160     Unless *attr_name* has an on_setattr hook, use normal assignment after
       
  2161     conversion. Otherwise relegate to _setattr_with_converter.
       
  2162     """
       
  2163     if has_on_setattr:
       
  2164         return _setattr_with_converter(attr_name, value_var, True)
       
  2165 
       
  2166     return "self.%s = %s(%s)" % (
       
  2167         attr_name,
       
  2168         _init_converter_pat % (attr_name,),
       
  2169         value_var,
       
  2170     )
       
  2171 
       
  2172 
       
  2173 def _attrs_to_init_script(
       
  2174     attrs,
       
  2175     frozen,
       
  2176     slots,
       
  2177     pre_init,
       
  2178     post_init,
       
  2179     cache_hash,
       
  2180     base_attr_map,
       
  2181     is_exc,
       
  2182     has_cls_on_setattr,
       
  2183     attrs_init,
       
  2184 ):
   666     """
  2185     """
   667     Return a script of an initializer for *attrs* and a dict of globals.
  2186     Return a script of an initializer for *attrs* and a dict of globals.
   668 
  2187 
   669     The globals are expected by the generated script.
  2188     The globals are expected by the generated script.
   670 
  2189 
   671      If *frozen* is True, we cannot set the attributes directly so we use
  2190     If *frozen* is True, we cannot set the attributes directly so we use
   672     a cached ``object.__setattr__``.
  2191     a cached ``object.__setattr__``.
   673     """
  2192     """
   674     lines = []
  2193     lines = []
       
  2194     if pre_init:
       
  2195         lines.append("self.__attrs_pre_init__()")
       
  2196 
   675     if frozen is True:
  2197     if frozen is True:
   676         lines.append(
  2198         if slots is True:
   677             # Circumvent the __setattr__ descriptor to save one lookup per
  2199             fmt_setter = _setattr
   678             # assignment.
  2200             fmt_setter_with_converter = _setattr_with_converter
   679             "_setattr = _cached_setattr.__get__(self, self.__class__)"
  2201         else:
   680         )
  2202             # Dict frozen classes assign directly to __dict__.
   681 
  2203             # But only if the attribute doesn't come from an ancestor slot
   682         def fmt_setter(attr_name, value_var):
  2204             # class.
   683             return "_setattr('%(attr_name)s', %(value_var)s)" % {
  2205             # Note _inst_dict will be used again below if cache_hash is True
   684                 "attr_name": attr_name,
  2206             lines.append("_inst_dict = self.__dict__")
   685                 "value_var": value_var,
  2207 
   686             }
  2208             def fmt_setter(attr_name, value_var, has_on_setattr):
   687 
  2209                 if _is_slot_attr(attr_name, base_attr_map):
   688         def fmt_setter_with_converter(attr_name, value_var):
  2210                     return _setattr(attr_name, value_var, has_on_setattr)
   689             conv_name = _init_convert_pat.format(attr_name)
  2211 
   690             return "_setattr('%(attr_name)s', %(conv)s(%(value_var)s))" % {
  2212                 return "_inst_dict['%s'] = %s" % (attr_name, value_var)
   691                 "attr_name": attr_name,
  2213 
   692                 "value_var": value_var,
  2214             def fmt_setter_with_converter(
   693                 "conv": conv_name,
  2215                 attr_name, value_var, has_on_setattr
   694             }
  2216             ):
       
  2217                 if has_on_setattr or _is_slot_attr(attr_name, base_attr_map):
       
  2218                     return _setattr_with_converter(
       
  2219                         attr_name, value_var, has_on_setattr
       
  2220                     )
       
  2221 
       
  2222                 return "_inst_dict['%s'] = %s(%s)" % (
       
  2223                     attr_name,
       
  2224                     _init_converter_pat % (attr_name,),
       
  2225                     value_var,
       
  2226                 )
       
  2227 
   695     else:
  2228     else:
   696         def fmt_setter(attr_name, value):
  2229         # Not frozen.
   697             return "self.%(attr_name)s = %(value)s" % {
  2230         fmt_setter = _assign
   698                 "attr_name": attr_name,
  2231         fmt_setter_with_converter = _assign_with_converter
   699                 "value": value,
       
   700             }
       
   701 
       
   702         def fmt_setter_with_converter(attr_name, value_var):
       
   703             conv_name = _init_convert_pat.format(attr_name)
       
   704             return "self.%(attr_name)s = %(conv)s(%(value_var)s)" % {
       
   705                 "attr_name": attr_name,
       
   706                 "value_var": value_var,
       
   707                 "conv": conv_name,
       
   708             }
       
   709 
  2232 
   710     args = []
  2233     args = []
       
  2234     kw_only_args = []
   711     attrs_to_validate = []
  2235     attrs_to_validate = []
   712 
  2236 
   713     # This is a dictionary of names to validator and converter callables.
  2237     # This is a dictionary of names to validator and converter callables.
   714     # Injecting this into __init__ globals lets us avoid lookups.
  2238     # Injecting this into __init__ globals lets us avoid lookups.
   715     names_for_globals = {}
  2239     names_for_globals = {}
       
  2240     annotations = {"return": None}
   716 
  2241 
   717     for a in attrs:
  2242     for a in attrs:
   718         if a.validator:
  2243         if a.validator:
   719             attrs_to_validate.append(a)
  2244             attrs_to_validate.append(a)
       
  2245 
   720         attr_name = a.name
  2246         attr_name = a.name
       
  2247         has_on_setattr = a.on_setattr is not None or (
       
  2248             a.on_setattr is not setters.NO_OP and has_cls_on_setattr
       
  2249         )
   721         arg_name = a.name.lstrip("_")
  2250         arg_name = a.name.lstrip("_")
       
  2251 
   722         has_factory = isinstance(a.default, Factory)
  2252         has_factory = isinstance(a.default, Factory)
   723         if has_factory and a.default.takes_self:
  2253         if has_factory and a.default.takes_self:
   724             maybe_self = "self"
  2254             maybe_self = "self"
   725         else:
  2255         else:
   726             maybe_self = ""
  2256             maybe_self = ""
       
  2257 
   727         if a.init is False:
  2258         if a.init is False:
   728             if has_factory:
  2259             if has_factory:
   729                 init_factory_name = _init_factory_pat.format(a.name)
  2260                 init_factory_name = _init_factory_pat.format(a.name)
   730                 if a.convert is not None:
  2261                 if a.converter is not None:
   731                     lines.append(fmt_setter_with_converter(
  2262                     lines.append(
   732                         attr_name,
  2263                         fmt_setter_with_converter(
   733                         init_factory_name + "({0})".format(maybe_self)))
  2264                             attr_name,
   734                     conv_name = _init_convert_pat.format(a.name)
  2265                             init_factory_name + "(%s)" % (maybe_self,),
   735                     names_for_globals[conv_name] = a.convert
  2266                             has_on_setattr,
       
  2267                         )
       
  2268                     )
       
  2269                     conv_name = _init_converter_pat % (a.name,)
       
  2270                     names_for_globals[conv_name] = a.converter
   736                 else:
  2271                 else:
   737                     lines.append(fmt_setter(
  2272                     lines.append(
   738                         attr_name,
  2273                         fmt_setter(
   739                         init_factory_name + "({0})".format(maybe_self)
  2274                             attr_name,
   740                     ))
  2275                             init_factory_name + "(%s)" % (maybe_self,),
       
  2276                             has_on_setattr,
       
  2277                         )
       
  2278                     )
   741                 names_for_globals[init_factory_name] = a.default.factory
  2279                 names_for_globals[init_factory_name] = a.default.factory
   742             else:
  2280             else:
   743                 if a.convert is not None:
  2281                 if a.converter is not None:
   744                     lines.append(fmt_setter_with_converter(
  2282                     lines.append(
       
  2283                         fmt_setter_with_converter(
       
  2284                             attr_name,
       
  2285                             "attr_dict['%s'].default" % (attr_name,),
       
  2286                             has_on_setattr,
       
  2287                         )
       
  2288                     )
       
  2289                     conv_name = _init_converter_pat % (a.name,)
       
  2290                     names_for_globals[conv_name] = a.converter
       
  2291                 else:
       
  2292                     lines.append(
       
  2293                         fmt_setter(
       
  2294                             attr_name,
       
  2295                             "attr_dict['%s'].default" % (attr_name,),
       
  2296                             has_on_setattr,
       
  2297                         )
       
  2298                     )
       
  2299         elif a.default is not NOTHING and not has_factory:
       
  2300             arg = "%s=attr_dict['%s'].default" % (arg_name, attr_name)
       
  2301             if a.kw_only:
       
  2302                 kw_only_args.append(arg)
       
  2303             else:
       
  2304                 args.append(arg)
       
  2305 
       
  2306             if a.converter is not None:
       
  2307                 lines.append(
       
  2308                     fmt_setter_with_converter(
       
  2309                         attr_name, arg_name, has_on_setattr
       
  2310                     )
       
  2311                 )
       
  2312                 names_for_globals[
       
  2313                     _init_converter_pat % (a.name,)
       
  2314                 ] = a.converter
       
  2315             else:
       
  2316                 lines.append(fmt_setter(attr_name, arg_name, has_on_setattr))
       
  2317 
       
  2318         elif has_factory:
       
  2319             arg = "%s=NOTHING" % (arg_name,)
       
  2320             if a.kw_only:
       
  2321                 kw_only_args.append(arg)
       
  2322             else:
       
  2323                 args.append(arg)
       
  2324             lines.append("if %s is not NOTHING:" % (arg_name,))
       
  2325 
       
  2326             init_factory_name = _init_factory_pat.format(a.name)
       
  2327             if a.converter is not None:
       
  2328                 lines.append(
       
  2329                     "    "
       
  2330                     + fmt_setter_with_converter(
       
  2331                         attr_name, arg_name, has_on_setattr
       
  2332                     )
       
  2333                 )
       
  2334                 lines.append("else:")
       
  2335                 lines.append(
       
  2336                     "    "
       
  2337                     + fmt_setter_with_converter(
   745                         attr_name,
  2338                         attr_name,
   746                         "attr_dict['{attr_name}'].default"
  2339                         init_factory_name + "(" + maybe_self + ")",
   747                         .format(attr_name=attr_name)
  2340                         has_on_setattr,
   748                     ))
  2341                     )
   749                     conv_name = _init_convert_pat.format(a.name)
  2342                 )
   750                     names_for_globals[conv_name] = a.convert
  2343                 names_for_globals[
   751                 else:
  2344                     _init_converter_pat % (a.name,)
   752                     lines.append(fmt_setter(
  2345                 ] = a.converter
       
  2346             else:
       
  2347                 lines.append(
       
  2348                     "    " + fmt_setter(attr_name, arg_name, has_on_setattr)
       
  2349                 )
       
  2350                 lines.append("else:")
       
  2351                 lines.append(
       
  2352                     "    "
       
  2353                     + fmt_setter(
   753                         attr_name,
  2354                         attr_name,
   754                         "attr_dict['{attr_name}'].default"
  2355                         init_factory_name + "(" + maybe_self + ")",
   755                         .format(attr_name=attr_name)
  2356                         has_on_setattr,
   756                     ))
  2357                     )
   757         elif a.default is not NOTHING and not has_factory:
       
   758             args.append(
       
   759                 "{arg_name}=attr_dict['{attr_name}'].default".format(
       
   760                     arg_name=arg_name,
       
   761                     attr_name=attr_name,
       
   762                 )
  2358                 )
   763             )
       
   764             if a.convert is not None:
       
   765                 lines.append(fmt_setter_with_converter(attr_name, arg_name))
       
   766                 names_for_globals[_init_convert_pat.format(a.name)] = a.convert
       
   767             else:
       
   768                 lines.append(fmt_setter(attr_name, arg_name))
       
   769         elif has_factory:
       
   770             args.append("{arg_name}=NOTHING".format(arg_name=arg_name))
       
   771             lines.append("if {arg_name} is not NOTHING:"
       
   772                          .format(arg_name=arg_name))
       
   773             init_factory_name = _init_factory_pat.format(a.name)
       
   774             if a.convert is not None:
       
   775                 lines.append("    " + fmt_setter_with_converter(attr_name,
       
   776                                                                 arg_name))
       
   777                 lines.append("else:")
       
   778                 lines.append("    " + fmt_setter_with_converter(
       
   779                     attr_name,
       
   780                     init_factory_name + "({0})".format(maybe_self)
       
   781                 ))
       
   782                 names_for_globals[_init_convert_pat.format(a.name)] = a.convert
       
   783             else:
       
   784                 lines.append("    " + fmt_setter(attr_name, arg_name))
       
   785                 lines.append("else:")
       
   786                 lines.append("    " + fmt_setter(
       
   787                     attr_name,
       
   788                     init_factory_name + "({0})".format(maybe_self)
       
   789                 ))
       
   790             names_for_globals[init_factory_name] = a.default.factory
  2359             names_for_globals[init_factory_name] = a.default.factory
   791         else:
  2360         else:
   792             args.append(arg_name)
  2361             if a.kw_only:
   793             if a.convert is not None:
  2362                 kw_only_args.append(arg_name)
   794                 lines.append(fmt_setter_with_converter(attr_name, arg_name))
       
   795                 names_for_globals[_init_convert_pat.format(a.name)] = a.convert
       
   796             else:
  2363             else:
   797                 lines.append(fmt_setter(attr_name, arg_name))
  2364                 args.append(arg_name)
       
  2365 
       
  2366             if a.converter is not None:
       
  2367                 lines.append(
       
  2368                     fmt_setter_with_converter(
       
  2369                         attr_name, arg_name, has_on_setattr
       
  2370                     )
       
  2371                 )
       
  2372                 names_for_globals[
       
  2373                     _init_converter_pat % (a.name,)
       
  2374                 ] = a.converter
       
  2375             else:
       
  2376                 lines.append(fmt_setter(attr_name, arg_name, has_on_setattr))
       
  2377 
       
  2378         if a.init is True:
       
  2379             if a.type is not None and a.converter is None:
       
  2380                 annotations[arg_name] = a.type
       
  2381             elif a.converter is not None:
       
  2382                 # Try to get the type from the converter.
       
  2383                 t = _AnnotationExtractor(a.converter).get_first_param_type()
       
  2384                 if t:
       
  2385                     annotations[arg_name] = t
   798 
  2386 
   799     if attrs_to_validate:  # we can skip this if there are no validators.
  2387     if attrs_to_validate:  # we can skip this if there are no validators.
   800         names_for_globals["_config"] = _config
  2388         names_for_globals["_config"] = _config
   801         lines.append("if _config._run_validators is True:")
  2389         lines.append("if _config._run_validators is True:")
   802         for a in attrs_to_validate:
  2390         for a in attrs_to_validate:
   803             val_name = "__attr_validator_{}".format(a.name)
  2391             val_name = "__attr_validator_" + a.name
   804             attr_name = "__attr_{}".format(a.name)
  2392             attr_name = "__attr_" + a.name
   805             lines.append("    {}(self, {}, self.{})".format(
  2393             lines.append(
   806                 val_name, attr_name, a.name))
  2394                 "    %s(self, %s, self.%s)" % (val_name, attr_name, a.name)
       
  2395             )
   807             names_for_globals[val_name] = a.validator
  2396             names_for_globals[val_name] = a.validator
   808             names_for_globals[attr_name] = a
  2397             names_for_globals[attr_name] = a
       
  2398 
   809     if post_init:
  2399     if post_init:
   810         lines.append("self.__attrs_post_init__()")
  2400         lines.append("self.__attrs_post_init__()")
   811 
  2401 
   812     return """\
  2402     # because this is set only after __attrs_post_init__ is called, a crash
   813 def __init__(self, {args}):
  2403     # will result if post-init tries to access the hash code.  This seemed
       
  2404     # preferable to setting this beforehand, in which case alteration to
       
  2405     # field values during post-init combined with post-init accessing the
       
  2406     # hash code would result in silent bugs.
       
  2407     if cache_hash:
       
  2408         if frozen:
       
  2409             if slots:
       
  2410                 # if frozen and slots, then _setattr defined above
       
  2411                 init_hash_cache = "_setattr(self, '%s', %s)"
       
  2412             else:
       
  2413                 # if frozen and not slots, then _inst_dict defined above
       
  2414                 init_hash_cache = "_inst_dict['%s'] = %s"
       
  2415         else:
       
  2416             init_hash_cache = "self.%s = %s"
       
  2417         lines.append(init_hash_cache % (_hash_cache_field, "None"))
       
  2418 
       
  2419     # For exceptions we rely on BaseException.__init__ for proper
       
  2420     # initialization.
       
  2421     if is_exc:
       
  2422         vals = ",".join("self." + a.name for a in attrs if a.init)
       
  2423 
       
  2424         lines.append("BaseException.__init__(self, %s)" % (vals,))
       
  2425 
       
  2426     args = ", ".join(args)
       
  2427     if kw_only_args:
       
  2428         args += "%s*, %s" % (
       
  2429             ", " if args else "",  # leading comma
       
  2430             ", ".join(kw_only_args),  # kw_only args
       
  2431         )
       
  2432     return (
       
  2433         """\
       
  2434 def {init_name}(self, {args}):
   814     {lines}
  2435     {lines}
   815 """.format(
  2436 """.format(
   816         args=", ".join(args),
  2437             init_name=("__attrs_init__" if attrs_init else "__init__"),
   817         lines="\n    ".join(lines) if lines else "pass",
  2438             args=args,
   818     ), names_for_globals
  2439             lines="\n    ".join(lines) if lines else "pass",
   819 
  2440         ),
   820 
  2441         names_for_globals,
   821 class Attribute(object):
  2442         annotations,
       
  2443     )
       
  2444 
       
  2445 
       
  2446 class Attribute:
   822     """
  2447     """
   823     *Read-only* representation of an attribute.
  2448     *Read-only* representation of an attribute.
   824 
  2449 
   825     :attribute name: The name of the attribute.
  2450     The class has *all* arguments of `attr.ib` (except for ``factory``
   826 
  2451     which is only syntactic sugar for ``default=Factory(...)`` plus the
   827     Plus *all* arguments of :func:`attr.ib`.
  2452     following:
   828     """
  2453 
       
  2454     - ``name`` (`str`): The name of the attribute.
       
  2455     - ``inherited`` (`bool`): Whether or not that attribute has been inherited
       
  2456       from a base class.
       
  2457     - ``eq_key`` and ``order_key`` (`typing.Callable` or `None`): The callables
       
  2458       that are used for comparing and ordering objects by this attribute,
       
  2459       respectively. These are set by passing a callable to `attr.ib`'s ``eq``,
       
  2460       ``order``, or ``cmp`` arguments. See also :ref:`comparison customization
       
  2461       <custom-comparison>`.
       
  2462 
       
  2463     Instances of this class are frequently used for introspection purposes
       
  2464     like:
       
  2465 
       
  2466     - `fields` returns a tuple of them.
       
  2467     - Validators get them passed as the first argument.
       
  2468     - The :ref:`field transformer <transform-fields>` hook receives a list of
       
  2469       them.
       
  2470 
       
  2471     .. versionadded:: 20.1.0 *inherited*
       
  2472     .. versionadded:: 20.1.0 *on_setattr*
       
  2473     .. versionchanged:: 20.2.0 *inherited* is not taken into account for
       
  2474         equality checks and hashing anymore.
       
  2475     .. versionadded:: 21.1.0 *eq_key* and *order_key*
       
  2476 
       
  2477     For the full version history of the fields, see `attr.ib`.
       
  2478     """
       
  2479 
   829     __slots__ = (
  2480     __slots__ = (
   830         "name", "default", "validator", "repr", "cmp", "hash", "init",
  2481         "name",
   831         "convert", "metadata",
  2482         "default",
       
  2483         "validator",
       
  2484         "repr",
       
  2485         "eq",
       
  2486         "eq_key",
       
  2487         "order",
       
  2488         "order_key",
       
  2489         "hash",
       
  2490         "init",
       
  2491         "metadata",
       
  2492         "type",
       
  2493         "converter",
       
  2494         "kw_only",
       
  2495         "inherited",
       
  2496         "on_setattr",
   832     )
  2497     )
   833 
  2498 
   834     def __init__(self, name, default, validator, repr, cmp, hash, init,
  2499     def __init__(
   835                  convert=None, metadata=None):
  2500         self,
       
  2501         name,
       
  2502         default,
       
  2503         validator,
       
  2504         repr,
       
  2505         cmp,  # XXX: unused, remove along with other cmp code.
       
  2506         hash,
       
  2507         init,
       
  2508         inherited,
       
  2509         metadata=None,
       
  2510         type=None,
       
  2511         converter=None,
       
  2512         kw_only=False,
       
  2513         eq=None,
       
  2514         eq_key=None,
       
  2515         order=None,
       
  2516         order_key=None,
       
  2517         on_setattr=None,
       
  2518     ):
       
  2519         eq, eq_key, order, order_key = _determine_attrib_eq_order(
       
  2520             cmp, eq_key or eq, order_key or order, True
       
  2521         )
       
  2522 
   836         # Cache this descriptor here to speed things up later.
  2523         # Cache this descriptor here to speed things up later.
   837         bound_setattr = _obj_setattr.__get__(self, Attribute)
  2524         bound_setattr = _obj_setattr.__get__(self, Attribute)
   838 
  2525 
       
  2526         # Despite the big red warning, people *do* instantiate `Attribute`
       
  2527         # themselves.
   839         bound_setattr("name", name)
  2528         bound_setattr("name", name)
   840         bound_setattr("default", default)
  2529         bound_setattr("default", default)
   841         bound_setattr("validator", validator)
  2530         bound_setattr("validator", validator)
   842         bound_setattr("repr", repr)
  2531         bound_setattr("repr", repr)
   843         bound_setattr("cmp", cmp)
  2532         bound_setattr("eq", eq)
       
  2533         bound_setattr("eq_key", eq_key)
       
  2534         bound_setattr("order", order)
       
  2535         bound_setattr("order_key", order_key)
   844         bound_setattr("hash", hash)
  2536         bound_setattr("hash", hash)
   845         bound_setattr("init", init)
  2537         bound_setattr("init", init)
   846         bound_setattr("convert", convert)
  2538         bound_setattr("converter", converter)
   847         bound_setattr("metadata", (metadata_proxy(metadata) if metadata
  2539         bound_setattr(
   848                                    else _empty_metadata_singleton))
  2540             "metadata",
       
  2541             (
       
  2542                 types.MappingProxyType(dict(metadata))  # Shallow copy
       
  2543                 if metadata
       
  2544                 else _empty_metadata_singleton
       
  2545             ),
       
  2546         )
       
  2547         bound_setattr("type", type)
       
  2548         bound_setattr("kw_only", kw_only)
       
  2549         bound_setattr("inherited", inherited)
       
  2550         bound_setattr("on_setattr", on_setattr)
   849 
  2551 
   850     def __setattr__(self, name, value):
  2552     def __setattr__(self, name, value):
   851         raise FrozenInstanceError()
  2553         raise FrozenInstanceError()
   852 
  2554 
   853     @classmethod
  2555     @classmethod
   854     def from_counting_attr(cls, name, ca):
  2556     def from_counting_attr(cls, name, ca, type=None):
       
  2557         # type holds the annotated value. deal with conflicts:
       
  2558         if type is None:
       
  2559             type = ca.type
       
  2560         elif ca.type is not None:
       
  2561             raise ValueError(
       
  2562                 "Type annotation and type argument cannot both be present"
       
  2563             )
   855         inst_dict = {
  2564         inst_dict = {
   856             k: getattr(ca, k)
  2565             k: getattr(ca, k)
   857             for k
  2566             for k in Attribute.__slots__
   858             in Attribute.__slots__
  2567             if k
   859             if k not in (
  2568             not in (
   860                 "name", "validator", "default",
  2569                 "name",
   861             )  # exclude methods
  2570                 "validator",
       
  2571                 "default",
       
  2572                 "type",
       
  2573                 "inherited",
       
  2574             )  # exclude methods and deprecated alias
   862         }
  2575         }
   863         return cls(name=name, validator=ca._validator, default=ca._default,
  2576         return cls(
   864                    **inst_dict)
  2577             name=name,
       
  2578             validator=ca._validator,
       
  2579             default=ca._default,
       
  2580             type=type,
       
  2581             cmp=None,
       
  2582             inherited=False,
       
  2583             **inst_dict
       
  2584         )
       
  2585 
       
  2586     # Don't use attr.evolve since fields(Attribute) doesn't work
       
  2587     def evolve(self, **changes):
       
  2588         """
       
  2589         Copy *self* and apply *changes*.
       
  2590 
       
  2591         This works similarly to `attr.evolve` but that function does not work
       
  2592         with ``Attribute``.
       
  2593 
       
  2594         It is mainly meant to be used for `transform-fields`.
       
  2595 
       
  2596         .. versionadded:: 20.3.0
       
  2597         """
       
  2598         new = copy.copy(self)
       
  2599 
       
  2600         new._setattrs(changes.items())
       
  2601 
       
  2602         return new
   865 
  2603 
   866     # Don't use _add_pickle since fields(Attribute) doesn't work
  2604     # Don't use _add_pickle since fields(Attribute) doesn't work
   867     def __getstate__(self):
  2605     def __getstate__(self):
   868         """
  2606         """
   869         Play nice with pickle.
  2607         Play nice with pickle.
   870         """
  2608         """
   871         return tuple(getattr(self, name) if name != "metadata"
  2609         return tuple(
   872                      else dict(self.metadata)
  2610             getattr(self, name) if name != "metadata" else dict(self.metadata)
   873                      for name in self.__slots__)
  2611             for name in self.__slots__
       
  2612         )
   874 
  2613 
   875     def __setstate__(self, state):
  2614     def __setstate__(self, state):
   876         """
  2615         """
   877         Play nice with pickle.
  2616         Play nice with pickle.
   878         """
  2617         """
       
  2618         self._setattrs(zip(self.__slots__, state))
       
  2619 
       
  2620     def _setattrs(self, name_values_pairs):
   879         bound_setattr = _obj_setattr.__get__(self, Attribute)
  2621         bound_setattr = _obj_setattr.__get__(self, Attribute)
   880         for name, value in zip(self.__slots__, state):
  2622         for name, value in name_values_pairs:
   881             if name != "metadata":
  2623             if name != "metadata":
   882                 bound_setattr(name, value)
  2624                 bound_setattr(name, value)
   883             else:
  2625             else:
   884                 bound_setattr(name, metadata_proxy(value) if value else
  2626                 bound_setattr(
   885                               _empty_metadata_singleton)
  2627                     name,
   886 
  2628                     types.MappingProxyType(dict(value))
   887 
  2629                     if value
   888 _a = [Attribute(name=name, default=NOTHING, validator=None,
  2630                     else _empty_metadata_singleton,
   889                 repr=True, cmp=True, hash=(name != "metadata"), init=True)
  2631                 )
   890       for name in Attribute.__slots__]
  2632 
       
  2633 
       
  2634 _a = [
       
  2635     Attribute(
       
  2636         name=name,
       
  2637         default=NOTHING,
       
  2638         validator=None,
       
  2639         repr=True,
       
  2640         cmp=None,
       
  2641         eq=True,
       
  2642         order=False,
       
  2643         hash=(name != "metadata"),
       
  2644         init=True,
       
  2645         inherited=False,
       
  2646     )
       
  2647     for name in Attribute.__slots__
       
  2648 ]
   891 
  2649 
   892 Attribute = _add_hash(
  2650 Attribute = _add_hash(
   893     _add_cmp(_add_repr(Attribute, attrs=_a), attrs=_a),
  2651     _add_eq(
   894     attrs=[a for a in _a if a.hash]
  2652         _add_repr(Attribute, attrs=_a),
       
  2653         attrs=[a for a in _a if a.name != "inherited"],
       
  2654     ),
       
  2655     attrs=[a for a in _a if a.hash and a.name != "inherited"],
   895 )
  2656 )
   896 
  2657 
   897 
  2658 
   898 class _CountingAttr(object):
  2659 class _CountingAttr:
   899     """
  2660     """
   900     Intermediate representation of attributes that uses a counter to preserve
  2661     Intermediate representation of attributes that uses a counter to preserve
   901     the order in which the attributes have been defined.
  2662     the order in which the attributes have been defined.
   902 
  2663 
   903     *Internal* data structure of the attrs library.  Running into is most
  2664     *Internal* data structure of the attrs library.  Running into is most
   904     likely the result of a bug like a forgotten `@attr.s` decorator.
  2665     likely the result of a bug like a forgotten `@attr.s` decorator.
   905     """
  2666     """
   906     __slots__ = ("counter", "_default", "repr", "cmp", "hash", "init",
  2667 
   907                  "metadata", "_validator", "convert")
  2668     __slots__ = (
       
  2669         "counter",
       
  2670         "_default",
       
  2671         "repr",
       
  2672         "eq",
       
  2673         "eq_key",
       
  2674         "order",
       
  2675         "order_key",
       
  2676         "hash",
       
  2677         "init",
       
  2678         "metadata",
       
  2679         "_validator",
       
  2680         "converter",
       
  2681         "type",
       
  2682         "kw_only",
       
  2683         "on_setattr",
       
  2684     )
   908     __attrs_attrs__ = tuple(
  2685     __attrs_attrs__ = tuple(
   909         Attribute(name=name, default=NOTHING, validator=None,
  2686         Attribute(
   910                   repr=True, cmp=True, hash=True, init=True)
  2687             name=name,
   911         for name
  2688             default=NOTHING,
   912         in ("counter", "_default", "repr", "cmp", "hash", "init",)
  2689             validator=None,
       
  2690             repr=True,
       
  2691             cmp=None,
       
  2692             hash=True,
       
  2693             init=True,
       
  2694             kw_only=False,
       
  2695             eq=True,
       
  2696             eq_key=None,
       
  2697             order=False,
       
  2698             order_key=None,
       
  2699             inherited=False,
       
  2700             on_setattr=None,
       
  2701         )
       
  2702         for name in (
       
  2703             "counter",
       
  2704             "_default",
       
  2705             "repr",
       
  2706             "eq",
       
  2707             "order",
       
  2708             "hash",
       
  2709             "init",
       
  2710             "on_setattr",
       
  2711         )
   913     ) + (
  2712     ) + (
   914         Attribute(name="metadata", default=None, validator=None,
  2713         Attribute(
   915                   repr=True, cmp=True, hash=False, init=True),
  2714             name="metadata",
       
  2715             default=None,
       
  2716             validator=None,
       
  2717             repr=True,
       
  2718             cmp=None,
       
  2719             hash=False,
       
  2720             init=True,
       
  2721             kw_only=False,
       
  2722             eq=True,
       
  2723             eq_key=None,
       
  2724             order=False,
       
  2725             order_key=None,
       
  2726             inherited=False,
       
  2727             on_setattr=None,
       
  2728         ),
   916     )
  2729     )
   917     cls_counter = 0
  2730     cls_counter = 0
   918 
  2731 
   919     def __init__(self, default, validator, repr, cmp, hash, init, convert,
  2732     def __init__(
   920                  metadata):
  2733         self,
       
  2734         default,
       
  2735         validator,
       
  2736         repr,
       
  2737         cmp,
       
  2738         hash,
       
  2739         init,
       
  2740         converter,
       
  2741         metadata,
       
  2742         type,
       
  2743         kw_only,
       
  2744         eq,
       
  2745         eq_key,
       
  2746         order,
       
  2747         order_key,
       
  2748         on_setattr,
       
  2749     ):
   921         _CountingAttr.cls_counter += 1
  2750         _CountingAttr.cls_counter += 1
   922         self.counter = _CountingAttr.cls_counter
  2751         self.counter = _CountingAttr.cls_counter
   923         self._default = default
  2752         self._default = default
   924         # If validator is a list/tuple, wrap it using helper validator.
  2753         self._validator = validator
   925         if validator and isinstance(validator, (list, tuple)):
  2754         self.converter = converter
   926             self._validator = and_(*validator)
       
   927         else:
       
   928             self._validator = validator
       
   929         self.repr = repr
  2755         self.repr = repr
   930         self.cmp = cmp
  2756         self.eq = eq
       
  2757         self.eq_key = eq_key
       
  2758         self.order = order
       
  2759         self.order_key = order_key
   931         self.hash = hash
  2760         self.hash = hash
   932         self.init = init
  2761         self.init = init
   933         self.convert = convert
       
   934         self.metadata = metadata
  2762         self.metadata = metadata
       
  2763         self.type = type
       
  2764         self.kw_only = kw_only
       
  2765         self.on_setattr = on_setattr
   935 
  2766 
   936     def validator(self, meth):
  2767     def validator(self, meth):
   937         """
  2768         """
   938         Decorator that adds *meth* to the list of validators.
  2769         Decorator that adds *meth* to the list of validators.
   939 
  2770 
   963         self._default = Factory(meth, takes_self=True)
  2794         self._default = Factory(meth, takes_self=True)
   964 
  2795 
   965         return meth
  2796         return meth
   966 
  2797 
   967 
  2798 
   968 _CountingAttr = _add_cmp(_add_repr(_CountingAttr))
  2799 _CountingAttr = _add_eq(_add_repr(_CountingAttr))
   969 
  2800 
   970 
  2801 
   971 @attributes(slots=True, init=False)
  2802 class Factory:
   972 class Factory(object):
       
   973     """
  2803     """
   974     Stores a factory callable.
  2804     Stores a factory callable.
   975 
  2805 
   976     If passed as the default value to :func:`attr.ib`, the factory is used to
  2806     If passed as the default value to `attrs.field`, the factory is used to
   977     generate a new value.
  2807     generate a new value.
   978 
  2808 
   979     :param callable factory: A callable that takes either none or exactly one
  2809     :param callable factory: A callable that takes either none or exactly one
   980         mandatory positional argument depending on *takes_self*.
  2810         mandatory positional argument depending on *takes_self*.
   981     :param bool takes_self: Pass the partially initialized instance that is
  2811     :param bool takes_self: Pass the partially initialized instance that is
   982         being initialized as a positional argument.
  2812         being initialized as a positional argument.
   983 
  2813 
   984     .. versionadded:: 17.1.0  *takes_self*
  2814     .. versionadded:: 17.1.0  *takes_self*
   985     """
  2815     """
   986     factory = attr()
  2816 
   987     takes_self = attr()
  2817     __slots__ = ("factory", "takes_self")
   988 
  2818 
   989     def __init__(self, factory, takes_self=False):
  2819     def __init__(self, factory, takes_self=False):
   990         """
  2820         """
   991         `Factory` is part of the default machinery so if we want a default
  2821         `Factory` is part of the default machinery so if we want a default
   992         value here, we have to implement it ourselves.
  2822         value here, we have to implement it ourselves.
   993         """
  2823         """
   994         self.factory = factory
  2824         self.factory = factory
   995         self.takes_self = takes_self
  2825         self.takes_self = takes_self
   996 
  2826 
       
  2827     def __getstate__(self):
       
  2828         """
       
  2829         Play nice with pickle.
       
  2830         """
       
  2831         return tuple(getattr(self, name) for name in self.__slots__)
       
  2832 
       
  2833     def __setstate__(self, state):
       
  2834         """
       
  2835         Play nice with pickle.
       
  2836         """
       
  2837         for name, value in zip(self.__slots__, state):
       
  2838             setattr(self, name, value)
       
  2839 
       
  2840 
       
  2841 _f = [
       
  2842     Attribute(
       
  2843         name=name,
       
  2844         default=NOTHING,
       
  2845         validator=None,
       
  2846         repr=True,
       
  2847         cmp=None,
       
  2848         eq=True,
       
  2849         order=False,
       
  2850         hash=True,
       
  2851         init=True,
       
  2852         inherited=False,
       
  2853     )
       
  2854     for name in Factory.__slots__
       
  2855 ]
       
  2856 
       
  2857 Factory = _add_hash(_add_eq(_add_repr(Factory, attrs=_f), attrs=_f), attrs=_f)
       
  2858 
   997 
  2859 
   998 def make_class(name, attrs, bases=(object,), **attributes_arguments):
  2860 def make_class(name, attrs, bases=(object,), **attributes_arguments):
   999     """
  2861     """
  1000     A quick way to create a new class called *name* with *attrs*.
  2862     A quick way to create a new class called *name* with *attrs*.
  1001 
  2863 
  1002     :param name: The name for the new class.
  2864     :param str name: The name for the new class.
  1003     :type name: str
       
  1004 
  2865 
  1005     :param attrs: A list of names or a dictionary of mappings of names to
  2866     :param attrs: A list of names or a dictionary of mappings of names to
  1006         attributes.
  2867         attributes.
  1007     :type attrs: :class:`list` or :class:`dict`
  2868 
       
  2869         If *attrs* is a list or an ordered dict (`dict` on Python 3.6+,
       
  2870         `collections.OrderedDict` otherwise), the order is deduced from
       
  2871         the order of the names or attributes inside *attrs*.  Otherwise the
       
  2872         order of the definition of the attributes is used.
       
  2873     :type attrs: `list` or `dict`
  1008 
  2874 
  1009     :param tuple bases: Classes that the new class will subclass.
  2875     :param tuple bases: Classes that the new class will subclass.
  1010 
  2876 
  1011     :param attributes_arguments: Passed unmodified to :func:`attr.s`.
  2877     :param attributes_arguments: Passed unmodified to `attr.s`.
  1012 
  2878 
  1013     :return: A new class with *attrs*.
  2879     :return: A new class with *attrs*.
  1014     :rtype: type
  2880     :rtype: type
  1015 
  2881 
  1016     ..  versionadded:: 17.1.0 *bases*
  2882     .. versionadded:: 17.1.0 *bases*
       
  2883     .. versionchanged:: 18.1.0 If *attrs* is ordered, the order is retained.
  1017     """
  2884     """
  1018     if isinstance(attrs, dict):
  2885     if isinstance(attrs, dict):
  1019         cls_dict = attrs
  2886         cls_dict = attrs
  1020     elif isinstance(attrs, (list, tuple)):
  2887     elif isinstance(attrs, (list, tuple)):
  1021         cls_dict = dict((a, attr()) for a in attrs)
  2888         cls_dict = {a: attrib() for a in attrs}
  1022     else:
  2889     else:
  1023         raise TypeError("attrs argument must be a dict or a list.")
  2890         raise TypeError("attrs argument must be a dict or a list.")
  1024 
  2891 
  1025     return attributes(**attributes_arguments)(type(name, bases, cls_dict))
  2892     pre_init = cls_dict.pop("__attrs_pre_init__", None)
  1026 
  2893     post_init = cls_dict.pop("__attrs_post_init__", None)
  1027 
  2894     user_init = cls_dict.pop("__init__", None)
  1028 # These are required by whithin this module so we define them here and merely
  2895 
  1029 # import into .validators.
  2896     body = {}
  1030 
  2897     if pre_init is not None:
  1031 
  2898         body["__attrs_pre_init__"] = pre_init
  1032 @attributes(slots=True, hash=True)
  2899     if post_init is not None:
  1033 class _AndValidator(object):
  2900         body["__attrs_post_init__"] = post_init
       
  2901     if user_init is not None:
       
  2902         body["__init__"] = user_init
       
  2903 
       
  2904     type_ = types.new_class(name, bases, {}, lambda ns: ns.update(body))
       
  2905 
       
  2906     # For pickling to work, the __module__ variable needs to be set to the
       
  2907     # frame where the class is created.  Bypass this step in environments where
       
  2908     # sys._getframe is not defined (Jython for example) or sys._getframe is not
       
  2909     # defined for arguments greater than 0 (IronPython).
       
  2910     try:
       
  2911         type_.__module__ = sys._getframe(1).f_globals.get(
       
  2912             "__name__", "__main__"
       
  2913         )
       
  2914     except (AttributeError, ValueError):
       
  2915         pass
       
  2916 
       
  2917     # We do it here for proper warnings with meaningful stacklevel.
       
  2918     cmp = attributes_arguments.pop("cmp", None)
       
  2919     (
       
  2920         attributes_arguments["eq"],
       
  2921         attributes_arguments["order"],
       
  2922     ) = _determine_attrs_eq_order(
       
  2923         cmp,
       
  2924         attributes_arguments.get("eq"),
       
  2925         attributes_arguments.get("order"),
       
  2926         True,
       
  2927     )
       
  2928 
       
  2929     return _attrs(these=cls_dict, **attributes_arguments)(type_)
       
  2930 
       
  2931 
       
  2932 # These are required by within this module so we define them here and merely
       
  2933 # import into .validators / .converters.
       
  2934 
       
  2935 
       
  2936 @attrs(slots=True, hash=True)
       
  2937 class _AndValidator:
  1034     """
  2938     """
  1035     Compose many validators to a single one.
  2939     Compose many validators to a single one.
  1036     """
  2940     """
  1037     _validators = attr()
  2941 
       
  2942     _validators = attrib()
  1038 
  2943 
  1039     def __call__(self, inst, attr, value):
  2944     def __call__(self, inst, attr, value):
  1040         for v in self._validators:
  2945         for v in self._validators:
  1041             v(inst, attr, value)
  2946             v(inst, attr, value)
  1042 
  2947 
  1045     """
  2950     """
  1046     A validator that composes multiple validators into one.
  2951     A validator that composes multiple validators into one.
  1047 
  2952 
  1048     When called on a value, it runs all wrapped validators.
  2953     When called on a value, it runs all wrapped validators.
  1049 
  2954 
  1050     :param validators: Arbitrary number of validators.
  2955     :param callables validators: Arbitrary number of validators.
  1051     :type validators: callables
       
  1052 
  2956 
  1053     .. versionadded:: 17.1.0
  2957     .. versionadded:: 17.1.0
  1054     """
  2958     """
  1055     vals = []
  2959     vals = []
  1056     for validator in validators:
  2960     for validator in validators:
  1057         vals.extend(
  2961         vals.extend(
  1058             validator._validators if isinstance(validator, _AndValidator)
  2962             validator._validators
       
  2963             if isinstance(validator, _AndValidator)
  1059             else [validator]
  2964             else [validator]
  1060         )
  2965         )
  1061 
  2966 
  1062     return _AndValidator(tuple(vals))
  2967     return _AndValidator(tuple(vals))
       
  2968 
       
  2969 
       
  2970 def pipe(*converters):
       
  2971     """
       
  2972     A converter that composes multiple converters into one.
       
  2973 
       
  2974     When called on a value, it runs all wrapped converters, returning the
       
  2975     *last* value.
       
  2976 
       
  2977     Type annotations will be inferred from the wrapped converters', if
       
  2978     they have any.
       
  2979 
       
  2980     :param callables converters: Arbitrary number of converters.
       
  2981 
       
  2982     .. versionadded:: 20.1.0
       
  2983     """
       
  2984 
       
  2985     def pipe_converter(val):
       
  2986         for converter in converters:
       
  2987             val = converter(val)
       
  2988 
       
  2989         return val
       
  2990 
       
  2991     if not converters:
       
  2992         # If the converter list is empty, pipe_converter is the identity.
       
  2993         A = typing.TypeVar("A")
       
  2994         pipe_converter.__annotations__ = {"val": A, "return": A}
       
  2995     else:
       
  2996         # Get parameter type from first converter.
       
  2997         t = _AnnotationExtractor(converters[0]).get_first_param_type()
       
  2998         if t:
       
  2999             pipe_converter.__annotations__["val"] = t
       
  3000 
       
  3001         # Get return type from last converter.
       
  3002         rt = _AnnotationExtractor(converters[-1]).get_return_type()
       
  3003         if rt:
       
  3004             pipe_converter.__annotations__["return"] = rt
       
  3005 
       
  3006     return pipe_converter