@@ -280,12 +280,12 @@ def close(self):
280280 self .conn .parent .stop (self )
281281
282282 @staticmethod
283- def _wait_to_timeout (wait ):
283+ def _wait_to_timeout (wait ) -> Optional [ float ] :
284284 if isinstance (wait , bool ):
285- return None if wait else 0
285+ return None if wait else 0.0
286286
287- if isinstance (wait , numbers .Real ) and wait >= 0 :
288- return wait
287+ if isinstance (wait , numbers .Real ) and float ( wait ) >= 0 :
288+ return float ( wait )
289289
290290 raise ReqlDriverError (f"Invalid wait timeout '{ wait } '" )
291291
@@ -397,7 +397,7 @@ def __next__(self):
397397
398398 @staticmethod
399399 def _empty_error ():
400- return DefaultCursorEmpty ()
400+ return DefaultCursorEmpty
401401
402402 def _get_next (self , timeout : Optional [float ] = None ):
403403 deadline = None if timeout is None else time .time () + timeout
@@ -425,44 +425,33 @@ def __init__(self, parent: "ConnectionInstance", timeout: int):
425425 self .port : int = parent .parent .port
426426 self .ssl : dict = parent .parent .ssl
427427 self ._read_buffer : Optional [bytes ] = None
428+ self .__socket : Optional [Union [socket .socket , ssl .SSLSocket ]] = None
428429
429430 deadline : float = time .time () + timeout
430431
431432 try :
432433 self .__socket = socket .create_connection ((self .host , self .port ), timeout )
433434
434- self .socket .setsockopt (socket .IPPROTO_TCP , socket .TCP_NODELAY , 1 )
435- self .socket .setsockopt (socket .SOL_SOCKET , socket .SO_KEEPALIVE , 1 )
435+
436+ sock = self .__socket
437+ sock .setsockopt (socket .IPPROTO_TCP , socket .TCP_NODELAY , 1 )
438+ sock .setsockopt (socket .SOL_SOCKET , socket .SO_KEEPALIVE , 1 )
436439
437440 if len (self .ssl ) > 0 :
438441 try :
439- if hasattr (
440- ssl , "SSLContext"
441- ): # Python2.7 and 3.2+, or backports.ssl
442- ssl_context = ssl .SSLContext (ssl .PROTOCOL_SSLv23 )
443- if hasattr (ssl_context , "options" ):
444- ssl_context .options |= getattr (ssl , "OP_NO_SSLv2" , 0 )
445- ssl_context .options |= getattr (ssl , "OP_NO_SSLv3" , 0 )
446- ssl_context .verify_mode = ssl .CERT_REQUIRED
447- ssl_context .check_hostname = (
448- True # redundant with ssl.match_hostname
449- )
450- ssl_context .load_verify_locations (self .ssl ["ca_certs" ])
442+
443+ ssl_context = ssl .SSLContext (ssl .PROTOCOL_TLS_CLIENT )
444+ ssl_context .check_hostname = True
445+ ssl_context .verify_mode = ssl .CERT_REQUIRED
446+ ssl_context .load_verify_locations (self .ssl ["ca_certs" ])
447+
448+ if self .__socket is not None :
451449 self .socket = ssl_context .wrap_socket (
452- self .socket , server_hostname = self .host
453- )
454- else : # this does not disable SSLv2 or SSLv3
455- # TODO: Replace the deprecated wrap_socket
456- self .socket = (
457- ssl .wrap_socket ( # pylint: disable=deprecated-method
458- self .socket ,
459- cert_reqs = ssl .CERT_REQUIRED ,
460- ssl_version = ssl .PROTOCOL_SSLv23 ,
461- ca_certs = self .ssl ["ca_certs" ],
462- )
450+ self .__socket , server_hostname = self .host
463451 )
464452 except IOError as err :
465- self .socket .close ()
453+ if self .__socket is not None :
454+ self .__socket .close ()
466455
467456 if "EOF occurred in violation of protocol" in str (
468457 err
@@ -482,14 +471,6 @@ def __init__(self, parent: "ConnectionInstance", timeout: int):
482471 raise ReqlDriverError (
483472 f"SSL handshake failed (see server log for more information): { err } "
484473 ) from err
485- try :
486- # TODO: Replace the deprecated match_hostname
487- ssl .match_hostname ( # pylint: disable=deprecated-method
488- self .socket .getpeercert (), hostname = self .host
489- )
490- except ssl .CertificateError :
491- self .socket .close ()
492- raise
493474
494475 parent .parent .handshake .reset ()
495476 response = None
@@ -530,24 +511,24 @@ def __init__(self, parent: "ConnectionInstance", timeout: int):
530511 ) from exc
531512
532513 @property
533- def socket (self ) -> Union [socket .socket , ssl .SSLSocket ]:
514+ def socket (self ) -> "Optional[ Union[socket.socket, ssl.SSLSocket]]" :
534515 """
535516 Return the wrapped socket.
536517 """
537518 return self .__socket
538519
539520 @socket .setter
540- def socket (self , value : "socket.socket" ):
521+ def socket (self , value : "Optional[Union[ socket.socket, ssl.SSLSocket]] " ):
541522 """
542523 Set the socket instance.
543524 """
544- self ._socket = value
525+ self .__socket = value
545526
546527 def is_open (self ):
547528 """
548529 Return if the connection is open.
549530 """
550- return self .socket is not None
531+ return self .__socket is not None
551532
552533 def close (self ):
553534 """
@@ -557,8 +538,9 @@ def close(self):
557538 return
558539
559540 try :
560- self .socket .shutdown (socket .SHUT_RDWR )
561- self .socket .close ()
541+ if self .__socket is not None :
542+ self .__socket .shutdown (socket .SHUT_RDWR )
543+ self .__socket .close ()
562544 except ReqlError as exc :
563545 logger .error (exc .message )
564546 except Exception as exc : # pylint: disable=broad-except
@@ -574,16 +556,20 @@ def recvall(self, length: int, deadline: Optional[float]):
574556 timeout : Optional [float ] = (
575557 None if deadline is None else max (0.0 , deadline - time .time ())
576558 )
577- self .socket .settimeout (timeout )
559+ if self .__socket is not None :
560+ self .__socket .settimeout (timeout )
578561 while len (res ) < length :
579562 while True :
580563 try :
581- chunk = self .socket .recv (length - len (res ))
582- self .socket .settimeout (None )
564+ if self .__socket is None :
565+ raise ReqlDriverError ("Socket is None" )
566+ chunk = self .__socket .recv (length - len (res ))
567+ self .__socket .settimeout (None )
583568 break
584569 except socket .timeout as exc :
585570 self ._read_buffer = res
586- self .socket .settimeout (None )
571+ if self .__socket is not None :
572+ self .__socket .settimeout (None )
587573 raise ReqlTimeoutError (self .host , self .port ) from exc
588574 except IOError as exc :
589575 if exc .errno == errno .ECONNRESET :
@@ -618,7 +604,9 @@ def sendall(self, data: bytes):
618604 offset = 0
619605 while offset < len (data ):
620606 try :
621- offset += self .socket .send (data [offset :])
607+ if self .__socket is None :
608+ raise ReqlDriverError ("Socket is None" )
609+ offset += self .__socket .send (data [offset :])
622610 except IOError as exc :
623611 if exc .errno == errno .ECONNRESET :
624612 self .close ()
@@ -683,7 +671,12 @@ def client_port(self) -> Optional[int]:
683671 if not self .is_open ():
684672 return None
685673
686- return self .socket .socket .getsockname ()[1 ]
674+ if self .socket is None :
675+ raise ReqlDriverError ("Socket unexpectedly returned none." )
676+ socket_obj = self .socket .socket
677+ if socket_obj is not None :
678+ return socket_obj .getsockname ()[1 ]
679+ return None
687680
688681 def client_address (self ) -> Optional [str ]:
689682 """
@@ -695,7 +688,12 @@ def client_address(self) -> Optional[str]:
695688 if not self .is_open ():
696689 return None
697690
698- return self .socket .socket .getsockname ()[0 ]
691+ if self .socket is None :
692+ raise ReqlDriverError ("Socket unexpectedly returned none." )
693+ socket_obj = self .socket .socket
694+ if socket_obj is not None :
695+ return socket_obj .getsockname ()[0 ]
696+ return None
699697
700698 def connect (self , timeout : int ) -> "Connection" :
701699 """
@@ -728,7 +726,12 @@ def close(self, noreply_wait=False, token=None) -> None:
728726
729727 try :
730728 if noreply_wait :
731- query = Query (PbQuery .QueryType .NOREPLY_WAIT , token , None , None )
729+ query = Query (
730+ PbQuery .QueryType .NOREPLY_WAIT ,
731+ token or self .parent ._new_token (), # pylint: disable=protected-access
732+ None ,
733+ None
734+ )
732735 self .run_query (query , False )
733736 finally :
734737 if self .socket is None :
@@ -806,7 +809,7 @@ def read_response(self, query, deadline=None) -> Optional[Response]:
806809
807810 res = None
808811
809- cursor : Cursor = self .cursor_cache .get (res_token )
812+ cursor : Optional [ Cursor ] = self .cursor_cache .get (res_token )
810813 if cursor is not None :
811814 # Construct response
812815 cursor .extend (res_buf )
@@ -843,7 +846,7 @@ class Connection: # pylint: disable=too-many-instance-attributes
843846 _json_decoder = ReqlDecoder
844847 _json_encoder = ReqlEncoder
845848
846- # pylint: disable=too-many-arguments
849+ # pylint: disable=too-many-arguments,too-many-positional-arguments
847850 def __init__ ( # nosec
848851 self ,
849852 conn_type ,
@@ -853,7 +856,7 @@ def __init__( # nosec
853856 user : str ,
854857 password : str = "" ,
855858 timeout : int = 0 ,
856- ssl : dict = None , # pylint: disable=redefined-outer-name
859+ ssl : Optional [ dict ] = None , # pylint: disable=redefined-outer-name
857860 _handshake_version : Type [BaseHandshake ] = HandshakeV1_0 ,
858861 ** kwargs ,
859862 ):
@@ -988,6 +991,8 @@ def noreply_wait(self):
988991 """
989992 self .check_open ()
990993 query = Query (PbQuery .QueryType .NOREPLY_WAIT , self ._new_token (), None , None )
994+ if self ._instance is None :
995+ raise ReqlDriverError ("Connection instance unexpectedly none." )
991996 return self ._instance .run_query (query , False )
992997
993998 def server (self ):
@@ -997,6 +1002,8 @@ def server(self):
9971002
9981003 self .check_open ()
9991004 query = Query (PbQuery .QueryType .SERVER_INFO , self ._new_token (), None , None )
1005+ if self ._instance is None :
1006+ raise ReqlDriverError ("Connection instance unexpectedly none." )
10001007 return self ._instance .run_query (query , False )
10011008
10021009 def _new_token (self ):
@@ -1012,6 +1019,8 @@ def start(self, term, **kwargs):
10121019 if "db" in kwargs or self .db is not None :
10131020 kwargs ["db" ] = DB (kwargs .get ("db" , self .db ))
10141021 query = Query (PbQuery .QueryType .START , self ._new_token (), term , kwargs )
1022+ if self ._instance is None :
1023+ raise ReqlDriverError ("Connection instance unexpectedly none." )
10151024 return self ._instance .run_query (query , kwargs .get ("noreply" , False ))
10161025
10171026 def resume (self , cursor ):
@@ -1020,6 +1029,8 @@ def resume(self, cursor):
10201029 """
10211030 self .check_open ()
10221031 query = Query (PbQuery .QueryType .CONTINUE , cursor .query .token , None , None )
1032+ if self ._instance is None :
1033+ raise ReqlDriverError ("Connection instance unexpectedly none." )
10231034 return self ._instance .run_query (query , True )
10241035
10251036 def stop (self , cursor ):
@@ -1028,6 +1039,8 @@ def stop(self, cursor):
10281039 """
10291040 self .check_open ()
10301041 query = Query (PbQuery .QueryType .STOP , cursor .query .token , None , None )
1042+ if self ._instance is None :
1043+ raise ReqlDriverError ("Connection instance unexpectedly none." )
10311044 return self ._instance .run_query (query , True )
10321045
10331046 def get_json_decoder (self , query ):
@@ -1053,6 +1066,7 @@ def __init__(self, *args, **kwargs):
10531066
10541067
10551068# pylint: disable=too-many-arguments
1069+ # pylint: disable=too-many-positional-arguments
10561070def make_connection (
10571071 connection_type ,
10581072 host = DEFAULT_HOST ,
@@ -1086,10 +1100,10 @@ def make_connection(
10861100 port = connection_string .port or port
10871101
10881102 db = connection_string .path .replace ("/" , "" ) or None
1089- timeout = query_string .get ("timeout" , DEFAULT_TIMEOUT )
1103+ timeout_list = query_string .get ("timeout" , [ DEFAULT_TIMEOUT ] )
10901104
1091- if timeout :
1092- timeout = int (timeout [0 ])
1105+ if timeout_list :
1106+ timeout = int (timeout_list [0 ])
10931107
10941108 conn = connection_type (
10951109 host ,
0 commit comments