Skip to content

Commit 76f0dad

Browse files
authored
BUG: iter(ser.str) did not raise TypeError (#54174)
* BUG: iter(ser.str) did not raise TypeError * pass through * Change test * Typing
1 parent 04180b0 commit 76f0dad

File tree

4 files changed

+38
-20
lines changed

4 files changed

+38
-20
lines changed

doc/source/whatsnew/v2.1.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ Conversion
492492

493493
Strings
494494
^^^^^^^
495-
-
495+
- Bug in :meth:`Series.str` that did not raise a ``TypeError`` when iterated (:issue:`54173`)
496496
-
497497

498498
Interval

pandas/core/strings/accessor.py

+27-17
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@
4848
from pandas.core.construction import extract_array
4949

5050
if TYPE_CHECKING:
51-
from collections.abc import Hashable
51+
from collections.abc import (
52+
Hashable,
53+
Iterator,
54+
)
5255

5356
from pandas import (
5457
DataFrame,
@@ -243,6 +246,9 @@ def __getitem__(self, key):
243246
result = self._data.array._str_getitem(key)
244247
return self._wrap_result(result)
245248

249+
def __iter__(self) -> Iterator:
250+
raise TypeError(f"'{type(self).__name__}' object is not iterable")
251+
246252
def _wrap_result(
247253
self,
248254
result,
@@ -438,22 +444,26 @@ def _get_series_list(self, others):
438444
others = DataFrame(others, index=idx)
439445
return [others[x] for x in others]
440446
elif is_list_like(others, allow_sets=False):
441-
others = list(others) # ensure iterators do not get read twice etc
442-
443-
# in case of list-like `others`, all elements must be
444-
# either Series/Index/np.ndarray (1-dim)...
445-
if all(
446-
isinstance(x, (ABCSeries, ABCIndex))
447-
or (isinstance(x, np.ndarray) and x.ndim == 1)
448-
for x in others
449-
):
450-
los: list[Series] = []
451-
while others: # iterate through list and append each element
452-
los = los + self._get_series_list(others.pop(0))
453-
return los
454-
# ... or just strings
455-
elif all(not is_list_like(x) for x in others):
456-
return [Series(others, index=idx)]
447+
try:
448+
others = list(others) # ensure iterators do not get read twice etc
449+
except TypeError:
450+
# e.g. ser.str, raise below
451+
pass
452+
else:
453+
# in case of list-like `others`, all elements must be
454+
# either Series/Index/np.ndarray (1-dim)...
455+
if all(
456+
isinstance(x, (ABCSeries, ABCIndex))
457+
or (isinstance(x, np.ndarray) and x.ndim == 1)
458+
for x in others
459+
):
460+
los: list[Series] = []
461+
while others: # iterate through list and append each element
462+
los = los + self._get_series_list(others.pop(0))
463+
return los
464+
# ... or just strings
465+
elif all(not is_list_like(x) for x in others):
466+
return [Series(others, index=idx)]
457467
raise TypeError(
458468
"others must be Series, Index, DataFrame, np.ndarray "
459469
"or list-like (either containing only strings or "

pandas/tests/dtypes/test_inference.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,9 @@ def shape(self):
150150
((_ for _ in []), True, "generator-empty"),
151151
(Series([1]), True, "Series"),
152152
(Series([], dtype=object), True, "Series-empty"),
153-
(Series(["a"]).str, False, "StringMethods"),
154-
(Series([], dtype="O").str, False, "StringMethods-empty"),
153+
# Series.str will still raise a TypeError if iterated
154+
(Series(["a"]).str, True, "StringMethods"),
155+
(Series([], dtype="O").str, True, "StringMethods-empty"),
155156
(Index([1]), True, "Index"),
156157
(Index([]), True, "Index-empty"),
157158
(DataFrame([[1]]), True, "DataFrame"),

pandas/tests/strings/test_strings.py

+7
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ def test_startswith_endswith_non_str_patterns(pattern):
2727
ser.str.endswith(pattern)
2828

2929

30+
def test_iter_raises():
31+
# GH 54173
32+
ser = Series(["foo", "bar"])
33+
with pytest.raises(TypeError, match="'StringMethods' object is not iterable"):
34+
iter(ser.str)
35+
36+
3037
# test integer/float dtypes (inferred by constructor) and mixed
3138

3239

0 commit comments

Comments
 (0)