r47338 - Apply twcgi-py3-8009-3.patch.
adiroiban-TA+aISz0psMTMxyoc4vAAJOcrHinNvQL0E9HWUfgJXw@public.gmane.org Tue, 3 May 2016 01:50:12 -0600 (MDT)
| Newsgroups | gmane.comp.python.twisted.commits |
|---|---|
| Message-ID | <[email protected]> |
Author: adiroiban
Date: Tue May 3 01:50:04 2016
New Revision: 47338
Modified:
branches/twcgi-py3-8009-3/twisted/web/test/test_cgi.py
branches/twcgi-py3-8009-3/twisted/web/twcgi.py
Log:
Apply twcgi-py3-8009-3.patch.
Modified: branches/twcgi-py3-8009-3/twisted/web/test/test_cgi.py
==============================================================================
--- branches/twcgi-py3-8009-3/twisted/web/test/test_cgi.py (original)
+++ branches/twcgi-py3-8009-3/twisted/web/test/test_cgi.py Tue May 3 01:50:04 2016
@@ -10,35 +10,36 @@
from twisted.trial import unittest
from twisted.internet import reactor, interfaces, error
from twisted.python import util, failure, log
+from twisted.python.compat import _PY3
from twisted.web.http import NOT_FOUND, INTERNAL_SERVER_ERROR
from twisted.web import client, twcgi, server, resource
from twisted.web.test._util import _render
from twisted.web.test.test_web import DummyRequest
DUMMY_CGI = '''\
-print "Header: OK"
-print
-print "cgi output"
+print("Header: OK")
+print("")
+print("cgi output")
'''
DUAL_HEADER_CGI = '''\
-print "Header: spam"
-print "Header: eggs"
-print
-print "cgi output"
+print("Header: spam")
+print("Header: eggs")
+print("")
+print("cgi output")
'''
BROKEN_HEADER_CGI = '''\
-print "XYZ"
-print
-print "cgi output"
+print("XYZ")
+print("")
+print("cgi output")
'''
SPECIAL_HEADER_CGI = '''\
-print "Server: monkeys"
-print "Date: last year"
-print
-print "cgi output"
+print("Server: monkeys")
+print("Date: last year")
+print("")
+print("cgi output")
'''
READINPUT_CGI = '''\
@@ -49,9 +50,9 @@
body_length = int(os.environ.get('CONTENT_LENGTH',0))
indata = sys.stdin.read(body_length)
-print "Header: OK"
-print
-print "readinput ok"
+print("Header: OK")
+print("")
+print("readinput ok")
'''
READALLINPUT_CGI = '''\
@@ -62,15 +63,15 @@
import sys
indata = sys.stdin.read()
-print "Header: OK"
-print
-print "readallinput ok"
+print("Header: OK")
+print("")
+print("readallinput ok")
'''
NO_DUPLICATE_CONTENT_TYPE_HEADER_CGI = '''\
-print "content-type: text/cgi-duplicate-test"
-print
-print "cgi output"
+print("content-type: text/cgi-duplicate-test")
+print("")
+print("cgi output")
'''
class PythonScript(twcgi.FilteredScript):
@@ -87,7 +88,7 @@
def startServer(self, cgi):
root = resource.Resource()
cgipath = util.sibpath(__file__, cgi)
- root.putChild("cgi", PythonScript(cgipath))
+ root.putChild(b"cgi", PythonScript(cgipath))
site = server.Site(root)
self.p = reactor.listenTCP(0, site)
return self.p.getHost().port
@@ -99,9 +100,10 @@
def writeCGI(self, source):
cgiFilename = os.path.abspath(self.mktemp())
- cgiFile = file(cgiFilename, 'wt')
- cgiFile.write(source)
- cgiFile.close()
+
+ with open(cgiFilename, 'wt') as fh:
+ fh.write(source)
+
return cgiFilename
@@ -109,13 +111,14 @@
cgiFilename = self.writeCGI(DUMMY_CGI)
portnum = self.startServer(cgiFilename)
- d = client.getPage("http://localhost:%d/cgi" % portnum)
+ url = "http://localhost:%d/cgi" % (portnum,)
+ d = client.getPage(url.encode("ascii"))
d.addCallback(self._testCGI_1)
return d
def _testCGI_1(self, res):
- self.assertEqual(res, "cgi output" + os.linesep)
+ self.assertEqual(res, ("cgi output" + os.linesep).encode("ascii"))
def test_protectedServerAndDate(self):
@@ -127,11 +130,11 @@
portnum = self.startServer(cgiFilename)
url = "http://localhost:%d/cgi" % (portnum,)
- factory = client.HTTPClientFactory(url)
+ factory = client.HTTPClientFactory(url.encode("ascii"))
reactor.connectTCP('localhost', portnum, factory)
def checkResponse(ignored):
- self.assertNotIn('monkeys', factory.response_headers['server'])
- self.assertNotIn('last year', factory.response_headers['date'])
+ self.assertNotIn('monkeys', factory.response_headers[b'server'])
+ self.assertNotIn('last year', factory.response_headers[b'date'])
factory.deferred.addCallback(checkResponse)
return factory.deferred
@@ -145,11 +148,11 @@
portnum = self.startServer(cgiFilename)
url = "http://localhost:%d/cgi" % (portnum,)
- factory = client.HTTPClientFactory(url)
+ factory = client.HTTPClientFactory(url.encode("ascii"))
reactor.connectTCP('localhost', portnum, factory)
def checkResponse(ignored):
self.assertEqual(
- factory.response_headers['content-type'], ['text/cgi-duplicate-test'])
+ factory.response_headers[b'content-type'], [b'text/cgi-duplicate-test'])
factory.deferred.addCallback(checkResponse)
return factory.deferred
@@ -163,11 +166,11 @@
portnum = self.startServer(cgiFilename)
url = "http://localhost:%d/cgi" % (portnum,)
- factory = client.HTTPClientFactory(url)
+ factory = client.HTTPClientFactory(url.encode("ascii"))
reactor.connectTCP('localhost', portnum, factory)
def checkResponse(ignored):
self.assertEqual(
- factory.response_headers['header'], ['spam', 'eggs'])
+ factory.response_headers[b'header'], [b'spam', b'eggs'])
factory.deferred.addCallback(checkResponse)
return factory.deferred
@@ -180,7 +183,7 @@
portnum = self.startServer(cgiFilename)
url = "http://localhost:%d/cgi" % (portnum,)
- factory = client.HTTPClientFactory(url)
+ factory = client.HTTPClientFactory(url.encode("ascii"))
reactor.connectTCP('localhost', portnum, factory)
loggedMessages = []
@@ -191,8 +194,12 @@
self.addCleanup(log.removeObserver, addMessage)
def checkResponse(ignored):
- self.assertEqual(loggedMessages[0],
- "ignoring malformed CGI header: 'XYZ'")
+ if _PY3:
+ self.assertEqual(loggedMessages[0],
+ "ignoring malformed CGI header: b'XYZ'")
+ else:
+ self.assertEqual(loggedMessages[0],
+ "ignoring malformed CGI header: 'XYZ'")
factory.deferred.addCallback(checkResponse)
return factory.deferred
@@ -200,50 +207,57 @@
def testReadEmptyInput(self):
cgiFilename = os.path.abspath(self.mktemp())
- cgiFile = file(cgiFilename, 'wt')
- cgiFile.write(READINPUT_CGI)
- cgiFile.close()
+ with open(cgiFilename, 'wt') as fh:
+ fh.write(READINPUT_CGI)
portnum = self.startServer(cgiFilename)
- d = client.getPage("http://localhost:%d/cgi" % portnum)
+ url = "http://localhost:%d/cgi" % (portnum,)
+ d = client.getPage(url.encode("ascii"))
d.addCallback(self._testReadEmptyInput_1)
return d
testReadEmptyInput.timeout = 5
+
+
def _testReadEmptyInput_1(self, res):
- self.assertEqual(res, "readinput ok%s" % os.linesep)
+ self.assertEqual(res, ("readinput ok%s" % os.linesep).encode("ascii"))
def testReadInput(self):
cgiFilename = os.path.abspath(self.mktemp())
- cgiFile = file(cgiFilename, 'wt')
- cgiFile.write(READINPUT_CGI)
- cgiFile.close()
+ with open(cgiFilename, 'wt') as fh:
+ fh.write(READINPUT_CGI)
portnum = self.startServer(cgiFilename)
- d = client.getPage("http://localhost:%d/cgi" % portnum,
- method="POST",
- postdata="Here is your stdin")
+ url = "http://localhost:%d/cgi" % (portnum,)
+ d = client.getPage(url.encode("ascii"),
+ method=b"POST",
+ postdata=b"Here is your stdin")
d.addCallback(self._testReadInput_1)
return d
testReadInput.timeout = 5
+
+
def _testReadInput_1(self, res):
- self.assertEqual(res, "readinput ok%s" % os.linesep)
+ self.assertEqual(res, ("readinput ok%s" % os.linesep).encode("ascii"))
def testReadAllInput(self):
cgiFilename = os.path.abspath(self.mktemp())
- cgiFile = file(cgiFilename, 'wt')
- cgiFile.write(READALLINPUT_CGI)
- cgiFile.close()
+ with open(cgiFilename, 'wt') as fh:
+ fh.write(READALLINPUT_CGI)
portnum = self.startServer(cgiFilename)
- d = client.getPage("http://localhost:%d/cgi" % portnum,
- method="POST",
- postdata="Here is your stdin")
+ url = "http://localhost:%d/cgi" % (portnum,)
+ d = client.getPage(url.encode("ascii"),
+ method=b"POST",
+ postdata=b"Here is your stdin")
d.addCallback(self._testReadAllInput_1)
return d
testReadAllInput.timeout = 5
+
+
def _testReadAllInput_1(self, res):
- self.assertEqual(res, "readallinput ok%s" % os.linesep)
+ self.assertEqual(res,
+ ("readallinput ok%s" % os.linesep).encode("ascii"))
def test_useReactorArgument(self):
Modified: branches/twcgi-py3-8009-3/twisted/web/twcgi.py
==============================================================================
--- branches/twcgi-py3-8009-3/twisted/web/twcgi.py (original)
+++ branches/twcgi-py3-8009-3/twisted/web/twcgi.py Tue May 3 01:50:04 2016
@@ -14,10 +14,21 @@
# Twisted Imports
from twisted.web import http
from twisted.internet import protocol
-from twisted.spread import pb
from twisted.python import log, filepath
from twisted.web import resource, server, static
+# t.spread.pb.Viewable is a subclass to CGIProcessProtocol but t.spread.pb is
+# not ported to Python 3.x yet. We'll just try to import it anyway and:
+# - in Python 2.x it should just work
+# - in 3.x, SyntaxError will be raised so we'll assign `object` to it;
+# CGIProcessProtocol won't be Viewable.
+#
+# See https://twistedmatrix.com/trac/ticket/8009 .
+try:
+ from twisted.spread.pb import Viewable
+except SyntaxError:
+ Viewable = object
+
class CGIDirectory(resource.Resource, filepath.FilePath):
def __init__(self, pathname):
@@ -70,11 +81,14 @@
I will set up the usual slew of environment variables, then spin off a
process.
+ Headers from HTTP request will be propagated to process' environment;
+ their names will be decoded using 'iso-8859-1'.
+
@type request: L{twisted.web.http.Request}
@param request: An HTTP request.
"""
- script_name = "/" + "/".join(request.prepath)
- serverName = request.getRequestHostname().split(':')[0]
+ script_name = b"/" + b"/".join(request.prepath)
+ serverName = request.getRequestHostname().split(b':')[0]
env = {"SERVER_SOFTWARE": server.version,
"SERVER_NAME": serverName,
"GATEWAY_INTERFACE": "CGI/1.1",
@@ -102,7 +116,7 @@
env['CONTENT_LENGTH'] = str(length)
try:
- qindex = request.uri.index('?')
+ qindex = request.uri.index(b'?')
except ValueError:
env['QUERY_STRING'] = ''
qargs = []
@@ -115,7 +129,7 @@
# Propagate HTTP headers
for title, header in request.getAllHeaders().items():
- envname = title.replace('-', '_').upper()
+ envname = title.decode('iso-8859-1').replace('-', '_').upper()
if title not in ('content-type', 'content-length'):
envname = "HTTP_" + envname
env[envname] = header
@@ -125,6 +139,7 @@
env[key] = value
# And they're off!
self.runProcess(env, request, qargs)
+
return server.NOT_DONE_YET
@@ -194,11 +209,11 @@
-class CGIProcessProtocol(protocol.ProcessProtocol, pb.Viewable):
+class CGIProcessProtocol(protocol.ProcessProtocol, Viewable):
handling_headers = 1
headers_written = 0
- headertext = ''
- errortext = ''
+ headertext = b''
+ errortext = b''
# Remotely relay producer interface.
@@ -243,7 +258,7 @@
if self.handling_headers:
text = self.headertext + output
headerEnds = []
- for delimiter in '\n\n','\r\n\r\n','\r\r', '\n\r\n':
+ for delimiter in b'\n\n', b'\r\n\r\n', b'\r\r', b'\n\r\n':
headerend = text.find(delimiter)
if headerend != -1:
headerEnds.append((headerend, delimiter))
@@ -260,7 +275,7 @@
linebreak = delimiter[:len(delimiter)//2]
headers = self.headertext.split(linebreak)
for header in headers:
- br = header.find(': ')
+ br = header.find(b': ')
if br == -1:
log.msg(
format='ignoring malformed CGI header: %(header)r',