def _fit(self, y, exogenous=None, **fit_args):
        """Internal fit"""

        # This wrapper is used for fitting either an ARIMA or a SARIMAX
        def _fit_wrapper():
            # these might change depending on which one
            method = self.method

            # If it's in kwargs, we'll use it
            trend = self.trend

            # if not seasonal:
            if not self._is_seasonal():
                if method is None:
                    method = "css-mle"

                if trend is None:
                    if self.with_intercept:
                        trend = 'c'
                    else:
                        trend = 'nc'

                # create the statsmodels ARIMA
                arima = _ARIMA(endog=y, order=self.order, missing='none',
                               exog=exogenous, dates=None, freq=None)

                # there's currently a bug in the ARIMA model where on pickling
                # it tries to acquire an attribute called
                # 'self.{dates|freq|missing}', but they do not exist as class
                # attrs! They're passed up to TimeSeriesModel in base, but
                # are never set. So we inject them here so as not to get an
                # AttributeError later. (see http://bit.ly/2f7SkKH)
                for attr, val in (('dates', None), ('freq', None),
                                  ('missing', 'none')):
                    if not hasattr(arima, attr):
                        setattr(arima, attr, val)
            else:
                if method is None:
                    method = 'lbfgs'

                if trend is None:
                    if self.with_intercept:
                        trend = 'c'
                    else:
                        trend = None

                # create the SARIMAX
                arima = sm.tsa.statespace.SARIMAX(
                    endog=y, exog=exogenous, order=self.order,
                    seasonal_order=self.seasonal_order, trend=trend,
                    enforce_stationarity=self.transparams)

            # actually fit the model, now. If this was called from 'update',
            # give priority to start_params from the fit_args
            start_params = fit_args.pop("start_params", self.start_params)

            # Same for 'maxiter' if called from update. Also allows it to be
            # passed as a fit arg, if a user does it explicitly.
            _maxiter = self.maxiter
            if _maxiter is None:
                if self._is_seasonal():
                    _maxiter = sm_compat.DEFAULT_SEASONAL_MAXITER  # 50
                else:
                    _maxiter = sm_compat.DEFAULT_NON_SEASONAL_MAXITER  # 500

            # If maxiter is provided in the fit_args by a savvy user or the
            # update method, we should default to their preference
            _maxiter = fit_args.pop("maxiter", _maxiter)

            return arima, arima.fit(start_params=start_params,
                                    trend=trend, method=method,
                                    transparams=self.transparams,
                                    solver=self.solver, maxiter=_maxiter,
                                    disp=self.disp, callback=self.callback,
                                    **fit_args)

        # sometimes too many warnings...
        if self.suppress_warnings:
            with warnings.catch_warnings(record=False):
                warnings.simplefilter('ignore')
                fit, self.arima_res_ = _fit_wrapper()
        else:
            fit, self.arima_res_ = _fit_wrapper()

        # Set df_model attribute for SARIMAXResults object
        sm_compat.bind_df_model(fit, self.arima_res_)

        # Non-seasonal ARIMA models may not capture sigma2. Statsmodels' code
        # is buggy and difficult to follow, so this checks whether it needs to
        # be set or not...
        # if (not self._is_seasonal()) and np.isnan(self.arima_res_.sigma2):
        #     self.arima_res_.sigma2 = self.arima_res_.model.loglike(
        #         self.params(), True)

        # if the model is fit with an exogenous array, it must
        # be predicted with one as well.
        self.fit_with_exog_ = exogenous is not None

        # Save nobs since we might change it later if using OOB
        self.nobs_ = y.shape[0]

        # As of version 0.7.2, start saving the version with the model so
        # we can track changes over time.
        self.pkg_version_ = pmdarima.__version__
        return self
Internal fit