code: def papermill_process(self, nb_man, resources):
          
          # Execute each cell and update the output in real time.
          nb = nb_man.nb
          for index, cell in enumerate(nb.cells):
              try:
                  nb_man.cell_start(cell, index)
                  if not cell.source:
                      continue
                  nb.cells[index], resources = self.preprocess_cell(cell, resources, index)
              except CellExecutionError as ex:
                  nb_man.cell_exception(nb.cells[index], cell_index=index, exception=ex)
                  break
              finally:
                  nb_man.cell_complete(nb.cells[index], cell_index=index)
          return nb, resources
docs: This function acts as a replacement for the grandparent's `preprocess`
          method.
  
          We are doing this for the following reasons:
  
          1. Notebooks will stop executing when they encounter a failure but not
             raise a `CellException`. This allows us to save the notebook with the
             traceback even though a `CellExecutionError` was encountered.
  
          2. We want to write the notebook as cells are executed. We inject our
             logic for that here.
  
          3. We want to include timing and execution status information with the
             metadata of each cell.
  
          Parameters
          ----------
          nb_man : NotebookExecutionManager
              Engine wrapper of notebook being converted
          resources : dictionary
              Additional resources used in the conversion process.  Allows
              preprocessors to pass variables into the Jinja engine.