【问题标题】:Metaclass error when extending scipy.stats.rv_continuous mocked for Read the Docs扩展 scipy.stats.rv_continuous 时的元类错误为 Read the Docs 嘲笑
【发布时间】:2014-12-05 21:44:59
【问题描述】:

在我的 Python 项目中,我像这样扩展 scipy.stats.rv_continuous

class GenlogisticGen(LmomDistrMixin, scipy.stats.rv_continuous):
    ...

我正在尝试在 Read the Docs 上构建文档,但遇到构建错误:

class GenlogisticGen(LmomDistrMixin, scipy.stats.rv_continuous):
TypeError: metaclass conflict: the metaclass of a derived class must
be a (non-strict) subclass of the metaclasses of all its bases

请注意,我根据 Read the Docs FAQ 模拟了 scipy.stats 模块。

我猜想通过模拟基类会出现问题。但是什么?

【问题讨论】:

    标签: python scipy mocking python-sphinx metaclass


    【解决方案1】:

    我今天遇到了同样的问题,但是是 Qt 相关的课程。问题是 ReadTheDocs 建议的 Mock 类具有与预期不同的元类。这是问题的描述和解决方案,您想要的是从object继承的基类:

    # =============================================================================
    # Part 1. Set up the mock (you would put this in conf.py for Sphinx/autodoc).
    # =============================================================================
    
    import os
    import sys
    from unittest.mock import MagicMock
    
    
    class Mock(MagicMock):
        """
        Mock class that gives whatever attribute it's asked for, as per
        https://docs.readthedocs.io/en/latest/faq.html. Intended to be used when
        you can't genuinely install/import a module because ReadTheDocs (RTD)
        doesn't allow the installation of modules with C (rather than pure Python)
        code.
        """
        @classmethod
        def __getattr__(cls, name: str):
            return MagicMock()
    
    
    class SimpleClass(object):
        """
        Dummy base class to replace a :class:`Mock` version; see
        ``FIX_THE_PROBLEM`` below.
        """
        pass
    
    
    MOCK_MODULES = [
        # Things that ReadTheDocs won't install, but we want:
        'PyQt5',
        'PyQt5.QtCore',
        'PyQt5.QtGui',
        'PyQt5.QtNetwork',
        'PyQt5.QtWidgets',
    ]
    
    ON_READTHEDOCS = os.environ.get('READTHEDOCS') == 'True'  # the normal test
    ON_READTHEDOCS = True  # for testing!
    if ON_READTHEDOCS:
        # Insert copies of our Mock class for modules we want to fake.
        sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)
    
    
    MODULE_MEMBERS_TO_MAKE_SIMPLE_CLASS = (
        ('PyQt5.QtCore', 'QAbstractListModel'),
        ('PyQt5.QtCore', 'QAbstractTableModel'),
        # etc.
    )
    
    
    FIX_THE_PROBLEM = False  # to see the problem, or True to fix it!
    if FIX_THE_PROBLEM:
        for module_name, class_name in MODULE_MEMBERS_TO_MAKE_SIMPLE_CLASS:
            setattr(sys.modules[module_name], class_name, SimpleClass)
    
    
    # =============================================================================
    # Part 2. Simulate some user code.
    # =============================================================================
    
    from PyQt5.QtCore import QAbstractListModel
    
    print(QAbstractListModel)
    # For real:                 <class 'PyQt5.QtCore.QAbstractListModel'>
    # If ON_READTHEDOCS:        <MagicMock id='139789117901176'>
    # If FIX_THE_PROBLEM too:   <class '__main__.SimpleClass'>
    
    print(type(QAbstractListModel))
    # For real:                 <class 'sip.wrappertype'>
    # If ON_READTHEDOCS:        <class 'unittest.mock.MagicMock'>
    # If FIX_THE_PROBLEM too:   <class 'type'>
    
    
    class MyRandomMixin(object):
        pass
    
    
    class MyDerived(QAbstractListModel, MyRandomMixin):
        pass
    
    # For real: it's happy.
    # If ON_READTHEDOCS: will not create MyDerived; will crash with:
    #   TypeError: metaclass conflict: the metaclass of a derived class must be a
    #   (non-strict) subclass of the metaclasses of all its bases
    # If ON_READTHEDOCS and FIX_THE_PROBLEM: happy again.
    

    【讨论】:

      猜你喜欢
      • 2021-09-29
      • 1970-01-01
      • 2019-02-15
      • 1970-01-01
      • 1970-01-01
      • 2019-07-05
      • 2017-12-01
      • 1970-01-01
      • 2020-05-06
      相关资源
      最近更新 更多