Fix Python 3 issues

* Replace unicode with six.text_type
* Replace "raise a, b, c" with six.reraise(a, b, c)
* Replace dict.iteritems() with six.iteritems(dict)
* Replace StringIO.StringIO with six.BytesIO for image content
* Get AssertionError from builtins, don't use the exceptions module
  which was removed in Python 3
* Open configuration file in text mode (not in binary mode) in
  functional tests
* Use absolute imports in artifacts_sample and image_artifact plugins
  instead of relative imports.
* Fix usage of __import__() function: the level parameter expects a
  positive integer, use level=0, not level=-1
* Get the input function from six.moves: use raw_input() on Python 2 and
  input() on Python 3. raw_input() was renamed to input() in Python 3.
* Unpacking parameters in function definition is no more possible:
  unpack the tuple manually in test_glance_replicator.py
* On Python 3, socket.fromfd() now returns directly the right socket
  type. It's not more needed to cast manually the result of
  socket.fromfd().

For more information on Python 3, see:
https://wiki.openstack.org/wiki/Python3

Change-Id: Iaa1a392590154058eab4645fb288d1534f66e528
This commit is contained in:
Victor Stinner 2015-05-21 08:51:39 -07:00 committed by Flavio Percoco
parent 609fda5643
commit 6652f4b029
13 changed files with 28 additions and 24 deletions

View File

@ -29,6 +29,7 @@ import time
from oslo_utils import timeutils
from glance.common import utils
from six.moves import input
# If ../glance/__init__.py exists, add ../ to Python search path, so that
# it will override what happens to be installed in /usr/(local/)lib/python...
@ -467,7 +468,7 @@ def user_confirm(prompt, default=False):
else:
prompt_default = "[y/N]"
answer = raw_input("%s %s " % (prompt, prompt_default))
answer = input("%s %s " % (prompt, prompt_default))
if answer == "":
return default

View File

@ -586,7 +586,8 @@ def get_test_suite_socket():
if GLANCE_TEST_SOCKET_FD_STR in os.environ:
fd = int(os.environ[GLANCE_TEST_SOCKET_FD_STR])
sock = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
sock = socket.SocketType(_sock=sock)
if six.PY2:
sock = socket.SocketType(_sock=sock)
sock.listen(CONF.backlog)
del os.environ[GLANCE_TEST_SOCKET_FD_STR]
os.close(fd)
@ -682,12 +683,12 @@ def no_4byte_params(f):
def wrapper(*args, **kwargs):
def _is_match(some_str):
return (isinstance(some_str, unicode) and
return (isinstance(some_str, six.text_type) and
REGEX_4BYTE_UNICODE.findall(some_str) != [])
def _check_dict(data_dict):
# a dict of dicts has to be checked recursively
for key, value in data_dict.iteritems():
for key, value in six.iteritems(data_dict):
if isinstance(value, dict):
_check_dict(value)
else:

View File

@ -873,7 +873,7 @@ class Resource(object):
request, **action_args)
except webob.exc.WSGIHTTPException as e:
exc_info = sys.exc_info()
raise translate_exception(request, e), None, exc_info[2]
six.reraise(translate_exception(request, e), None, exc_info[2])
try:
response = webob.Response(request=request)

View File

@ -1,5 +1,5 @@
from v1 import artifact as art1
from v2 import artifact as art2
from glance.contrib.plugins.artifacts_sample.v1 import artifact as art1
from glance.contrib.plugins.artifacts_sample.v2 import artifact as art2
MY_ARTIFACT = [art1.MyArtifact, art2.MyArtifact]

View File

@ -12,8 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from v1 import image as v1
from v1_1 import image as v1_1
from v2 import image as v2
from glance.contrib.plugins.image_artifact.v1 import image as v1
from glance.contrib.plugins.image_artifact.v1_1 import image as v1_1
from glance.contrib.plugins.image_artifact.v2 import image as v2
versions = [v1.ImageAsAnArtifact, v1_1.ImageAsAnArtifact, v2.ImageAsAnArtifact]

View File

@ -92,7 +92,7 @@ def from_migration_import(module_name, fromlist):
# Refer to images table
"""
module_path = 'glance.db.sqlalchemy.migrate_repo.versions.%s' % module_name
module = __import__(module_path, globals(), locals(), fromlist, -1)
module = __import__(module_path, globals(), locals(), fromlist, 0)
return [getattr(module, item) for item in fromlist]

View File

@ -115,7 +115,7 @@ class Server(object):
utils.safe_mkdirs(conf_dir)
def override_conf(filepath, overridden):
with open(filepath, 'wb') as conf_file:
with open(filepath, 'w') as conf_file:
conf_file.write(overridden)
conf_file.flush()
return conf_file.name
@ -207,7 +207,7 @@ class Server(object):
utils.safe_mkdirs(conf_dir)
conf_filepath = os.path.join(conf_dir, 'glance-manage.conf')
with open(conf_filepath, 'wb') as conf_file:
with open(conf_filepath, 'w') as conf_file:
conf_file.write('[DEFAULT]\n')
conf_file.write('sql_connection = %s' % self.sql_connection)
conf_file.flush()

View File

@ -14,6 +14,8 @@
import uuid
import six
import glance.artifacts as ga
from glance.common import exception as exc
from glance import context
@ -513,7 +515,7 @@ class ArtifactTests(object):
self.assertIsNotNone(res['published_at'])
published_at = res['published_at']
expected['published_at'] = published_at
for key, value in expected.iteritems():
for key, value in six.iteritems(expected):
self.assertEqual(expected[key], res[key])
def test_artifact_get_all(self):

View File

@ -16,11 +16,11 @@
import json
import mock
import os
import StringIO
import glance_store
from oslo_concurrency import processutils
from oslo_config import cfg
import six
from glance.async.flows import convert
from glance.async import taskflow_executor
@ -147,7 +147,7 @@ class TestImportTask(test_utils.BaseTestCase):
return ("", None)
with mock.patch.object(script_utils, 'get_image_data_iter') as dmock:
dmock.return_value = StringIO.StringIO("TEST_IMAGE")
dmock.return_value = six.BytesIO("TEST_IMAGE")
with mock.patch.object(processutils, 'execute') as exc_mock:
exc_mock.side_effect = fake_execute

View File

@ -529,7 +529,7 @@ class TestHelpers(test_utils.BaseTestCase):
'properties': {'distro': 'Ubuntu 10.04 LTS'}}
headers = utils.image_meta_to_http_headers(fixture)
for k, v in six.iteritems(headers):
self.assertIsInstance(v, unicode)
self.assertIsInstance(v, six.text_type)
def test_data_passed_properly_through_headers(self):
"""

View File

@ -108,7 +108,8 @@ class FakeHTTPConnection(object):
def getresponse(self):
class FakeResponse(object):
def __init__(self, (code, body, headers)):
def __init__(self, args):
(code, body, headers) = args
self.body = six.StringIO(body)
self.headers = headers
self.status = code

View File

@ -26,7 +26,6 @@ if possible.
from __future__ import print_function
import datetime
import exceptions
import os
import pickle
import uuid
@ -420,7 +419,7 @@ class MigrationsMixin(test_migrations.WalkVersionsMixin):
invalid_scheme_uri = ('http://acct:usr:pass@example.com'
'/container/obj-id')
self.assertRaises(exceptions.AssertionError,
self.assertRaises(AssertionError,
legacy_parse_uri_fn,
invalid_scheme_uri,
True)

View File

@ -1101,7 +1101,7 @@ class TestGlanceAPI(base.IsolatedUnitTest):
req = webob.Request.blank("/images")
req.headers['Content-Type'] = 'application/octet-stream'
req.method = 'POST'
for k, v in fixture_headers.iteritems():
for k, v in six.iteritems(fixture_headers):
req.headers[k] = v
res = req.get_response(self.api)
self.assertEqual(400, res.status_int)
@ -1117,7 +1117,7 @@ class TestGlanceAPI(base.IsolatedUnitTest):
req = webob.Request.blank("/images")
req.headers['Content-Type'] = 'application/octet-stream'
req.method = 'POST'
for k, v in fixture_headers.iteritems():
for k, v in six.iteritems(fixture_headers):
req.headers[k] = v
res = req.get_response(self.api)
self.assertEqual(400, res.status_int)
@ -1131,7 +1131,7 @@ class TestGlanceAPI(base.IsolatedUnitTest):
req = webob.Request.blank("/images")
req.headers['Content-Type'] = 'application/octet-stream'
req.method = 'POST'
for k, v in fixture_headers.iteritems():
for k, v in six.iteritems(fixture_headers):
req.headers[k] = v
res = req.get_response(self.api)
self.assertEqual(400, res.status_int)
@ -1751,7 +1751,7 @@ class TestGlanceAPI(base.IsolatedUnitTest):
req = webob.Request.blank("/images")
req.method = 'POST'
for k, v in fixture_headers.iteritems():
for k, v in six.iteritems(fixture_headers):
req.headers[k] = v
res = req.get_response(self.api)