2
2
import pandas ._testing as tm
3
3
from pandas .core .accessor import accessor_entry_point_loader
4
4
5
- # TODO: test for pkg names
6
-
7
5
PANDAS_ENTRY_POINT_GROUP : str = "pandas.accessor"
8
6
9
7
10
- def test_no_accessors (monkeypatch ):
11
- # GH29076
12
-
13
- # Mock entry_points
14
- def mock_entry_points (* , group ):
15
- return []
8
+ def create_mock_entry_points (entry_points ):
9
+ """
10
+ Auxiliary function to create mock entry points for testing accessor loading.
16
11
17
- # Patch entry_points in the correct module
18
- monkeypatch .setattr ("pandas.core.accessor.entry_points" , mock_entry_points )
12
+ Parameters:
13
+ -----------
14
+ entry_points : list of tuple
15
+ List of (name, accessor_class, dist_name) where:
16
+ - name: str, the name of the accessor
17
+ - accessor_class: class, the accessor class to be returned by load()
18
+ - dist_name: str, the name of the distribution (package)
19
19
20
- accessor_entry_point_loader ()
20
+ Returns:
21
+ --------
22
+ function
23
+ A mock_entry_points function that returns the mocked entry points.
24
+ """
21
25
26
+ class MockDistribution :
27
+ def __init__ (self , name ):
28
+ self .name = name
22
29
23
- def test_load_dataframe_accessors (monkeypatch ):
24
- # GH29076
25
- # Mocked EntryPoint to simulate a plugin
26
30
class MockEntryPoint :
27
- name = "test_accessor"
31
+ def __init__ (self , name , accessor_class , dist_name ):
32
+ self .name = name
33
+ self ._accessor_class = accessor_class
34
+ self .dist = MockDistribution (dist_name )
28
35
29
36
def load (self ):
30
- class TestAccessor :
31
- def __init__ (self , df ):
32
- self ._df = df
37
+ return self ._accessor_class
33
38
34
- def test_method (self ):
35
- return "success"
36
-
37
- return TestAccessor
39
+ # Create list of MockEntryPoint instances
40
+ mock_eps = [
41
+ MockEntryPoint (name , accessor_class , dist_name )
42
+ for name , accessor_class , dist_name in entry_points
43
+ ]
38
44
39
- # Mock entry_points
40
45
def mock_entry_points (* , group ):
41
46
if group == PANDAS_ENTRY_POINT_GROUP :
42
- return [ MockEntryPoint ()]
47
+ return mock_eps
43
48
return []
44
49
45
- # Patch entry_points in the correct module
50
+ return mock_entry_points
51
+
52
+
53
+ def test_no_accessors (monkeypatch ):
54
+ # No entry points
55
+ mock_entry_points = create_mock_entry_points ([])
56
+ monkeypatch .setattr ("pandas.core.accessor.entry_points" , mock_entry_points )
57
+
58
+ accessor_entry_point_loader ()
59
+
60
+
61
+ def test_load_dataframe_accessors (monkeypatch ):
62
+ class TestAccessor :
63
+ def __init__ (self , df ):
64
+ self ._df = df
65
+
66
+ def test_method (self ):
67
+ return "success"
68
+
69
+ mock_entry_points = create_mock_entry_points (
70
+ [("test_accessor" , TestAccessor , "TestPackage" )]
71
+ )
46
72
monkeypatch .setattr ("pandas.core.accessor.entry_points" , mock_entry_points )
47
73
48
74
accessor_entry_point_loader ()
@@ -54,40 +80,26 @@ def mock_entry_points(*, group):
54
80
55
81
56
82
def test_duplicate_accessor_names (monkeypatch ):
57
- # GH29076
58
- # Create plugin
59
- class MockEntryPoint1 :
60
- name = "duplicate_accessor"
83
+ class Accessor1 :
84
+ def __init__ (self , df ):
85
+ self ._df = df
61
86
62
- def load (self ):
63
- class Accessor1 :
64
- def __init__ (self , df ):
65
- self ._df = df
87
+ def which (self ):
88
+ return "Accessor1"
66
89
67
- def which (self ):
68
- return "Accessor1"
90
+ class Accessor2 :
91
+ def __init__ (self , df ):
92
+ self ._df = df
69
93
70
- return Accessor1
71
-
72
- # Create plugin
73
- class MockEntryPoint2 :
74
- name = "duplicate_accessor"
75
-
76
- def load (self ):
77
- class Accessor2 :
78
- def __init__ (self , df ):
79
- self ._df = df
80
-
81
- def which (self ):
82
- return "Accessor2"
83
-
84
- return Accessor2
85
-
86
- def mock_entry_points (* , group ):
87
- if group == PANDAS_ENTRY_POINT_GROUP :
88
- return [MockEntryPoint1 (), MockEntryPoint2 ()]
89
- return []
94
+ def which (self ):
95
+ return "Accessor2"
90
96
97
+ mock_entry_points = create_mock_entry_points (
98
+ [
99
+ ("duplicate_accessor" , Accessor1 , "Package1" ),
100
+ ("duplicate_accessor" , Accessor2 , "Package2" ),
101
+ ]
102
+ )
91
103
monkeypatch .setattr ("pandas.core.accessor.entry_points" , mock_entry_points )
92
104
93
105
# Check that the UserWarning is raised
@@ -99,44 +111,27 @@ def mock_entry_points(*, group):
99
111
100
112
df = pd .DataFrame ({"x" : [1 , 2 , 3 ]})
101
113
assert hasattr (df , "duplicate_accessor" )
102
- assert df .duplicate_accessor .which () in { "Accessor1" , " Accessor2"}
114
+ assert df .duplicate_accessor .which () == " Accessor2" # Last registered accessor
103
115
104
116
105
117
def test_unique_accessor_names (monkeypatch ):
106
- # GH29076
107
- # Create plugin
108
- class MockEntryPoint1 :
109
- name = "accessor1"
110
-
111
- def load (self ):
112
- class Accessor1 :
113
- def __init__ (self , df ):
114
- self ._df = df
115
-
116
- def which (self ):
117
- return "Accessor1"
118
+ class Accessor1 :
119
+ def __init__ (self , df ):
120
+ self ._df = df
118
121
119
- return Accessor1
122
+ def which (self ):
123
+ return "Accessor1"
120
124
121
- # Create plugin
122
- class MockEntryPoint2 :
123
- name = "accessor2"
124
-
125
- def load (self ):
126
- class Accessor2 :
127
- def __init__ (self , df ):
128
- self ._df = df
125
+ class Accessor2 :
126
+ def __init__ (self , df ):
127
+ self ._df = df
129
128
130
- def which (self ):
131
- return "Accessor2"
132
-
133
- return Accessor2
134
-
135
- def mock_entry_points (* , group ):
136
- if group == PANDAS_ENTRY_POINT_GROUP :
137
- return [MockEntryPoint1 (), MockEntryPoint2 ()]
138
- return []
129
+ def which (self ):
130
+ return "Accessor2"
139
131
132
+ mock_entry_points = create_mock_entry_points (
133
+ [("accessor1" , Accessor1 , "Package1" ), ("accessor2" , Accessor2 , "Package2" )]
134
+ )
140
135
monkeypatch .setattr ("pandas.core.accessor.entry_points" , mock_entry_points )
141
136
142
137
# Check that no UserWarning is raised
@@ -146,59 +141,40 @@ def mock_entry_points(*, group):
146
141
df = pd .DataFrame ({"x" : [1 , 2 , 3 ]})
147
142
assert hasattr (df , "accessor1" ), "Accessor1 not registered"
148
143
assert hasattr (df , "accessor2" ), "Accessor2 not registered"
144
+
149
145
assert df .accessor1 .which () == "Accessor1" , "Accessor1 method incorrect"
150
146
assert df .accessor2 .which () == "Accessor2" , "Accessor2 method incorrect"
151
147
152
148
153
149
def test_duplicate_and_unique_accessor_names (monkeypatch ):
154
- # GH29076
155
- # Create plugin
156
- class MockEntryPoint1 :
157
- name = "duplicate_accessor"
150
+ class Accessor1 :
151
+ def __init__ (self , df ):
152
+ self ._df = df
158
153
159
- def load (self ):
160
- class Accessor1 :
161
- def __init__ (self , df ):
162
- self ._df = df
154
+ def which (self ):
155
+ return "Accessor1"
163
156
164
- def which (self ):
165
- return "Accessor1"
157
+ class Accessor2 :
158
+ def __init__ (self , df ):
159
+ self ._df = df
166
160
167
- return Accessor1
161
+ def which (self ):
162
+ return "Accessor2"
168
163
169
- # Create plugin
170
- class MockEntryPoint2 :
171
- name = "duplicate_accessor"
164
+ class Accessor3 :
165
+ def __init__ ( self , df ) :
166
+ self . _df = df
172
167
173
- def load (self ):
174
- class Accessor2 :
175
- def __init__ (self , df ):
176
- self ._df = df
177
-
178
- def which (self ):
179
- return "Accessor2"
180
-
181
- return Accessor2
182
-
183
- # Create plugin
184
- class MockEntryPoint3 :
185
- name = "unique_accessor"
186
-
187
- def load (self ):
188
- class Accessor3 :
189
- def __init__ (self , df ):
190
- self ._df = df
191
-
192
- def which (self ):
193
- return "Accessor3"
194
-
195
- return Accessor3
196
-
197
- def mock_entry_points (* , group ):
198
- if group == PANDAS_ENTRY_POINT_GROUP :
199
- return [MockEntryPoint1 (), MockEntryPoint2 (), MockEntryPoint3 ()]
200
- return []
168
+ def which (self ):
169
+ return "Accessor3"
201
170
171
+ mock_entry_points = create_mock_entry_points (
172
+ [
173
+ ("duplicate_accessor" , Accessor1 , "Package1" ),
174
+ ("duplicate_accessor" , Accessor2 , "Package2" ),
175
+ ("unique_accessor" , Accessor3 , "Package3" ),
176
+ ]
177
+ )
202
178
monkeypatch .setattr ("pandas.core.accessor.entry_points" , mock_entry_points )
203
179
204
180
# Capture warnings
@@ -222,10 +198,9 @@ def mock_entry_points(*, group):
222
198
223
199
df = pd .DataFrame ({"x" : [1 , 2 , 3 ]})
224
200
assert hasattr (df , "duplicate_accessor" ), "duplicate_accessor not registered"
225
-
226
201
assert hasattr (df , "unique_accessor" ), "unique_accessor not registered"
227
202
228
- assert df .duplicate_accessor .which () in { "Accessor1" , " Accessor2"} , (
229
- "duplicate_accessor method incorrect "
203
+ assert df .duplicate_accessor .which () == " Accessor2" , (
204
+ "duplicate_accessor should use Accessor2 "
230
205
)
231
206
assert df .unique_accessor .which () == "Accessor3" , "unique_accessor method incorrect"
0 commit comments