Port more API unit tests to Python 3

* HTTP body type must be bytes on Python 3:

  * WsgiLimiterProxy, JSONDictSerializer: encode JSON as bytes
  * Use byte strings for literal HTTP bodies
  * Encode explicitly HTTP body to UTF-8 on Python 3

* Fix the prototype of FakeHttplibSocket.makefile(): only the first
  mode parameter is mandatory
* Replace dict.keys().sort() with sorted(dict.keys())
* tox.ini: add the following unit tests to Python 3.4:

  - api/common/test_extensions.py
  - api/test_versions.py

Partially implements: blueprint trove-python3
Change-Id: I175dc55424e9b5786819f08a584ac967d083db11
This commit is contained in:
Victor Stinner
2016-05-02 17:57:58 +02:00
parent bdf664bbdf
commit a007c948ae
5 changed files with 14 additions and 10 deletions
+2
View File
@@ -31,6 +31,8 @@ commands =
# all unit tests will pass on Python 3.
commands =
python -bb -m testtools.run \
trove/tests/unittests/api/common/test_extensions.py \
trove/tests/unittests/api/common/test_limits.py \
trove/tests/unittests/common/test_common_extensions.py \
trove/tests/unittests/common/test_context.py \
trove/tests/unittests/common/test_crypto_utils.py \
+1 -1
View File
@@ -396,7 +396,7 @@ class WsgiLimiterProxy(object):
self.limiter_address = limiter_address
def check_for_delay(self, verb, path, username=None):
body = jsonutils.dumps({"verb": verb, "path": path})
body = jsonutils.dump_as_bytes({"verb": verb, "path": path})
headers = {"Content-Type": "application/json"}
conn = http_client.HTTPConnection(self.limiter_address)
+1 -1
View File
@@ -659,4 +659,4 @@ class JSONDictSerializer(DictSerializer):
"""Default JSON request body serialization."""
def default(self, data):
return jsonutils.dumps(data)
return jsonutils.dump_as_bytes(data)
@@ -88,8 +88,8 @@ class TestExtensionLoading(trove_testtools.TestCase):
eps = pkg_resources.EntryPoint.parse_group('plugins', entry_points)
mock_iter_eps.return_value = eps.values()
extension_mgr = extensions.ExtensionManager()
self.assertEqual(DEFAULT_EXTENSION_MAP.keys().sort(),
extension_mgr.extensions.keys().sort(),
self.assertEqual(sorted(DEFAULT_EXTENSION_MAP.keys()),
sorted(extension_mgr.extensions.keys()),
"Invalid extension names")
self._assert_default_extensions(extension_mgr.extensions)
@@ -496,7 +496,7 @@ class WsgiLimiterTest(BaseLimitTestSuite):
def _request_data(self, verb, path):
"""Get data describing a limit request verb/path."""
return jsonutils.dumps({"verb": verb, "path": path})
return jsonutils.dump_as_bytes({"verb": verb, "path": path})
def _request(self, verb, url, username=None):
"""Make sure that POSTing to the given url causes the given username
@@ -561,9 +561,9 @@ class FakeHttplibSocket(object):
def __init__(self, response_string):
"""Initialize new `FakeHttplibSocket`."""
self._buffer = six.StringIO(response_string)
self._buffer = six.BytesIO(response_string)
def makefile(self, _mode, _other):
def makefile(self, _mode, *args):
"""Returns the socket's internal buffer."""
return self._buffer
@@ -580,7 +580,7 @@ class FakeHttplibConnection(object):
self.app = app
self.host = host
def request(self, method, path, body="", headers=None):
def request(self, method, path, body=b"", headers=None):
"""
Requests made via this connection actually get translated and routed
into our WSGI app, we then wait for the response and turn it back into
@@ -597,6 +597,8 @@ class FakeHttplibConnection(object):
resp = str(req.get_response(self.app))
resp = "HTTP/1.0 %s" % resp
if six.PY3:
resp = resp.encode("utf-8")
sock = FakeHttplibSocket(resp)
self.http_response = http_client.HTTPResponse(sock)
self.http_response.begin()
@@ -676,8 +678,8 @@ class WsgiLimiterProxyTest(BaseLimitTestSuite):
error = error.strip()
self.assertAlmostEqual(float(delay), 60, 1)
self.assertEqual("403 Forbidden\n\nOnly 1 GET request(s) can be"
" made to /delayed every minute.", error)
self.assertEqual(b"403 Forbidden\n\nOnly 1 GET request(s) can be"
b" made to /delayed every minute.", error)
def tearDown(self):
# restore original HTTPConnection object