class_docstr: Processes source nodes before other nodes are joined.
  
  Generally, the source nodes will be combined with other dataflow plan nodes to produce a new set of nodes to realize
  a condition of the query. For example, to realize a time range constraint, a ConstrainTimeRangeNode will be added
  to the source nodes.
  
  e.g.
  
  <SomeDataflowPlanNode/>
  
  ->
  
  <ConstrainTimeRangeNode>
      <SomeDataflowPlanNode/>
  </ConstrainTimeRangeNode>
code: def __init__(  # noqa: D
      self,
      semantic_model_lookup: SemanticModelAccessor,
      node_data_set_resolver: DataflowPlanNodeOutputDataSetResolver,
  ):
      self._node_data_set_resolver = node_data_set_resolver
      self._partition_resolver = PartitionJoinResolver(
          semantic_model_lookup
      )
      self._semantic_model_lookup = semantic_model_lookup
      self._join_evaluator = SemanticModelJoinEvaluator(
          semantic_model_lookup
      )
  
imports: from __future__ import annotations
  import logging
  from dataclasses import dataclass
  from typing import List, Optional, Sequence, Set
  from dbt_semantic_interfaces.pretty_print import pformat_big_objects
  from dbt_semantic_interfaces.references import EntityReference, TimeDimensionReference
  from metricflow.dataflow.builder.node_data_set import DataflowPlanNodeOutputDataSetResolver
  from metricflow.dataflow.builder.partitions import PartitionJoinResolver
  from metricflow.dataflow.dataflow_plan import BaseOutput, ConstrainTimeRangeNode, FilterElementsNode, JoinDescription, JoinToBaseOutputNode
  from metricflow.filters.time_constraint import TimeRangeConstraint
  from metricflow.model.semantics.semantic_model_join_evaluator import MAX_JOIN_HOPS, SemanticModelJoinEvaluator
  from metricflow.protocols.semantics import SemanticModelAccessor
  from metricflow.specs.spec_set_transforms import ToElementNameSet
  from metricflow.specs.specs import InstanceSpecSet, LinkableInstanceSpec, LinklessEntitySpec
  from metricflow.sql.sql_plan import SqlJoinType
label_desc: Use image node_id 1 to create a new PreJoinNodeProcessor object  with example: obj = PreJoinNodeProcessor(semantic_model_lookup, node_data_set_resolver)