Skip to content

Commit

Permalink
Ensure slow private attrs are maybe proxies (#14380)
Browse files Browse the repository at this point in the history
Expected pandas test failures:

>  tests/indexing/test_indexing.py

Due to this PR, it appears an `assert something._values is something_else` fails more after this PR since `._values` wraps objects in an proxy object now (a known failure mode)

> tests/series/indexing/test_setitem.py

Runs into the issue where a test set up calls `proxy._values[key] = something` using a pandas helper function that isn't proxying correctly

Authors:
  - Matthew Roeschke (https://github.com/mroeschke)
  - GALI PREM SAGAR (https://github.com/galipremsagar)

Approvers:
  - Bradley Dice (https://github.com/bdice)
  - GALI PREM SAGAR (https://github.com/galipremsagar)

URL: #14380
  • Loading branch information
mroeschke authored Feb 22, 2024
1 parent 4e39e71 commit 2b57c61
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 2 deletions.
19 changes: 18 additions & 1 deletion python/cudf/cudf/pandas/fast_slow_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,24 @@ def __getattr__(self, name: str) -> Any:
_raise_attribute_error(self.__class__.__name__, name)
if name.startswith("_"):
# private attributes always come from `._fsproxy_slow`:
return getattr(self._fsproxy_slow, name)
obj = getattr(self._fsproxy_slow, name)
if name.startswith("__array"):
# TODO: numpy methods raise when given proxy ndarray objects
# https://numpy.org/doc/stable/reference/arrays.classes.html#special-attributes-and-methods # noqa:E501
return obj

if not _is_function_or_method(obj):
return _maybe_wrap_result(
obj, getattr, self._fsproxy_slow, name
)

@functools.wraps(obj)
def _wrapped_private_slow(*args, **kwargs):
slow_args, slow_kwargs = _slow_arg(args), _slow_arg(kwargs)
result = obj(*slow_args, **slow_kwargs)
return _maybe_wrap_result(result, obj, *args, **kwargs)

return _wrapped_private_slow
attr = _FastSlowAttribute(name)
return attr.__get__(self)

Expand Down
7 changes: 7 additions & 0 deletions python/cudf/cudf_pandas_tests/test_cudf_pandas.py
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,13 @@ def test_dataframe_query():
tm.assert_equal(actual, expected)


def test_private_method_result_wrapped():
xoffset = xpd.offsets.Day()
dt = datetime.datetime(2020, 1, 1)
result = xoffset._apply(dt)
assert isinstance(result, xpd.Timestamp)


def test_numpy_var():
np.random.seed(42)
data = np.random.rand(1000)
Expand Down
31 changes: 30 additions & 1 deletion python/cudf/cudf_pandas_tests/test_fast_slow_proxy.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES.
# SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES.
# All rights reserved.
# SPDX-License-Identifier: Apache-2.0

Expand Down Expand Up @@ -445,6 +445,35 @@ def __radd__(self, other):
assert BarProxy() + Foo() == "sum"


def test_slow_attr_still_proxy():
class A:
pass

class B:
@property
def _private(self):
return A()

pxy_a = make_final_proxy_type(
"A",
_Unusable,
A,
fast_to_slow=_Unusable(),
slow_to_fast=_Unusable(),
)

pxy_b = make_final_proxy_type(
"B",
_Unusable,
B,
fast_to_slow=_Unusable(),
slow_to_fast=_Unusable(),
)

result = pxy_b()._private
assert isinstance(result, pxy_a)


def tuple_with_attrs(name, fields: list[str], extra_fields: set[str]):
# Build a tuple-like class with some extra attributes and a custom
# pickling scheme with __getnewargs_ex__
Expand Down

0 comments on commit 2b57c61

Please sign in to comment.