【发布时间】:2022-01-10 04:51:39
【问题描述】:
这是我的包结构:
.
├── src
│ ├── damastes
│ │ ├── __init__.py
│ │ ├── main.py
│ │ └── run.py
__init__.py:
from .run import *
run.py:
...
_ARGS
...
def _path_compare(path_x: Path, path_y: Path) -> Ord:
return (
...
if _ARGS.sort_lex
else ...
)
...
def run()
...
我可以从run 模块导入任何我想要的东西,但不能导入run 模块本身。直到我不得不提供猴子补丁的模块,这并没有给我带来不便:
test.py:
from src.damastes.run import _path_compare
...
def test_path_compare(monkeypatch):
args = RestrictedDotDict(copy.deepcopy(CLEAN_CONTEXT_PARAMS))
args.sort_lex = True
monkeypatch.setattr(src.damastes.run, "_ARGS", args)
assert _path_compare("alfa", "alfa") == 0
我的麻烦是monkeypatch.setattr() 需要 module 作为第一个参数,但我无法提供它。 src.damastes.run 实际上是一个函数。应该如此。 “短路”是故意的。
错误:
AttributeError: <function run at 0x7f3392b9f790> has no attribute '_ARGS'
在实验中,我提供src.damastes:
AttributeError: <module 'src.damastes' from '/src/damastes/__init__.py'> has no attribute '_ARGS'
当然没有。有没有办法将run 模块提供给monkeypatch.setattr() 而无需重构现有的包/导入解决方案?
顺便说一句,from src.damastes.run import _path_compare 部分可以正常工作。
【问题讨论】:
-
不确定这是否是您问题的根源,但
__init__.py中的from .run import *不会导入以下划线开头的名称,例如_ARGS。 -
如果您需要对
_ARGS进行猴子补丁以便正确测试,那么也许它们不应该被硬编码和“标记为私有”(通过使用前导下划线)。考虑依赖倒置的原则。 -
确实没有。我暂时不确定这也是我问题的根源
-
"
from src.damastes.run import _path_compare部分工作,顺便说一句。"是的,因为现在.run是“来自”路径的一部分,它可以被解析为引用run.py定义的模块,而不是src.damastes中定义的run名称(通过@987654347 @自动加载)。 -
@KarlKnechtel 就我而言,有出路吗?
标签: python import pytest monkeypatching