1
1
from __future__ import annotations
2
2
3
3
import json
4
+ import logging
4
5
import re
5
6
import sys
6
7
from abc import ABC
23
24
from variantlib .models .variant import VariantProperty
24
25
from variantlib .plugins .loader import BasePluginLoader
25
26
from variantlib .plugins .loader import EntryPointPluginLoader
26
- from variantlib .plugins .loader import ManualPluginLoader
27
+ from variantlib .plugins .loader import ListPluginLoader
27
28
from variantlib .plugins .loader import PluginLoader
28
29
from variantlib .protocols import PluginType
29
30
from variantlib .protocols import VariantFeatureConfigType
@@ -113,26 +114,18 @@ def test_get_supported_configs(
113
114
}
114
115
115
116
116
- def test_manual_loading (mocked_plugin_apis : list [str ]):
117
- loader = ManualPluginLoader ()
118
- for plugin_api in mocked_plugin_apis :
119
- loader .load_plugin (plugin_api )
120
-
121
- assert list (loader .get_supported_configs ().keys ()) == [
122
- "test_namespace" ,
123
- "second_namespace" ,
124
- ]
125
-
126
-
127
117
def test_namespace_clash ():
128
- loader = ManualPluginLoader ()
129
- loader .load_plugin ("tests.mocked_plugins:MockedPluginA" )
130
- with pytest .raises (
131
- RuntimeError ,
132
- match = "Two plugins found using the same namespace test_namespace. Refusing to "
133
- "proceed." ,
118
+ with (
119
+ pytest .raises (
120
+ RuntimeError ,
121
+ match = "Two plugins found using the same namespace test_namespace. Refusing "
122
+ "to proceed." ,
123
+ ),
124
+ ListPluginLoader (
125
+ ["tests.mocked_plugins:MockedPluginA" , "tests.test_plugins:ClashingPlugin" ]
126
+ ),
134
127
):
135
- loader . load_plugin ( "tests.test_plugins:ClashingPlugin" )
128
+ pass
136
129
137
130
138
131
class IncorrectListTypePlugin (ExceptionPluginBase ):
@@ -144,16 +137,16 @@ class IncorrectListTypePlugin(ExceptionPluginBase):
144
137
145
138
@pytest .mark .parametrize ("method" , ["get_all_configs" , "get_supported_configs" ])
146
139
def test_get_configs_incorrect_list_type (method : str ):
147
- loader = ManualPluginLoader ()
148
- loader . load_plugin ( "tests.test_plugins:IncorrectListTypePlugin" )
149
-
150
- with pytest . raises (
151
- PluginError ,
152
- match = r".*"
153
- + re . escape (
154
- f"Provider exception_test, { method } () method returned incorrect type. "
155
- "Expected list[variantlib.protocols.VariantFeatureConfigType], "
156
- "got <class 'tuple'>"
140
+ with (
141
+ ListPluginLoader ([ "tests.test_plugins:IncorrectListTypePlugin" ]) as loader ,
142
+ pytest . raises (
143
+ PluginError ,
144
+ match = r".*"
145
+ + re . escape (
146
+ f"Provider exception_test, { method } () method returned incorrect type. "
147
+ "Expected list[variantlib.protocols.VariantFeatureConfigType], "
148
+ "got <class 'tuple'> "
149
+ ),
157
150
),
158
151
):
159
152
getattr (loader , method )()
@@ -164,13 +157,13 @@ class IncorrectListLengthPlugin(ExceptionPluginBase):
164
157
165
158
166
159
def test_get_all_configs_incorrect_list_length ():
167
- loader = ManualPluginLoader ()
168
- loader . load_plugin ( "tests.test_plugins:IncorrectListLengthPlugin" )
169
-
170
- with pytest . raises (
171
- ValueError ,
172
- match = r"Provider exception_test, get_all_configs\(\) method returned no valid "
173
- r"configs" ,
160
+ with (
161
+ ListPluginLoader ([ "tests.test_plugins:IncorrectListLengthPlugin" ]) as loader ,
162
+ pytest . raises (
163
+ ValueError ,
164
+ match = r"Provider exception_test, get_all_configs\(\) method returned "
165
+ r" no valid configs" ,
166
+ ) ,
174
167
):
175
168
loader .get_all_configs ()
176
169
@@ -181,38 +174,44 @@ class IncorrectListMemberTypePlugin(ExceptionPluginBase):
181
174
182
175
@pytest .mark .parametrize ("method" , ["get_all_configs" , "get_supported_configs" ])
183
176
def test_get_configs_incorrect_list_member_type (method : str ):
184
- loader = ManualPluginLoader ()
185
- loader .load_plugin ("tests.test_plugins:IncorrectListMemberTypePlugin" )
186
-
187
- with pytest .raises (
188
- PluginError ,
189
- match = r".*"
190
- + re .escape (
191
- f"Provider exception_test, { method } () method returned incorrect type. "
192
- "Expected list[variantlib.protocols.VariantFeatureConfigType], "
193
- "got list[typing.Union[variantlib.protocols.VariantFeatureConfigType, "
194
- )
195
- + r"(dict, int|int, dict)" ,
177
+ with (
178
+ ListPluginLoader (
179
+ ["tests.test_plugins:IncorrectListMemberTypePlugin" ]
180
+ ) as loader ,
181
+ pytest .raises (
182
+ PluginError ,
183
+ match = r".*"
184
+ + re .escape (
185
+ f"Provider exception_test, { method } () method returned incorrect type. "
186
+ "Expected list[variantlib.protocols.VariantFeatureConfigType], "
187
+ "got list[typing.Union[variantlib.protocols.VariantFeatureConfigType, "
188
+ )
189
+ + r"(dict, int|int, dict)" ,
190
+ ),
196
191
):
197
192
getattr (loader , method )()
198
193
199
194
200
- def test_namespace_missing_module ():
201
- with pytest .raises (
202
- PluginError ,
203
- match = r"Loading the plugin from 'tests.no_such_module:foo' failed: "
204
- r"No module named 'tests.no_such_module'" ,
205
- ):
206
- ManualPluginLoader ().load_plugin ("tests.no_such_module:foo" )
195
+ def test_namespace_missing_module (caplog : pytest .CapLogFixture ):
196
+ caplog .set_level (logging .DEBUG )
197
+ with ListPluginLoader (["tests.no_such_module:foo" ]):
198
+ pass
199
+ assert caplog .records [- 1 ].exc_info [0 ] == PluginError
200
+ assert (
201
+ "Loading the plugin from 'tests.no_such_module:foo' failed: "
202
+ "No module named 'tests.no_such_module'"
203
+ ) in str (caplog .records [- 1 ].exc_info [1 ])
207
204
208
205
209
- def test_namespace_incorrect_name ():
210
- with pytest .raises (
211
- PluginError ,
212
- match = r"Loading the plugin from 'tests.test_plugins:no_such_name' "
213
- r"failed: module 'tests.test_plugins' has no attribute 'no_such_name'" ,
214
- ):
215
- ManualPluginLoader ().load_plugin ("tests.test_plugins:no_such_name" )
206
+ def test_namespace_incorrect_name (caplog : pytest .CapLogFixture ):
207
+ caplog .set_level (logging .DEBUG )
208
+ with ListPluginLoader ([("tests.test_plugins:no_such_name" )]):
209
+ pass
210
+ assert caplog .records [- 1 ].exc_info [0 ] == PluginError
211
+ assert (
212
+ "Loading the plugin from 'tests.test_plugins:no_such_name' "
213
+ "failed: module 'tests.test_plugins' has no attribute 'no_such_name'"
214
+ ) in str (caplog .records [- 1 ].exc_info [1 ])
216
215
217
216
218
217
class IncompletePlugin :
@@ -222,13 +221,14 @@ def get_supported_configs(self) -> list[VariantFeatureConfigType]:
222
221
return []
223
222
224
223
225
- def test_namespace_incorrect_type ():
226
- with pytest .raises (
227
- PluginError ,
228
- match = r"'tests.test_plugins:RANDOM_STUFF' points at a value that "
229
- r"is not callable: 123" ,
230
- ):
231
- ManualPluginLoader ().load_plugin ("tests.test_plugins:RANDOM_STUFF" )
224
+ def test_namespace_incorrect_type (caplog : pytest .CapLogFixture ):
225
+ caplog .set_level (logging .DEBUG )
226
+ with ListPluginLoader (["tests.test_plugins:RANDOM_STUFF" ]):
227
+ pass
228
+ assert caplog .records [- 1 ].exc_info [0 ] == PluginError
229
+ assert (
230
+ "'tests.test_plugins:RANDOM_STUFF' points at a value that is not callable: 123"
231
+ ) in str (caplog .records [- 1 ].exc_info [1 ])
232
232
233
233
234
234
class RaisingInstantiationPlugin :
@@ -244,16 +244,15 @@ def get_supported_configs(self) -> list[VariantFeatureConfigType]:
244
244
return []
245
245
246
246
247
- def test_namespace_instantiation_raises ():
248
- with pytest .raises (
249
- PluginError ,
250
- match = r"Instantiating the plugin from "
251
- r"'tests.test_plugins:RaisingInstantiationPlugin' failed: "
252
- r"I failed to initialize" ,
253
- ):
254
- ManualPluginLoader ().load_plugin (
255
- "tests.test_plugins:RaisingInstantiationPlugin"
256
- )
247
+ def test_namespace_instantiation_raises (caplog : pytest .CapLogFixture ):
248
+ caplog .set_level (logging .DEBUG )
249
+ with ListPluginLoader (["tests.test_plugins:RaisingInstantiationPlugin" ]):
250
+ pass
251
+ assert (
252
+ "Instantiating the plugin from "
253
+ "'tests.test_plugins:RaisingInstantiationPlugin' failed: "
254
+ "I failed to initialize"
255
+ ) in str (caplog .records [- 1 ].exc_info [1 ])
257
256
258
257
259
258
class CrossTypeInstantiationPlugin :
@@ -270,15 +269,20 @@ def get_supported_configs(self) -> list[VariantFeatureConfigType]:
270
269
271
270
272
271
@pytest .mark .parametrize ("cls" , ["IncompletePlugin" , "CrossTypeInstantiationPlugin" ])
273
- def test_namespace_instantiation_returns_incorrect_type (cls : type ):
274
- with pytest .raises (
275
- PluginError ,
276
- match = rf"Instantiating the plugin from 'tests.test_plugins:{ cls } ' "
277
- r"returned an object that does not meet the PluginType prototype: "
278
- r"<tests.test_plugins.IncompletePlugin object at .*> "
279
- r"\(missing attributes: get_all_configs\)" ,
280
- ):
281
- ManualPluginLoader ().load_plugin (f"tests.test_plugins:{ cls } " )
272
+ def test_namespace_instantiation_returns_incorrect_type (
273
+ cls : type , caplog : pytest .CapLogFixture
274
+ ):
275
+ caplog .set_level (logging .DEBUG )
276
+ with ListPluginLoader ([f"tests.test_plugins:{ cls } " ]):
277
+ pass
278
+ assert (
279
+ f"Instantiating the plugin from 'tests.test_plugins:{ cls } ' "
280
+ "returned an object that does not meet the PluginType prototype: "
281
+ "<tests.test_plugins.IncompletePlugin object at "
282
+ ) in str (caplog .records [- 1 ].exc_info [1 ])
283
+ assert ("(missing attributes: get_all_configs)" ) in str (
284
+ caplog .records [- 1 ].exc_info [1 ]
285
+ )
282
286
283
287
284
288
def test_get_build_setup (
@@ -327,29 +331,19 @@ def test_namespaces(
327
331
]
328
332
329
333
330
- def test_load_plugin ():
331
- loader = ManualPluginLoader ()
332
- loader .load_plugin ("tests.mocked_plugins:IndirectPath.MoreIndirection.plugin_a" )
333
- assert loader .namespaces == ["test_namespace" ]
334
-
335
- loader .load_plugin ("tests.mocked_plugins:IndirectPath.MoreIndirection.plugin_b" )
336
- assert loader .namespaces == ["test_namespace" , "second_namespace" ]
337
-
338
-
339
- def test_manual_plugin_loader_as_context_manager ():
340
- with ManualPluginLoader () as loader :
341
- loader .load_plugin ("tests.mocked_plugins:IndirectPath.MoreIndirection.plugin_a" )
342
- assert loader .namespaces == ["test_namespace" ]
343
-
344
- loader .load_plugin ("tests.mocked_plugins:IndirectPath.MoreIndirection.plugin_b" )
334
+ def test_non_class_attrs ():
335
+ with ListPluginLoader (
336
+ [
337
+ "tests.mocked_plugins:IndirectPath.MoreIndirection.plugin_a" ,
338
+ "tests.mocked_plugins:IndirectPath.MoreIndirection.plugin_b" ,
339
+ ]
340
+ ) as loader :
345
341
assert loader .namespaces == ["test_namespace" , "second_namespace" ]
346
342
347
- assert not loader .namespaces
348
-
349
343
350
344
def test_load_plugin_invalid_arg ():
351
- with pytest .raises (ValidationError ):
352
- ManualPluginLoader (). load_plugin ( "tests.mocked_plugins" )
345
+ with pytest .raises (ValidationError ), ListPluginLoader ([ "tests.mocked_plugins" ]) :
346
+ pass
353
347
354
348
355
349
@pytest .mark .parametrize (
0 commit comments