Added more documentation

This commit is contained in:
Sean Arietta 2014-12-23 02:37:53 -08:00
commit 455890a700
2 changed files with 62 additions and 12 deletions

View file

@ -16,7 +16,6 @@ except ImportError:
from .exceptions import ConnectionError, TimeoutError, PacketError
from .transports import _get_response
_SocketIOSession = namedtuple('_SocketIOSession', [
'id',
'heartbeat_interval',
@ -24,7 +23,6 @@ _SocketIOSession = namedtuple('_SocketIOSession', [
'server_supported_transports',
])
_log = logging.getLogger(__name__)
PROTOCOL_VERSION = 1
RETRY_INTERVAL_IN_SECONDS = 1
class BaseNamespace(object):
@ -171,6 +169,9 @@ class SocketIO(object):
self._terminate_heartbeat();
def _terminate_heartbeat(self):
"""Terminates the heartbeat thread.
"""
if self.heartbeat_terminator is not None:
self.heartbeat_terminator.set();
self.heartbeat_thread.join();
@ -365,6 +366,21 @@ class SocketIO(object):
return self.__transport
def _upgrade(self):
"""Attempts to upgrade the connection to a websocket.
This method will execute the update process outline here:
https://github.com/Automattic/engine.io-protocol#transport-upgrading
To summarize, we first send a PING packet with the string
'probe' appended as data. This signals to the server that we
want to probe the ability to upgrade. If the server has this
functionality, it responds with a PONG packet and the 'probe'
string.
We then send an UPGRADE packet, restart the heartbeat thread,
and return.
"""
websocket = transports.WebsocketTransport(self.session, self.is_secure, self.base_url, **self.kw);
websocket.send_packet(PacketType.PING, "", "probe");
for packet in websocket.recv_packet():
@ -384,6 +400,19 @@ class SocketIO(object):
return websocket;
def _start_heartbeat(self, transport):
"""Starts the heartbeat thread.
The heartbeat thread ensures that our connection is never
severed. This effectively spawns a thread that sits in an
infinite loop. The thread waits
self.session.heartbeat_interval / 2 (gleaned from the server)
seconds, then sends a heartbeat packet (PING).
The thread is implemented using a multiprocessing.Event to
perform the wait, so it doesn't waste any cpu cycles while
it's waiting.
"""
_log.debug("[start heartbeat pacemaker]");
self.heartbeat_terminator = multiprocessing.Event();
self.heartbeat_thread = multiprocessing.Process(
@ -458,10 +487,14 @@ class SocketIO(object):
find_event_callback('disconnect')()
def _on_event(self, packet, find_event_callback):
# Accoding to the documentation
# (https://github.com/automattic/socket.io-protocol#event),
# the event name is the first entry in the message array, and
# the arguments are the rest of the entries.
"""This delegate is called when there is an EVENT packet.
Accoding to the documentation
(https://github.com/automattic/socket.io-protocol#event), the
event name is the first entry in the message array, and the
arguments are the rest of the entries.
"""
event = packet.payload.message[0];
args = packet.payload.message[1:] if len(packet.payload.message) > 1 else [];
@ -556,7 +589,7 @@ def _yield_elapsed_time(seconds=None):
def _get_socketIO_session(is_secure, base_url, **kw):
server_url = '%s://%s/?EIO=%d&transport=polling' \
% ('https' if is_secure else 'http', base_url, parser.ENGINE_PROTOCOL)
% ('https' if is_secure else 'http', base_url, parser.ENGINEIO_PROTOCOL)
_log.debug('[session] %s', server_url)
try:
response = _get_response(requests.get, server_url, **kw)

View file

@ -4,7 +4,7 @@ import json
_log = logging.getLogger(__name__)
ENGINE_PROTOCOL = 3;
ENGINEIO_PROTOCOL = 3;
class PacketType(Enum):
OPEN = 0;
@ -25,6 +25,8 @@ class MessageType(Enum):
BINARY_ACK = 6;
class Packet():
""" Represents a 'packet' from the engine.io protocol.
"""
def __init__(self, packet_type, payload):
self.type = packet_type;
self.payload = payload;
@ -33,6 +35,16 @@ class Packet():
return "PACKET{type: " + str(self.type) + ", payload: " + str(self.payload) + "}";
def encode_as_string(self, for_websocket = False):
"""Returns the packet encoded according to the engine.io-protocol.
Reference: (https://github.com/Automattic/engine.io-protocol).
It's worth noting that websockets have their own framing and
encoding mechanism so if the packet is going to be transmitted
via websockets, we encode it slightly differently per the
documentation.
"""
data = "";
path = "";
if self.type == PacketType.MESSAGE and not isinstance(self.payload, basestring):
@ -54,6 +66,8 @@ class Packet():
return encoded;
class Message():
"""Represents a 'message' from the socket.io protocol.
"""
def __init__(self, message_type, message, path = "", attachments = "", message_id = None):
self.type = message_type;
if isinstance(message, basestring):
@ -84,9 +98,8 @@ class Message():
"}";
def encode_as_json(self):
"""Encodes a Message to be sent to socket.io server.
Assumes the message payload will be dumped as a json string.
"""Encodes a JSON Message to be sent to socket.io server.
"""
data = json.dumps(self.message);
if self.id is not None:
@ -97,7 +110,11 @@ class Message():
return str(self.type) + self.path + "," + data;
def encode_as_string(self):
"""Same as the encode_as_string method except it doesn't encode things as a JSON string"""
"""Encodes a Message to be to a socket.io server.
This will call encode_as_json if the message is not a string.
"""
if not isinstance(self.message, basestring):
return self.encode_as_json();
data = self.message;