# Path: src/cattr/errors.py



from functools import lru_cache, singledispatch
from typing import Any, Callable, List, Tuple, Union
from .errors import StructureHandlerNotFoundError
import attr
    """
    FunctionDispatch is similar to functools.singledispatch, but
    instead dispatches based on functions that take the type of the
    first argument in the method, and return True or False.

    objects that help determine dispatch should be instantiated objects.
    """

    _handler_pairs: list = attr.ib(factory=list)

    def register(self, can_handle: Callable[[Any], bool], func, is_generator=False):
        self._handler_pairs.insert(0, (can_handle, func, is_generator))

    def dispatch(self, typ):
        """
        returns the appropriate handler, for the object passed.
        """
        for can_handle, handler, is_generator in self._handler_pairs:
            # can handle could raise an exception here
            # such as issubclass being called on an instance.
            # it's easier to just ignore that case.
            try:
                ch = can_handle(typ)
            except Exception:
                continue
            if ch:
                if is_generator:
                    return handler(typ)
                else:
                    return handler

# Path: src/cattr/errors.py



# Path: src/cattr/dispatch.py
from functools import lru_cache, singledispatch
from typing import Any, Callable, List, Tuple, Union
from .errors import StructureHandlerNotFoundError
import attr

    """
    FunctionDispatch is similar to functools.singledispatch, but
    instead dispatches based on functions that take the type of the
    first argument in the method, and return True or False.

    objects that help determine dispatch should be instantiated objects.
    """

    _handler_pairs: list = attr.ib(factory=list)

    def register(self, can_handle: Callable[[Any], bool], func, is_generator=False):
        self._handler_pairs.insert(0, (can_handle, func, is_generator))

    def dispatch(self, typ):
        """
        returns the appropriate handler, for the object passed.
        """
        for can_handle, handler, is_generator in self._handler_pairs:
            # can handle could raise an exception here
            # such as issubclass being called on an instance.
            # it's easier to just ignore that case.
            try:
                ch = can_handle(typ)
            except Exception:
                continue
            if ch:
                if is_generator:
                    return handler(typ)
                else:
                    return handler

        raise StructureHandlerNotFoundError(