sot/agasc

Error monkeypatching builtin open

Closed this issue · 1 comments

There is currently a test error which occurs only when running within testr. I regularly test using pytest before merging, but that is not exactly the same that is run in standard regression tests.

This has to do with the way I am monkeypatching the builtin open function. (Read about monkeypatching in pytest's documentation).

The pattern currently used for monkeypatching is as follows: Within the test_whatever function, any call to the builtin open function will be sent to our own _open function, which in turn returns an io.StringIO object.

def _open(filename):
    return io.StringIO(TEST_YAML[filename])

def test_whatever(monkeypatch):
    monkeypatch.setitem(__builtins__, 'open', _open)
    # ...

This is ok most of the time, but when running within run_testr there is a call to open that looks like open('/dev/null', 'w'), and this gives the following error:

TypeError: _open() takes 1 positional argument but 2 were given

The solution

One way is to change the pattern in the following way, to default to the builtin implementation:

def _open(filename, mode='r', **kwargs):
    if filename in TEST_YAML and mode == 'r':
        return io.StringIO(TEST_YAML[filename])
    return builtins.default_open(filename, mode, **kwargs)

def test_whatever(monkeypatch):
    monkeypatch.setitem(__builtins__, 'default_open', builtins.open)
    monkeypatch.setitem(__builtins__, 'open', _open)
    # ...

Fixed