名称空间被覆盖的模块中的 monkeypatch 函数

monkeypatch function in module whose namespace was overwritten

我正在尝试对我使用的外部模块中的函数进行 monkeypatch,但 monkeypatch 似乎无法访问该函数,因为模块的名称空间在导入时被覆盖。

具体来说,我在我的代码中使用了一个 Bio.PDB.PDBList.PDBList 对象(biopython 模块),我试图在 Bio.PDB.PDBList 中修补 _urlretrieve 以防止调用internet 而不是从本地目录获取文件,而不必模拟 PDBList 的实例方法,这将大大增加工作量。但是当我尝试天真时:

m.setattr("Bio.PDB.PDBList._urlretrieve", mock_retrieve)

pytest 抱怨:

AttributeError: 'type' object at Bio.PDB.PDBList has no attribute '_urlretrieve'

进一步检查 Bio.PDB,我发现模块命名空间 .PDBList 似乎被 class .PDBList.PDBList:

覆盖
# Download from the PDB
from .PDBList import PDBList

这样就可以解释为什么 pytest 将 Bio.PDB.PDBList 视为没有属性 _urlretrievetype 对象。我的问题是,有没有办法让 monkeypatch 修补这个 'hidden' 函数?


PDBList用法的具体例子 class:

from Bio.PDB.PDBList import PDBList

_pdblist = PDBList()

downloaded_file = _pdblist.retrieve_pdb_file('2O8B', pdir='./temp', file_format='pdb')

你是对的 - 由于 PDBList class 与模块 Bio.PDB.PDBList 同名,在 import Bio.PDB.PDBList 之后你将无法访问该模块顾名思义(阴影问题)。但是,您仍然可以从加载的模块缓存和 monkeypatch 中获取导入的模块对象:

import sys
from unittest.mock import Mock
import Bio.PDB.PDBList

def test_spam(monkeypatch):
    assert isinstance(Bio.PDB.PDBList, type)
    with monkeypatch.context() as m:
        m.setattr(sys.modules['Bio.PDB.PDBList'], '_urlretrieve', Mock())
        ...