Я пытаюсь обезвредить функцию во внешнем модуле, который я использую, но monkeypatch не может получить доступ к функции, потому что пространство имен модуля перезаписывается при импорте.
Конкретно, я использую объект Bio.PDB.PDBList.PDBList
(модуль biopython
) в своем коде, и я пытаюсь исправить _urlretrieve
в Bio.PDB.PDBList
чтобы предотвратить вызовы в Интернет и вместо этого получать файлы из локального каталога, без вынуждены издеваться над методами экземпляра PDBList
которые будут значительно больше работать. Но когда я пытаюсь наивно:
m.setattr("Bio.PDB.PDBList._urlretrieve", mock_retrieve)
pytest жалуется:
AttributeError: 'type' object at Bio.PDB.PDBList has no attribute '_urlretrieve'
При дальнейшем проверке Bio.PDB
я вижу, что пространство имен модулей .PDBList
кажется, перезаписывается классом .PDBList.PDBList
:
# Download from the PDB
from .PDBList import PDBList
Таким образом, это объясняет, почему pytest видит Bio.PDB.PDBList
как объект type
без атрибута _urlretrieve
. Мой вопрос в том, есть ли способ получить monkeypatch для исправления этой "скрытой" функции?
Конкретный пример использования класса PDBList
:
from Bio.PDB.PDBList import PDBList
_pdblist = PDBList()
downloaded_file = _pdblist.retrieve_pdb_file('2O8B', pdir='./temp', file_format='pdb')
Вы правы - поскольку класс PDBList
имеет то же имя, что и модуль 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())
...
sys
.