[New-bugs-announce] [issue27197] mock.patch interactions with "from" imports

Clark Breyman report at bugs.python.org
Fri Jun 3 13:21:05 EDT 2016

New submission from Clark Breyman:

Unclear if this is a code bug or a gotcha that should be documented:
Cross posted to https://github.com/testing-cabal/mock/issues/365

Since "from"-style imports in modules bind names on the first execution of the import, there is a subtle interaction with patching:

_If a name is imported when the source is patched, the imported name will refer to the patched version even after the source is restored_

Test case:
# patchbug/__init__.py

# patchbug/a.py
class A(object):
    def name(self):
        return "unpatched"

# patchbug/b.py
from patchbug.a import A

def reference():
    return A().name()

# patchbug/tests.py
import mock

patchbug.reference.UnpatchedClass is bound to the value of patchbug.source.UnpatchedClass
at the time of the first import of patchbug.reference. If patched at that time it is not repaired.

def test_unpatched():
    import patchbug.a
    assert patchbug.a.A().name() == "unpatched"

uncommenting the import causes reference.UnpatchedClass to be bound before the patch, fixing
test_reference and breaking test_unpatched
def test_import_reference():
#    import patchbug.b

def test_patched():
    with mock.patch('patchbug.a.A') as P:
        import patchbug.a, patchbug.b
        P.return_value.name.return_value = "patched"
        assert patchbug.a.A().name() == "patched"
        assert patchbug.b.reference() == "patched"

def test_reference():
    import patchbug.b
    assert patchbug.b.reference() == "unpatched"

components: Library (Lib)
messages: 267114
nosy: clarkbreyman
priority: normal
severity: normal
status: open
title: mock.patch interactions with "from" imports
type: behavior
versions: Python 3.5

Python tracker <report at bugs.python.org>

More information about the New-bugs-announce mailing list