Mock import of ctypes fails with unsupported operand on Read The Docs

629 views Asked by At

I have small Windows module that relies on the ctypes core module. On the project RTD site the page for the module comes up empty. Looking at the latest almost successful build log https://readthedocs.org/builds/apt/2900858/ there is a failure during make html stage.

  File "/var/build/user_builds/apt/checkouts/latest/knownpaths.py", line 5, in <module>
    from ctypes import windll, wintypes
  File "/usr/lib/python2.7/ctypes/wintypes.py", line 23, in <module>
    class VARIANT_BOOL(_SimpleCData):
ValueError: _type_ 'v' not supported

Following the FAQ entry https://read-the-docs.readthedocs.org/en/latest/faq.html#i-get-import-errors-on-libraries-that-depend-on-c-modules I tried to fake import ctypes using mock, but doing so cause the build to fail completely. From what I can tell, but I'm no means an expert in this area, it's because mock itself is missing some math functions:

  File "/var/build/user_builds/apt/checkouts/latest/knownpaths.py", line 13, in GUID
    ("Data4", wintypes.BYTE * 8)
TypeError: unsupported operand type(s) for *: 'Mock' and 'int'

Research on the error leads to only 3 search hits, the most relevant about Mock missing (at least) a true division operator: https://mail.python.org/pipermail/python-bugs-list/2014-March/235709.html

Am I following the right path? Can ctypes be used in a project on RTD and I just need to persevere, or do I need to give up and just use sphinx from my local machine?

Here is the current mock block from my conf.py:

try:
    #py3 import
    from unittest.mock import MagicMock
except ImportError:
    #py27 import
    from mock import Mock as MagicMock

class Mock(MagicMock):
    @classmethod
    def __getattr__(cls, name):
        return Mock()

MOCK_MODULES = ['ctypes']
sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)

// this is a cross post from https://github.com/rtfd/readthedocs.org/issues/1342. Zero responses after a week so am looking farther afield. //

1

There are 1 answers

1
matt wilkie On

Initially I thought it was ctypes itself that needed to be mocked, but it turns out I needed to work closer to home and mock the module which calls ctypes, not ctypes itself.

- MOCK_MODULES = ['ctypes']
+ MOCK_MODULES = ['knownpaths']

Thank you to @Dunes, whose comment I thought was off-track and not going to help. However it gave just enough of a turning to my mind and path of investigation to land me in the right place after all. Not all teachings look like teaching when they first grace one's attention. ;-)