@@ -26,6 +26,98 @@ def assert_series_or_index_equal(left, right):
2626 assert_index_equal (left , right )
2727
2828
29+ _any_string_method = [
30+ ('cat' , (), {'sep' : ',' }), # noqa: E241
31+ ('cat' , (Series (list ('zyx' )),), {'sep' : ',' , # noqa: E241
32+ 'join' : 'left' }),
33+ ('center' , (10 ,), {}), # noqa: E241
34+ ('contains' , ('a' ,), {}), # noqa: E241
35+ ('count' , ('a' ,), {}), # noqa: E241
36+ ('decode' , ('UTF-8' ,), {}), # noqa: E241
37+ ('encode' , ('UTF-8' ,), {}), # noqa: E241
38+ ('endswith' , ('a' ,), {}), # noqa: E241
39+ ('extract' , ('([a-z]*)' ,), {'expand' : False }), # noqa: E241
40+ ('extract' , ('([a-z]*)' ,), {'expand' : True }), # noqa: E241
41+ ('extractall' , ('([a-z]*)' ,), {}), # noqa: E241
42+ ('find' , ('a' ,), {}), # noqa: E241
43+ ('findall' , ('a' ,), {}), # noqa: E241
44+ ('get' , (0 ,), {}), # noqa: E241
45+ # because "index" (and "rindex") fail intentionally
46+ # if the string is not found, search only for empty string
47+ ('index' , ('' ,), {}), # noqa: E241
48+ ('join' , (',' ,), {}), # noqa: E241
49+ ('ljust' , (10 ,), {}), # noqa: E241
50+ ('match' , ('a' ,), {}), # noqa: E241
51+ ('normalize' , ('NFC' ,), {}), # noqa: E241
52+ ('pad' , (10 ,), {}), # noqa: E241
53+ ('partition' , (' ' ,), {'expand' : False }), # noqa: E241
54+ ('partition' , (' ' ,), {'expand' : True }), # noqa: E241
55+ ('repeat' , (3 ,), {}), # noqa: E241
56+ ('replace' , ('a' , 'z' ,), {}), # noqa: E241
57+ ('rfind' , ('a' ,), {}), # noqa: E241
58+ ('rindex' , ('' ,), {}), # noqa: E241
59+ ('rjust' , (10 ,), {}), # noqa: E241
60+ ('rpartition' , (' ' ,), {'expand' : False }), # noqa: E241
61+ ('rpartition' , (' ' ,), {'expand' : True }), # noqa: E241
62+ ('slice' , (0 , 1 ,), {}), # noqa: E241
63+ ('slice_replace' , (0 , 1 , 'z' ,), {}), # noqa: E241
64+ ('split' , (' ' ,), {'expand' : False }), # noqa: E241
65+ ('split' , (' ' ,), {'expand' : True }), # noqa: E241
66+ ('startswith' , ('a' ,), {}), # noqa: E241
67+ # translating unicode points of "a" to "d"
68+ ('translate' , ({97 : 100 },), {}), # noqa: E241
69+ ('wrap' , (2 ,), {}), # noqa: E241
70+ ('zfill' , (10 ,), {}) # noqa: E241
71+ ] + list (zip ([
72+ # methods without positional arguments: zip with empty tuple and empty dict
73+ 'capitalize' , 'cat' , 'get_dummies' ,
74+ 'isalnum' , 'isalpha' , 'isdecimal' ,
75+ 'isdigit' , 'islower' , 'isnumeric' ,
76+ 'isspace' , 'istitle' , 'isupper' ,
77+ 'len' , 'lower' , 'lstrip' , 'partition' ,
78+ 'rpartition' , 'rsplit' , 'rstrip' ,
79+ 'slice' , 'slice_replace' , 'split' ,
80+ 'strip' , 'swapcase' , 'title' , 'upper'
81+ ], [()] * 100 , [{}] * 100 ))
82+ ids , _ , _ = zip (* _any_string_method ) # use method name as fixture-id
83+
84+
85+ # test that the above list captures all methods of StringMethods
86+ missing_methods = {f for f in dir (strings .StringMethods )
87+ if not f .startswith ('_' )} - set (ids )
88+ assert not missing_methods
89+
90+
91+ @pytest .fixture (params = _any_string_method , ids = ids )
92+ def any_string_method (request ):
93+ """
94+ Fixture for all public methods of `StringMethods`
95+
96+ This fixture returns a tuple of the method name and sample arguments
97+ necessary to call the method.
98+
99+ Returns
100+ -------
101+ method_name : str
102+ The name of the method in `StringMethods`
103+ args : tuple
104+ Sample values for the positional arguments
105+ kwargs : dict
106+ Sample values for the keyword arguments
107+
108+ Examples
109+ --------
110+ >>> def test_something(any_string_method):
111+ ... s = pd.Series(['a', 'b', np.nan, 'd'])
112+ ...
113+ ... method_name, args, kwargs = any_string_method
114+ ... method = getattr(s.str, method_name)
115+ ... # will not raise
116+ ... method(*args, **kwargs)
117+ """
118+ return request .param
119+
120+
29121class TestStringMethods (object ):
30122
31123 def test_api (self ):
@@ -40,6 +132,26 @@ def test_api(self):
40132 invalid .str
41133 assert not hasattr (invalid , 'str' )
42134
135+ def test_api_for_categorical (self , any_string_method ):
136+ # https://github.com/pandas-dev/pandas/issues/10661
137+ s = Series (list ('aabb' ))
138+ s = s + " " + s
139+ c = s .astype ('category' )
140+ assert isinstance (c .str , strings .StringMethods )
141+
142+ method_name , args , kwargs = any_string_method
143+
144+ result = getattr (c .str , method_name )(* args , ** kwargs )
145+ expected = getattr (s .str , method_name )(* args , ** kwargs )
146+
147+ if isinstance (result , DataFrame ):
148+ tm .assert_frame_equal (result , expected )
149+ elif isinstance (result , Series ):
150+ tm .assert_series_equal (result , expected )
151+ else :
152+ # str.cat(others=None) returns string, for example
153+ assert result == expected
154+
43155 def test_iter (self ):
44156 # GH3638
45157 strs = 'google' , 'wikimedia' , 'wikipedia' , 'wikitravel'
0 commit comments