code: def _draw_nodes(
      node: DependencyMixin,
      parent_graph: graphviz.Digraph,
      states_by_task_id: dict[str, str] | None,
  ) -> None:
      """Draw the node and its children on the given parent_graph recursively."""
      if isinstance(node, (BaseOperator, MappedOperator)):
          _draw_task(node, parent_graph, states_by_task_id)
      else:
          if not isinstance(node, TaskGroup):
              raise AirflowException(
                  f"The node {node} should be TaskGroup and is not"
              )
          # Draw TaskGroup
          if node.is_root:
              # No need to draw background for root TaskGroup.
              _draw_task_group(node, parent_graph, states_by_task_id)
          else:
              with parent_graph.subgraph(
                  name=f"cluster_{node.group_id}"
              ) as sub:
                  sub.attr(
                      shape="rectangle",
                      style="filled",
                      color=_refine_color(node.ui_fgcolor),
                      # Partially transparent CornflowerBlue
                      fillcolor="#6495ed7f",
                      label=node.label,
                  )
                  _draw_task_group(node, sub, states_by_task_id)
  
file_path: airflow/airflow/utils/dot_renderer.py
imports: from __future__ import annotations
  import warnings
  from typing import TYPE_CHECKING, Any
  from airflow.exceptions import AirflowException
  from airflow.models.baseoperator import BaseOperator
  from airflow.models.mappedoperator import MappedOperator
  from airflow.utils.dag_edges import dag_edges
  from airflow.utils.state import State
  from airflow.utils.task_group import TaskGroup
label_desc: Use image node_id 4 for calling a global function with example usage: _draw_nodes(node, parent_graph, states_by_task_id) without return types