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