Collect attr.ibs from base classes of *cls*, except *taken_attr_names*.
(
cls, taken_attr_names
)
| 316 | |
| 317 | |
| 318 | def _collect_base_attrs( |
| 319 | cls, taken_attr_names |
| 320 | ) -> tuple[list[Attribute], dict[str, type]]: |
| 321 | """ |
| 322 | Collect attr.ibs from base classes of *cls*, except *taken_attr_names*. |
| 323 | """ |
| 324 | base_attrs = [] |
| 325 | base_attr_map = {} # A dictionary of base attrs to their classes. |
| 326 | |
| 327 | # Traverse the MRO and collect attributes. |
| 328 | for base_cls in reversed(cls.__mro__[1:-1]): |
| 329 | for a in getattr(base_cls, "__attrs_attrs__", []): |
| 330 | if a.inherited or a.name in taken_attr_names: |
| 331 | continue |
| 332 | |
| 333 | a = a.evolve(inherited=True) # noqa: PLW2901 |
| 334 | base_attrs.append(a) |
| 335 | base_attr_map[a.name] = base_cls |
| 336 | |
| 337 | # For each name, only keep the freshest definition i.e. the furthest at the |
| 338 | # back. base_attr_map is fine because it gets overwritten with every new |
| 339 | # instance. |
| 340 | filtered = [] |
| 341 | seen = set() |
| 342 | for a in reversed(base_attrs): |
| 343 | if a.name in seen: |
| 344 | continue |
| 345 | filtered.insert(0, a) |
| 346 | seen.add(a.name) |
| 347 | |
| 348 | return filtered, base_attr_map |
| 349 | |
| 350 | |
| 351 | def _collect_base_attrs_broken(cls, taken_attr_names): |
no test coverage detected