Skip to content

Commit 001c05a

Browse files
committed
Compliance with Code Checks && fixed tests
1 parent 03885c5 commit 001c05a

File tree

2 files changed

+115
-135
lines changed

2 files changed

+115
-135
lines changed

pandas/core/accessor.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ def accessor_entry_point_loader() -> None:
436436
437437
Examples
438438
--------
439-
>>> df.myplugin.do_something() # Assuming such accessor was registered
439+
df.myplugin.do_something() # Assuming such accessor was registered
440440
"""
441441

442442
ENTRY_POINT_GROUP: str = "pandas.accessor"
@@ -445,15 +445,20 @@ def accessor_entry_point_loader() -> None:
445445
accessor_package_dict: dict[str, str] = {}
446446

447447
for new_accessor in accessors:
448-
try:
449-
new_pkg_name: str = new_accessor.dist.name
450-
except AttributeError:
448+
if new_accessor.dist is not None:
449+
# Try to get new_accessor.dist.name,
450+
# if that's not possible: new_pkg_name = 'Unknown'
451+
new_pkg_name: str = getattr(new_accessor.dist, "name", "Unknown")
452+
else:
451453
new_pkg_name: str = "Unknown"
452454

453455
# Verifies duplicated accessor names
454456
if new_accessor.name in accessor_package_dict:
455457
loaded_pkg_name: str = accessor_package_dict.get(new_accessor.name)
456458

459+
if loaded_pkg_name is None:
460+
loaded_pkg_name = "Unknown"
461+
457462
warnings.warn(
458463
"Warning: you have two accessors with the same name:"
459464
f" '{new_accessor.name}' has already been registered"

pandas/tests/test_plugins_entrypoint_loader.py

Lines changed: 106 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,73 @@
22
import pandas._testing as tm
33
from pandas.core.accessor import accessor_entry_point_loader
44

5-
# TODO: test for pkg names
6-
75
PANDAS_ENTRY_POINT_GROUP: str = "pandas.accessor"
86

97

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.
1611
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)
1919
20-
accessor_entry_point_loader()
20+
Returns:
21+
--------
22+
function
23+
A mock_entry_points function that returns the mocked entry points.
24+
"""
2125

26+
class MockDistribution:
27+
def __init__(self, name):
28+
self.name = name
2229

23-
def test_load_dataframe_accessors(monkeypatch):
24-
# GH29076
25-
# Mocked EntryPoint to simulate a plugin
2630
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)
2835

2936
def load(self):
30-
class TestAccessor:
31-
def __init__(self, df):
32-
self._df = df
37+
return self._accessor_class
3338

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+
]
3844

39-
# Mock entry_points
4045
def mock_entry_points(*, group):
4146
if group == PANDAS_ENTRY_POINT_GROUP:
42-
return [MockEntryPoint()]
47+
return mock_eps
4348
return []
4449

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+
)
4672
monkeypatch.setattr("pandas.core.accessor.entry_points", mock_entry_points)
4773

4874
accessor_entry_point_loader()
@@ -54,40 +80,26 @@ def mock_entry_points(*, group):
5480

5581

5682
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
6186

62-
def load(self):
63-
class Accessor1:
64-
def __init__(self, df):
65-
self._df = df
87+
def which(self):
88+
return "Accessor1"
6689

67-
def which(self):
68-
return "Accessor1"
90+
class Accessor2:
91+
def __init__(self, df):
92+
self._df = df
6993

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"
9096

97+
mock_entry_points = create_mock_entry_points(
98+
[
99+
("duplicate_accessor", Accessor1, "Package1"),
100+
("duplicate_accessor", Accessor2, "Package2"),
101+
]
102+
)
91103
monkeypatch.setattr("pandas.core.accessor.entry_points", mock_entry_points)
92104

93105
# Check that the UserWarning is raised
@@ -99,44 +111,27 @@ def mock_entry_points(*, group):
99111

100112
df = pd.DataFrame({"x": [1, 2, 3]})
101113
assert hasattr(df, "duplicate_accessor")
102-
assert df.duplicate_accessor.which() in {"Accessor1", "Accessor2"}
114+
assert df.duplicate_accessor.which() == "Accessor2" # Last registered accessor
103115

104116

105117
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
118121

119-
return Accessor1
122+
def which(self):
123+
return "Accessor1"
120124

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
129128

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"
139131

132+
mock_entry_points = create_mock_entry_points(
133+
[("accessor1", Accessor1, "Package1"), ("accessor2", Accessor2, "Package2")]
134+
)
140135
monkeypatch.setattr("pandas.core.accessor.entry_points", mock_entry_points)
141136

142137
# Check that no UserWarning is raised
@@ -146,59 +141,40 @@ def mock_entry_points(*, group):
146141
df = pd.DataFrame({"x": [1, 2, 3]})
147142
assert hasattr(df, "accessor1"), "Accessor1 not registered"
148143
assert hasattr(df, "accessor2"), "Accessor2 not registered"
144+
149145
assert df.accessor1.which() == "Accessor1", "Accessor1 method incorrect"
150146
assert df.accessor2.which() == "Accessor2", "Accessor2 method incorrect"
151147

152148

153149
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
158153

159-
def load(self):
160-
class Accessor1:
161-
def __init__(self, df):
162-
self._df = df
154+
def which(self):
155+
return "Accessor1"
163156

164-
def which(self):
165-
return "Accessor1"
157+
class Accessor2:
158+
def __init__(self, df):
159+
self._df = df
166160

167-
return Accessor1
161+
def which(self):
162+
return "Accessor2"
168163

169-
# Create plugin
170-
class MockEntryPoint2:
171-
name = "duplicate_accessor"
164+
class Accessor3:
165+
def __init__(self, df):
166+
self._df = df
172167

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"
201170

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+
)
202178
monkeypatch.setattr("pandas.core.accessor.entry_points", mock_entry_points)
203179

204180
# Capture warnings
@@ -222,10 +198,9 @@ def mock_entry_points(*, group):
222198

223199
df = pd.DataFrame({"x": [1, 2, 3]})
224200
assert hasattr(df, "duplicate_accessor"), "duplicate_accessor not registered"
225-
226201
assert hasattr(df, "unique_accessor"), "unique_accessor not registered"
227202

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"
230205
)
231206
assert df.unique_accessor.which() == "Accessor3", "unique_accessor method incorrect"

0 commit comments

Comments
 (0)