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