diff --git a/devel/py-zope.publisher/files/patch-2to3 b/devel/py-zope.publisher/files/patch-2to3
new file mode 100644
index 000000000000..ccf232582607
--- /dev/null
+++ b/devel/py-zope.publisher/files/patch-2to3
@@ -0,0 +1,1513 @@
+--- src/zope/publisher/ftp.py.orig 2012-07-02 06:19:44 UTC
++++ src/zope/publisher/ftp.py
+@@ -27,7 +27,7 @@ class FTPResponse(BaseResponse):
+
+ def getResult(self):
+ if getattr(self, '_exc', None) is not None:
+- raise self._exc[0], self._exc[1], self._exc[2]
++ raise self._exc[0](self._exc[1]).with_traceback(self._exc[2])
+ return self._result
+
+ def handleException(self, exc_info):
+--- src/zope/publisher/http.py.orig 2012-07-02 06:19:44 UTC
++++ src/zope/publisher/http.py
+@@ -13,7 +13,7 @@
+ ##############################################################################
+ """HTTP Publisher
+ """
+-from cStringIO import StringIO
++from io import StringIO
+ from zope.i18n.interfaces import IUserPreferredCharsets
+ from zope.i18n.interfaces import IUserPreferredLanguages
+ from zope.i18n.locales import locales, LoadLocaleError
+@@ -31,13 +31,13 @@ from zope.publisher.interfaces.http import IHTTPVirtua
+ from zope.publisher.interfaces.http import IResult
+ from zope.publisher.interfaces.logginginfo import ILoggingInfo
+ from zope.publisher.skinnable import setDefaultSkin
+-import Cookie
++import http.cookies
+ import cgi
+ import logging
+ import tempfile
+ import types
+-import urllib
+-import urlparse
++import urllib.request, urllib.parse, urllib.error
++import urllib.parse
+ import zope.component
+ import zope.contenttype.parse
+ import zope.event
+@@ -65,7 +65,7 @@ def sane_environment(env):
+ # or HTTP_CGI_AUTHORIZATION hacks.
+ # It also makes sure PATH_INFO is a unicode string.
+ dict = {}
+- for key, val in env.items():
++ for key, val in list(env.items()):
+ while key.startswith('REDIRECT_'):
+ key = key[9:]
+ dict[key] = val
+@@ -138,7 +138,7 @@ status_codes={}
+ def init_status_codes():
+ # Add mappings for builtin exceptions and
+ # provide text -> error code lookups.
+- for key, val in status_reasons.items():
++ for key, val in list(status_reasons.items()):
+ status_codes[val.replace(' ', '').lower()] = key
+ status_codes[val.lower()] = key
+ status_codes[key] = key
+@@ -176,7 +176,7 @@ class URLGetter(object):
+ return self.__request.getURL(i)
+ else:
+ return self.__request.getApplicationURL(i)
+- except IndexError, v:
++ except IndexError as v:
+ if v[0] == i:
+ return default
+ raise
+@@ -352,7 +352,7 @@ class HTTPRequest(BaseRequest):
+ script = get_env('SCRIPT_NAME', '').strip()
+
+ # _script and the other _names are meant for URL construction
+- self._app_names = filter(None, script.split('/'))
++ self._app_names = [_f for _f in script.split('/') if _f]
+
+ # get server URL and store it too, since we are already looking it up
+ server_url = get_env('SERVER_URL', None)
+@@ -379,9 +379,9 @@ class HTTPRequest(BaseRequest):
+ else:
+ protocol = 'http'
+
+- if environ.has_key('HTTP_HOST'):
++ if 'HTTP_HOST' in environ:
+ host = environ['HTTP_HOST'].strip()
+- hostname, port = urllib.splitport(host)
++ hostname, port = urllib.parse.splitport(host)
+ else:
+ hostname = environ.get('SERVER_NAME', '').strip()
+ port = environ.get('SERVER_PORT', '')
+@@ -401,13 +401,13 @@ class HTTPRequest(BaseRequest):
+
+ # ignore cookies on a CookieError
+ try:
+- c = Cookie.SimpleCookie(text)
+- except Cookie.CookieError, e:
++ c = http.cookies.SimpleCookie(text)
++ except http.cookies.CookieError as e:
+ eventlog.warn(e)
+ return result
+
+- for k,v in c.items():
+- result[unicode(k, ENCODING)] = unicode(v.value, ENCODING)
++ for k,v in list(c.items()):
++ result[str(k, ENCODING)] = str(v.value, ENCODING)
+
+ return result
+
+@@ -521,7 +521,7 @@ class HTTPRequest(BaseRequest):
+ raise IndexError(level)
+ names = names[:-level]
+ # See: http://www.ietf.org/rfc/rfc2718.txt, Section 2.2.5
+- names = [urllib.quote(name.encode("utf-8"), safe='/+@')
++ names = [urllib.parse.quote(name.encode("utf-8"), safe='/+@')
+ for name in names]
+
+ if path_only:
+@@ -544,7 +544,7 @@ class HTTPRequest(BaseRequest):
+ names = self._app_names
+
+ # See: http://www.ietf.org/rfc/rfc2718.txt, Section 2.2.5
+- names = [urllib.quote(name.encode("utf-8"), safe='/+@')
++ names = [urllib.parse.quote(name.encode("utf-8"), safe='/+@')
+ for name in names]
+
+ if path_only:
+@@ -604,7 +604,7 @@ class HTTPRequest(BaseRequest):
+ d = {}
+ d.update(self._environ)
+ d.update(self._cookies)
+- return d.keys()
++ return list(d.keys())
+
+
+
+@@ -645,7 +645,7 @@ class HTTPResponse(BaseResponse):
+ try:
+ status = int(status)
+ except ValueError:
+- if isinstance(status, basestring):
++ if isinstance(status, str):
+ status = status.lower()
+ # Use a standard status code, falling back to 500 for
+ # nonstandard values (such as "valueerror")
+@@ -701,7 +701,7 @@ class HTTPResponse(BaseResponse):
+ result.append(
+ ("X-Powered-By", "Zope (www.zope.org), Python (www.python.org)"))
+
+- for key, values in headers.items():
++ for key, values in list(headers.items()):
+ if key.lower() == key:
+ # only change non-literal header names
+ key = '-'.join([k.capitalize() for k in key.split('-')])
+@@ -729,7 +729,7 @@ class HTTPResponse(BaseResponse):
+ def expireCookie(self, name, **kw):
+ 'See IHTTPResponse'
+ dict = {'max_age':0, 'expires':'Wed, 31-Dec-97 23:59:59 GMT'}
+- for k, v in kw.items():
++ for k, v in list(kw.items()):
+ if v is not None:
+ dict[k] = v
+ cookies = self._cookies
+@@ -744,7 +744,7 @@ class HTTPResponse(BaseResponse):
+ cookies = self._cookies
+ cookie = cookies.setdefault(name, {})
+
+- for k, v in kw.items():
++ for k, v in list(kw.items()):
+ if v is not None:
+ cookie[k.lower()] = v
+
+@@ -764,7 +764,7 @@ class HTTPResponse(BaseResponse):
+ r = zope.component.queryMultiAdapter(
+ (result, self._request), IResult)
+ if r is None:
+- if isinstance(result, basestring):
++ if isinstance(result, str):
+ r = result
+ elif result is None:
+ r = ''
+@@ -772,7 +772,7 @@ class HTTPResponse(BaseResponse):
+ raise TypeError(
+ 'The result should be None, a string, or adaptable to '
+ 'IResult.')
+- if isinstance(r, basestring):
++ if isinstance(r, str):
+ r, headers = self._implicitResult(r)
+ self._headers.update(dict((k, [v]) for (k, v) in headers))
+ r = (r,) # chunking should be much larger than per character
+@@ -796,7 +796,7 @@ class HTTPResponse(BaseResponse):
+ encoding = getCharsetUsingRequest(self._request) or 'utf-8'
+ content_type = self.getHeader('content-type')
+
+- if isinstance(body, unicode):
++ if isinstance(body, str):
+ if not unicode_mimetypes_re.match(content_type):
+ raise ValueError(
+ 'Unicode results must have a text, RFC 3023, or '
+@@ -818,7 +818,7 @@ class HTTPResponse(BaseResponse):
+
+ params['charset'] = encoding
+ content_type = "%s/%s;" % (major, minor)
+- content_type += ";".join(k + "=" + v for k, v in params.items())
++ content_type += ";".join(k + "=" + v for k, v in list(params.items()))
+
+ if content_type:
+ headers = [('content-type', content_type),
+@@ -833,13 +833,13 @@ class HTTPResponse(BaseResponse):
+ Calls self.setBody() with an error response.
+ """
+ t, v = exc_info[:2]
+- if isinstance(t, (types.ClassType, type)):
++ if isinstance(t, type):
+ if issubclass(t, Redirect):
+ self.redirect(v.getLocation())
+ return
+ title = tname = t.__name__
+ else:
+- title = tname = unicode(t)
++ title = tname = str(t)
+
+ # Throwing non-protocol-specific exceptions is a good way
+ # for apps to control the status code.
+@@ -851,15 +851,15 @@ class HTTPResponse(BaseResponse):
+
+ def internalError(self):
+ 'See IPublisherResponse'
+- self.setStatus(500, u"The engines can't take any more, Jim!")
++ self.setStatus(500, "The engines can't take any more, Jim!")
+
+ def _html(self, title, content):
+ t = cgi.escape(title)
+ return (
+- u"
%s\n"
+- u"%s
\n"
+- u"%s\n"
+- u"\n" %
++ "%s\n"
++ "%s
\n"
++ "%s\n"
++ "\n" %
+ (t, t, content)
+ )
+
+@@ -900,14 +900,14 @@ class HTTPResponse(BaseResponse):
+
+ def _cookie_list(self):
+ try:
+- c = Cookie.SimpleCookie()
+- except Cookie.CookieError, e:
++ c = http.cookies.SimpleCookie()
++ except http.cookies.CookieError as e:
+ eventlog.warn(e)
+ return []
+- for name, attrs in self._cookies.items():
++ for name, attrs in list(self._cookies.items()):
+ name = str(name)
+ c[name] = attrs['value'].encode(ENCODING)
+- for k,v in attrs.items():
++ for k,v in list(attrs.items()):
+ if k == 'value':
+ continue
+ if k == 'secure':
+@@ -918,7 +918,7 @@ class HTTPResponse(BaseResponse):
+ k = 'max-age'
+ elif k == 'comment':
+ # Encode rather than throw an exception
+- v = urllib.quote(v.encode('utf-8'), safe="/?:@&+")
++ v = urllib.parse.quote(v.encode('utf-8'), safe="/?:@&+")
+ c[name][k] = str(v)
+ return str(c).splitlines()
+
+@@ -938,7 +938,7 @@ def sort_charsets(x, y):
+
+
+ def extract_host(url):
+- scheme, host, path, query, fragment = urlparse.urlsplit(url)
++ scheme, host, path, query, fragment = urllib.parse.urlsplit(url)
+ if ':' not in host:
+ port = DEFAULT_PORTS.get(scheme)
+ if port:
+--- src/zope/publisher/interfaces/__init__.py.orig 2012-07-02 06:19:42 UTC
++++ src/zope/publisher/interfaces/__init__.py
+@@ -60,10 +60,10 @@ class NotFound(LookupError, TraversalException):
+
+ def __str__(self):
+ try:
+- ob = `self.ob`
++ ob = repr(self.ob)
+ except:
+ ob = 'unprintable object'
+- return 'Object: %s, name: %s' % (ob, `self.name`)
++ return 'Object: %s, name: %s' % (ob, repr(self.name))
+
+ class IDebugError(ITraversalException):
+ def getObject():
+--- src/zope/publisher/publish.py.orig 2012-07-02 06:19:44 UTC
++++ src/zope/publisher/publish.py
+@@ -64,8 +64,8 @@ def mapply(obj, positional=(), request={}):
+
+ unwrapped, wrapperCount = unwrapMethod(unwrapped)
+
+- code = unwrapped.func_code
+- defaults = unwrapped.func_defaults
++ code = unwrapped.__code__
++ defaults = unwrapped.__defaults__
+ names = code.co_varnames[wrapperCount:code.co_argcount]
+
+ nargs = len(names)
+@@ -154,7 +154,7 @@ def publish(request, handle_errors=True):
+
+ break # Successful.
+
+- except Retry, retryException:
++ except Retry as retryException:
+ if request.supportsRetry():
+ # Create a copy of the request and use it.
+ newrequest = request.retry()
+@@ -187,7 +187,7 @@ def publish(request, handle_errors=True):
+
+ response = request.response
+ if to_raise is not None:
+- raise to_raise[0], to_raise[1], to_raise[2]
++ raise to_raise[0](to_raise[1]).with_traceback(to_raise[2])
+
+ finally:
+ to_raise = None # Avoid circ. ref.
+--- src/zope/publisher/tests/test_browserrequest.py.orig 2012-07-02 06:19:44 UTC
++++ src/zope/publisher/tests/test_browserrequest.py
+@@ -14,7 +14,7 @@
+
+ import sys
+ import unittest
+-from StringIO import StringIO
++from io import StringIO
+
+ from zope.interface import implements, directlyProvides, Interface
+ from zope.interface.verify import verifyObject
+@@ -101,12 +101,12 @@ class BrowserTests(HTTPTests):
+ class Item(object):
+ """Required docstring for the publisher."""
+ def __call__(self, a, b):
+- return u"%s, %s" % (`a`, `b`)
++ return "%s, %s" % (repr(a), repr(b))
+
+ class Item3(object):
+ """Required docstring for the publisher."""
+ def __call__(self, *args):
+- return u"..."
++ return "..."
+
+ class View(object):
+ """Required docstring for the publisher."""
+@@ -115,7 +115,7 @@ class BrowserTests(HTTPTests):
+
+ def index(self, a, b):
+ """Required docstring for the publisher."""
+- return u"%s, %s" % (`a`, `b`)
++ return "%s, %s" % (repr(a), repr(b))
+
+ class Item2(object):
+ """Required docstring for the publisher."""
+@@ -145,7 +145,7 @@ class BrowserTests(HTTPTests):
+
+ def testTraversalToItem(self):
+ res = self._publisherResults()
+- self.failUnlessEqual(
++ self.assertEqual(
+ res,
+ "Status: 200 Ok\r\n"
+ "Content-Length: 7\r\n"
+@@ -159,7 +159,7 @@ class BrowserTests(HTTPTests):
+ request = self._createRequest()
+ response = request.response
+ publish(request)
+- self.failIf(response.getBase())
++ self.assertFalse(response.getBase())
+
+ def testDefault(self):
+ extra = {'PATH_INFO': '/folder/item2'}
+@@ -183,7 +183,7 @@ class BrowserTests(HTTPTests):
+ should be catched"""
+
+ extra = {'REQUEST_METHOD':'POST',
+- 'PATH_INFO': u'/',
++ 'PATH_INFO': '/',
+ 'CONTENT_TYPE': 'multipart/form-data;\
+ boundary=---------------------------1'}
+
+@@ -201,17 +201,17 @@ class BrowserTests(HTTPTests):
+ its filename."""
+
+ extra = {'REQUEST_METHOD':'POST',
+- 'PATH_INFO': u'/',
++ 'PATH_INFO': '/',
+ 'CONTENT_TYPE': 'multipart/form-data;\
+ boundary=---------------------------1'}
+
+ request = self._createRequest(extra, body=LARGE_FILE_BODY)
+ request.processInputs()
+- self.assert_(request.form['upload'].name)
++ self.assertTrue(request.form['upload'].name)
+
+ request = self._createRequest(extra, body=IE_FILE_BODY)
+ request.processInputs()
+- self.assertEquals(request.form['upload'].filename, 'notepad.exe')
++ self.assertEqual(request.form['upload'].filename, 'notepad.exe')
+
+
+ def testDefault2(self):
+@@ -227,14 +227,14 @@ class BrowserTests(HTTPTests):
+ request = self._createRequest(extra)
+ response = request.response
+ publish(request)
+- self.failIf(response.getBase())
++ self.assertFalse(response.getBase())
+
+ def testDefault4(self):
+ extra = {'PATH_INFO': '/folder/item2/view/'}
+ request = self._createRequest(extra)
+ response = request.response
+ publish(request)
+- self.failIf(response.getBase())
++ self.assertFalse(response.getBase())
+
+ def testDefault6(self):
+ extra = {'PATH_INFO': '/folder/item2/'}
+@@ -258,7 +258,7 @@ class BrowserTests(HTTPTests):
+ request = self._createRequest()
+ publish(request)
+ self.assertEqual(request.form,
+- {u'a':u'5', u'b':6})
++ {'a':'5', 'b':6})
+
+ def testFormNoEncodingUsesUTF8(self):
+ encoded = 'K\xc3\x83\xc2\xb6hlerstra\xc3\x83\xc2\x9fe'
+@@ -271,8 +271,8 @@ class BrowserTests(HTTPTests):
+ # many mainstream browsers do not send HTTP_ACCEPT_CHARSET
+ del request._environ['HTTP_ACCEPT_CHARSET']
+ publish(request)
+- self.assert_(isinstance(request.form[u'street'], unicode))
+- self.assertEqual(unicode(encoded, 'utf-8'), request.form['street'])
++ self.assertTrue(isinstance(request.form['street'], str))
++ self.assertEqual(str(encoded, 'utf-8'), request.form['street'])
+
+ def testFormAcceptsStarButNotUTF8(self):
+ extra = {
+@@ -287,100 +287,100 @@ class BrowserTests(HTTPTests):
+ extra = {'QUERY_STRING':'a:list=5&a:list=6&b=1'}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'a':[u'5',u'6'], u'b':u'1'})
++ self.assertEqual(request.form, {'a':['5','6'], 'b':'1'})
+
+ def testQueryStringIgnoredForPOST(self):
+ request = self._createRequest(
+ {"REQUEST_METHOD": "POST",
+ 'PATH_INFO': '/folder/item3'}, body='c=5&d:int=6')
+ publish(request)
+- self.assertEqual(request.form, {u'c': u'5', u'd': 6})
++ self.assertEqual(request.form, {'c': '5', 'd': 6})
+ self.assertEqual(request.get('QUERY_STRING'), 'a=5&b:int=6')
+
+ def testFormTupleTypes(self):
+ extra = {'QUERY_STRING':'a:tuple=5&a:tuple=6&b=1'}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'a':(u'5',u'6'), u'b':u'1'})
++ self.assertEqual(request.form, {'a':('5','6'), 'b':'1'})
+
+ def testFormTupleRecordTypes(self):
+ extra = {'QUERY_STRING':'a.x:tuple:record=5&a.x:tuple:record=6&b=1'}
+ request = self._createRequest(extra)
+ publish(request)
+- keys = request.form.keys()
++ keys = list(request.form.keys())
+ keys.sort()
+- self.assertEqual(keys, [u'a',u'b'])
+- self.assertEqual(request.form[u'b'], u'1')
+- self.assertEqual(request.form[u'a'].keys(), [u'x'])
+- self.assertEqual(request.form[u'a'][u'x'], (u'5',u'6'))
+- self.assertEqual(request.form[u'a'].x, (u'5',u'6'))
+- self.assertEqual(str(request.form[u'a']), "{x: (u'5', u'6')}")
+- self.assertEqual(repr(request.form[u'a']), "{x: (u'5', u'6')}")
++ self.assertEqual(keys, ['a','b'])
++ self.assertEqual(request.form['b'], '1')
++ self.assertEqual(list(request.form['a'].keys()), ['x'])
++ self.assertEqual(request.form['a']['x'], ('5','6'))
++ self.assertEqual(request.form['a'].x, ('5','6'))
++ self.assertEqual(str(request.form['a']), "{x: (u'5', u'6')}")
++ self.assertEqual(repr(request.form['a']), "{x: (u'5', u'6')}")
+
+ def testFormRecordsTypes(self):
+ extra = {'QUERY_STRING':'a.x:records=5&a.x:records=6&b=1'}
+ request = self._createRequest(extra)
+ publish(request)
+- keys = request.form.keys()
++ keys = list(request.form.keys())
+ keys.sort()
+- self.assertEqual(keys, [u'a',u'b'])
+- self.assertEqual(request.form[u'b'], u'1')
+- self.assertEqual(len(request.form[u'a']), 2)
+- self.assertEqual(request.form[u'a'][0][u'x'], u'5')
+- self.assertEqual(request.form[u'a'][0].x, u'5')
+- self.assertEqual(request.form[u'a'][1][u'x'], u'6')
+- self.assertEqual(request.form[u'a'][1].x, u'6')
+- self.assertEqual(str(request.form[u'a']), "[{x: u'5'}, {x: u'6'}]")
+- self.assertEqual(repr(request.form[u'a']), "[{x: u'5'}, {x: u'6'}]")
++ self.assertEqual(keys, ['a','b'])
++ self.assertEqual(request.form['b'], '1')
++ self.assertEqual(len(request.form['a']), 2)
++ self.assertEqual(request.form['a'][0]['x'], '5')
++ self.assertEqual(request.form['a'][0].x, '5')
++ self.assertEqual(request.form['a'][1]['x'], '6')
++ self.assertEqual(request.form['a'][1].x, '6')
++ self.assertEqual(str(request.form['a']), "[{x: u'5'}, {x: u'6'}]")
++ self.assertEqual(repr(request.form['a']), "[{x: u'5'}, {x: u'6'}]")
+
+ def testFormMultipleRecordsTypes(self):
+ extra = {'QUERY_STRING':'a.x:records:int=5&a.y:records:int=51'
+ '&a.x:records:int=6&a.y:records:int=61&b=1'}
+ request = self._createRequest(extra)
+ publish(request)
+- keys = request.form.keys()
++ keys = list(request.form.keys())
+ keys.sort()
+- self.assertEqual(keys, [u'a',u'b'])
+- self.assertEqual(request.form[u'b'], u'1')
+- self.assertEqual(len(request.form[u'a']), 2)
+- self.assertEqual(request.form[u'a'][0][u'x'], 5)
+- self.assertEqual(request.form[u'a'][0].x, 5)
+- self.assertEqual(request.form[u'a'][0][u'y'], 51)
+- self.assertEqual(request.form[u'a'][0].y, 51)
+- self.assertEqual(request.form[u'a'][1][u'x'], 6)
+- self.assertEqual(request.form[u'a'][1].x, 6)
+- self.assertEqual(request.form[u'a'][1][u'y'], 61)
+- self.assertEqual(request.form[u'a'][1].y, 61)
+- self.assertEqual(str(request.form[u'a']),
++ self.assertEqual(keys, ['a','b'])
++ self.assertEqual(request.form['b'], '1')
++ self.assertEqual(len(request.form['a']), 2)
++ self.assertEqual(request.form['a'][0]['x'], 5)
++ self.assertEqual(request.form['a'][0].x, 5)
++ self.assertEqual(request.form['a'][0]['y'], 51)
++ self.assertEqual(request.form['a'][0].y, 51)
++ self.assertEqual(request.form['a'][1]['x'], 6)
++ self.assertEqual(request.form['a'][1].x, 6)
++ self.assertEqual(request.form['a'][1]['y'], 61)
++ self.assertEqual(request.form['a'][1].y, 61)
++ self.assertEqual(str(request.form['a']),
+ "[{x: 5, y: 51}, {x: 6, y: 61}]")
+- self.assertEqual(repr(request.form[u'a']),
++ self.assertEqual(repr(request.form['a']),
+ "[{x: 5, y: 51}, {x: 6, y: 61}]")
+
+ def testFormListRecordTypes(self):
+ extra = {'QUERY_STRING':'a.x:list:record=5&a.x:list:record=6&b=1'}
+ request = self._createRequest(extra)
+ publish(request)
+- keys = request.form.keys()
++ keys = list(request.form.keys())
+ keys.sort()
+- self.assertEqual(keys, [u'a',u'b'])
+- self.assertEqual(request.form[u'b'], u'1')
+- self.assertEqual(request.form[u'a'].keys(), [u'x'])
+- self.assertEqual(request.form[u'a'][u'x'], [u'5',u'6'])
+- self.assertEqual(request.form[u'a'].x, [u'5',u'6'])
+- self.assertEqual(str(request.form[u'a']), "{x: [u'5', u'6']}")
+- self.assertEqual(repr(request.form[u'a']), "{x: [u'5', u'6']}")
++ self.assertEqual(keys, ['a','b'])
++ self.assertEqual(request.form['b'], '1')
++ self.assertEqual(list(request.form['a'].keys()), ['x'])
++ self.assertEqual(request.form['a']['x'], ['5','6'])
++ self.assertEqual(request.form['a'].x, ['5','6'])
++ self.assertEqual(str(request.form['a']), "{x: [u'5', u'6']}")
++ self.assertEqual(repr(request.form['a']), "{x: [u'5', u'6']}")
+
+ def testFormListTypes2(self):
+ extra = {'QUERY_STRING':'a=5&a=6&b=1'}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'a':[u'5',u'6'], u'b':u'1'})
++ self.assertEqual(request.form, {'a':['5','6'], 'b':'1'})
+
+ def testFormIntTypes(self):
+ extra = {'QUERY_STRING':'a:int=5&b:int=-5&c:int=0&d:int=-0'}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'a': 5, u'b': -5, u'c': 0, u'd': 0})
++ self.assertEqual(request.form, {'a': 5, 'b': -5, 'c': 0, 'd': 0})
+
+ extra = {'QUERY_STRING':'a:int='}
+ request = self._createRequest(extra)
+@@ -394,7 +394,7 @@ class BrowserTests(HTTPTests):
+ extra = {'QUERY_STRING':'a:float=5&b:float=-5.01&c:float=0'}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'a': 5.0, u'b': -5.01, u'c': 0.0})
++ self.assertEqual(request.form, {'a': 5.0, 'b': -5.01, 'c': 0.0})
+
+ extra = {'QUERY_STRING':'a:float='}
+ request = self._createRequest(extra)
+@@ -408,7 +408,7 @@ class BrowserTests(HTTPTests):
+ extra = {'QUERY_STRING':'a:long=99999999999999&b:long=0L'}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'a': 99999999999999, u'b': 0})
++ self.assertEqual(request.form, {'a': 99999999999999, 'b': 0})
+
+ extra = {'QUERY_STRING':'a:long='}
+ request = self._createRequest(extra)
+@@ -422,27 +422,27 @@ class BrowserTests(HTTPTests):
+ extra = {'QUERY_STRING':'a:tokens=a%20b%20c%20d&b:tokens='}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'a': [u'a', u'b', u'c', u'd'],
+- u'b': []})
++ self.assertEqual(request.form, {'a': ['a', 'b', 'c', 'd'],
++ 'b': []})
+
+ def testFormStringTypes(self):
+ extra = {'QUERY_STRING':'a:string=test&b:string='}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'a': u'test', u'b': u''})
++ self.assertEqual(request.form, {'a': 'test', 'b': ''})
+
+ def testFormLinesTypes(self):
+ extra = {'QUERY_STRING':'a:lines=a%0ab%0ac%0ad&b:lines='}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'a': [u'a', u'b', u'c', u'd'],
+- u'b': []})
++ self.assertEqual(request.form, {'a': ['a', 'b', 'c', 'd'],
++ 'b': []})
+
+ def testFormTextTypes(self):
+ extra = {'QUERY_STRING':'a:text=a%0a%0db%0d%0ac%0dd%0ae&b:text='}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'a': u'a\nb\nc\nd\ne', u'b': u''})
++ self.assertEqual(request.form, {'a': 'a\nb\nc\nd\ne', 'b': ''})
+
+ def testFormRequiredTypes(self):
+ extra = {'QUERY_STRING':'a:required=%20'}
+@@ -453,33 +453,33 @@ class BrowserTests(HTTPTests):
+ extra = {'QUERY_STRING':'a:boolean=&b:boolean=1&c:boolean=%20'}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'a': False, u'b': True, u'c': True})
++ self.assertEqual(request.form, {'a': False, 'b': True, 'c': True})
+
+ def testFormDefaults(self):
+ extra = {'QUERY_STRING':'a:default=10&a=6&b=1'}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'a':u'6', u'b':u'1'})
++ self.assertEqual(request.form, {'a':'6', 'b':'1'})
+
+ def testFormDefaults2(self):
+ extra = {'QUERY_STRING':'a:default=10&b=1'}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'a':u'10', u'b':u'1'})
++ self.assertEqual(request.form, {'a':'10', 'b':'1'})
+
+ def testFormFieldName(self):
+ extra = {'QUERY_STRING':'c+%2B%2F%3D%26c%3Aint=6',
+ 'PATH_INFO': '/folder/item3/'}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'c +/=&c': 6})
++ self.assertEqual(request.form, {'c +/=&c': 6})
+
+ def testFormFieldValue(self):
+ extra = {'QUERY_STRING':'a=b+%2B%2F%3D%26b%3Aint',
+ 'PATH_INFO': '/folder/item3/'}
+ request = self._createRequest(extra)
+ publish(request)
+- self.assertEqual(request.form, {u'a':u'b +/=&b:int'})
++ self.assertEqual(request.form, {'a':'b +/=&b:int'})
+
+ def testInterface(self):
+ request = self._createRequest()
+@@ -506,7 +506,7 @@ class BrowserTests(HTTPTests):
+ request = self._createRequest(extra)
+ publish(request)
+ self.assertEqual(request.headers.get('HTTP_REFERER'), 'http://localhost/')
+- self.assertEqual(request.form, {u'HTTP_REFERER': u'peter'})
++ self.assertEqual(request.form, {'HTTP_REFERER': 'peter'})
+
+
+ def test_post_body_not_consumed_unnecessarily(self):
+--- src/zope/publisher/tests/test_http.py.orig 2012-07-02 06:19:44 UTC
++++ src/zope/publisher/tests/test_http.py
+@@ -17,8 +17,8 @@
+ import sys
+ import tempfile
+ import unittest
+-from cStringIO import StringIO
+-from Cookie import CookieError
++from io import StringIO
++from http.cookies import CookieError
+ from doctest import DocFileSuite
+
+ import zope.event
+@@ -128,19 +128,19 @@ class HTTPInputStreamTests(unittest.TestCase):
+
+ # HTTPInputStream understands both CONTENT_LENGTH...
+ stream = HTTPInputStream(StringIO(data), {'CONTENT_LENGTH': '100000'})
+- self.assert_(isinstance(stream.getCacheStream(), TempFileType))
++ self.assertTrue(isinstance(stream.getCacheStream(), TempFileType))
+
+ # ... and HTTP_CONTENT_LENGTH.
+ stream = HTTPInputStream(StringIO(data), {'HTTP_CONTENT_LENGTH':
+ '100000'})
+- self.assert_(isinstance(stream.getCacheStream(), TempFileType))
++ self.assertTrue(isinstance(stream.getCacheStream(), TempFileType))
+
+ # If CONTENT_LENGTH is absent or empty, it takes the value
+ # given in HTTP_CONTENT_LENGTH:
+ stream = HTTPInputStream(StringIO(data),
+ {'CONTENT_LENGTH': '',
+ 'HTTP_CONTENT_LENGTH': '100000'})
+- self.assert_(isinstance(stream.getCacheStream(), TempFileType))
++ self.assertTrue(isinstance(stream.getCacheStream(), TempFileType))
+
+ # In fact, HTTPInputStream can be instantiated with both an
+ # empty CONTENT_LENGTH and an empty HTTP_CONTENT_LENGTH:
+@@ -165,7 +165,7 @@ class HTTPInputStreamTests(unittest.TestCase):
+ return 'a'*size
+
+ stream = HTTPInputStream(NonClosingStream(), {'CONTENT_LENGTH': '10'})
+- self.assertEquals(stream.getCacheStream().read(), 'aaaaaaaaaa')
++ self.assertEqual(stream.getCacheStream().read(), 'aaaaaaaaaa')
+ stream = HTTPInputStream(NonClosingStream(), {})
+ self.assertRaises(ServerHung, stream.getCacheStream)
+
+@@ -194,7 +194,7 @@ class HTTPTests(unittest.TestCase):
+ class Item(object):
+ """Required docstring for the publisher."""
+ def __call__(self, a, b):
+- return "%s, %s" % (`a`, `b`)
++ return "%s, %s" % (repr(a), repr(b))
+
+ self.app = AppRoot()
+ self.app.folder = Folder()
+@@ -252,7 +252,7 @@ class HTTPTests(unittest.TestCase):
+
+ def testTraversalToItem(self):
+ res = self._publisherResults()
+- self.failUnlessEqual(
++ self.assertEqual(
+ res,
+ "Status: 200 Ok\r\n"
+ "Content-Length: 6\r\n"
+@@ -266,27 +266,27 @@ class HTTPTests(unittest.TestCase):
+
+ request = self._createRequest(env, '')
+ location = request.response.redirect('http://foobar.com/redirected')
+- self.assertEquals(location, 'http://foobar.com/redirected')
+- self.assertEquals(request.response.getStatus(), 302)
+- self.assertEquals(request.response.getHeader('location'), location)
++ self.assertEqual(location, 'http://foobar.com/redirected')
++ self.assertEqual(request.response.getStatus(), 302)
++ self.assertEqual(request.response.getHeader('location'), location)
+
+ # test HTTP/1.1
+ env = {'SERVER_PROTOCOL':'HTTP/1.1'}
+
+ request = self._createRequest(env, '')
+ location = request.response.redirect('http://foobar.com/redirected')
+- self.assertEquals(request.response.getStatus(), 303)
++ self.assertEqual(request.response.getStatus(), 303)
+
+ # test explicit status
+ request = self._createRequest(env, '')
+ request.response.redirect('http://foobar.com/explicit', 304)
+- self.assertEquals(request.response.getStatus(), 304)
++ self.assertEqual(request.response.getStatus(), 304)
+
+ # test non-string location, like URLGetter
+ request = self._createRequest(env, '')
+ request.response.redirect(request.URL)
+- self.assertEquals(request.response.getStatus(), 303)
+- self.assertEquals(request.response.getHeader('location'),
++ self.assertEqual(request.response.getStatus(), 303)
++ self.assertEqual(request.response.getHeader('location'),
+ str(request.URL))
+
+ def testUntrustedRedirect(self):
+@@ -301,81 +301,81 @@ class HTTPTests(unittest.TestCase):
+ # host. They aren't really allowed per RFC but the response object
+ # supports them and people are probably using them.
+ location = request.response.redirect('/foo', trusted=False)
+- self.assertEquals('/foo', location)
++ self.assertEqual('/foo', location)
+
+ # If we pass `trusted` for the redirect, we can redirect the browser
+ # anywhere we want, though.
+ location = request.response.redirect(
+ 'http://my-friends.com', trusted=True)
+- self.assertEquals('http://my-friends.com', location)
++ self.assertEqual('http://my-friends.com', location)
+
+ # We can redirect to our own full server URL, with or without a port
+ # being specified. Let's explicitly set a host name to test this is
+ # this is how virtual hosting works:
+ request.setApplicationServer('example.com')
+ location = request.response.redirect('http://example.com')
+- self.assertEquals('http://example.com', location)
++ self.assertEqual('http://example.com', location)
+
+ request.setApplicationServer('example.com', port=8080)
+ location = request.response.redirect('http://example.com:8080')
+- self.assertEquals('http://example.com:8080', location)
++ self.assertEqual('http://example.com:8080', location)
+
+ # The default port for HTTP and HTTPS may be omitted:
+ request.setApplicationServer('example.com')
+ location = request.response.redirect('http://example.com:80')
+- self.assertEquals('http://example.com:80', location)
++ self.assertEqual('http://example.com:80', location)
+
+ request.setApplicationServer('example.com', port=80)
+ location = request.response.redirect('http://example.com')
+- self.assertEquals('http://example.com', location)
++ self.assertEqual('http://example.com', location)
+
+ request.setApplicationServer('example.com', 'https')
+ location = request.response.redirect('https://example.com:443')
+- self.assertEquals('https://example.com:443', location)
++ self.assertEqual('https://example.com:443', location)
+
+ request.setApplicationServer('example.com', 'https', 443)
+ location = request.response.redirect('https://example.com')
+- self.assertEquals('https://example.com', location)
++ self.assertEqual('https://example.com', location)
+
+ def testUnregisteredStatus(self):
+ # verify we can set the status to an unregistered int value
+ request = self._createRequest({}, '')
+ request.response.setStatus(289)
+- self.assertEquals(request.response.getStatus(), 289)
++ self.assertEqual(request.response.getStatus(), 289)
+
+ def testRequestEnvironment(self):
+ req = self._createRequest()
+ publish(req, handle_errors=0) # Force expansion of URL variables
+
+- self.assertEquals(str(req.URL), 'http://foobar.com/folder/item')
+- self.assertEquals(req.URL['-1'], 'http://foobar.com/folder')
+- self.assertEquals(req.URL['-2'], 'http://foobar.com')
++ self.assertEqual(str(req.URL), 'http://foobar.com/folder/item')
++ self.assertEqual(req.URL['-1'], 'http://foobar.com/folder')
++ self.assertEqual(req.URL['-2'], 'http://foobar.com')
+ self.assertRaises(KeyError, req.URL.__getitem__, '-3')
+
+- self.assertEquals(req.URL['0'], 'http://foobar.com')
+- self.assertEquals(req.URL['1'], 'http://foobar.com/folder')
+- self.assertEquals(req.URL['2'], 'http://foobar.com/folder/item')
++ self.assertEqual(req.URL['0'], 'http://foobar.com')
++ self.assertEqual(req.URL['1'], 'http://foobar.com/folder')
++ self.assertEqual(req.URL['2'], 'http://foobar.com/folder/item')
+ self.assertRaises(KeyError, req.URL.__getitem__, '3')
+
+- self.assertEquals(req.URL.get('0'), 'http://foobar.com')
+- self.assertEquals(req.URL.get('1'), 'http://foobar.com/folder')
+- self.assertEquals(req.URL.get('2'), 'http://foobar.com/folder/item')
+- self.assertEquals(req.URL.get('3', 'none'), 'none')
++ self.assertEqual(req.URL.get('0'), 'http://foobar.com')
++ self.assertEqual(req.URL.get('1'), 'http://foobar.com/folder')
++ self.assertEqual(req.URL.get('2'), 'http://foobar.com/folder/item')
++ self.assertEqual(req.URL.get('3', 'none'), 'none')
+
+- self.assertEquals(req['SERVER_URL'], 'http://foobar.com')
+- self.assertEquals(req['HTTP_HOST'], 'foobar.com')
+- self.assertEquals(req['PATH_INFO'], '/folder/item')
+- self.assertEquals(req['CONTENT_LENGTH'], '0')
++ self.assertEqual(req['SERVER_URL'], 'http://foobar.com')
++ self.assertEqual(req['HTTP_HOST'], 'foobar.com')
++ self.assertEqual(req['PATH_INFO'], '/folder/item')
++ self.assertEqual(req['CONTENT_LENGTH'], '0')
+ self.assertRaises(KeyError, req.__getitem__, 'HTTP_AUTHORIZATION')
+- self.assertEquals(req['GATEWAY_INTERFACE'], 'TestFooInterface/1.0')
+- self.assertEquals(req['HTTP_OFF_THE_WALL'], "Spam 'n eggs")
++ self.assertEqual(req['GATEWAY_INTERFACE'], 'TestFooInterface/1.0')
++ self.assertEqual(req['HTTP_OFF_THE_WALL'], "Spam 'n eggs")
+
+ self.assertRaises(KeyError, req.__getitem__,
+ 'HTTP_WE_DID_NOT_PROVIDE_THIS')
+
+ def testRequestLocale(self):
+ eq = self.assertEqual
+- unless = self.failUnless
++ unless = self.assertTrue
+
+ from zope.publisher.browser import BrowserLanguages
+ from zope.publisher.interfaces.http import IHTTPRequest
+@@ -448,17 +448,17 @@ class HTTPTests(unittest.TestCase):
+ }
+ req = self._createRequest(extra_env=cookies)
+
+- self.assertEquals(req.cookies[u'foo'], u'bar')
+- self.assertEquals(req[u'foo'], u'bar')
++ self.assertEqual(req.cookies['foo'], 'bar')
++ self.assertEqual(req['foo'], 'bar')
+
+- self.assertEquals(req.cookies[u'spam'], u'eggs')
+- self.assertEquals(req[u'spam'], u'eggs')
++ self.assertEqual(req.cookies['spam'], 'eggs')
++ self.assertEqual(req['spam'], 'eggs')
+
+- self.assertEquals(req.cookies[u'this'], u'Should be accepted')
+- self.assertEquals(req[u'this'], u'Should be accepted')
++ self.assertEqual(req.cookies['this'], 'Should be accepted')
++ self.assertEqual(req['this'], 'Should be accepted')
+
+ # Reserved key
+- self.failIf(req.cookies.has_key('path'))
++ self.assertFalse('path' in req.cookies)
+
+ def testCookieErrorToLog(self):
+ cookies = {
+@@ -467,23 +467,23 @@ class HTTPTests(unittest.TestCase):
+ }
+ req = self._createRequest(extra_env=cookies)
+
+- self.failIf(req.cookies.has_key('foo'))
+- self.failIf(req.has_key('foo'))
++ self.assertFalse('foo' in req.cookies)
++ self.assertFalse('foo' in req)
+
+- self.failIf(req.cookies.has_key('spam'))
+- self.failIf(req.has_key('spam'))
++ self.assertFalse('spam' in req.cookies)
++ self.assertFalse('spam' in req)
+
+- self.failIf(req.cookies.has_key('ldap/OU'))
+- self.failIf(req.has_key('ldap/OU'))
++ self.assertFalse('ldap/OU' in req.cookies)
++ self.assertFalse('ldap/OU' in req)
+
+ # Reserved key
+- self.failIf(req.cookies.has_key('path'))
++ self.assertFalse('path' in req.cookies)
+
+ def testCookiesUnicode(self):
+ # Cookie values are assumed to be UTF-8 encoded
+ cookies = {'HTTP_COOKIE': r'key="\342\230\243";'}
+ req = self._createRequest(extra_env=cookies)
+- self.assertEquals(req.cookies[u'key'], u'\N{BIOHAZARD SIGN}')
++ self.assertEqual(req.cookies['key'], '\N{BIOHAZARD SIGN}')
+
+ def testHeaders(self):
+ headers = {
+@@ -491,13 +491,13 @@ class HTTPTests(unittest.TestCase):
+ 'Another-Test': 'another',
+ }
+ req = self._createRequest(extra_env=headers)
+- self.assertEquals(req.headers[u'TEST_HEADER'], u'test')
+- self.assertEquals(req.headers[u'TEST-HEADER'], u'test')
+- self.assertEquals(req.headers[u'test_header'], u'test')
+- self.assertEquals(req.getHeader('TEST_HEADER', literal=True), u'test')
+- self.assertEquals(req.getHeader('TEST-HEADER', literal=True), None)
+- self.assertEquals(req.getHeader('test_header', literal=True), None)
+- self.assertEquals(req.getHeader('Another-Test', literal=True),
++ self.assertEqual(req.headers['TEST_HEADER'], 'test')
++ self.assertEqual(req.headers['TEST-HEADER'], 'test')
++ self.assertEqual(req.headers['test_header'], 'test')
++ self.assertEqual(req.getHeader('TEST_HEADER', literal=True), 'test')
++ self.assertEqual(req.getHeader('TEST-HEADER', literal=True), None)
++ self.assertEqual(req.getHeader('test_header', literal=True), None)
++ self.assertEqual(req.getHeader('Another-Test', literal=True),
+ 'another')
+
+ def testBasicAuth(self):
+@@ -505,19 +505,19 @@ class HTTPTests(unittest.TestCase):
+ req = self._createRequest()
+ verifyObject(IHTTPCredentials, req)
+ lpq = req._authUserPW()
+- self.assertEquals(lpq, None)
++ self.assertEqual(lpq, None)
+ env = {}
+ login, password = ("tim", "123:456")
+ s = ("%s:%s" % (login, password)).encode("base64").rstrip()
+ env['HTTP_AUTHORIZATION'] = "Basic %s" % s
+ req = self._createRequest(env)
+ lpw = req._authUserPW()
+- self.assertEquals(lpw, (login, password))
++ self.assertEqual(lpw, (login, password))
+
+ def testSetPrincipal(self):
+ req = self._createRequest()
+ req.setPrincipal(UserStub("jim"))
+- self.assertEquals(req.response.authUser, 'jim')
++ self.assertEqual(req.response.authUser, 'jim')
+
+ def test_method(self):
+ r = self._createRequest(extra_env={'REQUEST_METHOD':'SPAM'})
+@@ -530,25 +530,25 @@ class HTTPTests(unittest.TestCase):
+ zope.event.subscribers.append(events.append)
+ req = self._createRequest()
+ req.setApplicationServer('foo')
+- self.assertEquals(req._app_server, 'http://foo')
++ self.assertEqual(req._app_server, 'http://foo')
+ req.setApplicationServer('foo', proto='https')
+- self.assertEquals(req._app_server, 'https://foo')
++ self.assertEqual(req._app_server, 'https://foo')
+ req.setApplicationServer('foo', proto='https', port=8080)
+- self.assertEquals(req._app_server, 'https://foo:8080')
++ self.assertEqual(req._app_server, 'https://foo:8080')
+ req.setApplicationServer('foo', proto='http', port='9673')
+- self.assertEquals(req._app_server, 'http://foo:9673')
++ self.assertEqual(req._app_server, 'http://foo:9673')
+ req.setApplicationServer('foo', proto='https', port=443)
+- self.assertEquals(req._app_server, 'https://foo')
++ self.assertEqual(req._app_server, 'https://foo')
+ req.setApplicationServer('foo', proto='https', port='443')
+- self.assertEquals(req._app_server, 'https://foo')
++ self.assertEqual(req._app_server, 'https://foo')
+ req.setApplicationServer('foo', port=80)
+- self.assertEquals(req._app_server, 'http://foo')
++ self.assertEqual(req._app_server, 'http://foo')
+ req.setApplicationServer('foo', proto='telnet', port=80)
+- self.assertEquals(req._app_server, 'telnet://foo:80')
++ self.assertEqual(req._app_server, 'telnet://foo:80')
+ zope.event.subscribers.pop()
+- self.assertEquals(len(events), 8)
++ self.assertEqual(len(events), 8)
+ for event in events:
+- self.assertEquals(event.request, req)
++ self.assertEqual(event.request, req)
+
+ def test_setApplicationNames(self):
+ events = []
+@@ -556,12 +556,12 @@ class HTTPTests(unittest.TestCase):
+ req = self._createRequest()
+ names = ['x', 'y', 'z']
+ req.setVirtualHostRoot(names)
+- self.assertEquals(req._app_names, ['x', 'y', 'z'])
++ self.assertEqual(req._app_names, ['x', 'y', 'z'])
+ names[0] = 'muahahahaha'
+- self.assertEquals(req._app_names, ['x', 'y', 'z'])
++ self.assertEqual(req._app_names, ['x', 'y', 'z'])
+ zope.event.subscribers.pop()
+- self.assertEquals(len(events), 1)
+- self.assertEquals(events[0].request, req)
++ self.assertEqual(len(events), 1)
++ self.assertEqual(events[0].request, req)
+
+ def test_setVirtualHostRoot(self):
+ events = []
+@@ -570,22 +570,22 @@ class HTTPTests(unittest.TestCase):
+ req._traversed_names = ['x', 'y']
+ req._last_obj_traversed = object()
+ req.setVirtualHostRoot()
+- self.failIf(req._traversed_names)
+- self.assertEquals(req._vh_root, req._last_obj_traversed)
++ self.assertFalse(req._traversed_names)
++ self.assertEqual(req._vh_root, req._last_obj_traversed)
+ zope.event.subscribers.pop()
+- self.assertEquals(len(events), 1)
+- self.assertEquals(events[0].request, req)
++ self.assertEqual(len(events), 1)
++ self.assertEqual(events[0].request, req)
+
+ def test_getVirtualHostRoot(self):
+ req = self._createRequest()
+- self.assertEquals(req.getVirtualHostRoot(), None)
++ self.assertEqual(req.getVirtualHostRoot(), None)
+ req._vh_root = object()
+- self.assertEquals(req.getVirtualHostRoot(), req._vh_root)
++ self.assertEqual(req.getVirtualHostRoot(), req._vh_root)
+
+ def test_traverse(self):
+ req = self._createRequest()
+ req.traverse(self.app)
+- self.assertEquals(req._traversed_names, ['folder', 'item'])
++ self.assertEqual(req._traversed_names, ['folder', 'item'])
+
+ # setting it during traversal matters
+ req = self._createRequest()
+@@ -594,8 +594,8 @@ class HTTPTests(unittest.TestCase):
+ req.setVirtualHostRoot()
+ req.publication.callTraversalHooks = hook
+ req.traverse(self.app)
+- self.assertEquals(req._traversed_names, ['item'])
+- self.assertEquals(req._vh_root, self.app.folder)
++ self.assertEqual(req._traversed_names, ['item'])
++ self.assertEqual(req._vh_root, self.app.folder)
+
+ def test_traverseDuplicateHooks(self):
+ """
+@@ -620,7 +620,7 @@ class HTTPTests(unittest.TestCase):
+ req.setPublication(publication)
+ req.setTraversalStack(req.getTraversalStack() + ["vh"])
+ req.traverse(self.app)
+- self.assertEquals(len(hooks), 3)
++ self.assertEqual(len(hooks), 3)
+
+ def testInterface(self):
+ from zope.publisher.interfaces.http import IHTTPCredentials
+@@ -634,31 +634,31 @@ class HTTPTests(unittest.TestCase):
+ req = self._createRequest()
+ deduceServerURL = req._HTTPRequest__deduceServerURL
+ req._environ = {'HTTP_HOST': 'example.com:80'}
+- self.assertEquals(deduceServerURL(), 'http://example.com')
++ self.assertEqual(deduceServerURL(), 'http://example.com')
+ req._environ = {'HTTP_HOST': 'example.com:8080'}
+- self.assertEquals(deduceServerURL(), 'http://example.com:8080')
++ self.assertEqual(deduceServerURL(), 'http://example.com:8080')
+ req._environ = {'HTTP_HOST': 'example.com:443', 'HTTPS': 'on'}
+- self.assertEquals(deduceServerURL(), 'https://example.com')
++ self.assertEqual(deduceServerURL(), 'https://example.com')
+ req._environ = {'HTTP_HOST': 'example.com:80', 'HTTPS': 'ON'}
+- self.assertEquals(deduceServerURL(), 'https://example.com:80')
++ self.assertEqual(deduceServerURL(), 'https://example.com:80')
+ req._environ = {'HTTP_HOST': 'example.com:8080',
+ 'SERVER_PORT_SECURE': '1'}
+- self.assertEquals(deduceServerURL(), 'https://example.com:8080')
++ self.assertEqual(deduceServerURL(), 'https://example.com:8080')
+ req._environ = {'SERVER_NAME': 'example.com', 'SERVER_PORT':'8080',
+ 'SERVER_PORT_SECURE': '0'}
+- self.assertEquals(deduceServerURL(), 'http://example.com:8080')
++ self.assertEqual(deduceServerURL(), 'http://example.com:8080')
+ req._environ = {'SERVER_NAME': 'example.com'}
+- self.assertEquals(deduceServerURL(), 'http://example.com')
++ self.assertEqual(deduceServerURL(), 'http://example.com')
+
+ def testUnicodeURLs(self):
+ # The request expects PATH_INFO to be utf-8 encoded when it gets it.
+ req = self._createRequest(
+ {'PATH_INFO': '/\xc3\xa4\xc3\xb6/\xc3\xbc\xc3\x9f/foo/bar.html'})
+ self.assertEqual(req._traversal_stack,
+- [u'bar.html', u'foo', u'\u00fc\u00df', u'\u00e4\u00f6'])
++ ['bar.html', 'foo', '\u00fc\u00df', '\u00e4\u00f6'])
+ # the request should have converted PATH_INFO to unicode
+ self.assertEqual(req['PATH_INFO'],
+- u'/\u00e4\u00f6/\u00fc\u00df/foo/bar.html')
++ '/\u00e4\u00f6/\u00fc\u00df/foo/bar.html')
+
+ def testResponseWriteFaile(self):
+ self.assertRaises(TypeError,
+@@ -673,7 +673,7 @@ class HTTPTests(unittest.TestCase):
+ def test_unacceptable_charset(self):
+ # Regression test for https://bugs.launchpad.net/zope3/+bug/98337
+ request = self._createRequest({'HTTP_ACCEPT_CHARSET': 'ISO-8859-1'})
+- result = u"Latin a with ogonek\u0105 Cyrillic ya \u044f"
++ result = "Latin a with ogonek\u0105 Cyrillic ya \u044f"
+ provideAdapter(HTTPCharsets)
+ request.response.setHeader('Content-Type', 'text/plain')
+
+@@ -682,10 +682,10 @@ class HTTPTests(unittest.TestCase):
+ request.response.setResult(result)
+
+ body = request.response.consumeBody()
+- self.assertEquals(request.response.getStatus(), 200)
+- self.assertEquals(request.response.getHeader('Content-Type'),
++ self.assertEqual(request.response.getStatus(), 200)
++ self.assertEqual(request.response.getHeader('Content-Type'),
+ 'text/plain;charset=utf-8')
+- self.assertEquals(body,
++ self.assertEqual(body,
+ 'Latin a with ogonek\xc4\x85 Cyrillic ya \xd1\x8f')
+
+ class ConcreteHTTPTests(HTTPTests):
+@@ -704,7 +704,7 @@ class ConcreteHTTPTests(HTTPTests):
+ r = self._createRequest(extra_env={"PATH_INFO": "/xxx"})
+ publish(r, handle_errors=0)
+ r.shiftNameToApplication()
+- self.assertEquals(r.getApplicationURL(), appurl+"/xxx")
++ self.assertEqual(r.getApplicationURL(), appurl+"/xxx")
+
+ # Verify that we can only shift if we've traversed only a single name
+ r = self._createRequest(extra_env={"PATH_INFO": "/folder/item"})
+@@ -732,7 +732,7 @@ class TestHTTPResponse(unittest.TestCase):
+ response = self._createResponse()
+ assert(charset == 'utf-8')
+ if headers is not None:
+- for hdr, val in headers.iteritems():
++ for hdr, val in headers.items():
+ response.setHeader(hdr, val)
+ response.setResult(body)
+ return self._parseResult(response)
+@@ -755,10 +755,10 @@ class TestHTTPResponse(unittest.TestCase):
+ self.assertEqual(body, data)
+
+ # Make sure that no Content-Length header was added
+- self.assert_('Content-Length' not in headers)
++ self.assertTrue('Content-Length' not in headers)
+
+ def testContentLength(self):
+- eq = self.failUnlessEqual
++ eq = self.assertEqual
+
+ headers, body = self._getResultFromResponse("test", "utf-8",
+ {"content-type": "text/plain"})
+@@ -766,29 +766,29 @@ class TestHTTPResponse(unittest.TestCase):
+ eq("test", body)
+
+ headers, body = self._getResultFromResponse(
+- u'\u0442\u0435\u0441\u0442', "utf-8",
++ '\u0442\u0435\u0441\u0442', "utf-8",
+ {"content-type": "text/plain"})
+ eq("8", headers["Content-Length"])
+ eq('\xd1\x82\xd0\xb5\xd1\x81\xd1\x82', body)
+
+ def testContentType(self):
+- eq = self.failUnlessEqual
++ eq = self.assertEqual
+
+ headers, body = self._getResultFromResponse("test", "utf-8")
+ eq("", headers.get("Content-Type", ""))
+ eq("test", body)
+
+- headers, body = self._getResultFromResponse(u"test",
++ headers, body = self._getResultFromResponse("test",
+ headers={"content-type": "text/plain"})
+ eq("text/plain;charset=utf-8", headers["Content-Type"])
+ eq("test", body)
+
+- headers, body = self._getResultFromResponse(u"test", "utf-8",
++ headers, body = self._getResultFromResponse("test", "utf-8",
+ {"content-type": "text/html"})
+ eq("text/html;charset=utf-8", headers["Content-Type"])
+ eq("test", body)
+
+- headers, body = self._getResultFromResponse(u"test", "utf-8",
++ headers, body = self._getResultFromResponse("test", "utf-8",
+ {"content-type": "text/plain;charset=cp1251"})
+ eq("text/plain;charset=cp1251", headers["Content-Type"])
+ eq("test", body)
+@@ -796,30 +796,30 @@ class TestHTTPResponse(unittest.TestCase):
+ # see https://bugs.launchpad.net/zope.publisher/+bug/98395
+ # RFC 3023 types and */*+xml output as unicode
+
+- headers, body = self._getResultFromResponse(u"test", "utf-8",
++ headers, body = self._getResultFromResponse("test", "utf-8",
+ {"content-type": "text/xml"})
+ eq("text/xml;charset=utf-8", headers["Content-Type"])
+ eq("test", body)
+
+- headers, body = self._getResultFromResponse(u"test", "utf-8",
++ headers, body = self._getResultFromResponse("test", "utf-8",
+ {"content-type": "application/xml"})
+ eq("application/xml;charset=utf-8", headers["Content-Type"])
+ eq("test", body)
+
+- headers, body = self._getResultFromResponse(u"test", "utf-8",
++ headers, body = self._getResultFromResponse("test", "utf-8",
+ {"content-type": "text/xml-external-parsed-entity"})
+ eq("text/xml-external-parsed-entity;charset=utf-8",
+ headers["Content-Type"])
+ eq("test", body)
+
+- headers, body = self._getResultFromResponse(u"test", "utf-8",
++ headers, body = self._getResultFromResponse("test", "utf-8",
+ {"content-type": "application/xml-external-parsed-entity"})
+ eq("application/xml-external-parsed-entity;charset=utf-8",
+ headers["Content-Type"])
+ eq("test", body)
+
+ # Mozilla XUL
+- headers, body = self._getResultFromResponse(u"test", "utf-8",
++ headers, body = self._getResultFromResponse("test", "utf-8",
+ {"content-type": "application/vnd+xml"})
+ eq("application/vnd+xml;charset=utf-8", headers["Content-Type"])
+ eq("test", body)
+@@ -846,20 +846,20 @@ class TestHTTPResponse(unittest.TestCase):
+ c = self._getCookieFromResponse([
+ ('foo', 'bar', {}),
+ ])
+- self.failUnless('foo=bar;' in c or 'foo=bar' in c,
++ self.assertTrue('foo=bar;' in c or 'foo=bar' in c,
+ 'foo=bar; not in %r' % c)
+
+ c = self._getCookieFromResponse([
+ ('foo', 'bar', {}),
+ ('alpha', 'beta', {}),
+ ])
+- self.failUnless('foo=bar;' in c or 'foo=bar' in c)
+- self.failUnless('alpha=beta;' in c or 'alpha=beta' in c)
++ self.assertTrue('foo=bar;' in c or 'foo=bar' in c)
++ self.assertTrue('alpha=beta;' in c or 'alpha=beta' in c)
+
+ c = self._getCookieFromResponse([
+- ('sign', u'\N{BIOHAZARD SIGN}', {}),
++ ('sign', '\N{BIOHAZARD SIGN}', {}),
+ ])
+- self.failUnless((r'sign="\342\230\243";' in c) or
++ self.assertTrue((r'sign="\342\230\243";' in c) or
+ (r'sign="\342\230\243"' in c))
+
+ self.assertRaises(
+@@ -874,21 +874,21 @@ class TestHTTPResponse(unittest.TestCase):
+ 'domain': 'example.com',
+ 'pAth': '/froboz',
+ 'max_age': 3600,
+- 'comment': u'blah;\N{BIOHAZARD SIGN}?',
++ 'comment': 'blah;\N{BIOHAZARD SIGN}?',
+ 'seCure': True,
+ }),
+ ])[0]
+- self.failUnless('foo=bar;' in c or 'foo=bar' in c)
+- self.failUnless('expires=Sat, 12 Jul 2014 23:26:28 GMT;' in c, repr(c))
+- self.failUnless('Domain=example.com;' in c)
+- self.failUnless('Path=/froboz;' in c)
+- self.failUnless('Max-Age=3600;' in c)
+- self.failUnless('Comment=blah%3B%E2%98%A3?;' in c, repr(c))
+- self.failUnless('secure;' in c or 'secure' in c)
++ self.assertTrue('foo=bar;' in c or 'foo=bar' in c)
++ self.assertTrue('expires=Sat, 12 Jul 2014 23:26:28 GMT;' in c, repr(c))
++ self.assertTrue('Domain=example.com;' in c)
++ self.assertTrue('Path=/froboz;' in c)
++ self.assertTrue('Max-Age=3600;' in c)
++ self.assertTrue('Comment=blah%3B%E2%98%A3?;' in c, repr(c))
++ self.assertTrue('secure;' in c or 'secure' in c)
+
+ c = self._getCookieFromResponse([('foo', 'bar', {'secure': False})])[0]
+- self.failUnless('foo=bar;' in c or 'foo=bar' in c)
+- self.failIf('secure' in c)
++ self.assertTrue('foo=bar;' in c or 'foo=bar' in c)
++ self.assertFalse('secure' in c)
+
+ def test_handleException(self):
+ response = HTTPResponse()
+@@ -898,10 +898,10 @@ class TestHTTPResponse(unittest.TestCase):
+ exc_info = sys.exc_info()
+
+ response.handleException(exc_info)
+- self.assertEquals(response.getHeader("content-type"),
++ self.assertEqual(response.getHeader("content-type"),
+ "text/html;charset=utf-8")
+- self.assertEquals(response.getStatus(), 500)
+- self.assert_(response.consumeBody() in
++ self.assertEqual(response.getStatus(), 500)
++ self.assertTrue(response.consumeBody() in
+ [""
+ "<type 'exceptions.ValueError'>\n"
+ "<type 'exceptions.ValueError'>
\n"
+--- src/zope/publisher/tests/test_xmlrpcrequest.py.orig 2012-07-02 06:19:44 UTC
++++ src/zope/publisher/tests/test_xmlrpcrequest.py
+@@ -14,7 +14,7 @@
+ """XML-RPC Request Tests
+ """
+ import unittest
+-from StringIO import StringIO
++from io import StringIO
+
+ from zope.publisher.base import DefaultPublication
+ from zope.publisher.http import HTTPCharsets
+@@ -39,7 +39,7 @@ class TestXMLRPCRequest(XMLRPCRequest, HTTPCharsets):
+ XMLRPCRequest.__init__(self, *args, **kw)
+
+
+-xmlrpc_call = u'''
++xmlrpc_call = '''
+
+ action
+
+@@ -81,7 +81,7 @@ class XMLRPCTests(unittest.TestCase):
+ class Item(object):
+
+ def __call__(self, a, b):
+- return "%s, %s" % (`a`, `b`)
++ return "%s, %s" % (repr(a), repr(b))
+
+ def doit(self, a, b):
+ return 'do something %s %s' % (a, b)
+@@ -90,7 +90,7 @@ class XMLRPCTests(unittest.TestCase):
+
+ def action(self, a):
+ return "Parameter[type: %s; value: %s" %(
+- type(a).__name__, `a`)
++ type(a).__name__, repr(a))
+
+ class Item2(object):
+ view = View()
+@@ -118,15 +118,15 @@ class XMLRPCTests(unittest.TestCase):
+ def testProcessInput(self):
+ req = self._createRequest({}, xmlrpc_call)
+ req.processInputs()
+- self.failUnlessEqual(req.getPositionalArguments(), (1,))
+- self.failUnlessEqual(tuple(req._path_suffix), ('action',))
++ self.assertEqual(req.getPositionalArguments(), (1,))
++ self.assertEqual(tuple(req._path_suffix), ('action',))
+
+
+ def testTraversal(self):
+ req = self._createRequest({}, xmlrpc_call)
+ req.processInputs()
+ action = req.traverse(self.app)
+- self.failUnlessEqual(action(*req.getPositionalArguments()),
++ self.assertEqual(action(*req.getPositionalArguments()),
+ "Parameter[type: int; value: 1")
+
+
+--- src/zope/publisher/xmlrpc.py.orig 2012-07-02 06:19:44 UTC
++++ src/zope/publisher/xmlrpc.py
+@@ -18,9 +18,9 @@ This module contains the XMLRPCRequest and XMLRPCRespo
+ __docformat__ = 'restructuredtext'
+
+ import sys
+-import xmlrpclib
++import xmlrpc.client
+ import datetime
+-from StringIO import StringIO
++from io import StringIO
+
+ import zope.component
+ import zope.interface
+@@ -53,7 +53,7 @@ class XMLRPCRequest(HTTPRequest):
+ if not line:
+ break
+ lines += line
+- self._args, function = xmlrpclib.loads(lines)
++ self._args, function = xmlrpc.client.loads(lines)
+
+ # Translate '.' to '/' in function to represent object traversal.
+ function = function.split('.')
+@@ -102,15 +102,15 @@ class XMLRPCResponse(HTTPResponse):
+ message instead of a generic HTML page.
+ """
+ body = premarshal(result)
+- if isinstance(body, xmlrpclib.Fault):
++ if isinstance(body, xmlrpc.client.Fault):
+ # Convert Fault object to XML-RPC response.
+- body = xmlrpclib.dumps(body, methodresponse=True)
++ body = xmlrpc.client.dumps(body, methodresponse=True)
+ else:
+ # Marshall our body as an XML-RPC response. Strings will be sent
+ # as strings, integers as integers, etc. We do *not* convert
+ # everything to a string first.
+ try:
+- body = xmlrpclib.dumps((body,), methodresponse=True,
++ body = xmlrpc.client.dumps((body,), methodresponse=True,
+ allow_none=True)
+ except:
+ # We really want to catch all exceptions at this point!
+@@ -148,7 +148,7 @@ class XMLRPCResponse(HTTPResponse):
+ # Create an appropriate Fault object. Unfortunately, we throw away
+ # most of the debugging information. More useful error reporting is
+ # left as an exercise for the reader.
+- Fault = xmlrpclib.Fault
++ Fault = xmlrpc.client.Fault
+ fault_text = None
+ try:
+ if isinstance(value, Fault):
+@@ -183,7 +183,7 @@ class PreMarshallerBase(object):
+ self.data = data
+
+ def __call__(self):
+- raise Exception, "Not implemented"
++ raise Exception("Not implemented")
+
+ class DictPreMarshaller(PreMarshallerBase):
+ """Pre-marshaller for dicts"""
+@@ -191,48 +191,48 @@ class DictPreMarshaller(PreMarshallerBase):
+
+ def __call__(self):
+ return dict([(premarshal(k), premarshal(v))
+- for (k, v) in self.data.items()])
++ for (k, v) in list(self.data.items())])
+
+ class ListPreMarshaller(PreMarshallerBase):
+ """Pre-marshaller for list"""
+ zope.component.adapts(list)
+
+ def __call__(self):
+- return map(premarshal, self.data)
++ return list(map(premarshal, self.data))
+
+ class TuplePreMarshaller(ListPreMarshaller):
+ zope.component.adapts(tuple)
+
+ class BinaryPreMarshaller(PreMarshallerBase):
+ """Pre-marshaller for xmlrpc.Binary"""
+- zope.component.adapts(xmlrpclib.Binary)
++ zope.component.adapts(xmlrpc.client.Binary)
+
+ def __call__(self):
+- return xmlrpclib.Binary(self.data.data)
++ return xmlrpc.client.Binary(self.data.data)
+
+ class FaultPreMarshaller(PreMarshallerBase):
+ """Pre-marshaller for xmlrpc.Fault"""
+- zope.component.adapts(xmlrpclib.Fault)
++ zope.component.adapts(xmlrpc.client.Fault)
+
+ def __call__(self):
+- return xmlrpclib.Fault(
++ return xmlrpc.client.Fault(
+ premarshal(self.data.faultCode),
+ premarshal(self.data.faultString),
+ )
+
+ class DateTimePreMarshaller(PreMarshallerBase):
+ """Pre-marshaller for xmlrpc.DateTime"""
+- zope.component.adapts(xmlrpclib.DateTime)
++ zope.component.adapts(xmlrpc.client.DateTime)
+
+ def __call__(self):
+- return xmlrpclib.DateTime(self.data.value)
++ return xmlrpc.client.DateTime(self.data.value)
+
+ class PythonDateTimePreMarshaller(PreMarshallerBase):
+ """Pre-marshaller for datetime.datetime"""
+ zope.component.adapts(datetime.datetime)
+
+ def __call__(self):
+- return xmlrpclib.DateTime(self.data.isoformat())
++ return xmlrpc.client.DateTime(self.data.isoformat())
+
+ def premarshal(data):
+ """Premarshal data before handing it to xmlrpclib for marhalling