Skip to content

Commit 65fec19

Browse files
committed
PYTHON-2443 Fix TypeError when pyOpenSSL socket has timeout of None (#527)
(cherry picked from commit 5625860)
1 parent 5b845ec commit 65fec19

File tree

2 files changed

+38
-3
lines changed

2 files changed

+38
-3
lines changed

pymongo/socket_checker.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def __init__(self):
4141
self._poller = None
4242

4343
def select(self, sock, read=False, write=False, timeout=0):
44-
"""Select for reads or writes with a timeout in seconds.
44+
"""Select for reads or writes with a timeout in seconds (or None).
4545
4646
Returns True if the socket is readable/writable, False on timeout.
4747
"""
@@ -57,7 +57,8 @@ def select(self, sock, read=False, write=False, timeout=0):
5757
try:
5858
# poll() timeout is in milliseconds. select()
5959
# timeout is in seconds.
60-
res = self._poller.poll(timeout * 1000)
60+
timeout_ = None if timeout is None else timeout * 1000
61+
res = self._poller.poll(timeout_)
6162
# poll returns a possibly-empty list containing
6263
# (fd, event) 2-tuples for the descriptors that have
6364
# events or errors to report. Return True if the list

test/test_pooling.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121
import threading
2222
import time
2323

24-
from pymongo import MongoClient
24+
from bson.son import SON
25+
from bson.codec_options import DEFAULT_CODEC_OPTIONS
26+
27+
from pymongo import MongoClient, message
2528
from pymongo.errors import (AutoReconnect,
2629
ConnectionFailure,
2730
DuplicateKeyError,
@@ -259,6 +262,37 @@ def test_socket_closed(self):
259262
s.close()
260263
self.assertTrue(socket_checker.socket_closed(s))
261264

265+
def test_socket_checker(self):
266+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
267+
s.connect((client_context.host, client_context.port))
268+
socket_checker = SocketChecker()
269+
# Socket has nothing to read.
270+
self.assertFalse(socket_checker.select(s, read=True))
271+
self.assertFalse(socket_checker.select(s, read=True, timeout=0))
272+
self.assertFalse(socket_checker.select(s, read=True, timeout=.05))
273+
# Socket is writable.
274+
self.assertTrue(socket_checker.select(s, write=True, timeout=None))
275+
self.assertTrue(socket_checker.select(s, write=True))
276+
self.assertTrue(socket_checker.select(s, write=True, timeout=0))
277+
self.assertTrue(socket_checker.select(s, write=True, timeout=.05))
278+
# Make the socket readable
279+
_, msg, _ = message.query(
280+
0, 'admin.$cmd', 0, -1, SON([('isMaster', 1)]), None,
281+
DEFAULT_CODEC_OPTIONS)
282+
s.sendall(msg)
283+
# Block until the socket is readable.
284+
self.assertTrue(socket_checker.select(s, read=True, timeout=None))
285+
self.assertTrue(socket_checker.select(s, read=True))
286+
self.assertTrue(socket_checker.select(s, read=True, timeout=0))
287+
self.assertTrue(socket_checker.select(s, read=True, timeout=.05))
288+
# Socket is still writable.
289+
self.assertTrue(socket_checker.select(s, write=True, timeout=None))
290+
self.assertTrue(socket_checker.select(s, write=True))
291+
self.assertTrue(socket_checker.select(s, write=True, timeout=0))
292+
self.assertTrue(socket_checker.select(s, write=True, timeout=.05))
293+
s.close()
294+
self.assertTrue(socket_checker.socket_closed(s))
295+
262296
def test_return_socket_after_reset(self):
263297
pool = self.create_pool()
264298
with pool.get_socket({}) as sock:

0 commit comments

Comments
 (0)