Skip to content

Commit 6a1c63d

Browse files
authored
Merge branch 'main' into main
2 parents 9b3eeeb + 59a977b commit 6a1c63d

File tree

6 files changed

+64
-1
lines changed

6 files changed

+64
-1
lines changed

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,7 @@ Strings
10141014
^^^^^^^
10151015
- Bug in :meth:`Series.str.zfill` raising ``AttributeError`` for :class:`ArrowDtype` (:issue:`61485`)
10161016
- Bug in :meth:`Series.value_counts` would not respect ``sort=False`` for series having ``string`` dtype (:issue:`55224`)
1017+
- Bug in multiplication with a :class:`StringDtype` incorrectly allowing multiplying by bools; explicitly cast to integers instead (:issue:`62595`)
10171018

10181019
Interval
10191020
^^^^^^^^

pandas/core/arrays/string_.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,16 @@ def _cmp_method(self, other, op):
11131113
other = np.asarray(other)
11141114
other = other[valid]
11151115

1116+
other_dtype = getattr(other, "dtype", None)
1117+
if op.__name__.strip("_") in ["mul", "rmul"] and (
1118+
lib.is_bool(other) or lib.is_np_dtype(other_dtype, "b")
1119+
):
1120+
# GH#62595
1121+
raise TypeError(
1122+
"Cannot multiply StringArray by bools. "
1123+
"Explicitly cast to integers instead."
1124+
)
1125+
11161126
if op.__name__ in ops.ARITHMETIC_BINOPS:
11171127
result = np.empty_like(self._ndarray, dtype="object")
11181128
result[mask] = self.dtype.na_value

pandas/io/formats/info.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1096,7 +1096,7 @@ def headers(self) -> Sequence[str]:
10961096

10971097
def _gen_rows_without_counts(self) -> Iterator[Sequence[str]]:
10981098
"""Iterator with string representation of body data without counts."""
1099-
yield from self._gen_dtypes()
1099+
yield from ([dtype] for dtype in self._gen_dtypes())
11001100

11011101
def _gen_rows_with_counts(self) -> Iterator[Sequence[str]]:
11021102
"""Iterator with string representation of body data with counts."""

pandas/tests/arithmetic/test_string.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,25 @@ def test_pyarrow_numpy_string_invalid():
112112

113113
with pytest.raises(TypeError, match="Invalid comparison"):
114114
ser > ser4
115+
116+
117+
def test_mul_bool_invalid(any_string_dtype):
118+
# GH#62595
119+
dtype = any_string_dtype
120+
ser = Series(["a", "b", "c"], dtype=dtype)
121+
122+
if dtype == object:
123+
pytest.skip("This is not expect to raise")
124+
elif dtype.storage == "python":
125+
msg = "Cannot multiply StringArray by bools. Explicitly cast to integers"
126+
else:
127+
msg = "Can only string multiply by an integer"
128+
129+
with pytest.raises(TypeError, match=msg):
130+
False * ser
131+
with pytest.raises(TypeError, match=msg):
132+
ser * True
133+
with pytest.raises(TypeError, match=msg):
134+
ser * np.array([True, False, True], dtype=bool)
135+
with pytest.raises(TypeError, match=msg):
136+
np.array([True, False, True], dtype=bool) * ser

pandas/tests/series/methods/test_info.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,23 @@ def test_info_memory_usage_bug_on_multiindex():
190190
# high upper bound
191191
diff = unstacked.memory_usage(deep=True).sum() - s.memory_usage(deep=True)
192192
assert diff < 2000
193+
194+
195+
def test_info_show_counts_false():
196+
s = Series([1])
197+
buf = StringIO()
198+
s.info(buf=buf, show_counts=False)
199+
result = buf.getvalue()
200+
memory_bytes = float(s.memory_usage())
201+
expected = textwrap.dedent(
202+
f"""\
203+
<class 'pandas.Series'>
204+
RangeIndex: 1 entries, 0 to 0
205+
Series name: None
206+
Dtype
207+
-----
208+
int64
209+
dtypes: int64(1)
210+
memory usage: {memory_bytes} bytes"""
211+
)
212+
assert result.strip() == expected.strip()

pandas/tests/util/test_assert_frame_equal.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import numpy as np
12
import pytest
23

34
from pandas.errors import Pandas4Warning
@@ -413,3 +414,12 @@ def test_datetimelike_compat_deprecated():
413414
tm.assert_series_equal(df["a"], df["a"], check_datetimelike_compat=True)
414415
with tm.assert_produces_warning(Pandas4Warning, match=msg):
415416
tm.assert_series_equal(df["a"], df["a"], check_datetimelike_compat=False)
417+
418+
419+
@pytest.mark.parametrize("na_value", [pd.NA, np.nan, None])
420+
def test_assert_frame_equal_nested_df_na(na_value):
421+
# GH#43022
422+
inner = DataFrame({"a": [1, na_value]})
423+
df1 = DataFrame({"df": [inner]})
424+
df2 = DataFrame({"df": [inner]})
425+
tm.assert_frame_equal(df1, df2)

0 commit comments

Comments
 (0)