from collections.abc import Callable
from typing import Any


def insist(
  func: Callable[[], Any],
  validator: Callable[[Any], bool] = bool,
  func2: Callable[[], Any] | None = None,
):
  """### Keep invoking `func` until `validator(func())` returns Truey result, return it.

  # Use `functools.partial` for this!!!

  ```py
  from functools import partial
  number = int(insist(
    partial(input, "Input a number: "),
    partial(tcr.able, int)
  ))
  ```

  `func2` is invoked on 2nd and every later iteration, unless not provided, in that case `func` is invoked at all times.

  Keep in mind that insist won't convert the, str that was returned by `input()` in the above example, only verify its compliance with validator.
  """
  result = func()
  if validator(result):
    return result
  while True:
    result = (func2 if func2 else func)()
    if not validator(result):
      continue

    return result
