为什么 monkeypatching os.path 需要路径参数?

Why does monkeypatching os.path require a path argument?

pytest 在 monkeypatching 文档中有这个例子:

import os.path
def getssh(): # pseudo application code
    return os.path.join(os.path.expanduser("~admin"), '.ssh')

def test_mytest(monkeypatch):
    def mockreturn(path):
        return '/abc'
    monkeypatch.setattr(os.path, 'expanduser', mockreturn)
    x = getssh()
    assert x == '/abc/.ssh'

当我从 mockreturn 函数中删除 path 参数时,出现错误

    def getssh():  # pseudo application code
>       return os.path.join(os.path.expanduser("~admin"), '.ssh')
E       TypeError: mockreturn() takes 0 positional arguments but 1 was given

我不明白是什么提供了位置参数?

此外,当我为 pathlib.Path.home() 重新实现相同的东西时,我不能在那里使用此参数 path,否则它将不起作用。不幸的是,文档没有说明这个不祥的 path 论点。

任何关于这里正在发生的魔法的说明都会非常有帮助!

您正在尝试用一个根本不接受参数的模拟替换接受一个参数的 os.path.expanduser,这会在调用时导致错误。 在引擎盖下 monkeypatch.setattr 使用内置 setattr 所以原始版本基本上是做以下工作因为 expandusermock 都采用单个参数:

>>> import os.path
>>> def mock(path):
...     return '/abc'
... 
>>> setattr(os.path, 'expanduser', mock)
>>> os.path.expanduser('~admin')
'/abc'

现在,如果您尝试将 expanduser 替换为不接受参数的方法并继续以相同的方式调用它,您将收到错误消息:

>>> setattr(os.path, 'expanduser', mock)
>>> os.path.expanduser('~admin')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: mock() takes 0 positional arguments but 1 was given

请注意,如果您尝试直接调用 mock,您将得到完全相同的错误:

>>> mock('~admin')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: mock() takes 0 positional arguments but 1 was given