docs: def set_components(self, params):
          """ Set the value of exogenous model elements.
          Element values can be passed as keyword=value pairs in the function call.
          Values can be numeric type or pandas Series.
          Series will be interpolated by integrator.
  
          Examples
          --------
  
          >>> model.set_components({'birth_rate': 10})
          >>> model.set_components({'Birth Rate': 10})
  
          >>> br = pandas.Series(index=range(30), values=np.sin(range(30))
          >>> model.set_components({'birth_rate': br})
  
  
          """
          # It might make sense to allow the params argument to take a pandas series, where
          # the indices of the series are variable names. This would make it easier to
          # do a Pandas apply on a DataFrame of parameter values. However, this may conflict
          # with a pandas series being passed in as a dictionary element.
  
          for key, value in params.items():
              if isinstance(value, pd.Series):
                  new_function = self._timeseries_component(value)
              elif callable(value):
                  new_function = value
              else:
                  new_function = self._constant_component(value)
  
              func_name = utils.get_value_by_insensitive_key_or_value(key, self.components._namespace)
  
              if func_name is None:
                  raise NameError('%s is not recognized as a model component' % key)
  
              if '_integ_' + func_name in dir(self.components):  # this won't handle other statefuls...
                  warnings.warn("Replacing the equation of stock {} with params".format(key),
                                stacklevel=2)
  
              setattr(self.components, func_name, new_function)