code: def run_notebook(
      notebook,
      notebook_dir,
      kernel=None,
      no_cache=False,
      temp_dir="tmp_notebook",
  ):
      """Run tutorial Jupyter notebook to catch any execution error.
  
      Parameters
      ----------
      notebook : string
          the name of the notebook to be tested
      notebook_dir : string
          the directory of the notebook to be tested
      kernel : string, None
          controls which kernel to use when running the notebook. e.g: python2
      no_cache : '1' or False
          controls whether to clean the temporary directory in which the
          notebook was run and re-download any resource file. The default
          behavior is to not clean the directory. Set to '1' to force clean the
          directory.
          NB: in the real CI, the tests will re-download everything since they
          start from a clean workspace.
      temp_dir: string
          The temporary sub-directory directory in which to run the notebook.
  
      Returns
      -------
         Returns true if the workbook runs with no warning or exception.
      """
      logging.info("Running notebook '{}'".format(notebook))
      notebook_path = os.path.join(
          *([notebook_dir] + notebook.split("/"))
      )
      working_dir = os.path.join(*([temp_dir] + notebook.split("/")))
  
      if no_cache == "1":
          logging.info(
              "Cleaning and setting up temp directory '{}'".format(
                  working_dir
              )
          )
          shutil.rmtree(temp_dir, ignore_errors=True)
  
      errors = []
      notebook = None
      if not os.path.isdir(working_dir):
          os.makedirs(working_dir)
      try:
          notebook = nbformat.read(
              notebook_path + ".ipynb", as_version=IPYTHON_VERSION
          )
          if kernel is not None:
              eprocessor = ExecutePreprocessor(
                  timeout=TIME_OUT, kernel_name=kernel
              )
          else:
              eprocessor = ExecutePreprocessor(timeout=TIME_OUT)
  
          success = False
          # There is a low (< 1%) chance that starting a notebook executor will fail due to the kernel
          # taking to long to start, or a port collision, etc.
          for i in range(ATTEMPTS):
              try:
                  nb, _ = eprocessor.preprocess(
                      notebook, {"metadata": {"path": working_dir}}
                  )
                  success = True
              except RuntimeError as rte:
                  # We check if the exception has to do with the Jupyter kernel failing to start. If
                  # not, we rethrow to prevent the notebook from erring ATTEMPTS times. It is not
                  # ideal to inspect the exception message, but necessary for retry logic, as Jupyter
                  # client throws the generic RuntimeError that can be confused with other Runtime
                  # errors.
                  if str(rte) != KERNEL_ERROR_MSG:
                      raise rte
  
                  logging.info(
                      "Error starting preprocessor: {}. Attempt {}/{}".format(
                          str(rte), i + 1, ATTEMPTS
                      )
                  )
                  time.sleep(1)
                  continue
              break
          if not success:
              errors.append(
                  "Error: Notebook failed to run after {} attempts.".format(
                      ATTEMPTS
                  )
              )
      except Exception as err:
          err_msg = str(err)
          errors.append(err_msg)
      finally:
          if notebook is not None:
              output_file = os.path.join(working_dir, "output.txt")
              nbformat.write(notebook, output_file)
              output_nb = open(output_file, mode="r", encoding="utf-8")
              for line in output_nb:
                  if (
                      "Warning:" in line
                      and "numpy operator signatures" not in line
                  ):
                      errors.append("Warning:\n" + line)
          if len(errors) > 0:
              logging.error("\n".join(errors))
              return False
          return True
  
imports: import io
  import logging
  import os
  import shutil
  import time
  from nbconvert.preprocessors import ExecutePreprocessor
  import nbformat
label_desc: Use image node_id 1 for calling a global function with example usage: run_notebook(notebook, notebook_dir, kernel, no_cache, temp_dir) and returns: True, False