Making this a wrapper ensures this code runs during class creation. We also ensure that frozen-ness of classes is inherited.
(cls)
| 105 | ) |
| 106 | |
| 107 | def wrap(cls): |
| 108 | """ |
| 109 | Making this a wrapper ensures this code runs during class creation. |
| 110 | |
| 111 | We also ensure that frozen-ness of classes is inherited. |
| 112 | """ |
| 113 | nonlocal frozen, on_setattr |
| 114 | |
| 115 | had_on_setattr = on_setattr not in (None, setters.NO_OP) |
| 116 | |
| 117 | # By default, mutable classes convert & validate on setattr. |
| 118 | if frozen is False and on_setattr is None: |
| 119 | on_setattr = _ng_default_on_setattr |
| 120 | |
| 121 | # However, if we subclass a frozen class, we inherit the immutability |
| 122 | # and disable on_setattr. |
| 123 | for base_cls in cls.__bases__: |
| 124 | if base_cls.__setattr__ is _frozen_setattrs: |
| 125 | if had_on_setattr: |
| 126 | raise ValueError( |
| 127 | "Frozen classes can't use on_setattr " |
| 128 | "(frozen-ness was inherited)." |
| 129 | ) |
| 130 | |
| 131 | on_setattr = setters.NO_OP |
| 132 | break |
| 133 | |
| 134 | if auto_attribs is not None: |
| 135 | return do_it(cls, auto_attribs) |
| 136 | |
| 137 | try: |
| 138 | return do_it(cls, True) |
| 139 | except UnannotatedAttributeError: |
| 140 | return do_it(cls, False) |
| 141 | |
| 142 | # maybe_cls's type depends on the usage of the decorator. It's a class |
| 143 | # if it's used as `@attrs` but ``None`` if used as `@attrs()`. |