22
22
23
23
24
24
__all__ = (
25
- 'StringProcessAdapter' , 'GlobalsItemDeletorMetaCls' , 'InheritedTestMethodsOverrideWrapperInstanceDecorator' ,
26
- 'InheritedTestMethodsOverrideWrapperMetaClsAutoMixin' ,
25
+ 'StringProcessAdapter' , 'GlobalsItemDeletorMetaCls' , 'InheritedTestMethodsOverrideWrapperMetaClsAutoMixin' ,
27
26
'with_rw_repo' , 'with_rw_and_rw_remote_repo' , 'TestBase' , 'TestCase' , 'needs_module_or_skip'
28
27
)
29
28
@@ -239,44 +238,7 @@ def __new__(metacls, name, bases, clsdict):
239
238
#END skip case that people import our base without actually using it
240
239
#END handle deletion
241
240
return new_type
242
-
243
-
244
- class InheritedTestMethodsOverrideWrapperInstanceDecorator (object ):
245
- """Utility to wrap all inherited methods into a given decorator and set up new
246
- overridden methods on our actual type. This allows to adjust tests which are inherited
247
- by our parent type, automatically. The decorator set in a derived type should
248
- do what it has to do, possibly skipping the test if some prerequesites are not met.
249
-
250
- To use it, instatiate it and use it as a wrapper for the __new__ function of your metacls, as in
251
-
252
- __new__ = @InheritedTestMethodsOverrideWrapperInstanceDecorator(mydecorator)(MyMetaclsBase.__new__)"""
253
241
254
-
255
- def __init__ (self , decorator ):
256
- self .decorator = decorator
257
-
258
- def _patch_methods_recursive (self , bases , clsdict ):
259
- """depth-first patching of methods"""
260
- for base in bases :
261
- self ._patch_methods_recursive (base .__bases__ , clsdict )
262
- for name , item in base .__dict__ .iteritems ():
263
- if not name .startswith ('test_' ):
264
- continue
265
- #END skip non-tests
266
- clsdict [name ] = self .decorator (item )
267
- #END for each item
268
- #END for each base
269
-
270
- def __call__ (self , func ):
271
- def wrapper (metacls , name , bases , clsdict ):
272
- self ._patch_methods_recursive (bases , clsdict )
273
- return func (metacls , name , bases , clsdict )
274
- #END wrapper
275
- assert func .__name__ == '__new__' , "Can only wrap __new__ function of metaclasses"
276
- wrapper .__name__ = func .__name__
277
- return wrapper
278
-
279
-
280
242
281
243
class InheritedTestMethodsOverrideWrapperMetaClsAutoMixin (object ):
282
244
"""Automatically picks up the actual metaclass of the the type to be created,
@@ -299,11 +261,25 @@ def _find_metacls(metacls, bases):
299
261
return metacls ._find_metacls (base .__bases__ )
300
262
#END for each base
301
263
raise AssertionError ("base class had not metaclass attached" )
302
-
264
+
265
+ @classmethod
266
+ def _patch_methods_recursive (metacls , bases , clsdict ):
267
+ """depth-first patching of methods"""
268
+ for base in bases :
269
+ metacls ._patch_methods_recursive (base .__bases__ , clsdict )
270
+ for name , item in base .__dict__ .iteritems ():
271
+ if not name .startswith ('test_' ):
272
+ continue
273
+ #END skip non-tests
274
+ clsdict [name ] = metacls .decorator [0 ](item )
275
+ #END for each item
276
+ #END for each base
277
+
303
278
def __new__ (metacls , name , bases , clsdict ):
304
279
assert metacls .decorator , "'decorator' member needs to be set in subclass"
305
280
base_metacls = metacls ._find_metacls (bases )
306
- return InheritedTestMethodsOverrideWrapperInstanceDecorator (metacls .decorator [0 ])(base_metacls .__new__ )(base_metacls , name , bases , clsdict )
281
+ metacls ._patch_methods_recursive (bases , clsdict )
282
+ return base_metacls .__new__ (base_metacls , name , bases , clsdict )
307
283
308
284
#} END meta classes
309
285
0 commit comments