docs: def debug_shell(user_ns, user_global_ns, traceback=None, execWrapper=None):
      """
      Spawns some interactive shell. Tries to use IPython if available.
      Falls back to :func:`pdb.post_mortem` or :func:`simple_debug_shell`.
  
      :param dict[str] user_ns:
      :param dict[str] user_global_ns:
      :param traceback:
      :param execWrapper:
      :return: nothing
      """
      ipshell = None
      try:
          # noinspection PyPackageRequirements
          import IPython
          have_ipython = True
      except ImportError:
          have_ipython = False
  
      if not ipshell and traceback and have_ipython:
          # noinspection PyBroadException
          try:
              # noinspection PyPackageRequirements,PyUnresolvedReferences
              from IPython.core.debugger import Pdb
              # noinspection PyPackageRequirements,PyUnresolvedReferences
              from IPython.terminal.debugger import TerminalPdb
              # noinspection PyPackageRequirements,PyUnresolvedReferences
              from IPython.terminal.ipapp import TerminalIPythonApp
              ipapp = TerminalIPythonApp.instance()
              ipapp.interact = False  # Avoid output (banner, prints)
              ipapp.initialize(argv=[])
              def_colors = ipapp.shell.colors
              pdb_obj = TerminalPdb(def_colors)
              pdb_obj.botframe = None  # not sure. exception otherwise at quit
  
              def ipshell():
                  """
                  Run the IPython shell.
                  """
                  pdb_obj.interaction(None, traceback=traceback)
  
          except Exception:
              print("IPython Pdb exception:")
              better_exchook(*sys.exc_info(), autodebugshell=False)
  
      if not ipshell and have_ipython:
          # noinspection PyBroadException
          try:
              # noinspection PyPackageRequirements,PyUnresolvedReferences
              import IPython
              # noinspection PyPackageRequirements,PyUnresolvedReferences
              import IPython.terminal.embed
  
              class DummyMod(object):
                  """Dummy module"""
              module = DummyMod()
              module.__dict__ = user_global_ns
              module.__name__ = "_DummyMod"
              if "__name__" not in user_ns:
                  user_ns = user_ns.copy()
                  user_ns["__name__"] = "_DummyUserNsMod"
              ipshell = IPython.terminal.embed.InteractiveShellEmbed.instance(
                  user_ns=user_ns, user_module=module)
          except Exception:
              print("IPython not available:")
              better_exchook(*sys.exc_info(), autodebugshell=False)
          else:
              if execWrapper:
                  old = ipshell.run_code
                  ipshell.run_code = lambda code: execWrapper(lambda: old(code))
      if ipshell:
          ipshell()
      else:
          print("Use simple debug shell:")
          if traceback:
              import pdb
              pdb.post_mortem(traceback)
          else:
              simple_debug_shell(user_global_ns, user_ns)