Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/attr/_make.py: 69%

907 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-08 06:51 +0000

1# SPDX-License-Identifier: MIT 

2 

3import copy 

4import enum 

5import linecache 

6import sys 

7import types 

8import typing 

9 

10from operator import itemgetter 

11 

12# We need to import _compat itself in addition to the _compat members to avoid 

13# having the thread-local in the globals here. 

14from . import _compat, _config, setters 

15from ._compat import ( 

16 PY310, 

17 _AnnotationExtractor, 

18 get_generic_base, 

19 set_closure_cell, 

20) 

21from .exceptions import ( 

22 DefaultAlreadySetError, 

23 FrozenInstanceError, 

24 NotAnAttrsClassError, 

25 UnannotatedAttributeError, 

26) 

27 

28 

29# This is used at least twice, so cache it here. 

30_obj_setattr = object.__setattr__ 

31_init_converter_pat = "__attr_converter_%s" 

32_init_factory_pat = "__attr_factory_%s" 

33_classvar_prefixes = ( 

34 "typing.ClassVar", 

35 "t.ClassVar", 

36 "ClassVar", 

37 "typing_extensions.ClassVar", 

38) 

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 = types.MappingProxyType({}) 

45 

46# Unique object for unequivocal getattr() defaults. 

47_sentinel = object() 

48 

49_ng_default_on_setattr = setters.pipe(setters.convert, setters.validate) 

50 

51 

52class _Nothing(enum.Enum): 

53 """ 

54 Sentinel to indicate the lack of a value when ``None`` is ambiguous. 

55 

56 If extending attrs, you can use ``typing.Literal[NOTHING]`` to show 

57 that a value may be ``NOTHING``. 

58 

59 .. versionchanged:: 21.1.0 ``bool(NOTHING)`` is now False. 

60 .. versionchanged:: 22.2.0 ``NOTHING`` is now an ``enum.Enum`` variant. 

61 """ 

62 

63 NOTHING = enum.auto() 

64 

65 def __repr__(self): 

66 return "NOTHING" 

67 

68 def __bool__(self): 

69 return False 

70 

71 

72NOTHING = _Nothing.NOTHING 

73""" 

74Sentinel to indicate the lack of a value when ``None`` is ambiguous. 

75""" 

76 

77 

78class _CacheHashWrapper(int): 

79 """ 

80 An integer subclass that pickles / copies as None 

81 

82 This is used for non-slots classes with ``cache_hash=True``, to avoid 

83 serializing a potentially (even likely) invalid hash value. Since ``None`` 

84 is the default value for uncalculated hashes, whenever this is copied, 

85 the copy's value for the hash should automatically reset. 

86 

87 See GH #613 for more details. 

88 """ 

89 

90 def __reduce__(self, _none_constructor=type(None), _args=()): 

91 return _none_constructor, _args 

92 

93 

94def attrib( 

95 default=NOTHING, 

96 validator=None, 

97 repr=True, 

98 cmp=None, 

99 hash=None, 

100 init=True, 

101 metadata=None, 

102 type=None, 

103 converter=None, 

104 factory=None, 

105 kw_only=False, 

106 eq=None, 

107 order=None, 

108 on_setattr=None, 

109 alias=None, 

110): 

111 """ 

112 Create a new attribute on a class. 

113 

114 .. warning:: 

115 

116 Does *not* do anything unless the class is also decorated with 

117 `attr.s` / `attrs.define` / et cetera! 

118 

119 Please consider using `attrs.field` in new code (``attr.ib`` will *never* 

120 go away, though). 

121 

122 :param default: A value that is used if an *attrs*-generated ``__init__`` 

123 is used and no value is passed while instantiating or the attribute is 

124 excluded using ``init=False``. 

125 

126 If the value is an instance of `attrs.Factory`, its callable will be 

127 used to construct a new value (useful for mutable data types like lists 

128 or dicts). 

129 

130 If a default is not set (or set manually to `attrs.NOTHING`), a value 

131 *must* be supplied when instantiating; otherwise a `TypeError` 

132 will be raised. 

133 

134 The default can also be set using decorator notation as shown below. 

135 

136 :type default: Any value 

137 

138 :param callable factory: Syntactic sugar for 

139 ``default=attr.Factory(factory)``. 

140 

141 :param validator: `callable` that is called by *attrs*-generated 

142 ``__init__`` methods after the instance has been initialized. They 

143 receive the initialized instance, the :func:`~attrs.Attribute`, and the 

144 passed value. 

145 

146 The return value is *not* inspected so the validator has to throw an 

147 exception itself. 

148 

149 If a `list` is passed, its items are treated as validators and must 

150 all pass. 

151 

152 Validators can be globally disabled and re-enabled using 

153 `attrs.validators.get_disabled` / `attrs.validators.set_disabled`. 

154 

155 The validator can also be set using decorator notation as shown below. 

156 

157 :type validator: `callable` or a `list` of `callable`\\ s. 

158 

159 :param repr: Include this attribute in the generated ``__repr__`` 

160 method. If ``True``, include the attribute; if ``False``, omit it. By 

161 default, the built-in ``repr()`` function is used. To override how the 

162 attribute value is formatted, pass a ``callable`` that takes a single 

163 value and returns a string. Note that the resulting string is used 

164 as-is, i.e. it will be used directly *instead* of calling ``repr()`` 

165 (the default). 

166 :type repr: a `bool` or a `callable` to use a custom function. 

167 

168 :param eq: If ``True`` (default), include this attribute in the 

169 generated ``__eq__`` and ``__ne__`` methods that check two instances 

170 for equality. To override how the attribute value is compared, 

171 pass a ``callable`` that takes a single value and returns the value 

172 to be compared. 

173 :type eq: a `bool` or a `callable`. 

174 

175 :param order: If ``True`` (default), include this attributes in the 

176 generated ``__lt__``, ``__le__``, ``__gt__`` and ``__ge__`` methods. 

177 To override how the attribute value is ordered, 

178 pass a ``callable`` that takes a single value and returns the value 

179 to be ordered. 

180 :type order: a `bool` or a `callable`. 

181 

182 :param cmp: Setting *cmp* is equivalent to setting *eq* and *order* to the 

183 same value. Must not be mixed with *eq* or *order*. 

184 :type cmp: a `bool` or a `callable`. 

185 

186 :param Optional[bool] hash: Include this attribute in the generated 

187 ``__hash__`` method. If ``None`` (default), mirror *eq*'s value. This 

188 is the correct behavior according the Python spec. Setting this value 

189 to anything else than ``None`` is *discouraged*. 

190 :param bool init: Include this attribute in the generated ``__init__`` 

191 method. It is possible to set this to ``False`` and set a default 

192 value. In that case this attributed is unconditionally initialized 

193 with the specified default value or factory. 

194 :param callable converter: `callable` that is called by 

195 *attrs*-generated ``__init__`` methods to convert attribute's value 

196 to the desired format. It is given the passed-in value, and the 

197 returned value will be used as the new value of the attribute. The 

198 value is converted before being passed to the validator, if any. 

199 :param metadata: An arbitrary mapping, to be used by third-party 

200 components. See `extending-metadata`. 

201 

202 :param type: The type of the attribute. Nowadays, the preferred method to 

203 specify the type is using a variable annotation (see :pep:`526`). 

204 This argument is provided for backward compatibility. 

205 Regardless of the approach used, the type will be stored on 

206 ``Attribute.type``. 

207 

208 Please note that *attrs* doesn't do anything with this metadata by 

209 itself. You can use it as part of your own code or for 

210 `static type checking <types>`. 

211 :param kw_only: Make this attribute keyword-only in the generated 

212 ``__init__`` (if ``init`` is ``False``, this parameter is ignored). 

213 :param on_setattr: Allows to overwrite the *on_setattr* setting from 

214 `attr.s`. If left `None`, the *on_setattr* value from `attr.s` is used. 

215 Set to `attrs.setters.NO_OP` to run **no** `setattr` hooks for this 

216 attribute -- regardless of the setting in `attr.s`. 

217 :type on_setattr: `callable`, or a list of callables, or `None`, or 

218 `attrs.setters.NO_OP` 

219 :param Optional[str] alias: Override this attribute's parameter name in the 

220 generated ``__init__`` method. If left `None`, default to ``name`` 

221 stripped of leading underscores. See `private-attributes`. 

222 

223 .. versionadded:: 15.2.0 *convert* 

224 .. versionadded:: 16.3.0 *metadata* 

225 .. versionchanged:: 17.1.0 *validator* can be a ``list`` now. 

226 .. versionchanged:: 17.1.0 

227 *hash* is ``None`` and therefore mirrors *eq* by default. 

228 .. versionadded:: 17.3.0 *type* 

229 .. deprecated:: 17.4.0 *convert* 

230 .. versionadded:: 17.4.0 *converter* as a replacement for the deprecated 

231 *convert* to achieve consistency with other noun-based arguments. 

232 .. versionadded:: 18.1.0 

233 ``factory=f`` is syntactic sugar for ``default=attr.Factory(f)``. 

234 .. versionadded:: 18.2.0 *kw_only* 

235 .. versionchanged:: 19.2.0 *convert* keyword argument removed. 

236 .. versionchanged:: 19.2.0 *repr* also accepts a custom callable. 

237 .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01. 

238 .. versionadded:: 19.2.0 *eq* and *order* 

239 .. versionadded:: 20.1.0 *on_setattr* 

240 .. versionchanged:: 20.3.0 *kw_only* backported to Python 2 

241 .. versionchanged:: 21.1.0 

242 *eq*, *order*, and *cmp* also accept a custom callable 

243 .. versionchanged:: 21.1.0 *cmp* undeprecated 

244 .. versionadded:: 22.2.0 *alias* 

245 """ 

246 eq, eq_key, order, order_key = _determine_attrib_eq_order( 

247 cmp, eq, order, True 

248 ) 

249 

250 if hash is not None and hash is not True and hash is not False: 

251 raise TypeError( 

252 "Invalid value for hash. Must be True, False, or None." 

253 ) 

254 

255 if factory is not None: 

256 if default is not NOTHING: 

257 raise ValueError( 

258 "The `default` and `factory` arguments are mutually " 

259 "exclusive." 

260 ) 

261 if not callable(factory): 

262 raise ValueError("The `factory` argument must be a callable.") 

263 default = Factory(factory) 

264 

265 if metadata is None: 

266 metadata = {} 

267 

268 # Apply syntactic sugar by auto-wrapping. 

269 if isinstance(on_setattr, (list, tuple)): 

270 on_setattr = setters.pipe(*on_setattr) 

271 

272 if validator and isinstance(validator, (list, tuple)): 

273 validator = and_(*validator) 

274 

275 if converter and isinstance(converter, (list, tuple)): 

276 converter = pipe(*converter) 

277 

278 return _CountingAttr( 

279 default=default, 

280 validator=validator, 

281 repr=repr, 

282 cmp=None, 

283 hash=hash, 

284 init=init, 

285 converter=converter, 

286 metadata=metadata, 

287 type=type, 

288 kw_only=kw_only, 

289 eq=eq, 

290 eq_key=eq_key, 

291 order=order, 

292 order_key=order_key, 

293 on_setattr=on_setattr, 

294 alias=alias, 

295 ) 

296 

297 

298def _compile_and_eval(script, globs, locs=None, filename=""): 

299 """ 

300 "Exec" the script with the given global (globs) and local (locs) variables. 

301 """ 

302 bytecode = compile(script, filename, "exec") 

303 eval(bytecode, globs, locs) 

304 

305 

306def _make_method(name, script, filename, globs): 

307 """ 

308 Create the method with the script given and return the method object. 

309 """ 

310 locs = {} 

311 

312 # In order of debuggers like PDB being able to step through the code, 

313 # we add a fake linecache entry. 

314 count = 1 

315 base_filename = filename 

316 while True: 

317 linecache_tuple = ( 

318 len(script), 

319 None, 

320 script.splitlines(True), 

321 filename, 

322 ) 

323 old_val = linecache.cache.setdefault(filename, linecache_tuple) 

324 if old_val == linecache_tuple: 

325 break 

326 else: 

327 filename = f"{base_filename[:-1]}-{count}>" 

328 count += 1 

329 

330 _compile_and_eval(script, globs, locs, filename) 

331 

332 return locs[name] 

333 

334 

335def _make_attr_tuple_class(cls_name, attr_names): 

336 """ 

337 Create a tuple subclass to hold `Attribute`s for an `attrs` class. 

338 

339 The subclass is a bare tuple with properties for names. 

340 

341 class MyClassAttributes(tuple): 

342 __slots__ = () 

343 x = property(itemgetter(0)) 

344 """ 

345 attr_class_name = f"{cls_name}Attributes" 

346 attr_class_template = [ 

347 f"class {attr_class_name}(tuple):", 

348 " __slots__ = ()", 

349 ] 

350 if attr_names: 

351 for i, attr_name in enumerate(attr_names): 

352 attr_class_template.append( 

353 f" {attr_name} = _attrs_property(_attrs_itemgetter({i}))" 

354 ) 

355 else: 

356 attr_class_template.append(" pass") 

357 globs = {"_attrs_itemgetter": itemgetter, "_attrs_property": property} 

358 _compile_and_eval("\n".join(attr_class_template), globs) 

359 return globs[attr_class_name] 

360 

361 

362# Tuple class for extracted attributes from a class definition. 

363# `base_attrs` is a subset of `attrs`. 

364_Attributes = _make_attr_tuple_class( 

365 "_Attributes", 

366 [ 

367 # all attributes to build dunder methods for 

368 "attrs", 

369 # attributes that have been inherited 

370 "base_attrs", 

371 # map inherited attributes to their originating classes 

372 "base_attrs_map", 

373 ], 

374) 

375 

376 

377def _is_class_var(annot): 

378 """ 

379 Check whether *annot* is a typing.ClassVar. 

380 

381 The string comparison hack is used to avoid evaluating all string 

382 annotations which would put attrs-based classes at a performance 

383 disadvantage compared to plain old classes. 

384 """ 

385 annot = str(annot) 

386 

387 # Annotation can be quoted. 

388 if annot.startswith(("'", '"')) and annot.endswith(("'", '"')): 

389 annot = annot[1:-1] 

390 

391 return annot.startswith(_classvar_prefixes) 

392 

393 

394def _has_own_attribute(cls, attrib_name): 

395 """ 

396 Check whether *cls* defines *attrib_name* (and doesn't just inherit it). 

397 """ 

398 attr = getattr(cls, attrib_name, _sentinel) 

399 if attr is _sentinel: 

400 return False 

401 

402 for base_cls in cls.__mro__[1:]: 

403 a = getattr(base_cls, attrib_name, None) 

404 if attr is a: 

405 return False 

406 

407 return True 

408 

409 

410def _get_annotations(cls): 

411 """ 

412 Get annotations for *cls*. 

413 """ 

414 if _has_own_attribute(cls, "__annotations__"): 

415 return cls.__annotations__ 

416 

417 return {} 

418 

419 

420def _collect_base_attrs(cls, taken_attr_names): 

421 """ 

422 Collect attr.ibs from base classes of *cls*, except *taken_attr_names*. 

423 """ 

424 base_attrs = [] 

425 base_attr_map = {} # A dictionary of base attrs to their classes. 

426 

427 # Traverse the MRO and collect attributes. 

428 for base_cls in reversed(cls.__mro__[1:-1]): 

429 for a in getattr(base_cls, "__attrs_attrs__", []): 

430 if a.inherited or a.name in taken_attr_names: 

431 continue 

432 

433 a = a.evolve(inherited=True) 

434 base_attrs.append(a) 

435 base_attr_map[a.name] = base_cls 

436 

437 # For each name, only keep the freshest definition i.e. the furthest at the 

438 # back. base_attr_map is fine because it gets overwritten with every new 

439 # instance. 

440 filtered = [] 

441 seen = set() 

442 for a in reversed(base_attrs): 

443 if a.name in seen: 

444 continue 

445 filtered.insert(0, a) 

446 seen.add(a.name) 

447 

448 return filtered, base_attr_map 

449 

450 

451def _collect_base_attrs_broken(cls, taken_attr_names): 

452 """ 

453 Collect attr.ibs from base classes of *cls*, except *taken_attr_names*. 

454 

455 N.B. *taken_attr_names* will be mutated. 

456 

457 Adhere to the old incorrect behavior. 

458 

459 Notably it collects from the front and considers inherited attributes which 

460 leads to the buggy behavior reported in #428. 

461 """ 

462 base_attrs = [] 

463 base_attr_map = {} # A dictionary of base attrs to their classes. 

464 

465 # Traverse the MRO and collect attributes. 

466 for base_cls in cls.__mro__[1:-1]: 

467 for a in getattr(base_cls, "__attrs_attrs__", []): 

468 if a.name in taken_attr_names: 

469 continue 

470 

471 a = a.evolve(inherited=True) 

472 taken_attr_names.add(a.name) 

473 base_attrs.append(a) 

474 base_attr_map[a.name] = base_cls 

475 

476 return base_attrs, base_attr_map 

477 

478 

479def _transform_attrs( 

480 cls, these, auto_attribs, kw_only, collect_by_mro, field_transformer 

481): 

482 """ 

483 Transform all `_CountingAttr`s on a class into `Attribute`s. 

484 

485 If *these* is passed, use that and don't look for them on the class. 

486 

487 *collect_by_mro* is True, collect them in the correct MRO order, otherwise 

488 use the old -- incorrect -- order. See #428. 

489 

490 Return an `_Attributes`. 

491 """ 

492 cd = cls.__dict__ 

493 anns = _get_annotations(cls) 

494 

495 if these is not None: 

496 ca_list = [(name, ca) for name, ca in these.items()] 

497 elif auto_attribs is True: 

498 ca_names = { 

499 name 

500 for name, attr in cd.items() 

501 if isinstance(attr, _CountingAttr) 

502 } 

503 ca_list = [] 

504 annot_names = set() 

505 for attr_name, type in anns.items(): 

506 if _is_class_var(type): 

507 continue 

508 annot_names.add(attr_name) 

509 a = cd.get(attr_name, NOTHING) 

510 

511 if not isinstance(a, _CountingAttr): 

512 if a is NOTHING: 

513 a = attrib() 

514 else: 

515 a = attrib(default=a) 

516 ca_list.append((attr_name, a)) 

517 

518 unannotated = ca_names - annot_names 

519 if len(unannotated) > 0: 

520 raise UnannotatedAttributeError( 

521 "The following `attr.ib`s lack a type annotation: " 

522 + ", ".join( 

523 sorted(unannotated, key=lambda n: cd.get(n).counter) 

524 ) 

525 + "." 

526 ) 

527 else: 

528 ca_list = sorted( 

529 ( 

530 (name, attr) 

531 for name, attr in cd.items() 

532 if isinstance(attr, _CountingAttr) 

533 ), 

534 key=lambda e: e[1].counter, 

535 ) 

536 

537 own_attrs = [ 

538 Attribute.from_counting_attr( 

539 name=attr_name, ca=ca, type=anns.get(attr_name) 

540 ) 

541 for attr_name, ca in ca_list 

542 ] 

543 

544 if collect_by_mro: 

545 base_attrs, base_attr_map = _collect_base_attrs( 

546 cls, {a.name for a in own_attrs} 

547 ) 

548 else: 

549 base_attrs, base_attr_map = _collect_base_attrs_broken( 

550 cls, {a.name for a in own_attrs} 

551 ) 

552 

553 if kw_only: 

554 own_attrs = [a.evolve(kw_only=True) for a in own_attrs] 

555 base_attrs = [a.evolve(kw_only=True) for a in base_attrs] 

556 

557 attrs = base_attrs + own_attrs 

558 

559 # Mandatory vs non-mandatory attr order only matters when they are part of 

560 # the __init__ signature and when they aren't kw_only (which are moved to 

561 # the end and can be mandatory or non-mandatory in any order, as they will 

562 # be specified as keyword args anyway). Check the order of those attrs: 

563 had_default = False 

564 for a in (a for a in attrs if a.init is not False and a.kw_only is False): 

565 if had_default is True and a.default is NOTHING: 

566 raise ValueError( 

567 "No mandatory attributes allowed after an attribute with a " 

568 f"default value or factory. Attribute in question: {a!r}" 

569 ) 

570 

571 if had_default is False and a.default is not NOTHING: 

572 had_default = True 

573 

574 if field_transformer is not None: 

575 attrs = field_transformer(cls, attrs) 

576 

577 # Resolve default field alias after executing field_transformer. 

578 # This allows field_transformer to differentiate between explicit vs 

579 # default aliases and supply their own defaults. 

580 attrs = [ 

581 a.evolve(alias=_default_init_alias_for(a.name)) if not a.alias else a 

582 for a in attrs 

583 ] 

584 

585 # Create AttrsClass *after* applying the field_transformer since it may 

586 # add or remove attributes! 

587 attr_names = [a.name for a in attrs] 

588 AttrsClass = _make_attr_tuple_class(cls.__name__, attr_names) 

589 

590 return _Attributes((AttrsClass(attrs), base_attrs, base_attr_map)) 

591 

592 

593def _frozen_setattrs(self, name, value): 

594 """ 

595 Attached to frozen classes as __setattr__. 

596 """ 

597 if isinstance(self, BaseException) and name in ( 

598 "__cause__", 

599 "__context__", 

600 "__traceback__", 

601 ): 

602 BaseException.__setattr__(self, name, value) 

603 return 

604 

605 raise FrozenInstanceError() 

606 

607 

608def _frozen_delattrs(self, name): 

609 """ 

610 Attached to frozen classes as __delattr__. 

611 """ 

612 raise FrozenInstanceError() 

613 

614 

615class _ClassBuilder: 

616 """ 

617 Iteratively build *one* class. 

618 """ 

619 

620 __slots__ = ( 

621 "_attr_names", 

622 "_attrs", 

623 "_base_attr_map", 

624 "_base_names", 

625 "_cache_hash", 

626 "_cls", 

627 "_cls_dict", 

628 "_delete_attribs", 

629 "_frozen", 

630 "_has_pre_init", 

631 "_has_post_init", 

632 "_is_exc", 

633 "_on_setattr", 

634 "_slots", 

635 "_weakref_slot", 

636 "_wrote_own_setattr", 

637 "_has_custom_setattr", 

638 ) 

639 

640 def __init__( 

641 self, 

642 cls, 

643 these, 

644 slots, 

645 frozen, 

646 weakref_slot, 

647 getstate_setstate, 

648 auto_attribs, 

649 kw_only, 

650 cache_hash, 

651 is_exc, 

652 collect_by_mro, 

653 on_setattr, 

654 has_custom_setattr, 

655 field_transformer, 

656 ): 

657 attrs, base_attrs, base_map = _transform_attrs( 

658 cls, 

659 these, 

660 auto_attribs, 

661 kw_only, 

662 collect_by_mro, 

663 field_transformer, 

664 ) 

665 

666 self._cls = cls 

667 self._cls_dict = dict(cls.__dict__) if slots else {} 

668 self._attrs = attrs 

669 self._base_names = {a.name for a in base_attrs} 

670 self._base_attr_map = base_map 

671 self._attr_names = tuple(a.name for a in attrs) 

672 self._slots = slots 

673 self._frozen = frozen 

674 self._weakref_slot = weakref_slot 

675 self._cache_hash = cache_hash 

676 self._has_pre_init = bool(getattr(cls, "__attrs_pre_init__", False)) 

677 self._has_post_init = bool(getattr(cls, "__attrs_post_init__", False)) 

678 self._delete_attribs = not bool(these) 

679 self._is_exc = is_exc 

680 self._on_setattr = on_setattr 

681 

682 self._has_custom_setattr = has_custom_setattr 

683 self._wrote_own_setattr = False 

684 

685 self._cls_dict["__attrs_attrs__"] = self._attrs 

686 

687 if frozen: 

688 self._cls_dict["__setattr__"] = _frozen_setattrs 

689 self._cls_dict["__delattr__"] = _frozen_delattrs 

690 

691 self._wrote_own_setattr = True 

692 elif on_setattr in ( 

693 _ng_default_on_setattr, 

694 setters.validate, 

695 setters.convert, 

696 ): 

697 has_validator = has_converter = False 

698 for a in attrs: 

699 if a.validator is not None: 

700 has_validator = True 

701 if a.converter is not None: 

702 has_converter = True 

703 

704 if has_validator and has_converter: 

705 break 

706 if ( 

707 ( 

708 on_setattr == _ng_default_on_setattr 

709 and not (has_validator or has_converter) 

710 ) 

711 or (on_setattr == setters.validate and not has_validator) 

712 or (on_setattr == setters.convert and not has_converter) 

713 ): 

714 # If class-level on_setattr is set to convert + validate, but 

715 # there's no field to convert or validate, pretend like there's 

716 # no on_setattr. 

717 self._on_setattr = None 

718 

719 if getstate_setstate: 

720 ( 

721 self._cls_dict["__getstate__"], 

722 self._cls_dict["__setstate__"], 

723 ) = self._make_getstate_setstate() 

724 

725 def __repr__(self): 

726 return f"<_ClassBuilder(cls={self._cls.__name__})>" 

727 

728 if PY310: 

729 import abc 

730 

731 def build_class(self): 

732 """ 

733 Finalize class based on the accumulated configuration. 

734 

735 Builder cannot be used after calling this method. 

736 """ 

737 if self._slots is True: 

738 return self._create_slots_class() 

739 

740 return self.abc.update_abstractmethods( 

741 self._patch_original_class() 

742 ) 

743 

744 else: 

745 

746 def build_class(self): 

747 """ 

748 Finalize class based on the accumulated configuration. 

749 

750 Builder cannot be used after calling this method. 

751 """ 

752 if self._slots is True: 

753 return self._create_slots_class() 

754 

755 return self._patch_original_class() 

756 

757 def _patch_original_class(self): 

758 """ 

759 Apply accumulated methods and return the class. 

760 """ 

761 cls = self._cls 

762 base_names = self._base_names 

763 

764 # Clean class of attribute definitions (`attr.ib()`s). 

765 if self._delete_attribs: 

766 for name in self._attr_names: 

767 if ( 

768 name not in base_names 

769 and getattr(cls, name, _sentinel) is not _sentinel 

770 ): 

771 try: 

772 delattr(cls, name) 

773 except AttributeError: 

774 # This can happen if a base class defines a class 

775 # variable and we want to set an attribute with the 

776 # same name by using only a type annotation. 

777 pass 

778 

779 # Attach our dunder methods. 

780 for name, value in self._cls_dict.items(): 

781 setattr(cls, name, value) 

782 

783 # If we've inherited an attrs __setattr__ and don't write our own, 

784 # reset it to object's. 

785 if not self._wrote_own_setattr and getattr( 

786 cls, "__attrs_own_setattr__", False 

787 ): 

788 cls.__attrs_own_setattr__ = False 

789 

790 if not self._has_custom_setattr: 

791 cls.__setattr__ = _obj_setattr 

792 

793 return cls 

794 

795 def _create_slots_class(self): 

796 """ 

797 Build and return a new class with a `__slots__` attribute. 

798 """ 

799 cd = { 

800 k: v 

801 for k, v in self._cls_dict.items() 

802 if k not in tuple(self._attr_names) + ("__dict__", "__weakref__") 

803 } 

804 

805 # If our class doesn't have its own implementation of __setattr__ 

806 # (either from the user or by us), check the bases, if one of them has 

807 # an attrs-made __setattr__, that needs to be reset. We don't walk the 

808 # MRO because we only care about our immediate base classes. 

809 # XXX: This can be confused by subclassing a slotted attrs class with 

810 # XXX: a non-attrs class and subclass the resulting class with an attrs 

811 # XXX: class. See `test_slotted_confused` for details. For now that's 

812 # XXX: OK with us. 

813 if not self._wrote_own_setattr: 

814 cd["__attrs_own_setattr__"] = False 

815 

816 if not self._has_custom_setattr: 

817 for base_cls in self._cls.__bases__: 

818 if base_cls.__dict__.get("__attrs_own_setattr__", False): 

819 cd["__setattr__"] = _obj_setattr 

820 break 

821 

822 # Traverse the MRO to collect existing slots 

823 # and check for an existing __weakref__. 

824 existing_slots = dict() 

825 weakref_inherited = False 

826 for base_cls in self._cls.__mro__[1:-1]: 

827 if base_cls.__dict__.get("__weakref__", None) is not None: 

828 weakref_inherited = True 

829 existing_slots.update( 

830 { 

831 name: getattr(base_cls, name) 

832 for name in getattr(base_cls, "__slots__", []) 

833 } 

834 ) 

835 

836 base_names = set(self._base_names) 

837 

838 names = self._attr_names 

839 if ( 

840 self._weakref_slot 

841 and "__weakref__" not in getattr(self._cls, "__slots__", ()) 

842 and "__weakref__" not in names 

843 and not weakref_inherited 

844 ): 

845 names += ("__weakref__",) 

846 

847 # We only add the names of attributes that aren't inherited. 

848 # Setting __slots__ to inherited attributes wastes memory. 

849 slot_names = [name for name in names if name not in base_names] 

850 # There are slots for attributes from current class 

851 # that are defined in parent classes. 

852 # As their descriptors may be overridden by a child class, 

853 # we collect them here and update the class dict 

854 reused_slots = { 

855 slot: slot_descriptor 

856 for slot, slot_descriptor in existing_slots.items() 

857 if slot in slot_names 

858 } 

859 slot_names = [name for name in slot_names if name not in reused_slots] 

860 cd.update(reused_slots) 

861 if self._cache_hash: 

862 slot_names.append(_hash_cache_field) 

863 cd["__slots__"] = tuple(slot_names) 

864 

865 cd["__qualname__"] = self._cls.__qualname__ 

866 

867 # Create new class based on old class and our methods. 

868 cls = type(self._cls)(self._cls.__name__, self._cls.__bases__, cd) 

869 

870 # The following is a fix for 

871 # <https://github.com/python-attrs/attrs/issues/102>. 

872 # If a method mentions `__class__` or uses the no-arg super(), the 

873 # compiler will bake a reference to the class in the method itself 

874 # as `method.__closure__`. Since we replace the class with a 

875 # clone, we rewrite these references so it keeps working. 

876 for item in cls.__dict__.values(): 

877 if isinstance(item, (classmethod, staticmethod)): 

878 # Class- and staticmethods hide their functions inside. 

879 # These might need to be rewritten as well. 

880 closure_cells = getattr(item.__func__, "__closure__", None) 

881 elif isinstance(item, property): 

882 # Workaround for property `super()` shortcut (PY3-only). 

883 # There is no universal way for other descriptors. 

884 closure_cells = getattr(item.fget, "__closure__", None) 

885 else: 

886 closure_cells = getattr(item, "__closure__", None) 

887 

888 if not closure_cells: # Catch None or the empty list. 

889 continue 

890 for cell in closure_cells: 

891 try: 

892 match = cell.cell_contents is self._cls 

893 except ValueError: # ValueError: Cell is empty 

894 pass 

895 else: 

896 if match: 

897 set_closure_cell(cell, cls) 

898 

899 return cls 

900 

901 def add_repr(self, ns): 

902 self._cls_dict["__repr__"] = self._add_method_dunders( 

903 _make_repr(self._attrs, ns, self._cls) 

904 ) 

905 return self 

906 

907 def add_str(self): 

908 repr = self._cls_dict.get("__repr__") 

909 if repr is None: 

910 raise ValueError( 

911 "__str__ can only be generated if a __repr__ exists." 

912 ) 

913 

914 def __str__(self): 

915 return self.__repr__() 

916 

917 self._cls_dict["__str__"] = self._add_method_dunders(__str__) 

918 return self 

919 

920 def _make_getstate_setstate(self): 

921 """ 

922 Create custom __setstate__ and __getstate__ methods. 

923 """ 

924 # __weakref__ is not writable. 

925 state_attr_names = tuple( 

926 an for an in self._attr_names if an != "__weakref__" 

927 ) 

928 

929 def slots_getstate(self): 

930 """ 

931 Automatically created by attrs. 

932 """ 

933 return {name: getattr(self, name) for name in state_attr_names} 

934 

935 hash_caching_enabled = self._cache_hash 

936 

937 def slots_setstate(self, state): 

938 """ 

939 Automatically created by attrs. 

940 """ 

941 __bound_setattr = _obj_setattr.__get__(self) 

942 if isinstance(state, tuple): 

943 # Backward compatibility with attrs instances pickled with 

944 # attrs versions before v22.2.0 which stored tuples. 

945 for name, value in zip(state_attr_names, state): 

946 __bound_setattr(name, value) 

947 else: 

948 for name in state_attr_names: 

949 if name in state: 

950 __bound_setattr(name, state[name]) 

951 

952 # The hash code cache is not included when the object is 

953 # serialized, but it still needs to be initialized to None to 

954 # indicate that the first call to __hash__ should be a cache 

955 # miss. 

956 if hash_caching_enabled: 

957 __bound_setattr(_hash_cache_field, None) 

958 

959 return slots_getstate, slots_setstate 

960 

961 def make_unhashable(self): 

962 self._cls_dict["__hash__"] = None 

963 return self 

964 

965 def add_hash(self): 

966 self._cls_dict["__hash__"] = self._add_method_dunders( 

967 _make_hash( 

968 self._cls, 

969 self._attrs, 

970 frozen=self._frozen, 

971 cache_hash=self._cache_hash, 

972 ) 

973 ) 

974 

975 return self 

976 

977 def add_init(self): 

978 self._cls_dict["__init__"] = self._add_method_dunders( 

979 _make_init( 

980 self._cls, 

981 self._attrs, 

982 self._has_pre_init, 

983 self._has_post_init, 

984 self._frozen, 

985 self._slots, 

986 self._cache_hash, 

987 self._base_attr_map, 

988 self._is_exc, 

989 self._on_setattr, 

990 attrs_init=False, 

991 ) 

992 ) 

993 

994 return self 

995 

996 def add_match_args(self): 

997 self._cls_dict["__match_args__"] = tuple( 

998 field.name 

999 for field in self._attrs 

1000 if field.init and not field.kw_only 

1001 ) 

1002 

1003 def add_attrs_init(self): 

1004 self._cls_dict["__attrs_init__"] = self._add_method_dunders( 

1005 _make_init( 

1006 self._cls, 

1007 self._attrs, 

1008 self._has_pre_init, 

1009 self._has_post_init, 

1010 self._frozen, 

1011 self._slots, 

1012 self._cache_hash, 

1013 self._base_attr_map, 

1014 self._is_exc, 

1015 self._on_setattr, 

1016 attrs_init=True, 

1017 ) 

1018 ) 

1019 

1020 return self 

1021 

1022 def add_eq(self): 

1023 cd = self._cls_dict 

1024 

1025 cd["__eq__"] = self._add_method_dunders( 

1026 _make_eq(self._cls, self._attrs) 

1027 ) 

1028 cd["__ne__"] = self._add_method_dunders(_make_ne()) 

1029 

1030 return self 

1031 

1032 def add_order(self): 

1033 cd = self._cls_dict 

1034 

1035 cd["__lt__"], cd["__le__"], cd["__gt__"], cd["__ge__"] = ( 

1036 self._add_method_dunders(meth) 

1037 for meth in _make_order(self._cls, self._attrs) 

1038 ) 

1039 

1040 return self 

1041 

1042 def add_setattr(self): 

1043 if self._frozen: 

1044 return self 

1045 

1046 sa_attrs = {} 

1047 for a in self._attrs: 

1048 on_setattr = a.on_setattr or self._on_setattr 

1049 if on_setattr and on_setattr is not setters.NO_OP: 

1050 sa_attrs[a.name] = a, on_setattr 

1051 

1052 if not sa_attrs: 

1053 return self 

1054 

1055 if self._has_custom_setattr: 

1056 # We need to write a __setattr__ but there already is one! 

1057 raise ValueError( 

1058 "Can't combine custom __setattr__ with on_setattr hooks." 

1059 ) 

1060 

1061 # docstring comes from _add_method_dunders 

1062 def __setattr__(self, name, val): 

1063 try: 

1064 a, hook = sa_attrs[name] 

1065 except KeyError: 

1066 nval = val 

1067 else: 

1068 nval = hook(self, a, val) 

1069 

1070 _obj_setattr(self, name, nval) 

1071 

1072 self._cls_dict["__attrs_own_setattr__"] = True 

1073 self._cls_dict["__setattr__"] = self._add_method_dunders(__setattr__) 

1074 self._wrote_own_setattr = True 

1075 

1076 return self 

1077 

1078 def _add_method_dunders(self, method): 

1079 """ 

1080 Add __module__ and __qualname__ to a *method* if possible. 

1081 """ 

1082 try: 

1083 method.__module__ = self._cls.__module__ 

1084 except AttributeError: 

1085 pass 

1086 

1087 try: 

1088 method.__qualname__ = ".".join( 

1089 (self._cls.__qualname__, method.__name__) 

1090 ) 

1091 except AttributeError: 

1092 pass 

1093 

1094 try: 

1095 method.__doc__ = ( 

1096 "Method generated by attrs for class " 

1097 f"{self._cls.__qualname__}." 

1098 ) 

1099 except AttributeError: 

1100 pass 

1101 

1102 return method 

1103 

1104 

1105def _determine_attrs_eq_order(cmp, eq, order, default_eq): 

1106 """ 

1107 Validate the combination of *cmp*, *eq*, and *order*. Derive the effective 

1108 values of eq and order. If *eq* is None, set it to *default_eq*. 

1109 """ 

1110 if cmp is not None and any((eq is not None, order is not None)): 

1111 raise ValueError("Don't mix `cmp` with `eq' and `order`.") 

1112 

1113 # cmp takes precedence due to bw-compatibility. 

1114 if cmp is not None: 

1115 return cmp, cmp 

1116 

1117 # If left None, equality is set to the specified default and ordering 

1118 # mirrors equality. 

1119 if eq is None: 

1120 eq = default_eq 

1121 

1122 if order is None: 

1123 order = eq 

1124 

1125 if eq is False and order is True: 

1126 raise ValueError("`order` can only be True if `eq` is True too.") 

1127 

1128 return eq, order 

1129 

1130 

1131def _determine_attrib_eq_order(cmp, eq, order, default_eq): 

1132 """ 

1133 Validate the combination of *cmp*, *eq*, and *order*. Derive the effective 

1134 values of eq and order. If *eq* is None, set it to *default_eq*. 

1135 """ 

1136 if cmp is not None and any((eq is not None, order is not None)): 

1137 raise ValueError("Don't mix `cmp` with `eq' and `order`.") 

1138 

1139 def decide_callable_or_boolean(value): 

1140 """ 

1141 Decide whether a key function is used. 

1142 """ 

1143 if callable(value): 

1144 value, key = True, value 

1145 else: 

1146 key = None 

1147 return value, key 

1148 

1149 # cmp takes precedence due to bw-compatibility. 

1150 if cmp is not None: 

1151 cmp, cmp_key = decide_callable_or_boolean(cmp) 

1152 return cmp, cmp_key, cmp, cmp_key 

1153 

1154 # If left None, equality is set to the specified default and ordering 

1155 # mirrors equality. 

1156 if eq is None: 

1157 eq, eq_key = default_eq, None 

1158 else: 

1159 eq, eq_key = decide_callable_or_boolean(eq) 

1160 

1161 if order is None: 

1162 order, order_key = eq, eq_key 

1163 else: 

1164 order, order_key = decide_callable_or_boolean(order) 

1165 

1166 if eq is False and order is True: 

1167 raise ValueError("`order` can only be True if `eq` is True too.") 

1168 

1169 return eq, eq_key, order, order_key 

1170 

1171 

1172def _determine_whether_to_implement( 

1173 cls, flag, auto_detect, dunders, default=True 

1174): 

1175 """ 

1176 Check whether we should implement a set of methods for *cls*. 

1177 

1178 *flag* is the argument passed into @attr.s like 'init', *auto_detect* the 

1179 same as passed into @attr.s and *dunders* is a tuple of attribute names 

1180 whose presence signal that the user has implemented it themselves. 

1181 

1182 Return *default* if no reason for either for or against is found. 

1183 """ 

1184 if flag is True or flag is False: 

1185 return flag 

1186 

1187 if flag is None and auto_detect is False: 

1188 return default 

1189 

1190 # Logically, flag is None and auto_detect is True here. 

1191 for dunder in dunders: 

1192 if _has_own_attribute(cls, dunder): 

1193 return False 

1194 

1195 return default 

1196 

1197 

1198def attrs( 

1199 maybe_cls=None, 

1200 these=None, 

1201 repr_ns=None, 

1202 repr=None, 

1203 cmp=None, 

1204 hash=None, 

1205 init=None, 

1206 slots=False, 

1207 frozen=False, 

1208 weakref_slot=True, 

1209 str=False, 

1210 auto_attribs=False, 

1211 kw_only=False, 

1212 cache_hash=False, 

1213 auto_exc=False, 

1214 eq=None, 

1215 order=None, 

1216 auto_detect=False, 

1217 collect_by_mro=False, 

1218 getstate_setstate=None, 

1219 on_setattr=None, 

1220 field_transformer=None, 

1221 match_args=True, 

1222 unsafe_hash=None, 

1223): 

1224 r""" 

1225 A class decorator that adds :term:`dunder methods` according to the 

1226 specified attributes using `attr.ib` or the *these* argument. 

1227 

1228 Please consider using `attrs.define` / `attrs.frozen` in new code 

1229 (``attr.s`` will *never* go away, though). 

1230 

1231 :param these: A dictionary of name to `attr.ib` mappings. This is 

1232 useful to avoid the definition of your attributes within the class body 

1233 because you can't (e.g. if you want to add ``__repr__`` methods to 

1234 Django models) or don't want to. 

1235 

1236 If *these* is not ``None``, *attrs* will *not* search the class body 

1237 for attributes and will *not* remove any attributes from it. 

1238 

1239 The order is deduced from the order of the attributes inside *these*. 

1240 

1241 :type these: `dict` of `str` to `attr.ib` 

1242 

1243 :param str repr_ns: When using nested classes, there's no way in Python 2 

1244 to automatically detect that. Therefore it's possible to set the 

1245 namespace explicitly for a more meaningful ``repr`` output. 

1246 :param bool auto_detect: Instead of setting the *init*, *repr*, *eq*, 

1247 *order*, and *hash* arguments explicitly, assume they are set to 

1248 ``True`` **unless any** of the involved methods for one of the 

1249 arguments is implemented in the *current* class (i.e. it is *not* 

1250 inherited from some base class). 

1251 

1252 So for example by implementing ``__eq__`` on a class yourself, 

1253 *attrs* will deduce ``eq=False`` and will create *neither* 

1254 ``__eq__`` *nor* ``__ne__`` (but Python classes come with a sensible 

1255 ``__ne__`` by default, so it *should* be enough to only implement 

1256 ``__eq__`` in most cases). 

1257 

1258 .. warning:: 

1259 

1260 If you prevent *attrs* from creating the ordering methods for you 

1261 (``order=False``, e.g. by implementing ``__le__``), it becomes 

1262 *your* responsibility to make sure its ordering is sound. The best 

1263 way is to use the `functools.total_ordering` decorator. 

1264 

1265 

1266 Passing ``True`` or ``False`` to *init*, *repr*, *eq*, *order*, 

1267 *cmp*, or *hash* overrides whatever *auto_detect* would determine. 

1268 

1269 :param bool repr: Create a ``__repr__`` method with a human readable 

1270 representation of *attrs* attributes.. 

1271 :param bool str: Create a ``__str__`` method that is identical to 

1272 ``__repr__``. This is usually not necessary except for 

1273 `Exception`\ s. 

1274 :param Optional[bool] eq: If ``True`` or ``None`` (default), add ``__eq__`` 

1275 and ``__ne__`` methods that check two instances for equality. 

1276 

1277 They compare the instances as if they were tuples of their *attrs* 

1278 attributes if and only if the types of both classes are *identical*! 

1279 :param Optional[bool] order: If ``True``, add ``__lt__``, ``__le__``, 

1280 ``__gt__``, and ``__ge__`` methods that behave like *eq* above and 

1281 allow instances to be ordered. If ``None`` (default) mirror value of 

1282 *eq*. 

1283 :param Optional[bool] cmp: Setting *cmp* is equivalent to setting *eq* 

1284 and *order* to the same value. Must not be mixed with *eq* or *order*. 

1285 :param Optional[bool] unsafe_hash: If ``None`` (default), the ``__hash__`` 

1286 method is generated according how *eq* and *frozen* are set. 

1287 

1288 1. If *both* are True, *attrs* will generate a ``__hash__`` for you. 

1289 2. If *eq* is True and *frozen* is False, ``__hash__`` will be set to 

1290 None, marking it unhashable (which it is). 

1291 3. If *eq* is False, ``__hash__`` will be left untouched meaning the 

1292 ``__hash__`` method of the base class will be used (if base class is 

1293 ``object``, this means it will fall back to id-based hashing.). 

1294 

1295 Although not recommended, you can decide for yourself and force 

1296 *attrs* to create one (e.g. if the class is immutable even though you 

1297 didn't freeze it programmatically) by passing ``True`` or not. Both of 

1298 these cases are rather special and should be used carefully. 

1299 

1300 See our documentation on `hashing`, Python's documentation on 

1301 `object.__hash__`, and the `GitHub issue that led to the default \ 

1302 behavior <https://github.com/python-attrs/attrs/issues/136>`_ for more 

1303 details. 

1304 :param Optional[bool] hash: Alias for *unsafe_hash*. *unsafe_hash* takes 

1305 precedence. 

1306 :param bool init: Create a ``__init__`` method that initializes the 

1307 *attrs* attributes. Leading underscores are stripped for the argument 

1308 name. If a ``__attrs_pre_init__`` method exists on the class, it will 

1309 be called before the class is initialized. If a ``__attrs_post_init__`` 

1310 method exists on the class, it will be called after the class is fully 

1311 initialized. 

1312 

1313 If ``init`` is ``False``, an ``__attrs_init__`` method will be 

1314 injected instead. This allows you to define a custom ``__init__`` 

1315 method that can do pre-init work such as ``super().__init__()``, 

1316 and then call ``__attrs_init__()`` and ``__attrs_post_init__()``. 

1317 :param bool slots: Create a :term:`slotted class <slotted classes>` that's 

1318 more memory-efficient. Slotted classes are generally superior to the 

1319 default dict classes, but have some gotchas you should know about, so 

1320 we encourage you to read the :term:`glossary entry <slotted classes>`. 

1321 :param bool frozen: Make instances immutable after initialization. If 

1322 someone attempts to modify a frozen instance, 

1323 `attrs.exceptions.FrozenInstanceError` is raised. 

1324 

1325 .. note:: 

1326 

1327 1. This is achieved by installing a custom ``__setattr__`` method 

1328 on your class, so you can't implement your own. 

1329 

1330 2. True immutability is impossible in Python. 

1331 

1332 3. This *does* have a minor a runtime performance `impact 

1333 <how-frozen>` when initializing new instances. In other words: 

1334 ``__init__`` is slightly slower with ``frozen=True``. 

1335 

1336 4. If a class is frozen, you cannot modify ``self`` in 

1337 ``__attrs_post_init__`` or a self-written ``__init__``. You can 

1338 circumvent that limitation by using 

1339 ``object.__setattr__(self, "attribute_name", value)``. 

1340 

1341 5. Subclasses of a frozen class are frozen too. 

1342 

1343 :param bool weakref_slot: Make instances weak-referenceable. This has no 

1344 effect unless ``slots`` is also enabled. 

1345 :param bool auto_attribs: If ``True``, collect :pep:`526`-annotated 

1346 attributes from the class body. 

1347 

1348 In this case, you **must** annotate every field. If *attrs* 

1349 encounters a field that is set to an `attr.ib` but lacks a type 

1350 annotation, an `attr.exceptions.UnannotatedAttributeError` is 

1351 raised. Use ``field_name: typing.Any = attr.ib(...)`` if you don't 

1352 want to set a type. 

1353 

1354 If you assign a value to those attributes (e.g. ``x: int = 42``), that 

1355 value becomes the default value like if it were passed using 

1356 ``attr.ib(default=42)``. Passing an instance of `attrs.Factory` also 

1357 works as expected in most cases (see warning below). 

1358 

1359 Attributes annotated as `typing.ClassVar`, and attributes that are 

1360 neither annotated nor set to an `attr.ib` are **ignored**. 

1361 

1362 .. warning:: 

1363 For features that use the attribute name to create decorators (e.g. 

1364 :ref:`validators <validators>`), you still *must* assign `attr.ib` 

1365 to them. Otherwise Python will either not find the name or try to 

1366 use the default value to call e.g. ``validator`` on it. 

1367 

1368 These errors can be quite confusing and probably the most common bug 

1369 report on our bug tracker. 

1370 

1371 :param bool kw_only: Make all attributes keyword-only 

1372 in the generated ``__init__`` (if ``init`` is ``False``, this 

1373 parameter is ignored). 

1374 :param bool cache_hash: Ensure that the object's hash code is computed 

1375 only once and stored on the object. If this is set to ``True``, 

1376 hashing must be either explicitly or implicitly enabled for this 

1377 class. If the hash code is cached, avoid any reassignments of 

1378 fields involved in hash code computation or mutations of the objects 

1379 those fields point to after object creation. If such changes occur, 

1380 the behavior of the object's hash code is undefined. 

1381 :param bool auto_exc: If the class subclasses `BaseException` 

1382 (which implicitly includes any subclass of any exception), the 

1383 following happens to behave like a well-behaved Python exceptions 

1384 class: 

1385 

1386 - the values for *eq*, *order*, and *hash* are ignored and the 

1387 instances compare and hash by the instance's ids (N.B. *attrs* will 

1388 *not* remove existing implementations of ``__hash__`` or the equality 

1389 methods. It just won't add own ones.), 

1390 - all attributes that are either passed into ``__init__`` or have a 

1391 default value are additionally available as a tuple in the ``args`` 

1392 attribute, 

1393 - the value of *str* is ignored leaving ``__str__`` to base classes. 

1394 :param bool collect_by_mro: Setting this to `True` fixes the way *attrs* 

1395 collects attributes from base classes. The default behavior is 

1396 incorrect in certain cases of multiple inheritance. It should be on by 

1397 default but is kept off for backward-compatibility. 

1398 

1399 See issue `#428 <https://github.com/python-attrs/attrs/issues/428>`_ for 

1400 more details. 

1401 

1402 :param Optional[bool] getstate_setstate: 

1403 .. note:: 

1404 This is usually only interesting for slotted classes and you should 

1405 probably just set *auto_detect* to `True`. 

1406 

1407 If `True`, ``__getstate__`` and 

1408 ``__setstate__`` are generated and attached to the class. This is 

1409 necessary for slotted classes to be pickleable. If left `None`, it's 

1410 `True` by default for slotted classes and ``False`` for dict classes. 

1411 

1412 If *auto_detect* is `True`, and *getstate_setstate* is left `None`, 

1413 and **either** ``__getstate__`` or ``__setstate__`` is detected directly 

1414 on the class (i.e. not inherited), it is set to `False` (this is usually 

1415 what you want). 

1416 

1417 :param on_setattr: A callable that is run whenever the user attempts to set 

1418 an attribute (either by assignment like ``i.x = 42`` or by using 

1419 `setattr` like ``setattr(i, "x", 42)``). It receives the same arguments 

1420 as validators: the instance, the attribute that is being modified, and 

1421 the new value. 

1422 

1423 If no exception is raised, the attribute is set to the return value of 

1424 the callable. 

1425 

1426 If a list of callables is passed, they're automatically wrapped in an 

1427 `attrs.setters.pipe`. 

1428 :type on_setattr: `callable`, or a list of callables, or `None`, or 

1429 `attrs.setters.NO_OP` 

1430 

1431 :param Optional[callable] field_transformer: 

1432 A function that is called with the original class object and all 

1433 fields right before *attrs* finalizes the class. You can use 

1434 this, e.g., to automatically add converters or validators to 

1435 fields based on their types. See `transform-fields` for more details. 

1436 

1437 :param bool match_args: 

1438 If `True` (default), set ``__match_args__`` on the class to support 

1439 :pep:`634` (Structural Pattern Matching). It is a tuple of all 

1440 non-keyword-only ``__init__`` parameter names on Python 3.10 and later. 

1441 Ignored on older Python versions. 

1442 

1443 .. versionadded:: 16.0.0 *slots* 

1444 .. versionadded:: 16.1.0 *frozen* 

1445 .. versionadded:: 16.3.0 *str* 

1446 .. versionadded:: 16.3.0 Support for ``__attrs_post_init__``. 

1447 .. versionchanged:: 17.1.0 

1448 *hash* supports ``None`` as value which is also the default now. 

1449 .. versionadded:: 17.3.0 *auto_attribs* 

1450 .. versionchanged:: 18.1.0 

1451 If *these* is passed, no attributes are deleted from the class body. 

1452 .. versionchanged:: 18.1.0 If *these* is ordered, the order is retained. 

1453 .. versionadded:: 18.2.0 *weakref_slot* 

1454 .. deprecated:: 18.2.0 

1455 ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` now raise a 

1456 `DeprecationWarning` if the classes compared are subclasses of 

1457 each other. ``__eq`` and ``__ne__`` never tried to compared subclasses 

1458 to each other. 

1459 .. versionchanged:: 19.2.0 

1460 ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` now do not consider 

1461 subclasses comparable anymore. 

1462 .. versionadded:: 18.2.0 *kw_only* 

1463 .. versionadded:: 18.2.0 *cache_hash* 

1464 .. versionadded:: 19.1.0 *auto_exc* 

1465 .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01. 

1466 .. versionadded:: 19.2.0 *eq* and *order* 

1467 .. versionadded:: 20.1.0 *auto_detect* 

1468 .. versionadded:: 20.1.0 *collect_by_mro* 

1469 .. versionadded:: 20.1.0 *getstate_setstate* 

1470 .. versionadded:: 20.1.0 *on_setattr* 

1471 .. versionadded:: 20.3.0 *field_transformer* 

1472 .. versionchanged:: 21.1.0 

1473 ``init=False`` injects ``__attrs_init__`` 

1474 .. versionchanged:: 21.1.0 Support for ``__attrs_pre_init__`` 

1475 .. versionchanged:: 21.1.0 *cmp* undeprecated 

1476 .. versionadded:: 21.3.0 *match_args* 

1477 .. versionadded:: 22.2.0 

1478 *unsafe_hash* as an alias for *hash* (for :pep:`681` compliance). 

1479 """ 

1480 eq_, order_ = _determine_attrs_eq_order(cmp, eq, order, None) 

1481 

1482 # unsafe_hash takes precedence due to PEP 681. 

1483 if unsafe_hash is not None: 

1484 hash = unsafe_hash 

1485 

1486 if isinstance(on_setattr, (list, tuple)): 

1487 on_setattr = setters.pipe(*on_setattr) 

1488 

1489 def wrap(cls): 

1490 is_frozen = frozen or _has_frozen_base_class(cls) 

1491 is_exc = auto_exc is True and issubclass(cls, BaseException) 

1492 has_own_setattr = auto_detect and _has_own_attribute( 

1493 cls, "__setattr__" 

1494 ) 

1495 

1496 if has_own_setattr and is_frozen: 

1497 raise ValueError("Can't freeze a class with a custom __setattr__.") 

1498 

1499 builder = _ClassBuilder( 

1500 cls, 

1501 these, 

1502 slots, 

1503 is_frozen, 

1504 weakref_slot, 

1505 _determine_whether_to_implement( 

1506 cls, 

1507 getstate_setstate, 

1508 auto_detect, 

1509 ("__getstate__", "__setstate__"), 

1510 default=slots, 

1511 ), 

1512 auto_attribs, 

1513 kw_only, 

1514 cache_hash, 

1515 is_exc, 

1516 collect_by_mro, 

1517 on_setattr, 

1518 has_own_setattr, 

1519 field_transformer, 

1520 ) 

1521 if _determine_whether_to_implement( 

1522 cls, repr, auto_detect, ("__repr__",) 

1523 ): 

1524 builder.add_repr(repr_ns) 

1525 if str is True: 

1526 builder.add_str() 

1527 

1528 eq = _determine_whether_to_implement( 

1529 cls, eq_, auto_detect, ("__eq__", "__ne__") 

1530 ) 

1531 if not is_exc and eq is True: 

1532 builder.add_eq() 

1533 if not is_exc and _determine_whether_to_implement( 

1534 cls, order_, auto_detect, ("__lt__", "__le__", "__gt__", "__ge__") 

1535 ): 

1536 builder.add_order() 

1537 

1538 builder.add_setattr() 

1539 

1540 nonlocal hash 

1541 if ( 

1542 hash is None 

1543 and auto_detect is True 

1544 and _has_own_attribute(cls, "__hash__") 

1545 ): 

1546 hash = False 

1547 

1548 if hash is not True and hash is not False and hash is not None: 

1549 # Can't use `hash in` because 1 == True for example. 

1550 raise TypeError( 

1551 "Invalid value for hash. Must be True, False, or None." 

1552 ) 

1553 elif hash is False or (hash is None and eq is False) or is_exc: 

1554 # Don't do anything. Should fall back to __object__'s __hash__ 

1555 # which is by id. 

1556 if cache_hash: 

1557 raise TypeError( 

1558 "Invalid value for cache_hash. To use hash caching," 

1559 " hashing must be either explicitly or implicitly " 

1560 "enabled." 

1561 ) 

1562 elif hash is True or ( 

1563 hash is None and eq is True and is_frozen is True 

1564 ): 

1565 # Build a __hash__ if told so, or if it's safe. 

1566 builder.add_hash() 

1567 else: 

1568 # Raise TypeError on attempts to hash. 

1569 if cache_hash: 

1570 raise TypeError( 

1571 "Invalid value for cache_hash. To use hash caching," 

1572 " hashing must be either explicitly or implicitly " 

1573 "enabled." 

1574 ) 

1575 builder.make_unhashable() 

1576 

1577 if _determine_whether_to_implement( 

1578 cls, init, auto_detect, ("__init__",) 

1579 ): 

1580 builder.add_init() 

1581 else: 

1582 builder.add_attrs_init() 

1583 if cache_hash: 

1584 raise TypeError( 

1585 "Invalid value for cache_hash. To use hash caching," 

1586 " init must be True." 

1587 ) 

1588 

1589 if ( 

1590 PY310 

1591 and match_args 

1592 and not _has_own_attribute(cls, "__match_args__") 

1593 ): 

1594 builder.add_match_args() 

1595 

1596 return builder.build_class() 

1597 

1598 # maybe_cls's type depends on the usage of the decorator. It's a class 

1599 # if it's used as `@attrs` but ``None`` if used as `@attrs()`. 

1600 if maybe_cls is None: 

1601 return wrap 

1602 else: 

1603 return wrap(maybe_cls) 

1604 

1605 

1606_attrs = attrs 

1607""" 

1608Internal alias so we can use it in functions that take an argument called 

1609*attrs*. 

1610""" 

1611 

1612 

1613def _has_frozen_base_class(cls): 

1614 """ 

1615 Check whether *cls* has a frozen ancestor by looking at its 

1616 __setattr__. 

1617 """ 

1618 return cls.__setattr__ is _frozen_setattrs 

1619 

1620 

1621def _generate_unique_filename(cls, func_name): 

1622 """ 

1623 Create a "filename" suitable for a function being generated. 

1624 """ 

1625 return ( 

1626 f"<attrs generated {func_name} {cls.__module__}." 

1627 f"{getattr(cls, '__qualname__', cls.__name__)}>" 

1628 ) 

1629 

1630 

1631def _make_hash(cls, attrs, frozen, cache_hash): 

1632 attrs = tuple( 

1633 a for a in attrs if a.hash is True or (a.hash is None and a.eq is True) 

1634 ) 

1635 

1636 tab = " " 

1637 

1638 unique_filename = _generate_unique_filename(cls, "hash") 

1639 type_hash = hash(unique_filename) 

1640 # If eq is custom generated, we need to include the functions in globs 

1641 globs = {} 

1642 

1643 hash_def = "def __hash__(self" 

1644 hash_func = "hash((" 

1645 closing_braces = "))" 

1646 if not cache_hash: 

1647 hash_def += "):" 

1648 else: 

1649 hash_def += ", *" 

1650 

1651 hash_def += ( 

1652 ", _cache_wrapper=" 

1653 + "__import__('attr._make')._make._CacheHashWrapper):" 

1654 ) 

1655 hash_func = "_cache_wrapper(" + hash_func 

1656 closing_braces += ")" 

1657 

1658 method_lines = [hash_def] 

1659 

1660 def append_hash_computation_lines(prefix, indent): 

1661 """ 

1662 Generate the code for actually computing the hash code. 

1663 Below this will either be returned directly or used to compute 

1664 a value which is then cached, depending on the value of cache_hash 

1665 """ 

1666 

1667 method_lines.extend( 

1668 [ 

1669 indent + prefix + hash_func, 

1670 indent + f" {type_hash},", 

1671 ] 

1672 ) 

1673 

1674 for a in attrs: 

1675 if a.eq_key: 

1676 cmp_name = f"_{a.name}_key" 

1677 globs[cmp_name] = a.eq_key 

1678 method_lines.append( 

1679 indent + f" {cmp_name}(self.{a.name})," 

1680 ) 

1681 else: 

1682 method_lines.append(indent + f" self.{a.name},") 

1683 

1684 method_lines.append(indent + " " + closing_braces) 

1685 

1686 if cache_hash: 

1687 method_lines.append(tab + f"if self.{_hash_cache_field} is None:") 

1688 if frozen: 

1689 append_hash_computation_lines( 

1690 f"object.__setattr__(self, '{_hash_cache_field}', ", tab * 2 

1691 ) 

1692 method_lines.append(tab * 2 + ")") # close __setattr__ 

1693 else: 

1694 append_hash_computation_lines( 

1695 f"self.{_hash_cache_field} = ", tab * 2 

1696 ) 

1697 method_lines.append(tab + f"return self.{_hash_cache_field}") 

1698 else: 

1699 append_hash_computation_lines("return ", tab) 

1700 

1701 script = "\n".join(method_lines) 

1702 return _make_method("__hash__", script, unique_filename, globs) 

1703 

1704 

1705def _add_hash(cls, attrs): 

1706 """ 

1707 Add a hash method to *cls*. 

1708 """ 

1709 cls.__hash__ = _make_hash(cls, attrs, frozen=False, cache_hash=False) 

1710 return cls 

1711 

1712 

1713def _make_ne(): 

1714 """ 

1715 Create __ne__ method. 

1716 """ 

1717 

1718 def __ne__(self, other): 

1719 """ 

1720 Check equality and either forward a NotImplemented or 

1721 return the result negated. 

1722 """ 

1723 result = self.__eq__(other) 

1724 if result is NotImplemented: 

1725 return NotImplemented 

1726 

1727 return not result 

1728 

1729 return __ne__ 

1730 

1731 

1732def _make_eq(cls, attrs): 

1733 """ 

1734 Create __eq__ method for *cls* with *attrs*. 

1735 """ 

1736 attrs = [a for a in attrs if a.eq] 

1737 

1738 unique_filename = _generate_unique_filename(cls, "eq") 

1739 lines = [ 

1740 "def __eq__(self, other):", 

1741 " if other.__class__ is not self.__class__:", 

1742 " return NotImplemented", 

1743 ] 

1744 

1745 # We can't just do a big self.x = other.x and... clause due to 

1746 # irregularities like nan == nan is false but (nan,) == (nan,) is true. 

1747 globs = {} 

1748 if attrs: 

1749 lines.append(" return (") 

1750 others = [" ) == ("] 

1751 for a in attrs: 

1752 if a.eq_key: 

1753 cmp_name = f"_{a.name}_key" 

1754 # Add the key function to the global namespace 

1755 # of the evaluated function. 

1756 globs[cmp_name] = a.eq_key 

1757 lines.append(f" {cmp_name}(self.{a.name}),") 

1758 others.append(f" {cmp_name}(other.{a.name}),") 

1759 else: 

1760 lines.append(f" self.{a.name},") 

1761 others.append(f" other.{a.name},") 

1762 

1763 lines += others + [" )"] 

1764 else: 

1765 lines.append(" return True") 

1766 

1767 script = "\n".join(lines) 

1768 

1769 return _make_method("__eq__", script, unique_filename, globs) 

1770 

1771 

1772def _make_order(cls, attrs): 

1773 """ 

1774 Create ordering methods for *cls* with *attrs*. 

1775 """ 

1776 attrs = [a for a in attrs if a.order] 

1777 

1778 def attrs_to_tuple(obj): 

1779 """ 

1780 Save us some typing. 

1781 """ 

1782 return tuple( 

1783 key(value) if key else value 

1784 for value, key in ( 

1785 (getattr(obj, a.name), a.order_key) for a in attrs 

1786 ) 

1787 ) 

1788 

1789 def __lt__(self, other): 

1790 """ 

1791 Automatically created by attrs. 

1792 """ 

1793 if other.__class__ is self.__class__: 

1794 return attrs_to_tuple(self) < attrs_to_tuple(other) 

1795 

1796 return NotImplemented 

1797 

1798 def __le__(self, other): 

1799 """ 

1800 Automatically created by attrs. 

1801 """ 

1802 if other.__class__ is self.__class__: 

1803 return attrs_to_tuple(self) <= attrs_to_tuple(other) 

1804 

1805 return NotImplemented 

1806 

1807 def __gt__(self, other): 

1808 """ 

1809 Automatically created by attrs. 

1810 """ 

1811 if other.__class__ is self.__class__: 

1812 return attrs_to_tuple(self) > attrs_to_tuple(other) 

1813 

1814 return NotImplemented 

1815 

1816 def __ge__(self, other): 

1817 """ 

1818 Automatically created by attrs. 

1819 """ 

1820 if other.__class__ is self.__class__: 

1821 return attrs_to_tuple(self) >= attrs_to_tuple(other) 

1822 

1823 return NotImplemented 

1824 

1825 return __lt__, __le__, __gt__, __ge__ 

1826 

1827 

1828def _add_eq(cls, attrs=None): 

1829 """ 

1830 Add equality methods to *cls* with *attrs*. 

1831 """ 

1832 if attrs is None: 

1833 attrs = cls.__attrs_attrs__ 

1834 

1835 cls.__eq__ = _make_eq(cls, attrs) 

1836 cls.__ne__ = _make_ne() 

1837 

1838 return cls 

1839 

1840 

1841def _make_repr(attrs, ns, cls): 

1842 unique_filename = _generate_unique_filename(cls, "repr") 

1843 # Figure out which attributes to include, and which function to use to 

1844 # format them. The a.repr value can be either bool or a custom 

1845 # callable. 

1846 attr_names_with_reprs = tuple( 

1847 (a.name, (repr if a.repr is True else a.repr), a.init) 

1848 for a in attrs 

1849 if a.repr is not False 

1850 ) 

1851 globs = { 

1852 name + "_repr": r for name, r, _ in attr_names_with_reprs if r != repr 

1853 } 

1854 globs["_compat"] = _compat 

1855 globs["AttributeError"] = AttributeError 

1856 globs["NOTHING"] = NOTHING 

1857 attribute_fragments = [] 

1858 for name, r, i in attr_names_with_reprs: 

1859 accessor = ( 

1860 "self." + name if i else 'getattr(self, "' + name + '", NOTHING)' 

1861 ) 

1862 fragment = ( 

1863 "%s={%s!r}" % (name, accessor) 

1864 if r == repr 

1865 else "%s={%s_repr(%s)}" % (name, name, accessor) 

1866 ) 

1867 attribute_fragments.append(fragment) 

1868 repr_fragment = ", ".join(attribute_fragments) 

1869 

1870 if ns is None: 

1871 cls_name_fragment = '{self.__class__.__qualname__.rsplit(">.", 1)[-1]}' 

1872 else: 

1873 cls_name_fragment = ns + ".{self.__class__.__name__}" 

1874 

1875 lines = [ 

1876 "def __repr__(self):", 

1877 " try:", 

1878 " already_repring = _compat.repr_context.already_repring", 

1879 " except AttributeError:", 

1880 " already_repring = {id(self),}", 

1881 " _compat.repr_context.already_repring = already_repring", 

1882 " else:", 

1883 " if id(self) in already_repring:", 

1884 " return '...'", 

1885 " else:", 

1886 " already_repring.add(id(self))", 

1887 " try:", 

1888 f" return f'{cls_name_fragment}({repr_fragment})'", 

1889 " finally:", 

1890 " already_repring.remove(id(self))", 

1891 ] 

1892 

1893 return _make_method( 

1894 "__repr__", "\n".join(lines), unique_filename, globs=globs 

1895 ) 

1896 

1897 

1898def _add_repr(cls, ns=None, attrs=None): 

1899 """ 

1900 Add a repr method to *cls*. 

1901 """ 

1902 if attrs is None: 

1903 attrs = cls.__attrs_attrs__ 

1904 

1905 cls.__repr__ = _make_repr(attrs, ns, cls) 

1906 return cls 

1907 

1908 

1909def fields(cls): 

1910 """ 

1911 Return the tuple of *attrs* attributes for a class. 

1912 

1913 The tuple also allows accessing the fields by their names (see below for 

1914 examples). 

1915 

1916 :param type cls: Class to introspect. 

1917 

1918 :raise TypeError: If *cls* is not a class. 

1919 :raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs* 

1920 class. 

1921 

1922 :rtype: tuple (with name accessors) of `attrs.Attribute` 

1923 

1924 .. versionchanged:: 16.2.0 Returned tuple allows accessing the fields 

1925 by name. 

1926 .. versionchanged:: 23.1.0 Add support for generic classes. 

1927 """ 

1928 generic_base = get_generic_base(cls) 

1929 

1930 if generic_base is None and not isinstance(cls, type): 

1931 raise TypeError("Passed object must be a class.") 

1932 

1933 attrs = getattr(cls, "__attrs_attrs__", None) 

1934 

1935 if attrs is None: 

1936 if generic_base is not None: 

1937 attrs = getattr(generic_base, "__attrs_attrs__", None) 

1938 if attrs is not None: 

1939 # Even though this is global state, stick it on here to speed 

1940 # it up. We rely on `cls` being cached for this to be 

1941 # efficient. 

1942 cls.__attrs_attrs__ = attrs 

1943 return attrs 

1944 raise NotAnAttrsClassError(f"{cls!r} is not an attrs-decorated class.") 

1945 

1946 return attrs 

1947 

1948 

1949def fields_dict(cls): 

1950 """ 

1951 Return an ordered dictionary of *attrs* attributes for a class, whose 

1952 keys are the attribute names. 

1953 

1954 :param type cls: Class to introspect. 

1955 

1956 :raise TypeError: If *cls* is not a class. 

1957 :raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs* 

1958 class. 

1959 

1960 :rtype: dict 

1961 

1962 .. versionadded:: 18.1.0 

1963 """ 

1964 if not isinstance(cls, type): 

1965 raise TypeError("Passed object must be a class.") 

1966 attrs = getattr(cls, "__attrs_attrs__", None) 

1967 if attrs is None: 

1968 raise NotAnAttrsClassError(f"{cls!r} is not an attrs-decorated class.") 

1969 return {a.name: a for a in attrs} 

1970 

1971 

1972def validate(inst): 

1973 """ 

1974 Validate all attributes on *inst* that have a validator. 

1975 

1976 Leaves all exceptions through. 

1977 

1978 :param inst: Instance of a class with *attrs* attributes. 

1979 """ 

1980 if _config._run_validators is False: 

1981 return 

1982 

1983 for a in fields(inst.__class__): 

1984 v = a.validator 

1985 if v is not None: 

1986 v(inst, a, getattr(inst, a.name)) 

1987 

1988 

1989def _is_slot_cls(cls): 

1990 return "__slots__" in cls.__dict__ 

1991 

1992 

1993def _is_slot_attr(a_name, base_attr_map): 

1994 """ 

1995 Check if the attribute name comes from a slot class. 

1996 """ 

1997 return a_name in base_attr_map and _is_slot_cls(base_attr_map[a_name]) 

1998 

1999 

2000def _make_init( 

2001 cls, 

2002 attrs, 

2003 pre_init, 

2004 post_init, 

2005 frozen, 

2006 slots, 

2007 cache_hash, 

2008 base_attr_map, 

2009 is_exc, 

2010 cls_on_setattr, 

2011 attrs_init, 

2012): 

2013 has_cls_on_setattr = ( 

2014 cls_on_setattr is not None and cls_on_setattr is not setters.NO_OP 

2015 ) 

2016 

2017 if frozen and has_cls_on_setattr: 

2018 raise ValueError("Frozen classes can't use on_setattr.") 

2019 

2020 needs_cached_setattr = cache_hash or frozen 

2021 filtered_attrs = [] 

2022 attr_dict = {} 

2023 for a in attrs: 

2024 if not a.init and a.default is NOTHING: 

2025 continue 

2026 

2027 filtered_attrs.append(a) 

2028 attr_dict[a.name] = a 

2029 

2030 if a.on_setattr is not None: 

2031 if frozen is True: 

2032 raise ValueError("Frozen classes can't use on_setattr.") 

2033 

2034 needs_cached_setattr = True 

2035 elif has_cls_on_setattr and a.on_setattr is not setters.NO_OP: 

2036 needs_cached_setattr = True 

2037 

2038 unique_filename = _generate_unique_filename(cls, "init") 

2039 

2040 script, globs, annotations = _attrs_to_init_script( 

2041 filtered_attrs, 

2042 frozen, 

2043 slots, 

2044 pre_init, 

2045 post_init, 

2046 cache_hash, 

2047 base_attr_map, 

2048 is_exc, 

2049 needs_cached_setattr, 

2050 has_cls_on_setattr, 

2051 attrs_init, 

2052 ) 

2053 if cls.__module__ in sys.modules: 

2054 # This makes typing.get_type_hints(CLS.__init__) resolve string types. 

2055 globs.update(sys.modules[cls.__module__].__dict__) 

2056 

2057 globs.update({"NOTHING": NOTHING, "attr_dict": attr_dict}) 

2058 

2059 if needs_cached_setattr: 

2060 # Save the lookup overhead in __init__ if we need to circumvent 

2061 # setattr hooks. 

2062 globs["_cached_setattr_get"] = _obj_setattr.__get__ 

2063 

2064 init = _make_method( 

2065 "__attrs_init__" if attrs_init else "__init__", 

2066 script, 

2067 unique_filename, 

2068 globs, 

2069 ) 

2070 init.__annotations__ = annotations 

2071 

2072 return init 

2073 

2074 

2075def _setattr(attr_name, value_var, has_on_setattr): 

2076 """ 

2077 Use the cached object.setattr to set *attr_name* to *value_var*. 

2078 """ 

2079 return f"_setattr('{attr_name}', {value_var})" 

2080 

2081 

2082def _setattr_with_converter(attr_name, value_var, has_on_setattr): 

2083 """ 

2084 Use the cached object.setattr to set *attr_name* to *value_var*, but run 

2085 its converter first. 

2086 """ 

2087 return "_setattr('%s', %s(%s))" % ( 

2088 attr_name, 

2089 _init_converter_pat % (attr_name,), 

2090 value_var, 

2091 ) 

2092 

2093 

2094def _assign(attr_name, value, has_on_setattr): 

2095 """ 

2096 Unless *attr_name* has an on_setattr hook, use normal assignment. Otherwise 

2097 relegate to _setattr. 

2098 """ 

2099 if has_on_setattr: 

2100 return _setattr(attr_name, value, True) 

2101 

2102 return f"self.{attr_name} = {value}" 

2103 

2104 

2105def _assign_with_converter(attr_name, value_var, has_on_setattr): 

2106 """ 

2107 Unless *attr_name* has an on_setattr hook, use normal assignment after 

2108 conversion. Otherwise relegate to _setattr_with_converter. 

2109 """ 

2110 if has_on_setattr: 

2111 return _setattr_with_converter(attr_name, value_var, True) 

2112 

2113 return "self.%s = %s(%s)" % ( 

2114 attr_name, 

2115 _init_converter_pat % (attr_name,), 

2116 value_var, 

2117 ) 

2118 

2119 

2120def _attrs_to_init_script( 

2121 attrs, 

2122 frozen, 

2123 slots, 

2124 pre_init, 

2125 post_init, 

2126 cache_hash, 

2127 base_attr_map, 

2128 is_exc, 

2129 needs_cached_setattr, 

2130 has_cls_on_setattr, 

2131 attrs_init, 

2132): 

2133 """ 

2134 Return a script of an initializer for *attrs* and a dict of globals. 

2135 

2136 The globals are expected by the generated script. 

2137 

2138 If *frozen* is True, we cannot set the attributes directly so we use 

2139 a cached ``object.__setattr__``. 

2140 """ 

2141 lines = [] 

2142 if pre_init: 

2143 lines.append("self.__attrs_pre_init__()") 

2144 

2145 if needs_cached_setattr: 

2146 lines.append( 

2147 # Circumvent the __setattr__ descriptor to save one lookup per 

2148 # assignment. 

2149 # Note _setattr will be used again below if cache_hash is True 

2150 "_setattr = _cached_setattr_get(self)" 

2151 ) 

2152 

2153 if frozen is True: 

2154 if slots is True: 

2155 fmt_setter = _setattr 

2156 fmt_setter_with_converter = _setattr_with_converter 

2157 else: 

2158 # Dict frozen classes assign directly to __dict__. 

2159 # But only if the attribute doesn't come from an ancestor slot 

2160 # class. 

2161 # Note _inst_dict will be used again below if cache_hash is True 

2162 lines.append("_inst_dict = self.__dict__") 

2163 

2164 def fmt_setter(attr_name, value_var, has_on_setattr): 

2165 if _is_slot_attr(attr_name, base_attr_map): 

2166 return _setattr(attr_name, value_var, has_on_setattr) 

2167 

2168 return f"_inst_dict['{attr_name}'] = {value_var}" 

2169 

2170 def fmt_setter_with_converter( 

2171 attr_name, value_var, has_on_setattr 

2172 ): 

2173 if has_on_setattr or _is_slot_attr(attr_name, base_attr_map): 

2174 return _setattr_with_converter( 

2175 attr_name, value_var, has_on_setattr 

2176 ) 

2177 

2178 return "_inst_dict['%s'] = %s(%s)" % ( 

2179 attr_name, 

2180 _init_converter_pat % (attr_name,), 

2181 value_var, 

2182 ) 

2183 

2184 else: 

2185 # Not frozen. 

2186 fmt_setter = _assign 

2187 fmt_setter_with_converter = _assign_with_converter 

2188 

2189 args = [] 

2190 kw_only_args = [] 

2191 attrs_to_validate = [] 

2192 

2193 # This is a dictionary of names to validator and converter callables. 

2194 # Injecting this into __init__ globals lets us avoid lookups. 

2195 names_for_globals = {} 

2196 annotations = {"return": None} 

2197 

2198 for a in attrs: 

2199 if a.validator: 

2200 attrs_to_validate.append(a) 

2201 

2202 attr_name = a.name 

2203 has_on_setattr = a.on_setattr is not None or ( 

2204 a.on_setattr is not setters.NO_OP and has_cls_on_setattr 

2205 ) 

2206 # a.alias is set to maybe-mangled attr_name in _ClassBuilder if not 

2207 # explicitly provided 

2208 arg_name = a.alias 

2209 

2210 has_factory = isinstance(a.default, Factory) 

2211 if has_factory and a.default.takes_self: 

2212 maybe_self = "self" 

2213 else: 

2214 maybe_self = "" 

2215 

2216 if a.init is False: 

2217 if has_factory: 

2218 init_factory_name = _init_factory_pat % (a.name,) 

2219 if a.converter is not None: 

2220 lines.append( 

2221 fmt_setter_with_converter( 

2222 attr_name, 

2223 init_factory_name + f"({maybe_self})", 

2224 has_on_setattr, 

2225 ) 

2226 ) 

2227 conv_name = _init_converter_pat % (a.name,) 

2228 names_for_globals[conv_name] = a.converter 

2229 else: 

2230 lines.append( 

2231 fmt_setter( 

2232 attr_name, 

2233 init_factory_name + f"({maybe_self})", 

2234 has_on_setattr, 

2235 ) 

2236 ) 

2237 names_for_globals[init_factory_name] = a.default.factory 

2238 else: 

2239 if a.converter is not None: 

2240 lines.append( 

2241 fmt_setter_with_converter( 

2242 attr_name, 

2243 f"attr_dict['{attr_name}'].default", 

2244 has_on_setattr, 

2245 ) 

2246 ) 

2247 conv_name = _init_converter_pat % (a.name,) 

2248 names_for_globals[conv_name] = a.converter 

2249 else: 

2250 lines.append( 

2251 fmt_setter( 

2252 attr_name, 

2253 f"attr_dict['{attr_name}'].default", 

2254 has_on_setattr, 

2255 ) 

2256 ) 

2257 elif a.default is not NOTHING and not has_factory: 

2258 arg = f"{arg_name}=attr_dict['{attr_name}'].default" 

2259 if a.kw_only: 

2260 kw_only_args.append(arg) 

2261 else: 

2262 args.append(arg) 

2263 

2264 if a.converter is not None: 

2265 lines.append( 

2266 fmt_setter_with_converter( 

2267 attr_name, arg_name, has_on_setattr 

2268 ) 

2269 ) 

2270 names_for_globals[ 

2271 _init_converter_pat % (a.name,) 

2272 ] = a.converter 

2273 else: 

2274 lines.append(fmt_setter(attr_name, arg_name, has_on_setattr)) 

2275 

2276 elif has_factory: 

2277 arg = f"{arg_name}=NOTHING" 

2278 if a.kw_only: 

2279 kw_only_args.append(arg) 

2280 else: 

2281 args.append(arg) 

2282 lines.append(f"if {arg_name} is not NOTHING:") 

2283 

2284 init_factory_name = _init_factory_pat % (a.name,) 

2285 if a.converter is not None: 

2286 lines.append( 

2287 " " 

2288 + fmt_setter_with_converter( 

2289 attr_name, arg_name, has_on_setattr 

2290 ) 

2291 ) 

2292 lines.append("else:") 

2293 lines.append( 

2294 " " 

2295 + fmt_setter_with_converter( 

2296 attr_name, 

2297 init_factory_name + "(" + maybe_self + ")", 

2298 has_on_setattr, 

2299 ) 

2300 ) 

2301 names_for_globals[ 

2302 _init_converter_pat % (a.name,) 

2303 ] = a.converter 

2304 else: 

2305 lines.append( 

2306 " " + fmt_setter(attr_name, arg_name, has_on_setattr) 

2307 ) 

2308 lines.append("else:") 

2309 lines.append( 

2310 " " 

2311 + fmt_setter( 

2312 attr_name, 

2313 init_factory_name + "(" + maybe_self + ")", 

2314 has_on_setattr, 

2315 ) 

2316 ) 

2317 names_for_globals[init_factory_name] = a.default.factory 

2318 else: 

2319 if a.kw_only: 

2320 kw_only_args.append(arg_name) 

2321 else: 

2322 args.append(arg_name) 

2323 

2324 if a.converter is not None: 

2325 lines.append( 

2326 fmt_setter_with_converter( 

2327 attr_name, arg_name, has_on_setattr 

2328 ) 

2329 ) 

2330 names_for_globals[ 

2331 _init_converter_pat % (a.name,) 

2332 ] = a.converter 

2333 else: 

2334 lines.append(fmt_setter(attr_name, arg_name, has_on_setattr)) 

2335 

2336 if a.init is True: 

2337 if a.type is not None and a.converter is None: 

2338 annotations[arg_name] = a.type 

2339 elif a.converter is not None: 

2340 # Try to get the type from the converter. 

2341 t = _AnnotationExtractor(a.converter).get_first_param_type() 

2342 if t: 

2343 annotations[arg_name] = t 

2344 

2345 if attrs_to_validate: # we can skip this if there are no validators. 

2346 names_for_globals["_config"] = _config 

2347 lines.append("if _config._run_validators is True:") 

2348 for a in attrs_to_validate: 

2349 val_name = "__attr_validator_" + a.name 

2350 attr_name = "__attr_" + a.name 

2351 lines.append(f" {val_name}(self, {attr_name}, self.{a.name})") 

2352 names_for_globals[val_name] = a.validator 

2353 names_for_globals[attr_name] = a 

2354 

2355 if post_init: 

2356 lines.append("self.__attrs_post_init__()") 

2357 

2358 # because this is set only after __attrs_post_init__ is called, a crash 

2359 # will result if post-init tries to access the hash code. This seemed 

2360 # preferable to setting this beforehand, in which case alteration to 

2361 # field values during post-init combined with post-init accessing the 

2362 # hash code would result in silent bugs. 

2363 if cache_hash: 

2364 if frozen: 

2365 if slots: 

2366 # if frozen and slots, then _setattr defined above 

2367 init_hash_cache = "_setattr('%s', %s)" 

2368 else: 

2369 # if frozen and not slots, then _inst_dict defined above 

2370 init_hash_cache = "_inst_dict['%s'] = %s" 

2371 else: 

2372 init_hash_cache = "self.%s = %s" 

2373 lines.append(init_hash_cache % (_hash_cache_field, "None")) 

2374 

2375 # For exceptions we rely on BaseException.__init__ for proper 

2376 # initialization. 

2377 if is_exc: 

2378 vals = ",".join(f"self.{a.name}" for a in attrs if a.init) 

2379 

2380 lines.append(f"BaseException.__init__(self, {vals})") 

2381 

2382 args = ", ".join(args) 

2383 if kw_only_args: 

2384 args += "%s*, %s" % ( 

2385 ", " if args else "", # leading comma 

2386 ", ".join(kw_only_args), # kw_only args 

2387 ) 

2388 

2389 return ( 

2390 "def %s(self, %s):\n %s\n" 

2391 % ( 

2392 ("__attrs_init__" if attrs_init else "__init__"), 

2393 args, 

2394 "\n ".join(lines) if lines else "pass", 

2395 ), 

2396 names_for_globals, 

2397 annotations, 

2398 ) 

2399 

2400 

2401def _default_init_alias_for(name: str) -> str: 

2402 """ 

2403 The default __init__ parameter name for a field. 

2404 

2405 This performs private-name adjustment via leading-unscore stripping, 

2406 and is the default value of Attribute.alias if not provided. 

2407 """ 

2408 

2409 return name.lstrip("_") 

2410 

2411 

2412class Attribute: 

2413 """ 

2414 *Read-only* representation of an attribute. 

2415 

2416 .. warning:: 

2417 

2418 You should never instantiate this class yourself. 

2419 

2420 The class has *all* arguments of `attr.ib` (except for ``factory`` 

2421 which is only syntactic sugar for ``default=Factory(...)`` plus the 

2422 following: 

2423 

2424 - ``name`` (`str`): The name of the attribute. 

2425 - ``alias`` (`str`): The __init__ parameter name of the attribute, after 

2426 any explicit overrides and default private-attribute-name handling. 

2427 - ``inherited`` (`bool`): Whether or not that attribute has been inherited 

2428 from a base class. 

2429 - ``eq_key`` and ``order_key`` (`typing.Callable` or `None`): The callables 

2430 that are used for comparing and ordering objects by this attribute, 

2431 respectively. These are set by passing a callable to `attr.ib`'s ``eq``, 

2432 ``order``, or ``cmp`` arguments. See also :ref:`comparison customization 

2433 <custom-comparison>`. 

2434 

2435 Instances of this class are frequently used for introspection purposes 

2436 like: 

2437 

2438 - `fields` returns a tuple of them. 

2439 - Validators get them passed as the first argument. 

2440 - The :ref:`field transformer <transform-fields>` hook receives a list of 

2441 them. 

2442 - The ``alias`` property exposes the __init__ parameter name of the field, 

2443 with any overrides and default private-attribute handling applied. 

2444 

2445 

2446 .. versionadded:: 20.1.0 *inherited* 

2447 .. versionadded:: 20.1.0 *on_setattr* 

2448 .. versionchanged:: 20.2.0 *inherited* is not taken into account for 

2449 equality checks and hashing anymore. 

2450 .. versionadded:: 21.1.0 *eq_key* and *order_key* 

2451 .. versionadded:: 22.2.0 *alias* 

2452 

2453 For the full version history of the fields, see `attr.ib`. 

2454 """ 

2455 

2456 __slots__ = ( 

2457 "name", 

2458 "default", 

2459 "validator", 

2460 "repr", 

2461 "eq", 

2462 "eq_key", 

2463 "order", 

2464 "order_key", 

2465 "hash", 

2466 "init", 

2467 "metadata", 

2468 "type", 

2469 "converter", 

2470 "kw_only", 

2471 "inherited", 

2472 "on_setattr", 

2473 "alias", 

2474 ) 

2475 

2476 def __init__( 

2477 self, 

2478 name, 

2479 default, 

2480 validator, 

2481 repr, 

2482 cmp, # XXX: unused, remove along with other cmp code. 

2483 hash, 

2484 init, 

2485 inherited, 

2486 metadata=None, 

2487 type=None, 

2488 converter=None, 

2489 kw_only=False, 

2490 eq=None, 

2491 eq_key=None, 

2492 order=None, 

2493 order_key=None, 

2494 on_setattr=None, 

2495 alias=None, 

2496 ): 

2497 eq, eq_key, order, order_key = _determine_attrib_eq_order( 

2498 cmp, eq_key or eq, order_key or order, True 

2499 ) 

2500 

2501 # Cache this descriptor here to speed things up later. 

2502 bound_setattr = _obj_setattr.__get__(self) 

2503 

2504 # Despite the big red warning, people *do* instantiate `Attribute` 

2505 # themselves. 

2506 bound_setattr("name", name) 

2507 bound_setattr("default", default) 

2508 bound_setattr("validator", validator) 

2509 bound_setattr("repr", repr) 

2510 bound_setattr("eq", eq) 

2511 bound_setattr("eq_key", eq_key) 

2512 bound_setattr("order", order) 

2513 bound_setattr("order_key", order_key) 

2514 bound_setattr("hash", hash) 

2515 bound_setattr("init", init) 

2516 bound_setattr("converter", converter) 

2517 bound_setattr( 

2518 "metadata", 

2519 ( 

2520 types.MappingProxyType(dict(metadata)) # Shallow copy 

2521 if metadata 

2522 else _empty_metadata_singleton 

2523 ), 

2524 ) 

2525 bound_setattr("type", type) 

2526 bound_setattr("kw_only", kw_only) 

2527 bound_setattr("inherited", inherited) 

2528 bound_setattr("on_setattr", on_setattr) 

2529 bound_setattr("alias", alias) 

2530 

2531 def __setattr__(self, name, value): 

2532 raise FrozenInstanceError() 

2533 

2534 @classmethod 

2535 def from_counting_attr(cls, name, ca, type=None): 

2536 # type holds the annotated value. deal with conflicts: 

2537 if type is None: 

2538 type = ca.type 

2539 elif ca.type is not None: 

2540 raise ValueError( 

2541 "Type annotation and type argument cannot both be present" 

2542 ) 

2543 inst_dict = { 

2544 k: getattr(ca, k) 

2545 for k in Attribute.__slots__ 

2546 if k 

2547 not in ( 

2548 "name", 

2549 "validator", 

2550 "default", 

2551 "type", 

2552 "inherited", 

2553 ) # exclude methods and deprecated alias 

2554 } 

2555 return cls( 

2556 name=name, 

2557 validator=ca._validator, 

2558 default=ca._default, 

2559 type=type, 

2560 cmp=None, 

2561 inherited=False, 

2562 **inst_dict, 

2563 ) 

2564 

2565 # Don't use attrs.evolve since fields(Attribute) doesn't work 

2566 def evolve(self, **changes): 

2567 """ 

2568 Copy *self* and apply *changes*. 

2569 

2570 This works similarly to `attrs.evolve` but that function does not work 

2571 with `Attribute`. 

2572 

2573 It is mainly meant to be used for `transform-fields`. 

2574 

2575 .. versionadded:: 20.3.0 

2576 """ 

2577 new = copy.copy(self) 

2578 

2579 new._setattrs(changes.items()) 

2580 

2581 return new 

2582 

2583 # Don't use _add_pickle since fields(Attribute) doesn't work 

2584 def __getstate__(self): 

2585 """ 

2586 Play nice with pickle. 

2587 """ 

2588 return tuple( 

2589 getattr(self, name) if name != "metadata" else dict(self.metadata) 

2590 for name in self.__slots__ 

2591 ) 

2592 

2593 def __setstate__(self, state): 

2594 """ 

2595 Play nice with pickle. 

2596 """ 

2597 self._setattrs(zip(self.__slots__, state)) 

2598 

2599 def _setattrs(self, name_values_pairs): 

2600 bound_setattr = _obj_setattr.__get__(self) 

2601 for name, value in name_values_pairs: 

2602 if name != "metadata": 

2603 bound_setattr(name, value) 

2604 else: 

2605 bound_setattr( 

2606 name, 

2607 types.MappingProxyType(dict(value)) 

2608 if value 

2609 else _empty_metadata_singleton, 

2610 ) 

2611 

2612 

2613_a = [ 

2614 Attribute( 

2615 name=name, 

2616 default=NOTHING, 

2617 validator=None, 

2618 repr=True, 

2619 cmp=None, 

2620 eq=True, 

2621 order=False, 

2622 hash=(name != "metadata"), 

2623 init=True, 

2624 inherited=False, 

2625 alias=_default_init_alias_for(name), 

2626 ) 

2627 for name in Attribute.__slots__ 

2628] 

2629 

2630Attribute = _add_hash( 

2631 _add_eq( 

2632 _add_repr(Attribute, attrs=_a), 

2633 attrs=[a for a in _a if a.name != "inherited"], 

2634 ), 

2635 attrs=[a for a in _a if a.hash and a.name != "inherited"], 

2636) 

2637 

2638 

2639class _CountingAttr: 

2640 """ 

2641 Intermediate representation of attributes that uses a counter to preserve 

2642 the order in which the attributes have been defined. 

2643 

2644 *Internal* data structure of the attrs library. Running into is most 

2645 likely the result of a bug like a forgotten `@attr.s` decorator. 

2646 """ 

2647 

2648 __slots__ = ( 

2649 "counter", 

2650 "_default", 

2651 "repr", 

2652 "eq", 

2653 "eq_key", 

2654 "order", 

2655 "order_key", 

2656 "hash", 

2657 "init", 

2658 "metadata", 

2659 "_validator", 

2660 "converter", 

2661 "type", 

2662 "kw_only", 

2663 "on_setattr", 

2664 "alias", 

2665 ) 

2666 __attrs_attrs__ = tuple( 

2667 Attribute( 

2668 name=name, 

2669 alias=_default_init_alias_for(name), 

2670 default=NOTHING, 

2671 validator=None, 

2672 repr=True, 

2673 cmp=None, 

2674 hash=True, 

2675 init=True, 

2676 kw_only=False, 

2677 eq=True, 

2678 eq_key=None, 

2679 order=False, 

2680 order_key=None, 

2681 inherited=False, 

2682 on_setattr=None, 

2683 ) 

2684 for name in ( 

2685 "counter", 

2686 "_default", 

2687 "repr", 

2688 "eq", 

2689 "order", 

2690 "hash", 

2691 "init", 

2692 "on_setattr", 

2693 "alias", 

2694 ) 

2695 ) + ( 

2696 Attribute( 

2697 name="metadata", 

2698 alias="metadata", 

2699 default=None, 

2700 validator=None, 

2701 repr=True, 

2702 cmp=None, 

2703 hash=False, 

2704 init=True, 

2705 kw_only=False, 

2706 eq=True, 

2707 eq_key=None, 

2708 order=False, 

2709 order_key=None, 

2710 inherited=False, 

2711 on_setattr=None, 

2712 ), 

2713 ) 

2714 cls_counter = 0 

2715 

2716 def __init__( 

2717 self, 

2718 default, 

2719 validator, 

2720 repr, 

2721 cmp, 

2722 hash, 

2723 init, 

2724 converter, 

2725 metadata, 

2726 type, 

2727 kw_only, 

2728 eq, 

2729 eq_key, 

2730 order, 

2731 order_key, 

2732 on_setattr, 

2733 alias, 

2734 ): 

2735 _CountingAttr.cls_counter += 1 

2736 self.counter = _CountingAttr.cls_counter 

2737 self._default = default 

2738 self._validator = validator 

2739 self.converter = converter 

2740 self.repr = repr 

2741 self.eq = eq 

2742 self.eq_key = eq_key 

2743 self.order = order 

2744 self.order_key = order_key 

2745 self.hash = hash 

2746 self.init = init 

2747 self.metadata = metadata 

2748 self.type = type 

2749 self.kw_only = kw_only 

2750 self.on_setattr = on_setattr 

2751 self.alias = alias 

2752 

2753 def validator(self, meth): 

2754 """ 

2755 Decorator that adds *meth* to the list of validators. 

2756 

2757 Returns *meth* unchanged. 

2758 

2759 .. versionadded:: 17.1.0 

2760 """ 

2761 if self._validator is None: 

2762 self._validator = meth 

2763 else: 

2764 self._validator = and_(self._validator, meth) 

2765 return meth 

2766 

2767 def default(self, meth): 

2768 """ 

2769 Decorator that allows to set the default for an attribute. 

2770 

2771 Returns *meth* unchanged. 

2772 

2773 :raises DefaultAlreadySetError: If default has been set before. 

2774 

2775 .. versionadded:: 17.1.0 

2776 """ 

2777 if self._default is not NOTHING: 

2778 raise DefaultAlreadySetError() 

2779 

2780 self._default = Factory(meth, takes_self=True) 

2781 

2782 return meth 

2783 

2784 

2785_CountingAttr = _add_eq(_add_repr(_CountingAttr)) 

2786 

2787 

2788class Factory: 

2789 """ 

2790 Stores a factory callable. 

2791 

2792 If passed as the default value to `attrs.field`, the factory is used to 

2793 generate a new value. 

2794 

2795 :param callable factory: A callable that takes either none or exactly one 

2796 mandatory positional argument depending on *takes_self*. 

2797 :param bool takes_self: Pass the partially initialized instance that is 

2798 being initialized as a positional argument. 

2799 

2800 .. versionadded:: 17.1.0 *takes_self* 

2801 """ 

2802 

2803 __slots__ = ("factory", "takes_self") 

2804 

2805 def __init__(self, factory, takes_self=False): 

2806 self.factory = factory 

2807 self.takes_self = takes_self 

2808 

2809 def __getstate__(self): 

2810 """ 

2811 Play nice with pickle. 

2812 """ 

2813 return tuple(getattr(self, name) for name in self.__slots__) 

2814 

2815 def __setstate__(self, state): 

2816 """ 

2817 Play nice with pickle. 

2818 """ 

2819 for name, value in zip(self.__slots__, state): 

2820 setattr(self, name, value) 

2821 

2822 

2823_f = [ 

2824 Attribute( 

2825 name=name, 

2826 default=NOTHING, 

2827 validator=None, 

2828 repr=True, 

2829 cmp=None, 

2830 eq=True, 

2831 order=False, 

2832 hash=True, 

2833 init=True, 

2834 inherited=False, 

2835 ) 

2836 for name in Factory.__slots__ 

2837] 

2838 

2839Factory = _add_hash(_add_eq(_add_repr(Factory, attrs=_f), attrs=_f), attrs=_f) 

2840 

2841 

2842def make_class(name, attrs, bases=(object,), **attributes_arguments): 

2843 r""" 

2844 A quick way to create a new class called *name* with *attrs*. 

2845 

2846 :param str name: The name for the new class. 

2847 

2848 :param attrs: A list of names or a dictionary of mappings of names to 

2849 `attr.ib`\ s / `attrs.field`\ s. 

2850 

2851 The order is deduced from the order of the names or attributes inside 

2852 *attrs*. Otherwise the order of the definition of the attributes is 

2853 used. 

2854 :type attrs: `list` or `dict` 

2855 

2856 :param tuple bases: Classes that the new class will subclass. 

2857 

2858 :param attributes_arguments: Passed unmodified to `attr.s`. 

2859 

2860 :return: A new class with *attrs*. 

2861 :rtype: type 

2862 

2863 .. versionadded:: 17.1.0 *bases* 

2864 .. versionchanged:: 18.1.0 If *attrs* is ordered, the order is retained. 

2865 """ 

2866 if isinstance(attrs, dict): 

2867 cls_dict = attrs 

2868 elif isinstance(attrs, (list, tuple)): 

2869 cls_dict = {a: attrib() for a in attrs} 

2870 else: 

2871 raise TypeError("attrs argument must be a dict or a list.") 

2872 

2873 pre_init = cls_dict.pop("__attrs_pre_init__", None) 

2874 post_init = cls_dict.pop("__attrs_post_init__", None) 

2875 user_init = cls_dict.pop("__init__", None) 

2876 

2877 body = {} 

2878 if pre_init is not None: 

2879 body["__attrs_pre_init__"] = pre_init 

2880 if post_init is not None: 

2881 body["__attrs_post_init__"] = post_init 

2882 if user_init is not None: 

2883 body["__init__"] = user_init 

2884 

2885 type_ = types.new_class(name, bases, {}, lambda ns: ns.update(body)) 

2886 

2887 # For pickling to work, the __module__ variable needs to be set to the 

2888 # frame where the class is created. Bypass this step in environments where 

2889 # sys._getframe is not defined (Jython for example) or sys._getframe is not 

2890 # defined for arguments greater than 0 (IronPython). 

2891 try: 

2892 type_.__module__ = sys._getframe(1).f_globals.get( 

2893 "__name__", "__main__" 

2894 ) 

2895 except (AttributeError, ValueError): 

2896 pass 

2897 

2898 # We do it here for proper warnings with meaningful stacklevel. 

2899 cmp = attributes_arguments.pop("cmp", None) 

2900 ( 

2901 attributes_arguments["eq"], 

2902 attributes_arguments["order"], 

2903 ) = _determine_attrs_eq_order( 

2904 cmp, 

2905 attributes_arguments.get("eq"), 

2906 attributes_arguments.get("order"), 

2907 True, 

2908 ) 

2909 

2910 return _attrs(these=cls_dict, **attributes_arguments)(type_) 

2911 

2912 

2913# These are required by within this module so we define them here and merely 

2914# import into .validators / .converters. 

2915 

2916 

2917@attrs(slots=True, hash=True) 

2918class _AndValidator: 

2919 """ 

2920 Compose many validators to a single one. 

2921 """ 

2922 

2923 _validators = attrib() 

2924 

2925 def __call__(self, inst, attr, value): 

2926 for v in self._validators: 

2927 v(inst, attr, value) 

2928 

2929 

2930def and_(*validators): 

2931 """ 

2932 A validator that composes multiple validators into one. 

2933 

2934 When called on a value, it runs all wrapped validators. 

2935 

2936 :param callables validators: Arbitrary number of validators. 

2937 

2938 .. versionadded:: 17.1.0 

2939 """ 

2940 vals = [] 

2941 for validator in validators: 

2942 vals.extend( 

2943 validator._validators 

2944 if isinstance(validator, _AndValidator) 

2945 else [validator] 

2946 ) 

2947 

2948 return _AndValidator(tuple(vals)) 

2949 

2950 

2951def pipe(*converters): 

2952 """ 

2953 A converter that composes multiple converters into one. 

2954 

2955 When called on a value, it runs all wrapped converters, returning the 

2956 *last* value. 

2957 

2958 Type annotations will be inferred from the wrapped converters', if 

2959 they have any. 

2960 

2961 :param callables converters: Arbitrary number of converters. 

2962 

2963 .. versionadded:: 20.1.0 

2964 """ 

2965 

2966 def pipe_converter(val): 

2967 for converter in converters: 

2968 val = converter(val) 

2969 

2970 return val 

2971 

2972 if not converters: 

2973 # If the converter list is empty, pipe_converter is the identity. 

2974 A = typing.TypeVar("A") 

2975 pipe_converter.__annotations__ = {"val": A, "return": A} 

2976 else: 

2977 # Get parameter type from first converter. 

2978 t = _AnnotationExtractor(converters[0]).get_first_param_type() 

2979 if t: 

2980 pipe_converter.__annotations__["val"] = t 

2981 

2982 # Get return type from last converter. 

2983 rt = _AnnotationExtractor(converters[-1]).get_return_type() 

2984 if rt: 

2985 pipe_converter.__annotations__["return"] = rt 

2986 

2987 return pipe_converter