Repository: scipy/scipy
File: scipy/optimize/_optimize.py (Python)

Code before:

    Nshape = shape(Jout)

    indx = argmin(Jout.ravel(), axis=-1)
    Nindx = np.empty(N, int)
    xmin = np.empty(N, float)
    for k in range(N - 1, -1, -1):
        thisN = Nshape[k]
        Nindx[k] = indx % Nshape[k]
        indx = indx // thisN
    for k in range(N):
        xmin[k] = grid[k][tuple(Nindx)]

    Jmin = Jout[tuple(Nindx)]
    if (N == 1):
        grid = grid[0]
        xmin = xmin[0]

    if callable(finish):
        # set up kwargs for `finish` function
        _finish_args = wrapped_inspect_signature(finish)
        finish_args = [
            p.name for p in _finish_args.parameters.values()
            if p.kind in [inspect.Parameter.POSITIONAL_OR_KEYWORD,
                          inspect.Parameter.KEYWORD_ONLY]
        ]
        finish_kwargs = dict()
        if 'full_output' in finish_args:
            finish_kwargs['full_output'] = 1
        if 'disp' in finish_args:
            finish_kwargs['disp'] = disp
        elif 'options' in finish_args:
            # pass 'disp' as `options`
            # (e.g., if `finish` is `minimize`)
            finish_kwargs['options'] = {'disp': disp}

        # run minimizer
        res = finish(func, xmin, args=args, **finish_kwargs)

        if isinstance(res, OptimizeResult):
            xmin = res.x
            Jmin = res.fun
            success = res.success
        else:
            xmin = res[0]
            Jmin = res[1]
            success = res[-1] == 0
        if not success:
            if disp:
                warnings.warn("Either final optimization did not succeed or `finish` "
                              "does not return `statuscode` as its last argument.",

Review comment (suggestion):
Rather than make this change, can you fix `getfullargspec_no_self()` instead? That has many callers, and likely almost none of them care about annotations. (The name refers to a legacy API, so anything calling this was likely written before annotations existed.)

Code after:

    Nshape = shape(Jout)

    indx = argmin(Jout.ravel(), axis=-1)
    Nindx = np.empty(N, int)
    xmin = np.empty(N, float)
    for k in range(N - 1, -1, -1):
        thisN = Nshape[k]
        Nindx[k] = indx % Nshape[k]
        indx = indx // thisN
    for k in range(N):
        xmin[k] = grid[k][tuple(Nindx)]

    Jmin = Jout[tuple(Nindx)]
    if (N == 1):
        grid = grid[0]
        xmin = xmin[0]

    if callable(finish):
        # set up kwargs for `finish` function
        finish_args = _getfullargspec(finish).args
        finish_kwargs = dict()
        if 'full_output' in finish_args:
            finish_kwargs['full_output'] = 1
        if 'disp' in finish_args:
            finish_kwargs['disp'] = disp
        elif 'options' in finish_args:
            # pass 'disp' as `options`
            # (e.g., if `finish` is `minimize`)
            finish_kwargs['options'] = {'disp': disp}

        # run minimizer
        res = finish(func, xmin, args=args, **finish_kwargs)

        if isinstance(res, OptimizeResult):
            xmin = res.x
            Jmin = res.fun
            success = res.success
        else:
            xmin = res[0]
            Jmin = res[1]
            success = res[-1] == 0
        if not success:
            if disp:
                warnings.warn("Either final optimization did not succeed or `finish` "
                              "does not return `statuscode` as its last argument.",
                              RuntimeWarning, stacklevel=2)

    if full_output:
        return xmin, Jmin, grid, Jout
    else: