Python 扩展scipy.stats.rv_以读取文档时出现元类错误

Python 扩展scipy.stats.rv_以读取文档时出现元类错误,python,scipy,mocking,python-sphinx,metaclass,Python,Scipy,Mocking,Python Sphinx,Metaclass,在我的Python项目中,我扩展了scipy.stats.rv\u continuous,如下所示: class GenlogisticGen(LmomDistrMixin, scipy.stats.rv_continuous): ... 我试图在上生成文档,但出现生成错误: class GenlogisticGen(LmomDistrMixin, scipy.stats.rv_continuous): TypeError: metaclass conflict: the metacl

在我的Python项目中,我扩展了
scipy.stats.rv\u continuous
,如下所示:

class GenlogisticGen(LmomDistrMixin, scipy.stats.rv_continuous):
    ...
我试图在上生成文档,但出现生成错误:

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
请注意,我正在按照下面的步骤模拟
scipy.stats
模块


我想通过模仿基类会出问题。但是什么呢?

我今天也遇到了同样的问题,但我的课与Qt有关。问题是ReadTheDocs建议的
Mock
类与预期的元类不同。下面是对问题和解决方案的描述,您需要的是从
对象继承的基类

# =============================================================================
# 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.
#=============================================================================
#第一部分。设置模拟(对于Sphinx/autodoc,您可以将其放在conf.py中)。
# =============================================================================
导入操作系统
导入系统
从unittest.mock导入MagicMock
类模拟(MagicMock):
"""
Mock类,根据
https://docs.readthedocs.io/en/latest/faq.html. 打算在以下情况下使用:
您无法真正安装/导入模块,因为ReadTheDocs(RTD)
不允许使用C(而不是纯Python)安装模块
代码。
"""
@类方法
def _uGetAttr _;(cls,名称:str):
返回MagicMock()
类SimpleClass(对象):
"""
用于替换:class:`Mock`版本的虚拟基类;请参阅
``解决下面的问题。
"""
通过
模拟_模块=[
#ReadTheDocs的东西不会安装,但我们需要:
“PyQt5”,
'PyQt5.QtCore',
“PyQt5.QtGui”,
“PyQt5.QtNetwork”,
“PyQt5.qtwidts”,
]
ON_READTHEDOCS=os.environ.get('READTHEDOCS')=='True'#正常测试
ON_READTHEDOCS=True#用于测试!
如果打开了DOC,请执行以下操作:
#为我们想要伪造的模块插入模拟类的副本。
sys.modules.update((mod_name,Mock())用于Mock_模块中的mod_name)
模块成员到简单类=(
('PyQt5.QtCore','QAbstractListModel'),
('PyQt5.QtCore','QAbstractTableModel'),
#等等。
)
修复问题=False以查看问题,或True以修复问题!
如果要解决问题,请执行以下操作:
对于模块名称,模块成员到简单类中的类名称:
setattr(系统模块[模块名称],类名称,SimpleClass)
# =============================================================================
#第二部分。模拟一些用户代码。
# =============================================================================
从PyQt5.QtCore导入QAbstractListModel
打印(QAbstractListModel)
#实际上:
#如果打开了DOC,请执行以下操作:
#如果也解决了问题:
打印(类型(QAbstractListModel))
#实际上:
#如果打开了DOC,请执行以下操作:
#如果也解决了问题:
类MyRandomMixin(对象):
通过
类MyDerived(QAbstractListModel,MyRandomMixin):
通过
#说真的:很开心。
#如果打开,则READTHEDOCS:将不创建MyDerivated;将在以下情况下崩溃:
#TypeError:元类冲突:派生类的元类必须是
#(非严格的)所有基元类的子类
#如果你读了DOC并解决了问题:再次快乐。