Skip to content

Pin numpy to get ci back to green #45179

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 4, 2022
Merged

Conversation

phofl
Copy link
Member

@phofl phofl commented Jan 3, 2022

Let's see if this gets us back to green

@jreback jreback added the CI Continuous Integration label Jan 3, 2022
@jreback
Copy link
Contributor

jreback commented Jan 3, 2022

hmm something odd happeneing in the release then.

cc @seberg @charris

@phofl
Copy link
Member Author

phofl commented Jan 3, 2022

I think

``` @td.skip_if_no("numba") def test_alignment_deprecation_many_inputs(): # https://github.com//issues/39184 # test that the deprecation also works with > 2 inputs -> using a numba # written ufunc for this because numpy itself doesn't have such ufuncs from numba import ( float64, vectorize, )
    @vectorize([float64(float64, float64, float64)])
    def my_ufunc(x, y, z):
        return x + y + z

    df1 = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
    df2 = pd.DataFrame({"b": [1, 2, 3], "c": [4, 5, 6]})
    df3 = pd.DataFrame({"a": [1, 2, 3], "c": [4, 5, 6]})

    with tm.assert_produces_warning(FutureWarning):
      result = my_ufunc(df1, df2, df3)

pandas/tests/frame/test_ufunc.py:273:


pandas/core/generic.py:2078: in array_ufunc
return arraylike.array_ufunc(self, ufunc, method, *inputs, **kwargs)
pandas/core/arraylike.py:258: in array_ufunc
result = _maybe_fallback(ufunc, method, *inputs, **kwargs)
pandas/core/arraylike.py:236: in _maybe_fallback
return getattr(ufunc, method)(*new_inputs, **kwargs)
pandas/core/generic.py:2078: in array_ufunc
return arraylike.array_ufunc(self, ufunc, method, *inputs, **kwargs)


self = a b
0 1 4
1 2 5
2 3 6, ufunc = <ufunc 'my_ufunc'>
method = 'call'
inputs = (array([[1, 4],
[2, 5],
[3, 6]]), array([[1, 4],
[2, 5],
[3, 6]]), array([[1, 4],
[2, 5],
[3, 6]]))
kwargs = {}, cls = <class 'pandas.core.frame.DataFrame'>
result = NotImplemented
no_defer = (<method 'array_ufunc' of 'numpy.ndarray' objects>, <function NDFrame.array_ufunc at 0x7fed5e53dee0>)
item = array([[1, 4],
[2, 5],
[3, 6]]), higher_priority = False
has_array_ufunc = False
types = (<class 'pandas.core.frame.DataFrame'>, <class 'numpy.ndarray'>, <class 'numpy.ndarray'>)

def array_ufunc(self, ufunc: np.ufunc, method: str, *inputs: Any, **kwargs: Any):
    """
    Compatibility with numpy ufuncs.

    See also
    --------
    numpy.org/doc/stable/reference/arrays.classes.html#numpy.class.__array_ufunc__
    """
    from pandas.core.generic import NDFrame
    from pandas.core.internals import BlockManager

    cls = type(self)

    kwargs = _standardize_out_kwarg(**kwargs)

    # for backwards compatibility check and potentially fallback for non-aligned frames
    result = _maybe_fallback(ufunc, method, *inputs, **kwargs)
    if result is not NotImplemented:
        return result

    # for binary ops, use our custom dunder methods
    result = maybe_dispatch_ufunc_to_dunder_op(self, ufunc, method, *inputs, **kwargs)
    if result is not NotImplemented:
        return result

    # Determine if we should defer.

    # error: "Type[ndarray]" has no attribute "__array_ufunc__"
    no_defer = (
        np.ndarray.__array_ufunc__,  # type: ignore[attr-defined]
        cls.__array_ufunc__,
    )

    for item in inputs:
        higher_priority = (
            hasattr(item, "__array_priority__")
            and item.__array_priority__ > self.__array_priority__
        )
        has_array_ufunc = (
            hasattr(item, "__array_ufunc__")
            and type(item).__array_ufunc__ not in no_defer
            and not isinstance(item, self._HANDLED_TYPES)
        )
        if higher_priority or has_array_ufunc:
            return NotImplemented

    # align all the inputs.
    types = tuple(type(x) for x in inputs)
    alignable = [x for x, t in zip(inputs, types) if issubclass(t, NDFrame)]

    if len(alignable) > 1:
        # This triggers alignment.
        # At the moment, there aren't any ufuncs with more than two inputs
        # so this ends up just being x1.index | x2.index, but we write
        # it to handle *args.

        if len(set(types)) > 1:
            # We currently don't handle ufunc(DataFrame, Series)
            # well. Previously this raised an internal ValueError. We might
            # support it someday, so raise a NotImplementedError.
            raise NotImplementedError(
                "Cannot apply ufunc {} to mixed DataFrame and Series "
                "inputs.".format(ufunc)
            )
        axes = self.axes
        for obj in alignable[1:]:
            # this relies on the fact that we aren't handling mixed
            # series / frame ufuncs.
            for i, (ax1, ax2) in enumerate(zip(axes, obj.axes)):
                axes[i] = ax1.union(ax2)

        reconstruct_axes = dict(zip(self._AXIS_ORDERS, axes))
        inputs = tuple(
            x.reindex(**reconstruct_axes) if issubclass(t, NDFrame) else x
            for x, t in zip(inputs, types)
        )
    else:
        reconstruct_axes = dict(zip(self._AXIS_ORDERS, self.axes))

    if self.ndim == 1:
        names = [getattr(x, "name") for x in inputs if hasattr(x, "name")]
        name = names[0] if len(set(names)) == 1 else None
        reconstruct_kwargs = {"name": name}
    else:
        reconstruct_kwargs = {}

    def reconstruct(result):
        if ufunc.nout > 1:
            # np.modf, np.frexp, np.divmod
            return tuple(_reconstruct(x) for x in result)

        return _reconstruct(result)

    def _reconstruct(result):
        if lib.is_scalar(result):
            return result

        if result.ndim != self.ndim:
            if method == "outer":
                if self.ndim == 2:
                    # we already deprecated for Series
                    msg = (
                        "outer method for ufunc {} is not implemented on "
                        "pandas objects. Returning an ndarray, but in the "
                        "future this will raise a 'NotImplementedError'. "
                        "Consider explicitly converting the DataFrame "
                        "to an array with '.to_numpy()' first."
                    )
                    warnings.warn(
                        msg.format(ufunc), FutureWarning, stacklevel=find_stack_level()
                    )
                    return result
                raise NotImplementedError
            return result
        if isinstance(result, BlockManager):
            # we went through BlockManager.apply e.g. np.sqrt
            result = self._constructor(result, **reconstruct_kwargs, copy=False)
        else:
            # we converted an array, lost our axes
            result = self._constructor(
                result, **reconstruct_axes, **reconstruct_kwargs, copy=False
            )
        # TODO: When we support multiple values in __finalize__, this
        # should pass alignable to `__finalize__` instead of self.
        # Then `np.add(a, b)` would consider attrs from both a and b
        # when a and b are NDFrames.
        if len(alignable) == 1:
            result = result.__finalize__(self)
        return result

    if "out" in kwargs:
        # e.g. test_multiindex_get_loc
        result = dispatch_ufunc_with_out(self, ufunc, method, *inputs, **kwargs)
        return reconstruct(result)

    if method == "reduce":
        # e.g. test.series.test_ufunc.test_reduce
        result = dispatch_reduction_ufunc(self, ufunc, method, *inputs, **kwargs)
        if result is not NotImplemented:
            return result

    # We still get here with kwargs `axis` for e.g. np.maximum.accumulate
    #  and `dtype` and `keepdims` for np.ptp

    if self.ndim > 1 and (len(inputs) > 1 or ufunc.nout > 1):
        # Just give up on preserving types in the complex case.
        # In theory we could preserve them for them.
        # * nout>1 is doable if BlockManager.apply took nout and
        #   returned a Tuple[BlockManager].
        # * len(inputs) > 1 is doable when we know that we have
        #   aligned blocks / dtypes.

        # e.g. my_ufunc, modf, logaddexp, heaviside, subtract, add
        inputs = tuple(np.asarray(x) for x in inputs)
        # Note: we can't use default_array_ufunc here bc reindexing means
        #  that `self` may not be among `inputs`
      result = getattr(ufunc, method)(*inputs, **kwargs)

E numpy.core._exceptions._UFuncNoLoopError: ufunc 'my_ufunc' did not contain a loop with signature matching types (<class 'numpy.dtype[int64]'>, <class 'numpy.dtype[int64]'>, <class 'numpy.dtype[int64]'>) -> None

</details>

is the only real failure apart from the typing issues

@phofl
Copy link
Member Author

phofl commented Jan 3, 2022

xfailing for new numpy and pinning only for typing checks

@jreback jreback added this to the 1.4 milestone Jan 4, 2022
@jreback
Copy link
Contributor

jreback commented Jan 4, 2022

let's re-run this

@jreback jreback closed this Jan 4, 2022
@jreback jreback reopened this Jan 4, 2022
@phofl
Copy link
Member Author

phofl commented Jan 4, 2022

This looks good now, the lagging build has numpy 1.18.5

@jreback jreback merged commit 1696c0f into pandas-dev:master Jan 4, 2022
@jreback
Copy link
Contributor

jreback commented Jan 4, 2022

do we have an issue to revert the numpy pin? can u post a failing test here (not the one u x failed but)

@phofl
Copy link
Member Author

phofl commented Jan 4, 2022

I have linked the issue above, #45182
I posted the x-failed test and the typing issues there

@phofl phofl deleted the pin_numpy branch January 4, 2022 10:28
@jreback
Copy link
Contributor

jreback commented Jan 4, 2022

sure but do we actually need the numpy pin now that u x failed that particular test?

@phofl
Copy link
Member Author

phofl commented Jan 4, 2022

In the global environment yml yes, because this one is used for the typing checks.

@jreback
Copy link
Contributor

jreback commented Jan 4, 2022

ok got it thxs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI Continuous Integration
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants