|
2 | 2 |
|
3 | 3 | from __future__ import annotations |
4 | 4 |
|
| 5 | +import abc |
5 | 6 | import contextlib |
6 | 7 | import copy |
7 | 8 | import enum |
@@ -683,34 +684,28 @@ def __init__( |
683 | 684 | def __repr__(self): |
684 | 685 | return f"<_ClassBuilder(cls={self._cls.__name__})>" |
685 | 686 |
|
686 | | - if PY_3_10_PLUS: |
687 | | - import abc |
688 | | - |
689 | | - def build_class(self): |
690 | | - """ |
691 | | - Finalize class based on the accumulated configuration. |
692 | | -
|
693 | | - Builder cannot be used after calling this method. |
694 | | - """ |
695 | | - if self._slots is True: |
696 | | - return self._create_slots_class() |
697 | | - |
698 | | - return self.abc.update_abstractmethods( |
699 | | - self._patch_original_class() |
700 | | - ) |
701 | | - |
702 | | - else: |
| 687 | + def build_class(self): |
| 688 | + """ |
| 689 | + Finalize class based on the accumulated configuration. |
703 | 690 |
|
704 | | - def build_class(self): |
705 | | - """ |
706 | | - Finalize class based on the accumulated configuration. |
| 691 | + Builder cannot be used after calling this method. |
| 692 | + """ |
| 693 | + if self._slots is True: |
| 694 | + cls = self._create_slots_class() |
| 695 | + else: |
| 696 | + cls = self._patch_original_class() |
| 697 | + if PY_3_10_PLUS: |
| 698 | + cls = abc.update_abstractmethods(cls) |
707 | 699 |
|
708 | | - Builder cannot be used after calling this method. |
709 | | - """ |
710 | | - if self._slots is True: |
711 | | - return self._create_slots_class() |
| 700 | + # The method gets only called if it's not inherited from a base class. |
| 701 | + # _has_own_attribute does NOT work properly for classmethods. |
| 702 | + if ( |
| 703 | + getattr(cls, "__attrs_init_subclass__", None) |
| 704 | + and "__attrs_init_subclass__" not in cls.__dict__ |
| 705 | + ): |
| 706 | + cls.__attrs_init_subclass__() |
712 | 707 |
|
713 | | - return self._patch_original_class() |
| 708 | + return cls |
714 | 709 |
|
715 | 710 | def _patch_original_class(self): |
716 | 711 | """ |
@@ -1269,10 +1264,12 @@ def attrs( |
1269 | 1264 | *unsafe_hash* as an alias for *hash* (for :pep:`681` compliance). |
1270 | 1265 | .. deprecated:: 24.1.0 *repr_ns* |
1271 | 1266 | .. versionchanged:: 24.1.0 |
1272 | | -
|
1273 | 1267 | Instances are not compared as tuples of attributes anymore, but using a |
1274 | 1268 | big ``and`` condition. This is faster and has more correct behavior for |
1275 | 1269 | uncomparable values like `math.nan`. |
| 1270 | + .. versionadded:: 24.1.0 |
| 1271 | + If a class has an *inherited* classmethod called |
| 1272 | + ``__attrs_init_subclass__``, it is executed after the class is created. |
1276 | 1273 | """ |
1277 | 1274 | if repr_ns is not None: |
1278 | 1275 | import warnings |
|
0 commit comments