class_docstr: Singleton class for CLI logging.
  
  Without calling 'cli_logger.configure', the CLILogger will default
  to 'record' style logging.
  
  Attributes:
      color_mode (str):
          Can be "true", "false", or "auto".
  
          Enables or disables `colorful`.
  
          If `color_mode` is "auto", is set to `not stdout.isatty()`
      indent_level (int):
          The current indentation level.
  
          All messages will be indented by prepending `"  " * indent_level`
      vebosity (int):
          Output verbosity.
  
          Low verbosity will disable `verbose` and `very_verbose` messages.
class_docstr_tok: ["Singleton","class","for","CLI","logging",".","Without","calling","'cli_logger.configure","'",",","the","CLILogger","will","default","to","'record","'","style","logging",".","Attributes",":","color_mode","(","str",")",":","Can","be","``","true","''",",","``","false","''",",","or","``","auto","''",".","Enables","or","disables","`","colorful","`",".","If","`","color_mode","`","is","``","auto","''",",","is","set","to","`","not","stdout.isatty","(",")","`","indent_level","(","int",")",":","The","current","indentation","level",".","All","messages","will","be","indented","by","prepending","`","``","``","*","indent_level","`","vebosity","(","int",")",":","Output","verbosity",".","Low","verbosity","will","disable","`","verbose","`","and","`","very_verbose","`","messages","."]
docstr: Display a confirmation dialog.
  
  Valid answers are "y/yes/true/1" and "n/no/false/0".
  
  Args:
      yes: If `yes` is `True` the dialog will default to "yes"
                  and continue without waiting for user input.
      _abort (bool):
          If `_abort` is `True`,
          "no" means aborting the program.
      _default (bool):
          The default action to take if the user just presses enter
          with no input.
      _timeout_s (float):
          If user has no input within _timeout_s seconds, the default
          action is taken. None means no timeout.
code: def confirm(
      self,
      yes: bool,
      msg: str,
      *args: Any,
      _abort: bool = False,
      _default: bool = False,
      _timeout_s: Optional[float] = None,
      **kwargs: Any,
  ):
      """Display a confirmation dialog.
  
      Valid answers are "y/yes/true/1" and "n/no/false/0".
  
      Args:
          yes: If `yes` is `True` the dialog will default to "yes"
                      and continue without waiting for user input.
          _abort (bool):
              If `_abort` is `True`,
              "no" means aborting the program.
          _default (bool):
              The default action to take if the user just presses enter
              with no input.
          _timeout_s (float):
              If user has no input within _timeout_s seconds, the default
              action is taken. None means no timeout.
      """
      should_abort = _abort
      default = _default
  
      if not self.interactive and not yes:
          # no formatting around --yes here since this is non-interactive
          self.error(
              "This command requires user confirmation. "
              "When running non-interactively, supply --yes to skip."
          )
          raise ValueError("Non-interactive confirm without --yes.")
  
      if default:
          yn_str = "Y/n"
      else:
          yn_str = "y/N"
  
      confirm_str = cf.underlined("Confirm [" + yn_str + "]:") + " "
  
      rendered_message = _format_msg(msg, *args, **kwargs)
      # the rendered message ends with ascii coding
      if rendered_message and not msg.endswith("\n"):
          rendered_message += " "
  
      msg_len = len(rendered_message.split("\n")[-1])
      complete_str = rendered_message + confirm_str
  
      if yes:
          self._print(
              complete_str
              + "y "
              + cf.dimmed("[automatic, due to --yes]")
          )
          return True
  
      self._print(complete_str, _linefeed=False)
  
      res = None
      yes_answers = ["y", "yes", "true", "1"]
      no_answers = ["n", "no", "false", "0"]
      try:
          while True:
              if _timeout_s is None:
                  ans = sys.stdin.readline()
              elif sys.platform == "win32":
                  # Windows doesn't support select
                  start_time = time.time()
                  ans = ""
                  while True:
                      if (time.time() - start_time) >= _timeout_s:
                          self.newline()
                          ans = "\n"
                          break
                      elif msvcrt.kbhit():
                          ch = msvcrt.getwch()
                          if ch in ("\n", "\r"):
                              self.newline()
                              ans = ans + "\n"
                              break
                          elif ch == "\b":
                              if ans:
                                  ans = ans[:-1]
                                  # Emulate backspace erasing
                                  print("\b \b", end="", flush=True)
                          else:
                              ans = ans + ch
                              print(ch, end="", flush=True)
                      else:
                          time.sleep(0.1)
              else:
                  ready, _, _ = select.select(
                      [sys.stdin], [], [], _timeout_s
                  )
                  if not ready:
                      self.newline()
                      ans = "\n"
                  else:
                      ans = sys.stdin.readline()
  
              ans = ans.lower()
  
              if ans == "\n":
                  res = default
                  break
  
              ans = ans.strip()
              if ans in yes_answers:
                  res = True
                  break
              if ans in no_answers:
                  res = False
                  break
  
              indent = " " * msg_len
              self.error(
                  "{}Invalid answer: {}. Expected {} or {}",
                  indent,
                  cf.bold(ans.strip()),
                  self.render_list(yes_answers, "/"),
                  self.render_list(no_answers, "/"),
              )
              self._print(indent + confirm_str, _linefeed=False)
      except KeyboardInterrupt:
          self.newline()
          res = default
  
      if not res and should_abort:
          # todo: make sure we tell the user if they
          # need to do cleanup
          self._print("Exiting...")
          raise SilentClickException(
              "Exiting due to the response to confirm(should_abort=True)."
          )
  
      return res
  
imports: import inspect
  import logging
  import os
  import sys
  import time
  from contextlib import contextmanager
  from functools import wraps
  from typing import Any, Callable, Dict, List, Optional, Tuple
  import click
  import colorama
  import ray
label_desc: Use image node_id 32 for calling the _CliLogger obj's underlying member method code with example usage: obj.confirm(yes, msg) and returns: res, True