在Python运行之前覆盖默认的type()元类 [英] Overriding the default type() metaclass before Python runs

查看:144
本文介绍了在Python运行之前覆盖默认的type()元类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里有龙.您已收到警告.

我正在考虑创建一个新的库,以尝试帮助编写更好的测试套件.
为此,功能之一是一种功能,该功能可验证正在使用的不是测试运行程序和

I'm thinking about creating a new library that will attempt to help write a better test suite.
In order to do that one of the features is a feature that verifies that any object that is being used which isn't the test runner and the system under test has a test double (a mock object, a stub, a fake or a dummy). If the tester wants the live object and thus reduce test isolation it has to specify so explicitly.

我看到的唯一方法是重写内置的type()函数,该函数是默认的元类.
新的默认元类将检查测试双重注册表字典,以查看它是否已被测试双重替换或是否指定了活动对象.

The only way I see to do this is to override the builtin type() function which is the default metaclass.
The new default metaclass will check the test double registry dictionary to see if it has been replaced with a test double or if the live object was specified.

当然,这不可能通过Python本身实现:

Of course this is not possible through Python itself:

>>> TypeError: can't set attributes of built-in/extension type 'type'

在测试套件(可能还有Python)运行之前,是否有办法干预Python的元类查找?
也许使用字节码操作?但是到底如何呢?

Is there a way to intervene with Python's metaclass lookup before the test suite will run (and probably Python)?
Maybe using bytecode manipulation? But how exactly?

推荐答案

以下内容不建议使用,您会遇到很多问题和实现您的想法的极端情况,但是在Python 3.1及更高版本上,您可以加入<通过覆盖__build_class__内置钩子来创建em> custom 类的过程:

The following is not advisable, and you'll hit plenty of problems and cornercases implementing your idea, but on Python 3.1 and onwards, you can hook into the custom class creation process by overriding the __build_class__ built-in hook:

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

这仅限于 个自定义类,但确实为您提供了强大的功能.

This is limited to custom classes only, but does give you an all-powerful hook.

对于3.1之前的Python版本,您可以忘记钩子类的创建. C build_class函数直接使用如果未定义元类,则为C型type()值,它永远不会从__builtin__模块中查找它,因此您无法覆盖它.

For Python versions before 3.1, you can forget hooking class creation. The C build_class function directly uses the C-type type() value if no metaclass has been defined, it never looks it up from the __builtin__ module, so you cannot override it.

这篇关于在Python运行之前覆盖默认的type()元类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆