class_docstr: The state of a config.
code: def __post_init__(self) -> None:
      with StepProfiler(
          method="ConfigState.__post_init__",
          step="get_config_level_artifact_states",
          context=f"dataset={self.dataset},config={self.config}",
      ):
          self.artifact_state_by_step = {
              processing_step.name: ArtifactState(
                  processing_step=processing_step,
                  dataset=self.dataset,
                  revision=self.revision,
                  config=self.config,
                  split=None,
                  pending_jobs_df=self.pending_jobs_df[
                      (self.pending_jobs_df["split"].isnull())
                      & (
                          self.pending_jobs_df["type"]
                          == processing_step.job_type
                      )
                  ],
                  cache_entries_df=self.cache_entries_df[
                      self.cache_entries_df["kind"]
                      == processing_step.cache_kind
                  ],
              )
              for processing_step in self.processing_graph.get_input_type_processing_steps(
                  input_type="config"
              )
          }
  
      with StepProfiler(
          method="ConfigState.__post_init__",
          step="get_split_names",
          context=f"dataset={self.dataset},config={self.config}",
      ):
          self.split_names = fetch_names(
              dataset=self.dataset,
              config=self.config,
              cache_kinds=CONFIG_SPLIT_NAMES_KINDS,
              names_field="splits",
              name_field="split",
          )  # Note that we use the cached content even the revision is different (ie. maybe obsolete)
  
      with StepProfiler(
          method="ConfigState.__post_init__",
          step="get_split_states",
          context=f"dataset={self.dataset},config={self.config}",
      ):
          self.split_states = [
              SplitState(
                  self.dataset,
                  self.revision,
                  self.config,
                  split_name,
                  processing_graph=self.processing_graph,
                  pending_jobs_df=self.pending_jobs_df[
                      self.pending_jobs_df["split"] == split_name
                  ],
                  cache_entries_df=self.cache_entries_df[
                      self.cache_entries_df["split"] == split_name
                  ],
              )
              for split_name in self.split_names
          ]
  
imports: import logging
  from dataclasses import dataclass, field
  from typing import Optional
  import pandas
  from libcommon.constants import CONFIG_SPLIT_NAMES_KINDS, DATASET_CONFIG_NAMES_KINDS, ERROR_CODES_TO_RETRY, MAX_FAILED_RUNS
  from libcommon.processing_graph import Artifact, ProcessingGraph
  from libcommon.prometheus import StepProfiler
  from libcommon.simple_cache import CacheEntryMetadata, fetch_names
label_desc: Use image node_id 1 for calling the ConfigState obj's underlying member method code with example usage: obj.__post_init__() without return types