Python 3 compat: Improve subprocess, WSGI and tests
This commit is contained in:
@@ -21,7 +21,7 @@ if getattr(subprocess_orig, 'TimeoutExpired', None) is None:
|
||||
a child process.
|
||||
"""
|
||||
|
||||
def __init__(self, cmd, output=None):
|
||||
def __init__(self, timeout, cmd, output=None):
|
||||
self.cmd = cmd
|
||||
self.output = output
|
||||
|
||||
@@ -64,7 +64,7 @@ class Popen(subprocess_orig.Popen):
|
||||
if status is not None:
|
||||
return status
|
||||
if timeout is not None and time.time() > endtime:
|
||||
raise TimeoutExpired(self.args)
|
||||
raise TimeoutExpired(self.args, timeout)
|
||||
eventlet.sleep(check_interval)
|
||||
except OSError as e:
|
||||
if e.errno == errno.ECHILD:
|
||||
|
@@ -100,7 +100,7 @@ class Timeout(BaseException):
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
>>> raise Timeout
|
||||
>>> raise Timeout # doctest: +IGNORE_EXCEPTION_DETAIL
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
Timeout
|
||||
|
@@ -99,10 +99,10 @@ class Input(object):
|
||||
if self.hundred_continue_headers is not None:
|
||||
# 100 Continue headers
|
||||
for header in self.hundred_continue_headers:
|
||||
towrite.append('%s: %s\r\n' % header)
|
||||
towrite.append(six.b('%s: %s\r\n' % header))
|
||||
|
||||
# Blank line
|
||||
towrite.append('\r\n')
|
||||
towrite.append(b'\r\n')
|
||||
|
||||
self.wfile.writelines(towrite)
|
||||
self.wfile = None
|
||||
@@ -558,7 +558,7 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
|
||||
if env.get('HTTP_EXPECT') == '100-continue':
|
||||
wfile = self.wfile
|
||||
wfile_line = 'HTTP/1.1 100 Continue\r\n'
|
||||
wfile_line = b'HTTP/1.1 100 Continue\r\n'
|
||||
else:
|
||||
wfile = None
|
||||
wfile_line = None
|
||||
@@ -580,6 +580,9 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
greenio.shutdown_safe(self.connection)
|
||||
self.connection.close()
|
||||
|
||||
def handle_expect_100(self):
|
||||
return True
|
||||
|
||||
|
||||
class Server(BaseHTTPServer.HTTPServer):
|
||||
|
||||
|
@@ -8,6 +8,7 @@ import eventlet
|
||||
import os
|
||||
import sys
|
||||
import signal
|
||||
from eventlet.support import bytes_to_str, six
|
||||
mydir = %r
|
||||
signal_file = os.path.join(mydir, "output.txt")
|
||||
pid = os.fork()
|
||||
@@ -30,18 +31,18 @@ if (pid != 0):
|
||||
break
|
||||
except (IOError, IndexError):
|
||||
eventlet.sleep(0.1)
|
||||
print('result {0}'.format(result))
|
||||
print('result {0}'.format(bytes_to_str(result)))
|
||||
finally:
|
||||
os.kill(pid, signal.SIGTERM)
|
||||
else:
|
||||
try:
|
||||
s = eventlet.listen(('', 0))
|
||||
fd = open(signal_file, "wb")
|
||||
fd.write(str(s.getsockname()[1]))
|
||||
fd.write("\\n")
|
||||
fd.write(six.b(str(s.getsockname()[1])))
|
||||
fd.write(b"\\n")
|
||||
fd.flush()
|
||||
s.accept()
|
||||
fd.write("done")
|
||||
fd.write(b"done")
|
||||
fd.flush()
|
||||
finally:
|
||||
fd.close()
|
||||
|
@@ -17,7 +17,7 @@ from eventlet.green import subprocess
|
||||
from eventlet import greenio
|
||||
from eventlet import greenthread
|
||||
from eventlet import support
|
||||
from eventlet.support import six
|
||||
from eventlet.support import bytes_to_str, six
|
||||
from eventlet import tpool
|
||||
from eventlet import wsgi
|
||||
|
||||
@@ -27,13 +27,6 @@ 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',
|
||||
@@ -347,7 +340,7 @@ class TestHttpd(_TestBase):
|
||||
def test_007_get_arg(self):
|
||||
# define a new handler that does a get_arg as well as a read_body
|
||||
def new_app(env, start_response):
|
||||
body = env['wsgi.input'].read()
|
||||
body = bytes_to_str(env['wsgi.input'].read())
|
||||
a = cgi.parse_qs(body).get('a', [1])[0]
|
||||
start_response('200 OK', [('Content-type', 'text/plain')])
|
||||
return [six.b('a is %s, body is %s' % (a, body))]
|
||||
@@ -368,7 +361,7 @@ class TestHttpd(_TestBase):
|
||||
# send some junk after the actual request
|
||||
fd.write(b'01234567890123456789')
|
||||
result = read_http(sock)
|
||||
self.assertEqual(result.body, 'a is a, body is a=a')
|
||||
self.assertEqual(result.body, b'a is a, body is a=a')
|
||||
fd.close()
|
||||
|
||||
def test_008_correctresponse(self):
|
||||
@@ -434,7 +427,7 @@ class TestHttpd(_TestBase):
|
||||
assert chunks > 1
|
||||
response = fd.read()
|
||||
# Require a CRLF to close the message body
|
||||
self.assertEqual(response, '\r\n')
|
||||
self.assertEqual(response, b'\r\n')
|
||||
|
||||
@tests.skip_if_no_ssl
|
||||
def test_012_ssl_server(self):
|
||||
@@ -771,7 +764,7 @@ class TestHttpd(_TestBase):
|
||||
break
|
||||
else:
|
||||
header_lines.append(line)
|
||||
assert header_lines[0].startswith('HTTP/1.1 100 Continue')
|
||||
assert header_lines[0].startswith(b'HTTP/1.1 100 Continue')
|
||||
header_lines = []
|
||||
while True:
|
||||
line = fd.readline()
|
||||
@@ -779,7 +772,7 @@ class TestHttpd(_TestBase):
|
||||
break
|
||||
else:
|
||||
header_lines.append(line)
|
||||
assert header_lines[0].startswith('HTTP/1.1 200 OK')
|
||||
assert header_lines[0].startswith(b'HTTP/1.1 200 OK')
|
||||
assert fd.read(7) == b'testing'
|
||||
fd.close()
|
||||
sock.close()
|
||||
@@ -788,7 +781,7 @@ class TestHttpd(_TestBase):
|
||||
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:
|
||||
environ['wsgi.input'].set_hundred_continue_response_headers(
|
||||
[('Hundred-Continue-Header-1', 'H1'),
|
||||
@@ -799,13 +792,13 @@ class TestHttpd(_TestBase):
|
||||
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')
|
||||
@@ -813,27 +806,27 @@ 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.strip())
|
||||
assert header_lines[0].startswith('HTTP/1.1 100 Continue')
|
||||
headers = dict((k, v) for k, v in (h.split(': ', 1) for h in header_lines[1:]))
|
||||
assert 'Hundred-Continue-Header-1' in headers
|
||||
assert 'Hundred-Continue-Header-2' in headers
|
||||
assert 'Hundred-Continue-Header-K' in headers
|
||||
self.assertEqual('H1', headers['Hundred-Continue-Header-1'])
|
||||
self.assertEqual('H2', headers['Hundred-Continue-Header-2'])
|
||||
self.assertEqual('Hk', headers['Hundred-Continue-Header-K'])
|
||||
assert header_lines[0].startswith(b'HTTP/1.1 100 Continue')
|
||||
headers = dict((k, v) for k, v in (h.split(b': ', 1) for h in header_lines[1:]))
|
||||
assert b'Hundred-Continue-Header-1' in headers
|
||||
assert b'Hundred-Continue-Header-2' in headers
|
||||
assert b'Hundred-Continue-Header-K' in headers
|
||||
self.assertEqual(b'H1', headers[b'Hundred-Continue-Header-1'])
|
||||
self.assertEqual(b'H2', headers[b'Hundred-Continue-Header-2'])
|
||||
self.assertEqual(b'Hk', headers[b'Hundred-Continue-Header-K'])
|
||||
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 header_lines[0].startswith(b'HTTP/1.1 200 OK')
|
||||
self.assertEqual(fd.read(7), b'testing')
|
||||
fd.close()
|
||||
sock.close()
|
||||
|
||||
@@ -1079,7 +1072,7 @@ class TestHttpd(_TestBase):
|
||||
'POST / HTTP/1.0\r\n'
|
||||
'Host: localhost\r\n'
|
||||
'Content-Length: %i\r\n\r\n%s'
|
||||
) % (len(upload_data), upload_data)
|
||||
) % (len(upload_data), bytes_to_str(upload_data))
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('rwb')
|
||||
fd.write(request.encode())
|
||||
@@ -1092,7 +1085,7 @@ class TestHttpd(_TestBase):
|
||||
def test_zero_length_chunked_response(self):
|
||||
def zero_chunked_app(env, start_response):
|
||||
start_response('200 OK', [('Content-type', 'text/plain')])
|
||||
yield ""
|
||||
yield b""
|
||||
|
||||
self.site.application = zero_chunked_app
|
||||
sock = eventlet.connect(
|
||||
@@ -1106,9 +1099,9 @@ class TestHttpd(_TestBase):
|
||||
while True:
|
||||
h = response.pop(0)
|
||||
headers.append(h)
|
||||
if h == '':
|
||||
if h == b'':
|
||||
break
|
||||
assert b'Transfer-Encoding: chunked' in ''.join(headers)
|
||||
assert b'Transfer-Encoding: chunked' in b''.join(headers), headers
|
||||
# should only be one chunk of zero size with two blank lines
|
||||
# (one terminates the chunk, one terminates the body)
|
||||
self.assertEqual(response, [b'0', b'', b''])
|
||||
@@ -1190,8 +1183,8 @@ class TestHttpd(_TestBase):
|
||||
def test_path_info_decoding(self):
|
||||
def wsgi_app(environ, start_response):
|
||||
start_response("200 OK", [])
|
||||
yield "decoded: %s" % environ['PATH_INFO']
|
||||
yield "raw: %s" % environ['RAW_PATH_INFO']
|
||||
yield six.b("decoded: %s" % environ['PATH_INFO'])
|
||||
yield six.b("raw: %s" % environ['RAW_PATH_INFO'])
|
||||
self.site.application = wsgi_app
|
||||
sock = eventlet.connect(('localhost', self.port))
|
||||
fd = sock.makefile('rwb')
|
||||
@@ -1467,7 +1460,7 @@ class TestChunkedInput(_TestBase):
|
||||
|
||||
def ping(self, fd):
|
||||
fd.sendall(b"GET /ping HTTP/1.1\r\n\r\n")
|
||||
self.assertEqual(read_http(fd).body, "pong")
|
||||
self.assertEqual(read_http(fd).body, b"pong")
|
||||
|
||||
def test_short_read_with_content_length(self):
|
||||
body = self.body()
|
||||
@@ -1529,12 +1522,12 @@ class TestChunkedInput(_TestBase):
|
||||
fd = self.connect()
|
||||
fd.sendall(b"POST /yield_spaces/override_min HTTP/1.1\r\nContent-Length: 0\r\n\r\n")
|
||||
|
||||
resp_so_far = ''
|
||||
resp_so_far = b''
|
||||
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), b' ')
|
||||
try:
|
||||
|
Reference in New Issue
Block a user