from typing import Any
from typing import Set
import inspect
from typing import get_origin
from typing import get_args


def get_types(annotation: Any) -> Set[Any]:
    """Returns all types in the annotation

    :param annotation: variable to get types from
    :returns: set of available types

    Example:
        >>> get_types(Optional[List[UserInfoResponse]])
        {typing.Union, <class 'NoneType'>, <class '__main__.UserInfoResponse'>, <class 'list'>}
    """
    result = set()

    if inspect.isclass(annotation):
        result.add(annotation)

    if alias := get_origin(annotation):
        result.add(alias)
        result.update(get_types(alias))

    for i in get_args(annotation):
        if not get_origin(i):
            result.add(i)
        else:
            result.update(get_types(i))
    return result