code: def run(self):
          
          logger = make_default_logger(INTERNAL_LOGGER_NAME)
          logger.info('\n%s\nExecuting `%s`\n%s\n', '-'*80, self.name, '-'*80)
          logger.info('\n%s', str(self))
  
          threads = []
  
          if not self.tasks:
              raise LaneExecutionError('No tasks to execute!')
  
          for task_def_or_branch in self.tasks:
              if isinstance(task_def_or_branch, Branch):
                  task_def_or_branch.run()
              elif isinstance(task_def_or_branch['cls_or_branch'], Branch):  # Nested Branch
                  task_def_or_branch['cls_or_branch'].run()
              else:
                  task = task_def_or_branch['cls_or_branch'](*task_def_or_branch['args'],
                                                             **task_def_or_branch['kwargs'])
                  if self.run_parallel:
                      threads.append(LaneTaskThread(task))
                  else:
                      task()
  
          if threads:
              for thread in threads:
                  thread.start()
              for thread in threads:
                  thread.join()
  
          logger.info('\n%s\nFinished executing `%s`\n%s', '-'*80, self.name, '-'*80)
  
          return self
docs: Executes the tasks in the lane in the order in which they have been added, unless
          `self.run_parallel` is True, then a thread is spawned for each task and executed in
          parallel (note that task threads are still spawned in the order in which they were added).