text: import contextvars
  import os
  import os.path
  import re
  from typing import Any, Dict, List, Optional, Tuple, Union
  
  import yaml
  from logzero import logger
  
  from chaoslib.types import Settings
  
  __all__ = [
      "get_loaded_settings",
      "load_settings",
      "save_settings",
      "locate_settings_entry",
  ]
  CHAOSTOOLKIT_CONFIG_PATH = os.path.abspath(
      os.path.expanduser("~/.chaostoolkit/settings.yaml")
  )
  loaded_settings = contextvars.ContextVar("loaded_settings", default={})
  
  
  def load_settings(settings_path: str = CHAOSTOOLKIT_CONFIG_PATH) -> Settings:
      """
      Load chaostoolkit settings as a mapping of key/values or return `None`
      when the file could not be found.
      """
      if not os.path.exists(settings_path):
          logger.debug(
              "The Chaos Toolkit settings file could not be found at "
              "'{c}'.".format(c=settings_path)
          )
          return
  
      with open(settings_path) as f:
          try:
              settings = yaml.safe_load(f.read())
              loaded_settings.set(settings)
              return settings
          except yaml.YAMLError as ye:
              logger.error(f"Failed parsing YAML settings: {str(ye)}")
  
  
  def save_settings(settings: Settings, settings_path: str = CHAOSTOOLKIT_CONFIG_PATH):
      """
      Save chaostoolkit settings as a mapping of key/values, overwriting any file
      that may already be present.
      """
      loaded_settings.set(settings)
      settings_dir = os.path.dirname(settings_path)
      if not os.path.isdir(settings_dir):
          os.mkdir(settings_dir)
  
      with open(settings_path, "w") as outfile:
          yaml.dump(settings, outfile, default_flow_style=False)
  
  
  def get_loaded_settings() -> Settings:
      """
      Settings that have been loaded in the current context.
      """
      return loaded_settings.get()
  
  
  def locate_settings_entry(
      settings: Settings, key: str
  ) -> Optional[Tuple[Union[Dict[str, Any], List], Any, Optional[str], Optional[int]]]:
      """
      Lookup the entry at the given dotted key in the provided settings and
      return a a tuple as follows:
  
      * the parent of the found entry (can be a list or a dict)
      * the entry (can eb anything: string, int, list, dict)
      * the key on the parent that has the entry (in case parent is a dict)
      * the index in the parent that has the entry (in case parent is a list)
  
      Otherwise, returns `None`.
  
      When the key in the settings has at least one dot, it must be escaped
      with two backslahes.
  
      Examples of valid keys:
  
      * auths
      * auths.example\\.com
      * auths.example\\.com:8443
      * auths.example\\.com.type
      * controls[0].name
      """
      array_index = re.compile(r"\[([0-9]*)\]$")
      # borrowed from https://github.com/carlosescri/DottedDict (MIT)
      # this kindly preserves escaped dots
      parts = [x for x in re.split(r"(?<!\\)(\.)", key) if x != "."]
  
      current = settings
      parent = settings
      last_key = None
      last_index = None
      for part in parts:
          # we don't know to escape now that we have our part
          part = part.replace("\\", "")
          m = array_index.search(part)
          if m:
              # this is part with an index
              part = part[: m.start()]
              if part not in current:
                  return
              current = current.get(part)
              parent = current
              index = int(m.groups()[0])
              last_key = None
              last_index = index
              try:
                  current = current[index]
              except (KeyError, IndexError):
                  return
          else:
              # this is just a regular key
              if part not in current:
                  return
              parent = current
              last_key = part
              last_index = None
              current = current.get(part)
  
      return (parent, current, last_key, last_index)
  