Нашли.
Изменения должны быть сделаны в cptestcase. Суть проблемы заключается в том, что этот рецепт в некоторой степени зависит от внутренней работы Cherrypy, 2to3 (инструмент, который я использовал для выполнения основной работы по миграции) не мог достаточно хорошо управлять деталями, чтобы он понравился cp.
Суть в том, что вместо io.StringIO (что по умолчанию предусмотрено 2to3) вам нужно переключиться на io.BytesIO. Поэтому предыдущие вызовы StringIO (данные) должны быть BytesIO (данные). Дело в том, что внутренне cp ожидает, что эти строки / байты (так как py2 на самом деле не имеет никакого значения между 2) будут настоящими байтами (потому что py3 на самом деле дифференцируется). И да, в самом тесте при создании утверждений вы должны либо преобразовать response.output_status & response.body из байтов в строки, либо сравнить их с байтами, например:
self.assertEqual(response.output_status, b'200 OK')
Однако строка запроса (для GET) все еще должна оставаться строкой.
Вот полное редактирование кода, который работал для меня:
from io import BytesIO
import unittest
import urllib.request, urllib.parse, urllib.error
import cherrypy
cherrypy.config.update({'environment': "test_suite"})
cherrypy.server.unsubscribe()
local = cherrypy.lib.httputil.Host('127.0.0.1', 50000, "")
remote = cherrypy.lib.httputil.Host('127.0.0.1', 50001, "")
__all__ = ['BaseCherryPyTestCase']
class BaseCherryPyTestCase(unittest.TestCase):
def request(self, path='/', method='GET', app_path='', scheme='http',
proto='HTTP/1.1', data=None, headers=None, **kwargs):
h = {'Host': '127.0.0.1'}
if headers is not None:
h.update(headers)
if method in ('POST', 'PUT') and not data:
data = urllib.parse.urlencode(kwargs).encode('utf-8')
kwargs = None
h['content-type'] = 'application/x-www-form-urlencoded'
qs = None
if kwargs:
qs = urllib.parse.urlencode(kwargs)
fd = None
if data is not None:
h['content-length'] = '%d' % len(data.decode('utf-8'))
fd = BytesIO(data)
app = cherrypy.tree.apps.get(app_path)
if not app:
raise AssertionError("No application mounted at '%s'" % app_path)
app.release_serving()
request, response = app.get_serving(local, remote, scheme, proto)
try:
h = [(k, v) for k, v in h.items()]
response = request.run(method, path, qs, proto, h, fd)
finally:
if fd:
fd.close()
fd = None
if response.output_status.startswith(b'500'):
print(response.body)
raise AssertionError("Unexpected error")
response.collapse_body()
return response