code: def execute_notebook(
          cls, nb, kernel_name, output_path=None, progress_bar=True, log_output=False, **kwargs
      ):
          
          nb_man = NotebookExecutionManager(
              nb, output_path=output_path, progress_bar=progress_bar, log_output=log_output
          )
  
          nb_man.notebook_start()
          try:
              nb = cls.execute_managed_notebook(nb_man, kernel_name, log_output=log_output, **kwargs)
              # Update the notebook object in case the executor didn't do it for us
              if nb:
                  nb_man.nb = nb
          finally:
              nb_man.cleanup_pbar()
              nb_man.notebook_complete()
  
          return nb_man.nb
docs: A wrapper to handle notebook execution tasks.
  
          Wraps the notebook object in a `NotebookExecutionManager` in order to track
          execution state in a uniform manner. This is meant to help simplify
          engine implementations. This allows a developer to just focus on
          iterating and executing the cell contents.