Remove final six usage
We also update docs since guidance has necessarily changed here. Change-Id: I7c24a1aa3545f3499a7a2ce30b73e2656666c764 Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
This commit is contained in:
parent
f68e04f268
commit
33741138d9
@ -26,38 +26,9 @@ The Great Change
|
|||||||
|
|
||||||
With the demise of Python 2.7 in January 2020, beginning with the Ussuri
|
With the demise of Python 2.7 in January 2020, beginning with the Ussuri
|
||||||
development cycle, Glance only needs to support Python 3 runtimes (in
|
development cycle, Glance only needs to support Python 3 runtimes (in
|
||||||
particular, 3.6 and 3.7). Thus we can begin to incorporate Python 3
|
particular, 3.6 and 3.7). There was a four cycle transition period, but
|
||||||
language features and remove Python 2 compatibility code. At the same
|
starting in the Yoga development cycle, all Python 2 compatibility code
|
||||||
time, however, we are still supporting stable branches that must support
|
has been removed and only Python 3 is supposed.
|
||||||
Python 2. Our biggest interaction with the stable branches is backporting
|
|
||||||
bugfixes, where in the ideal case, we're just doing a simple cherry-pick of
|
|
||||||
a commit from master to the stable branches. You can see that there's some
|
|
||||||
tension here.
|
|
||||||
|
|
||||||
With that in mind, here are some guidelines for reviewers and developers
|
|
||||||
that the Glance community has agreed on during this phase where we want to
|
|
||||||
write pure Python 3 but still must support Python 2 code.
|
|
||||||
|
|
||||||
.. _transition-guidelines:
|
|
||||||
|
|
||||||
Python 2 to Python 3 transition guidelines
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
* We need to be checking the code coverage of test cases very carefully so
|
|
||||||
that new code has excellent coverage. The idea is that we want these
|
|
||||||
tests to fail when a backport is proposed to a stable branch and the
|
|
||||||
tests are run under Python 2 (if the code is using any Python-3-only
|
|
||||||
language features).
|
|
||||||
* New features can use Python-3-only language constructs, but bugfixes
|
|
||||||
likely to be backported should be more conservative and write for
|
|
||||||
Python 2 compatibility.
|
|
||||||
* The code for drivers may continue to use the six compatibility library at
|
|
||||||
their discretion.
|
|
||||||
* We will not remove six from mainline Cinder code that impacts the drivers
|
|
||||||
(for example, classes they inherit from).
|
|
||||||
* We can remove six from code that doesn't impact drivers, keeping in mind
|
|
||||||
that backports may be more problematic, and hence making sure that we have
|
|
||||||
really good test coverage.
|
|
||||||
|
|
||||||
Unit Tests
|
Unit Tests
|
||||||
----------
|
----------
|
||||||
|
@ -24,7 +24,6 @@ the local cached copy of the image file is returned.
|
|||||||
|
|
||||||
import http.client as http
|
import http.client as http
|
||||||
import re
|
import re
|
||||||
import six
|
|
||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
import webob
|
import webob
|
||||||
@ -220,8 +219,7 @@ class CacheFilter(wsgi.Middleware):
|
|||||||
# https://github.com/Pylons/webob/issues/86
|
# https://github.com/Pylons/webob/issues/86
|
||||||
response.headers['Content-Type'] = 'application/octet-stream'
|
response.headers['Content-Type'] = 'application/octet-stream'
|
||||||
if image.checksum:
|
if image.checksum:
|
||||||
response.headers['Content-MD5'] = (image.checksum.encode('utf-8')
|
response.headers['Content-MD5'] = image.checksum
|
||||||
if six.PY2 else image.checksum)
|
|
||||||
response.headers['Content-Length'] = str(image.size)
|
response.headers['Content-Length'] = str(image.size)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ from oslo_log import log as logging
|
|||||||
import oslo_serialization.jsonutils as json
|
import oslo_serialization.jsonutils as json
|
||||||
from oslo_utils import encodeutils
|
from oslo_utils import encodeutils
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
import six
|
|
||||||
import webob.exc
|
import webob.exc
|
||||||
|
|
||||||
from glance.api import common
|
from glance.api import common
|
||||||
@ -270,8 +269,6 @@ class ResponseSerializer(wsgi.JSONResponseSerializer):
|
|||||||
|
|
||||||
def _inject_location_header(self, response, task):
|
def _inject_location_header(self, response, task):
|
||||||
location = self._get_task_location(task)
|
location = self._get_task_location(task)
|
||||||
if six.PY2:
|
|
||||||
location = location.encode('utf-8')
|
|
||||||
response.headers['Location'] = location
|
response.headers['Location'] = location
|
||||||
|
|
||||||
def _get_task_location(self, task):
|
def _get_task_location(self, task):
|
||||||
|
@ -26,7 +26,6 @@ from oslo_log import log as logging
|
|||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
from oslo_utils import encodeutils
|
from oslo_utils import encodeutils
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
import six
|
|
||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
from glance.common import config
|
from glance.common import config
|
||||||
@ -395,11 +394,7 @@ def replication_dump(options, args):
|
|||||||
'data_filename': data_filename})
|
'data_filename': data_filename})
|
||||||
|
|
||||||
# Dump glance information
|
# Dump glance information
|
||||||
if six.PY3:
|
with open(data_path, 'w', encoding='utf-8') as f:
|
||||||
f = open(data_path, 'w', encoding='utf-8')
|
|
||||||
else:
|
|
||||||
f = open(data_path, 'w')
|
|
||||||
with f:
|
|
||||||
f.write(jsonutils.dumps(image))
|
f.write(jsonutils.dumps(image))
|
||||||
|
|
||||||
if image['status'] == 'active' and not options.metaonly:
|
if image['status'] == 'active' and not options.metaonly:
|
||||||
|
@ -44,7 +44,6 @@ except ImportError:
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import encodeutils
|
from oslo_utils import encodeutils
|
||||||
from oslo_utils import netutils
|
from oslo_utils import netutils
|
||||||
import six
|
|
||||||
|
|
||||||
from glance.common import auth
|
from glance.common import auth
|
||||||
from glance.common import exception
|
from glance.common import exception
|
||||||
@ -411,11 +410,7 @@ class BaseClient(object):
|
|||||||
:returns: Dictionary with encoded headers'
|
:returns: Dictionary with encoded headers'
|
||||||
names and values
|
names and values
|
||||||
"""
|
"""
|
||||||
if six.PY3:
|
return {str(h): str(v) for h, v in headers.items()}
|
||||||
to_str = str
|
|
||||||
else:
|
|
||||||
to_str = encodeutils.safe_encode
|
|
||||||
return {to_str(h): to_str(v) for h, v in headers.items()}
|
|
||||||
|
|
||||||
@handle_redirects
|
@handle_redirects
|
||||||
def _do_request(self, method, url, body, headers):
|
def _do_request(self, method, url, body, headers):
|
||||||
@ -512,9 +507,7 @@ class BaseClient(object):
|
|||||||
return res.getheader('Retry-After')
|
return res.getheader('Retry-After')
|
||||||
|
|
||||||
def read_body(res):
|
def read_body(res):
|
||||||
body = res.read()
|
body = res.read().decode('utf-8')
|
||||||
if six.PY3:
|
|
||||||
body = body.decode('utf-8')
|
|
||||||
return body
|
return body
|
||||||
|
|
||||||
status_code = self.get_status_code(res)
|
status_code = self.get_status_code(res)
|
||||||
|
@ -26,7 +26,6 @@ from cryptography.hazmat.primitives.ciphers import algorithms
|
|||||||
from cryptography.hazmat.primitives.ciphers import Cipher
|
from cryptography.hazmat.primitives.ciphers import Cipher
|
||||||
from cryptography.hazmat.primitives.ciphers import modes
|
from cryptography.hazmat.primitives.ciphers import modes
|
||||||
from oslo_utils import encodeutils
|
from oslo_utils import encodeutils
|
||||||
import six
|
|
||||||
|
|
||||||
|
|
||||||
def urlsafe_encrypt(key, plaintext, blocksize=16):
|
def urlsafe_encrypt(key, plaintext, blocksize=16):
|
||||||
@ -48,7 +47,7 @@ def urlsafe_encrypt(key, plaintext, blocksize=16):
|
|||||||
# NOTE(rosmaita): I know this looks stupid, but we can't just
|
# NOTE(rosmaita): I know this looks stupid, but we can't just
|
||||||
# use os.urandom() to get the bytes because we use char(0) as
|
# use os.urandom() to get the bytes because we use char(0) as
|
||||||
# a delimiter
|
# a delimiter
|
||||||
pad = b''.join(six.int2byte(random.SystemRandom().randint(1, 0xFF))
|
pad = b''.join(bytes((random.SystemRandom().randint(1, 0xFF),))
|
||||||
for i in range(pad_length - 1))
|
for i in range(pad_length - 1))
|
||||||
# We use chr(0) as a delimiter between text and padding
|
# We use chr(0) as a delimiter between text and padding
|
||||||
return text + b'\0' + pad
|
return text + b'\0' + pad
|
||||||
@ -63,7 +62,6 @@ def urlsafe_encrypt(key, plaintext, blocksize=16):
|
|||||||
encryptor = cypher.encryptor()
|
encryptor = cypher.encryptor()
|
||||||
padded = encryptor.update(pad(plaintext)) + encryptor.finalize()
|
padded = encryptor.update(pad(plaintext)) + encryptor.finalize()
|
||||||
encoded = base64.urlsafe_b64encode(init_vector + padded)
|
encoded = base64.urlsafe_b64encode(init_vector + padded)
|
||||||
if six.PY3:
|
|
||||||
encoded = encoded.decode('ascii')
|
encoded = encoded.decode('ascii')
|
||||||
return encoded
|
return encoded
|
||||||
|
|
||||||
@ -88,6 +86,5 @@ def urlsafe_decrypt(key, ciphertext):
|
|||||||
decryptor = cypher.decryptor()
|
decryptor = cypher.decryptor()
|
||||||
padded = decryptor.update(ciphertext[16:]) + decryptor.finalize()
|
padded = decryptor.update(ciphertext[16:]) + decryptor.finalize()
|
||||||
text = padded[:padded.rfind(b'\0')]
|
text = padded[:padded.rfind(b'\0')]
|
||||||
if six.PY3:
|
|
||||||
text = text.decode('utf-8')
|
text = text.decode('utf-8')
|
||||||
return text
|
return text
|
||||||
|
@ -39,7 +39,6 @@ from oslo_log import log as logging
|
|||||||
from oslo_utils import excutils
|
from oslo_utils import excutils
|
||||||
from oslo_utils import netutils
|
from oslo_utils import netutils
|
||||||
from oslo_utils import strutils
|
from oslo_utils import strutils
|
||||||
import six
|
|
||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
from glance.common import exception
|
from glance.common import exception
|
||||||
@ -443,8 +442,6 @@ def get_test_suite_socket():
|
|||||||
if GLANCE_TEST_SOCKET_FD_STR in os.environ:
|
if GLANCE_TEST_SOCKET_FD_STR in os.environ:
|
||||||
fd = int(os.environ[GLANCE_TEST_SOCKET_FD_STR])
|
fd = int(os.environ[GLANCE_TEST_SOCKET_FD_STR])
|
||||||
sock = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
|
sock = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
|
||||||
if six.PY2:
|
|
||||||
sock = socket.SocketType(_sock=sock)
|
|
||||||
sock.listen(CONF.backlog)
|
sock.listen(CONF.backlog)
|
||||||
del os.environ[GLANCE_TEST_SOCKET_FD_STR]
|
del os.environ[GLANCE_TEST_SOCKET_FD_STR]
|
||||||
os.close(fd)
|
os.close(fd)
|
||||||
|
@ -45,7 +45,6 @@ from oslo_utils import encodeutils
|
|||||||
from oslo_utils import strutils
|
from oslo_utils import strutils
|
||||||
from osprofiler import opts as profiler_opts
|
from osprofiler import opts as profiler_opts
|
||||||
import routes.middleware
|
import routes.middleware
|
||||||
import six
|
|
||||||
import webob.dec
|
import webob.dec
|
||||||
import webob.exc
|
import webob.exc
|
||||||
from webob import multidict
|
from webob import multidict
|
||||||
@ -1104,26 +1103,6 @@ class Request(webob.Request):
|
|||||||
# not be inherited.
|
# not be inherited.
|
||||||
webob.Request.body_file.fset(self, value)
|
webob.Request.body_file.fset(self, value)
|
||||||
|
|
||||||
@property
|
|
||||||
def params(self):
|
|
||||||
"""Override params property of webob.request.BaseRequest.
|
|
||||||
|
|
||||||
Added an 'encoded_params' attribute in case of PY2 to avoid
|
|
||||||
encoding values in next subsequent calls to the params property.
|
|
||||||
"""
|
|
||||||
if six.PY2:
|
|
||||||
encoded_params = getattr(self, 'encoded_params', None)
|
|
||||||
if encoded_params is None:
|
|
||||||
params = super(Request, self).params
|
|
||||||
params_dict = multidict.MultiDict()
|
|
||||||
for key, value in params.items():
|
|
||||||
params_dict.add(key, encodeutils.safe_encode(value))
|
|
||||||
|
|
||||||
setattr(self, 'encoded_params',
|
|
||||||
multidict.NestedMultiDict(params_dict))
|
|
||||||
return self.encoded_params
|
|
||||||
return super(Request, self).params
|
|
||||||
|
|
||||||
def best_match_content_type(self):
|
def best_match_content_type(self):
|
||||||
"""Determine the requested response content-type."""
|
"""Determine the requested response content-type."""
|
||||||
supported = ('application/json',)
|
supported = ('application/json',)
|
||||||
@ -1352,9 +1331,8 @@ class Resource(object):
|
|||||||
action_result = self.dispatch(self.controller, action,
|
action_result = self.dispatch(self.controller, action,
|
||||||
request, **action_args)
|
request, **action_args)
|
||||||
except webob.exc.WSGIHTTPException as e:
|
except webob.exc.WSGIHTTPException as e:
|
||||||
exc_info = sys.exc_info()
|
|
||||||
e = translate_exception(request, e)
|
e = translate_exception(request, e)
|
||||||
six.reraise(type(e), e, exc_info[2])
|
raise e.with_traceback(sys.exc_info()[2])
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
msg = _("Error decoding your request. Either the URL or the "
|
msg = _("Error decoding your request. Either the URL or the "
|
||||||
"request body contained characters that could not be "
|
"request body contained characters that could not be "
|
||||||
@ -1373,10 +1351,6 @@ class Resource(object):
|
|||||||
try:
|
try:
|
||||||
response = webob.Response(request=request)
|
response = webob.Response(request=request)
|
||||||
self.dispatch(self.serializer, action, response, action_result)
|
self.dispatch(self.serializer, action, response, action_result)
|
||||||
# encode all headers in response to utf-8 to prevent unicode errors
|
|
||||||
for name, value in list(response.headers.items()):
|
|
||||||
if six.PY2 and isinstance(value, str):
|
|
||||||
response.headers[name] = encodeutils.safe_encode(value)
|
|
||||||
return response
|
return response
|
||||||
except webob.exc.WSGIHTTPException as e:
|
except webob.exc.WSGIHTTPException as e:
|
||||||
return translate_exception(request, e)
|
return translate_exception(request, e)
|
||||||
|
@ -61,7 +61,6 @@ from oslo_log import log as logging
|
|||||||
from oslo_utils import encodeutils
|
from oslo_utils import encodeutils
|
||||||
from oslo_utils import excutils
|
from oslo_utils import excutils
|
||||||
from oslo_utils import fileutils
|
from oslo_utils import fileutils
|
||||||
import six
|
|
||||||
import xattr
|
import xattr
|
||||||
|
|
||||||
from glance.common import exception
|
from glance.common import exception
|
||||||
@ -477,9 +476,7 @@ def set_xattr(path, key, value):
|
|||||||
"""
|
"""
|
||||||
namespaced_key = _make_namespaced_xattr_key(key)
|
namespaced_key = _make_namespaced_xattr_key(key)
|
||||||
if not isinstance(value, bytes):
|
if not isinstance(value, bytes):
|
||||||
value = str(value)
|
value = str(value).encode('utf-8')
|
||||||
if six.PY3:
|
|
||||||
value = value.encode('utf-8')
|
|
||||||
xattr.setxattr(path, namespaced_key, value)
|
xattr.setxattr(path, namespaced_key, value)
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ import fixtures
|
|||||||
from oslo_concurrency import processutils
|
from oslo_concurrency import processutils
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
import routes
|
import routes
|
||||||
import six
|
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
from glance.api.v2 import router as router_v2
|
from glance.api.v2 import router as router_v2
|
||||||
@ -111,12 +110,6 @@ class RequestTest(test_utils.BaseTestCase):
|
|||||||
self.assertEqual("application/json", result)
|
self.assertEqual("application/json", result)
|
||||||
|
|
||||||
def test_params(self):
|
def test_params(self):
|
||||||
if six.PY2:
|
|
||||||
expected = webob.multidict.NestedMultiDict({
|
|
||||||
'limit': '20', 'name':
|
|
||||||
'\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82',
|
|
||||||
'sort_key': 'name', 'sort_dir': 'asc'})
|
|
||||||
else:
|
|
||||||
expected = webob.multidict.NestedMultiDict({
|
expected = webob.multidict.NestedMultiDict({
|
||||||
'limit': '20', 'name': 'Привет', 'sort_key': 'name',
|
'limit': '20', 'name': 'Привет', 'sort_key': 'name',
|
||||||
'sort_dir': 'asc'})
|
'sort_dir': 'asc'})
|
||||||
@ -414,8 +407,7 @@ class ResourceTest(test_utils.BaseTestCase):
|
|||||||
response = resource.__call__(request)
|
response = resource.__call__(request)
|
||||||
|
|
||||||
# ensure it has been encoded correctly
|
# ensure it has been encoded correctly
|
||||||
value = (response.headers['unicode_test'].decode('utf-8')
|
value = response.headers['unicode_test']
|
||||||
if six.PY2 else response.headers['unicode_test'])
|
|
||||||
self.assertEqual(for_openstack_comrades, value)
|
self.assertEqual(for_openstack_comrades, value)
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
from glance.common import crypt
|
from glance.common import crypt
|
||||||
from glance.common import utils
|
from glance.common import utils
|
||||||
from glance.tests import utils as test_utils
|
from glance.tests import utils as test_utils
|
||||||
@ -33,9 +31,7 @@ class UtilsTestCase(test_utils.BaseTestCase):
|
|||||||
plaintext_list = ['']
|
plaintext_list = ['']
|
||||||
blocksize = 64
|
blocksize = 64
|
||||||
for i in range(3 * blocksize):
|
for i in range(3 * blocksize):
|
||||||
text = os.urandom(i)
|
text = os.urandom(i).decode('latin1')
|
||||||
if six.PY3:
|
|
||||||
text = text.decode('latin1')
|
|
||||||
plaintext_list.append(text)
|
plaintext_list.append(text)
|
||||||
|
|
||||||
for key in key_list:
|
for key in key_list:
|
||||||
|
@ -33,8 +33,6 @@ Paste>=2.0.2 # MIT
|
|||||||
jsonschema>=3.2.0 # MIT
|
jsonschema>=3.2.0 # MIT
|
||||||
python-keystoneclient>=3.8.0 # Apache-2.0
|
python-keystoneclient>=3.8.0 # Apache-2.0
|
||||||
pyOpenSSL>=17.1.0 # Apache-2.0
|
pyOpenSSL>=17.1.0 # Apache-2.0
|
||||||
# Required by openstack.common libraries
|
|
||||||
six>=1.11.0 # MIT
|
|
||||||
|
|
||||||
oslo.db>=5.0.0 # Apache-2.0
|
oslo.db>=5.0.0 # Apache-2.0
|
||||||
oslo.i18n>=5.0.0 # Apache-2.0
|
oslo.i18n>=5.0.0 # Apache-2.0
|
||||||
|
Loading…
Reference in New Issue
Block a user