Return all concrete (i.e. non-trait and non-abstract) subclasses. Include both direct and indirect subclasses. Place classes with no children first.
(self)
| 361 | return result |
| 362 | |
| 363 | def concrete_subclasses(self) -> list[ClassIR] | None: |
| 364 | """Return all concrete (i.e. non-trait and non-abstract) subclasses. |
| 365 | |
| 366 | Include both direct and indirect subclasses. Place classes with no children first. |
| 367 | """ |
| 368 | subs = self.subclasses() |
| 369 | if subs is None: |
| 370 | return None |
| 371 | concrete = {c for c in subs if not (c.is_trait or c.is_abstract)} |
| 372 | # We place classes with no children first because they are more likely |
| 373 | # to appear in various isinstance() checks. We then sort leaves by name |
| 374 | # to get stable order. |
| 375 | return sorted(concrete, key=lambda c: (len(c.children or []), c.name)) |
| 376 | |
| 377 | def is_serializable(self) -> bool: |
| 378 | return any(ci._serializable for ci in self.mro) |
no test coverage detected