"""
Socket interface, connecting front-end to back-end.
Plus some other common attributes.
"""
import sys
if sys.platform == "win32" and "socket" not in sys.modules:
from socket import setdefaulttimeout
setdefaulttimeout (7.5)
from socket import SHUT_RD, SO_REUSEADDR, SOL_SOCKET, SocketType, error
from marshal import loads, dumps
version = "2.1.6"
class Error (Exception):
" generic DB-API error "
class ServerNotUp (Error):
" fail to connect to back-end "
class PicklingError (Error):
" data can not be flattened for transport over sockets "
def e_str (e):
" format exception as string "
return "%s: %s" % (e.__class__.__name__, e)
def print23 (*args, **kwargs):
""" python3 style print function """
kwargs.pop ("file", sys.stdout).write (
' '.join (map (str, args)) + kwargs.pop ("end", "\n")
)
class Socket (SocketType):
"""
Adapts a socket to sqmediumlite front-end back-end interface.
Raises ServerNotUp and closes the socket in case any network
error occurs.
"""
def sconnect (self, address):
try:
self.connect (address)
except error as e:
raise ServerNotUp ("error connecting to %s:%s" % (address, e))
return self
def sbindlisten (self, address):
self.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
try:
self.bind (address)
except Exception as e:
self.close ()
raise ServerNotUp ("%s (binding to %s)" % (e, address))
self.listen (2)
return self
def saccept (self):
while True:
try:
if sys.version < '3':
return Socket(_sock=self._sock.accept() [0])
else:
return Socket(fileno=self._accept() [0])
except Exception as e:
if not _is_retriable (e):
self.close ()
raise ServerNotUp ("accept error " + e_str (e))
def srecv (self):
data = None
while True:
try:
if data is None:
data = self.recv (1500)
else:
data2 = self.recv (150000)
if not data2:
self.close()
data += data2
except Exception as e:
if not _is_retriable (e):
self.close()
raise ServerNotUp ( "recv error " + e_str (e))
continue
try:
return loads (data)
except EOFError:
pass
except ValueError as e:
if "unknown type code" in str (e):
raise PicklingError (
"received unexpected data in Python %.3s" % sys.version)
def ssend (self, d):
try:
data = dumps (d)
except Exception as e:
raise PicklingError (str (e))
while data:
try:
data = data [self.send (data):]
except Exception as e:
if not _is_retriable (e):
self.close()
raise ServerNotUp ( "send error " + e_str (e))
def sshutdown (self):
try:
self.shutdown (SHUT_RD)
except error as e:
self.close()
raise ServerNotUp ( "shutdown error " + e_str (e))
def sgetpeername (self):
try:
return self.getpeername ()
except error as e:
return (str (e), -1)
def _is_retriable (e):
" see if socket error is a timeout "
return isinstance (e, error) and (
"timed out" in str (e) or "temporarily" in str (e))