class_docstr: Glues together all other inference classes in a sequence that actually runs inference.
docstr: Runs inference with the given configs.
docstr_tok: ["Runs","inference","with","the","given","configs","."]
code: def run(self) -> None:
      """Runs inference with the given configs."""
      # FIXME: currently we only accept DataWarehouseContextProvider
      provider: DataWarehouseInferenceContextProvider = self.context_providers[0]  # type: ignore
  
      with self._progress.warehouse():
          warehouse = provider.get_context(
              table_progress=self._progress.table,
          )
  
      with self._progress.rules():
          signals_by_column = defaultdict(list)
          signals = [rule.process(warehouse) for rule in self.ruleset]
          for rule_signal in tuple(more_itertools.flatten(signals)):
              signals_by_column[rule_signal.column].append(rule_signal)
  
      with self._progress.solver():
          results = [
              self.solver.solve_column(column, signals)
              for column, signals in signals_by_column.items()
          ]
  
      with self._progress.renderers():
          for renderer in self.renderers:
              renderer.render(results)
  
imports: from __future__ import annotations
  import contextlib
  import logging
  from abc import ABC, abstractmethod
  from collections import defaultdict
  from typing import Iterator, List
  import more_itertools
  from metricflow.dataflow.sql_table import SqlTable
  from metricflow.inference.context.base import InferenceContextProvider
  from metricflow.inference.context.data_warehouse import DataWarehouseInferenceContextProvider
  from metricflow.inference.renderer.base import InferenceRenderer
  from metricflow.inference.rule.base import InferenceRule
  from metricflow.inference.solver.base import InferenceSolver
label_desc: Use image node_id 2 for calling the InferenceRunner obj's underlying member method code with example usage: obj.run() without return types