code: def make_task_info_tree(
      task: TaskOnKart,
      ignore_task_names: Optional[List[str]] = None,
      cache: Optional[Dict[str, TaskInfo]] = None,
  ) -> TaskInfo:
      with warnings.catch_warnings():
          warnings.filterwarnings(
              action="ignore",
              message="Task .* without outputs has no custom complete() method",
          )
          is_task_complete = task.complete()
  
      name = task.__class__.__name__
      unique_id = task.make_unique_id()
      output_paths = [
          t.path() for t in luigi.task.flatten(task.output())
      ]
  
      cache = {} if cache is None else cache
      cache_id = f"{name}_{unique_id}_{is_task_complete}"
      if cache_id in cache:
          return cache[cache_id]
  
      params = task.get_info(only_significant=True)
      processing_time = task.get_processing_time()
      if isinstance(processing_time, float):
          processing_time = str(processing_time) + "s"
      is_complete = "COMPLETE" if is_task_complete else "PENDING"
      task_log = dict(task.get_task_log())
      requires = _make_requires_info(task.requires())
  
      children = luigi.task.flatten(task.requires())
      children_task_infos: List[TaskInfo] = []
      for child in children:
          if (
              ignore_task_names is None
              or child.__class__.__name__ not in ignore_task_names
          ):
              children_task_infos.append(
                  make_task_info_tree(
                      child,
                      ignore_task_names=ignore_task_names,
                      cache=cache,
                  )
              )
      task_info = TaskInfo(
          name=name,
          unique_id=unique_id,
          output_paths=output_paths,
          params=params,
          processing_time=processing_time,
          is_complete=is_complete,
          task_log=task_log,
          requires=requires,
          children_task_infos=children_task_infos,
      )
      cache[cache_id] = task_info
      return task_info
  
file_path: gokart/gokart/tree/task_info_formatter.py
imports: import typing
  import warnings
  from dataclasses import dataclass
  from typing import Dict, List, NamedTuple, Optional, Set, Union
  import luigi
  from gokart.task import TaskOnKart
label_desc: Use image node_id 2 for calling a global function with example usage: make_task_info_tree(task, ignore_task_names, cache) and returns: task_info, cache