Skip to content

Commit 88d8650

Browse files
CLN: re-use maybe_cast_to_integer_array for checked cast in python parser
1 parent 520cae3 commit 88d8650

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
lines changed

pandas/io/parsers/base_parser.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
from pandas.util._exceptions import find_stack_level
4444

4545
from pandas.core.dtypes.astype import astype_nansafe
46+
from pandas.core.dtypes.cast import maybe_cast_to_integer_array
4647
from pandas.core.dtypes.common import (
4748
ensure_object,
4849
is_bool_dtype,
@@ -789,16 +790,14 @@ def _cast_types(self, values, cast_type, column):
789790

790791
else:
791792
try:
792-
casted = astype_nansafe(values, cast_type, copy=True, skipna=True)
793-
except ValueError as err:
793+
if is_integer_dtype(cast_type):
794+
values = maybe_cast_to_integer_array(values, cast_type, copy=True)
795+
else:
796+
values = astype_nansafe(values, cast_type, copy=True, skipna=True)
797+
except (ValueError, OverflowError) as err:
794798
raise ValueError(
795799
f"Unable to convert column {column} to type {cast_type}"
796800
) from err
797-
if is_integer_dtype(cast_type) and not (casted == values).all():
798-
raise TypeError(
799-
f"cannot safely cast non-equivalent {values.dtype} to {cast_type}"
800-
)
801-
values = casted
802801
return values
803802

804803
@overload

pandas/tests/io/parser/common/test_ints.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import pandas._testing as tm
1616
from pandas.api.types import (
1717
is_extension_array_dtype,
18+
is_unsigned_integer_dtype,
1819
pandas_dtype,
1920
)
2021

@@ -142,6 +143,22 @@ def test_integer_overflow_with_user_dtype(all_parsers, any_int_dtype, getval, ex
142143
val = getval(dtype)
143144
data = f"A\n{val}"
144145

146+
# Positive value overflow with uint8, uint16, uint32 and any overflow with
147+
# int8, int16, int32 only throw a FutureWarning until deprecation from #41734
148+
# becomes enforced. After enforcement, the following block must be deleted.
149+
if (
150+
(expected is _raises_int_overflow)
151+
and (parser.engine == "python")
152+
and (not is_extension_array_dtype(dtype))
153+
and (dtype < np.dtype("int64"))
154+
and not (is_unsigned_integer_dtype(dtype) and (val < 0))
155+
):
156+
expected = tm.assert_produces_warning(
157+
FutureWarning,
158+
match=f"Values are too large to be losslessly cast to {dtype}.",
159+
check_stacklevel=False,
160+
)
161+
145162
with expected:
146163
result = parser.read_csv(StringIO(data), dtype=dtype)
147164
if "result" in locals():

0 commit comments

Comments
 (0)