capturemock scans sys.modules, which can interact badly with six module

Bug #1314408 reported by Marc Abramowitz
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
CaptureMock
Fix Released
Undecided
Unassigned

Bug Description

The six module has something called six.moves which creates fake module objects in sys.modules that are proxies that lazy load the real modules.

When I use six and capturemock together, I get errors because capturemock scans through all the modules in sys.modules and sometimes chokes on one of them:

```
 ❯ py.test -k test_get_all_unresolved --maxfail=1 tests/functional/test_entity_correction.py
Test session starts (darwin, 2.6.7)
plugins: capturelog, cov, sugar

―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― TestEntityAttributesUnverified.test_get_all_unresolved ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
../../lib/python2.6/site-packages/capturemock/__init__.py:210: in wrapped_func
> interceptor = interceptPython(self.mode, recordFile, replayFile, self.rcFiles, self.pythonAttrs)
../../lib/python2.6/site-packages/capturemock/capturepython.py:221: in interceptPython
> handler.makeIntercepts()
../../lib/python2.6/site-packages/capturemock/capturepython.py:281: in makeIntercepts
> import_handler = ImportHandler(fullIntercepts, callStackChecker, trafficHandler)
../../lib/python2.6/site-packages/capturemock/capturepython.py:84: in __init__
> self.handleImportedModules()
../../lib/python2.6/site-packages/capturemock/capturepython.py:92: in handleImportedModules
> loadingMods = self.modulesLoading(currModName, modName)
../../lib/python2.6/site-packages/capturemock/capturepython.py:131: in modulesLoading
> modAttrName = self.findAttribute(otherMod, oldModule)
../../lib/python2.6/site-packages/capturemock/capturepython.py:140: in findAttribute
> if getattr(module, currAttrName) is attr:
../../lib/python2.6/site-packages/six.py:90: in __get__
> raise AttributeError("%s could not be imported " % self.name)
E AttributeError: dbm_gnu could not be imported
```

Here's a patch that makes CaptureMock not error out if it can find an attribute it was expecting to find:

```
diff --git a/capturepython.py.2014-04-29-143822 b/capturepython.py
index 0483931..3ac8060 100644
--- a/capturepython.py.2014-04-29-143822
+++ b/capturepython.py
@@ -137,7 +137,7 @@ class ImportHandler:
         # Can't assume the attribute will have the same name of the module,
         # because of "import x as y" construct
         for currAttrName in dir(module):
- if getattr(module, currAttrName) is attr:
+ if getattr(module, currAttrName, None) is attr:
                 return currAttrName

     def shouldIntercept(self, name):
```

Revision history for this message
Geoff Bache (geoff.bache) wrote :

Integrated the suggested patch. Let me know if it's OK and I'll release 1.0.2. (I fixed a few other things last week)

Changed in capturemock:
status: New → Fix Committed
Revision history for this message
Marc Abramowitz (msabramo) wrote :

Testing out your recent change -- here's the before and after:

$ bzr update -r 4662
 M capturemock/capturepython.py
All changes applied successfully.
Updated to revision 4662 of branch /Users/marca/dev/surveymonkey/profilesvc/src/capturemock

$ python foobar.py
Traceback (most recent call last):
  File "foobar.py", line 10, in <module>
    foo()
  File "/Users/marca/dev/surveymonkey/profilesvc/src/capturemock/capturemock/__init__.py", line 210, in wrapped_func
    interceptor = interceptPython(self.mode, recordFile, replayFile, self.rcFiles, self.pythonAttrs)
  File "/Users/marca/dev/surveymonkey/profilesvc/src/capturemock/capturemock/capturepython.py", line 221, in interceptPython
    handler.makeIntercepts()
  File "/Users/marca/dev/surveymonkey/profilesvc/src/capturemock/capturemock/capturepython.py", line 281, in makeIntercepts
    import_handler = ImportHandler(fullIntercepts, callStackChecker, trafficHandler)
  File "/Users/marca/dev/surveymonkey/profilesvc/src/capturemock/capturemock/capturepython.py", line 84, in __init__
    self.handleImportedModules()
  File "/Users/marca/dev/surveymonkey/profilesvc/src/capturemock/capturemock/capturepython.py", line 92, in handleImportedModules
    loadingMods = self.modulesLoading(currModName, modName)
  File "/Users/marca/dev/surveymonkey/profilesvc/src/capturemock/capturemock/capturepython.py", line 131, in modulesLoading
    modAttrName = self.findAttribute(otherMod, oldModule)
  File "/Users/marca/dev/surveymonkey/profilesvc/src/capturemock/capturemock/capturepython.py", line 140, in findAttribute
    if getattr(module, currAttrName) is attr:
  File "/Users/marca/dev/surveymonkey/profilesvc/lib/python2.6/site-packages/six.py", line 90, in __get__
    raise AttributeError("%s could not be imported " % self.name)
AttributeError: dbm_gnu could not be imported

$ bzr update
 M capturemock/capturepython.py
All changes applied successfully.
Updated to revision 4663 of branch /Users/marca/dev/surveymonkey/profilesvc/src/capturemock

$ python foobar.py
WARNING: having to reset the variable '__main__.sqlalchemy'.
This implies you are intercepting the module 'sqlalchemy' after importing it.
While this might work, it may well be very slow and is not recommended.

WARNING: having to reset the variable '__main__.sqlalchemy'.
This implies you are intercepting the module 'sqlalchemy' after importing it.
While this might work, it may well be very slow and is not recommended.

0.8.6

So that looks good! I will run a bigger program with the new code and see if anything changes.

Revision history for this message
Marc Abramowitz (msabramo) wrote :

Just tested out revision 4663 with py.test and some more involved code mocking sqlalchemy and it worked the same as before (which isn't actually working, but I think that's my fault, and the behavior didn't change so it's not working in the same exact way, which is what I think matters; i.e.: no regressions that I could detect).

Changed in capturemock:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.