class_docstr: A graph of processing steps.
  
  The processing steps can have multiple parents, and multiple children (next processing steps, found automatically
    by traversing the graph).
  The graph can have multiple roots.
  
  Args:
      specification (ProcessingGraphSpecification): The specification of the graph.
  
  Raises:
      ValueError: If the graph is not a DAG.
      ValueError: If a processing step provides dataset config names but its input type is not 'dataset', or if a
        processing step provides config split names but its input type is not 'config'.
      ValueError: If a root processing step (ie. a processing step with no parent) is not a dataset processing step.
class_docstr_tok: ["A","graph","of","processing","steps",".","The","processing","steps","can","have","multiple","parents",",","and","multiple","children","(","next","processing","steps",",","found","automatically","by","traversing","the","graph",")",".","The","graph","can","have","multiple","roots",".","Args",":","specification","(","ProcessingGraphSpecification",")",":","The","specification","of","the","graph",".","Raises",":","ValueError",":","If","the","graph","is","not","a","DAG",".","ValueError",":","If","a","processing","step","provides","dataset","config","names","but","its","input","type","is","not","'dataset","'",",","or","if","a","processing","step","provides","config","split","names","but","its","input","type","is","not","'config","'",".","ValueError",":","If","a","root","processing","step","(","ie",".","a","processing","step","with","no","parent",")","is","not","a","dataset","processing","step","."]
docstr: Get the list of parents processing steps
  
  The parent processing steps are the ones that trigger the processing step.
  
  The returned processing steps are copies of the original ones, so that they can be modified without affecting
  the original ones.
  
  Args:
      processing_step_name (str): The name of the processing step
  
  Returns:
      list[ProcessingStep]: The list of parent processing steps (predecessors)
  
  Raises:
      ProcessingStepDoesNotExist: If the processing step is not in the graph
docstr_tok: ["Get","the","list","of","parents","processing","steps","The","parent","processing","steps","are","the","ones","that","trigger","the","processing","step",".","The","returned","processing","steps","are","copies","of","the","original","ones",",","so","that","they","can","be","modified","without","affecting","the","original","ones",".","Args",":","processing_step_name","(","str",")",":","The","name","of","the","processing","step","Returns",":","list","[","ProcessingStep","]",":","The","list","of","parent","processing","steps","(","predecessors",")","Raises",":","ProcessingStepDoesNotExist",":","If","the","processing","step","is","not","in","the","graph"]
code: def get_parents(
      self, processing_step_name: str
  ) -> list[ProcessingStep]:
      """
      Get the list of parents processing steps
  
      The parent processing steps are the ones that trigger the processing step.
  
      The returned processing steps are copies of the original ones, so that they can be modified without affecting
      the original ones.
  
      Args:
          processing_step_name (str): The name of the processing step
  
      Returns:
          list[ProcessingStep]: The list of parent processing steps (predecessors)
  
      Raises:
          ProcessingStepDoesNotExist: If the processing step is not in the graph
      """
      try:
          return [
              self.get_processing_step(predecessor)
              for predecessor in self._nx_graph.predecessors(
                  processing_step_name
              )
          ]
      except nx.NetworkXError as e:
          raise ProcessingStepDoesNotExist(
              f"Unknown processing step: {processing_step_name}"
          ) from e
  
imports: from __future__ import annotations
  from collections.abc import Mapping
  from dataclasses import dataclass, field
  from typing import Any, Literal, Optional, TypedDict, Union, get_args
  import networkx
  from libcommon.constants import DEFAULT_DIFFICULTY, DEFAULT_INPUT_TYPE, DEFAULT_JOB_RUNNER_VERSION, MIN_BYTES_FOR_BONUS_DIFFICULTY
  from libcommon.utils import inputs_to_string
label_desc: Use image node_id 5 for calling the ProcessingGraph obj's underlying member method code with example usage: obj.get_parents(processing_step_name) and returns: unknown