code: def _switch_backend_notebook(backend):
      """
      Handles switching the matplotlib backend when running in a Jupyter
      notebook.
  
      Parameters
      ----------
      backend : str
          the interactive matplotlib backend to switch to
  
      Notes
      -----
      1. `flush_figures` is a post-cell execution callback that
         `plt.show()`s & `plt.close()`s all figures created in a cell so
         that later `plt.plot()` calls create new figures. There's a weird
         circular matplotlib/IPython interaction where:
           - `matplotlib.pyplot` (via `IPython.core.pylabtools`) registers
              `flush_figures` when it's imported into an IPython
              environment
           - The `%matplotlib inline` magic command also registers a
             `flush_figures` call each it's run, whether or not one has
             been registered already
           - IPython runs `%matplotlib inline` if it detects
             `matplotlib.pyplot` has been imported and no backend is set
             in the same cell.
         So depending on import order, whether imports happen across
         multiple cells, and whether/when/how many times the backend has
         been switched, there may be any number of `flush_figures`
         callbacks registered. Switching to the interactive notebook
         backend unregisters one `flush_figures` callback but leaves the
         other(s), and creating an interactive figure with `flush_figures`
         registered closes the figure immediately after the cell executes
         and causes the matplotlib event loop to throw an error. So we
         need to ensure all `flush_figures` instances are unregistered
         before plotting.
      2. In certain situations, the IPython magic command fails to switch
         the backend but the matplotlib command will succeed. And for some
         unfathomable reason, when the magic command fails, IPython
         **prints** a warning message rather than issuing it via
         `warnings.warn()` [1]. So the only way to catch this warning is
         to temporarily suppress and capture stdout.
  
      [1] https://github.com/ipython/ipython/blob/e394d65a6b499b5d91df7ca0306c1cb88c543f43/IPython/core/interactiveshell.py#L3495
      """
      # ipykernel is only guaranteed to be installed if running in notebook
      from ipykernel.pylab.backend_inline import flush_figures
  
      backend = backend.as_ipython()
      tmp_stdout = StringIO()
      exc = None
  
      with redirect_stdout(tmp_stdout):
          try:
              IPYTHON_INSTANCE.run_line_magic("matplotlib", backend)
          except KeyError as e:
              exc = e
              IPYTHON_INSTANCE.run_line_magic("matplotlib", "-l")
  
      output_msg = tmp_stdout.getvalue().strip()
      tmp_stdout.close()
      if exc is not None:
          # just in case something else was somehow sent to stdout while
          # redirected, or if we managed to catch a different KeyError
          backends_avail = output_msg.splitlines()[-1]
          raise ValueError(
              f"{backend} is not a valid IPython plotting "
              f"backend.\n{backends_avail}"
          ) from exc
  
      elif output_msg.startswith(
          "Warning: Cannot change to a different GUI toolkit"
      ):
          try:
              _switch_backend_regular(backend)
          except HypertoolsBackendError as e:
              err_msg = (
                  f'Failed to switch plotting backend to "{backend}" via '
                  f"IPython with the following message:\n\t{output_msg}\n\n"
                  f"Fell back to switching via matplotlib and failed with "
                  f"the above error"
              )
              raise HypertoolsBackendError(err_msg) from e
  
      if backend != "inline":
          while (
              flush_figures
              in IPYTHON_INSTANCE.events.callbacks["post_execute"]
          ):
              IPYTHON_INSTANCE.events.unregister(
                  "post_execute", flush_figures
              )
  
imports: import inspect
  import sys
  import traceback
  import warnings
  from contextlib import contextmanager, redirect_stdout
  from functools import wraps
  from io import StringIO
  from os import getenv
  from typing import Iterable
  import matplotlib
  import matplotlib.pyplot
  from .._shared.exceptions import HypertoolsBackendError
label_desc: Use image node_id 4 for calling a global function with example usage: _switch_backend_notebook(backend) without return types