the*_*row 9 python metaclass bytecode-manipulation
这里是龙.你被警告过了.
我正在考虑创建一个新的库,试图帮助编写一个更好的测试套件.
为了做到这一点,其中一个功能是一个功能,它验证正在使用的任何不是测试运行器和被测系统的对象都有一个测试对象(模拟对象,存根,伪造或虚拟对象) ).如果测试人员想要活动对象并因此减少测试隔离,则必须明确指定.
我看到这样做的唯一方法是覆盖内置type()函数,它是默认的元类.
新的默认元类将检查测试双重注册表字典,以查看它是否已被测试双重替换或是否指定了活动对象.
当然,这不可能通过Python本身实现:
>>> TypeError: can't set attributes of built-in/extension type 'type'
Run Code Online (Sandbox Code Playgroud)
有没有办法在测试套件运行之前干预Python的元类查找(可能还有Python)?
也许使用字节码操作?但到底怎么样?
以下是不可取的,你会遇到很多问题和角落实现你的想法,但是在Python 3.1及以后,你可以通过覆盖内置的钩子来挂钩自定义类创建过程__build_class__:
import builtins
_orig_build_class = builtins.__build_class__
class SomeMockingMeta(type):
# whatever
def my_build_class(func, name, *bases, **kwargs):
if not any(isinstance(b, type) for b in bases):
# a 'regular' class, not a metaclass
if 'metaclass' in kwargs:
if not isinstance(kwargs['metaclass'], type):
# the metaclass is a callable, but not a class
orig_meta = kwargs.pop('metaclass')
class HookedMeta(SomeMockingMeta):
def __new__(meta, name, bases, attrs):
return orig_meta(name, bases, attrs)
kwargs['metaclass'] = HookedMeta
else:
# There already is a metaclass, insert ours and hope for the best
class SubclassedMeta(SomeMockingMeta, kwargs['metaclass']):
pass
kwargs['metaclass'] = SubclassedMeta
else:
kwargs['metaclass'] = SomeMockingMeta
return _orig_build_class(func, name, *bases, **kwargs)
builtins.__build_class__ = my_build_class
Run Code Online (Sandbox Code Playgroud)
这仅限于自定义类只,但不会给你一个全能的钩.
对于3.1之前的Python版本,您可以忘记挂钩类创建.如果没有定义元类,C build_class函数直接使用C类型type()值,它从不从__builtin__模块中查找,因此您无法覆盖它.