# Path: selene/core/exceptions.py
# class TimeoutException(AssertionError):
#     def __init__(self, msg=None):
#         self.msg = msg
# 
#     def __str__(self):
#         exception_msg = "Message: %s\n" % self.msg
#         return exception_msg
# 
# Path: selene/common/fp.py
# def identity(it: T) -> T:
#     return it


import time
from abc import abstractmethod, ABC
from typing import Generic, Callable, TypeVar, Optional
from selene.core.exceptions import TimeoutException
from selene.common.fp import identity
Lambda = Callable[[T], R]
Proc = Callable[[T], None]
Predicate = Callable[[T], bool]


Fn = Callable[[T], R]


# todo: consider moving outside of "wait" module... because there is no direct cohesion with it
class Query(Generic[T, R]):
    def __init__(self, description: str, fn: Callable[[T], R]):
        self._description = description
        self._fn = fn

    def __call__(self, entity: T) -> R:
        return self._fn(entity)

    def __str__(self):
        return self._description


class Command(Query[T, None]):
    pass


# todo: provide sexy fluent implementation via builder, i.e. Wait.the(element).atMost(3).orFailWith(hook)
class Wait(Generic[E]):

    # todo: provide the smallest possible timeout default, something like 1ms
    def __init__(

# Path: selene/core/exceptions.py
# class TimeoutException(AssertionError):
#     def __init__(self, msg=None):
#         self.msg = msg
# 
#     def __str__(self):
#         exception_msg = "Message: %s\n" % self.msg
#         return exception_msg
# 
# Path: selene/common/fp.py
# def identity(it: T) -> T:
#     return it


# Path: selene/core/wait.py
import time
from abc import abstractmethod, ABC
from typing import Generic, Callable, TypeVar, Optional
from selene.core.exceptions import TimeoutException
from selene.common.fp import identity

Lambda = Callable[[T], R]
Proc = Callable[[T], None]
Predicate = Callable[[T], bool]


Fn = Callable[[T], R]


# todo: consider moving outside of "wait" module... because there is no direct cohesion with it
class Query(Generic[T, R]):
    def __init__(self, description: str, fn: Callable[[T], R]):
        self._description = description
        self._fn = fn

    def __call__(self, entity: T) -> R:
        return self._fn(entity)

    def __str__(self):
        return self._description


class Command(Query[T, None]):
    pass


# todo: provide sexy fluent implementation via builder, i.e. Wait.the(element).atMost(3).orFailWith(hook)
class Wait(Generic[E]):

    # todo: provide the smallest possible timeout default, something like 1ms
    def __init__(

        self,