Skip to content

Commit 3c010ad

Browse files
committed
make it work in py2
1 parent 51fdc52 commit 3c010ad

File tree

7 files changed

+61
-15
lines changed

7 files changed

+61
-15
lines changed

splitio/push/splitsse.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from enum import Enum
55
import six
66
from splitio.push.sse import SSEClient, SSE_EVENT_ERROR
7-
from splitio.util.threading import EventGroup
7+
from splitio.util.threadutil import EventGroup
88

99

1010
_LOGGER = logging.getLogger(__name__)
@@ -104,9 +104,11 @@ def start(self, token):
104104

105105
def connect(url):
106106
"""Connect to sse in a blocking manner."""
107-
self._client.start(url)
108-
self._sse_connection_closed.set()
109-
self._status = SplitSSEClient._Status.IDLE
107+
try:
108+
self._client.start(url)
109+
finally:
110+
self._sse_connection_closed.set()
111+
self._status = SplitSSEClient._Status.IDLE
110112

111113
url = self._build_url(token)
112114
task = threading.Thread(target=connect, args=(url,))

splitio/push/sse.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
"""Low-level SSE Client."""
22
import logging
33
import socket
4+
import sys
45
from collections import namedtuple
56

67
try: # try to import python3 names. fallback to python2
78
from http.client import HTTPConnection, HTTPSConnection
89
from urllib.parse import urlparse
910
except ImportError:
10-
import urlparse
11+
from urlparse import urlparse
1112
from httplib import HTTPConnection, HTTPSConnection
1213

1314

@@ -21,6 +22,33 @@
2122
SSEEvent = namedtuple('SSEEvent', ['event_id', 'event', 'retry', 'data'])
2223

2324

25+
__ENDING_CHARS = set(['\n', ''])
26+
def __httpresponse_readline_py2(response):
27+
"""
28+
Hacky `readline` implementation to be used with chunked transfers in python2.
29+
30+
This makes syscalls in a loop, so not particularly efficient. Migrate to py3 now!
31+
32+
:param response: HTTPConnection's response after a .request() call
33+
:type response: httplib.HTTPResponse
34+
35+
:returns: a string with the read line
36+
:rtype: str
37+
"""
38+
buf = []
39+
while True:
40+
read = response.read(1)
41+
buf.append(read)
42+
if read in __ENDING_CHARS:
43+
break
44+
45+
return ''.join(buf)
46+
47+
48+
_http_response_readline = (__httpresponse_readline_py2 if sys.version_info.major <= 2 #pylint:disable=invalid-name
49+
else lambda response: response.readline())
50+
51+
2452
class EventBuilder(object):
2553
"""Event builder class."""
2654

@@ -77,7 +105,8 @@ def _read_events(self):
77105
response = self._connection.getresponse()
78106
event_builder = EventBuilder()
79107
while True:
80-
line = response.readline()
108+
# line = response.readline()
109+
line = _http_response_readline(response)
81110
if line is None or len(line) <= 0: # connection ended
82111
_LOGGER.info("sse connection has ended.")
83112
break
@@ -93,7 +122,7 @@ def _read_events(self):
93122
event_builder.process_line(line)
94123
except Exception: #pylint:disable=broad-except
95124
_LOGGER.info('sse connection ended.')
96-
_LOGGER.debug(exc_info=True)
125+
_LOGGER.debug('stack trace: ', exc_info=True)
97126
finally:
98127
self._connection.close()
99128
self._connection = None # clear so it can be started again

tests/push/__init__.py

Whitespace-only changes.

tests/push/test_splitsse.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
from splitio.models.token import Token
88
from splitio.push.splitsse import SplitSSEClient
99
from splitio.push.sse import SSEEvent
10-
from tests.push.mockserver import SSEMockServer
10+
11+
from .mockserver import SSEMockServer
1112

1213

1314
class SSEClientTests(object):
@@ -47,6 +48,9 @@ def handler(event):
4748
SSEEvent('2', 'message', '1', 'a')
4849
]
4950

51+
server.publish(SSEMockServer.VIOLENT_REQUEST_END)
52+
server.stop()
53+
5054
def test_split_sse_error(self):
5155
"""Test correct initialization. Client ends the connection."""
5256

@@ -66,10 +70,12 @@ def handler(event):
6670

6771
server.publish({'event': 'error'}) # send an error event early to unblock start
6872
assert not client.start(token)
69-
time.sleep(1)
7073
client.stop(True)
7174
with pytest.raises(Exception):
7275
client.stop()
7376

7477
assert request_queue.get() == ('/event-stream?v=1.1&accessToken=some'
7578
'&channels=chan1,[?occupancy=metrics.publishers]chan2')
79+
80+
server.publish(SSEMockServer.VIOLENT_REQUEST_END)
81+
server.stop()

tests/push/test_sse.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import threading
55
import pytest
66
from splitio.push.sse import SSEClient, SSEEvent
7-
from tests.push.mockserver import SSEMockServer
7+
from .mockserver import SSEMockServer
88

99

1010
class SSEClientTests(object):
@@ -22,7 +22,10 @@ def callback(event):
2222

2323
client = SSEClient(callback)
2424

25-
client_task = threading.Thread(target=client.start, args=('http://127.0.0.1:' + str(server.port()),))
25+
def runner():
26+
"""SSE client runner thread."""
27+
assert client.start('http://127.0.0.1:' + str(server.port()))
28+
client_task = threading.Thread(target=runner)
2629
client_task.setDaemon(True)
2730
client_task.setName('client')
2831
client_task.start()
@@ -60,7 +63,10 @@ def callback(event):
6063

6164
client = SSEClient(callback)
6265

63-
client_task = threading.Thread(target=client.start, args=('http://127.0.0.1:' + str(server.port()),))
66+
def runner():
67+
"""SSE client runner thread."""
68+
assert client.start('http://127.0.0.1:' + str(server.port()))
69+
client_task = threading.Thread(target=runner)
6470
client_task.setDaemon(True)
6571
client_task.setName('client')
6672
client_task.start()
@@ -87,15 +93,18 @@ def test_sse_server_disconnects_abruptly(self):
8793
"""Test correct initialization. Server ends connection."""
8894
server = SSEMockServer()
8995
server.start()
90-
96+
9197
events = []
9298
def callback(event):
9399
"""Callback."""
94100
events.append(event)
95101

96102
client = SSEClient(callback)
97103

98-
client_task = threading.Thread(target=client.start, args=('http://127.0.0.1:' + str(server.port()),))
104+
def runner():
105+
"""SSE client runner thread."""
106+
assert client.start('http://127.0.0.1:' + str(server.port()))
107+
client_task = threading.Thread(target=runner)
99108
client_task.setDaemon(True)
100109
client_task.setName('client')
101110
client_task.start()
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import time
44
import threading
55

6-
from splitio.util.threading import EventGroup
6+
from splitio.util.threadutil import EventGroup
77

88

99
class EventGroupTests(object):

0 commit comments

Comments
 (0)