Skip to content

TST: port maybe_promote tests from #23982 #28764

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
Oct 3, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 144 additions & 9 deletions pandas/tests/dtypes/cast/test_promote.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,72 @@ def test_maybe_promote_float_with_int(float_dtype, any_int_dtype, box):
)


def test_maybe_promote_float_with_float():
# placeholder due to too many xfails; see GH 23982 / 25425
pass
@pytest.mark.parametrize(
"dtype, fill_value, expected_dtype",
[
# float filled with float
("float32", 1, "float32"),
("float32", np.finfo("float32").max * 1.1, "float64"),
("float64", 1, "float64"),
("float64", np.finfo("float32").max * 1.1, "float64"),
# complex filled with float
("complex64", 1, "complex64"),
("complex64", np.finfo("float32").max * 1.1, "complex128"),
("complex128", 1, "complex128"),
("complex128", np.finfo("float32").max * 1.1, "complex128"),
# float filled with complex
("float32", 1 + 1j, "complex64"),
("float32", np.finfo("float32").max * (1.1 + 1j), "complex128"),
("float64", 1 + 1j, "complex128"),
("float64", np.finfo("float32").max * (1.1 + 1j), "complex128"),
# complex filled with complex
("complex64", 1 + 1j, "complex64"),
("complex64", np.finfo("float32").max * (1.1 + 1j), "complex128"),
("complex128", 1 + 1j, "complex128"),
("complex128", np.finfo("float32").max * (1.1 + 1j), "complex128"),
],
)
def test_maybe_promote_float_with_float(dtype, fill_value, expected_dtype, box):

dtype = np.dtype(dtype)
expected_dtype = np.dtype(expected_dtype)
boxed, box_dtype = box # read from parametrized fixture

if box_dtype == object:
pytest.xfail("falsely upcasts to object")
if boxed and is_float_dtype(dtype) and is_complex_dtype(expected_dtype):
pytest.xfail("does not upcast to complex")
if (dtype, expected_dtype) in [
("float32", "float64"),
("float32", "complex64"),
("complex64", "complex128"),
]:
pytest.xfail("does not upcast correctly depending on value")
# this following xfails are "only" a consequence of the - now strictly
# enforced - principle that maybe_promote_with_scalar always casts
if not boxed and abs(fill_value) < 2:
pytest.xfail("wrong return type of fill_value")
if (
not boxed
and dtype == "complex128"
and expected_dtype == "complex128"
and is_float_dtype(type(fill_value))
):
pytest.xfail("wrong return type of fill_value")

# output is not a generic float, but corresponds to expected_dtype
exp_val_for_scalar = np.array([fill_value], dtype=expected_dtype)[0]
exp_val_for_array = np.nan

_check_promote(
dtype,
fill_value,
boxed,
box_dtype,
expected_dtype,
exp_val_for_scalar,
exp_val_for_array,
)


def test_maybe_promote_bool_with_any(any_numpy_dtype_reduced, box):
Expand Down Expand Up @@ -300,9 +363,45 @@ def test_maybe_promote_any_with_bytes():
pass


def test_maybe_promote_datetime64_with_any():
# placeholder due to too many xfails; see GH 23982 / 25425
pass
def test_maybe_promote_datetime64_with_any(
datetime64_dtype, any_numpy_dtype_reduced, box
):
dtype = np.dtype(datetime64_dtype)
fill_dtype = np.dtype(any_numpy_dtype_reduced)
boxed, box_dtype = box # read from parametrized fixture

if is_datetime64_dtype(fill_dtype):
if box_dtype == object:
pytest.xfail("falsely upcasts to object")
else:
if boxed and box_dtype is None:
pytest.xfail("does not upcast to object")
if not boxed:
pytest.xfail("does not upcast to object or raises")

# create array of given dtype; casts "1" to correct dtype
fill_value = np.array([1], dtype=fill_dtype)[0]

# filling datetime with anything but datetime casts to object
if is_datetime64_dtype(fill_dtype):
expected_dtype = dtype
# for datetime dtypes, scalar values get cast to to_datetime64
exp_val_for_scalar = pd.Timestamp(fill_value).to_datetime64()
exp_val_for_array = np.datetime64("NaT", "ns")
else:
expected_dtype = np.dtype(object)
exp_val_for_scalar = fill_value
exp_val_for_array = np.nan

_check_promote(
dtype,
fill_value,
boxed,
box_dtype,
expected_dtype,
exp_val_for_scalar,
exp_val_for_array,
)


# override parametrization of box to add special case for dt_dtype
Expand Down Expand Up @@ -505,9 +604,45 @@ def test_maybe_promote_any_numpy_dtype_with_datetimetz(
)


def test_maybe_promote_timedelta64_with_any():
# placeholder due to too many xfails; see GH 23982 / 25425
pass
def test_maybe_promote_timedelta64_with_any(
timedelta64_dtype, any_numpy_dtype_reduced, box
):
dtype = np.dtype(timedelta64_dtype)
fill_dtype = np.dtype(any_numpy_dtype_reduced)
boxed, box_dtype = box # read from parametrized fixture

if is_timedelta64_dtype(fill_dtype):
if box_dtype == object:
pytest.xfail("falsely upcasts to object")
else:
if boxed and box_dtype is None:
pytest.xfail("does not upcast to object")
if not boxed:
pytest.xfail("does not upcast to object or raises")

# create array of given dtype; casts "1" to correct dtype
fill_value = np.array([1], dtype=fill_dtype)[0]

# filling timedelta with anything but timedelta casts to object
if is_timedelta64_dtype(fill_dtype):
expected_dtype = dtype
# for timedelta dtypes, scalar values get cast to pd.Timedelta.value
exp_val_for_scalar = pd.Timedelta(fill_value).to_timedelta64()
exp_val_for_array = np.timedelta64("NaT", "ns")
else:
expected_dtype = np.dtype(object)
exp_val_for_scalar = fill_value
exp_val_for_array = np.nan

_check_promote(
dtype,
fill_value,
boxed,
box_dtype,
expected_dtype,
exp_val_for_scalar,
exp_val_for_array,
)


@pytest.mark.parametrize(
Expand Down