Prepare to check against master branch

This commit is contained in:
Roy Hyunjin Han 2015-02-22 14:17:24 -05:00
commit ebd18b7017
3 changed files with 75 additions and 38 deletions

View file

@ -1,11 +1,11 @@
import json
from .exceptions import ConnectionError, TimeoutError, PacketError from .exceptions import ConnectionError, TimeoutError, PacketError
from .heartbeats import HeartbeatThread from .heartbeats import HeartbeatThread
from .logs import LoggingMixin from .logs import LoggingMixin
from .namespaces import EngineIONamespace, SocketIONamespace, find_callback from .namespaces import EngineIONamespace, SocketIONamespace, find_callback
from .parsers import parse_host, parse_socketIO_data from .parsers import (
from .symmetries import encode_string, get_character parse_host, parse_engineIO_session,
parse_socketIO_data, format_socketIO_data)
from .symmetries import get_character
from .transports import XHR_PollingTransport, prepare_http_session, TRANSPORTS from .transports import XHR_PollingTransport, prepare_http_session, TRANSPORTS
@ -46,7 +46,7 @@ class EngineIO(LoggingMixin):
return self.__transport return self.__transport
except AttributeError: except AttributeError:
pass pass
self._get_engineIO_session() self._engineIO_session = self._get_engineIO_session()
self._negotiate_transport() self._negotiate_transport()
self._reset_heartbeat() self._reset_heartbeat()
self._connect_namespaces() self._connect_namespaces()
@ -60,18 +60,13 @@ class EngineIO(LoggingMixin):
try: try:
engineIO_packet_type, engineIO_packet_data = next( engineIO_packet_type, engineIO_packet_data = next(
transport.recv_packet()) transport.recv_packet())
except (TimeoutError, ConnectionError) as e: except (TimeoutError, ConnectionError) as e:
if not self._wait_for_connection: if not self._wait_for_connection:
raise raise
warning = Exception('[waiting for connection] %s' % e) warning = Exception('[waiting for connection] %s' % e)
warning_screen.throw(warning) warning_screen.throw(warning)
assert engineIO_packet_type == 0 assert engineIO_packet_type == 0
value_by_name = json.loads(encode_string(engineIO_packet_data)) return parse_engineIO_session(engineIO_packet_data)
self._session_id = value_by_name['sid']
self._ping_interval = value_by_name['pingInterval'] / float(1000)
self._ping_timeout = value_by_name['pingTimeout'] / float(1000)
self._transport_upgrades = value_by_name['upgrades']
def _negotiate_transport(self): def _negotiate_transport(self):
self.__transport = self._get_transport('xhr-polling') self.__transport = self._get_transport('xhr-polling')
@ -83,7 +78,7 @@ class EngineIO(LoggingMixin):
pass pass
self._heartbeat_thread = HeartbeatThread( self._heartbeat_thread = HeartbeatThread(
send_heartbeat=self.__transport._ping, send_heartbeat=self.__transport._ping,
relax_interval_in_seconds=self._ping_interval, relax_interval_in_seconds=self._engineIO_session.ping_interval,
hurry_interval_in_seconds=1) hurry_interval_in_seconds=1)
self._heartbeat_thread.start() self._heartbeat_thread.start()
@ -129,6 +124,9 @@ class EngineIO(LoggingMixin):
# Act # Act
def send(self, engineIO_packet_data):
self._message(engineIO_packet_data)
def _open(self): def _open(self):
engineIO_packet_type = 0 engineIO_packet_type = 0
self._transport.send_packet(engineIO_packet_type, '') self._transport.send_packet(engineIO_packet_type, '')
@ -188,7 +186,6 @@ class EngineIO(LoggingMixin):
self._heartbeat_thread.relax() self._heartbeat_thread.relax()
def _should_stop_waiting(self): def _should_stop_waiting(self):
# Use __transport to make sure that we do not reconnect inadvertently
return self._wants_to_close return self._wants_to_close
def _process_packets(self): def _process_packets(self):
@ -278,7 +275,7 @@ class SocketIO(EngineIO):
for path, namespace in self._namespace_by_path.items(): for path, namespace in self._namespace_by_path.items():
namespace._transport = self.__transport namespace._transport = self.__transport
if path: if path:
self.__transport.connect(path) self.connect(path)
def __exit__(self, *exception_pack): def __exit__(self, *exception_pack):
self.disconnect() self.disconnect()
@ -311,34 +308,29 @@ class SocketIO(EngineIO):
# Act # Act
def connect(): def connect(self, path):
pass socketIO_packet_type = 0
socketIO_packet_data = format_socketIO_data(path)
self._message(str(socketIO_packet_type) + socketIO_packet_data)
def disconnect(): def disconnect(self, path=''):
socketIO_packet_type = 1
socketIO_packet_data = format_socketIO_data(path)
self._message(str(socketIO_packet_type) + socketIO_packet_data)
try:
namespace = self._namespace_by_path.pop(path)
namespace.on_disconnect()
except KeyError:
pass pass
def emit(self, event, *args, **kw): def emit(self, event, *args, **kw):
path = kw.get('path', '') path = kw.get('path', '')
callback, args = find_callback(args, kw) callback, args = find_callback(args, kw)
self._emit(path, event, args, callback) ack_id = self._set_ack_callback(callback) if callback else None
def _emit(self, path, event, args, callback):
socketIO_packet_type = 2 socketIO_packet_type = 2
socketIO_packet_data = format_socketIO_data(path, ack_id, args)
socketIO_packet_data = json.dumps([event] + list(args))
if callback:
ack_id = self._set_ack_callback(callback) if callback else ''
socketIO_packet_data = str(ack_id) + socketIO_packet_data
if path:
socketIO_packet_data = path + ',' + socketIO_packet_data
self._message(str(socketIO_packet_type) + socketIO_packet_data) self._message(str(socketIO_packet_type) + socketIO_packet_data)
def _set_ack_callback(self, callback):
self._ack_id += 1
self._callback_by_ack_id[self._ack_id] = callback
return self._ack_id
def send(self, data='', callback=None): def send(self, data='', callback=None):
args = [data] args = [data]
if callback: if callback:
@ -354,8 +346,7 @@ class SocketIO(EngineIO):
self.wait(seconds, for_callbacks=True) self.wait(seconds, for_callbacks=True)
def _should_stop_waiting(self, for_callbacks): def _should_stop_waiting(self, for_callbacks):
# Use __transport to make sure that we do not reconnect inadvertently if for_callbacks and not self._has_ack_callback:
if for_callbacks and not self.__transport.has_ack_callback:
return True return True
return super(SocketIO, self)._should_stop_waiting() return super(SocketIO, self)._should_stop_waiting()
@ -423,5 +414,14 @@ class SocketIO(EngineIO):
'Return function that acknowledges the server' 'Return function that acknowledges the server'
return lambda *args: self._ack(path, ack_id, *args) return lambda *args: self._ack(path, ack_id, *args)
def _set_ack_callback(self, callback):
self._ack_id += 1
self._callback_by_ack_id[self._ack_id] = callback
return self._ack_id
def _get_ack_callback(self, ack_id): def _get_ack_callback(self, ack_id):
return self._callback_by_ack_id.pop(ack_id) return self._callback_by_ack_id.pop(ack_id)
@property
def _has_ack_callback(self):
return True if self._callback_by_ack_id else False

View file

@ -18,6 +18,10 @@ class EngineIONamespace(LoggingMixin):
'Define a callback to handle an event emitted by the server' 'Define a callback to handle an event emitted by the server'
self._callback_by_event[event] = callback self._callback_by_event[event] = callback
def send(self, data):
'Send a message'
self._io.send(data)
def on_open(self): def on_open(self):
"""Called after engine.io connects. """Called after engine.io connects.
You can override this method.""" You can override this method."""
@ -63,6 +67,18 @@ class SocketIONamespace(EngineIONamespace):
self.path = path self.path = path
super(SocketIONamespace, self).__init__(io) super(SocketIONamespace, self).__init__(io)
def connect(self):
self._io.connect(self.path)
def disconnect(self):
self._io.disconnect(self.path)
def emit(self, event, *args, **kw):
self._io.emit(event, *args, **kw)
def send(self, data='', callback=None):
self._io.send(data, callback)
def on_connect(self): def on_connect(self):
"""Called after socket.io connects. """Called after socket.io connects.
You can override this method.""" You can override this method."""

View file

@ -1,9 +1,12 @@
import json import json
from collections import namedtuple from collections import namedtuple
from .symmetries import encode_string, get_byte, get_character, parse_url from .symmetries import (
decode_string, encode_string, get_byte, get_character, parse_url)
EngineIOSession = namedtuple('EngineIOSession', [
'id', 'ping_interval', 'ping_timeout', 'transport_upgrades'])
SocketIOData = namedtuple('SocketIOData', ['path', 'ack_id', 'args']) SocketIOData = namedtuple('SocketIOData', ['path', 'ack_id', 'args'])
@ -17,6 +20,15 @@ def parse_host(host, port, resource):
return is_secure, url return is_secure, url
def parse_engineIO_session(engineIO_packet_data):
d = json.loads(decode_string(engineIO_packet_data))
return EngineIOSession(
id=d['sid'],
ping_interval=d['pingInterval'] / float(1000),
ping_timeout=d['pingTimeout'] / float(1000),
transport_upgrades=d['upgrades'])
def encode_engineIO_content(engineIO_packets): def encode_engineIO_content(engineIO_packets):
parts = [] parts = []
for packet_type, packet_data in engineIO_packets: for packet_type, packet_data in engineIO_packets:
@ -42,7 +54,7 @@ def decode_engineIO_content(content):
def parse_socketIO_data(data): def parse_socketIO_data(data):
data = encode_string(data) data = decode_string(data)
if data.startswith('/'): if data.startswith('/'):
try: try:
path, data = data.split(',', 1) path, data = data.split(',', 1)
@ -64,6 +76,15 @@ def parse_socketIO_data(data):
return SocketIOData(path=path, ack_id=ack_id, args=args) return SocketIOData(path=path, ack_id=ack_id, args=args)
def format_socketIO_data(path=None, ack_id=None, args=None):
socketIO_packet_data = json.dumps(args) if args else ''
if ack_id is not None:
socketIO_packet_data = str(ack_id) + socketIO_packet_data
if path:
socketIO_packet_data = path + ',' + socketIO_packet_data
return socketIO_packet_data
def _make_packet_header(packet_string): def _make_packet_header(packet_string):
length_string = str(len(packet_string)) length_string = str(len(packet_string))
header_digits = [0] header_digits = [0]