# Buggy code
def fit(self, data, *args, **kwds):
    # Override rv_continuous.fit, so we can more efficiently handle the
    # case where floc and fscale are given.

    floc = kwds.get("floc", None)
    fscale = kwds.get("fscale", None)

    if floc is None or fscale is None:
        # do general fit
        return super(beta_gen, self).fit(data, *args, **kwds)

    # We already got these from kwds, so just pop them.
    kwds.pop("floc", None)
    kwds.pop("fscale", None)

    f0 = _get_fixed_fit_value(kwds, ["f0", "fa", "fix_a"])
    f1 = _get_fixed_fit_value(kwds, ["f1", "fb", "fix_b"])

    _remove_optimizer_parameters(kwds)

    if f0 is not None and f1 is not None:
        # This check is for consistency with `rv_continuous.fit`.
        raise ValueError("All parameters fixed. There is nothing to optimize.")

    # Special case: loc and scale are constrained, so we are fitting
    # just the shape parameters.  This can be done much more efficiently
    # than the method used in `rv_continuous.fit`.  (See the subsection
    # "Two unknown parameters" in the section "Maximum likelihood" of
    # the Wikipedia article on the Beta distribution for the formulas.)

    # Normalize the data to the interval [0, 1].
    data = (np.ravel(data) - floc) / fscale
    if np.any(data <= 0) or np.any(data >= 1):
        raise FitDataError("beta", lower=floc, upper=floc + fscale)
    xbar = data.mean()

    if f0 is not None or f1 is not None:
        # One of the shape parameters is fixed.

        if f0 is not None:
            # The shape parameter a is fixed, so swap the parameters
            # and flip the data.  We always solve for `a`.  The result
            # will be swapped back before returning.
            b = f0
            data = 1 - data
            xbar = 1 - xbar
        else:
            b = f1

        # Initial guess for a.  Use the formula for the mean of the beta
        # distribution, E[x] = a / (a + b), to generate a reasonable
        # starting point based on the mean of the data and the given
        # value of b.
        a = b * xbar / (1 - xbar)

        # Compute the MLE for `a` by solving _beta_mle_a.
        theta, info, ier, mesg = optimize.fsolve(
            _beta_mle_a, a, args=(b, len(data), np.log(data).sum()), full_output=True
        )
        if ier != 1:
            raise FitSolverError(mesg=mesg)
        a = theta[0]

        if f0 is not None:
            # The shape parameter a was fixed, so swap back the
            # parameters.
            a, b = b, a

    else:
        # Neither of the shape parameters is fixed.

        # s1 and s2 are used in the extra arguments passed to _beta_mle_ab
        # by optimize.fsolve.
        s1 = np.log(data).sum()
        s2 = sc.log1p(-data).sum()

        # Use the "method of moments" to estimate the initial
        # guess for a and b.
        fac = xbar * (1 - xbar) / data.var(ddof=0) - 1
        a = xbar * fac
        b = (1 - xbar) * fac

        # Compute the MLE for a and b by solving _beta_mle_ab.
        theta, info, ier, mesg = optimize.fsolve(
            _beta_mle_ab, [a, b], args=(len(data), s1, s2), full_output=True
        )
        if ier != 1:
            raise FitSolverError(mesg=mesg)
        a, b = theta

    return a, b, floc, fscale


# Traceback (RuntimeError)
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-86-fb3d43a0acaa> in <module>
13        1.5754, 2.2669, 1.6383, 1.7696, 1.9079, 1.0955, 1.5637, 2.66  ,
14        1.746 , 1.5319, 2.0958,    np.nan])
---> 15 K = stats.exponnorm.fit(x)

/anaconda3/lib/python3.7/site-packages/scipy/stats/_distn_infrastructure.py in fit(self, data, *args, **kwds)
2195                                          'scale' in kwds):
2196             # get distribution specific starting locations
-> 2197             start = self._fitstart(data)
2198             args += start[Narg:-2]
2199         loc = kwds.pop('loc', start[-2])

/anaconda3/lib/python3.7/site-packages/scipy/stats/_distn_infrastructure.py in _fitstart(self, data, args)
2034         if args is None:
2035             args = (1.0,)*self.numargs
-> 2036         loc, scale = self._fit_loc_scale_support(data, *args)
2037         return args + (loc, scale)
2038

/anaconda3/lib/python3.7/site-packages/scipy/stats/_distn_infrastructure.py in _fit_loc_scale_support(self, data, *args)
2287             return (data_b - b) + margin, 1
2288         else:
-> 2289             raise RuntimeError
2290
2291     def fit_loc_scale(self, data, *args):

RuntimeError:

# Fixed code
def fit(self, data, *args, **kwds):
    # Override rv_continuous.fit, so we can more efficiently handle the
    # case where floc and fscale are given.

    floc = kwds.get("floc", None)
    fscale = kwds.get("fscale", None)

    if floc is None or fscale is None:
        # do general fit
        return super(beta_gen, self).fit(data, *args, **kwds)

    # We already got these from kwds, so just pop them.
    kwds.pop("floc", None)
    kwds.pop("fscale", None)

    f0 = _get_fixed_fit_value(kwds, ["f0", "fa", "fix_a"])
    f1 = _get_fixed_fit_value(kwds, ["f1", "fb", "fix_b"])

    _remove_optimizer_parameters(kwds)

    if f0 is not None and f1 is not None:
        # This check is for consistency with `rv_continuous.fit`.
        raise ValueError("All parameters fixed. There is nothing to optimize.")

    # Special case: loc and scale are constrained, so we are fitting
    # just the shape parameters.  This can be done much more efficiently
    # than the method used in `rv_continuous.fit`.  (See the subsection
    # "Two unknown parameters" in the section "Maximum likelihood" of
    # the Wikipedia article on the Beta distribution for the formulas.)

    if not np.isfinite(data).all():
        raise RuntimeError("The data contains non-finite values.")

    # Normalize the data to the interval [0, 1].
    data = (np.ravel(data) - floc) / fscale
    if np.any(data <= 0) or np.any(data >= 1):
        raise FitDataError("beta", lower=floc, upper=floc + fscale)

    xbar = data.mean()

    if f0 is not None or f1 is not None:
        # One of the shape parameters is fixed.

        if f0 is not None:
            # The shape parameter a is fixed, so swap the parameters
            # and flip the data.  We always solve for `a`.  The result
            # will be swapped back before returning.
            b = f0
            data = 1 - data
            xbar = 1 - xbar
        else:
            b = f1

        # Initial guess for a.  Use the formula for the mean of the beta
        # distribution, E[x] = a / (a + b), to generate a reasonable
        # starting point based on the mean of the data and the given
        # value of b.
        a = b * xbar / (1 - xbar)

        # Compute the MLE for `a` by solving _beta_mle_a.
        theta, info, ier, mesg = optimize.fsolve(
            _beta_mle_a, a, args=(b, len(data), np.log(data).sum()), full_output=True
        )
        if ier != 1:
            raise FitSolverError(mesg=mesg)
        a = theta[0]

        if f0 is not None:
            # The shape parameter a was fixed, so swap back the
            # parameters.
            a, b = b, a

    else:
        # Neither of the shape parameters is fixed.

        # s1 and s2 are used in the extra arguments passed to _beta_mle_ab
        # by optimize.fsolve.
        s1 = np.log(data).sum()
        s2 = sc.log1p(-data).sum()

        # Use the "method of moments" to estimate the initial
        # guess for a and b.
        fac = xbar * (1 - xbar) / data.var(ddof=0) - 1
        a = xbar * fac
        b = (1 - xbar) * fac

        # Compute the MLE for a and b by solving _beta_mle_ab.
        theta, info, ier, mesg = optimize.fsolve(
            _beta_mle_ab, [a, b], args=(len(data), s1, s2), full_output=True
        )
        if ier != 1:
            raise FitSolverError(mesg=mesg)
        a, b = theta

    return a, b, floc, fscale