Skip to content

Commit

Permalink
Better support for unicode in Python 2
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed Jul 3, 2015
1 parent a0dbf69 commit 9fb200c
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 18 deletions.
2 changes: 1 addition & 1 deletion engineio/packet.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def __init__(self, packet_type=NOOP, data=None, binary=None,
self.data = data
if binary is not None:
self.binary = binary
elif isinstance(data, six.string_types):
elif isinstance(data, six.text_type):
self.binary = False
elif isinstance(data, six.binary_type):
self.binary = True
Expand Down
9 changes: 7 additions & 2 deletions engineio/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,20 @@ def set_handler(handler):
return set_handler
set_handler(handler)

def send(self, sid, data):
def send(self, sid, data, binary=None):
"""Send a message to a client.
:param sid: The session id of the recipient client.
:param data: The data to send to the client. Data can be of type
``str``, ``bytes``, ``list`` or ``dict``. If a ``list``
or ``dict``, the data will be serialized as JSON.
:param binary: ``True`` to send packet as binary, ``False`` to send
as text. If not given, unicode (Python 2) and str
(Python 3) are sent as text, and str (Python 2) and
bytes (Python 3) are sent as binary.
"""
self._get_socket(sid).send(packet.Packet(packet.MESSAGE, data=data))
self._get_socket(sid).send(packet.Packet(packet.MESSAGE, data=data,
binary=binary))

def close(self, sid=None):
"""Close a client connection.
Expand Down
7 changes: 3 additions & 4 deletions tests/test_packet.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ def test_decode_default_packet(self):
self.assertTrue(pkt.encode(), b'6')

def test_encode_text_packet(self):
pkt = packet.Packet(packet.MESSAGE, data='text')
data = six.text_type('text')
pkt = packet.Packet(packet.MESSAGE, data=data)
self.assertEqual(pkt.packet_type, packet.MESSAGE)
self.assertEqual(pkt.data, 'text')
self.assertEqual(pkt.data, data)
self.assertFalse(pkt.binary)
self.assertEqual(pkt.encode(), b'4text')

Expand All @@ -44,8 +45,6 @@ def test_encode_binary_b64_packet(self):
self.assertTrue(pkt.binary)
self.assertEqual(pkt.encode(b64=True), b'b4AQIDBA==')

@unittest.skipIf(six.PY2,
'automatic binary detection not support in Python 2')
def test_encode_binary_packet_py3(self):
pkt = packet.Packet(packet.MESSAGE, data=b'\x01\x02\x03')
self.assertEqual(pkt.packet_type, packet.MESSAGE)
Expand Down
6 changes: 4 additions & 2 deletions tests/test_payload.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import unittest

import six

from engineio import packet
from engineio import payload

Expand All @@ -15,7 +17,7 @@ def test_decode_empty_payload(self):
self.assertEqual(p.encode(), b'')

def test_encode_payload_xhr2(self):
pkt = packet.Packet(packet.MESSAGE, data='abc')
pkt = packet.Packet(packet.MESSAGE, data=six.text_type('abc'))
p = payload.Payload([pkt])
self.assertEqual(p.packets, [pkt])
self.assertEqual(p.encode(), b'\x00\x04\xff4abc')
Expand All @@ -25,7 +27,7 @@ def test_decode_payload_xhr2(self):
self.assertEqual(p.encode(), b'\x00\x04\xff4abc')

def test_encode_payload_xhr_text(self):
pkt = packet.Packet(packet.MESSAGE, data='abc')
pkt = packet.Packet(packet.MESSAGE, data=six.text_type('abc'))
p = payload.Payload([pkt])
self.assertEqual(p.packets, [pkt])
self.assertEqual(p.encode(b64=True), b'4:4abc')
Expand Down
25 changes: 16 additions & 9 deletions tests/test_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,28 +155,32 @@ def test_upgrade_no_upgrade_packet(self):
s = socket.Socket(mock_server, 'sid')
s.queue.join = mock.MagicMock(return_value=None)
ws = mock.MagicMock()
probe = six.text_type('probe')
ws.wait.side_effect = [
packet.Packet(packet.PING, data='probe').encode(
packet.Packet(packet.PING, data=probe).encode(
always_bytes=False),
packet.Packet(packet.NOOP).encode(always_bytes=False)]
s._websocket_handler(ws)
ws.send.assert_called_once_with(packet.Packet(
packet.PONG, data='probe').encode(always_bytes=False))
packet.PONG, data=probe).encode(always_bytes=False))
self.assertEqual(s.queue.get().packet_type, packet.NOOP)
self.assertFalse(s.upgraded)

def test_websocket_read_write(self):
mock_server = mock.Mock()
s = socket.Socket(mock_server, 'sid')
s.queue.join = mock.MagicMock(return_value=None)
foo = six.text_type('foo')
bar = six.text_type('bar')
probe = six.text_type('probe')
s.poll = mock.MagicMock(side_effect=[
[packet.Packet(packet.MESSAGE, data='bar')], IOError])
[packet.Packet(packet.MESSAGE, data=bar)], IOError])
ws = mock.MagicMock()
ws.wait.side_effect = [
packet.Packet(packet.PING, data='probe').encode(
packet.Packet(packet.PING, data=probe).encode(
always_bytes=False),
packet.Packet(packet.UPGRADE).encode(always_bytes=False),
packet.Packet(packet.MESSAGE, data='foo').encode(
packet.Packet(packet.MESSAGE, data=foo).encode(
always_bytes=False),
None]
s._websocket_handler(ws)
Expand All @@ -192,23 +196,26 @@ def test_websocket_ignore_invalid_packet(self):
mock_server = mock.Mock()
s = socket.Socket(mock_server, 'sid')
s.queue.join = mock.MagicMock(return_value=None)
foo = six.text_type('foo')
bar = six.text_type('bar')
probe = six.text_type('probe')
s.poll = mock.MagicMock(side_effect=[
[packet.Packet(packet.MESSAGE, data='bar')], IOError])
[packet.Packet(packet.MESSAGE, data=bar)], IOError])
ws = mock.MagicMock()
ws.wait.side_effect = [
packet.Packet(packet.PING, data='probe').encode(
packet.Packet(packet.PING, data=probe).encode(
always_bytes=False),
packet.Packet(packet.UPGRADE).encode(always_bytes=False),
packet.Packet(packet.OPEN).encode(always_bytes=False),
packet.Packet(packet.MESSAGE, data='foo').encode(
packet.Packet(packet.MESSAGE, data=foo).encode(
always_bytes=False),
None]
s._websocket_handler(ws)
eventlet.sleep()
self.assertTrue(s.upgraded)
self.assertEqual(mock_server._trigger_event.call_count, 2)
mock_server._trigger_event.assert_has_calls([
mock.call('message', 'sid', 'foo'),
mock.call('message', 'sid', foo),
mock.call('disconnect', 'sid')])
ws.send.assert_called_with('4bar')

Expand Down

0 comments on commit 9fb200c

Please sign in to comment.