@@ -166,7 +166,16 @@ def test_contains_na_kwarg_for_nullable_string_dtype(
166
166
# https://github.com/pandas-dev/pandas/pull/41025#issuecomment-824062416
167
167
168
168
values = Series (["a" , "b" , "c" , "a" , np .nan ], dtype = nullable_string_dtype )
169
- result = values .str .contains ("a" , na = na , regex = regex )
169
+
170
+ msg = (
171
+ "Allowing a non-bool 'na' in obj.str.contains is deprecated and "
172
+ "will raise in a future version"
173
+ )
174
+ warn = None
175
+ if not pd .isna (na ) and not isinstance (na , bool ):
176
+ warn = FutureWarning
177
+ with tm .assert_produces_warning (warn , match = msg ):
178
+ result = values .str .contains ("a" , na = na , regex = regex )
170
179
expected = Series ([True , False , False , True , expected ], dtype = "boolean" )
171
180
tm .assert_series_equal (result , expected )
172
181
@@ -232,7 +241,12 @@ def test_contains_nan(any_string_dtype):
232
241
expected = Series ([True , True , True ], dtype = expected_dtype )
233
242
tm .assert_series_equal (result , expected )
234
243
235
- result = s .str .contains ("foo" , na = "foo" )
244
+ msg = (
245
+ "Allowing a non-bool 'na' in obj.str.contains is deprecated and "
246
+ "will raise in a future version"
247
+ )
248
+ with tm .assert_produces_warning (FutureWarning , match = msg ):
249
+ result = s .str .contains ("foo" , na = "foo" )
236
250
if any_string_dtype == "object" :
237
251
expected = Series (["foo" , "foo" , "foo" ], dtype = np .object_ )
238
252
elif any_string_dtype .na_value is np .nan :
@@ -254,6 +268,34 @@ def test_contains_nan(any_string_dtype):
254
268
# --------------------------------------------------------------------------------------
255
269
256
270
271
+ def test_startswith_endswith_validate_na (any_string_dtype ):
272
+ # GH#59615
273
+ ser = Series (
274
+ ["om" , np .nan , "foo_nom" , "nom" , "bar_foo" , np .nan , "foo" ],
275
+ dtype = any_string_dtype ,
276
+ )
277
+
278
+ dtype = ser .dtype
279
+ if (
280
+ isinstance (dtype , pd .StringDtype ) and dtype .storage == "python"
281
+ ) or dtype == np .dtype ("object" ):
282
+ msg = "Allowing a non-bool 'na' in obj.str.startswith is deprecated"
283
+ with tm .assert_produces_warning (FutureWarning , match = msg ):
284
+ ser .str .startswith ("kapow" , na = "baz" )
285
+ msg = "Allowing a non-bool 'na' in obj.str.endswith is deprecated"
286
+ with tm .assert_produces_warning (FutureWarning , match = msg ):
287
+ ser .str .endswith ("bar" , na = "baz" )
288
+ else :
289
+ # TODO(infer_string): don't surface pyarrow errors
290
+ import pyarrow as pa
291
+
292
+ msg = "Could not convert 'baz' with type str: tried to convert to boolean"
293
+ with pytest .raises (pa .lib .ArrowInvalid , match = msg ):
294
+ ser .str .startswith ("kapow" , na = "baz" )
295
+ with pytest .raises (pa .lib .ArrowInvalid , match = msg ):
296
+ ser .str .endswith ("kapow" , na = "baz" )
297
+
298
+
257
299
@pytest .mark .parametrize ("pat" , ["foo" , ("foo" , "baz" )])
258
300
@pytest .mark .parametrize ("dtype" , ["object" , "category" ])
259
301
@pytest .mark .parametrize ("null_value" , [None , np .nan , pd .NA ])
0 commit comments