class_docstr: Base forecaster template class.
  
  The base forecaster specifies the methods and method signatures that all forecasters
  have to implement.
  
  Specific implementations of these methods is deferred to concrete forecasters.
class_docstr_tok: ["Base","forecaster","template","class",".","The","base","forecaster","specifies","the","methods","and","method","signatures","that","all","forecasters","have","to","implement",".","Specific","implementations","of","these","methods","is","deferred","to","concrete","forecasters","."]
docstr: Check and coerce X/y for fit/predict/update functions.
  
  Parameters
  ----------
  y : pd.Series, pd.DataFrame, or np.ndarray (1D or 2D), optional (default=None)
      Time series to check.
  X : pd.DataFrame, or 2D np.array, optional (default=None)
      Exogeneous time series.
  
  Returns
  -------
  y_inner : Series, Panel, or Hierarchical object, or VectorizedDF
          compatible with self.get_tag("y_inner_mtype") format
      Case 1: self.get_tag("y_inner_mtype") supports scitype of y, then
          converted/coerced version of y, mtype determined by "y_inner_mtype" tag
      Case 2: self.get_tag("y_inner_mtype") does not support scitype of y, then
          VectorizedDF of y, iterated as the most complex supported scitype
              (complexity order: Hierarchical > Panel > Series)
      Case 3: None if y was None
  X_inner : Series, Panel, or Hierarchical object, or VectorizedDF
          compatible with self.get_tag("X_inner_mtype") format
      Case 1: self.get_tag("X_inner_mtype") supports scitype of X, then
          converted/coerced version of X, mtype determined by "X_inner_mtype" tag
      Case 2: self.get_tag("X_inner_mtype") does not support scitype of X, then
          VectorizedDF of X, iterated as the most complex supported scitype
      Case 3: None if X was None
  
  Raises
  ------
  TypeError if y or X is not one of the permissible Series mtypes
  TypeError if y is not compatible with self.get_tag("scitype:y")
      if tag value is "univariate", y must be univariate
      if tag value is "multivariate", y must be bi- or higher-variate
      if tag value is "both", y can be either
  TypeError if self.get_tag("X-y-must-have-same-index") is True
      and the index set of X is not a super-set of the index set of y
  
  Writes to self
  --------------
  _y_metadata : dict with str keys, metadata from checking y
  _converter_store_y : dict, metadata from conversion for back-conversion
docstr_tok: ["Check","and","coerce","X\/y","for","fit\/predict\/update","functions",".","Parameters","--","--","--","--","--","y",":","pd.Series",",","pd.DataFrame",",","or","np.ndarray","(","1D","or","2D",")",",","optional","(","default=None",")","Time","series","to","check",".","X",":","pd.DataFrame",",","or","2D","np.array",",","optional","(","default=None",")","Exogeneous","time","series",".","Returns","--","--","--","-","y_inner",":","Series",",","Panel",",","or","Hierarchical","object",",","or","VectorizedDF","compatible","with","self.get_tag","(","``","y_inner_mtype","''",")","format","Case","1",":","self.get_tag","(","``","y_inner_mtype","''",")","supports","scitype","of","y",",","then","converted\/coerced","version","of","y",",","mtype","determined","by","``","y_inner_mtype","''","tag","Case","2",":","self.get_tag","(","``","y_inner_mtype","''",")","does","not","support","scitype","of","y",",","then","VectorizedDF","of","y",",","iterated","as","the","most","complex","supported","scitype","(","complexity","order",":","Hierarchical",">","Panel",">","Series",")","Case","3",":","None","if","y","was","None","X_inner",":","Series",",","Panel",",","or","Hierarchical","object",",","or","VectorizedDF","compatible","with","self.get_tag","(","``","X_inner_mtype","''",")","format","Case","1",":","self.get_tag","(","``","X_inner_mtype","''",")","supports","scitype","of","X",",","then","converted\/coerced","version","of","X",",","mtype","determined","by","``","X_inner_mtype","''","tag","Case","2",":","self.get_tag","(","``","X_inner_mtype","''",")","does","not","support","scitype","of","X",",","then","VectorizedDF","of","X",",","iterated","as","the","most","complex","supported","scitype","Case","3",":","None","if","X","was","None","Raises","--","--","--","TypeError","if","y","or","X","is","not","one","of","the","permissible","Series","mtypes","TypeError","if","y","is","not","compatible","with","self.get_tag","(","``","scitype",":","y","''",")","if","tag","value","is","``","univariate","''",",","y","must","be","univariate","if","tag","value","is","``","multivariate","''",",","y","must","be","bi-","or","higher-variate","if","tag","value","is","``","both","''",",","y","can","be","either","TypeError","if","self.get_tag","(","``","X-y-must-have-same-index","''",")","is","True","and","the","index","set","of","X","is","not","a","super-set","of","the","index","set","of","y","Writes","to","self","--","--","--","--","--","--","--","_y_metadata",":","dict","with","str","keys",",","metadata","from","checking","y","_converter_store_y",":","dict",",","metadata","from","conversion","for","back-conversion"]
code: def _check_X_y(self, X=None, y=None):
      """Check and coerce X/y for fit/predict/update functions.
  
      Parameters
      ----------
      y : pd.Series, pd.DataFrame, or np.ndarray (1D or 2D), optional (default=None)
          Time series to check.
      X : pd.DataFrame, or 2D np.array, optional (default=None)
          Exogeneous time series.
  
      Returns
      -------
      y_inner : Series, Panel, or Hierarchical object, or VectorizedDF
              compatible with self.get_tag("y_inner_mtype") format
          Case 1: self.get_tag("y_inner_mtype") supports scitype of y, then
              converted/coerced version of y, mtype determined by "y_inner_mtype" tag
          Case 2: self.get_tag("y_inner_mtype") does not support scitype of y, then
              VectorizedDF of y, iterated as the most complex supported scitype
                  (complexity order: Hierarchical > Panel > Series)
          Case 3: None if y was None
      X_inner : Series, Panel, or Hierarchical object, or VectorizedDF
              compatible with self.get_tag("X_inner_mtype") format
          Case 1: self.get_tag("X_inner_mtype") supports scitype of X, then
              converted/coerced version of X, mtype determined by "X_inner_mtype" tag
          Case 2: self.get_tag("X_inner_mtype") does not support scitype of X, then
              VectorizedDF of X, iterated as the most complex supported scitype
          Case 3: None if X was None
  
      Raises
      ------
      TypeError if y or X is not one of the permissible Series mtypes
      TypeError if y is not compatible with self.get_tag("scitype:y")
          if tag value is "univariate", y must be univariate
          if tag value is "multivariate", y must be bi- or higher-variate
          if tag value is "both", y can be either
      TypeError if self.get_tag("X-y-must-have-same-index") is True
          and the index set of X is not a super-set of the index set of y
  
      Writes to self
      --------------
      _y_metadata : dict with str keys, metadata from checking y
      _converter_store_y : dict, metadata from conversion for back-conversion
      """
      if X is None and y is None:
          return None, None
  
      def _most_complex_scitype(scitypes, smaller_equal_than=None):
          """Return most complex scitype in a list of str."""
          if (
              "Hierarchical" in scitypes
              and smaller_equal_than == "Hierarchical"
          ):
              return "Hierarchical"
          elif "Panel" in scitypes and smaller_equal_than != "Series":
              return "Panel"
          elif "Series" in scitypes:
              return "Series"
          else:
              raise ValueError(
                  "no series scitypes supported, bug in estimator"
              )
  
      def _check_missing(metadata, obj_name):
          """Check input metadata against self's missing capability tag."""
          if not self.get_tag("handles-missing-data"):
              msg = (
                  f"{type(self).__name__} cannot handle missing data (nans), "
                  f"but {obj_name} passed contained missing data."
              )
              if self.get_class_tag("handles-missing-data"):
                  msg = msg + (
                      f" Whether instances of {type(self).__name__} can handle "
                      "missing data depends on parameters of the instance, "
                      "e.g., estimator components."
                  )
              if metadata["has_nans"]:
                  raise ValueError(msg)
  
      # retrieve supported mtypes
      y_inner_mtype = _coerce_to_list(self.get_tag("y_inner_mtype"))
      X_inner_mtype = _coerce_to_list(self.get_tag("X_inner_mtype"))
      y_inner_scitype = mtype_to_scitype(
          y_inner_mtype, return_unique=True
      )
      X_inner_scitype = mtype_to_scitype(
          X_inner_mtype, return_unique=True
      )
  
      ALLOWED_SCITYPES = ["Series", "Panel", "Hierarchical"]
      FORBIDDEN_MTYPES = ["numpyflat", "pd-wide"]
  
      mtypes_messages = []
      for scitype in ALLOWED_SCITYPES:
          mtypes = set(scitype_to_mtype(scitype))
          mtypes = list(mtypes.difference(FORBIDDEN_MTYPES))
          mtypes_messages.append(f'"For {scitype} scitype: {mtypes}. ')
  
      # checking y
      if y is not None:
          # request only required metadata from checks
          y_metadata_required = ["n_features", "feature_names"]
          if self.get_tag("scitype:y") != "both":
              y_metadata_required += ["is_univariate"]
          if not self.get_tag("handles-missing-data"):
              y_metadata_required += ["has_nans"]
  
          y_valid, _, y_metadata = check_is_scitype(
              y,
              scitype=ALLOWED_SCITYPES,
              return_metadata=y_metadata_required,
              var_name="y",
          )
          msg = (
              "y must be in an sktime compatible format, "
              f"of scitype {', '.join(ALLOWED_SCITYPES)}, "
              "for instance a pandas.DataFrame with sktime compatible time indices, "
              "or with MultiIndex and last(-1) level an sktime compatible time index."
              " See the forecasting tutorial examples/01_forecasting.ipynb, or"
              " the data format tutorial examples/AA_datatypes_and_datasets.ipynb,"
              "If you think y is already in an sktime supported input format, "
              "run sktime.datatypes.check_raise(y, mtype) to diagnose the error, "
              "where mtype is the string of the type specification you want for y. "
              "Possible mtype specification strings are as follows: "
          )
          if not y_valid:
              raise TypeError(msg + ", ".join(mtypes_messages))
  
          y_scitype = y_metadata["scitype"]
          self._y_metadata = y_metadata
          self._y_mtype_last_seen = y_metadata["mtype"]
  
          req_vec_because_rows = y_scitype not in y_inner_scitype
          req_vec_because_cols = (
              self.get_tag("scitype:y") == "univariate"
              and not y_metadata["is_univariate"]
          )
          requires_vectorization = (
              req_vec_because_rows or req_vec_because_cols
          )
  
          if (
              self.get_tag("scitype:y") == "multivariate"
              and y_metadata["is_univariate"]
          ):
              raise ValueError(
                  "y must have two or more variables, but found only one"
              )
  
          _check_missing(y_metadata, "y")
  
      else:
          # y_scitype is used below - set to None if y is None
          y_scitype = None
          requires_vectorization = False
      # end checking y
  
      # checking X
      if X is not None:
          # request only required metadata from checks
          X_metadata_required = []
          if not self.get_tag("handles-missing-data"):
              X_metadata_required += ["has_nans"]
  
          X_valid, _, X_metadata = check_is_scitype(
              X,
              scitype=ALLOWED_SCITYPES,
              return_metadata=X_metadata_required,
              var_name="X",
          )
  
          msg = (
              "X must be either None, or in an sktime compatible format, "
              "of scitype Series, Panel or Hierarchical, "
              "for instance a pandas.DataFrame with sktime compatible time indices, "
              "or with MultiIndex and last(-1) level an sktime compatible time index."
              " See the forecasting tutorial examples/01_forecasting.ipynb, or"
              " the data format tutorial examples/AA_datatypes_and_datasets.ipynb"
              "If you think X is already in an sktime supported input format, "
              "run sktime.datatypes.check_raise(X, mtype) to diagnose the error, "
              "where mtype is the string of the type specification you want for X. "
              "Possible mtype specification strings are as follows. "
          )
          if not X_valid:
              raise TypeError(msg + ", ".join(mtypes_messages))
  
          X_scitype = X_metadata["scitype"]
          X_requires_vectorization = X_scitype not in X_inner_scitype
          requires_vectorization = (
              requires_vectorization or X_requires_vectorization
          )
  
          _check_missing(X_metadata, "X")
  
      else:
          # X_scitype is used below - set to None if X is None
          X_scitype = None
  
      # extra check: if X is ignored by inner methods, pass None to them
      if self.get_tag("ignores-exogeneous-X"):
          X = None
          X_scitype = None
      # end checking X
  
      # compatibility checks between X and y
      if X is not None and y is not None:
          if self.get_tag("X-y-must-have-same-index"):
              # currently, check_equal_time_index only works for Series
              # TODO: fix this so the check is general, using get_time_index
              if (
                  not self.get_tag("ignores-exogeneous-X")
                  and X_scitype == "Series"
              ):
                  check_equal_time_index(X, y, mode="contains")
  
          if y_scitype != X_scitype:
              raise TypeError("X and y must have the same scitype")
      # end compatibility checking X and y
  
      # TODO: add tests that :
      #   y_inner_scitype are same as X_inner_scitype
      #   y_inner_scitype always includes "less index" scitypes
  
      # convert X & y to supported inner type, if necessary
      #####################################################
  
      # convert X and y to a supported internal mtype
      #  it X/y mtype is already supported, no conversion takes place
      #  if X/y is None, then no conversion takes place (returns None)
      #  if vectorization is required, we wrap in Vect
  
      if not requires_vectorization:
          # converts y, skips conversion if already of right type
          y_inner = convert_to(
              y,
              to_type=y_inner_mtype,
              as_scitype=y_scitype,  # we are dealing with series
              store=self._converter_store_y,
              store_behaviour="reset",
          )
  
          # converts X, converts None to None if X is None
          X_inner = convert_to(
              X,
              to_type=X_inner_mtype,
              as_scitype=X_scitype,  # we are dealing with series
          )
      else:
          iterate_as = _most_complex_scitype(
              y_inner_scitype, smaller_equal_than=y_scitype
          )
          if y is not None:
              y_inner = VectorizedDF(
                  X=y,
                  iterate_as=iterate_as,
                  is_scitype=y_scitype,
                  iterate_cols=req_vec_because_cols,
              )
          else:
              y_inner = None
          if X is not None:
              X_inner = VectorizedDF(
                  X=X, iterate_as=iterate_as, is_scitype=X_scitype
              )
          else:
              X_inner = None
  
      return X_inner, y_inner
  
imports: from copy import deepcopy
  from itertools import product
  import numpy
  import pandas
  from sktime.base import BaseEstimator
  from sktime.datatypes import VectorizedDF, check_is_scitype, convert_to, get_cutoff, mtype_to_scitype, scitype_to_mtype, update_data
  from sktime.forecasting.base._fh import ForecastingHorizon
  from sktime.utils.datetime import _shift
  from sktime.utils.validation._dependencies import _check_estimator_deps
  from sktime.utils.validation.forecasting import check_alpha, check_cv, check_fh, check_X
  from sktime.utils.validation.series import check_equal_time_index
  from sktime.utils.warnings import warn
label_desc: Use image node_id 20 for calling the BaseForecaster obj's underlying member method code with example usage: obj._check_X_y(X, y) and returns: X_inner,  y_inner, None,  None, str, str, str