File: _utils.py

package info (click to toggle)
ansible-core 2.19.0~beta6-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 32,628 kB
  • sloc: python: 180,313; cs: 4,929; sh: 4,601; xml: 34; makefile: 21
file content (34 lines) | stat: -rw-r--r-- 1,082 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Copyright (c) 2018, Ansible Project
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
"""
Modules in _utils are waiting to find a better home.  If you need to use them, be prepared for them
to move to a different location in the future.
"""

from __future__ import annotations

import inspect
import typing as t

_Type = t.TypeVar('_Type')


def get_all_subclasses(cls: type[_Type], *, include_abstract: bool = True, consider_self: bool = False) -> set[type[_Type]]:
    """Recursively find all subclasses of a given type, including abstract classes by default."""
    subclasses: set[type[_Type]] = {cls} if consider_self else set()
    queue: list[type[_Type]] = [cls]

    while queue:
        parent = queue.pop()

        for child in parent.__subclasses__():
            if child in subclasses:
                continue

            queue.append(child)
            subclasses.add(child)

    if not include_abstract:
        subclasses = {sc for sc in subclasses if not inspect.isabstract(sc)}

    return subclasses