diff --git a/.travis.yml b/.travis.yml index 18c6aa7..647883c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: python python: - "2.6" - "2.7" + - "3.4" before_install: "sudo apt-get install python-dev libevent-dev" diff --git a/socketio/handler.py b/socketio/handler.py index e4b972f..672e674 100644 --- a/socketio/handler.py +++ b/socketio/handler.py @@ -1,7 +1,7 @@ import sys import re import gevent -import urlparse +from six.moves.urllib import parse as urlparse from gevent.pywsgi import WSGIHandler from socketio import transports @@ -57,10 +57,11 @@ def _do_handshake(self, tokens): self.log_error("socket.io URL mismatch") else: socket = self.server.get_socket() - data = "%s:%s:%s:%s" % (socket.sessid, + data_str = "%s:%s:%s:%s" % (socket.sessid, self.config['heartbeat_timeout'] or '', self.config['close_timeout'] or '', ",".join(self.transports)) + data = data_str.encode('utf-8') self.write_smart(data) def write_jsonp_result(self, data, wrapper="0"): diff --git a/socketio/namespace.py b/socketio/namespace.py index cef5ca1..4e192bc 100644 --- a/socketio/namespace.py +++ b/socketio/namespace.py @@ -167,14 +167,14 @@ def process_packet(self, packet): elif packet_type == 'ack': callback = self.socket._pop_ack_callback(packet['ackId']) if not callback: - print "ERROR: No such callback for ackId %s" % packet['ackId'] + print("ERROR: No such callback for ackId %s" % packet['ackId']) return return callback(*(packet['args'])) elif packet_type == 'disconnect': # Force a disconnect on the namespace. return self.call_method_with_acl('recv_disconnect', packet) else: - print "Unprocessed packet", packet + print("Unprocessed packet", packet) # TODO: manage the other packet types: disconnect def process_event(self, packet): diff --git a/socketio/packet.py b/socketio/packet.py index f626d40..f33efa6 100644 --- a/socketio/packet.py +++ b/socketio/packet.py @@ -1,3 +1,5 @@ +from six import iteritems + from socketio.defaultjson import default_json_dumps, default_json_loads MSG_TYPES = { @@ -12,7 +14,7 @@ 'noop': 8, } -MSG_VALUES = dict((v, k) for k, v in MSG_TYPES.iteritems()) +MSG_VALUES = dict((v, k) for k, v in iteritems(MSG_TYPES)) ERROR_REASONS = { 'transport not supported': 0, @@ -20,13 +22,13 @@ 'unauthorized': 2 } -REASONS_VALUES = dict((v, k) for k, v in ERROR_REASONS.iteritems()) +REASONS_VALUES = dict((v, k) for k, v in iteritems(ERROR_REASONS)) ERROR_ADVICES = { 'reconnect': 0, } -ADVICES_VALUES = dict((v, k) for k, v in ERROR_ADVICES.iteritems()) +ADVICES_VALUES = dict((v, k) for k, v in iteritems(ERROR_ADVICES)) socketio_packet_attributes = ['type', 'name', 'data', 'endpoint', 'args', 'ackId', 'reason', 'advice', 'qs', 'id'] @@ -153,7 +155,7 @@ def decode(rawstr, json_loads=default_json_loads): elif msg_type == "5": # event try: data = json_loads(data) - except ValueError, e: + except ValueError as e: print("Invalid JSON event message", data) decoded_msg['args'] = [] else: diff --git a/socketio/server.py b/socketio/server.py index 74f2428..d698cb7 100644 --- a/socketio/server.py +++ b/socketio/server.py @@ -105,7 +105,7 @@ def start_accepting(self): try: if not self.policy_server.started: self.policy_server.start() - except error, ex: + except error as ex: sys.stderr.write( 'FAILED to start flash policy server: %s\n' % (ex, )) except Exception: diff --git a/socketio/transports.py b/socketio/transports.py index d4b7ab2..40a6619 100644 --- a/socketio/transports.py +++ b/socketio/transports.py @@ -1,6 +1,6 @@ import gevent import urllib -import urlparse +from six.moves.urllib import parse as urlparse from geventwebsocket import WebSocketError from gevent.queue import Empty @@ -26,7 +26,9 @@ def __init__(self, handler, config, **kwargs): self.handler = handler self.config = config - def write(self, data=""): + def write(self, data=b""): + if not isinstance(data, bytes): + data = data.encode('latin-1') # Gevent v 0.13 if hasattr(self.handler, 'response_headers_list'): if 'Content-Length' not in self.handler.response_headers_list: diff --git a/socketio/virtsocket.py b/socketio/virtsocket.py index bd79c01..04acc71 100644 --- a/socketio/virtsocket.py +++ b/socketio/virtsocket.py @@ -13,6 +13,8 @@ import weakref import logging +from six import iteritems + import gevent from gevent.queue import Queue from gevent.event import Event @@ -311,7 +313,7 @@ def disconnect(self, silent=False): :meth:`~socketio.namespace.BaseNamespace.disconnect` calls. """ - for ns_name, ns in list(self.active_ns.iteritems()): + for ns_name, ns in list(iteritems(self.active_ns)): ns.recv_disconnect() def remove_namespace(self, namespace): @@ -362,7 +364,7 @@ def _receiver_loop(self): continue # or close the connection ? try: pkt = packet.decode(rawdata, self.json_loads) - except (ValueError, KeyError, Exception), e: + except (ValueError, KeyError, Exception) as e: self.error('invalid_packet', "There was a decoding error when dealing with packet " "with event: %s... (%s)" % (rawdata[:20], e)) @@ -436,7 +438,7 @@ def _watcher(self): while True: gevent.sleep(1.0) if not self.connected: - for ns_name, ns in list(self.active_ns.iteritems()): + for ns_name, ns in list(iteritems(self.active_ns)): ns.recv_disconnect() # Killing Socket-level jobs gevent.killall(self.jobs) diff --git a/tests/test_namespace.py b/tests/test_namespace.py index 98a6e4f..64ad6ba 100644 --- a/tests/test_namespace.py +++ b/tests/test_namespace.py @@ -206,7 +206,7 @@ def test_del_acl_method(self): except ValueError as e: self.assertEqual( message, - e.message, + e.args[0], ) else: raise Exception("""We should not be able to delete an acl that @@ -278,12 +278,12 @@ def test_blocked_event(self): self.ns.process_packet(pkt) - args = [ + args = [ 'method_access_denied', 'You do not have access to method "on_bar"', ] - kwargs = dict( + kwargs = dict( msg_id=None, endpoint='/chat', quiet=False @@ -313,7 +313,7 @@ def test_del_acl_method(self): self.ns.process_packet(pkt) - args = [ + args = [ 'method_access_denied', 'You do not have access to method "on_foo"', ] diff --git a/tests/test_packet.py b/tests/test_packet.py index 6d67c07..7ff3346 100644 --- a/tests/test_packet.py +++ b/tests/test_packet.py @@ -40,7 +40,7 @@ def test_encode_heartbeat(self): self.assertEqual(encoded_message, '2::') def test_encode_message(self): - """encoding a message packet """ + """encoding a message packet """ encoded_message = encode({'type': 'message', 'endpoint': '', 'data': 'woot' @@ -190,14 +190,14 @@ def test_encode_noop(self): class TestDecodeMessage(TestCase): - + def test_decode_deconnect(self): """decoding a disconnection packet """ decoded_message = decode('0::/woot') self.assertEqual(decoded_message, {'type': 'disconnect', 'endpoint': '/woot' }) - + def test_decode_connect(self): """decoding a connection packet """ decoded_message = decode('1::/tobi') @@ -287,7 +287,7 @@ def test_decode_ack(self): 'ackId': 140, 'endpoint': '', 'args': []}) - + # Decode with endpoint decoded_message = decode('6::/chat:140') self.assertEqual(decoded_message, {'type': 'ack', @@ -349,7 +349,7 @@ def test_except_on_invalid_message_type(self): try: decoded_message = decode('99::') except Exception as e: - self.assertEqual(e.message, "Unknown message type: 99") + self.assertEqual(e.args[0], "Unknown message type: 99") else: self.assertEqual(decoded_message, None, "We should not get a valid message")