comparison env/lib/python3.9/site-packages/attr/_make.py @ 0:4f3585e2f14b draft default tip

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