code: def test_run_forecast_config_custom():
      """Tests `run_forecast_config` on weekly data with custom config:
  
      - numeric and categorical regressors
      - coverage
      - null model
      """
      data = generate_df_with_reg_for_tests(
          freq="W-MON",
          periods=140,
          remove_extra_cols=True,
          mask_test_actuals=True,
      )
      reg_cols = ["regressor1", "regressor2", "regressor_categ"]
      keep_cols = [TIME_COL, VALUE_COL] + reg_cols
      df = data["df"][keep_cols]
  
      metric = EvaluationMetricEnum.MeanAbsoluteError
      evaluation_metric = EvaluationMetricParam(
          cv_selection_metric=metric.name,
          agg_periods=7,
          agg_func=np.max,
          null_model_params={
              "strategy": "quantile",
              "constant": None,
              "quantile": 0.5,
          },
      )
  
      evaluation_period = EvaluationPeriodParam(
          test_horizon=10,
          periods_between_train_test=5,
          cv_horizon=4,
          cv_min_train_periods=80,
          cv_expanding_window=False,
          cv_periods_between_splits=20,
          cv_periods_between_train_test=3,
          cv_max_splits=3,
      )
  
      model_components = ModelComponentsParam(
          regressors={"regressor_cols": reg_cols},
          custom={
              "fit_algorithm_dict": {
                  "fit_algorithm": "ridge",
                  "fit_algorithm_params": {"cv": 2},
              }
          },
      )
      computation = ComputationParam(verbose=2)
      forecast_horizon = 27
      coverage = 0.90
  
      forecast_config = ForecastConfig(
          model_template=ModelTemplateEnum.SILVERKITE.name,
          computation_param=computation,
          coverage=coverage,
          evaluation_metric_param=evaluation_metric,
          evaluation_period_param=evaluation_period,
          forecast_horizon=forecast_horizon,
          model_components_param=model_components,
      )
  
      with warnings.catch_warnings():
          warnings.simplefilter("ignore")
          forecaster = Forecaster()
          result = forecaster.run_forecast_config(
              df=df, config=forecast_config
          )
  
          mse = (
              EvaluationMetricEnum.RootMeanSquaredError.get_metric_name()
          )
          q80 = EvaluationMetricEnum.Quantile80.get_metric_name()
          assert result.backtest.test_evaluation[mse] == pytest.approx(
              3.299, rel=1e-2
          )
          assert result.backtest.test_evaluation[q80] == pytest.approx(
              1.236, rel=1e-2
          )
          assert result.forecast.train_evaluation[mse] == pytest.approx(
              1.782, rel=1e-2
          )
          assert result.forecast.train_evaluation[q80] == pytest.approx(
              0.746, rel=1e-2
          )
          check_forecast_pipeline_result(
              result,
              coverage=coverage,
              strategy=None,
              score_func=metric.name,
              greater_is_better=False,
          )
  
      # Note that for newer scikit-learn (1.1+), we need to add a check for ValueError, matching "model is misconfigured"
      with pytest.raises((ValueError, KeyError)) as exception_info:
          model_components = ModelComponentsParam(
              regressors={"regressor_cols": ["missing_regressor"]}
          )
          forecaster = Forecaster()
          result = forecaster.run_forecast_config(
              df=df,
              config=ForecastConfig(
                  model_template=ModelTemplateEnum.SILVERKITE.name,
                  model_components_param=model_components,
              ),
          )
          check_forecast_pipeline_result(
              result,
              coverage=None,
              strategy=None,
              score_func=metric.get_metric_func(),
              greater_is_better=False,
          )
      info_str = str(exception_info.value)
      assert (
          "missing_regressor" in info_str
          or "model is misconfigured" in info_str
      )
  
imports: import sys
  import warnings
  from enum import Enum
  import numpy
  import pandas
  import pytest
  from testfixtures import LogCapture
  from greykite.common.constants import LOGGER_NAME
  from greykite.common.constants import PREDICTED_LOWER_COL
  from greykite.common.constants import PREDICTED_UPPER_COL
  from greykite.common.constants import TIME_COL
  from greykite.common.constants import VALUE_COL
  from greykite.common.data_loader import DataLoader
  from greykite.common.evaluation import EvaluationMetricEnum
  from greykite.common.python_utils import assert_equal
  from greykite.common.testing_utils import generate_df_for_tests
  from greykite.common.testing_utils import generate_df_with_reg_for_tests
  from greykite.framework.templates.autogen.forecast_config import ComputationParam
  from greykite.framework.templates.autogen.forecast_config import EvaluationMetricParam
  from greykite.framework.templates.autogen.forecast_config import EvaluationPeriodParam
  from greykite.framework.templates.autogen.forecast_config import ForecastConfig
  from greykite.framework.templates.autogen.forecast_config import MetadataParam
  from greykite.framework.templates.autogen.forecast_config import ModelComponentsParam
  from greykite.framework.templates.forecaster import Forecaster
  from greykite.framework.templates.model_templates import ModelTemplate
  from greykite.framework.templates.model_templates import ModelTemplateEnum
  from greykite.framework.templates.prophet_template import ProphetTemplate
  from greykite.framework.templates.silverkite_template import SilverkiteTemplate
  from greykite.framework.templates.simple_silverkite_template import SimpleSilverkiteTemplate
  from greykite.framework.templates.simple_silverkite_template_config import SILVERKITE_COMPONENT_KEYWORDS
  from greykite.framework.templates.simple_silverkite_template_config import SimpleSilverkiteTemplateOptions
  from greykite.framework.utils.framework_testing_utils import assert_basic_pipeline_equal
  from greykite.framework.utils.framework_testing_utils import assert_forecast_pipeline_result_equal
  from greykite.framework.utils.framework_testing_utils import check_forecast_pipeline_result
  from greykite.framework.utils.result_summary import summarize_grid_search_results
label_desc: Use image node_id 7 for calling a global function with example usage: test_run_forecast_config_custom() without return types