1

Whenever I enable HTTPretty, I'm unable to make a connection with PyMongo. I know that HTTPretty alters the core socket module; is there any way around this?

Code Example:



    import pymongo
    import httpretty
    import time

    httpretty.enable()
    try:
        client = pymongo.MongoClient()
    except pymongo.errors.AutoReconnect:
        print("AutoReconnect")
        time.sleep(2)

Raises exception:



    Traceback (most recent call last):
      File "C:\Python33\lib\site-packages\pymongo\mongo_client.py", line 363, in __init__
        self._ensure_connected(True)
      File "C:\Python33\lib\site-packages\pymongo\mongo_client.py", line 924, in _ensure_connected
        self.__ensure_member()
      File "C:\Python33\lib\site-packages\pymongo\mongo_client.py", line 797, in __ensure_member
        member, nodes = self.__find_node()
      File "C:\Python33\lib\site-packages\pymongo\mongo_client.py", line 888, in __find_node
        raise AutoReconnect(', '.join(errors))
    pymongo.errors.AutoReconnect: [WinError 10035] A non-blocking socket operation could not be completed immediately

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "tmp.py", line 7, in 
        client = pymongo.MongoClient()
      File "C:\Python33\lib\site-packages\pymongo\mongo_client.py", line 366, in __init__
        raise ConnectionFailure(str(e))
    pymongo.errors.ConnectionFailure: [WinError 10035] A non-blocking socket operation could not be completed immediately

I am on Windows 8.1 using Python 3.3.

Can anyone explain this behavior and how to resolve it? Thanks!

Stennie
  • 63,885
  • 14
  • 149
  • 175
bmsauer
  • 105
  • 9

1 Answers1

2

It looks like the Exception being raised has to do with HTTPretty's monkey-patched socket, which calls settimeout(0) on its own socket whenever we call sendall on something that isn't an HTTP request (see real_sendall). This puts the socket in non-blocking mode. The timeout on the socket is never reset after real_sendall, so subsequent calls to recv fail with WSAEWOULDBLOCK (errno 10035). This might be a bug in HTTPretty.

One workaround for this is to reset the timeout on the socket after real_sendall. This can be accomplished by monkey-patching fakesocket.socket in HTTPretty:

from httpretty.core import fakesock

class MySocket(fakesock.socket):
    def real_sendall(self, data, *args, **kw):
        super(MySocket, self).real_sendall(data, *args, **kw)
        # Restore non-zero timeout
        self.truesock.settimeout(self.timeout)

fakesock.socket = MySocket
llovett
  • 1,449
  • 1
  • 12
  • 21
  • I came to realize that the problem was in the monkey patching, and my solution was to try my best to just enable() and disable() httpretty around my mongo calls. This is much better, thank you. – bmsauer Jul 22 '14 at 19:17
  • Also, the last line should be fakesock.socket = MySocket. – bmsauer Jul 22 '14 at 19:20
  • Ah yes, thanks for the correction. Updated my answer to use the correct class name. – llovett Jul 22 '14 at 22:15