mercurial/thirdparty/attr/_make.py
author Manuel Jacob <me@manueljacob.de>
Thu, 15 Sep 2022 01:48:38 +0200
changeset 49494 c96ed4029fda
parent 41833 89f01ea906ae
child 49643 e1c586b9a43c
permissions -rw-r--r--
templates: add filter to reverse list The filter supports only lists because for lists, it’s straightforward to implement. Reversing text doesn’t seem very useful and is hard to implement. Reversing the bytes would break multi-bytes encodings. Reversing the code points would break characters consisting of multiple code points. Reversing graphemes is non-trivial without using a library not included in the standard library.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
34397
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     1
from __future__ import absolute_import, division, print_function
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     2
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     3
import hashlib
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     4
import linecache
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     5
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     6
from operator import itemgetter
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     7
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     8
from . import _config
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     9
from ._compat import PY2, iteritems, isclass, iterkeys, metadata_proxy
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    10
from .exceptions import (
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    11
    DefaultAlreadySetError,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    12
    FrozenInstanceError,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    13
    NotAnAttrsClassError,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    14
)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    15
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    16
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    17
# This is used at least twice, so cache it here.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    18
_obj_setattr = object.__setattr__
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    19
_init_convert_pat = "__attr_convert_{}"
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    20
_init_factory_pat = "__attr_factory_{}"
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    21
_tuple_property_pat = "    {attr_name} = property(itemgetter({index}))"
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    22
_empty_metadata_singleton = metadata_proxy({})
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    23
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    24
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    25
class _Nothing(object):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    26
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    27
    Sentinel class to indicate the lack of a value when ``None`` is ambiguous.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    28
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    29
    All instances of `_Nothing` are equal.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    30
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    31
    def __copy__(self):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    32
        return self
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    33
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    34
    def __deepcopy__(self, _):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    35
        return self
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    36
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    37
    def __eq__(self, other):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    38
        return other.__class__ == _Nothing
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    39
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    40
    def __ne__(self, other):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    41
        return not self == other
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    42
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    43
    def __repr__(self):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    44
        return "NOTHING"
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    45
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    46
    def __hash__(self):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    47
        return 0xdeadbeef
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    48
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    49
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    50
NOTHING = _Nothing()
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    51
"""
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    52
Sentinel to indicate the lack of a value when ``None`` is ambiguous.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    53
"""
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    54
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    55
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    56
def attr(default=NOTHING, validator=None,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    57
         repr=True, cmp=True, hash=None, init=True,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    58
         convert=None, metadata={}):
41564
a5493a251ad3 attr: make some docstrings raw strings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 34397
diff changeset
    59
    r"""
34397
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    60
    Create a new attribute on a class.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    61
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    62
    ..  warning::
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    63
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    64
        Does *not* do anything unless the class is also decorated with
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    65
        :func:`attr.s`!
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    66
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    67
    :param default: A value that is used if an ``attrs``-generated ``__init__``
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    68
        is used and no value is passed while instantiating or the attribute is
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    69
        excluded using ``init=False``.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    70
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    71
        If the value is an instance of :class:`Factory`, its callable will be
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    72
        used to construct a new value (useful for mutable datatypes like lists
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    73
        or dicts).
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    74
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    75
        If a default is not set (or set manually to ``attr.NOTHING``), a value
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    76
        *must* be supplied when instantiating; otherwise a :exc:`TypeError`
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    77
        will be raised.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    78
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    79
        The default can also be set using decorator notation as shown below.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    80
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    81
    :type default: Any value.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    82
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    83
    :param validator: :func:`callable` that is called by ``attrs``-generated
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    84
        ``__init__`` methods after the instance has been initialized.  They
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    85
        receive the initialized instance, the :class:`Attribute`, and the
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    86
        passed value.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    87
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    88
        The return value is *not* inspected so the validator has to throw an
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    89
        exception itself.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    90
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    91
        If a ``list`` is passed, its items are treated as validators and must
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    92
        all pass.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    93
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    94
        Validators can be globally disabled and re-enabled using
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    95
        :func:`get_run_validators`.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    96
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    97
        The validator can also be set using decorator notation as shown below.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    98
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    99
    :type validator: ``callable`` or a ``list`` of ``callable``\ s.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   100
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   101
    :param bool repr: Include this attribute in the generated ``__repr__``
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   102
        method.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   103
    :param bool cmp: Include this attribute in the generated comparison methods
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   104
        (``__eq__`` et al).
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   105
    :param hash: Include this attribute in the generated ``__hash__``
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   106
        method.  If ``None`` (default), mirror *cmp*'s value.  This is the
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   107
        correct behavior according the Python spec.  Setting this value to
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   108
        anything else than ``None`` is *discouraged*.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   109
    :type hash: ``bool`` or ``None``
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   110
    :param bool init: Include this attribute in the generated ``__init__``
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   111
        method.  It is possible to set this to ``False`` and set a default
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   112
        value.  In that case this attributed is unconditionally initialized
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   113
        with the specified default value or factory.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   114
    :param callable convert: :func:`callable` that is called by
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   115
        ``attrs``-generated ``__init__`` methods to convert attribute's value
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   116
        to the desired format.  It is given the passed-in value, and the
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   117
        returned value will be used as the new value of the attribute.  The
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   118
        value is converted before being passed to the validator, if any.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   119
    :param metadata: An arbitrary mapping, to be used by third-party
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   120
        components.  See :ref:`extending_metadata`.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   121
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   122
    ..  versionchanged:: 17.1.0 *validator* can be a ``list`` now.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   123
    ..  versionchanged:: 17.1.0
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   124
        *hash* is ``None`` and therefore mirrors *cmp* by default .
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   125
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   126
    if hash is not None and hash is not True and hash is not False:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   127
        raise TypeError(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   128
            "Invalid value for hash.  Must be True, False, or None."
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   129
        )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   130
    return _CountingAttr(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   131
        default=default,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   132
        validator=validator,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   133
        repr=repr,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   134
        cmp=cmp,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   135
        hash=hash,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   136
        init=init,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   137
        convert=convert,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   138
        metadata=metadata,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   139
    )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   140
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   141
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   142
def _make_attr_tuple_class(cls_name, attr_names):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   143
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   144
    Create a tuple subclass to hold `Attribute`s for an `attrs` class.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   145
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   146
    The subclass is a bare tuple with properties for names.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   147
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   148
    class MyClassAttributes(tuple):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   149
        __slots__ = ()
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   150
        x = property(itemgetter(0))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   151
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   152
    attr_class_name = "{}Attributes".format(cls_name)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   153
    attr_class_template = [
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   154
        "class {}(tuple):".format(attr_class_name),
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   155
        "    __slots__ = ()",
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   156
    ]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   157
    if attr_names:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   158
        for i, attr_name in enumerate(attr_names):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   159
            attr_class_template.append(_tuple_property_pat.format(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   160
                index=i,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   161
                attr_name=attr_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   162
            ))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   163
    else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   164
        attr_class_template.append("    pass")
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   165
    globs = {"itemgetter": itemgetter}
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   166
    eval(compile("\n".join(attr_class_template), "", "exec"), globs)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   167
    return globs[attr_class_name]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   168
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   169
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   170
def _transform_attrs(cls, these):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   171
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   172
    Transforms all `_CountingAttr`s on a class into `Attribute`s and saves the
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   173
    list in `__attrs_attrs__`.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   174
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   175
    If *these* is passed, use that and don't look for them on the class.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   176
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   177
    super_cls = []
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   178
    for c in reversed(cls.__mro__[1:-1]):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   179
        sub_attrs = getattr(c, "__attrs_attrs__", None)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   180
        if sub_attrs is not None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   181
            super_cls.extend(a for a in sub_attrs if a not in super_cls)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   182
    if these is None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   183
        ca_list = [(name, attr)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   184
                   for name, attr
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   185
                   in cls.__dict__.items()
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   186
                   if isinstance(attr, _CountingAttr)]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   187
    else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   188
        ca_list = [(name, ca)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   189
                   for name, ca
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   190
                   in iteritems(these)]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   191
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   192
    non_super_attrs = [
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   193
        Attribute.from_counting_attr(name=attr_name, ca=ca)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   194
        for attr_name, ca
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   195
        in sorted(ca_list, key=lambda e: e[1].counter)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   196
    ]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   197
    attr_names = [a.name for a in super_cls + non_super_attrs]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   198
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   199
    AttrsClass = _make_attr_tuple_class(cls.__name__, attr_names)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   200
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   201
    cls.__attrs_attrs__ = AttrsClass(super_cls + [
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   202
        Attribute.from_counting_attr(name=attr_name, ca=ca)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   203
        for attr_name, ca
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   204
        in sorted(ca_list, key=lambda e: e[1].counter)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   205
    ])
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   206
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   207
    had_default = False
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   208
    for a in cls.__attrs_attrs__:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   209
        if these is None and a not in super_cls:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   210
            setattr(cls, a.name, a)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   211
        if had_default is True and a.default is NOTHING and a.init is True:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   212
            raise ValueError(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   213
                "No mandatory attributes allowed after an attribute with a "
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   214
                "default value or factory.  Attribute in question: {a!r}"
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   215
                .format(a=a)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   216
            )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   217
        elif had_default is False and \
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   218
                a.default is not NOTHING and \
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   219
                a.init is not False:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   220
            had_default = True
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   221
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   222
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   223
def _frozen_setattrs(self, name, value):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   224
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   225
    Attached to frozen classes as __setattr__.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   226
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   227
    raise FrozenInstanceError()
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   228
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   229
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   230
def _frozen_delattrs(self, name):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   231
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   232
    Attached to frozen classes as __delattr__.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   233
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   234
    raise FrozenInstanceError()
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   235
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   236
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   237
def attributes(maybe_cls=None, these=None, repr_ns=None,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   238
               repr=True, cmp=True, hash=None, init=True,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   239
               slots=False, frozen=False, str=False):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   240
    r"""
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   241
    A class decorator that adds `dunder
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   242
    <https://wiki.python.org/moin/DunderAlias>`_\ -methods according to the
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   243
    specified attributes using :func:`attr.ib` or the *these* argument.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   244
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   245
    :param these: A dictionary of name to :func:`attr.ib` mappings.  This is
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   246
        useful to avoid the definition of your attributes within the class body
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   247
        because you can't (e.g. if you want to add ``__repr__`` methods to
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   248
        Django models) or don't want to.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   249
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   250
        If *these* is not ``None``, ``attrs`` will *not* search the class body
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   251
        for attributes.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   252
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   253
    :type these: :class:`dict` of :class:`str` to :func:`attr.ib`
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   254
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   255
    :param str repr_ns: When using nested classes, there's no way in Python 2
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   256
        to automatically detect that.  Therefore it's possible to set the
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   257
        namespace explicitly for a more meaningful ``repr`` output.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   258
    :param bool repr: Create a ``__repr__`` method with a human readable
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   259
        represantation of ``attrs`` attributes..
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   260
    :param bool str: Create a ``__str__`` method that is identical to
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   261
        ``__repr__``.  This is usually not necessary except for
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   262
        :class:`Exception`\ s.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   263
    :param bool cmp: Create ``__eq__``, ``__ne__``, ``__lt__``, ``__le__``,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   264
        ``__gt__``, and ``__ge__`` methods that compare the class as if it were
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   265
        a tuple of its ``attrs`` attributes.  But the attributes are *only*
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   266
        compared, if the type of both classes is *identical*!
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   267
    :param hash: If ``None`` (default), the ``__hash__`` method is generated
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   268
        according how *cmp* and *frozen* are set.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   269
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   270
        1. If *both* are True, ``attrs`` will generate a ``__hash__`` for you.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   271
        2. If *cmp* is True and *frozen* is False, ``__hash__`` will be set to
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   272
           None, marking it unhashable (which it is).
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   273
        3. If *cmp* is False, ``__hash__`` will be left untouched meaning the
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   274
           ``__hash__`` method of the superclass will be used (if superclass is
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   275
           ``object``, this means it will fall back to id-based hashing.).
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   276
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   277
        Although not recommended, you can decide for yourself and force
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   278
        ``attrs`` to create one (e.g. if the class is immutable even though you
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   279
        didn't freeze it programmatically) by passing ``True`` or not.  Both of
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   280
        these cases are rather special and should be used carefully.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   281
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   282
        See the `Python documentation \
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   283
        <https://docs.python.org/3/reference/datamodel.html#object.__hash__>`_
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   284
        and the `GitHub issue that led to the default behavior \
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   285
        <https://github.com/python-attrs/attrs/issues/136>`_ for more details.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   286
    :type hash: ``bool`` or ``None``
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   287
    :param bool init: Create a ``__init__`` method that initialiazes the
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   288
        ``attrs`` attributes.  Leading underscores are stripped for the
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   289
        argument name.  If a ``__attrs_post_init__`` method exists on the
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   290
        class, it will be called after the class is fully initialized.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   291
    :param bool slots: Create a slots_-style class that's more
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   292
        memory-efficient.  See :ref:`slots` for further ramifications.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   293
    :param bool frozen: Make instances immutable after initialization.  If
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   294
        someone attempts to modify a frozen instance,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   295
        :exc:`attr.exceptions.FrozenInstanceError` is raised.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   296
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   297
        Please note:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   298
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   299
            1. This is achieved by installing a custom ``__setattr__`` method
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   300
               on your class so you can't implement an own one.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   301
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   302
            2. True immutability is impossible in Python.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   303
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   304
            3. This *does* have a minor a runtime performance :ref:`impact
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   305
               <how-frozen>` when initializing new instances.  In other words:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   306
               ``__init__`` is slightly slower with ``frozen=True``.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   307
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   308
            4. If a class is frozen, you cannot modify ``self`` in
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   309
               ``__attrs_post_init__`` or a self-written ``__init__``. You can
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   310
               circumvent that limitation by using
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   311
               ``object.__setattr__(self, "attribute_name", value)``.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   312
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   313
        ..  _slots: https://docs.python.org/3.5/reference/datamodel.html#slots
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   314
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   315
    ..  versionadded:: 16.0.0 *slots*
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   316
    ..  versionadded:: 16.1.0 *frozen*
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   317
    ..  versionadded:: 16.3.0 *str*, and support for ``__attrs_post_init__``.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   318
    ..  versionchanged::
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   319
            17.1.0 *hash* supports ``None`` as value which is also the default
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   320
            now.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   321
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   322
    def wrap(cls):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   323
        if getattr(cls, "__class__", None) is None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   324
            raise TypeError("attrs only works with new-style classes.")
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   325
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   326
        if repr is False and str is True:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   327
            raise ValueError(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   328
                "__str__ can only be generated if a __repr__ exists."
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   329
            )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   330
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   331
        if slots:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   332
            # Only need this later if we're using slots.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   333
            if these is None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   334
                ca_list = [name
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   335
                           for name, attr
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   336
                           in cls.__dict__.items()
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   337
                           if isinstance(attr, _CountingAttr)]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   338
            else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   339
                ca_list = list(iterkeys(these))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   340
        _transform_attrs(cls, these)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   341
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   342
        # Can't just re-use frozen name because Python's scoping. :(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   343
        # Can't compare function objects because Python 2 is terrible. :(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   344
        effectively_frozen = _has_frozen_superclass(cls) or frozen
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   345
        if repr is True:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   346
            cls = _add_repr(cls, ns=repr_ns)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   347
        if str is True:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   348
            cls.__str__ = cls.__repr__
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   349
        if cmp is True:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   350
            cls = _add_cmp(cls)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   351
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   352
        if hash is not True and hash is not False and hash is not None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   353
            raise TypeError(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   354
                "Invalid value for hash.  Must be True, False, or None."
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   355
            )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   356
        elif hash is False or (hash is None and cmp is False):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   357
            pass
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   358
        elif hash is True or (hash is None and cmp is True and frozen is True):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   359
            cls = _add_hash(cls)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   360
        else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   361
            cls.__hash__ = None
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   362
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   363
        if init is True:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   364
            cls = _add_init(cls, effectively_frozen)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   365
        if effectively_frozen is True:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   366
            cls.__setattr__ = _frozen_setattrs
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   367
            cls.__delattr__ = _frozen_delattrs
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   368
            if slots is True:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   369
                # slots and frozen require __getstate__/__setstate__ to work
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   370
                cls = _add_pickle(cls)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   371
        if slots is True:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   372
            cls_dict = dict(cls.__dict__)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   373
            cls_dict["__slots__"] = tuple(ca_list)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   374
            for ca_name in ca_list:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   375
                # It might not actually be in there, e.g. if using 'these'.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   376
                cls_dict.pop(ca_name, None)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   377
            cls_dict.pop("__dict__", None)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   378
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   379
            qualname = getattr(cls, "__qualname__", None)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   380
            cls = type(cls)(cls.__name__, cls.__bases__, cls_dict)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   381
            if qualname is not None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   382
                cls.__qualname__ = qualname
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   383
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   384
        return cls
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   385
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   386
    # attrs_or class type depends on the usage of the decorator.  It's a class
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   387
    # if it's used as `@attributes` but ``None`` if used # as `@attributes()`.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   388
    if maybe_cls is None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   389
        return wrap
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   390
    else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   391
        return wrap(maybe_cls)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   392
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   393
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   394
if PY2:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   395
    def _has_frozen_superclass(cls):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   396
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   397
        Check whether *cls* has a frozen ancestor by looking at its
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   398
        __setattr__.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   399
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   400
        return (
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   401
            getattr(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   402
                cls.__setattr__, "__module__", None
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   403
            ) == _frozen_setattrs.__module__ and
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   404
            cls.__setattr__.__name__ == _frozen_setattrs.__name__
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   405
        )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   406
else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   407
    def _has_frozen_superclass(cls):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   408
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   409
        Check whether *cls* has a frozen ancestor by looking at its
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   410
        __setattr__.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   411
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   412
        return cls.__setattr__ == _frozen_setattrs
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   413
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   414
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   415
def _attrs_to_tuple(obj, attrs):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   416
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   417
    Create a tuple of all values of *obj*'s *attrs*.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   418
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   419
    return tuple(getattr(obj, a.name) for a in attrs)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   420
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   421
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   422
def _add_hash(cls, attrs=None):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   423
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   424
    Add a hash method to *cls*.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   425
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   426
    if attrs is None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   427
        attrs = [a
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   428
                 for a in cls.__attrs_attrs__
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   429
                 if a.hash is True or (a.hash is None and a.cmp is True)]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   430
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   431
    def hash_(self):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   432
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   433
        Automatically created by attrs.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   434
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   435
        return hash(_attrs_to_tuple(self, attrs))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   436
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   437
    cls.__hash__ = hash_
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   438
    return cls
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   439
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   440
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   441
def _add_cmp(cls, attrs=None):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   442
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   443
    Add comparison methods to *cls*.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   444
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   445
    if attrs is None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   446
        attrs = [a for a in cls.__attrs_attrs__ if a.cmp]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   447
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   448
    def attrs_to_tuple(obj):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   449
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   450
        Save us some typing.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   451
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   452
        return _attrs_to_tuple(obj, attrs)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   453
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   454
    def eq(self, other):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   455
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   456
        Automatically created by attrs.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   457
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   458
        if other.__class__ is self.__class__:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   459
            return attrs_to_tuple(self) == attrs_to_tuple(other)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   460
        else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   461
            return NotImplemented
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   462
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   463
    def ne(self, other):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   464
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   465
        Automatically created by attrs.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   466
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   467
        result = eq(self, other)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   468
        if result is NotImplemented:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   469
            return NotImplemented
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   470
        else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   471
            return not result
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   472
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   473
    def lt(self, other):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   474
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   475
        Automatically created by attrs.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   476
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   477
        if isinstance(other, self.__class__):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   478
            return attrs_to_tuple(self) < attrs_to_tuple(other)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   479
        else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   480
            return NotImplemented
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   481
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   482
    def le(self, other):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   483
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   484
        Automatically created by attrs.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   485
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   486
        if isinstance(other, self.__class__):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   487
            return attrs_to_tuple(self) <= attrs_to_tuple(other)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   488
        else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   489
            return NotImplemented
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   490
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   491
    def gt(self, other):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   492
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   493
        Automatically created by attrs.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   494
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   495
        if isinstance(other, self.__class__):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   496
            return attrs_to_tuple(self) > attrs_to_tuple(other)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   497
        else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   498
            return NotImplemented
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   499
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   500
    def ge(self, other):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   501
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   502
        Automatically created by attrs.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   503
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   504
        if isinstance(other, self.__class__):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   505
            return attrs_to_tuple(self) >= attrs_to_tuple(other)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   506
        else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   507
            return NotImplemented
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   508
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   509
    cls.__eq__ = eq
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   510
    cls.__ne__ = ne
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   511
    cls.__lt__ = lt
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   512
    cls.__le__ = le
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   513
    cls.__gt__ = gt
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   514
    cls.__ge__ = ge
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   515
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   516
    return cls
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   517
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   518
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   519
def _add_repr(cls, ns=None, attrs=None):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   520
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   521
    Add a repr method to *cls*.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   522
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   523
    if attrs is None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   524
        attrs = [a for a in cls.__attrs_attrs__ if a.repr]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   525
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   526
    def repr_(self):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   527
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   528
        Automatically created by attrs.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   529
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   530
        real_cls = self.__class__
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   531
        if ns is None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   532
            qualname = getattr(real_cls, "__qualname__", None)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   533
            if qualname is not None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   534
                class_name = qualname.rsplit(">.", 1)[-1]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   535
            else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   536
                class_name = real_cls.__name__
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   537
        else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   538
            class_name = ns + "." + real_cls.__name__
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   539
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   540
        return "{0}({1})".format(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   541
            class_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   542
            ", ".join(a.name + "=" + repr(getattr(self, a.name))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   543
                      for a in attrs)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   544
        )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   545
    cls.__repr__ = repr_
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   546
    return cls
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   547
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   548
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   549
def _add_init(cls, frozen):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   550
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   551
    Add a __init__ method to *cls*.  If *frozen* is True, make it immutable.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   552
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   553
    attrs = [a for a in cls.__attrs_attrs__
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   554
             if a.init or a.default is not NOTHING]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   555
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   556
    # We cache the generated init methods for the same kinds of attributes.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   557
    sha1 = hashlib.sha1()
41833
89f01ea906ae attr: don't attempt to .encode() a str on Python 2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41564
diff changeset
   558
    r = repr(attrs)
89f01ea906ae attr: don't attempt to .encode() a str on Python 2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41564
diff changeset
   559
    if not isinstance(r, bytes):
89f01ea906ae attr: don't attempt to .encode() a str on Python 2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41564
diff changeset
   560
        r = r.encode('utf-8')
89f01ea906ae attr: don't attempt to .encode() a str on Python 2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41564
diff changeset
   561
    sha1.update(r)
34397
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   562
    unique_filename = "<attrs generated init {0}>".format(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   563
        sha1.hexdigest()
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   564
    )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   565
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   566
    script, globs = _attrs_to_script(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   567
        attrs,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   568
        frozen,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   569
        getattr(cls, "__attrs_post_init__", False),
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   570
    )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   571
    locs = {}
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   572
    bytecode = compile(script, unique_filename, "exec")
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   573
    attr_dict = dict((a.name, a) for a in attrs)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   574
    globs.update({
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   575
        "NOTHING": NOTHING,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   576
        "attr_dict": attr_dict,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   577
    })
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   578
    if frozen is True:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   579
        # Save the lookup overhead in __init__ if we need to circumvent
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   580
        # immutability.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   581
        globs["_cached_setattr"] = _obj_setattr
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   582
    eval(bytecode, globs, locs)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   583
    init = locs["__init__"]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   584
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   585
    # In order of debuggers like PDB being able to step through the code,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   586
    # we add a fake linecache entry.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   587
    linecache.cache[unique_filename] = (
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   588
        len(script),
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   589
        None,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   590
        script.splitlines(True),
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   591
        unique_filename
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   592
    )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   593
    cls.__init__ = init
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   594
    return cls
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   595
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   596
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   597
def _add_pickle(cls):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   598
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   599
    Add pickle helpers, needed for frozen and slotted classes
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   600
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   601
    def _slots_getstate__(obj):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   602
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   603
        Play nice with pickle.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   604
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   605
        return tuple(getattr(obj, a.name) for a in fields(obj.__class__))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   606
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   607
    def _slots_setstate__(obj, state):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   608
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   609
        Play nice with pickle.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   610
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   611
        __bound_setattr = _obj_setattr.__get__(obj, Attribute)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   612
        for a, value in zip(fields(obj.__class__), state):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   613
            __bound_setattr(a.name, value)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   614
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   615
    cls.__getstate__ = _slots_getstate__
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   616
    cls.__setstate__ = _slots_setstate__
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   617
    return cls
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   618
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   619
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   620
def fields(cls):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   621
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   622
    Returns the tuple of ``attrs`` attributes for a class.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   623
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   624
    The tuple also allows accessing the fields by their names (see below for
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   625
    examples).
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   626
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   627
    :param type cls: Class to introspect.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   628
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   629
    :raise TypeError: If *cls* is not a class.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   630
    :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   631
        class.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   632
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   633
    :rtype: tuple (with name accesors) of :class:`attr.Attribute`
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   634
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   635
    ..  versionchanged:: 16.2.0 Returned tuple allows accessing the fields
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   636
        by name.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   637
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   638
    if not isclass(cls):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   639
        raise TypeError("Passed object must be a class.")
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   640
    attrs = getattr(cls, "__attrs_attrs__", None)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   641
    if attrs is None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   642
        raise NotAnAttrsClassError(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   643
            "{cls!r} is not an attrs-decorated class.".format(cls=cls)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   644
        )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   645
    return attrs
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   646
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   647
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   648
def validate(inst):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   649
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   650
    Validate all attributes on *inst* that have a validator.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   651
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   652
    Leaves all exceptions through.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   653
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   654
    :param inst: Instance of a class with ``attrs`` attributes.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   655
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   656
    if _config._run_validators is False:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   657
        return
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   658
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   659
    for a in fields(inst.__class__):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   660
        v = a.validator
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   661
        if v is not None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   662
            v(inst, a, getattr(inst, a.name))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   663
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   664
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   665
def _attrs_to_script(attrs, frozen, post_init):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   666
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   667
    Return a script of an initializer for *attrs* and a dict of globals.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   668
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   669
    The globals are expected by the generated script.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   670
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   671
     If *frozen* is True, we cannot set the attributes directly so we use
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   672
    a cached ``object.__setattr__``.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   673
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   674
    lines = []
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   675
    if frozen is True:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   676
        lines.append(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   677
            # Circumvent the __setattr__ descriptor to save one lookup per
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   678
            # assignment.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   679
            "_setattr = _cached_setattr.__get__(self, self.__class__)"
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   680
        )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   681
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   682
        def fmt_setter(attr_name, value_var):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   683
            return "_setattr('%(attr_name)s', %(value_var)s)" % {
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   684
                "attr_name": attr_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   685
                "value_var": value_var,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   686
            }
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   687
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   688
        def fmt_setter_with_converter(attr_name, value_var):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   689
            conv_name = _init_convert_pat.format(attr_name)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   690
            return "_setattr('%(attr_name)s', %(conv)s(%(value_var)s))" % {
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   691
                "attr_name": attr_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   692
                "value_var": value_var,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   693
                "conv": conv_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   694
            }
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   695
    else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   696
        def fmt_setter(attr_name, value):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   697
            return "self.%(attr_name)s = %(value)s" % {
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   698
                "attr_name": attr_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   699
                "value": value,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   700
            }
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   701
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   702
        def fmt_setter_with_converter(attr_name, value_var):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   703
            conv_name = _init_convert_pat.format(attr_name)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   704
            return "self.%(attr_name)s = %(conv)s(%(value_var)s)" % {
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   705
                "attr_name": attr_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   706
                "value_var": value_var,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   707
                "conv": conv_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   708
            }
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   709
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   710
    args = []
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   711
    attrs_to_validate = []
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   712
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   713
    # This is a dictionary of names to validator and converter callables.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   714
    # Injecting this into __init__ globals lets us avoid lookups.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   715
    names_for_globals = {}
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   716
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   717
    for a in attrs:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   718
        if a.validator:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   719
            attrs_to_validate.append(a)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   720
        attr_name = a.name
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   721
        arg_name = a.name.lstrip("_")
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   722
        has_factory = isinstance(a.default, Factory)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   723
        if has_factory and a.default.takes_self:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   724
            maybe_self = "self"
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   725
        else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   726
            maybe_self = ""
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   727
        if a.init is False:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   728
            if has_factory:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   729
                init_factory_name = _init_factory_pat.format(a.name)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   730
                if a.convert is not None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   731
                    lines.append(fmt_setter_with_converter(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   732
                        attr_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   733
                        init_factory_name + "({0})".format(maybe_self)))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   734
                    conv_name = _init_convert_pat.format(a.name)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   735
                    names_for_globals[conv_name] = a.convert
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   736
                else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   737
                    lines.append(fmt_setter(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   738
                        attr_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   739
                        init_factory_name + "({0})".format(maybe_self)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   740
                    ))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   741
                names_for_globals[init_factory_name] = a.default.factory
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   742
            else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   743
                if a.convert is not None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   744
                    lines.append(fmt_setter_with_converter(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   745
                        attr_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   746
                        "attr_dict['{attr_name}'].default"
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   747
                        .format(attr_name=attr_name)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   748
                    ))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   749
                    conv_name = _init_convert_pat.format(a.name)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   750
                    names_for_globals[conv_name] = a.convert
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   751
                else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   752
                    lines.append(fmt_setter(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   753
                        attr_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   754
                        "attr_dict['{attr_name}'].default"
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   755
                        .format(attr_name=attr_name)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   756
                    ))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   757
        elif a.default is not NOTHING and not has_factory:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   758
            args.append(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   759
                "{arg_name}=attr_dict['{attr_name}'].default".format(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   760
                    arg_name=arg_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   761
                    attr_name=attr_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   762
                )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   763
            )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   764
            if a.convert is not None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   765
                lines.append(fmt_setter_with_converter(attr_name, arg_name))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   766
                names_for_globals[_init_convert_pat.format(a.name)] = a.convert
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   767
            else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   768
                lines.append(fmt_setter(attr_name, arg_name))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   769
        elif has_factory:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   770
            args.append("{arg_name}=NOTHING".format(arg_name=arg_name))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   771
            lines.append("if {arg_name} is not NOTHING:"
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   772
                         .format(arg_name=arg_name))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   773
            init_factory_name = _init_factory_pat.format(a.name)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   774
            if a.convert is not None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   775
                lines.append("    " + fmt_setter_with_converter(attr_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   776
                                                                arg_name))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   777
                lines.append("else:")
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   778
                lines.append("    " + fmt_setter_with_converter(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   779
                    attr_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   780
                    init_factory_name + "({0})".format(maybe_self)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   781
                ))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   782
                names_for_globals[_init_convert_pat.format(a.name)] = a.convert
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   783
            else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   784
                lines.append("    " + fmt_setter(attr_name, arg_name))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   785
                lines.append("else:")
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   786
                lines.append("    " + fmt_setter(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   787
                    attr_name,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   788
                    init_factory_name + "({0})".format(maybe_self)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   789
                ))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   790
            names_for_globals[init_factory_name] = a.default.factory
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   791
        else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   792
            args.append(arg_name)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   793
            if a.convert is not None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   794
                lines.append(fmt_setter_with_converter(attr_name, arg_name))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   795
                names_for_globals[_init_convert_pat.format(a.name)] = a.convert
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   796
            else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   797
                lines.append(fmt_setter(attr_name, arg_name))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   798
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   799
    if attrs_to_validate:  # we can skip this if there are no validators.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   800
        names_for_globals["_config"] = _config
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   801
        lines.append("if _config._run_validators is True:")
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   802
        for a in attrs_to_validate:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   803
            val_name = "__attr_validator_{}".format(a.name)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   804
            attr_name = "__attr_{}".format(a.name)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   805
            lines.append("    {}(self, {}, self.{})".format(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   806
                val_name, attr_name, a.name))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   807
            names_for_globals[val_name] = a.validator
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   808
            names_for_globals[attr_name] = a
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   809
    if post_init:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   810
        lines.append("self.__attrs_post_init__()")
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   811
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   812
    return """\
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   813
def __init__(self, {args}):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   814
    {lines}
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   815
""".format(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   816
        args=", ".join(args),
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   817
        lines="\n    ".join(lines) if lines else "pass",
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   818
    ), names_for_globals
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   819
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   820
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   821
class Attribute(object):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   822
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   823
    *Read-only* representation of an attribute.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   824
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   825
    :attribute name: The name of the attribute.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   826
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   827
    Plus *all* arguments of :func:`attr.ib`.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   828
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   829
    __slots__ = (
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   830
        "name", "default", "validator", "repr", "cmp", "hash", "init",
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   831
        "convert", "metadata",
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   832
    )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   833
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   834
    def __init__(self, name, default, validator, repr, cmp, hash, init,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   835
                 convert=None, metadata=None):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   836
        # Cache this descriptor here to speed things up later.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   837
        bound_setattr = _obj_setattr.__get__(self, Attribute)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   838
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   839
        bound_setattr("name", name)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   840
        bound_setattr("default", default)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   841
        bound_setattr("validator", validator)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   842
        bound_setattr("repr", repr)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   843
        bound_setattr("cmp", cmp)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   844
        bound_setattr("hash", hash)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   845
        bound_setattr("init", init)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   846
        bound_setattr("convert", convert)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   847
        bound_setattr("metadata", (metadata_proxy(metadata) if metadata
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   848
                                   else _empty_metadata_singleton))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   849
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   850
    def __setattr__(self, name, value):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   851
        raise FrozenInstanceError()
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   852
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   853
    @classmethod
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   854
    def from_counting_attr(cls, name, ca):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   855
        inst_dict = {
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   856
            k: getattr(ca, k)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   857
            for k
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   858
            in Attribute.__slots__
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   859
            if k not in (
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   860
                "name", "validator", "default",
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   861
            )  # exclude methods
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   862
        }
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   863
        return cls(name=name, validator=ca._validator, default=ca._default,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   864
                   **inst_dict)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   865
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   866
    # Don't use _add_pickle since fields(Attribute) doesn't work
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   867
    def __getstate__(self):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   868
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   869
        Play nice with pickle.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   870
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   871
        return tuple(getattr(self, name) if name != "metadata"
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   872
                     else dict(self.metadata)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   873
                     for name in self.__slots__)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   874
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   875
    def __setstate__(self, state):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   876
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   877
        Play nice with pickle.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   878
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   879
        bound_setattr = _obj_setattr.__get__(self, Attribute)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   880
        for name, value in zip(self.__slots__, state):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   881
            if name != "metadata":
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   882
                bound_setattr(name, value)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   883
            else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   884
                bound_setattr(name, metadata_proxy(value) if value else
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   885
                              _empty_metadata_singleton)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   886
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   887
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   888
_a = [Attribute(name=name, default=NOTHING, validator=None,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   889
                repr=True, cmp=True, hash=(name != "metadata"), init=True)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   890
      for name in Attribute.__slots__]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   891
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   892
Attribute = _add_hash(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   893
    _add_cmp(_add_repr(Attribute, attrs=_a), attrs=_a),
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   894
    attrs=[a for a in _a if a.hash]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   895
)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   896
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   897
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   898
class _CountingAttr(object):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   899
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   900
    Intermediate representation of attributes that uses a counter to preserve
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   901
    the order in which the attributes have been defined.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   902
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   903
    *Internal* data structure of the attrs library.  Running into is most
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   904
    likely the result of a bug like a forgotten `@attr.s` decorator.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   905
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   906
    __slots__ = ("counter", "_default", "repr", "cmp", "hash", "init",
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   907
                 "metadata", "_validator", "convert")
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   908
    __attrs_attrs__ = tuple(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   909
        Attribute(name=name, default=NOTHING, validator=None,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   910
                  repr=True, cmp=True, hash=True, init=True)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   911
        for name
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   912
        in ("counter", "_default", "repr", "cmp", "hash", "init",)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   913
    ) + (
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   914
        Attribute(name="metadata", default=None, validator=None,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   915
                  repr=True, cmp=True, hash=False, init=True),
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   916
    )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   917
    cls_counter = 0
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   918
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   919
    def __init__(self, default, validator, repr, cmp, hash, init, convert,
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   920
                 metadata):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   921
        _CountingAttr.cls_counter += 1
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   922
        self.counter = _CountingAttr.cls_counter
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   923
        self._default = default
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   924
        # If validator is a list/tuple, wrap it using helper validator.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   925
        if validator and isinstance(validator, (list, tuple)):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   926
            self._validator = and_(*validator)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   927
        else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   928
            self._validator = validator
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   929
        self.repr = repr
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   930
        self.cmp = cmp
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   931
        self.hash = hash
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   932
        self.init = init
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   933
        self.convert = convert
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   934
        self.metadata = metadata
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   935
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   936
    def validator(self, meth):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   937
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   938
        Decorator that adds *meth* to the list of validators.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   939
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   940
        Returns *meth* unchanged.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   941
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   942
        .. versionadded:: 17.1.0
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   943
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   944
        if self._validator is None:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   945
            self._validator = meth
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   946
        else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   947
            self._validator = and_(self._validator, meth)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   948
        return meth
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   949
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   950
    def default(self, meth):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   951
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   952
        Decorator that allows to set the default for an attribute.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   953
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   954
        Returns *meth* unchanged.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   955
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   956
        :raises DefaultAlreadySetError: If default has been set before.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   957
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   958
        .. versionadded:: 17.1.0
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   959
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   960
        if self._default is not NOTHING:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   961
            raise DefaultAlreadySetError()
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   962
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   963
        self._default = Factory(meth, takes_self=True)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   964
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   965
        return meth
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   966
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   967
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   968
_CountingAttr = _add_cmp(_add_repr(_CountingAttr))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   969
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   970
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   971
@attributes(slots=True, init=False)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   972
class Factory(object):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   973
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   974
    Stores a factory callable.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   975
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   976
    If passed as the default value to :func:`attr.ib`, the factory is used to
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   977
    generate a new value.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   978
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   979
    :param callable factory: A callable that takes either none or exactly one
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   980
        mandatory positional argument depending on *takes_self*.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   981
    :param bool takes_self: Pass the partially initialized instance that is
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   982
        being initialized as a positional argument.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   983
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   984
    .. versionadded:: 17.1.0  *takes_self*
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   985
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   986
    factory = attr()
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   987
    takes_self = attr()
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   988
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   989
    def __init__(self, factory, takes_self=False):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   990
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   991
        `Factory` is part of the default machinery so if we want a default
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   992
        value here, we have to implement it ourselves.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   993
        """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   994
        self.factory = factory
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   995
        self.takes_self = takes_self
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   996
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   997
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   998
def make_class(name, attrs, bases=(object,), **attributes_arguments):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
   999
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1000
    A quick way to create a new class called *name* with *attrs*.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1001
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1002
    :param name: The name for the new class.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1003
    :type name: str
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1004
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1005
    :param attrs: A list of names or a dictionary of mappings of names to
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1006
        attributes.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1007
    :type attrs: :class:`list` or :class:`dict`
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1008
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1009
    :param tuple bases: Classes that the new class will subclass.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1010
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1011
    :param attributes_arguments: Passed unmodified to :func:`attr.s`.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1012
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1013
    :return: A new class with *attrs*.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1014
    :rtype: type
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1015
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1016
    ..  versionadded:: 17.1.0 *bases*
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1017
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1018
    if isinstance(attrs, dict):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1019
        cls_dict = attrs
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1020
    elif isinstance(attrs, (list, tuple)):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1021
        cls_dict = dict((a, attr()) for a in attrs)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1022
    else:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1023
        raise TypeError("attrs argument must be a dict or a list.")
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1024
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1025
    return attributes(**attributes_arguments)(type(name, bases, cls_dict))
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1026
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1027
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1028
# These are required by whithin this module so we define them here and merely
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1029
# import into .validators.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1030
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1031
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1032
@attributes(slots=True, hash=True)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1033
class _AndValidator(object):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1034
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1035
    Compose many validators to a single one.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1036
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1037
    _validators = attr()
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1038
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1039
    def __call__(self, inst, attr, value):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1040
        for v in self._validators:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1041
            v(inst, attr, value)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1042
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1043
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1044
def and_(*validators):
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1045
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1046
    A validator that composes multiple validators into one.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1047
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1048
    When called on a value, it runs all wrapped validators.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1049
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1050
    :param validators: Arbitrary number of validators.
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1051
    :type validators: callables
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1052
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1053
    .. versionadded:: 17.1.0
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1054
    """
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1055
    vals = []
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1056
    for validator in validators:
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1057
        vals.extend(
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1058
            validator._validators if isinstance(validator, _AndValidator)
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1059
            else [validator]
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1060
        )
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1061
765eb17a7eb8 thirdparty: vendor attrs
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
  1062
    return _AndValidator(tuple(vals))