mirror of https://github.com/mahmoud/boltons.git
many more socketutils docs, now with an rst file for the sphinxing
This commit is contained in:
parent
1edb307882
commit
88d73c3e8b
|
@ -47,7 +47,7 @@ except Exception:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from typeutils import make_sentinel
|
from typeutils import make_sentinel
|
||||||
_UNSET = make_sentinel(var_name='_MISSING')
|
_UNSET = make_sentinel(var_name='_UNSET')
|
||||||
except ImportError:
|
except ImportError:
|
||||||
_UNSET = object()
|
_UNSET = object()
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ class BufferedSocket(object):
|
||||||
*timeout* and *maxsize* can both be overridden on individual socket
|
*timeout* and *maxsize* can both be overridden on individual socket
|
||||||
operations.
|
operations.
|
||||||
|
|
||||||
All ``recv`` methods return bytestrings (:type:`bytes`) and can
|
All ``recv`` methods return bytestrings (:class:`bytes`) and can
|
||||||
raise :exc:`socket.error`. :exc:`Timeout`,
|
raise :exc:`socket.error`. :exc:`Timeout`,
|
||||||
:exc:`ConnectionClosed`, and :exc:`MessageTooLong` all inherit
|
:exc:`ConnectionClosed`, and :exc:`MessageTooLong` all inherit
|
||||||
from :exc:`socket.error` and exist to provide better error
|
from :exc:`socket.error` and exist to provide better error
|
||||||
|
@ -87,7 +87,7 @@ class BufferedSocket(object):
|
||||||
|
|
||||||
BufferedSocket does not replace the built-in socket by any
|
BufferedSocket does not replace the built-in socket by any
|
||||||
means. While the overlapping parts of the API are kept parallel to
|
means. While the overlapping parts of the API are kept parallel to
|
||||||
the built-in :type:`socket.socket`, BufferedSocket does not
|
the built-in :class:`socket.socket`, BufferedSocket does not
|
||||||
inherit from socket, and most socket functionality is only
|
inherit from socket, and most socket functionality is only
|
||||||
available on the underlying socket. :meth:`socket.getpeername`,
|
available on the underlying socket. :meth:`socket.getpeername`,
|
||||||
:meth:`socket.getsockname`, :meth:`socket.fileno`, and others are
|
:meth:`socket.getsockname`, :meth:`socket.fileno`, and others are
|
||||||
|
@ -113,12 +113,12 @@ class BufferedSocket(object):
|
||||||
self.recv_lock = RLock()
|
self.recv_lock = RLock()
|
||||||
|
|
||||||
def settimeout(self, timeout):
|
def settimeout(self, timeout):
|
||||||
"Set the default timeout for future operations, in float seconds."
|
"Set the default *timeout* for future operations, in seconds."
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
|
|
||||||
def setmaxsize(self, maxsize):
|
def setmaxsize(self, maxsize):
|
||||||
"""Set the default maximum buffer size for future operations, in
|
"""Set the default maximum buffer size *maxsize* for future
|
||||||
integer of bytes. Does not truncate the current buffer.
|
operations, in bytes. Does not truncate the current buffer.
|
||||||
"""
|
"""
|
||||||
self.maxsize = maxsize
|
self.maxsize = maxsize
|
||||||
|
|
||||||
|
@ -140,15 +140,17 @@ class BufferedSocket(object):
|
||||||
size (int): The maximum number of bytes to receive.
|
size (int): The maximum number of bytes to receive.
|
||||||
flags (int): Kept for API compatibility with sockets. Only
|
flags (int): Kept for API compatibility with sockets. Only
|
||||||
the default, ``0``, is valid.
|
the default, ``0``, is valid.
|
||||||
timeout (float): The timeout for this operation. Can be 0 for
|
timeout (float): The timeout for this operation. Can be
|
||||||
nonblocking and None for no timeout. Defaults to the value
|
``0`` for nonblocking and ``None`` for no
|
||||||
set in the constructor of BufferedSocket.
|
timeout. Defaults to the value set in the constructor
|
||||||
|
of BufferedSocket.
|
||||||
|
|
||||||
If the operation does not complete in *timeout* seconds, a
|
If the operation does not complete in *timeout* seconds, a
|
||||||
:exc:`Timeout` is raised. Much like the built-in
|
:exc:`Timeout` is raised. Much like the built-in
|
||||||
:type:`socket.socket`, if this method returns an empty string,
|
:class:`socket.socket`, if this method returns an empty string,
|
||||||
then the socket is closed and recv buffer is empty. Further
|
then the socket is closed and recv buffer is empty. Further
|
||||||
calls to recv will raise :exc:`socket.error`.
|
calls to recv will raise :exc:`socket.error`.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
with self.recv_lock:
|
with self.recv_lock:
|
||||||
if timeout is _UNSET:
|
if timeout is _UNSET:
|
||||||
|
@ -314,7 +316,9 @@ class BufferedSocket(object):
|
||||||
|
|
||||||
def send(self, data, flags=0, timeout=_UNSET):
|
def send(self, data, flags=0, timeout=_UNSET):
|
||||||
"""Send the contents of the internal send buffer, as well as *data*,
|
"""Send the contents of the internal send buffer, as well as *data*,
|
||||||
to the receiving end of the connection.
|
to the receiving end of the connection. Returns the total
|
||||||
|
number of bytes sent. If no exception is raised, all of *data* was
|
||||||
|
sent and the internal send buffer is empty.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
data (bytes): The bytes to send.
|
data (bytes): The bytes to send.
|
||||||
|
@ -325,7 +329,9 @@ class BufferedSocket(object):
|
||||||
set in the constructor of BufferedSocket.
|
set in the constructor of BufferedSocket.
|
||||||
|
|
||||||
Will raise :exc:`Timeout` if the send operation fails to
|
Will raise :exc:`Timeout` if the send operation fails to
|
||||||
complete before *timeout*.
|
complete before *timeout*. In the event of an exception, use
|
||||||
|
:meth:`BufferedSocket.getsendbuffer` to see which data was
|
||||||
|
unsent.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
with self.send_lock:
|
with self.send_lock:
|
||||||
|
@ -336,12 +342,13 @@ class BufferedSocket(object):
|
||||||
sbuf = self.sbuf
|
sbuf = self.sbuf
|
||||||
sbuf.append(data)
|
sbuf.append(data)
|
||||||
if len(sbuf) > 1:
|
if len(sbuf) > 1:
|
||||||
sbuf[:] = [b''.join(sbuf)]
|
sbuf[:] = [b''.join([s for s in sbuf if s])]
|
||||||
self.sock.settimeout(timeout)
|
self.sock.settimeout(timeout)
|
||||||
start = time.time()
|
start, total_sent = time.time(), 0
|
||||||
try:
|
try:
|
||||||
while sbuf[0]:
|
while sbuf[0]:
|
||||||
sent = self.sock.send(sbuf[0])
|
sent = self.sock.send(sbuf[0])
|
||||||
|
total_sent += sent
|
||||||
sbuf[0] = sbuf[0][sent:]
|
sbuf[0] = sbuf[0][sent:]
|
||||||
if timeout:
|
if timeout:
|
||||||
cur_timeout = timeout - (time.time() - start)
|
cur_timeout = timeout - (time.time() - start)
|
||||||
|
@ -350,9 +357,13 @@ class BufferedSocket(object):
|
||||||
self.sock.settimeout(cur_timeout)
|
self.sock.settimeout(cur_timeout)
|
||||||
except socket.timeout:
|
except socket.timeout:
|
||||||
raise Timeout(timeout, '%s bytes unsent' % len(sbuf[0]))
|
raise Timeout(timeout, '%s bytes unsent' % len(sbuf[0]))
|
||||||
return
|
return total_sent
|
||||||
|
|
||||||
sendall = send
|
def sendall(self, data, flags=0, timeout=_UNSET):
|
||||||
|
"""An passthrough to :meth:`~BufferedSocket.send`, retained for
|
||||||
|
parallelism to the :class:`socket.socket` API.
|
||||||
|
"""
|
||||||
|
return self.send(data, flags, timeout)
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
"Send the contents of the internal send buffer."
|
"Send the contents of the internal send buffer."
|
||||||
|
@ -367,7 +378,14 @@ class BufferedSocket(object):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
class Error(socket.error, Exception):
|
class Error(socket.error):
|
||||||
|
"""A subclass of :exc:`socket.error` from which all other
|
||||||
|
``socketutils`` exceptions inherit.
|
||||||
|
|
||||||
|
When using :class:`BufferedSocket` and other ``socketutils``
|
||||||
|
types, generally you want to catch one of the specific exception
|
||||||
|
types below, or :exc:`socket.error`.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -376,13 +394,15 @@ class ConnectionClosed(Error):
|
||||||
|
|
||||||
|
|
||||||
class MessageTooLong(Error):
|
class MessageTooLong(Error):
|
||||||
"""Only raised from :meth:`BufferedSocket.recv_until` when more than
|
"""Raised from :meth:`BufferedSocket.recv_until` and
|
||||||
*maxsize* bytes are read without the socket closing.
|
:meth:`BufferedSocket.recv_closed` when more than *maxsize* bytes are
|
||||||
|
read without encountering the marker or a closed connection,
|
||||||
|
respectively.
|
||||||
"""
|
"""
|
||||||
def __init__(self, bytes_read=None, marker=None):
|
def __init__(self, bytes_read=None, marker=None):
|
||||||
msg = 'message exceeded maximum size'
|
msg = 'message exceeded maximum size'
|
||||||
if bytes_read is not None:
|
if bytes_read is not None:
|
||||||
msg += '%s bytes read' % (bytes_read,)
|
msg += '. %s bytes read' % (bytes_read,)
|
||||||
if marker is not None:
|
if marker is not None:
|
||||||
msg += '. Marker not found: %r' % (marker,)
|
msg += '. Marker not found: %r' % (marker,)
|
||||||
super(MessageTooLong, self).__init__(msg)
|
super(MessageTooLong, self).__init__(msg)
|
||||||
|
@ -405,7 +425,7 @@ class NetstringSocket(object):
|
||||||
More info: https://en.wikipedia.org/wiki/Netstring
|
More info: https://en.wikipedia.org/wiki/Netstring
|
||||||
Even more info: http://cr.yp.to/proto/netstrings.txt
|
Even more info: http://cr.yp.to/proto/netstrings.txt
|
||||||
"""
|
"""
|
||||||
def __init__(self, sock, timeout=30, maxsize=32 * 1024):
|
def __init__(self, sock, timeout=DEFAULT_TIMEOUT, maxsize=DEFAULT_MAXSIZE):
|
||||||
self.bsock = BufferedSocket(sock)
|
self.bsock = BufferedSocket(sock)
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self.maxsize = maxsize
|
self.maxsize = maxsize
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
``socketutils`` - ``socket`` wrappers
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
.. automodule:: boltons.socketutils
|
||||||
|
|
||||||
|
BufferedSocket
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. autoclass:: boltons.socketutils.BufferedSocket
|
||||||
|
:members:
|
||||||
|
|
||||||
|
Exceptions
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
These are a few exceptions that derive from :exc:`socket.error` and
|
||||||
|
provide clearer code and better error messages.
|
||||||
|
|
||||||
|
.. autoexception:: boltons.socketutils.Error
|
||||||
|
.. autoexception:: boltons.socketutils.Timeout
|
||||||
|
.. autoexception:: boltons.socketutils.ConnectionClosed
|
||||||
|
.. autoexception:: boltons.socketutils.MessageTooLong
|
||||||
|
|
||||||
|
Netstring
|
||||||
|
---------
|
||||||
|
|
||||||
|
.. autoclass:: boltons.socketutils.NetstringSocket
|
||||||
|
:members:
|
||||||
|
|
||||||
|
Nestring Exceptions
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
These are a few higher-level exceptions for netstring connections.
|
||||||
|
|
||||||
|
.. autoexception:: boltons.socketutils.NetstringProtocolError
|
||||||
|
.. autoexception:: boltons.socketutils.NetstringInvalidSize
|
||||||
|
.. autoexception:: boltons.socketutils.NetstringMessageTooLong
|
Loading…
Reference in New Issue