summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Stasiak <jakub@stasiak.at>2014-10-06 00:38:32 +0100
committerJakub Stasiak <jakub@stasiak.at>2014-10-10 09:17:41 +0100
commit6cbd4846ab2f12b1c18c38b570293c0bb05d28a7 (patch)
tree900c16e1c3da70e0aa58e2e88e84489db8e8249a
parent02a23c8bd78b3b923faed3e9c62c7664c7e6a6cd (diff)
downloadeventlet-6cbd4846ab2f12b1c18c38b570293c0bb05d28a7.tar.gz
Python 3 compat: Improve various bits
This includes changes to WSGI, websocket, bytes/str/unicode handling, SSL, backdoor, greenio and tests. Some comments and conditionals (PY2/PY3) were added for clarity GH issues: Closes #106 Closes #111 Closes #118 Closes #141 Incidentally should also close #135 (reopen if didn't) cc #6
-rw-r--r--NEWS1
-rw-r--r--eventlet/backdoor.py6
-rw-r--r--eventlet/green/ssl.py63
-rw-r--r--eventlet/greenio.py30
-rw-r--r--eventlet/websocket.py50
-rw-r--r--eventlet/wsgi.py48
-rw-r--r--tests/api_test.py10
-rw-r--r--tests/backdoor_test.py12
-rw-r--r--tests/convenience_test.py4
-rw-r--r--tests/env_test.py1
-rw-r--r--tests/greenio_test.py12
-rw-r--r--tests/mysqldb_test_monkey_patch.py4
-rw-r--r--tests/patcher_test.py23
-rw-r--r--tests/websocket_new_test.py36
-rw-r--r--tests/wsgi_test.py253
-rw-r--r--tests/wsgi_test_conntimeout.py2
16 files changed, 312 insertions, 243 deletions
diff --git a/NEWS b/NEWS
index a25e4ab..ae51d9a 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@
=========================
* removed deprecated modules: api, most of coros, pool, proc, processes and util
+* improved Python 3 compatibility
0.15.2
======
diff --git a/eventlet/backdoor.py b/eventlet/backdoor.py
index 5994035..2067772 100644
--- a/eventlet/backdoor.py
+++ b/eventlet/backdoor.py
@@ -7,7 +7,7 @@ import sys
import eventlet
from eventlet import hubs
-from eventlet.support import greenlets, get_errno, six
+from eventlet.support import greenlets, get_errno
try:
sys.ps1
@@ -30,13 +30,11 @@ class FileProxy(object):
pass
def write(self, data, *a, **kw):
- data = six.b(data)
self.f.write(data, *a, **kw)
self.f.flush()
def readline(self, *a):
- line = self.f.readline(*a).replace(b'\r\n', b'\n')
- return six.u(line)
+ return self.f.readline(*a).replace('\r\n', '\n')
def __getattr__(self, attr):
return getattr(self.f, attr)
diff --git a/eventlet/green/ssl.py b/eventlet/green/ssl.py
index ba5e6c2..b76ce38 100644
--- a/eventlet/green/ssl.py
+++ b/eventlet/green/ssl.py
@@ -7,7 +7,7 @@ import sys
import errno
time = __import__('time')
-from eventlet.support import get_errno
+from eventlet.support import get_errno, six
from eventlet.hubs import trampoline, IOClosed
from eventlet.greenio import set_nonblocking, GreenSocket, SOCKET_CLOSED, CONNECT_ERR, CONNECT_SUCCESS
orig_socket = __import__('socket')
@@ -21,9 +21,10 @@ else:
__patched__ = ['SSLSocket', 'wrap_socket', 'sslwrap_simple']
+_original_sslsocket = __ssl.SSLSocket
-class GreenSSLSocket(__ssl.SSLSocket):
+class GreenSSLSocket(_original_sslsocket):
""" This is a green version of the SSLSocket class from the ssl module added
in 2.6. For documentation on it, please see the Python standard
documentation.
@@ -40,23 +41,49 @@ class GreenSSLSocket(__ssl.SSLSocket):
# we are inheriting from SSLSocket because its constructor calls
# do_handshake whose behavior we wish to override
- def __init__(self, sock, *args, **kw):
+ def __init__(self, sock, keyfile=None, certfile=None,
+ server_side=False, cert_reqs=CERT_NONE,
+ ssl_version=PROTOCOL_SSLv23, ca_certs=None,
+ do_handshake_on_connect=True, *args, **kw):
if not isinstance(sock, GreenSocket):
sock = GreenSocket(sock)
self.act_non_blocking = sock.act_non_blocking
- self._timeout = sock.gettimeout()
- super(GreenSSLSocket, self).__init__(sock.fd, *args, **kw)
+
+ if six.PY2:
+ # On Python 2 SSLSocket constructor queries the timeout, it'd break without
+ # this assignment
+ self._timeout = sock.gettimeout()
+
+ # nonblocking socket handshaking on connect got disabled so let's pretend it's disabled
+ # even when it's on
+ super(GreenSSLSocket, self).__init__(
+ sock.fd, keyfile, certfile, server_side,cert_reqs, ssl_version,
+ ca_certs, do_handshake_on_connect and six.PY2, *args, **kw)
# the superclass initializer trashes the methods so we remove
# the local-object versions of them and let the actual class
# methods shine through
+ # Note: This for Python 2
try:
for fn in orig_socket._delegate_methods:
delattr(self, fn)
except AttributeError:
pass
+ if six.PY3:
+ # Python 3 SSLSocket construction process overwrites the timeout so restore it
+ self._timeout = sock.gettimeout()
+
+ # it also sets timeout to None internally apparently (tested with 3.4.2)
+ _original_sslsocket.settimeout(self, 0.0)
+ assert _original_sslsocket.gettimeout(self) == 0.0
+
+ # see note above about handshaking
+ self.do_handshake_on_connect = do_handshake_on_connect
+ if do_handshake_on_connect and self._connected:
+ self.do_handshake()
+
def settimeout(self, timeout):
self._timeout = timeout
@@ -98,14 +125,14 @@ class GreenSSLSocket(__ssl.SSLSocket):
return self._call_trampolining(
super(GreenSSLSocket, self).write, data)
- def read(self, len=1024):
+ def read(self, *args, **kwargs):
"""Read up to LEN bytes and return them.
Return zero-length string on EOF."""
try:
return self._call_trampolining(
- super(GreenSSLSocket, self).read, len)
+ super(GreenSSLSocket, self).read, *args, **kwargs)
except IOClosed:
- return ''
+ return b''
def send(self, data, flags=0):
if self._sslobj:
@@ -174,9 +201,9 @@ class GreenSSLSocket(__ssl.SSLSocket):
trampoline(self, read=True,
timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out'))
except IOClosed:
- return ''
+ return b''
if get_errno(e) in SOCKET_CLOSED:
- return ''
+ return b''
raise
def recv_into(self, buffer, nbytes=None, flags=0):
@@ -245,14 +272,16 @@ class GreenSSLSocket(__ssl.SSLSocket):
if self._sslobj:
raise ValueError("attempt to connect already-connected SSLSocket!")
self._socket_connect(addr)
- if has_ciphers:
- self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile,
- self.cert_reqs, self.ssl_version,
- self.ca_certs, self.ciphers)
+ server_side = False
+ try:
+ sslwrap = _ssl.sslwrap
+ except AttributeError:
+ # sslwrap was removed in 2.7.9
+ self._sslobj = self._context._wrap_socket(self, server_side)
else:
- self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile,
- self.cert_reqs, self.ssl_version,
- self.ca_certs)
+ self._sslobj = sslwrap(self._sock, server_side, self.keyfile, self.certfile,
+ self.cert_reqs, self.ssl_version,
+ self.ca_certs, *([self.ciphers] if has_ciphers else []))
if self.do_handshake_on_connect:
self.do_handshake()
diff --git a/eventlet/greenio.py b/eventlet/greenio.py
index 38e8168..cd521b3 100644
--- a/eventlet/greenio.py
+++ b/eventlet/greenio.py
@@ -160,6 +160,15 @@ class GreenSocket(object):
def _sock(self):
return self
+ if six.PY3:
+ def _get_io_refs(self):
+ return self.fd._io_refs
+
+ def _set_io_refs(self, value):
+ self.fd._io_refs = value
+
+ _io_refs = property(_get_io_refs, _set_io_refs)
+
# Forward unknown attributes to fd, cache the value for future use.
# I do not see any simple attribute which could be changed
# so caching everything in self is fine.
@@ -275,12 +284,16 @@ class GreenSocket(object):
newsock.settimeout(self.gettimeout())
return newsock
- def makefile(self, *args, **kw):
- dupped = self.dup()
- res = _fileobject(dupped, *args, **kw)
- if hasattr(dupped, "_drop"):
- dupped._drop()
- return res
+ if six.PY3:
+ def makefile(self, *args, **kwargs):
+ return _original_socket.makefile(self, *args, **kwargs)
+ else:
+ def makefile(self, *args, **kwargs):
+ dupped = self.dup()
+ res = _fileobject(dupped, *args, **kwargs)
+ if hasattr(dupped, "_drop"):
+ dupped._drop()
+ return res
def makeGreenFile(self, *args, **kw):
warnings.warn("makeGreenFile has been deprecated, please use "
@@ -457,11 +470,12 @@ class _SocketDuckForFd(object):
def send(self, data):
while True:
try:
- os.write(self._fileno, data)
+ return os.write(self._fileno, data)
except OSError as e:
if get_errno(e) not in SOCKET_BLOCKING:
raise IOError(*e.args)
- trampoline(self, write=True)
+ else:
+ trampoline(self, write=True)
def sendall(self, data):
len_data = len(data)
diff --git a/eventlet/websocket.py b/eventlet/websocket.py
index 64514c2..10c868d 100644
--- a/eventlet/websocket.py
+++ b/eventlet/websocket.py
@@ -37,15 +37,17 @@ for _mod in ('wsaccel.utf8validator', 'autobahn.utf8validator'):
ACCEPTABLE_CLIENT_ERRORS = set((errno.ECONNRESET, errno.EPIPE))
__all__ = ["WebSocketWSGI", "WebSocket"]
-PROTOCOL_GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
-VALID_CLOSE_STATUS = (range(1000, 1004)
- + range(1007, 1012)
- # 3000-3999: reserved for use by libraries, frameworks,
- # and applications
- + range(3000, 4000)
- # 4000-4999: reserved for private use and thus can't
- # be registered
- + range(4000, 5000))
+PROTOCOL_GUID = b'258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
+VALID_CLOSE_STATUS = set(
+ list(range(1000, 1004)) +
+ list(range(1007, 1012)) +
+ # 3000-3999: reserved for use by libraries, frameworks,
+ # and applications
+ list(range(3000, 4000)) +
+ # 4000-4999: reserved for private use and thus can't
+ # be registered
+ list(range(4000, 5000))
+)
class BadRequest(Exception):
@@ -115,7 +117,7 @@ class WebSocketWSGI(object):
raise BadRequest()
except BadRequest as e:
status = e.status
- body = e.body or ''
+ body = e.body or b''
headers = e.headers or []
start_response(status,
[('Connection', 'close'), ] + headers)
@@ -219,15 +221,14 @@ class WebSocketWSGI(object):
# extensions = [i.strip() for i in extensions.split(',')]
key = environ['HTTP_SEC_WEBSOCKET_KEY']
- response = base64.b64encode(sha1(key + PROTOCOL_GUID).digest())
- handshake_reply = ["HTTP/1.1 101 Switching Protocols",
- "Upgrade: websocket",
- "Connection: Upgrade",
- "Sec-WebSocket-Accept: %s" % (response, )]
+ response = base64.b64encode(sha1(six.b(key) + PROTOCOL_GUID).digest())
+ handshake_reply = [b"HTTP/1.1 101 Switching Protocols",
+ b"Upgrade: websocket",
+ b"Connection: Upgrade",
+ b"Sec-WebSocket-Accept: " + response]
if negotiated_protocol:
- handshake_reply.append("Sec-WebSocket-Protocol: %s"
- % (negotiated_protocol, ))
- sock.sendall('\r\n'.join(handshake_reply) + '\r\n\r\n')
+ handshake_reply.append(b"Sec-WebSocket-Protocol: " + six.b(negotiated_protocol))
+ sock.sendall(b'\r\n'.join(handshake_reply) + b'\r\n\r\n')
return RFC6455WebSocket(sock, environ, self.protocol_version,
protocol=negotiated_protocol)
@@ -425,7 +426,7 @@ class RFC6455WebSocket(WebSocket):
return self.decoder.decode(data, final)
def _get_bytes(self, numbytes):
- data = ''
+ data = b''
while len(data) < numbytes:
d = self.socket.recv(numbytes - len(data))
if not d:
@@ -447,14 +448,14 @@ class RFC6455WebSocket(WebSocket):
self.data.append(data)
def getvalue(self):
- return ''.join(self.data)
+ return ('' if self.decoder else b'').join(self.data)
@staticmethod
def _apply_mask(data, mask, length=None, offset=0):
if length is None:
length = len(data)
cnt = range(length)
- return ''.join(chr(ord(data[i]) ^ mask[(offset + i) % 4]) for i in cnt)
+ return b''.join(six.int2byte(six.indexbytes(data, i) ^ mask[(offset + i) % 4]) for i in cnt)
def _handle_control_frame(self, opcode, data):
if opcode == 8: # connection close
@@ -609,12 +610,13 @@ class RFC6455WebSocket(WebSocket):
# NOTE: RFC6455 states:
# A server MUST NOT mask any frames that it sends to the client
rand = Random(time.time())
- mask = map(rand.getrandbits, (8, ) * 4)
+ mask = [rand.getrandbits(8) for _ in six.moves.xrange(4)]
message = RFC6455WebSocket._apply_mask(message, mask, length)
maskdata = struct.pack('!BBBB', *mask)
else:
- maskdata = ''
- return ''.join((header, lengthdata, maskdata, message))
+ maskdata = b''
+
+ return b''.join((header, lengthdata, maskdata, message))
def wait(self):
for i in self.iterator:
diff --git a/eventlet/wsgi.py b/eventlet/wsgi.py
index 94a2405..2f89cbb 100644
--- a/eventlet/wsgi.py
+++ b/eventlet/wsgi.py
@@ -116,11 +116,11 @@ class Input(object):
if length and length > self.content_length - self.position:
length = self.content_length - self.position
if not length:
- return ''
+ return b''
try:
read = reader(length)
except greenio.SSL.ZeroReturnError:
- read = ''
+ read = b''
self.position += len(read)
return read
@@ -189,7 +189,7 @@ class Input(object):
return self._do_read(self.rfile.readlines, hint)
def __iter__(self):
- return iter(self.read, '')
+ return iter(self.read, b'')
def get_socket(self):
return self.rfile._sock
@@ -226,7 +226,7 @@ class FileObjectForHeaders(object):
if size < 0:
sz = MAX_HEADER_LINE
rv = self.fp.readline(sz)
- if size < 0 and len(rv) >= MAX_HEADER_LINE:
+ if len(rv) >= MAX_HEADER_LINE:
raise HeaderLineTooLong()
self.total_header_size += len(rv)
if self.total_header_size > MAX_TOTAL_HEADER_SIZE:
@@ -267,8 +267,8 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
self.raw_requestline = self.rfile.readline(self.server.url_length_limit)
if len(self.raw_requestline) == self.server.url_length_limit:
self.wfile.write(
- "HTTP/1.0 414 Request URI Too Long\r\n"
- "Connection: close\r\nContent-length: 0\r\n\r\n")
+ b"HTTP/1.0 414 Request URI Too Long\r\n"
+ b"Connection: close\r\nContent-length: 0\r\n\r\n")
self.close_connection = 1
return
except greenio.SSL.ZeroReturnError:
@@ -289,14 +289,14 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
return
except HeaderLineTooLong:
self.wfile.write(
- "HTTP/1.0 400 Header Line Too Long\r\n"
- "Connection: close\r\nContent-length: 0\r\n\r\n")
+ b"HTTP/1.0 400 Header Line Too Long\r\n"
+ b"Connection: close\r\nContent-length: 0\r\n\r\n")
self.close_connection = 1
return
except HeadersTooLarge:
self.wfile.write(
- "HTTP/1.0 400 Headers Too Large\r\n"
- "Connection: close\r\nContent-length: 0\r\n\r\n")
+ b"HTTP/1.0 400 Headers Too Large\r\n"
+ b"Connection: close\r\nContent-length: 0\r\n\r\n")
self.close_connection = 1
return
finally:
@@ -308,8 +308,8 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
int(content_length)
except ValueError:
self.wfile.write(
- "HTTP/1.0 400 Bad Request\r\n"
- "Connection: close\r\nContent-length: 0\r\n\r\n")
+ b"HTTP/1.0 400 Bad Request\r\n"
+ b"Connection: close\r\nContent-length: 0\r\n\r\n")
self.close_connection = 1
return
@@ -345,13 +345,13 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
status, response_headers = headers_set
headers_sent.append(1)
header_list = [header[0].lower() for header in response_headers]
- towrite.append('%s %s\r\n' % (self.protocol_version, status))
+ towrite.append(six.b('%s %s\r\n' % (self.protocol_version, status)))
for header in response_headers:
- towrite.append('%s: %s\r\n' % header)
+ towrite.append(six.b('%s: %s\r\n' % header))
# send Date header?
if 'date' not in header_list:
- towrite.append('Date: %s\r\n' % (format_date_time(time.time()),))
+ towrite.append(six.b('Date: %s\r\n' % (format_date_time(time.time()),)))
client_conn = self.headers.get('Connection', '').lower()
send_keep_alive = False
@@ -369,21 +369,21 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
if 'content-length' not in header_list:
if self.request_version == 'HTTP/1.1':
use_chunked[0] = True
- towrite.append('Transfer-Encoding: chunked\r\n')
+ towrite.append(b'Transfer-Encoding: chunked\r\n')
elif 'content-length' not in header_list:
# client is 1.0 and therefore must read to EOF
self.close_connection = 1
if self.close_connection:
- towrite.append('Connection: close\r\n')
+ towrite.append(b'Connection: close\r\n')
elif send_keep_alive:
- towrite.append('Connection: keep-alive\r\n')
- towrite.append('\r\n')
+ towrite.append(b'Connection: keep-alive\r\n')
+ towrite.append(b'\r\n')
# end of header writing
if use_chunked[0]:
# Write the chunked encoding
- towrite.append("%x\r\n%s\r\n" % (len(data), data))
+ towrite.append(six.b("%x" % (len(data),)) + b"\r\n" + data + b"\r\n")
else:
towrite.append(data)
try:
@@ -450,15 +450,15 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
towrite.append(data)
towrite_size += len(data)
if towrite_size >= minimum_write_chunk_size:
- write(''.join(towrite))
+ write(b''.join(towrite))
towrite = []
just_written_size = towrite_size
towrite_size = 0
if towrite:
just_written_size = towrite_size
- write(''.join(towrite))
+ write(b''.join(towrite))
if not headers_sent or (use_chunked[0] and just_written_size):
- write('')
+ write(b'')
except Exception:
self.close_connection = 1
tb = traceback.format_exc()
@@ -476,7 +476,7 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
result.close()
if (self.environ['eventlet.input'].chunked_input or
self.environ['eventlet.input'].position
- < self.environ['eventlet.input'].content_length):
+ < self.environ['eventlet.input'].content_length or 0):
# Read and discard body if there was no pending 100-continue
if not self.environ['eventlet.input'].wfile:
# NOTE: MINIMUM_CHUNK_SIZE is used here for purpose different than chunking.
diff --git a/tests/api_test.py b/tests/api_test.py
index 8cb7410..e63dbd2 100644
--- a/tests/api_test.py
+++ b/tests/api_test.py
@@ -1,7 +1,8 @@
import os
-import socket
from unittest import TestCase, main
+from nose.tools import eq_
+
import eventlet
from eventlet import greenio, hubs, greenthread, spawn
from eventlet.green import ssl
@@ -51,9 +52,8 @@ class TestApi(TestCase):
client = eventlet.connect(('127.0.0.1', server.getsockname()[1]))
fd = client.makefile('rb')
client.close()
- assert fd.readline() == b'hello\n'
-
- assert fd.read() == b''
+ eq_(fd.readline(), b'hello\n')
+ eq_(fd.read(), b'')
fd.close()
check_hub()
@@ -80,7 +80,7 @@ class TestApi(TestCase):
raw_client = eventlet.connect(('127.0.0.1', server.getsockname()[1]))
client = ssl.wrap_socket(raw_client)
- fd = socket._fileobject(client, 'rb', 8192)
+ fd = client.makefile('rb', 8192)
assert fd.readline() == b'hello\r\n'
try:
diff --git a/tests/backdoor_test.py b/tests/backdoor_test.py
index f304d3f..6facffe 100644
--- a/tests/backdoor_test.py
+++ b/tests/backdoor_test.py
@@ -14,15 +14,15 @@ class BackdoorTest(LimitedTestCase):
client = socket.socket()
client.connect(('localhost', listener.getsockname()[1]))
f = client.makefile('rw')
- assert b'Python' in f.readline()
+ assert 'Python' in f.readline()
f.readline() # build info
f.readline() # help info
- assert b'InteractiveConsole' in f.readline()
- self.assertEqual(b'>>> ', f.read(4))
- f.write(b'print("hi")\n')
+ assert 'InteractiveConsole' in f.readline()
+ self.assertEqual('>>> ', f.read(4))
+ f.write('print("hi")\n')
f.flush()
- self.assertEqual(b'hi\n', f.readline())
- self.assertEqual(b'>>> ', f.read(4))
+ self.assertEqual('hi\n', f.readline())
+ self.assertEqual('>>> ', f.read(4))
f.close()
client.close()
serv.kill()
diff --git a/tests/convenience_test.py b/tests/convenience_test.py
index 83726bc..194699c 100644
--- a/tests/convenience_test.py
+++ b/tests/convenience_test.py
@@ -125,8 +125,8 @@ class TestServe(LimitedTestCase):
eventlet.spawn(eventlet.serve, server, handle)
client = eventlet.wrap_ssl(eventlet.connect(('localhost', port)))
- client.sendall("echo")
- self.assertEqual("echo", client.recv(1024))
+ client.sendall(b"echo")
+ self.assertEqual(b"echo", client.recv(1024))
def test_socket_reuse(self):
lsock1 = eventlet.listen(('localhost', 0))
diff --git a/tests/env_test.py b/tests/env_test.py
index 4888e9d..f8931c1 100644
--- a/tests/env_test.py
+++ b/tests/env_test.py
@@ -1,4 +1,5 @@
import os
+from eventlet.support import six
from tests.patcher_test import ProcessBase
from tests import skip_with_pyevent
diff --git a/tests/greenio_test.py b/tests/greenio_test.py
index c56b946..ba3a826 100644
--- a/tests/greenio_test.py
+++ b/tests/greenio_test.py
@@ -450,7 +450,7 @@ class TestGreenSocket(LimitedTestCase):
def sender(evt):
s2, addr = server.accept()
- wrap_wfile = s2.makefile('w')
+ wrap_wfile = s2.makefile('wb')
eventlet.sleep(0.02)
wrap_wfile.write(b'hi')
@@ -627,7 +627,7 @@ class TestGreenPipe(LimitedTestCase):
wf = greenio.GreenPipe(w, 'w', 0)
def sender(f, content):
- for ch in content:
+ for ch in map(six.int2byte, six.iterbytes(content)):
eventlet.sleep(0.0001)
f.write(ch)
f.close()
@@ -638,7 +638,7 @@ class TestGreenPipe(LimitedTestCase):
line = rf.readline()
eventlet.sleep(0.01)
self.assertEqual(line, one_line)
- self.assertEqual(rf.readline(), '')
+ self.assertEqual(rf.readline(), b'')
def test_pipe_read(self):
# ensure that 'readline' works properly on GreenPipes when data is not
@@ -663,10 +663,10 @@ class TestGreenPipe(LimitedTestCase):
eventlet.sleep(0)
line = r.readline()
- self.assertEqual(line, 'line\n')
+ self.assertEqual(line, b'line\n')
line = r.readline()
- self.assertEqual(line, 'line\r\n')
+ self.assertEqual(line, b'line\r\n')
gt.wait()
@@ -676,7 +676,7 @@ class TestGreenPipe(LimitedTestCase):
r = greenio.GreenPipe(r)
w = greenio.GreenPipe(w, 'w')
- large_message = b"".join([1024 * chr(i) for i in range(65)])
+ large_message = b"".join([1024 * six.int2byte(i) for i in range(65)])
def writer():
w.write(large_message)
diff --git a/tests/mysqldb_test_monkey_patch.py b/tests/mysqldb_test_monkey_patch.py
index 2d9c0e7..a76178e 100644
--- a/tests/mysqldb_test_monkey_patch.py
+++ b/tests/mysqldb_test_monkey_patch.py
@@ -1,12 +1,12 @@
from __future__ import print_function
-import MySQLdb as m
from eventlet import patcher
-from eventlet.green import MySQLdb as gm
# no standard tests in this file, ignore
__test__ = False
if __name__ == '__main__':
+ import MySQLdb as m
+ from eventlet.green import MySQLdb as gm
patcher.monkey_patch(all=True, MySQLdb=True)
print("mysqltest {0}".format(",".join(sorted(patcher.already_patched.keys()))))
print("connect {0}".format(m.connect == gm.connect))
diff --git a/tests/patcher_test.py b/tests/patcher_test.py
index c575a80..f80b589 100644
--- a/tests/patcher_test.py
+++ b/tests/patcher_test.py
@@ -3,12 +3,16 @@ import shutil
import sys
import tempfile
+from eventlet.support import six
from tests import LimitedTestCase, main, run_python, skip_with_pyevent
base_module_contents = """
import socket
-import urllib
+try:
+ import urllib.request as urllib
+except ImportError:
+ import urllib
print("base {0} {1}".format(socket, urllib))
"""
@@ -45,14 +49,18 @@ class ProcessBase(LimitedTestCase):
filename = os.path.join(self.tempdir, name)
if not filename.endswith('.py'):
filename = filename + '.py'
- fd = open(filename, "wb")
- fd.write(contents)
- fd.close()
+ with open(filename, "w") as fd:
+ fd.write(contents)
def launch_subprocess(self, filename):
path = os.path.join(self.tempdir, filename)
output = run_python(path)
- lines = output.split("\n")
+ if six.PY3:
+ output = output.decode('utf-8')
+ separator = '\n'
+ else:
+ separator = b'\n'
+ lines = output.split(separator)
return output, lines
def run_script(self, contents, modname=None):
@@ -98,7 +106,10 @@ class MonkeyPatch(ProcessBase):
from eventlet import patcher
patcher.monkey_patch()
import socket
-import urllib
+try:
+ import urllib.request as urllib
+except ImportError:
+ import urllib
print("newmod {0} {1}".format(socket.socket, urllib.socket.socket))
"""
self.write_to_tempfile("newmod", new_mod)
diff --git a/tests/websocket_new_test.py b/tests/websocket_new_test.py
index ec29fc6..95d36b5 100644
--- a/tests/websocket_new_test.py
+++ b/tests/websocket_new_test.py
@@ -1,11 +1,15 @@
import errno
import struct
+from nose.tools import eq_
+
import eventlet
from eventlet import event
from eventlet import websocket
from eventlet.green import httplib
from eventlet.green import socket
+from eventlet import websocket
+from eventlet.support import six
from tests.wsgi_test import _TestBase
@@ -51,7 +55,7 @@ class TestWebSocket(_TestBase):
self.assertEqual(resp.status, 400)
self.assertEqual(resp.getheader('connection'), 'close')
- self.assertEqual(resp.read(), '')
+ self.assertEqual(resp.read(), b'')
# Now, miss off key
headers = dict(kv.split(': ') for kv in [
@@ -67,7 +71,7 @@ class TestWebSocket(_TestBase):
self.assertEqual(resp.status, 400)
self.assertEqual(resp.getheader('connection'), 'close')
- self.assertEqual(resp.read(), '')
+ self.assertEqual(resp.read(), b'')
# No Upgrade now
headers = dict(kv.split(': ') for kv in [
@@ -82,7 +86,7 @@ class TestWebSocket(_TestBase):
self.assertEqual(resp.status, 400)
self.assertEqual(resp.getheader('connection'), 'close')
- self.assertEqual(resp.read(), '')
+ self.assertEqual(resp.read(), b'')
def test_correct_upgrade_request_13(self):
for http_connection in ['Upgrade', 'UpGrAdE', 'keep-alive, Upgrade']:
@@ -97,16 +101,16 @@ class TestWebSocket(_TestBase):
]
sock = eventlet.connect(('localhost', self.port))
- sock.sendall('\r\n'.join(connect) + '\r\n\r\n')
+ sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
result = sock.recv(1024)
# The server responds the correct Websocket handshake
print('Connection string: %r' % http_connection)
- self.assertEqual(result, '\r\n'.join([
+ self.assertEqual(result, six.b('\r\n'.join([
'HTTP/1.1 101 Switching Protocols',
'Upgrade: websocket',
'Connection: Upgrade',
'Sec-WebSocket-Accept: ywSyWXCPNsDxLrQdQrn5RFNRfBU=\r\n\r\n',
- ]))
+ ])))
def test_send_recv_13(self):
connect = [
@@ -121,15 +125,15 @@ class TestWebSocket(_TestBase):
sock = eventlet.connect(
('localhost', self.port))
- sock.sendall('\r\n'.join(connect) + '\r\n\r\n')
+ sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
sock.recv(1024)
ws = websocket.RFC6455WebSocket(sock, {}, client=True)
- ws.send('hello')
- assert ws.wait() == 'hello'
- ws.send('hello world!\x01')
+ ws.send(b'hello')
+ eq_(ws.wait(), b'hello')
+ ws.send(b'hello world!\x01')
ws.send(u'hello world again!')
- assert ws.wait() == 'hello world!\x01'
- assert ws.wait() == u'hello world again!'
+ eq_(ws.wait(), b'hello world!\x01')
+ eq_(ws.wait(), u'hello world again!')
ws.close()
eventlet.sleep(0.01)
@@ -160,7 +164,7 @@ class TestWebSocket(_TestBase):
]
sock = eventlet.connect(
('localhost', self.port))
- sock.sendall('\r\n'.join(connect) + '\r\n\r\n')
+ sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
sock.recv(1024) # get the headers
sock.close() # close while the app is running
done_with_request.wait()
@@ -193,7 +197,7 @@ class TestWebSocket(_TestBase):
]
sock = eventlet.connect(
('localhost', self.port))
- sock.sendall('\r\n'.join(connect) + '\r\n\r\n')
+ sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
sock.recv(1024) # get the headers
closeframe = struct.pack('!BBIH', 1 << 7 | 8, 1 << 7 | 2, 0, 1000)
sock.sendall(closeframe) # "Close the connection" packet.
@@ -227,8 +231,8 @@ class TestWebSocket(_TestBase):
]
sock = eventlet.connect(
('localhost', self.port))
- sock.sendall('\r\n'.join(connect) + '\r\n\r\n')
+ sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
sock.recv(1024) # get the headers
- sock.sendall('\x07\xff') # Weird packet.
+ sock.sendall(b'\x07\xff') # Weird packet.
done_with_request.wait()
assert not error_detected[0]
diff --git a/tests/wsgi_test.py b/tests/wsgi_test.py
index 4ebf136..9765076 100644
--- a/tests/wsgi_test.py
+++ b/tests/wsgi_test.py
@@ -27,6 +27,13 @@ import tests
certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt')
private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
+if six.PY3:
+ def bytes_to_str(b):
+ return b.decode()
+else:
+ def bytes_to_str(b):
+ return b
+
HttpReadResult = collections.namedtuple(
'HttpReadResult',
@@ -36,17 +43,17 @@ HttpReadResult = collections.namedtuple(
def hello_world(env, start_response):
if env['PATH_INFO'] == 'notexist':
start_response('404 Not Found', [('Content-type', 'text/plain')])
- return ["not found"]
+ return [b"not found"]
start_response('200 OK', [('Content-type', 'text/plain')])
- return ["hello world"]
+ return [b"hello world"]
def chunked_app(env, start_response):
start_response('200 OK', [('Content-type', 'text/plain')])
- yield "this"
- yield "is"
- yield "chunked"
+ yield b"this"
+ yield b"is"
+ yield b"chunked"
def chunked_fail_app(environ, start_response):
@@ -56,8 +63,8 @@ def chunked_fail_app(environ, start_response):
start_response('200 OK', headers)
# We start streaming data just fine.
- yield "The dwarves of yore made mighty spells,"
- yield "While hammers fell like ringing bells"
+ yield b"The dwarves of yore made mighty spells,"
+ yield b"While hammers fell like ringing bells"
# Then the back-end fails!
try:
@@ -67,13 +74,13 @@ def chunked_fail_app(environ, start_response):
return
# So rest of the response data is not available.
- yield "In places deep, where dark things sleep,"
- yield "In hollow halls beneath the fells."
+ yield b"In places deep, where dark things sleep,"
+ yield b"In hollow halls beneath the fells."
def big_chunks(env, start_response):
start_response('200 OK', [('Content-type', 'text/plain')])
- line = 'a' * 8192
+ line = b'a' * 8192
for x in range(10):
yield line
@@ -150,11 +157,13 @@ class ConnectionClosed(Exception):
def read_http(sock):
- fd = sock.makefile()
+ fd = sock.makefile('rb')
try:
- response_line = fd.readline().rstrip('\r\n')
+ response_line = bytes_to_str(fd.readline().rstrip(b'\r\n'))
except socket.error as exc:
- if support.get_errno(exc) == 10053:
+ # TODO find out whether 54 is ok here or not, I see it when running tests
+ # on Python 3
+ if support.get_errno(exc) in (10053, 54):
raise ConnectionClosed
raise
if not response_line:
@@ -163,7 +172,7 @@ def read_http(sock):
header_lines = []
while True:
line = fd.readline()
- if line == '\r\n':
+ if line == b'\r\n':
break
else:
header_lines.append(line)
@@ -174,7 +183,7 @@ def read_http(sock):
x = x.strip()
if not x:
continue
- key, value = x.split(':', 1)
+ key, value = bytes_to_str(x).split(':', 1)
key = key.rstrip()
value = value.lstrip()
key_lower = key.lower()
@@ -256,20 +265,20 @@ class TestHttpd(_TestBase):
sock = eventlet.connect(
('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
fd.flush()
result = fd.read()
fd.close()
# The server responds with the maximum version it supports
- assert result.startswith('HTTP'), result
- assert result.endswith('hello world'), result
+ assert result.startswith(b'HTTP'), result
+ assert result.endswith(b'hello world'), result
def test_002_keepalive(self):
sock = eventlet.connect(
('localhost', self.port))
- fd = sock.makefile('w')
+ fd = sock.makefile('wb')
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fd.flush()
read_http(sock)
@@ -284,7 +293,7 @@ class TestHttpd(_TestBase):
sock = eventlet.connect(
('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fd.flush()
cancel = eventlet.Timeout(1, RuntimeError)
@@ -296,7 +305,7 @@ class TestHttpd(_TestBase):
sock = eventlet.connect(
('localhost', self.port))
- fd = sock.makefile('w')
+ fd = sock.makefile('wb')
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fd.flush()
read_http(sock)
@@ -323,8 +332,8 @@ class TestHttpd(_TestBase):
for ii in range(3000):
path_parts.append('path')
path = '/'.join(path_parts)
- request = 'GET /%s HTTP/1.0\r\nHost: localhost\r\n\r\n' % path
- fd = sock.makefile('rw')
+ request = ('GET /%s HTTP/1.0\r\nHost: localhost\r\n\r\n' % path).encode()
+ fd = sock.makefile('rwb')
fd.write(request)
fd.flush()
result = fd.readline()
@@ -352,8 +361,8 @@ class TestHttpd(_TestBase):
'Content-Length: 3',
'',
'a=a'))
- fd = sock.makefile('w')
- fd.write(request)
+ fd = sock.makefile('wb')
+ fd.write(request.encode())
fd.flush()
# send some junk after the actual request
@@ -365,7 +374,7 @@ class TestHttpd(_TestBase):
def test_008_correctresponse(self):
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('w')
+ fd = sock.makefile('wb')
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fd.flush()
result_200 = read_http(sock)
@@ -384,37 +393,37 @@ class TestHttpd(_TestBase):
sock = eventlet.connect(
('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
fd.flush()
- assert 'Transfer-Encoding: chunked' in fd.read()
+ assert b'Transfer-Encoding: chunked' in fd.read()
def test_010_no_chunked_http_1_0(self):
self.site.application = chunked_app
sock = eventlet.connect(
('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n')
fd.flush()
- assert 'Transfer-Encoding: chunked' not in fd.read()
+ assert b'Transfer-Encoding: chunked' not in fd.read()
def test_011_multiple_chunks(self):
self.site.application = big_chunks
sock = eventlet.connect(
('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
fd.flush()
- headers = ''
+ headers = b''
while True:
line = fd.readline()
- if line == '\r\n':
+ if line == b'\r\n':
break
else:
headers += line
- assert 'Transfer-Encoding: chunked' in headers
+ assert b'Transfer-Encoding: chunked' in headers
chunks = 0
chunklen = int(fd.readline(), 16)
while chunklen:
@@ -473,52 +482,52 @@ class TestHttpd(_TestBase):
def test_014_chunked_post(self):
self.site.application = chunked_post
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write('PUT /a HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n'
'Transfer-Encoding: chunked\r\n\r\n'
'2\r\noh\r\n4\r\n hai\r\n0\r\n\r\n'.encode())
fd.flush()
while True:
- if fd.readline() == '\r\n':
+ if fd.readline() == b'\r\n':
break
response = fd.read()
- assert response == 'oh hai', 'invalid response %s' % response
+ assert response == b'oh hai', 'invalid response %s' % response
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write('PUT /b HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n'
'Transfer-Encoding: chunked\r\n\r\n'
'2\r\noh\r\n4\r\n hai\r\n0\r\n\r\n'.encode())
fd.flush()
while True:
- if fd.readline() == '\r\n':
+ if fd.readline() == b'\r\n':
break
response = fd.read()
- assert response == 'oh hai', 'invalid response %s' % response
+ assert response == b'oh hai', 'invalid response %s' % response
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write('PUT /c HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n'
'Transfer-Encoding: chunked\r\n\r\n'
'2\r\noh\r\n4\r\n hai\r\n0\r\n\r\n'.encode())
fd.flush()
while True:
- if fd.readline() == '\r\n':
+ if fd.readline() == b'\r\n':
break
response = fd.read(8192)
- assert response == 'oh hai', 'invalid response %s' % response
+ assert response == b'oh hai', 'invalid response %s' % response
def test_015_write(self):
self.site.application = use_write
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('w')
+ fd = sock.makefile('wb')
fd.write(b'GET /a HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
fd.flush()
result1 = read_http(sock)
assert 'content-length' in result1.headers_lower
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('w')
+ fd = sock.makefile('wb')
fd.write(b'GET /b HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
fd.flush()
result2 = read_http(sock)
@@ -531,21 +540,21 @@ class TestHttpd(_TestBase):
"""
def wsgi_app(environ, start_response):
start_response('200 OK', [('Content-Length', '7')])
- return ['testing']
+ return [b'testing']
self.site.application = wsgi_app
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET /a HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
fd.flush()
header_lines = []
while True:
line = fd.readline()
- if line == '\r\n':
+ if line == b'\r\n':
break
else:
header_lines.append(line)
self.assertEqual(1, len(
- [l for l in header_lines if l.lower().startswith('content-length')]))
+ [l for l in header_lines if l.lower().startswith(b'content-length')]))
@tests.skip_if_no_ssl
def test_017_ssl_zeroreturnerror(self):
@@ -588,7 +597,7 @@ class TestHttpd(_TestBase):
sock = eventlet.connect(
('localhost', self.port))
- fd = sock.makefile('w')
+ fd = sock.makefile('wb')
fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\nConnection: keep-alive\r\n\r\n')
fd.flush()
@@ -607,13 +616,13 @@ class TestHttpd(_TestBase):
def use_fieldstorage(environ, start_response):
cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)
start_response('200 OK', [('Content-type', 'text/plain')])
- return ['hello!']
+ return [b'hello!']
self.site.application = use_fieldstorage
sock = eventlet.connect(
('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write('POST / HTTP/1.1\r\n'
'Host: localhost\r\n'
'Connection: close\r\n'
@@ -621,7 +630,7 @@ class TestHttpd(_TestBase):
'2\r\noh\r\n'
'4\r\n hai\r\n0\r\n\r\n'.encode())
fd.flush()
- assert 'hello!' in fd.read()
+ assert b'hello!' in fd.read()
def test_020_x_forwarded_for(self):
request_bytes = (
@@ -654,13 +663,13 @@ class TestHttpd(_TestBase):
self.spawn_server(sock=server_sock_2)
# do a single req/response to verify it's up
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
fd.flush()
result = fd.read(1024)
fd.close()
- assert result.startswith('HTTP'), result
- assert result.endswith('hello world')
+ assert result.startswith(b'HTTP'), result
+ assert result.endswith(b'hello world'), result
# shut down the server and verify the server_socket fd is still open,
# but the actual socketobject passed in to wsgi.server is closed
@@ -673,13 +682,13 @@ class TestHttpd(_TestBase):
self.assertEqual(support.get_errno(exc), errno.EBADF)
self.spawn_server(sock=server_sock)
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
fd.flush()
result = fd.read(1024)
fd.close()
- assert result.startswith('HTTP'), result
- assert result.endswith('hello world')
+ assert result.startswith(b'HTTP'), result
+ assert result.endswith(b'hello world'), result
def test_021_environ_clobbering(self):
def clobberin_time(environ, start_response):
@@ -695,13 +704,13 @@ class TestHttpd(_TestBase):
return []
self.site.application = clobberin_time
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write('GET / HTTP/1.1\r\n'
'Host: localhost\r\n'
'Connection: close\r\n'
'\r\n\r\n'.encode())
fd.flush()
- assert '200 OK' in fd.read()
+ assert b'200 OK' in fd.read()
def test_022_custom_pool(self):
# just test that it accepts the parameter for now
@@ -713,44 +722,44 @@ class TestHttpd(_TestBase):
# this stuff is copied from test_001_server, could be better factored
sock = eventlet.connect(
('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n')
fd.flush()
result = fd.read()
fd.close()
- assert result.startswith('HTTP'), result
- assert result.endswith('hello world')
+ assert result.startswith(b'HTTP'), result
+ assert result.endswith(b'hello world'), result
def test_023_bad_content_length(self):
sock = eventlet.connect(
('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET / HTTP/1.0\r\nHost: localhost\r\nContent-length: argh\r\n\r\n')
fd.flush()
result = fd.read()
fd.close()
- assert result.startswith('HTTP'), result
- assert '400 Bad Request' in result
- assert '500' not in result
+ assert result.startswith(b'HTTP'), result
+ assert b'400 Bad Request' in result, result
+ assert b'500' not in result, result
def test_024_expect_100_continue(self):
def wsgi_app(environ, start_response):
if int(environ['CONTENT_LENGTH']) > 1024:
start_response('417 Expectation Failed', [('Content-Length', '7')])
- return ['failure']
+ return [b'failure']
else:
text = environ['wsgi.input'].read()
start_response('200 OK', [('Content-Length', str(len(text)))])
return [text]
self.site.application = wsgi_app
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'PUT / HTTP/1.1\r\nHost: localhost\r\nContent-length: 1025\r\n'
b'Expect: 100-continue\r\n\r\n')
fd.flush()
result = read_http(sock)
self.assertEqual(result.status, 'HTTP/1.1 417 Expectation Failed')
- self.assertEqual(result.body, 'failure')
+ self.assertEqual(result.body, b'failure')
fd.write(
b'PUT / HTTP/1.1\r\nHost: localhost\r\nContent-length: 7\r\n'
b'Expect: 100-continue\r\n\r\ntesting')
@@ -758,7 +767,7 @@ class TestHttpd(_TestBase):
header_lines = []
while True:
line = fd.readline()
- if line == '\r\n':
+ if line == b'\r\n':
break
else:
header_lines.append(line)
@@ -766,12 +775,12 @@ class TestHttpd(_TestBase):
header_lines = []
while True:
line = fd.readline()
- if line == '\r\n':
+ if line == b'\r\n':
break
else:
header_lines.append(line)
assert header_lines[0].startswith('HTTP/1.1 200 OK')
- self.assertEqual(fd.read(7), 'testing')
+ assert fd.read(7) == b'testing'
fd.close()
sock.close()
@@ -871,7 +880,7 @@ class TestHttpd(_TestBase):
result = read_http(sock)
self.assertEqual(result.headers_lower['connection'], 'close')
self.assertNotEqual(result.headers_lower.get('transfer-encoding'), 'chunked')
- self.assertEqual(result.body, "thisischunked")
+ self.assertEqual(result.body, b"thisischunked")
def test_minimum_chunk_size_parameter_leaves_httpprotocol_class_member_intact(self):
start_size = wsgi.HttpProtocol.minimum_chunk_size
@@ -902,7 +911,7 @@ class TestHttpd(_TestBase):
self.assertEqual(result.body, expected_body)
# verify that socket is closed by server
- self.assertEqual(sock.recv(1), '')
+ self.assertEqual(sock.recv(1), b'')
def test_026_http_10_nokeepalive(self):
# verify that if an http/1.0 client sends connection: keep-alive
@@ -918,7 +927,7 @@ class TestHttpd(_TestBase):
def test_027_keepalive_chunked(self):
self.site.application = chunked_post
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('w')
+ fd = sock.makefile('wb')
common_suffix = (
b'Host: localhost\r\nTransfer-Encoding: chunked\r\n\r\n' +
b'10\r\n0123456789abcdef\r\n0\r\n\r\n')
@@ -995,13 +1004,13 @@ class TestHttpd(_TestBase):
env['eventlet.posthooks'].append(
(posthook1, (2,), {'multiplier': 3}))
start_response('200 OK', [('Content-Type', 'text/plain')])
- yield ''
+ yield b''
self.site.application = one_posthook_app
sock = eventlet.connect(('localhost', self.port))
- fp = sock.makefile('rw')
+ fp = sock.makefile('rwb')
fp.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fp.flush()
- self.assertEqual(fp.readline(), 'HTTP/1.1 200 OK\r\n')
+ self.assertEqual(fp.readline(), b'HTTP/1.1 200 OK\r\n')
fp.close()
sock.close()
self.assertEqual(posthook1_count[0], 6)
@@ -1018,13 +1027,13 @@ class TestHttpd(_TestBase):
env['eventlet.posthooks'].append(
(posthook2, (100,), {'divisor': 4}))
start_response('200 OK', [('Content-Type', 'text/plain')])
- yield ''
+ yield b''
self.site.application = two_posthook_app
sock = eventlet.connect(('localhost', self.port))
- fp = sock.makefile('rw')
+ fp = sock.makefile('rwb')
fp.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fp.flush()
- self.assertEqual(fp.readline(), 'HTTP/1.1 200 OK\r\n')
+ self.assertEqual(fp.readline(), b'HTTP/1.1 200 OK\r\n')
fp.close()
sock.close()
self.assertEqual(posthook1_count[0], 26)
@@ -1034,7 +1043,7 @@ class TestHttpd(_TestBase):
sock = eventlet.connect(('localhost', self.port))
request = 'GET / HTTP/1.0\r\nHost: localhost\r\nLong: %s\r\n\r\n' % \
('a' * 10000)
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(request.encode())
fd.flush()
result = read_http(sock)
@@ -1065,7 +1074,7 @@ class TestHttpd(_TestBase):
yield chunk
self.site.application = echo_by_iterating
- upload_data = '123456789abcdef' * 100
+ upload_data = b'123456789abcdef' * 100
request = (
'POST / HTTP/1.0\r\n'
'Host: localhost\r\n'
@@ -1089,20 +1098,20 @@ class TestHttpd(_TestBase):
sock = eventlet.connect(
('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
fd.flush()
- response = fd.read().split('\r\n')
+ response = fd.read().split(b'\r\n')
headers = []
while True:
h = response.pop(0)
headers.append(h)
if h == '':
break
- assert 'Transfer-Encoding: chunked' in ''.join(headers)
+ assert b'Transfer-Encoding: chunked' in ''.join(headers)
# should only be one chunk of zero size with two blank lines
# (one terminates the chunk, one terminates the body)
- self.assertEqual(response, ['0', '', ''])
+ self.assertEqual(response, [b'0', b'', b''])
def test_configurable_url_length_limit(self):
self.spawn_server(url_length_limit=20000)
@@ -1110,15 +1119,15 @@ class TestHttpd(_TestBase):
('localhost', self.port))
path = 'x' * 15000
request = 'GET /%s HTTP/1.0\r\nHost: localhost\r\n\r\n' % path
- fd = sock.makefile('rw')
- fd.write(request)
+ fd = sock.makefile('rwb')
+ fd.write(request.encode())
fd.flush()
result = fd.readline()
if result:
# windows closes the socket before the data is flushed,
# so we never get anything back
- status = result.split(' ')[1]
- self.assertEqual(status, '200')
+ status = result.split(b' ')[1]
+ self.assertEqual(status, b'200')
fd.close()
def test_aborted_chunked_post(self):
@@ -1130,7 +1139,7 @@ class TestHttpd(_TestBase):
content = env['wsgi.input'].read(1024)
except IOError:
blew_up[0] = True
- content = 'ok'
+ content = b'ok'
read_content.send(content)
start_response('200 OK', [('Content-Type', 'text/plain')])
return [content]
@@ -1147,7 +1156,7 @@ class TestHttpd(_TestBase):
sock.close()
# the test passes if we successfully get here, and read all the data
# in spite of the early close
- self.assertEqual(read_content.wait(), 'ok')
+ self.assertEqual(read_content.wait(), b'ok')
assert blew_up[0]
def test_exceptions_close_connection(self):
@@ -1155,7 +1164,7 @@ class TestHttpd(_TestBase):
raise RuntimeError("intentional error")
self.site.application = wsgi_app
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fd.flush()
result = read_http(sock)
@@ -1170,13 +1179,13 @@ class TestHttpd(_TestBase):
yield u"non-encodable unicode: \u0230"
self.site.application = wsgi_app
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
fd.flush()
result = read_http(sock)
self.assertEqual(result.status, 'HTTP/1.1 500 Internal Server Error')
self.assertEqual(result.headers_lower['connection'], 'close')
- assert 'unicode' in result.body
+ assert b'unicode' in result.body
def test_path_info_decoding(self):
def wsgi_app(environ, start_response):
@@ -1185,13 +1194,13 @@ class TestHttpd(_TestBase):
yield "raw: %s" % environ['RAW_PATH_INFO']
self.site.application = wsgi_app
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET /a*b@%40%233 HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
fd.flush()
result = read_http(sock)
self.assertEqual(result.status, 'HTTP/1.1 200 OK')
- assert 'decoded: /a*b@@#3' in result.body
- assert 'raw: /a*b@%40%233' in result.body
+ assert b'decoded: /a*b@@#3' in result.body
+ assert b'raw: /a*b@%40%233' in result.body
def test_ipv6(self):
try:
@@ -1224,12 +1233,12 @@ class TestHttpd(_TestBase):
self.site.application = crasher
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('w')
+ fd = sock.makefile('wb')
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fd.flush()
result1 = read_http(sock)
self.assertEqual(result1.status, 'HTTP/1.1 500 Internal Server Error')
- self.assertEqual(result1.body, '')
+ self.assertEqual(result1.body, b'')
self.assertEqual(result1.headers_lower['connection'], 'close')
assert 'transfer-encoding' not in result1.headers_lower
@@ -1237,14 +1246,14 @@ class TestHttpd(_TestBase):
self.spawn_server(debug=True)
self.site.application = crasher
sock = eventlet.connect(('localhost', self.port))
- fd = sock.makefile('w')
+ fd = sock.makefile('wb')
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fd.flush()
result2 = read_http(sock)
self.assertEqual(result2.status, 'HTTP/1.1 500 Internal Server Error')
- assert 'intentional crash' in result2.body
- assert 'RuntimeError' in result2.body
- assert 'Traceback' in result2.body
+ assert b'intentional crash' in result2.body, result2.body
+ assert b'RuntimeError' in result2.body, result2.body
+ assert b'Traceback' in result2.body, result2.body
self.assertEqual(result2.headers_lower['connection'], 'close')
assert 'transfer-encoding' not in result2.headers_lower
@@ -1253,7 +1262,7 @@ class TestHttpd(_TestBase):
"""
def long_response(environ, start_response):
start_response('200 OK', [('Content-Length', '9876')])
- yield 'a' * 9876
+ yield b'a' * 9876
server_sock = eventlet.listen(('localhost', 0))
self.port = server_sock.getsockname()[1]
@@ -1366,7 +1375,7 @@ class IterableAlreadyHandledTest(_TestBase):
sock = eventlet.connect(
('localhost', self.port))
- fd = sock.makefile('rw')
+ fd = sock.makefile('rwb')
fd.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fd.flush()
@@ -1378,7 +1387,7 @@ class IterableAlreadyHandledTest(_TestBase):
result = read_http(sock)
self.assertEqual(result.status, 'HTTP/1.1 200 OK')
self.assertEqual(result.headers_lower.get('transfer-encoding'), 'chunked')
- self.assertEqual(result.body, '0\r\n\r\n') # Still coming back chunked
+ self.assertEqual(result.body, b'0\r\n\r\n') # Still coming back chunked
class ProxiedIterableAlreadyHandledTest(IterableAlreadyHandledTest):
@@ -1418,13 +1427,13 @@ class TestChunkedInput(_TestBase):
self.yield_next_space = False
def response_iter():
- yield ' '
+ yield b' '
num_sleeps = 0
while not self.yield_next_space and num_sleeps < 200:
eventlet.sleep(.01)
num_sleeps += 1
- yield ' '
+ yield b' '
start_response('200 OK',
[('Content-Type', 'text/plain'),
@@ -1467,7 +1476,7 @@ class TestChunkedInput(_TestBase):
fd = self.connect()
fd.sendall(req.encode())
- self.assertEqual(read_http(fd).body, "this is ch")
+ self.assertEqual(read_http(fd).body, b"this is ch")
self.ping(fd)
fd.close()
@@ -1478,7 +1487,7 @@ class TestChunkedInput(_TestBase):
"Content-Length:0\r\n\r\n" + body
fd = self.connect()
fd.sendall(req.encode())
- self.assertEqual(read_http(fd).body, "this is ch")
+ self.assertEqual(read_http(fd).body, b"this is ch")
self.ping(fd)
fd.close()
@@ -1489,7 +1498,7 @@ class TestChunkedInput(_TestBase):
fd = self.connect()
fd.sendall(req.encode())
- self.assertEqual(read_http(fd).body, "this is ch")
+ self.assertEqual(read_http(fd).body, b"this is ch")
self.ping(fd)
fd.close()
@@ -1500,7 +1509,7 @@ class TestChunkedInput(_TestBase):
fd = self.connect()
fd.sendall(req.encode())
- self.assertEqual(read_http(fd).body, "pong")
+ self.assertEqual(read_http(fd).body, b"pong")
self.ping(fd)
fd.close()
@@ -1512,7 +1521,7 @@ class TestChunkedInput(_TestBase):
fd = self.connect()
fd.sendall(req.encode())
- self.assertEqual(read_http(fd).body, 'this is chunked\nline 2\nline3')
+ self.assertEqual(read_http(fd).body, b'this is chunked\nline 2\nline3')
fd.close()
def test_chunked_readline_wsgi_override_minimum_chunk_size(self):
@@ -1527,7 +1536,7 @@ class TestChunkedInput(_TestBase):
resp_so_far += one_byte
if resp_so_far.endswith('\r\n\r\n'):
break
- self.assertEqual(fd.recv(1), ' ')
+ self.assertEqual(fd.recv(1), b' ')
try:
with eventlet.Timeout(.1):
fd.recv(1)
@@ -1538,22 +1547,22 @@ class TestChunkedInput(_TestBase):
self.yield_next_space = True
with eventlet.Timeout(.1):
- self.assertEqual(fd.recv(1), ' ')
+ self.assertEqual(fd.recv(1), b' ')
def test_chunked_readline_wsgi_not_override_minimum_chunk_size(self):
fd = self.connect()
fd.sendall(b"POST /yield_spaces HTTP/1.1\r\nContent-Length: 0\r\n\r\n")
- resp_so_far = ''
+ resp_so_far = b''
try:
with eventlet.Timeout(.1):
while True:
one_byte = fd.recv(1)
resp_so_far += one_byte
- if resp_so_far.endswith('\r\n\r\n'):
+ if resp_so_far.endswith(b'\r\n\r\n'):
break
- self.assertEqual(fd.recv(1), ' ')
+ self.assertEqual(fd.recv(1), b' ')
except eventlet.Timeout:
pass
else:
diff --git a/tests/wsgi_test_conntimeout.py b/tests/wsgi_test_conntimeout.py
index 91a690f..d925a04 100644
--- a/tests/wsgi_test_conntimeout.py
+++ b/tests/wsgi_test_conntimeout.py
@@ -136,7 +136,7 @@ if __name__ == '__main__':
# req #1 - normal
sock1 = eventlet.connect(server_addr)
sock1.settimeout(0.1)
- fd1 = sock1.makefile('rw')
+ fd1 = sock1.makefile('rwb')
fd1.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fd1.flush()
tests.wsgi_test.read_http(sock1)