class_docstr: Encapsulates resources needed to compile a pipeline.
  
  `PipelineContext` is for compiling a single pipeline. If the pipeline is
  compiling a sub-pipeline (a `Pipeline` node as a `pipeline.components`) then
  another `PipelineContext` would be created and used.
  
  Use it as a first positional argument to the compiler extension functions as
  if you are extending a class and this is a self object.
class_docstr_tok: ["Encapsulates","resources","needed","to","compile","a","pipeline",".","`","PipelineContext","`","is","for","compiling","a","single","pipeline",".","If","the","pipeline","is","compiling","a","sub-pipeline","(","a","`","Pipeline","`","node","as","a","`","pipeline.components","`",")","then","another","`","PipelineContext","`","would","be","created","and","used",".","Use","it","as","a","first","positional","argument","to","the","compiler","extension","functions","as","if","you","are","extending","a","class","and","this","is","a","self","object","."]
code: def __init__(
      self,
      tfx_pipeline: pipeline.Pipeline,
      parent: Optional[PipelineContext] = None,
  ):
      self.pipeline = tfx_pipeline
  
      self.pipeline_info = self.pipeline.pipeline_info
      self.execution_mode = compiler_utils.resolve_execution_mode(
          self.pipeline
      )
      self.dsl_context_registry = self.pipeline.dsl_context_registry
      self.parent = parent or NullPipelineContext(child=self)
  
      # Stores channels available in the current pipeline scope.
      # Mapping from Channel object to compiled Channel proto.
      self.channels = dict()
  
      # Node ID -> NodeContext
      self._node_contexts: Dict[str, NodeContext] = {}
  
      # CondContext -> Context ID
      self._conditional_ids: Dict[conditional.CondContext, str] = {}
  
      self._pipeline_nodes_by_id = {}
      self._topological_order = {}
      self._implicit_upstream_nodes = collections.defaultdict(set)
      self._implicit_downstream_nodes = collections.defaultdict(set)
      for i, node in enumerate(tfx_pipeline.components, start=1):
          self._pipeline_nodes_by_id[node.id] = node
          self._topological_order[node.id] = i
          self._collect_conditional_dependency(node)
  
imports: from __future__ import annotations
  import collections
  from typing import Optional, List, Set, Iterable, Dict
  from tfx.dsl.compiler import compiler_utils
  from tfx.dsl.components.base import base_node
  from tfx.dsl.context_managers import dsl_context_registry
  from tfx.dsl.control_flow import for_each_internal
  from tfx.dsl.experimental.conditionals import conditional
  from tfx.dsl.input_resolution import resolver_op
  from tfx.orchestration import pipeline
  from tfx.proto.orchestration import pipeline_pb2
  from tfx.types import channel
  from tfx.types import channel_utils
label_desc: Use image node_id 1 to create a new PipelineContext object  with example: obj = PipelineContext(tfx_pipeline, parent)