Python iteration docking for use with Sphinx

I use Sphinx to document a project that is dependent on wxPython using the autodocs extension so that it automatically generates pages from our docstrings. The autodocs extension automatically works on every import module, which is great for our packages, but this is a problem when we import large external library such as wxPython. Thus, instead of letting it generate everything from wxPython, I use the unittest.mock library module (previously the external Mock package ). The most basic setup is fine for most parts of wxPython, but I came across a situation that I don't see in an easy way (probably due to my relative unfamiliarity with mock until this week).

Currently, the end of my conf.py file has the following:

 MOCK_MODULES = ['wx.lib.newevent'] # I've skipped irrelevant entries... for module_name in MOCK_MODULES: sys.modules[module_name] = mock.Mock() 

For all wxPython modules, but wx.lib.newevent , this works fine. However, here I use the newevent.NewCommandEvent() [1] function to create an event for a specific scenario. In this case, I get a warning when calling NewCommandEvent() with a TypeError: 'Mock' object is not iterable note TypeError: 'Mock' object is not iterable .

While I see how patching can be used to handle this for building unit tests (which I will be doing next month!), I can hardly see how to integrate this at a simple level in my Sphinx configuration.

Edit: I just tried using MagicMock() ; this still causes an error at the same point, although it now produces a ValueError: need more than 0 values to unpack . This seems like a step in the right direction, but I still don't know how to handle this without explicitly installing it for this single module. Maybe this is the best solution?


Footnotes

  • Yes, it is a function, a naming convention that makes it look like a class, despite this; wxPython follows the C ++ naming conventions that are used throughout the wxWidgets toolkit.
+8
python mocking python-sphinx python-mock
source share
1 answer

From the error, it looks like it actually executes newevent.NewCommandEvent() , so I assume somewhere in your code you have a top-level line something like this:

 import wx.lib.newevent ... event, binder = wx.lib.newevent.NewCommandEvent() 

When autodoc imports a module, it tries to run this line of code, but since NewCommandEvent actually a Mock object, Python cannot bind its output to a tuple (event, binder) . There are two possible solutions. The first is to change the code so that it does not execute on import, possibly wrapping it inside if __name__ == '__main__' . I would recommend this solution because biased side effects can often occur to create objects such as this during import.

The second solution is to tell the Mock object to return the appropriate values ​​this way:

 wx.lib.newevent.NewCommandEvent = mock.Mock(return_value=(Mock(), Mock())) 

However, if you do something in your code with return values, you may encounter the same problem down the line.

+1
source share

All Articles