Skip to content

TST: Fix maybe_promote floating non-boxed tests #28880

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 1 commit into from
Oct 10, 2019
Merged
Show file tree
Hide file tree
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
48 changes: 45 additions & 3 deletions pandas/core/dtypes/cast.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,14 +398,30 @@ def maybe_promote(dtype, fill_value=np.nan):
dtype = np.dtype(np.float64)
if not isna(fill_value):
fill_value = dtype.type(fill_value)

elif dtype.kind == "f":
if not np.can_cast(fill_value, dtype):
# e.g. dtype is float32, need float64
dtype = np.min_scalar_type(fill_value)

elif dtype.kind == "c":
if not np.can_cast(fill_value, dtype):
if np.can_cast(fill_value, np.dtype("c16")):
dtype = np.dtype(np.complex128)
else:
dtype = np.dtype(np.object_)

if dtype.kind == "c" and not np.isnan(fill_value):
fill_value = dtype.type(fill_value)

elif is_bool(fill_value):
if not issubclass(dtype.type, np.bool_):
dtype = np.object_
else:
fill_value = np.bool_(fill_value)
elif is_integer(fill_value):
if issubclass(dtype.type, np.bool_):
dtype = np.object_
dtype = np.dtype(np.object_)
elif issubclass(dtype.type, np.integer):
# upcast to prevent overflow
arr = np.asarray(fill_value)
Expand All @@ -415,11 +431,37 @@ def maybe_promote(dtype, fill_value=np.nan):
# check if we can cast
if _check_lossless_cast(fill_value, dtype):
fill_value = dtype.type(fill_value)

if dtype.kind in ["c", "f"]:
# e.g. if dtype is complex128 and fill_value is 1, we
# want np.complex128(1)
fill_value = dtype.type(fill_value)

elif is_complex(fill_value):
if issubclass(dtype.type, np.bool_):
dtype = np.object_
dtype = np.dtype(np.object_)
elif issubclass(dtype.type, (np.integer, np.floating)):
dtype = np.complex128
c8 = np.dtype(np.complex64)
info = np.finfo(dtype) if dtype.kind == "f" else np.iinfo(dtype)
if (
np.can_cast(fill_value, c8)
and np.can_cast(info.min, c8)
and np.can_cast(info.max, c8)
):
dtype = np.dtype(np.complex64)
else:
dtype = np.dtype(np.complex128)

elif dtype.kind == "c":
mst = np.min_scalar_type(fill_value)
if mst > dtype and mst.kind == "c":
# e.g. mst is np.complex128 and dtype is np.complex64
dtype = mst

if dtype.kind == "c":
# make sure we have a np.complex and not python complex
fill_value = dtype.type(fill_value)

elif fill_value is None:
if is_float_dtype(dtype) or is_complex_dtype(dtype):
fill_value = np.nan
Expand Down
15 changes: 2 additions & 13 deletions pandas/tests/dtypes/cast/test_promote.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,25 +408,14 @@ def test_maybe_promote_float_with_float(dtype, fill_value, expected_dtype, box):

if box_dtype == object:
pytest.xfail("falsely upcasts to object")
if boxed and is_float_dtype(dtype) and is_complex_dtype(expected_dtype):
elif boxed and is_float_dtype(dtype) and is_complex_dtype(expected_dtype):
pytest.xfail("does not upcast to complex")
if (dtype, expected_dtype) in [
elif boxed and (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]
Expand Down