diff --git a/doc/source/development_middleware.rst b/doc/source/development_middleware.rst index 6ee1d099b9..41e6ace20c 100644 --- a/doc/source/development_middleware.rst +++ b/doc/source/development_middleware.rst @@ -80,11 +80,7 @@ presented below:: from swift.common.request_helpers import get_sys_meta_prefix from swift.proxy.controllers.base import get_container_info from eventlet import Timeout - import six - if six.PY3: - from eventlet.green.urllib import request as urllib2 - else: - from eventlet.green import urllib2 + from eventlet.green.urllib import urllib_request # x-container-sysmeta-webhook SYSMETA_WEBHOOK = get_sys_meta_prefix('container') + 'webhook' @@ -119,10 +115,10 @@ presented below:: webhook = container_info['sysmeta'].get('webhook') if webhook: # create a POST request with obj name as body - webhook_req = urllib2.Request(webhook, data=obj) + webhook_req = urllib_request.Request(webhook, data=obj) with Timeout(20): try: - urllib2.urlopen(webhook_req).read() + urllib_request.urlopen(webhook_req).read() except (Exception, Timeout): self.logger.exception( 'failed POST to webhook %s' % webhook) diff --git a/lower-constraints.txt b/lower-constraints.txt index 19f2345159..3cee276cfa 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -65,7 +65,6 @@ PyYAML==3.12 requests==2.14.2 requests-mock==1.2.0 rfc3986==1.1.0 -six==1.10.0 smmap2==2.0.3 snowballstemmer==1.2.1 stestr==2.0.0 diff --git a/py3-constraints.txt b/py3-constraints.txt index 9b9f1e6572..6271838c0d 100644 --- a/py3-constraints.txt +++ b/py3-constraints.txt @@ -192,7 +192,6 @@ s3transfer===0.10.4;python_version>='3.8' s3transfer===0.8.2;python_version=='3.7' s3transfer===0.5.2;python_version=='3.6' setuptools===75.3.0;python_version>='3.12' -six===1.16.0 smmap===5.0.1;python_version>='3.7' smmap===5.0.0;python_version=='3.6' stestr===4.1.0 diff --git a/requirements.txt b/requirements.txt index b78a1ac12e..6105b8e4a3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,6 @@ greenlet>=0.3.3 PasteDeploy>=2.0.0 lxml>=4.2.3 requests>=2.14.2 # Apache-2.0 -six>=1.10.0 xattr>=0.7.2;sys_platform!='win32' # MIT PyECLib>=1.3.1,!=1.6.2,!=1.6.3 # BSD cryptography>=2.0.2 # BSD/Apache-2.0 diff --git a/swift/account/backend.py b/swift/account/backend.py index ec1de03d15..d0241a2708 100644 --- a/swift/account/backend.py +++ b/swift/account/backend.py @@ -19,10 +19,8 @@ import sqlite3 -import six - from swift.common.utils import Timestamp, RESERVED_BYTE -from swift.common.db import DatabaseBroker, utf8encode, zero_like +from swift.common.db import DatabaseBroker, zero_like DATADIR = 'accounts' @@ -372,9 +370,6 @@ def list_containers_iter(self, limit, marker, end_marker, prefix, put_timestamp, 0) """ delim_force_gte = False - if six.PY2: - (marker, end_marker, prefix, delimiter) = utf8encode( - marker, end_marker, prefix, delimiter) if reverse: # Reverse the markers if we are reversing the listing. marker, end_marker = end_marker, marker diff --git a/swift/account/reaper.py b/swift/account/reaper.py index 41f7a440b7..3323ade720 100644 --- a/swift/account/reaper.py +++ b/swift/account/reaper.py @@ -22,7 +22,6 @@ import itertools from eventlet import GreenPool, sleep, Timeout -import six import swift.common.db from swift.account.backend import AccountBroker, DATADIR @@ -267,12 +266,9 @@ def reap_account(self, broker, partition, nodes, container_shard=None): while containers: try: for (container, _junk, _junk, _junk, _junk) in containers: - if six.PY3: - container_ = container.encode('utf-8') - else: - container_ = container this_shard = ( - int(md5(container_, usedforsecurity=False) + int(md5(container.encode('utf-8'), + usedforsecurity=False) .hexdigest(), 16) % len(nodes)) if container_shard not in (this_shard, None): continue diff --git a/swift/account/utils.py b/swift/account/utils.py index 89fb26f841..ac7bc3a4e9 100644 --- a/swift/account/utils.py +++ b/swift/account/utils.py @@ -15,8 +15,6 @@ import json -import six - from swift.common import constraints from swift.common.middleware import listing_formats from swift.common.swob import HTTPOk, HTTPNoContent, str_to_wsgi @@ -86,12 +84,11 @@ def account_listing_response(account, req, response_content_type, broker=None, data = [] for (name, object_count, bytes_used, put_timestamp, is_subdir) \ in account_list: - name_ = name.decode('utf8') if six.PY2 else name if is_subdir: - data.append({'subdir': name_}) + data.append({'subdir': name}) else: data.append( - {'name': name_, 'count': object_count, 'bytes': bytes_used, + {'name': name, 'count': object_count, 'bytes': bytes_used, 'last_modified': Timestamp(put_timestamp).isoformat}) if response_content_type.endswith('/xml'): account_list = listing_formats.account_to_xml(data, account) diff --git a/swift/cli/account_audit.py b/swift/cli/account_audit.py index b809f0c7e3..5d7ff589ea 100755 --- a/swift/cli/account_audit.py +++ b/swift/cli/account_audit.py @@ -23,7 +23,7 @@ import json from eventlet.greenpool import GreenPool from eventlet.event import Event -from six.moves.urllib.parse import quote +from urllib.parse import quote from swift.common.ring import Ring from swift.common.utils import split_path diff --git a/swift/cli/container_deleter.py b/swift/cli/container_deleter.py index ecd8657d14..7b3ae95892 100644 --- a/swift/cli/container_deleter.py +++ b/swift/cli/container_deleter.py @@ -28,7 +28,6 @@ import io import itertools import json -import six import time from swift.common.internal_client import InternalClient @@ -50,17 +49,11 @@ def make_delete_jobs(account, container, objects, timestamp): :returns: list of dicts appropriate for an UPDATE request to an expiring-object queue ''' - if six.PY2: - if isinstance(account, str): - account = account.decode('utf8') - if isinstance(container, str): - container = container.decode('utf8') return [ { 'name': build_task_obj( timestamp, account, container, - obj.decode('utf8') if six.PY2 and isinstance(obj, str) - else obj, high_precision=True), + obj, high_precision=True), 'deleted': 0, 'created_at': timestamp.internal, 'etag': MD5_OF_EMPTY_STRING, diff --git a/swift/cli/dispersion_populate.py b/swift/cli/dispersion_populate.py index 7ed6b5a41a..a54b155b5f 100755 --- a/swift/cli/dispersion_populate.py +++ b/swift/cli/dispersion_populate.py @@ -23,9 +23,7 @@ from eventlet import GreenPool, patcher, sleep from eventlet.pools import Pool -import six -from six.moves import range -from six.moves.configparser import ConfigParser +from configparser import ConfigParser from swift.common.internal_client import SimpleClient from swift.common.ring import Ring @@ -53,7 +51,7 @@ def put_object(connpool, container, obj, report): global retries_done try: with connpool.item() as conn: - data = io.BytesIO(obj if six.PY2 else obj.encode('utf8')) + data = io.BytesIO(obj.encode('utf8')) conn.put_object(container, obj, data, headers={'x-object-meta-dispersion': obj}) retries_done += conn.attempts - 1 diff --git a/swift/cli/dispersion_report.py b/swift/cli/dispersion_report.py index 605e1281b5..270d1a0180 100644 --- a/swift/cli/dispersion_report.py +++ b/swift/cli/dispersion_report.py @@ -17,7 +17,7 @@ from __future__ import print_function import json from collections import defaultdict -from six.moves.configparser import ConfigParser +from configparser import ConfigParser from optparse import OptionParser from sys import exit, stdout, stderr from time import time diff --git a/swift/cli/drive_audit.py b/swift/cli/drive_audit.py index 5c74e52c3a..fa8367895c 100755 --- a/swift/cli/drive_audit.py +++ b/swift/cli/drive_audit.py @@ -24,8 +24,7 @@ import sys -import six -from six.moves.configparser import ConfigParser +from configparser import ConfigParser from swift.common.utils import backward, get_logger, dump_recon_cache, \ config_true_value @@ -128,8 +127,7 @@ def get_errors(error_re, log_file_pattern, minutes, logger, print("Unable to open " + path) sys.exit(1) for line in backward(f): - if not six.PY2: - line = line.decode(log_file_encoding, 'surrogateescape') + line = line.decode(log_file_encoding, 'surrogateescape') if '[ 0.000000]' in line \ or 'KERNEL supported cpus:' in line \ or 'BIOS-provided physical RAM map:' in line: diff --git a/swift/cli/form_signature.py b/swift/cli/form_signature.py index ab0d12f00a..f9c5bf1e00 100644 --- a/swift/cli/form_signature.py +++ b/swift/cli/form_signature.py @@ -17,7 +17,6 @@ """ from __future__ import print_function import hmac -import six from hashlib import sha1 from os.path import basename from time import time @@ -95,11 +94,9 @@ def main(argv): return 1 data = '%s\n%s\n%s\n%s\n%s' % (path, redirect, max_file_size, max_file_count, expires) - if six.PY3: - data = data if isinstance(data, six.binary_type) else \ - data.encode('utf8') - key = key if isinstance(key, six.binary_type) else \ - key.encode('utf8') + data = data.encode('utf8') + key = key if isinstance(key, bytes) else \ + key.encode('utf8') sig = hmac.new(key, data, sha1).hexdigest() print(' Expires:', expires) diff --git a/swift/cli/info.py b/swift/cli/info.py index 6c4952ef99..065b53d46c 100644 --- a/swift/cli/info.py +++ b/swift/cli/info.py @@ -21,8 +21,7 @@ import sys from collections import defaultdict -import six -from six.moves import urllib +import urllib from swift.common.exceptions import LockTimeout from swift.common.utils import hash_path, storage_directory, \ @@ -722,10 +721,9 @@ def print_item_locations(ring, ring_name=None, account=None, container=None, def obj_main(): - if not six.PY2: - # Make stdout able to write escaped bytes - sys.stdout = codecs.getwriter("utf-8")( - sys.stdout.detach(), errors='surrogateescape') + # Make stdout able to write escaped bytes + sys.stdout = codecs.getwriter("utf-8")( + sys.stdout.detach(), errors='surrogateescape') parser = OptionParser('%prog [options] OBJECT_FILE') parser.add_option( diff --git a/swift/cli/manage_shard_ranges.py b/swift/cli/manage_shard_ranges.py index 1977e7af39..0a8b7f1ce5 100644 --- a/swift/cli/manage_shard_ranges.py +++ b/swift/cli/manage_shard_ranges.py @@ -163,9 +163,6 @@ import time from contextlib import contextmanager -from six.moves import input - - from swift.common.utils import Timestamp, get_logger, ShardRange, readconf, \ ShardRangeList, non_negative_int, config_positive_int_value from swift.container.backend import ContainerBroker, UNSHARDED diff --git a/swift/cli/recon.py b/swift/cli/recon.py index dbf0edba4a..f17db3c5c5 100644 --- a/swift/cli/recon.py +++ b/swift/cli/recon.py @@ -18,8 +18,7 @@ from __future__ import print_function from eventlet.green import socket -from six import string_types -from six.moves.urllib.parse import urlparse +from urllib.parse import urlparse from swift.common.utils import ( SWIFT_CONF_FILE, md5_hash_for_file, set_swift_dir) @@ -30,13 +29,9 @@ import optparse import time import sys -import six import os -if six.PY3: - from eventlet.green.urllib import request as urllib2 -else: - from eventlet.green import urllib2 +from eventlet.green.urllib import request as urllib_request def seconds2timeunit(seconds): @@ -86,19 +81,19 @@ def scout_host(self, base_url, recon_type): """ url = base_url + recon_type try: - body = urllib2.urlopen(url, timeout=self.timeout).read() - if six.PY3 and isinstance(body, six.binary_type): + body = urllib_request.urlopen(url, timeout=self.timeout).read() + if isinstance(body, bytes): body = body.decode('utf8') content = json.loads(body) if self.verbose: print("-> %s: %s" % (url, content)) status = 200 - except urllib2.HTTPError as err: + except urllib_request.HTTPError as err: if not self.suppress_errors or self.verbose: print("-> %s: %s" % (url, err)) content = err status = err.code - except (urllib2.URLError, socket.timeout) as err: + except (urllib_request.URLError, socket.timeout) as err: if not self.suppress_errors or self.verbose: print("-> %s: %s" % (url, err)) content = err @@ -128,19 +123,19 @@ def scout_server_type(self, host): """ try: url = "http://%s:%s/" % (host[0], host[1]) - req = urllib2.Request(url) + req = urllib_request.Request(url) req.get_method = lambda: 'OPTIONS' - conn = urllib2.urlopen(req) + conn = urllib_request.urlopen(req) header = conn.info().get('Server') server_header = header.split('/') content = server_header[0] status = 200 - except urllib2.HTTPError as err: + except urllib_request.HTTPError as err: if not self.suppress_errors or self.verbose: print("-> %s: %s" % (url, err)) content = err status = err.code - except (urllib2.URLError, socket.timeout) as err: + except (urllib_request.URLError, socket.timeout) as err: if not self.suppress_errors or self.verbose: print("-> %s: %s" % (url, err)) content = err @@ -1074,7 +1069,7 @@ def _get_ring_names(self, policy=None): ring_names = [p.ring_name for p in POLICIES if ( p.name == policy or not policy or ( policy.isdigit() and int(policy) == int(p) or - (isinstance(policy, string_types) + (isinstance(policy, str) and policy in p.aliases)))] else: ring_names = [self.server_type] diff --git a/swift/cli/ringbuilder.py b/swift/cli/ringbuilder.py index 374f462356..5cbb70c30c 100644 --- a/swift/cli/ringbuilder.py +++ b/swift/cli/ringbuilder.py @@ -31,9 +31,6 @@ import optparse import math -from six.moves import zip as izip -from six.moves import input - from swift.common import exceptions from swift.common.ring import RingBuilder, Ring, RingData from swift.common.ring.builder import MAX_BALANCE @@ -156,8 +153,8 @@ def _parse_add_values(argvish): print(Commands.add.__doc__.strip()) exit(EXIT_ERROR) - devs_and_weights = izip(islice(args, 0, len(args), 2), - islice(args, 1, len(args), 2)) + devs_and_weights = zip(islice(args, 0, len(args), 2), + islice(args, 1, len(args), 2)) for devstr, weightstr in devs_and_weights: dev_dict = parse_add_value(devstr) @@ -257,8 +254,8 @@ def _parse_set_weight_values(argvish): print(Commands.set_weight.__doc__.strip()) exit(EXIT_ERROR) - devs_and_weights = izip(islice(argvish, 0, len(argvish), 2), - islice(argvish, 1, len(argvish), 2)) + devs_and_weights = zip(islice(argvish, 0, len(argvish), 2), + islice(argvish, 1, len(argvish), 2)) for devstr, weightstr in devs_and_weights: devs = (builder.search_devs( parse_search_value(devstr)) or []) @@ -347,8 +344,8 @@ def _parse_set_region_values(argvish): print(Commands.set_region.__doc__.strip()) exit(EXIT_ERROR) - devs_and_regions = izip(islice(argvish, 0, len(argvish), 2), - islice(argvish, 1, len(argvish), 2)) + devs_and_regions = zip(islice(argvish, 0, len(argvish), 2), + islice(argvish, 1, len(argvish), 2)) for devstr, regionstr in devs_and_regions: devs.extend(builder.search_devs( parse_search_value(devstr)) or []) @@ -382,8 +379,8 @@ def _parse_set_zone_values(argvish): print(Commands.set_zone.__doc__.strip()) exit(EXIT_ERROR) - devs_and_zones = izip(islice(argvish, 0, len(argvish), 2), - islice(argvish, 1, len(argvish), 2)) + devs_and_zones = zip(islice(argvish, 0, len(argvish), 2), + islice(argvish, 1, len(argvish), 2)) for devstr, zonestr in devs_and_zones: devs.extend(builder.search_devs( parse_search_value(devstr)) or []) @@ -415,8 +412,8 @@ def _parse_set_info_values(argvish): print(Commands.search.__doc__.strip()) exit(EXIT_ERROR) - searches_and_changes = izip(islice(argvish, 0, len(argvish), 2), - islice(argvish, 1, len(argvish), 2)) + searches_and_changes = zip(islice(argvish, 0, len(argvish), 2), + islice(argvish, 1, len(argvish), 2)) for search_value, change_value in searches_and_changes: devs = builder.search_devs(parse_search_value(search_value)) diff --git a/swift/common/bufferedhttp.py b/swift/common/bufferedhttp.py index c0aa259b3d..491adabfca 100644 --- a/swift/common/bufferedhttp.py +++ b/swift/common/bufferedhttp.py @@ -27,28 +27,22 @@ """ from swift.common import constraints +import http.client import logging import time import socket -import eventlet -from eventlet.green.httplib import CONTINUE, HTTPConnection, HTTPMessage, \ +from eventlet.green.http.client import CONTINUE, HTTPConnection, \ HTTPResponse, HTTPSConnection, _UNKNOWN, ImproperConnectionState -from six.moves.urllib.parse import quote, parse_qsl, urlencode -import six +from urllib.parse import quote, parse_qsl, urlencode -if six.PY2: - httplib = eventlet.import_patched('httplib') - from eventlet.green import httplib as green_httplib -else: - httplib = eventlet.import_patched('http.client') - from eventlet.green.http import client as green_httplib +from eventlet.green.http import client as green_http_client # Apparently http.server uses this to decide when/whether to send a 431. # Give it some slack, so the app is more likely to get the chance to reject # with a 400 instead. -httplib._MAXHEADERS = constraints.MAX_HEADER_COUNT * 1.6 -green_httplib._MAXHEADERS = constraints.MAX_HEADER_COUNT * 1.6 +http.client._MAXHEADERS = constraints.MAX_HEADER_COUNT * 1.6 +green_http_client._MAXHEADERS = constraints.MAX_HEADER_COUNT * 1.6 class BufferedHTTPResponse(HTTPResponse): @@ -65,11 +59,6 @@ def __init__(self, sock, debuglevel=0, strict=0, # No socket means no file-like -- set it to None like in # HTTPResponse.close() self.fp = None - elif six.PY2: - # sock.fd is a socket._socketobject - # sock.fd._sock is a _socket.socket object, which is what we want. - self._real_socket = sock.fd._sock - self.fp = sock.makefile('rb') else: # sock.fd is a socket.socket, which should have a _real_close self._real_socket = sock.fd @@ -91,24 +80,23 @@ def __init__(self, sock, debuglevel=0, strict=0, self.will_close = _UNKNOWN # conn will close at end of response self._readline_buffer = b'' - if not six.PY2: - def begin(self): - HTTPResponse.begin(self) - header_payload = self.headers.get_payload() - if isinstance(header_payload, list) and len(header_payload) == 1: - header_payload = header_payload[0].get_payload() - if header_payload: - # This shouldn't be here. We must've bumped up against - # https://bugs.python.org/issue37093 - for line in header_payload.rstrip('\r\n').split('\n'): - if ':' not in line or line[:1] in ' \t': - # Well, we're no more broken than we were before... - # Should we support line folding? - # How can/should we handle a bad header line? - break - header, value = line.split(':', 1) - value = value.strip(' \t\n\r') - self.headers.add_header(header, value) + def begin(self): + HTTPResponse.begin(self) + header_payload = self.headers.get_payload() + if isinstance(header_payload, list) and len(header_payload) == 1: + header_payload = header_payload[0].get_payload() + if header_payload: + # This shouldn't be here. We must've bumped up against + # https://bugs.python.org/issue37093 + for line in header_payload.rstrip('\r\n').split('\n'): + if ':' not in line or line[:1] in ' \t': + # Well, we're no more broken than we were before... + # Should we support line folding? + # How can/should we handle a bad header line? + break + header, value = line.split(':', 1) + value = value.strip(' \t\n\r') + self.headers.add_header(header, value) def expect_response(self): if self.fp: @@ -125,15 +113,7 @@ def expect_response(self): self.status = status self.reason = reason.strip() self.version = 11 - if six.PY2: - # Under py2, HTTPMessage.__init__ reads the headers - # which advances fp - self.msg = HTTPMessage(self.fp, 0) - # immediately kill msg.fp to make sure it isn't read again - self.msg.fp = None - else: - # py3 has a separate helper for it - self.headers = self.msg = httplib.parse_headers(self.fp) + self.headers = self.msg = http.client.parse_headers(self.fp) def read(self, amt=None): if not self._readline_buffer: @@ -157,26 +137,6 @@ def read(self, amt=None): self._readline_buffer = b'' return buf + HTTPResponse.read(self, smaller_amt) - def readline(self, size=1024): - # You'd think Python's httplib would provide this, but it doesn't. - # It does, however, provide a comment in the HTTPResponse class: - # - # # XXX It would be nice to have readline and __iter__ for this, - # # too. - # - # Yes, it certainly would. - while (b'\n' not in self._readline_buffer - and len(self._readline_buffer) < size): - read_size = size - len(self._readline_buffer) - chunk = HTTPResponse.read(self, read_size) - if not chunk: - break - self._readline_buffer += chunk - - line, newline, rest = self._readline_buffer.partition(b'\n') - self._readline_buffer = rest - return line + newline - def nuke_from_orbit(self): """ Terminate the socket with extreme prejudice. @@ -186,14 +146,9 @@ def nuke_from_orbit(self): you care about has a reference to this socket. """ if self._real_socket: - if six.PY2: - # this is idempotent; see sock_close in Modules/socketmodule.c - # in the Python source for details. - self._real_socket.close() - else: - # Hopefully this is equivalent? - # TODO: verify that this does everything ^^^^ does for py2 - self._real_socket._real_close() + # Hopefully this is equivalent to py2's _real_socket.close()? + # TODO: verify that this does everything ^^^^ does for py2 + self._real_socket._real_close() self._real_socket = None self.close() @@ -268,13 +223,13 @@ def http_connect(ipaddr, port, device, partition, method, path, :param ssl: set True if SSL should be used (default: False) :returns: HTTPConnection object """ - if isinstance(path, six.text_type): + if isinstance(path, str): path = path.encode("utf-8") - if isinstance(device, six.text_type): + if isinstance(device, str): device = device.encode("utf-8") - if isinstance(partition, six.text_type): + if isinstance(partition, str): partition = partition.encode('utf-8') - elif isinstance(partition, six.integer_types): + elif isinstance(partition, int): partition = str(partition).encode('ascii') path = quote(b'/' + device + b'/' + partition + path) return http_connect_raw( @@ -305,14 +260,10 @@ def http_connect_raw(ipaddr, port, method, path, headers=None, conn = BufferedHTTPConnection('%s:%s' % (ipaddr, port)) if query_string: # Round trip to ensure proper quoting - if six.PY2: - query_string = urlencode(parse_qsl( - query_string, keep_blank_values=True)) - else: - query_string = urlencode( - parse_qsl(query_string, keep_blank_values=True, - encoding='latin1'), - encoding='latin1') + query_string = urlencode( + parse_qsl(query_string, keep_blank_values=True, + encoding='latin1'), + encoding='latin1') path += '?' + query_string conn.path = path conn.putrequest(method, path, skip_host=(headers and 'Host' in headers)) diff --git a/swift/common/constraints.py b/swift/common/constraints.py index f572107b84..7b9a5f9e74 100644 --- a/swift/common/constraints.py +++ b/swift/common/constraints.py @@ -17,9 +17,8 @@ import os from os.path import isdir # tighter scoped import for mocking -import six -from six.moves.configparser import ConfigParser, NoSectionError, NoOptionError -from six.moves import urllib +from configparser import ConfigParser, NoSectionError, NoOptionError +import urllib from swift.common import utils, exceptions from swift.common.swob import HTTPBadRequest, HTTPLengthRequired, \ @@ -130,7 +129,7 @@ def check_metadata(req, target_type): meta_count = 0 meta_size = 0 for key, value in req.headers.items(): - if (isinstance(value, six.string_types) + if (isinstance(value, str) and len(value) > MAX_HEADER_SIZE): return HTTPBadRequest(body=b'Header value too long: %s' % @@ -364,7 +363,7 @@ def check_utf8(string, internal=False): if not string: return False try: - if isinstance(string, six.text_type): + if isinstance(string, str): encoded = string.encode('utf-8') decoded = string else: @@ -412,9 +411,6 @@ def check_name_format(req, name, target_type): raise HTTPPreconditionFailed( request=req, body='%s name cannot be empty' % target_type) - if six.PY2: - if isinstance(name, six.text_type): - name = name.encode('utf-8') if '/' in name: raise HTTPPreconditionFailed( request=req, diff --git a/swift/common/container_sync_realms.py b/swift/common/container_sync_realms.py index 3fc437bcea..51adcddf34 100644 --- a/swift/common/container_sync_realms.py +++ b/swift/common/container_sync_realms.py @@ -19,8 +19,7 @@ import os import time -import six -from six.moves import configparser +import configparser from swift.common.utils import get_valid_utf8_str @@ -158,7 +157,7 @@ def get_sig(self, request_method, path, x_timestamp, nonce, realm_key, user_key = get_valid_utf8_str(user_key) # XXX We don't know what is the best here yet; wait for container # sync to be tested. - if isinstance(path, six.text_type): + if isinstance(path, str): path = path.encode('utf-8') return hmac.new( realm_key, diff --git a/swift/common/db.py b/swift/common/db.py index 7c80dc1fa5..f8c0648379 100644 --- a/swift/common/db.py +++ b/swift/common/db.py @@ -21,11 +21,9 @@ import logging import os from uuid import uuid4 -import sys import time import errno -import six -import six.moves.cPickle as pickle +import pickle # nosec: B403 from tempfile import mkstemp from eventlet import sleep, Timeout @@ -55,28 +53,14 @@ RECLAIM_PAGE_SIZE = 10000 -def utf8encode(*args): - return [(s.encode('utf8') if isinstance(s, six.text_type) else s) - for s in args] - - def native_str_keys_and_values(metadata): - if six.PY2: - uni_keys = [k for k in metadata if isinstance(k, six.text_type)] - for k in uni_keys: - sv = metadata[k] - del metadata[k] - metadata[k.encode('utf-8')] = [ - x.encode('utf-8') if isinstance(x, six.text_type) else x - for x in sv] - else: - bin_keys = [k for k in metadata if isinstance(k, six.binary_type)] - for k in bin_keys: - sv = metadata[k] - del metadata[k] - metadata[k.decode('utf-8')] = [ - x.decode('utf-8') if isinstance(x, six.binary_type) else x - for x in sv] + bin_keys = [k for k in metadata if isinstance(k, bytes)] + for k in bin_keys: + sv = metadata[k] + del metadata[k] + metadata[k.decode('utf-8')] = [ + x.decode('utf-8') if isinstance(x, bytes) else x + for x in sv] ZERO_LIKE_VALUES = {None, '', 0, '0'} @@ -219,7 +203,7 @@ def get_db_connection(path, timeout=30, logger=None, okay_to_create=False): connect_time = time.time() conn = sqlite3.connect(path, check_same_thread=False, factory=GreenDBConnection, timeout=timeout) - if QUERY_LOGGING and logger and not six.PY2: + if QUERY_LOGGING and logger: conn.set_trace_callback(logger.debug) if not okay_to_create: # attempt to detect and fail when connect creates the db file @@ -380,7 +364,7 @@ def initialize(self, put_timestamp=None, storage_policy_index=None): os.close(fd) conn = sqlite3.connect(tmp_db_file, check_same_thread=False, factory=GreenDBConnection, timeout=0) - if QUERY_LOGGING and not six.PY2: + if QUERY_LOGGING: conn.set_trace_callback(self.logger.debug) # creating dbs implicitly does a lot of transactions, so we # pick fast, unsafe options here and do a big fsync at the end. @@ -505,25 +489,25 @@ def quarantine(self, reason): self.logger.error(detail) raise sqlite3.DatabaseError(detail) - def possibly_quarantine(self, exc_type, exc_value, exc_traceback): + def possibly_quarantine(self, err): """ Checks the exception info to see if it indicates a quarantine situation (malformed or corrupted database). If not, the original exception will be reraised. If so, the database will be quarantined and a new sqlite3.DatabaseError will be raised indicating the action taken. """ - if 'database disk image is malformed' in str(exc_value): + if 'database disk image is malformed' in str(err): exc_hint = 'malformed database' - elif 'malformed database schema' in str(exc_value): + elif 'malformed database schema' in str(err): exc_hint = 'malformed database' - elif ' is not a database' in str(exc_value): + elif ' is not a database' in str(err): # older versions said 'file is not a database' # now 'file is encrypted or is not a database' exc_hint = 'corrupted database' - elif 'disk I/O error' in str(exc_value): + elif 'disk I/O error' in str(err): exc_hint = 'disk error while accessing database' else: - six.reraise(exc_type, exc_value, exc_traceback) + raise err self.quarantine(exc_hint) @@ -557,8 +541,8 @@ def get(self): try: self.conn = get_db_connection(self.db_file, self.timeout, self.logger) - except (sqlite3.DatabaseError, DatabaseConnectionError): - self.possibly_quarantine(*sys.exc_info()) + except (sqlite3.DatabaseError, DatabaseConnectionError) as e: + self.possibly_quarantine(e) else: raise DatabaseConnectionError(self.db_file, "DB doesn't exist") conn = self.conn @@ -567,12 +551,12 @@ def get(self): yield conn conn.rollback() self.conn = conn - except sqlite3.DatabaseError: + except sqlite3.DatabaseError as e: try: conn.close() except Exception: pass - self.possibly_quarantine(*sys.exc_info()) + self.possibly_quarantine(e) except (Exception, Timeout): conn.close() raise @@ -848,11 +832,8 @@ def _commit_puts(self, item_list=None): for entry in fp.read().split(b':'): if entry: try: - if six.PY2: - data = pickle.loads(base64.b64decode(entry)) - else: - data = pickle.loads(base64.b64decode(entry), - encoding='utf8') + data = pickle.loads(base64.b64decode(entry), + encoding='utf8') # nosec: B301 self._commit_puts_load(item_list, data) except Exception: self.logger.exception( diff --git a/swift/common/digest.py b/swift/common/digest.py index 34db19409b..36bc47a9bd 100644 --- a/swift/common/digest.py +++ b/swift/common/digest.py @@ -13,9 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. import binascii -import hashlib import hmac -import six from swift.common.utils import strict_b64decode @@ -55,17 +53,14 @@ def get_hmac(request_method, path, expires, key, digest="sha1", parts.insert(0, ip_range) formats.insert(0, b"ip=%s") - if not isinstance(key, six.binary_type): + if isinstance(key, str): key = key.encode('utf8') message = b'\n'.join( - fmt % (part if isinstance(part, six.binary_type) + fmt % (part if isinstance(part, bytes) else part.encode("utf-8")) for fmt, part in zip(formats, parts)) - if six.PY2 and isinstance(digest, six.string_types): - digest = getattr(hashlib, digest) - return hmac.new(key, message, digest).hexdigest() @@ -132,15 +127,10 @@ def extract_digest_and_algorithm(value): if ('-' in value or '_' in value) and not ( '+' in value or '/' in value): value = value.replace('-', '+').replace('_', '/') - value = binascii.hexlify(strict_b64decode(value + '==')) - if not six.PY2: - value = value.decode('ascii') + value = binascii.hexlify( + strict_b64decode(value + '==')).decode('ascii') else: - try: - binascii.unhexlify(value) # make sure it decodes - except TypeError: - # This is just for py2 - raise ValueError('Non-hexadecimal digit found') + binascii.unhexlify(value) # make sure it decodes algo = { 40: 'sha1', 64: 'sha256', diff --git a/swift/common/direct_client.py b/swift/common/direct_client.py index f2097d9fe0..94a4558384 100644 --- a/swift/common/direct_client.py +++ b/swift/common/direct_client.py @@ -23,9 +23,8 @@ import socket from eventlet import sleep, Timeout -import six -import six.moves.cPickle as pickle -from six.moves.http_client import HTTPException +import pickle # nosec: B403 +from http.client import HTTPException from swift.common.bufferedhttp import http_connect, http_connect_raw from swift.common.exceptions import ClientException @@ -44,7 +43,7 @@ def __init__(self, stype, method, node, part, path, resp, host=None): # host can be used to override the node ip and port reported in # the exception host = host if host is not None else node - if not isinstance(path, six.text_type): + if isinstance(path, bytes): path = path.decode("utf-8") full_path = quote('/%s/%s%s' % (node['device'], part, path)) msg = '%s server %s:%s direct %s %r gave status %s' % ( @@ -59,7 +58,7 @@ def __init__(self, stype, method, node, part, path, resp, host=None): class DirectClientReconException(ClientException): def __init__(self, method, node, path, resp): - if not isinstance(path, six.text_type): + if isinstance(path, bytes): path = path.decode("utf-8") msg = 'server %s:%s direct %s %r gave status %s' % ( node['ip'], node['port'], method, path, resp.status) @@ -72,7 +71,7 @@ def __init__(self, method, node, path, resp): def _make_path(*components): return u'/' + u'/'.join( - x.decode('utf-8') if isinstance(x, six.binary_type) else x + x.decode('utf-8') if isinstance(x, bytes) else x for x in components) @@ -111,7 +110,7 @@ def _make_req(node, part, method, path, headers, stype, content_length = int(v) if not contents: headers['Content-Length'] = '0' - if isinstance(contents, six.string_types): + if isinstance(contents, str): contents = [contents] if content_length is None: headers['Transfer-Encoding'] = 'chunked' @@ -657,7 +656,7 @@ def direct_get_suffix_hashes(node, part, suffixes, conn_timeout=5, host={'ip': node['replication_ip'], 'port': node['replication_port']} ) - return pickle.loads(resp.read()) + return pickle.loads(resp.read()) # nosec: B301 def retry(func, *args, **kwargs): diff --git a/swift/common/header_key_dict.py b/swift/common/header_key_dict.py index 6cabe1ef9e..f6b906a15e 100644 --- a/swift/common/header_key_dict.py +++ b/swift/common/header_key_dict.py @@ -13,8 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import six - class HeaderKeyDict(dict): """ @@ -31,10 +29,7 @@ def __init__(self, base_headers=None, **kwargs): @staticmethod def _title(s): - if six.PY2: - return s.title() - else: - return s.encode('latin1').title().decode('latin1') + return s.encode('latin1').title().decode('latin1') def update(self, other): if hasattr(other, 'keys'): @@ -51,9 +46,7 @@ def __setitem__(self, key, value): key = self._title(key) if value is None: self.pop(key, None) - elif six.PY2 and isinstance(value, six.text_type): - return dict.__setitem__(self, key, value.encode('utf-8')) - elif six.PY3 and isinstance(value, six.binary_type): + elif isinstance(value, bytes): return dict.__setitem__(self, key, value.decode('latin-1')) else: return dict.__setitem__(self, key, str(value)) diff --git a/swift/common/http_protocol.py b/swift/common/http_protocol.py index 8147ad5597..c803cce05b 100644 --- a/swift/common/http_protocol.py +++ b/swift/common/http_protocol.py @@ -14,18 +14,13 @@ # limitations under the License. from eventlet import wsgi, websocket -import six from swift.common.utils import generate_trans_id from swift.common.http import HTTP_NO_CONTENT, HTTP_RESET_CONTENT, \ HTTP_NOT_MODIFIED -if six.PY2: - from eventlet.green import httplib as http_client - from cgi import escape -else: - from eventlet.green.http import client as http_client - from html import escape +from eventlet.green.http import client as http_client +from html import escape class SwiftHttpProtocol(wsgi.HttpProtocol): @@ -59,13 +54,6 @@ def log_message(self, f, *a): class MessageClass(wsgi.HttpProtocol.MessageClass): """Subclass to see when the client didn't provide a Content-Type""" - # for py2: - def parsetype(self): - if self.typeheader is None: - self.typeheader = '' - wsgi.HttpProtocol.MessageClass.parsetype(self) - - # for py3: def get_default_type(self): """If the client didn't provide a content type, leave it blank.""" return '' @@ -84,9 +72,7 @@ def parse_request(self): self.command = None # set in case of error on the first line self.request_version = version = self.default_request_version self.close_connection = True - requestline = self.raw_requestline - if not six.PY2: - requestline = requestline.decode('iso-8859-1') + requestline = self.raw_requestline.decode('iso-8859-1') requestline = requestline.rstrip('\r\n') self.requestline = requestline # Split off \x20 explicitly (see https://bugs.python.org/issue33973) @@ -147,26 +133,23 @@ def parse_request(self): self.command, self.path = command, path # Examine the headers and look for a Connection directive. - if six.PY2: - self.headers = self.MessageClass(self.rfile, 0) - else: - try: - self.headers = http_client.parse_headers( - self.rfile, - _class=self.MessageClass) - except http_client.LineTooLong as err: - self.send_error( - 431, - "Line too long", - str(err)) - return False - except http_client.HTTPException as err: - self.send_error( - 431, - "Too many headers", - str(err) - ) - return False + try: + self.headers = http_client.parse_headers( + self.rfile, + _class=self.MessageClass) + except http_client.LineTooLong as err: + self.send_error( + 431, + "Line too long", + str(err)) + return False + except http_client.HTTPException as err: + self.send_error( + 431, + "Too many headers", + str(err) + ) + return False conntype = self.headers.get('Connection', "") if conntype.lower() == 'close': @@ -183,52 +166,51 @@ def parse_request(self): return False return True - if not six.PY2: - def get_environ(self, *args, **kwargs): - environ = wsgi.HttpProtocol.get_environ(self, *args, **kwargs) - header_payload = self.headers.get_payload() - if isinstance(header_payload, list) and len(header_payload) == 1: - header_payload = header_payload[0].get_payload() - if header_payload: - # This shouldn't be here. We must've bumped up against - # https://bugs.python.org/issue37093 - headers_raw = list(environ['headers_raw']) - for line in header_payload.rstrip('\r\n').split('\n'): - if ':' not in line or line[:1] in ' \t': - # Well, we're no more broken than we were before... - # Should we support line folding? - # Should we 400 a bad header line? - break - header, value = line.split(':', 1) - value = value.strip(' \t\n\r') - # NB: Eventlet looks at the headers obj to figure out - # whether the client said the connection should close; - # see https://github.com/eventlet/eventlet/blob/v0.25.0/ - # eventlet/wsgi.py#L504 - self.headers.add_header(header, value) - headers_raw.append((header, value)) - wsgi_key = 'HTTP_' + header.replace('-', '_').encode( - 'latin1').upper().decode('latin1') - if wsgi_key in ('HTTP_CONTENT_LENGTH', - 'HTTP_CONTENT_TYPE'): - wsgi_key = wsgi_key[5:] - environ[wsgi_key] = value - environ['headers_raw'] = tuple(headers_raw) - # Since we parsed some more headers, check to see if they - # change how our wsgi.input should behave - te = environ.get('HTTP_TRANSFER_ENCODING', '').lower() - if te.rsplit(',', 1)[-1].strip() == 'chunked': - environ['wsgi.input'].chunked_input = True - else: - length = environ.get('CONTENT_LENGTH') - if length: - length = int(length) - environ['wsgi.input'].content_length = length - if environ.get('HTTP_EXPECT', '').lower() == '100-continue': - environ['wsgi.input'].wfile = self.wfile - environ['wsgi.input'].wfile_line = \ - b'HTTP/1.1 100 Continue\r\n' - return environ + def get_environ(self, *args, **kwargs): + environ = wsgi.HttpProtocol.get_environ(self, *args, **kwargs) + header_payload = self.headers.get_payload() + if isinstance(header_payload, list) and len(header_payload) == 1: + header_payload = header_payload[0].get_payload() + if header_payload: + # This shouldn't be here. We must've bumped up against + # https://bugs.python.org/issue37093 + headers_raw = list(environ['headers_raw']) + for line in header_payload.rstrip('\r\n').split('\n'): + if ':' not in line or line[:1] in ' \t': + # Well, we're no more broken than we were before... + # Should we support line folding? + # Should we 400 a bad header line? + break + header, value = line.split(':', 1) + value = value.strip(' \t\n\r') + # NB: Eventlet looks at the headers obj to figure out + # whether the client said the connection should close; + # see https://github.com/eventlet/eventlet/blob/v0.25.0/ + # eventlet/wsgi.py#L504 + self.headers.add_header(header, value) + headers_raw.append((header, value)) + wsgi_key = 'HTTP_' + header.replace('-', '_').encode( + 'latin1').upper().decode('latin1') + if wsgi_key in ('HTTP_CONTENT_LENGTH', + 'HTTP_CONTENT_TYPE'): + wsgi_key = wsgi_key[5:] + environ[wsgi_key] = value + environ['headers_raw'] = tuple(headers_raw) + # Since we parsed some more headers, check to see if they + # change how our wsgi.input should behave + te = environ.get('HTTP_TRANSFER_ENCODING', '').lower() + if te.rsplit(',', 1)[-1].strip() == 'chunked': + environ['wsgi.input'].chunked_input = True + else: + length = environ.get('CONTENT_LENGTH') + if length: + length = int(length) + environ['wsgi.input'].content_length = length + if environ.get('HTTP_EXPECT', '').lower() == '100-continue': + environ['wsgi.input'].wfile = self.wfile + environ['wsgi.input'].wfile_line = \ + b'HTTP/1.1 100 Continue\r\n' + return environ def _read_request_line(self): # Note this is not a new-style class, so super() won't work @@ -332,8 +314,7 @@ def __init__(self, *a, **kw): SwiftHttpProtocol.__init__(self, *a, **kw) def handle_error(self, connection_line): - if not six.PY2: - connection_line = connection_line.decode('latin-1') + connection_line = connection_line.decode('latin-1') # No further processing will proceed on this connection under any # circumstances. We always send the request into the superclass to @@ -373,16 +354,12 @@ def handle(self): # line. pass elif proxy_parts[1] in (b'TCP4', b'TCP6') and len(proxy_parts) == 6: - if six.PY2: - self.client_address = (proxy_parts[2], proxy_parts[4]) - self.proxy_address = (proxy_parts[3], proxy_parts[5]) - else: - self.client_address = ( - proxy_parts[2].decode('latin-1'), - proxy_parts[4].decode('latin-1')) - self.proxy_address = ( - proxy_parts[3].decode('latin-1'), - proxy_parts[5].decode('latin-1')) + self.client_address = ( + proxy_parts[2].decode('latin-1'), + proxy_parts[4].decode('latin-1')) + self.proxy_address = ( + proxy_parts[3].decode('latin-1'), + proxy_parts[5].decode('latin-1')) else: self.handle_error(connection_line) diff --git a/swift/common/internal_client.py b/swift/common/internal_client.py index fc5242ae8a..883cd4e16e 100644 --- a/swift/common/internal_client.py +++ b/swift/common/internal_client.py @@ -14,13 +14,13 @@ # limitations under the License. from eventlet import sleep, Timeout, spawn -from eventlet.green import httplib, socket +from eventlet.green import socket +from eventlet.green.http import client as http_client +from eventlet.green.urllib import request as urllib_request import json -import six -from six.moves import range -from six.moves import urllib +import urllib import struct -from sys import exc_info, exit +from sys import exit import zlib from time import gmtime, strftime, time from zlib import compressobj @@ -34,11 +34,6 @@ from swift.common.utils import quote, close_if_possible, drain_and_close from swift.common.wsgi import loadapp -if six.PY3: - from eventlet.green.urllib import request as urllib2 -else: - from eventlet.green import urllib2 - class UnexpectedResponse(Exception): """ @@ -127,8 +122,6 @@ def __next__(self): return chunk raise StopIteration - next = __next__ - def seek(self, offset, whence=0): if not (offset == 0 and whence == 0): raise NotImplementedError('Seek implemented on offset 0 only') @@ -217,7 +210,7 @@ def make_request( headers.setdefault(USE_REPLICATION_NETWORK_HEADER, 'true') for attempt in range(self.request_tries): - resp = exc_type = exc_value = exc_traceback = None + resp = err = None req = Request.blank( path, environ={'REQUEST_METHOD': method}, headers=headers) if body_file is not None: @@ -229,8 +222,8 @@ def make_request( try: # execute in a separate greenthread to not polute corolocals resp = spawn(req.get_response, self.app).wait() - except (Exception, Timeout): - exc_type, exc_value, exc_traceback = exc_info() + except (Exception, Timeout) as e: + err = e else: if resp.status_int in acceptable_statuses or \ resp.status_int // 100 in acceptable_statuses: @@ -256,9 +249,8 @@ def make_request( # non 2XX responses msg += ' (%s)' % resp.body raise UnexpectedResponse(msg, resp) - if exc_type: - # To make pep8 tool happy, in place of raise t, v, tb: - six.reraise(exc_type, exc_value, exc_traceback) + if err: + raise err def handle_request(self, *args, **kwargs): resp = self.make_request(*args, **kwargs) @@ -848,10 +840,10 @@ def upload_object( def get_auth(url, user, key, auth_version='1.0', **kwargs): if auth_version != '1.0': exit('ERROR: swiftclient missing, only auth v1.0 supported') - req = urllib2.Request(url) + req = urllib_request.Request(url) req.add_header('X-Auth-User', user) req.add_header('X-Auth-Key', key) - conn = urllib2.urlopen(req) + conn = urllib_request.urlopen(req) headers = conn.info() return ( headers.getheader('X-Storage-Url'), @@ -914,12 +906,12 @@ def base_request(self, method, container=None, name=None, prefix=None, url += '?' + '&'.join(params) - req = urllib2.Request(url, headers=headers, data=contents) + req = urllib_request.Request(url, headers=headers, data=contents) if proxy: proxy = urllib.parse.urlparse(proxy) req.set_proxy(proxy.netloc, proxy.scheme) req.get_method = lambda: method - conn = urllib2.urlopen(req, timeout=timeout) + conn = urllib_request.urlopen(req, timeout=timeout) body = conn.read() info = conn.info() try: @@ -961,14 +953,15 @@ def retry_request(self, method, **kwargs): self.attempts += 1 try: return self.base_request(method, **kwargs) - except urllib2.HTTPError as err: + except urllib_request.HTTPError as err: if is_client_error(err.getcode() or 500): raise ClientException('Client error', http_status=err.getcode()) elif self.attempts > retries: raise ClientException('Raise too many retries', http_status=err.getcode()) - except (socket.error, httplib.HTTPException, urllib2.URLError): + except (socket.error, http_client.HTTPException, + urllib_request.URLError): if self.attempts > retries: raise sleep(backoff) diff --git a/swift/common/linkat.py b/swift/common/linkat.py index 3de45e2a3d..a85463a325 100644 --- a/swift/common/linkat.py +++ b/swift/common/linkat.py @@ -17,8 +17,6 @@ import ctypes from ctypes.util import find_library -import six - __all__ = ['linkat'] @@ -72,9 +70,9 @@ def __call__(self, olddirfd, oldpath, newdirfd, newpath, flags): if not isinstance(olddirfd, int) or not isinstance(newdirfd, int): raise TypeError("fd must be an integer.") - if isinstance(oldpath, six.text_type): + if isinstance(oldpath, str): oldpath = oldpath.encode('utf8') - if isinstance(newpath, six.text_type): + if isinstance(newpath, str): newpath = newpath.encode('utf8') return self._c_linkat(olddirfd, oldpath, newdirfd, newpath, flags) diff --git a/swift/common/manager.py b/swift/common/manager.py index a0e0ef56ec..80beecf46b 100644 --- a/swift/common/manager.py +++ b/swift/common/manager.py @@ -24,14 +24,9 @@ import time import subprocess import re -import six import sys import tempfile -try: - from shutil import which -except ImportError: - # py2 - from distutils.spawn import find_executable as which +from shutil import which from swift.common.utils import search_tree, remove_file, write_file, readconf from swift.common.exceptions import InvalidPidFileException @@ -845,10 +840,8 @@ def wait(self, **kwargs): if proc.stdout.closed: output = '' else: - output = proc.stdout.read() + output = proc.stdout.read().decode('utf8', 'backslashreplace') proc.stdout.close() - if not six.PY2: - output = output.decode('utf8', 'backslashreplace') if kwargs.get('once', False): # if you don't want once to wait you can send it to the diff --git a/swift/common/memcached.py b/swift/common/memcached.py index 68f3424c76..9ffd861f34 100644 --- a/swift/common/memcached.py +++ b/swift/common/memcached.py @@ -45,7 +45,6 @@ """ import os -import six import json import logging # the name of 'time' module is changed to 'tm', to avoid changing the @@ -56,8 +55,7 @@ from eventlet.green import socket, ssl from eventlet.pools import Pool from eventlet import Timeout -from six.moves import range -from six.moves.configparser import ConfigParser, NoSectionError, NoOptionError +from configparser import ConfigParser, NoSectionError, NoOptionError from swift.common import utils from swift.common.exceptions import MemcacheConnectionError, \ MemcacheIncrNotFoundError, MemcachePoolTimeout @@ -91,10 +89,7 @@ def md5hash(key): if not isinstance(key, bytes): - if six.PY2: - key = key.encode('utf-8') - else: - key = key.encode('utf-8', errors='surrogateescape') + key = key.encode('utf-8', errors='surrogateescape') return md5(key, usedforsecurity=False).hexdigest().encode('ascii') @@ -421,8 +416,7 @@ def set(self, key, value, serialize=True, time=0, # Wait for the set to complete msg = fp.readline().strip() if msg != b'STORED': - if not six.PY2: - msg = msg.decode('ascii') + msg = msg.decode('ascii') raise MemcacheConnectionError('failed set: %s' % msg) self._return_conn(server, fp, sock) return diff --git a/swift/common/middleware/acl.py b/swift/common/middleware/acl.py index b0a01166c4..a8c0e04bce 100644 --- a/swift/common/middleware/acl.py +++ b/swift/common/middleware/acl.py @@ -14,8 +14,7 @@ # limitations under the License. import json -import six -from six.moves.urllib.parse import unquote, urlparse +from urllib.parse import unquote, urlparse def clean_acl(name, value): @@ -294,12 +293,8 @@ def acls_from_account_info(info): if not any((admin_members, readwrite_members, readonly_members)): return None - acls = { + return { 'admin': admin_members, 'read-write': readwrite_members, 'read-only': readonly_members, } - if six.PY2: - for k in ('admin', 'read-write', 'read-only'): - acls[k] = [v.encode('utf8') for v in acls[k]] - return acls diff --git a/swift/common/middleware/bulk.py b/swift/common/middleware/bulk.py index 6484508057..eb6465f16e 100644 --- a/swift/common/middleware/bulk.py +++ b/swift/common/middleware/bulk.py @@ -195,7 +195,6 @@ """ import json -import six import tarfile from xml.sax.saxutils import escape # nosec B406 from time import time @@ -257,8 +256,6 @@ def get_response_body(data_format, data_dict, error_list, root_tag): escape(status), '\n', ]) output.extend(['\n', root_tag, '>\n']) - if six.PY2: - return ''.join(output) return ''.join(output).encode('utf-8') output = [] @@ -268,8 +265,6 @@ def get_response_body(data_format, data_dict, error_list, root_tag): output.extend( '%s, %s\n' % (name, status) for name, status in error_list) - if six.PY2: - return ''.join(output) return ''.join(output).encode('utf-8') @@ -279,13 +274,9 @@ def pax_key_to_swift_header(pax_key): return "Content-Type" elif pax_key.startswith(u"SCHILY.xattr.user.meta."): useful_part = pax_key[len(u"SCHILY.xattr.user.meta."):] - if six.PY2: - return "X-Object-Meta-" + useful_part.encode("utf-8") return str_to_wsgi("X-Object-Meta-" + useful_part) elif pax_key.startswith(u"LIBARCHIVE.xattr.user.meta."): useful_part = pax_key[len(u"LIBARCHIVE.xattr.user.meta."):] - if six.PY2: - return "X-Object-Meta-" + useful_part.encode("utf-8") return str_to_wsgi("X-Object-Meta-" + useful_part) else: # You can get things like atime/mtime/ctime or filesystem ACLs in @@ -357,15 +348,12 @@ def get_objs_to_delete(self, req): while data_remaining: if b'\n' in line: obj_to_delete, line = line.split(b'\n', 1) - if six.PY2: - obj_to_delete = wsgi_unquote(obj_to_delete.strip()) - else: - # yeah, all this chaining is pretty terrible... - # but it gets even worse trying to use UTF-8 and - # errors='surrogateescape' when dealing with terrible - # input like b'\xe2%98\x83' - obj_to_delete = wsgi_to_str(wsgi_unquote( - bytes_to_wsgi(obj_to_delete.strip()))) + # yeah, all this chaining is pretty terrible... + # but it gets even worse trying to use UTF-8 and + # errors='surrogateescape' when dealing with terrible + # input like b'\xe2%98\x83' + obj_to_delete = wsgi_to_str(wsgi_unquote( + bytes_to_wsgi(obj_to_delete.strip()))) objs_to_delete.append({'name': obj_to_delete}) else: data = req.body_file.read(self.max_path_length) @@ -373,11 +361,8 @@ def get_objs_to_delete(self, req): line += data else: data_remaining = False - if six.PY2: - obj_to_delete = wsgi_unquote(line.strip()) - else: - obj_to_delete = wsgi_to_str(wsgi_unquote( - bytes_to_wsgi(line.strip()))) + obj_to_delete = wsgi_to_str(wsgi_unquote( + bytes_to_wsgi(line.strip()))) if obj_to_delete: objs_to_delete.append({'name': obj_to_delete}) if len(objs_to_delete) > self.max_deletes_per_request: @@ -577,9 +562,7 @@ def handle_extract_iter(self, req, compress_type, len(failed_files) >= self.max_failed_extractions: break if tar_info.isfile(): - obj_path = tar_info.name - if not six.PY2: - obj_path = obj_path.encode('utf-8', 'surrogateescape') + obj_path = tar_info.name.encode('utf-8', 'surrogateescape') obj_path = bytes_to_wsgi(obj_path) if obj_path.startswith('./'): obj_path = obj_path[2:] diff --git a/swift/common/middleware/cname_lookup.py b/swift/common/middleware/cname_lookup.py index 8cf5123e14..b9ef4f616f 100644 --- a/swift/common/middleware/cname_lookup.py +++ b/swift/common/middleware/cname_lookup.py @@ -27,8 +27,6 @@ rewritten and the request is passed further down the WSGI chain. """ -import six - try: import dns.resolver import dns.exception @@ -149,8 +147,6 @@ def __call__(self, env, start_response): if self.memcache: memcache_key = ''.join(['cname-', a_domain]) found_domain = self.memcache.get(memcache_key) - if six.PY2 and found_domain: - found_domain = found_domain.encode('utf-8') if found_domain is None: ttl, found_domain = lookup_cname(a_domain, self.resolver) if self.memcache and ttl > 0: diff --git a/swift/common/middleware/crypto/crypto_utils.py b/swift/common/middleware/crypto/crypto_utils.py index 16beceddd2..5cd2740bf9 100644 --- a/swift/common/middleware/crypto/crypto_utils.py +++ b/swift/common/middleware/crypto/crypto_utils.py @@ -19,8 +19,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes -import six -from six.moves.urllib import parse as urlparse +import urllib.parse from swift.common.exceptions import EncryptionException, UnknownSecretIdError from swift.common.swob import HTTPInternalServerError @@ -225,7 +224,7 @@ def b64_encode_meta(crypto_meta): for name, value in crypto_meta.items()} # use sort_keys=True to make serialized form predictable for testing - return urlparse.quote_plus( + return urllib.parse.quote_plus( json.dumps(b64_encode_meta(crypto_meta), sort_keys=True)) @@ -251,13 +250,13 @@ def b64_decode_meta(crypto_meta): str(name): ( base64.b64decode(val) if name in ('iv', 'key') and b64decode else b64_decode_meta(val) if isinstance(val, dict) - else val.encode('utf8') if six.PY2 else val) + else val) for name, val in crypto_meta.items()} try: - if not isinstance(value, six.string_types): + if not isinstance(value, str): raise ValueError('crypto meta not a string') - val = json.loads(urlparse.unquote_plus(value)) + val = json.loads(urllib.parse.unquote_plus(value)) if not isinstance(val, dict): raise ValueError('crypto meta not a Mapping') return b64_decode_meta(val) diff --git a/swift/common/middleware/crypto/keymaster.py b/swift/common/middleware/crypto/keymaster.py index 42f723d3de..f8d0e046ba 100644 --- a/swift/common/middleware/crypto/keymaster.py +++ b/swift/common/middleware/crypto/keymaster.py @@ -14,7 +14,6 @@ # limitations under the License. import hashlib import hmac -import six from swift.common.exceptions import UnknownSecretIdError from swift.common.middleware.crypto.crypto_utils import CRYPTO_KEY_CALLBACK @@ -101,14 +100,9 @@ def fetch_crypto_keys(self, key_id=None, *args, **kwargs): # Older py3 proxies may have written down crypto meta as WSGI # strings; we still need to be able to read that try: - if six.PY2: - alt_path = tuple( - part.decode('utf-8').encode('latin1') - for part in (key_acct, key_cont, key_obj)) - else: - alt_path = tuple( - part.encode('latin1').decode('utf-8') - for part in (key_acct, key_cont, key_obj)) + alt_path = tuple( + part.encode('latin1').decode('utf-8') + for part in (key_acct, key_cont, key_obj)) except UnicodeError: # Well, it was worth a shot pass @@ -336,8 +330,7 @@ def create_key(self, path, secret_id=None): self.logger.warning('Unrecognised secret id: %s' % secret_id) raise UnknownSecretIdError(secret_id) else: - if not six.PY2: - path = path.encode('utf-8') + path = path.encode('utf-8') return hmac.new(key, path, digestmod=hashlib.sha256).digest() diff --git a/swift/common/middleware/dlo.py b/swift/common/middleware/dlo.py index 5cb5223099..1b41ac9091 100644 --- a/swift/common/middleware/dlo.py +++ b/swift/common/middleware/dlo.py @@ -120,8 +120,6 @@ import json -import six - from swift.common import constraints from swift.common.exceptions import ListingIterError, SegmentError from swift.common.http import is_success @@ -207,8 +205,6 @@ def _segment_listing_iterator(self, req, version, account, container, break seg_name = segment['name'] - if six.PY2: - seg_name = seg_name.encode("utf-8") # We deliberately omit the etag and size here; # SegmentedIterable will check size and etag if diff --git a/swift/common/middleware/formpost.py b/swift/common/middleware/formpost.py index 45b5800956..00acfb5430 100644 --- a/swift/common/middleware/formpost.py +++ b/swift/common/middleware/formpost.py @@ -123,11 +123,9 @@ __all__ = ['FormPost', 'filter_factory', 'READ_CHUNK_SIZE', 'MAX_VALUE_LENGTH'] import hmac -import hashlib from time import time -import six -from six.moves.urllib.parse import quote +from urllib.parse import quote from swift.common.constraints import valid_api_version from swift.common.exceptions import MimeInvalid @@ -249,9 +247,7 @@ def __call__(self, env, start_response): ('Content-Length', str(len(body))))) return [body] except (FormInvalid, EOFError) as err: - body = 'FormPost: %s' % err - if six.PY3: - body = body.encode('utf-8') + body = ('FormPost: %s' % err).encode('utf-8') start_response( '400 Bad Request', (('Content-Type', 'text/plain'), @@ -273,8 +269,7 @@ def _translate_form(self, env, boundary): :returns: status_line, headers_list, body """ keys = self._get_keys(env) - if six.PY3: - boundary = boundary.encode('utf-8') + boundary = boundary.encode('utf-8') status = message = '' attributes = {} file_attributes = {} @@ -320,8 +315,7 @@ def _translate_form(self, env, boundary): data += chunk while fp.read(READ_CHUNK_SIZE): pass - if six.PY3: - data = data.decode('utf-8') + data = data.decode('utf-8') if 'name' in attrs: attributes[attrs['name'].lower()] = data.rstrip('\r\n--') if not status: @@ -337,8 +331,7 @@ def _translate_form(self, env, boundary): body = status if message: body = status + '\r\nFormPost: ' + message.title() - if six.PY3: - body = body.encode('utf-8') + body = body.encode('utf-8') if not is_success(status_code) and resp_body: body = resp_body headers.extend([('Content-Type', 'text/plain'), @@ -352,8 +345,7 @@ def _translate_form(self, env, boundary): quote(message)) body = '
' % redirect - if six.PY3: - body = body.encode('utf-8') + body = body.encode('utf-8') headers.extend( [('Location', redirect), ('Content-Length', str(len(body)))]) return '303 See Other', headers, body @@ -415,8 +407,7 @@ def _perform_subrequest(self, orig_env, attributes, fp, keys): attributes.get('max_file_size') or '0', attributes.get('max_file_count') or '0', attributes.get('expires') or '0') - if six.PY3: - hmac_body = hmac_body.encode('utf-8') + hmac_body = hmac_body.encode('utf-8') has_valid_sig = False signature = attributes.get('signature', '') @@ -426,13 +417,12 @@ def _perform_subrequest(self, orig_env, attributes, fp, keys): raise FormUnauthorized('invalid signature') if hash_name not in self.allowed_digests: raise FormUnauthorized('invalid signature') - hash_algorithm = getattr(hashlib, hash_name) if six.PY2 else hash_name for key in keys: # Encode key like in swift.common.utls.get_hmac. - if not isinstance(key, six.binary_type): + if not isinstance(key, bytes): key = key.encode('utf8') - sig = hmac.new(key, hmac_body, hash_algorithm).hexdigest() + sig = hmac.new(key, hmac_body, hash_name).hexdigest() if streq_const_time(sig, signature): has_valid_sig = True if not has_valid_sig: diff --git a/swift/common/middleware/gatekeeper.py b/swift/common/middleware/gatekeeper.py index 0254fef98b..dfb5ef04b0 100644 --- a/swift/common/middleware/gatekeeper.py +++ b/swift/common/middleware/gatekeeper.py @@ -36,7 +36,7 @@ from swift.common.request_helpers import ( remove_items, get_sys_meta_prefix, OBJECT_TRANSIENT_SYSMETA_PREFIX ) -from six.moves.urllib.parse import urlsplit +from urllib.parse import urlsplit import re #: A list of python regular expressions that will be used to diff --git a/swift/common/middleware/list_endpoints.py b/swift/common/middleware/list_endpoints.py index 424dc7b822..edceec421e 100644 --- a/swift/common/middleware/list_endpoints.py +++ b/swift/common/middleware/list_endpoints.py @@ -80,7 +80,7 @@ import json -from six.moves.urllib.parse import quote, unquote +from urllib.parse import quote, unquote from swift.common.ring import Ring from swift.common.utils import get_logger, split_path diff --git a/swift/common/middleware/listing_formats.py b/swift/common/middleware/listing_formats.py index 643341afb7..6d4ece4719 100644 --- a/swift/common/middleware/listing_formats.py +++ b/swift/common/middleware/listing_formats.py @@ -14,7 +14,6 @@ # limitations under the License. import json -import six from xml.etree.cElementTree import Element, SubElement, tostring from swift.common.constraints import valid_api_version @@ -84,8 +83,7 @@ def account_to_xml(listing, account_name): else: sub = SubElement(doc, 'container') for field in ('name', 'count', 'bytes', 'last_modified'): - SubElement(sub, field).text = six.text_type( - record.pop(field)) + SubElement(sub, field).text = str(record.pop(field)) sub.tail = '\n' return to_xml(doc) @@ -101,8 +99,7 @@ def container_to_xml(listing, base_name): sub = SubElement(doc, 'object') for field in ('name', 'hash', 'bytes', 'content_type', 'last_modified'): - SubElement(sub, field).text = six.text_type( - record.pop(field)) + SubElement(sub, field).text = str(record.pop(field)) return to_xml(doc) @@ -126,8 +123,6 @@ def filter_reserved(self, listing, account, container): for entry in list(listing): for key in ('name', 'subdir'): value = entry.get(key, '') - if six.PY2: - value = value.encode('utf-8') if RESERVED in value: if container: self.logger.warning( diff --git a/swift/common/middleware/s3api/controllers/bucket.py b/swift/common/middleware/s3api/controllers/bucket.py index 35d9fc516f..c4c8530c16 100644 --- a/swift/common/middleware/s3api/controllers/bucket.py +++ b/swift/common/middleware/s3api/controllers/bucket.py @@ -16,8 +16,7 @@ from base64 import standard_b64encode as b64encode from base64 import standard_b64decode as b64decode -import six -from six.moves.urllib.parse import quote +from urllib.parse import quote from swift.common import swob from swift.common.http import HTTP_OK @@ -145,9 +144,8 @@ def _parse_request_options(self, req, max_keys): query['marker'] = swob.wsgi_to_str(req.params['start-after']) # continuation-token overrides start-after if 'continuation-token' in req.params: - decoded = b64decode(req.params['continuation-token']) - if not six.PY2: - decoded = decoded.decode('utf8') + decoded = b64decode( + req.params['continuation-token']).decode('utf8') query['marker'] = decoded if 'fetch-owner' in req.params: fetch_owner = config_true_value(req.params['fetch-owner']) diff --git a/swift/common/middleware/s3api/controllers/multi_upload.py b/swift/common/middleware/s3api/controllers/multi_upload.py index 735d2be7cd..07e71a12af 100644 --- a/swift/common/middleware/s3api/controllers/multi_upload.py +++ b/swift/common/middleware/s3api/controllers/multi_upload.py @@ -65,17 +65,14 @@ import re import time -import six - from swift.common import constraints from swift.common.swob import Range, bytes_to_wsgi, normalize_etag, \ wsgi_to_str from swift.common.utils import json, public, reiterate, md5, Timestamp -from swift.common.db import utf8encode from swift.common.request_helpers import get_container_update_override_key, \ get_param -from six.moves.urllib.parse import quote, urlparse +from urllib.parse import quote, urlparse from swift.common.middleware.s3api.controllers.base import Controller, \ bucket_operation, object_operation, check_container_existence @@ -293,8 +290,6 @@ def separate_uploads(uploads, prefix, delimiter): :return (non_delimited_uploads, common_prefixes) """ - if six.PY2: - (prefix, delimiter) = utf8encode(prefix, delimiter) non_delimited_uploads = [] common_prefixes = set() for upload in uploads: @@ -363,10 +358,7 @@ def object_to_upload(object_info): new_uploads, prefix, delimiter) uploads.extend(new_uploads) prefixes.extend(new_prefixes) - if six.PY2: - query['marker'] = objects[-1]['name'].encode('utf-8') - else: - query['marker'] = objects[-1]['name'] + query['marker'] = objects[-1]['name'] truncated = len(uploads) >= maxuploads if len(uploads) > maxuploads: @@ -542,10 +534,7 @@ def filter_part_num_marker(o): if not new_objects: break objects.extend(new_objects) - if six.PY2: - query['marker'] = new_objects[-1]['name'].encode('utf-8') - else: - query['marker'] = new_objects[-1]['name'] + query['marker'] = new_objects[-1]['name'] last_part = 0 @@ -642,10 +631,7 @@ def DELETE(self, req): container = req.container_name + MULTIUPLOAD_SUFFIX obj = bytes_to_wsgi(o['name'].encode('utf-8')) req.get_response(self.app, container=container, obj=obj) - if six.PY2: - query['marker'] = objects[-1]['name'].encode('utf-8') - else: - query['marker'] = objects[-1]['name'] + query['marker'] = objects[-1]['name'] resp = req.get_response(self.app, 'GET', container, '', query=query) objects = json.loads(resp.body) diff --git a/swift/common/middleware/s3api/controllers/s3_acl.py b/swift/common/middleware/s3api/controllers/s3_acl.py index 7bb3764e08..ddd7fbe3d2 100644 --- a/swift/common/middleware/s3api/controllers/s3_acl.py +++ b/swift/common/middleware/s3api/controllers/s3_acl.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from six.moves.urllib.parse import quote +from urllib.parse import quote from swift.common.utils import public from swift.common.middleware.s3api.controllers.base import Controller diff --git a/swift/common/middleware/s3api/etree.py b/swift/common/middleware/s3api/etree.py index 4c24f8427b..e5d4112b8f 100644 --- a/swift/common/middleware/s3api/etree.py +++ b/swift/common/middleware/s3api/etree.py @@ -26,12 +26,11 @@ else: import importlib.resources resource_stream = None -import six from swift.common.utils import get_logger from swift.common.middleware.s3api.exception import S3Exception from swift.common.middleware.s3api.utils import camel_to_snake, \ - utf8encode, utf8decode + utf8decode XMLNS_S3 = 'http://s3.amazonaws.com/doc/2006-03-01/' XMLNS_XSI = 'http://www.w3.org/2001/XMLSchema-instance' @@ -51,7 +50,7 @@ def remove_ns(tag, ns): tag = tag[len('{%s}' % ns):] return tag - if not isinstance(elem.tag, six.string_types): + if not isinstance(elem.tag, str): # elem is a comment element. return @@ -136,8 +135,6 @@ def text(self): """ utf-8 wrapper property of lxml.etree.Element.text """ - if six.PY2: - return utf8encode(lxml.etree.ElementBase.text.__get__(self)) return lxml.etree.ElementBase.text.__get__(self) @text.setter diff --git a/swift/common/middleware/s3api/s3api.py b/swift/common/middleware/s3api/s3api.py index 55c8732f6c..cb498de3c3 100644 --- a/swift/common/middleware/s3api/s3api.py +++ b/swift/common/middleware/s3api/s3api.py @@ -144,7 +144,7 @@ from cgi import parse_header import json from paste.deploy import loadwsgi -from six.moves.urllib.parse import parse_qs +from urllib.parse import parse_qs from swift.common.constraints import valid_api_version from swift.common.middleware.listing_formats import \ diff --git a/swift/common/middleware/s3api/s3request.py b/swift/common/middleware/s3api/s3request.py index 282c82c0a0..c0ec725d14 100644 --- a/swift/common/middleware/s3api/s3request.py +++ b/swift/common/middleware/s3api/s3request.py @@ -20,9 +20,8 @@ from hashlib import sha1, sha256 import hmac import re -import six # pylint: disable-msg=import-error -from six.moves.urllib.parse import quote, unquote, parse_qsl +from urllib.parse import quote, unquote, parse_qsl import string from swift.common.utils import split_path, json, close_if_possible, md5, \ @@ -421,7 +420,7 @@ def _headers_to_sign(self): else: # mostly-functional fallback headers_lower_dict = dict( (k.lower().strip(), ' '.join(_header_strip(v or '').split())) - for (k, v) in six.iteritems(self.headers)) + for (k, v) in self.headers.items()) if 'host' in headers_lower_dict and re.match( 'Boto/2.[0-9].[0-2]', @@ -636,9 +635,8 @@ def check_signature(self, secret): secret = utf8encode(secret) user_signature = self.signature valid_signature = base64.b64encode(hmac.new( - secret, self.string_to_sign, sha1).digest()).strip() - if not six.PY2: - valid_signature = valid_signature.decode('ascii') + secret, self.string_to_sign, sha1 + ).digest()).strip().decode('ascii') return streq_const_time(user_signature, valid_signature) @property @@ -1488,8 +1486,6 @@ def _get_response(self, app, method, container, obj, self.user_id = "%s:%s" % ( sw_resp.environ['HTTP_X_TENANT_NAME'], sw_resp.environ['HTTP_X_USER_NAME']) - if six.PY2 and not isinstance(self.user_id, bytes): - self.user_id = self.user_id.encode('utf8') else: # tempauth self.user_id = self.access_key @@ -1687,8 +1683,6 @@ def authenticate(self, app): # keystone self.user_id = "%s:%s" % (sw_resp.environ['HTTP_X_TENANT_NAME'], sw_resp.environ['HTTP_X_USER_NAME']) - if six.PY2 and not isinstance(self.user_id, bytes): - self.user_id = self.user_id.encode('utf8') else: # tempauth self.user_id = self.access_key diff --git a/swift/common/middleware/s3api/s3response.py b/swift/common/middleware/s3api/s3response.py index 9a06b523f1..299bf30cef 100644 --- a/swift/common/middleware/s3api/s3response.py +++ b/swift/common/middleware/s3api/s3response.py @@ -14,10 +14,7 @@ # limitations under the License. import re -try: - from collections.abc import MutableMapping -except ImportError: - from collections import MutableMapping # py2 +from collections.abc import MutableMapping from functools import partial from swift.common import header_key_dict diff --git a/swift/common/middleware/s3api/s3token.py b/swift/common/middleware/s3api/s3token.py index 23ebcc7086..0c3f15d891 100644 --- a/swift/common/middleware/s3api/s3token.py +++ b/swift/common/middleware/s3api/s3token.py @@ -61,8 +61,7 @@ from keystoneauth1 import session as keystone_session from keystoneauth1 import loading as keystone_loading import requests -import six -from six.moves import urllib +import urllib from swift.common.swob import Request, HTTPBadRequest, HTTPUnauthorized, \ HTTPException, str_to_wsgi @@ -217,9 +216,7 @@ def _deny_request(self, code): error_msg = ('\r\n' '%s
\r\n '
'%s
'
for line in lines:
- el = html_escape(line)
+ el = html.escape(line)
i = i + 1
if i == lineno:
fmt2 = '\
diff --git a/swift/common/middleware/xprofile.py b/swift/common/middleware/xprofile.py
index 84d812acf6..a7f4f3e16b 100644
--- a/swift/common/middleware/xprofile.py
+++ b/swift/common/middleware/xprofile.py
@@ -85,8 +85,7 @@
from eventlet import greenthread, GreenPool, patcher
import eventlet.green.profile as eprofile
-import six
-from six.moves import urllib
+import urllib
from swift.common.utils import get_logger, config_true_value
from swift.common.swob import Request
@@ -112,10 +111,7 @@
app_iter_ = self.app(environ, start_response)
"""
-if six.PY3:
- thread = patcher.original('_thread') # non-monkeypatched module needed
-else:
- thread = patcher.original('thread') # non-monkeypatched module needed
+thread = patcher.original('_thread') # non-monkeypatched module needed
# This monkey patch code fix the problem of eventlet profile tool
@@ -217,7 +213,7 @@ def __call__(self, environ, start_response):
query_dict,
self.renew_profile)
start_response('200 OK', headers)
- if isinstance(content, six.text_type):
+ if isinstance(content, str):
content = content.encode('utf-8')
return [content]
except MethodNotAllowed as mx:
diff --git a/swift/common/recon.py b/swift/common/recon.py
index 44c8fb8ef1..f1928e2f1c 100644
--- a/swift/common/recon.py
+++ b/swift/common/recon.py
@@ -13,8 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import six
-
RECON_RELINKER_FILE = 'relinker.recon'
RECON_OBJECT_FILE = 'object.recon'
RECON_CONTAINER_FILE = 'container.recon'
@@ -24,7 +22,7 @@
def server_type_to_recon_file(server_type):
- if not isinstance(server_type, six.string_types) or \
+ if not isinstance(server_type, str) or \
server_type.lower() not in ('account', 'container', 'object'):
raise ValueError('Invalid server_type')
return "%s.recon" % server_type.lower()
diff --git a/swift/common/registry.py b/swift/common/registry.py
index 2aa5376ae0..f1b147ce80 100644
--- a/swift/common/registry.py
+++ b/swift/common/registry.py
@@ -16,7 +16,6 @@
# Used by get_swift_info and register_swift_info to store information about
# the swift cluster.
from copy import deepcopy
-import six
_swift_info = {}
_swift_admin_info = {}
@@ -115,10 +114,7 @@ def register_sensitive_header(header):
"""
if not isinstance(header, str):
raise TypeError
- if six.PY2:
- header.decode('ascii')
- else:
- header.encode('ascii')
+ header.encode('ascii')
_sensitive_headers.add(header.lower())
@@ -147,8 +143,5 @@ def register_sensitive_param(query_param):
"""
if not isinstance(query_param, str):
raise TypeError
- if six.PY2:
- query_param.decode('ascii')
- else:
- query_param.encode('ascii')
+ query_param.encode('ascii')
_sensitive_params.add(query_param)
diff --git a/swift/common/request_helpers.py b/swift/common/request_helpers.py
index c014bd8df9..60a862aa6c 100644
--- a/swift/common/request_helpers.py
+++ b/swift/common/request_helpers.py
@@ -21,10 +21,8 @@
"""
import itertools
-import sys
import time
-import six
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.constraints import AUTO_CREATE_ACCOUNT_PREFIX, \
@@ -51,15 +49,6 @@
MISPLACED_OBJECTS_ACCOUNT = '.misplaced_objects'
-if six.PY2:
- import cgi
-
- def html_escape(s, quote=True):
- return cgi.escape(s, quote=quote)
-else:
- from html import escape as html_escape # noqa: F401
-
-
def get_param(req, name, default=None):
"""
Get a parameter from an HTTP request ensuring proper handling UTF-8
@@ -68,30 +57,20 @@ def get_param(req, name, default=None):
:param req: request object
:param name: parameter name
:param default: result to return if the parameter is not found
- :returns: HTTP request parameter value, as a native string
- (in py2, as UTF-8 encoded str, not unicode object)
+ :returns: HTTP request parameter value, as a native (not WSGI) string
:raises HTTPBadRequest: if param not valid UTF-8 byte sequence
"""
value = req.params.get(name, default)
- if six.PY2:
- if value and not isinstance(value, six.text_type):
- try:
- value.decode('utf8') # Ensure UTF8ness
- except UnicodeDecodeError:
- raise HTTPBadRequest(
- request=req, content_type='text/plain',
- body='"%s" parameter not valid UTF-8' % name)
- else:
- if value:
- # req.params is a dict of WSGI strings, so encoding will succeed
- value = value.encode('latin1')
- try:
- # Ensure UTF8ness since we're at it
- value = value.decode('utf8')
- except UnicodeDecodeError:
- raise HTTPBadRequest(
- request=req, content_type='text/plain',
- body='"%s" parameter not valid UTF-8' % name)
+ if value:
+ # req.params is a dict of WSGI strings, so encoding will succeed
+ value = value.encode('latin1')
+ try:
+ # Ensure UTF8ness since we're at it
+ value = value.decode('utf8')
+ except UnicodeDecodeError:
+ raise HTTPBadRequest(
+ request=req, content_type='text/plain',
+ body='"%s" parameter not valid UTF-8' % name)
return value
@@ -606,11 +585,10 @@ def _coalesce_requests(self):
pending_etag = seg_etag
pending_size = seg_size
- except ListingIterError:
- e_type, e_value, e_traceback = sys.exc_info()
+ except ListingIterError as e:
if pending_req:
yield pending_req, pending_etag, pending_size
- six.reraise(e_type, e_value, e_traceback)
+ raise e
if pending_req:
yield pending_req, pending_etag, pending_size
@@ -629,9 +607,7 @@ def _requests_to_bytes_iter(self):
seg_resp = seg_req.get_response(self.app)
if not is_success(seg_resp.status_int):
# Error body should be short
- body = seg_resp.body
- if not six.PY2:
- body = body.decode('utf8')
+ body = seg_resp.body.decode('utf8')
msg = 'While processing manifest %s, got %d (%s) ' \
'while retrieving %s' % (
self.name, seg_resp.status_int,
diff --git a/swift/common/ring/builder.py b/swift/common/ring/builder.py
index 91845070ef..77b00bcd97 100644
--- a/swift/common/ring/builder.py
+++ b/swift/common/ring/builder.py
@@ -22,14 +22,12 @@
import random
import uuid
-import six.moves.cPickle as pickle
+import pickle # nosec: B403
from copy import deepcopy
from contextlib import contextmanager
from array import array
from collections import defaultdict
-import six
-from six.moves import range
from time import time
from swift.common import exceptions
@@ -646,8 +644,7 @@ def _build_dispersion_graph(self, old_replica2part2dev=None):
dispersion_graph = {}
# go over all the devices holding each replica part by part
- for part_id, dev_ids in enumerate(
- six.moves.zip(*self._replica2part2dev)):
+ for part_id, dev_ids in enumerate(zip(*self._replica2part2dev)):
# count the number of replicas of this part for each tier of each
# device, some devices may have overlapping tiers!
replicas_at_tier = defaultdict(int)
@@ -1741,7 +1738,7 @@ def load(cls, builder_file, open=open, **kwargs):
else:
with fp:
try:
- builder = pickle.load(fp)
+ builder = pickle.load(fp) # nosec: B301
except Exception:
# raise error during unpickling as UnPicklingError
raise exceptions.UnPicklingError(
diff --git a/swift/common/ring/ring.py b/swift/common/ring/ring.py
index c3f726df61..7ef9d11446 100644
--- a/swift/common/ring/ring.py
+++ b/swift/common/ring/ring.py
@@ -16,7 +16,7 @@
import array
import contextlib
-import six.moves.cPickle as pickle
+import pickle # nosec: B403
import json
from collections import defaultdict
from gzip import GzipFile
@@ -29,9 +29,6 @@
import sys
import zlib
-import six
-from six.moves import range
-
from swift.common.exceptions import RingLoadError
from swift.common.utils import hash_path, validate_configuration, md5
from swift.common.ring.utils import tiers_for_dev
@@ -206,7 +203,7 @@ def load(cls, filename, metadata_only=False):
else:
# Assume old-style pickled ring
gz_file.seek(0)
- ring_data = pickle.load(gz_file)
+ ring_data = pickle.load(gz_file) # nosec: B301
if hasattr(ring_data, 'devs'):
# pickled RingData; make sure we've got region/replication info
@@ -244,12 +241,7 @@ def serialize_v1(self, file_obj):
file_obj.write(struct.pack('!I', json_len))
file_obj.write(json_text)
for part2dev_id in ring['replica2part2dev_id']:
- if six.PY2:
- # Can't just use tofile() because a GzipFile apparently
- # doesn't count as an 'open file'
- file_obj.write(part2dev_id.tostring())
- else:
- part2dev_id.tofile(file_obj)
+ part2dev_id.tofile(file_obj)
def save(self, filename, mtime=1300507380.0):
"""
diff --git a/swift/common/splice.py b/swift/common/splice.py
index a365a93bbd..9c2384e25f 100644
--- a/swift/common/splice.py
+++ b/swift/common/splice.py
@@ -18,8 +18,6 @@
'''
import os
-import operator
-import six
import ctypes
import ctypes.util
@@ -82,8 +80,10 @@ def __call__(self, fd_in, fd_out, len_, flags):
if not self.available:
raise EnvironmentError('tee not available')
- if not isinstance(flags, six.integer_types):
- c_flags = six.moves.reduce(operator.or_, flags, 0)
+ if not isinstance(flags, int):
+ c_flags = 0
+ for flag in flags:
+ c_flags |= flag
else:
c_flags = flags
@@ -174,8 +174,10 @@ def __call__(self, fd_in, off_in, fd_out, off_out, len_, flags):
if not self.available:
raise EnvironmentError('splice not available')
- if not isinstance(flags, six.integer_types):
- c_flags = six.moves.reduce(operator.or_, flags, 0)
+ if not isinstance(flags, int):
+ c_flags = 0
+ for flag in flags:
+ c_flags |= flag
else:
c_flags = flags
diff --git a/swift/common/statsd_client.py b/swift/common/statsd_client.py
index 825bede383..2576ec8700 100644
--- a/swift/common/statsd_client.py
+++ b/swift/common/statsd_client.py
@@ -21,7 +21,6 @@
from random import random
from eventlet.green import socket
-import six
def get_statsd_client(conf=None, tail_prefix='', logger=None):
@@ -164,8 +163,7 @@ def _send(self, m_name, m_value, m_type, sample_rate):
parts.append('@%s' % (sample_rate,))
else:
return
- if six.PY3:
- parts = [part.encode('utf-8') for part in parts]
+ parts = [part.encode('utf-8') for part in parts]
# Ideally, we'd cache a sending socket in self, but that
# results in a socket getting shared by multiple green threads.
with closing(self._open_socket()) as sock:
diff --git a/swift/common/storage_policy.py b/swift/common/storage_policy.py
index dcad56b9c9..a1bcfc4130 100644
--- a/swift/common/storage_policy.py
+++ b/swift/common/storage_policy.py
@@ -17,8 +17,7 @@
import string
import sys
import textwrap
-import six
-from six.moves.configparser import ConfigParser
+from configparser import ConfigParser
from swift.common.utils import (
config_true_value, quorum_size, whataremyips, list_from_csv,
config_positive_int_value, get_zero_indexed_base_string, load_pkg_resource)
@@ -80,8 +79,10 @@ def all_bind_ports_for_node(self):
# the first one we notice.
# Return the requested set of ports from our (now-freshened) cache
- return six.moves.reduce(set.union,
- self.portsets_by_ring_path.values(), set())
+ res = set()
+ for ports in self.portsets_by_ring_path.values():
+ res.update(ports)
+ return res
class PolicyError(ValueError):
@@ -975,12 +976,9 @@ def reload_storage_policies():
Reload POLICIES from ``swift.conf``.
"""
global _POLICIES
- if six.PY2:
- policy_conf = ConfigParser()
- else:
- # Python 3.2 disallows section or option duplicates by default
- # strict=False allows us to preserve the older behavior
- policy_conf = ConfigParser(strict=False)
+ # Python disallows section or option duplicates by default
+ # strict=False allows them, which Swift has always done
+ policy_conf = ConfigParser(strict=False)
policy_conf.read(utils.SWIFT_CONF_FILE)
try:
_POLICIES = parse_storage_policies(policy_conf)
diff --git a/swift/common/swob.py b/swift/common/swob.py
index 60ccb332be..43d35959c8 100644
--- a/swift/common/swob.py
+++ b/swift/common/swob.py
@@ -36,10 +36,7 @@
"""
from collections import defaultdict
-try:
- from collections.abc import MutableMapping
-except ImportError:
- from collections import MutableMapping # py2
+from collections.abc import MutableMapping
import time
from functools import partial
from datetime import datetime
@@ -49,9 +46,8 @@
import functools
from io import BytesIO
-import six
-from six import StringIO
-from six.moves import urllib
+from io import StringIO
+import urllib
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.utils import UTC, reiterate, split_path, Timestamp, pairs, \
@@ -157,7 +153,7 @@ def getter(self):
return None
def setter(self, value):
- if isinstance(value, (float,) + six.integer_types):
+ if isinstance(value, (float, int)):
self.headers[header] = time.strftime(
"%a, %d %b %Y %H:%M:%S GMT", time.gmtime(value))
elif isinstance(value, datetime):
@@ -251,9 +247,7 @@ def __getitem__(self, key):
def __setitem__(self, key, value):
if value is None:
self.environ.pop(header_to_environ_key(key), None)
- elif six.PY2 and isinstance(value, six.text_type):
- self.environ[header_to_environ_key(key)] = value.encode('utf-8')
- elif not six.PY2 and isinstance(value, six.binary_type):
+ elif isinstance(value, bytes):
self.environ[header_to_environ_key(key)] = value.decode('latin1')
else:
self.environ[header_to_environ_key(key)] = str(value)
@@ -279,70 +273,42 @@ def keys(self):
def wsgi_to_bytes(wsgi_str):
if wsgi_str is None:
return None
- if six.PY2:
- return wsgi_str
return wsgi_str.encode('latin1')
def wsgi_to_str(wsgi_str):
if wsgi_str is None:
return None
- if six.PY2:
- return wsgi_str
return wsgi_to_bytes(wsgi_str).decode('utf8', errors='surrogateescape')
def bytes_to_wsgi(byte_str):
- if six.PY2:
- return byte_str
return byte_str.decode('latin1')
def str_to_wsgi(native_str):
- if six.PY2:
- return native_str
return bytes_to_wsgi(native_str.encode('utf8', errors='surrogateescape'))
def wsgi_quote(wsgi_str, safe='/'):
- if six.PY2:
- if not isinstance(wsgi_str, bytes):
- raise TypeError('Expected a WSGI string; got %r' % wsgi_str)
- return urllib.parse.quote(wsgi_str, safe=safe)
-
if not isinstance(wsgi_str, str) or any(ord(x) > 255 for x in wsgi_str):
raise TypeError('Expected a WSGI string; got %r' % wsgi_str)
return urllib.parse.quote(wsgi_str, safe=safe, encoding='latin-1')
def wsgi_unquote(wsgi_str):
- if six.PY2:
- if not isinstance(wsgi_str, bytes):
- raise TypeError('Expected a WSGI string; got %r' % wsgi_str)
- return urllib.parse.unquote(wsgi_str)
-
if not isinstance(wsgi_str, str) or any(ord(x) > 255 for x in wsgi_str):
raise TypeError('Expected a WSGI string; got %r' % wsgi_str)
return urllib.parse.unquote(wsgi_str, encoding='latin-1')
def wsgi_quote_plus(wsgi_str):
- if six.PY2:
- if not isinstance(wsgi_str, bytes):
- raise TypeError('Expected a WSGI string; got %r' % wsgi_str)
- return urllib.parse.quote_plus(wsgi_str)
-
if not isinstance(wsgi_str, str) or any(ord(x) > 255 for x in wsgi_str):
raise TypeError('Expected a WSGI string; got %r' % wsgi_str)
return urllib.parse.quote_plus(wsgi_str, encoding='latin-1')
def wsgi_unquote_plus(wsgi_str):
- if six.PY2:
- if not isinstance(wsgi_str, bytes):
- raise TypeError('Expected a WSGI string; got %r' % wsgi_str)
- return urllib.parse.unquote_plus(wsgi_str)
-
if not isinstance(wsgi_str, str) or any(ord(x) > 255 for x in wsgi_str):
raise TypeError('Expected a WSGI string; got %r' % wsgi_str)
return urllib.parse.unquote_plus(wsgi_str, encoding='latin-1')
@@ -360,7 +326,7 @@ def getter(self):
return '%s %s' % (self.status_int, self.title)
def setter(self, value):
- if isinstance(value, six.integer_types):
+ if isinstance(value, int):
self.status_int = value
self.explanation = self.title = RESPONSE_REASONS[value][0]
else:
@@ -388,9 +354,9 @@ def getter(self):
return self._body
def setter(self, value):
- if isinstance(value, six.text_type):
+ if isinstance(value, str):
raise TypeError('WSGI responses must be bytes')
- if isinstance(value, six.binary_type):
+ if isinstance(value, bytes):
self.content_length = len(value)
close_if_possible(self._app_iter)
self._app_iter = None
@@ -805,19 +771,13 @@ def getter(self):
return self.environ.get(environ_field, None)
def setter(self, value):
- if six.PY2:
- if isinstance(value, six.text_type):
- self.environ[environ_field] = value.encode('utf-8')
- else:
- self.environ[environ_field] = value
- else:
- if is_wsgi_string_field:
- # Check that input is valid before setting
- if isinstance(value, str):
- value.encode('latin1').decode('utf-8')
- if isinstance(value, bytes):
- value = value.decode('latin1')
- self.environ[environ_field] = value
+ if is_wsgi_string_field:
+ # Check that input is valid before setting
+ if isinstance(value, str):
+ value.encode('latin1').decode('utf-8')
+ if isinstance(value, bytes):
+ value = value.decode('latin1')
+ self.environ[environ_field] = value
return property(getter, setter, doc=("Get and set the %s property "
"in the WSGI environment") % environ_field)
@@ -835,7 +795,7 @@ def getter(self):
return body
def setter(self, value):
- if not isinstance(value, six.binary_type):
+ if not isinstance(value, bytes):
value = value.encode('utf8')
self.environ['wsgi.input'] = WsgiBytesIO(value)
self.environ['CONTENT_LENGTH'] = str(len(value))
@@ -932,15 +892,11 @@ def blank(cls, path, environ=None, headers=None, body=None, **kwargs):
"""
headers = headers or {}
environ = environ or {}
- if six.PY2:
- if isinstance(path, six.text_type):
- path = path.encode('utf-8')
+ if isinstance(path, bytes):
+ path = path.decode('latin1')
else:
- if isinstance(path, six.binary_type):
- path = path.decode('latin1')
- else:
- # Check that the input is valid
- path.encode('latin1')
+ # Check that the input is valid
+ path.encode('latin1')
parsed_path = urllib.parse.urlparse(path)
server_name = 'localhost'
@@ -970,7 +926,7 @@ def blank(cls, path, environ=None, headers=None, body=None, **kwargs):
}
env.update(environ)
if body is not None:
- if not isinstance(body, six.binary_type):
+ if not isinstance(body, bytes):
body = body.encode('utf8')
env['wsgi.input'] = WsgiBytesIO(body)
env['CONTENT_LENGTH'] = str(len(body))
@@ -996,13 +952,9 @@ def params(self):
"Provides QUERY_STRING parameters as a dictionary"
if self._params_cache is None:
if 'QUERY_STRING' in self.environ:
- if six.PY2:
- self._params_cache = dict(urllib.parse.parse_qsl(
- self.environ['QUERY_STRING'], True))
- else:
- self._params_cache = dict(urllib.parse.parse_qsl(
- self.environ['QUERY_STRING'],
- keep_blank_values=True, encoding='latin-1'))
+ self._params_cache = dict(urllib.parse.parse_qsl(
+ self.environ['QUERY_STRING'],
+ keep_blank_values=True, encoding='latin-1'))
else:
self._params_cache = {}
return self._params_cache
@@ -1011,11 +963,8 @@ def params(self):
@params.setter
def params(self, param_pairs):
self._params_cache = None
- if six.PY2:
- self.query_string = urllib.parse.urlencode(param_pairs)
- else:
- self.query_string = urllib.parse.urlencode(param_pairs,
- encoding='latin-1')
+ self.query_string = urllib.parse.urlencode(param_pairs,
+ encoding='latin-1')
def ensure_x_timestamp(self):
"""
@@ -1265,7 +1214,7 @@ def __init__(self, body=None, status=200, headers=None, app_iter=None,
self.request = request
self._app_iter = None
# Allow error messages to come as natural strings on py3.
- if isinstance(body, six.text_type):
+ if isinstance(body, str):
body = body.encode('utf8')
self.body = body
self.app_iter = app_iter
diff --git a/swift/common/utils/__init__.py b/swift/common/utils/__init__.py
index c5fdd6fd8b..67cd6dbd7a 100644
--- a/swift/common/utils/__init__.py
+++ b/swift/common/utils/__init__.py
@@ -64,15 +64,12 @@
from eventlet.green import socket
import eventlet.hubs
import eventlet.queue
-import six
-from six.moves import cPickle as pickle
-from six.moves.configparser import (ConfigParser, NoSectionError,
- NoOptionError)
-from six.moves import range
-from six.moves.urllib.parse import unquote
-from six.moves.urllib.parse import urlparse
-from six.moves import UserList
+import pickle # nosec: B403
+from configparser import (ConfigParser, NoSectionError,
+ NoOptionError)
+from urllib.parse import unquote, urlparse
+from collections import UserList
import swift.common.exceptions
from swift.common.http import is_server_error
@@ -373,26 +370,18 @@ def validate_hash_conf():
if not HASH_PATH_SUFFIX and not HASH_PATH_PREFIX:
hash_conf = ConfigParser()
- if six.PY3:
- # Use Latin1 to accept arbitrary bytes in the hash prefix/suffix
- with open(SWIFT_CONF_FILE, encoding='latin1') as swift_conf_file:
- hash_conf.read_file(swift_conf_file)
- else:
- with open(SWIFT_CONF_FILE) as swift_conf_file:
- hash_conf.readfp(swift_conf_file)
+ # Use Latin1 to accept arbitrary bytes in the hash prefix/suffix
+ with open(SWIFT_CONF_FILE, encoding='latin1') as swift_conf_file:
+ hash_conf.read_file(swift_conf_file)
try:
- HASH_PATH_SUFFIX = hash_conf.get('swift-hash',
- 'swift_hash_path_suffix')
- if six.PY3:
- HASH_PATH_SUFFIX = HASH_PATH_SUFFIX.encode('latin1')
+ HASH_PATH_SUFFIX = hash_conf.get(
+ 'swift-hash', 'swift_hash_path_suffix').encode('latin1')
except (NoSectionError, NoOptionError):
pass
try:
- HASH_PATH_PREFIX = hash_conf.get('swift-hash',
- 'swift_hash_path_prefix')
- if six.PY3:
- HASH_PATH_PREFIX = HASH_PATH_PREFIX.encode('latin1')
+ HASH_PATH_PREFIX = hash_conf.get(
+ 'swift-hash', 'swift_hash_path_prefix').encode('latin1')
except (NoSectionError, NoOptionError):
pass
@@ -498,7 +487,7 @@ def __init__(self, iterable):
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
"""
next(x) -> the next value, or raise StopIteration
"""
@@ -510,7 +499,6 @@ def next(self):
return rv
else:
return next(self.iterator)
- __next__ = next
def read(self, size=-1):
"""
@@ -949,7 +937,7 @@ def __init__(self, iterable, elements_per_second, limit_after=0,
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
next_value = next(self.iterator)
if self.ratelimit_if(next_value):
@@ -958,7 +946,6 @@ def next(self):
else:
self.rate_limiter.wait()
return next_value
- __next__ = next
class GreenthreadSafeIterator(object):
@@ -980,10 +967,9 @@ def __init__(self, unsafe_iterable):
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
with self.semaphore:
return next(self.unsafe_iter)
- __next__ = next
def timing_stats(**dec_kwargs):
@@ -1238,13 +1224,13 @@ def hash_path(account, container=None, object=None, raw_digest=False):
"""
if object and not container:
raise ValueError('container is required if object is provided')
- paths = [account if isinstance(account, six.binary_type)
+ paths = [account if isinstance(account, bytes)
else account.encode('utf8')]
if container:
- paths.append(container if isinstance(container, six.binary_type)
+ paths.append(container if isinstance(container, bytes)
else container.encode('utf8'))
if object:
- paths.append(object if isinstance(object, six.binary_type)
+ paths.append(object if isinstance(object, bytes)
else object.encode('utf8'))
if raw_digest:
return md5(HASH_PATH_PREFIX + b'/' + b'/'.join(paths)
@@ -2006,7 +1992,7 @@ def _wait(self, timeout, first_n=None):
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
while True:
try:
rv = self._responses.get_nowait()
@@ -2018,7 +2004,6 @@ def next(self):
if rv is DEAD:
continue
return rv
- __next__ = next
class StreamingPile(GreenAsyncPile):
@@ -2460,8 +2445,6 @@ def __next__(self):
self.close()
raise
- next = __next__ # py2
-
def close(self):
if not self.closed:
for wrapped in self.closeables:
@@ -3085,18 +3068,14 @@ def parse_mime_headers(doc_file):
while True:
line = doc_file.readline()
done = line in (b'\r\n', b'\n', b'')
- if six.PY3:
- try:
- line = line.decode('utf-8')
- except UnicodeDecodeError:
- line = line.decode('latin1')
+ try:
+ line = line.decode('utf-8')
+ except UnicodeDecodeError:
+ line = line.decode('latin1')
headers.append(line)
if done:
break
- if six.PY3:
- header_string = ''.join(headers)
- else:
- header_string = b''.join(headers)
+ header_string = ''.join(headers)
headers = email.parser.Parser().parsestr(header_string)
return HeaderKeyDict(headers)
@@ -3111,7 +3090,7 @@ def mime_to_document_iters(input_file, boundary, read_chunk_size=4096):
(e.g. "divider", not "--divider")
:param read_chunk_size: size of strings read via input_file.read()
"""
- if six.PY3 and isinstance(boundary, str):
+ if isinstance(boundary, str):
# Since the boundary is in client-supplied headers, it can contain
# garbage that trips us and we don't like client-induced 500.
boundary = boundary.encode('latin-1', errors='replace')
@@ -3351,8 +3330,6 @@ def __repr__(self):
def __bool__(self):
return False
- __nonzero__ = __bool__
-
@functools.total_ordering
class Namespace(object):
@@ -3451,9 +3428,7 @@ def __contains__(self, item):
@classmethod
def _encode(cls, value):
- if six.PY2 and isinstance(value, six.text_type):
- return value.encode('utf-8')
- if six.PY3 and isinstance(value, six.binary_type):
+ if isinstance(value, bytes):
# This should never fail -- the value should always be coming from
# valid swift paths, which means UTF-8
return value.decode('utf-8')
@@ -3462,8 +3437,8 @@ def _encode(cls, value):
def _encode_bound(self, bound):
if isinstance(bound, NamespaceOuterBound):
return bound
- if not (isinstance(bound, six.text_type) or
- isinstance(bound, six.binary_type)):
+ if not (isinstance(bound, str) or
+ isinstance(bound, bytes)):
raise TypeError('must be a string type')
return self._encode(bound)
@@ -4364,7 +4339,8 @@ class ShardRangeList(UserList):
"""
def __getitem__(self, index):
- # workaround for py3 - not needed for py2.7,py3.8
+ # workaround for py36,py37 - not needed for py3.8+
+ # see https://github.com/python/cpython/commit/b1c3167c
result = self.data[index]
return ShardRangeList(result) if type(result) is list else result
@@ -4593,7 +4569,7 @@ def strict_b64decode(value, allow_line_breaks=False):
value = value.decode('ascii')
except UnicodeDecodeError:
raise ValueError
- if not isinstance(value, six.text_type):
+ if not isinstance(value, str):
raise ValueError
# b64decode will silently discard bad characters, but we want to
# treat them as an error
@@ -4604,10 +4580,7 @@ def strict_b64decode(value, allow_line_breaks=False):
strip_chars += '\r\n'
if any(c not in valid_chars for c in value.strip(strip_chars)):
raise ValueError
- try:
- return base64.b64decode(value)
- except (TypeError, binascii.Error): # (py2 error, py3 error)
- raise ValueError
+ return base64.b64decode(value)
def cap_length(value, max_length):
diff --git a/swift/common/utils/base.py b/swift/common/utils/base.py
index 7e94eab3e7..159dac0c01 100644
--- a/swift/common/utils/base.py
+++ b/swift/common/utils/base.py
@@ -23,8 +23,7 @@
import codecs
import hashlib
-import six
-from six.moves.urllib.parse import quote as _quote
+from urllib.parse import quote as _quote
try:
@@ -50,10 +49,9 @@ def md5(string=b'', usedforsecurity=True):
utf8_decoder = codecs.getdecoder('utf-8')
utf8_encoder = codecs.getencoder('utf-8')
-if not six.PY2:
- # Apparently under py3 we need to go to utf-16 to collapse surrogates?
- utf16_decoder = codecs.getdecoder('utf-16')
- utf16_encoder = codecs.getencoder('utf-16')
+# Apparently under py3 we need to go to utf-16 to collapse surrogates?
+utf16_decoder = codecs.getdecoder('utf-16')
+utf16_encoder = codecs.getencoder('utf-16')
def get_valid_utf8_str(str_or_unicode):
@@ -62,20 +60,15 @@ def get_valid_utf8_str(str_or_unicode):
:param str_or_unicode: a string or an unicode which can be invalid utf-8
"""
- if six.PY2:
- if isinstance(str_or_unicode, six.text_type):
- (str_or_unicode, _len) = utf8_encoder(str_or_unicode, 'replace')
- (valid_unicode_str, _len) = utf8_decoder(str_or_unicode, 'replace')
- else:
- if isinstance(str_or_unicode, six.binary_type):
- try:
- (str_or_unicode, _len) = utf8_decoder(str_or_unicode,
- 'surrogatepass')
- except UnicodeDecodeError:
- (str_or_unicode, _len) = utf8_decoder(str_or_unicode,
- 'replace')
- (str_or_unicode, _len) = utf16_encoder(str_or_unicode, 'surrogatepass')
- (valid_unicode_str, _len) = utf16_decoder(str_or_unicode, 'replace')
+ if isinstance(str_or_unicode, bytes):
+ try:
+ (str_or_unicode, _len) = utf8_decoder(str_or_unicode,
+ 'surrogatepass')
+ except UnicodeDecodeError:
+ (str_or_unicode, _len) = utf8_decoder(str_or_unicode,
+ 'replace')
+ (str_or_unicode, _len) = utf16_encoder(str_or_unicode, 'surrogatepass')
+ (valid_unicode_str, _len) = utf16_decoder(str_or_unicode, 'replace')
return valid_unicode_str.encode('utf-8')
@@ -84,7 +77,7 @@ def quote(value, safe='/'):
Patched version of urllib.quote that encodes utf-8 strings before quoting
"""
quoted = _quote(get_valid_utf8_str(value), safe)
- if isinstance(value, six.binary_type):
+ if isinstance(value, bytes):
quoted = quoted.encode('utf-8')
return quoted
diff --git a/swift/common/utils/config.py b/swift/common/utils/config.py
index 5f4fe8a817..f56d89f0fd 100644
--- a/swift/common/utils/config.py
+++ b/swift/common/utils/config.py
@@ -13,12 +13,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import six
import os
import operator
import re
-from six.moves import configparser
-from six.moves.configparser import (ConfigParser, RawConfigParser)
+import configparser
+from configparser import ConfigParser, RawConfigParser
# Used when reading config values
TRUE_VALUES = {'true', '1', 'yes', 'on', 't', 'y'}
@@ -30,7 +29,7 @@ def config_true_value(value):
Returns False otherwise.
"""
return value is True or \
- (isinstance(value, six.string_types) and value.lower() in TRUE_VALUES)
+ (isinstance(value, str) and value.lower() in TRUE_VALUES)
def _non_negative_number(value, expected_type_f=float,
@@ -105,7 +104,7 @@ def config_auto_int_value(value, default):
Returns value as an int or raises ValueError otherwise.
"""
if value is None or \
- (isinstance(value, six.string_types) and value.lower() == 'auto'):
+ (isinstance(value, str) and value.lower() == 'auto'):
return default
try:
value = int(value)
@@ -338,15 +337,12 @@ def read_conf_dir(parser, conf_dir):
return parser.read(sorted(conf_files))
-if six.PY2:
- NicerInterpolation = None # just don't cause ImportErrors over in wsgi.py
-else:
- class NicerInterpolation(configparser.BasicInterpolation):
- def before_get(self, parser, section, option, value, defaults):
- if '%(' not in value:
- return value
- return super(NicerInterpolation, self).before_get(
- parser, section, option, value, defaults)
+class NicerInterpolation(configparser.BasicInterpolation):
+ def before_get(self, parser, section, option, value, defaults):
+ if '%(' not in value:
+ return value
+ return super(NicerInterpolation, self).before_get(
+ parser, section, option, value, defaults)
def readconf(conf_path, section_name=None, log_name=None, defaults=None,
@@ -370,27 +366,21 @@ def readconf(conf_path, section_name=None, log_name=None, defaults=None,
if raw:
c = RawConfigParser(defaults)
else:
- if six.PY2:
- c = ConfigParser(defaults)
- else:
- # In general, we haven't really thought much about interpolation
- # in configs. Python's default ConfigParser has always supported
- # it, though, so *we* got it "for free". Unfortunatley, since we
- # "supported" interpolation, we have to assume there are
- # deployments in the wild that use it, and try not to break them.
- # So, do what we can to mimic the py2 behavior of passing through
- # values like "1%" (which we want to support for
- # fallocate_reserve).
- c = ConfigParser(defaults, interpolation=NicerInterpolation())
+ # In general, we haven't really thought much about interpolation
+ # in configs. Python's default ConfigParser has always supported
+ # it, though, so *we* got it "for free". Unfortunatley, since we
+ # "supported" interpolation, we have to assume there are
+ # deployments in the wild that use it, and try not to break them.
+ # So, do what we can to mimic the py2 behavior of passing through
+ # values like "1%" (which we want to support for
+ # fallocate_reserve).
+ c = ConfigParser(defaults, interpolation=NicerInterpolation())
c.optionxform = str # Don't lower-case keys
if hasattr(conf_path, 'readline'):
if hasattr(conf_path, 'seek'):
conf_path.seek(0)
- if six.PY2:
- c.readfp(conf_path)
- else:
- c.read_file(conf_path)
+ c.read_file(conf_path)
else:
if os.path.isdir(conf_path):
# read all configs in directory
diff --git a/swift/common/utils/logs.py b/swift/common/utils/logs.py
index e35dbce7aa..b9833635f9 100644
--- a/swift/common/utils/logs.py
+++ b/swift/common/utils/logs.py
@@ -27,7 +27,6 @@
import time
import fcntl
import eventlet
-import six
import datetime
from swift.common.utils.base import md5, quote, split_path
@@ -41,11 +40,8 @@
# we do the same here
import swift.common.exceptions
-if six.PY2:
- from eventlet.green import httplib as green_http_client
-else:
- from eventlet.green.http import client as green_http_client
-from six.moves import http_client
+from eventlet.green.http import client as green_http_client
+import http.client
from eventlet.green import threading
@@ -350,7 +346,7 @@ def exception(self, msg, *args, **kwargs):
_junk, exc, _junk = sys.exc_info()
call = self.error
emsg = ''
- if isinstance(exc, (http_client.BadStatusLine,
+ if isinstance(exc, (http.client.BadStatusLine,
green_http_client.BadStatusLine)):
# Use error(); not really exceptional
emsg = repr(exc)
@@ -503,9 +499,8 @@ def flush(self):
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
raise IOError(errno.EBADF, 'Bad file descriptor')
- __next__ = next
def read(self, size=-1):
raise IOError(errno.EBADF, 'Bad file descriptor')
@@ -744,8 +739,7 @@ class StrAnonymizer(str):
def __new__(cls, data, method, salt):
method = method.lower()
- if method not in (hashlib.algorithms if six.PY2 else
- hashlib.algorithms_guaranteed):
+ if method not in hashlib.algorithms_guaranteed:
raise ValueError('Unsupported hashing method: %r' % method)
s = str.__new__(cls, data or '')
s.method = method
@@ -762,8 +756,8 @@ def anonymized(self):
else:
h = getattr(hashlib, self.method)()
if self.salt:
- h.update(six.b(self.salt))
- h.update(six.b(self))
+ h.update(self.salt.encode('latin1'))
+ h.update(self.encode('latin1'))
return '{%s%s}%s' % ('S' if self.salt else '', self.method.upper(),
h.hexdigest())
@@ -880,7 +874,7 @@ def get_policy_index(req_headers, res_headers):
"""
header = 'X-Backend-Storage-Policy-Index'
policy_index = res_headers.get(header, req_headers.get(header))
- if isinstance(policy_index, six.binary_type) and not six.PY2:
+ if isinstance(policy_index, bytes):
policy_index = policy_index.decode('ascii')
return str(policy_index) if policy_index is not None else None
diff --git a/swift/common/utils/timestamp.py b/swift/common/utils/timestamp.py
index 374763ce93..660ae26f19 100644
--- a/swift/common/utils/timestamp.py
+++ b/swift/common/utils/timestamp.py
@@ -21,8 +21,6 @@
import sys
import time
-import six
-
NORMAL_FORMAT = "%016.05f"
INTERNAL_FORMAT = NORMAL_FORMAT + '_%016x'
@@ -90,7 +88,7 @@ def __init__(self, timestamp, offset=0, delta=0, check_bounds=True):
"""
if isinstance(timestamp, bytes):
timestamp = timestamp.decode('ascii')
- if isinstance(timestamp, six.string_types):
+ if isinstance(timestamp, str):
base, base_offset = timestamp.partition('_')[::2]
self.timestamp = float(base)
if '_' in base_offset:
@@ -140,11 +138,8 @@ def __float__(self):
def __int__(self):
return int(self.timestamp)
- def __nonzero__(self):
- return bool(self.timestamp or self.offset)
-
def __bool__(self):
- return self.__nonzero__()
+ return bool(self.timestamp or self.offset)
@property
def normal(self):
@@ -176,24 +171,21 @@ def isoformat(self):
:return: an isoformat string
"""
t = float(self.normal)
- if six.PY3:
- # On Python 3, round manually using ROUND_HALF_EVEN rounding
- # method, to use the same rounding method than Python 2. Python 3
- # used a different rounding method, but Python 3.4.4 and 3.5.1 use
- # again ROUND_HALF_EVEN as Python 2.
- # See https://bugs.python.org/issue23517
- frac, t = math.modf(t)
- us = round(frac * 1e6)
- if us >= 1000000:
- t += 1
- us -= 1000000
- elif us < 0:
- t -= 1
- us += 1000000
- dt = datetime.datetime.fromtimestamp(t, UTC)
- dt = dt.replace(microsecond=us)
- else:
- dt = datetime.datetime.fromtimestamp(t, UTC)
+ # On Python 3, round manually using ROUND_HALF_EVEN rounding
+ # method, to use the same rounding method than Python 2. Python 3
+ # used a different rounding method, but Python 3.4.4 and 3.5.1 use
+ # again ROUND_HALF_EVEN as Python 2.
+ # See https://bugs.python.org/issue23517
+ frac, t = math.modf(t)
+ us = round(frac * 1e6)
+ if us >= 1000000:
+ t += 1
+ us -= 1000000
+ elif us < 0:
+ t -= 1
+ us += 1000000
+ dt = datetime.datetime.fromtimestamp(t, UTC)
+ dt = dt.replace(microsecond=us)
isoformat = dt.isoformat()
# need to drop tzinfo
@@ -316,7 +308,7 @@ def decode_timestamps(encoded, explicit=False):
# TODO: some tests, e.g. in test_replicator, put float timestamps values
# into container db's, hence this defensive check, but in real world
# this may never happen.
- if not isinstance(encoded, six.string_types):
+ if not isinstance(encoded, str):
ts = Timestamp(encoded)
return ts, ts, ts
diff --git a/swift/common/wsgi.py b/swift/common/wsgi.py
index fa5367c291..34abf26178 100644
--- a/swift/common/wsgi.py
+++ b/swift/common/wsgi.py
@@ -18,7 +18,6 @@
from __future__ import print_function
import errno
-import fcntl
import os
import signal
import sys
@@ -31,10 +30,7 @@
from eventlet import greenio, GreenPool, sleep, wsgi, listen, Timeout
from paste.deploy import loadwsgi
from eventlet.green import socket, ssl, os as green_os
-from io import BytesIO
-
-import six
-from six import StringIO
+from io import BytesIO, StringIO
from swift.common import utils, constraints
from swift.common.http_protocol import SwiftHttpProtocol, \
@@ -67,8 +63,7 @@ class NamedConfigLoader(loadwsgi.ConfigLoader):
"""
def get_context(self, object_type, name=None, global_conf=None):
- if not six.PY2:
- self.parser._interpolation = NicerInterpolation()
+ self.parser._interpolation = NicerInterpolation()
context = super(NamedConfigLoader, self).get_context(
object_type, name=name, global_conf=global_conf)
context.name = name
@@ -128,10 +123,7 @@ def __init__(self, config_string):
self.parser.optionxform = str # Don't lower-case keys
# Defaults don't need interpolation (crazy PasteDeploy...)
self.parser.defaults = lambda: dict(self.parser._defaults, **defaults)
- if six.PY2:
- self.parser.readfp(self.contents)
- else:
- self.parser.read_file(self.contents)
+ self.parser.read_file(self.contents)
def readline(self, *args, **kwargs):
return self.contents.readline(*args, **kwargs)
@@ -198,10 +190,7 @@ def get_socket(conf):
sock = listen(bind_addr, backlog=int(conf.get('backlog', 4096)),
family=address_family)
if 'cert_file' in conf:
- if six.PY2:
- context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
- else:
- context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
+ context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.verify_mode = ssl.CERT_NONE
context.load_cert_chain(conf['cert_file'], conf['key_file'])
warn_ssl = True
@@ -513,13 +502,10 @@ def set_close_on_exec_on_listen_sockets(self):
"""
for sock in self.iter_sockets():
- if six.PY2:
- fcntl.fcntl(sock.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC)
- else:
- # Python 3.4 and later default to sockets having close-on-exec
- # set (what PEP 0446 calls "non-inheritable"). This new method
- # on socket objects is provided to toggle it.
- sock.set_inheritable(False)
+ # Python 3.4 and later default to sockets having close-on-exec
+ # set (what PEP 0446 calls "non-inheritable"). This new method
+ # on socket objects is provided to toggle it.
+ sock.set_inheritable(False)
def signal_ready(self):
"""
diff --git a/swift/container/backend.py b/swift/container/backend.py
index 8b3533c2df..da0632fb24 100644
--- a/swift/container/backend.py
+++ b/swift/container/backend.py
@@ -20,9 +20,7 @@
import os
from uuid import uuid4
-import six
-from six.moves import range
-from six.moves.urllib.parse import unquote
+from urllib.parse import unquote
import sqlite3
from eventlet import tpool
@@ -33,7 +31,7 @@
ShardRange, renamer, MD5_OF_EMPTY_STRING, mkdirs, get_db_files, \
parse_db_filename, make_db_file_path, split_path, RESERVED_BYTE, \
ShardRangeList, Namespace
-from swift.common.db import DatabaseBroker, utf8encode, BROKER_TIMEOUT, \
+from swift.common.db import DatabaseBroker, BROKER_TIMEOUT, \
zero_like, DatabaseAlreadyExists, SQLITE_ARG_LIMIT
DATADIR = 'containers'
@@ -1138,9 +1136,6 @@ def list_objects_iter(self, limit, marker, end_marker, prefix, delimiter,
if transform_func is None:
transform_func = self._transform_record
delim_force_gte = False
- if six.PY2:
- (marker, end_marker, prefix, delimiter, path) = utf8encode(
- marker, end_marker, prefix, delimiter, path)
self._commit_puts_stale_ok()
if reverse:
# Reverse the markers if we are reversing the listing.
@@ -1335,9 +1330,7 @@ def merge_items(self, item_list, source=None):
:param source: if defined, update incoming_sync with the source
"""
for item in item_list:
- if six.PY2 and isinstance(item['name'], six.text_type):
- item['name'] = item['name'].encode('utf-8')
- elif not six.PY2 and isinstance(item['name'], six.binary_type):
+ if isinstance(item['name'], bytes):
item['name'] = item['name'].decode('utf-8')
def _really_really_merge_items(conn):
@@ -1433,9 +1426,7 @@ def merge_shard_ranges(self, shard_ranges):
if isinstance(item, ShardRange):
item = dict(item)
for col in ('name', 'lower', 'upper'):
- if six.PY2 and isinstance(item[col], six.text_type):
- item[col] = item[col].encode('utf-8')
- elif not six.PY2 and isinstance(item[col], six.binary_type):
+ if isinstance(item[col], bytes):
item[col] = item[col].decode('utf-8')
item_list.append(item)
diff --git a/swift/container/reconciler.py b/swift/container/reconciler.py
index ee030ee409..75a25d9e74 100644
--- a/swift/container/reconciler.py
+++ b/swift/container/reconciler.py
@@ -19,7 +19,6 @@
import logging
from eventlet import GreenPile, GreenPool, Timeout
-import six
from swift.common import constraints
from swift.common.daemon import Daemon, run_daemon
@@ -272,11 +271,7 @@ def parse_raw_obj(obj_info):
:returns: a queue entry dict with the keys: q_policy_index, account,
container, obj, q_op, q_ts, q_record, and path
"""
- if six.PY2:
- raw_obj_name = obj_info['name'].encode('utf-8')
- else:
- raw_obj_name = obj_info['name']
-
+ raw_obj_name = obj_info['name']
policy_index, obj_name = raw_obj_name.split(':', 1)
q_policy_index = int(policy_index)
account, container, obj = split_path(obj_name, 3, 3, rest_with_last=True)
@@ -758,9 +753,6 @@ def _iter_containers(self):
# reversed order since we expect older containers to be empty
for c in reversed(one_page):
container = c['name']
- if six.PY2:
- # encoding here is defensive
- container = container.encode('utf8')
if container == current_container:
continue # we've already hit this one this pass
yield container
diff --git a/swift/container/server.py b/swift/container/server.py
index e8005e1fd1..2c1ed749c2 100644
--- a/swift/container/server.py
+++ b/swift/container/server.py
@@ -21,8 +21,7 @@
from eventlet import Timeout
-import six
-from six.moves.urllib.parse import quote
+from urllib.parse import quote
import swift.common.db
from swift.container.sync_store import ContainerSyncStore
@@ -237,10 +236,7 @@ def account_update(self, req, account, container, broker):
return HTTPBadRequest(req=req)
if account_partition:
- # zip is lazy on py3, but we need a list, so force evaluation.
- # On py2 it's an extra list copy, but the list is so small
- # (one element per replica in account ring, usually 3) that it
- # doesn't matter.
+ # zip is lazy, but we need a list, so force evaluation.
updates = list(zip(account_hosts, account_devices))
else:
updates = []
@@ -644,11 +640,10 @@ def update_object_record(self, record):
"""
# record is object info
(name, created, size, content_type, etag) = record[:5]
- name_ = name.decode('utf8') if six.PY2 else name
if content_type is None:
- return {'subdir': name_}
+ return {'subdir': name}
response = {
- 'bytes': size, 'hash': etag, 'name': name_,
+ 'bytes': size, 'hash': etag, 'name': name,
'content_type': content_type}
override_bytes_from_content_type(response, logger=self.logger)
response['last_modified'] = Timestamp(created).isoformat
diff --git a/swift/container/sharder.py b/swift/container/sharder.py
index 4ee6b914ea..f08673c3e1 100644
--- a/swift/container/sharder.py
+++ b/swift/container/sharder.py
@@ -24,8 +24,7 @@
from random import random
import os
-import six
-from six.moves.urllib.parse import quote
+from urllib.parse import quote
from eventlet import Timeout
from contextlib import contextmanager
@@ -657,18 +656,13 @@ def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, ', '.join(
'%s=%r' % prop for prop in self))
- def _encode(cls, value):
- if value is not None and six.PY2 and isinstance(value, six.text_type):
- return value.encode('utf-8')
- return value
-
@property
def cursor(self):
return self._cursor
@cursor.setter
def cursor(self, value):
- self._cursor = self._encode(value)
+ self._cursor = value
@property
def marker(self):
diff --git a/swift/container/sync.py b/swift/container/sync.py
index 124d7ba4e3..28bda61240 100644
--- a/swift/container/sync.py
+++ b/swift/container/sync.py
@@ -22,7 +22,7 @@
from struct import unpack_from
from eventlet import sleep, Timeout
-from six.moves.urllib.parse import urlparse
+from urllib.parse import urlparse
import swift.common.db
from swift.common.db import DatabaseConnectionError
diff --git a/swift/obj/diskfile.py b/swift/obj/diskfile.py
index 723212a1d8..b581f43fae 100644
--- a/swift/obj/diskfile.py
+++ b/swift/obj/diskfile.py
@@ -30,7 +30,7 @@
are also not considered part of the backend API.
"""
-import six.moves.cPickle as pickle
+import pickle # nosec: B403
import binascii
import copy
import errno
@@ -52,7 +52,6 @@
from eventlet import Timeout, tpool
from eventlet.hubs import trampoline
-import six
from pyeclib.ec_iface import ECDriverError, ECInvalidFragmentMetadata, \
ECBadFragmentChecksum, ECInvalidParameter
@@ -154,16 +153,10 @@ def _encode_metadata(metadata):
:param metadata: a dict
"""
- if six.PY2:
- def encode_str(item):
- if isinstance(item, six.text_type):
- return item.encode('utf8')
- return item
- else:
- def encode_str(item):
- if isinstance(item, six.text_type):
- return item.encode('utf8', 'surrogateescape')
- return item
+ def encode_str(item):
+ if isinstance(item, str):
+ return item.encode('utf8', 'surrogateescape')
+ return item
return dict(((encode_str(k), encode_str(v)) for k, v in metadata.items()))
@@ -175,27 +168,16 @@ def _decode_metadata(metadata, metadata_written_by_py3):
:param metadata: a dict
:param metadata_written_by_py3:
"""
- if six.PY2:
- def to_str(item, is_name=False):
- # For years, py2 and py3 handled non-ascii metadata differently;
- # see https://bugs.launchpad.net/swift/+bug/2012531
- if metadata_written_by_py3 and not is_name:
- # do our best to read new-style data replicated from a py3 node
- item = item.decode('utf8').encode('latin1')
- if isinstance(item, six.text_type):
- return item.encode('utf8')
- return item
- else:
- def to_str(item, is_name=False):
- # For years, py2 and py3 handled non-ascii metadata differently;
- # see https://bugs.launchpad.net/swift/+bug/2012531
- if not metadata_written_by_py3 and isinstance(item, bytes) \
- and not is_name:
- # do our best to read old py2 data
- item = item.decode('latin1')
- if isinstance(item, six.binary_type):
- return item.decode('utf8', 'surrogateescape')
- return item
+ def to_str(item, is_name=False):
+ # For years, py2 and py3 handled non-ascii metadata differently;
+ # see https://bugs.launchpad.net/swift/+bug/2012531
+ if not metadata_written_by_py3 and isinstance(item, bytes) \
+ and not is_name:
+ # do our best to read old py2 data
+ item = item.decode('latin1')
+ if isinstance(item, bytes):
+ return item.decode('utf8', 'surrogateescape')
+ return item
return {to_str(k): to_str(v, k == b'name') for k, v in metadata.items()}
@@ -255,10 +237,7 @@ def read_metadata(fd, add_missing_checksum=False):
# strings are utf-8 encoded when written, but have not always been
# (see https://bugs.launchpad.net/swift/+bug/1678018) so encode them again
# when read
- if six.PY2:
- metadata = pickle.loads(metadata)
- else:
- metadata = pickle.loads(metadata, encoding='bytes')
+ metadata = pickle.loads(metadata, encoding='bytes') # nosec: B301
return _decode_metadata(metadata, metadata_written_by_py3)
@@ -360,7 +339,7 @@ def quarantine_renamer(device_path, corrupted_file_path):
def valid_suffix(value):
- if not isinstance(value, six.string_types) or len(value) != 3:
+ if not isinstance(value, str) or len(value) != 3:
return False
return all(c in '0123456789abcdef' for c in value)
@@ -381,7 +360,7 @@ def read_hashes(partition_dir):
pass
else:
try:
- hashes = pickle.loads(pickled_hashes)
+ hashes = pickle.loads(pickled_hashes) # nosec: B301
except Exception:
# pickle.loads() can raise a wide variety of exceptions when
# given invalid input depending on the way in which the
@@ -626,11 +605,7 @@ def get_auditor_status(datadir_path, logger, auditor_type):
datadir_path, "auditor_status_%s.json" % auditor_type)
status = {}
try:
- if six.PY3:
- statusfile = open(auditor_status, encoding='utf8')
- else:
- statusfile = open(auditor_status, 'rb')
- with statusfile:
+ with open(auditor_status, encoding='utf8') as statusfile:
status = statusfile.read()
except (OSError, IOError) as e:
if e.errno != errno.ENOENT and logger:
@@ -648,9 +623,7 @@ def get_auditor_status(datadir_path, logger, auditor_type):
def update_auditor_status(datadir_path, logger, partitions, auditor_type):
- status = json.dumps({'partitions': partitions})
- if six.PY3:
- status = status.encode('utf8')
+ status = json.dumps({'partitions': partitions}).encode('utf8')
auditor_status = os.path.join(
datadir_path, "auditor_status_%s.json" % auditor_type)
try:
@@ -1170,22 +1143,19 @@ def _hash_suffix_dir(self, path, policy):
:param path: full path to directory
:param policy: storage policy used
"""
- if six.PY2:
- hashes = defaultdict(lambda: md5(usedforsecurity=False))
- else:
- class shim(object):
- def __init__(self):
- self.md5 = md5(usedforsecurity=False)
+ class shim(object):
+ def __init__(self):
+ self.md5 = md5(usedforsecurity=False)
- def update(self, s):
- if isinstance(s, str):
- self.md5.update(s.encode('utf-8'))
- else:
- self.md5.update(s)
+ def update(self, s):
+ if isinstance(s, str):
+ self.md5.update(s.encode('utf-8'))
+ else:
+ self.md5.update(s)
- def hexdigest(self):
- return self.md5.hexdigest()
- hashes = defaultdict(shim)
+ def hexdigest(self):
+ return self.md5.hexdigest()
+ hashes = defaultdict(shim)
try:
path_contents = sorted(os.listdir(path))
except OSError as err:
@@ -3206,7 +3176,7 @@ def _init_checks(self):
def _check_frag(self, frag):
if not frag:
return
- if not isinstance(frag, six.binary_type):
+ if not isinstance(frag, bytes):
# ECInvalidParameter can be returned if the frag violates the input
# format so for safety, check the input chunk if it's binary to
# avoid quarantining a valid fragment archive.
diff --git a/swift/obj/expirer.py b/swift/obj/expirer.py
index 5d903b32a1..b5033ba0c8 100644
--- a/swift/obj/expirer.py
+++ b/swift/obj/expirer.py
@@ -13,8 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import six
-from six.moves import urllib
+import urllib
from random import random
from time import time
@@ -344,7 +343,7 @@ def _iter_task_container(self, task_account, task_container,
task_container,
acceptable_statuses=[2]):
container_empty = False
- task_object = o['name'].encode('utf8') if six.PY2 else o['name']
+ task_object = o['name']
try:
delete_timestamp, target_account, target_container, \
target_object = parse_task_obj(task_object)
diff --git a/swift/obj/reconstructor.py b/swift/obj/reconstructor.py
index 95406387ad..de0e749eed 100644
--- a/swift/obj/reconstructor.py
+++ b/swift/obj/reconstructor.py
@@ -21,8 +21,7 @@
import random
import time
from collections import defaultdict
-import six
-import six.moves.cPickle as pickle
+import pickle # nosec: B403
import shutil
from eventlet import (GreenPile, GreenPool, Timeout, sleep, tpool, spawn)
@@ -84,7 +83,7 @@ def _full_path(node, part, relative_path, policy):
:class:`~swift.common.storage_policy.BaseStoragePolicy`
:return: string representation of absolute path on node plus policy index
"""
- if not isinstance(relative_path, six.text_type):
+ if not isinstance(relative_path, str):
relative_path = relative_path.decode('utf8')
return '%(node)s/%(part)s%(path)s policy#%(policy)d' % {
'node': node_to_string(node, replication=True),
@@ -935,7 +934,7 @@ def _get_suffixes_to_sync(self, job, node):
"Invalid response %(resp)s from %(full_path)s",
{'resp': resp.status, 'full_path': full_path})
else:
- remote_suffixes = pickle.loads(resp.read())
+ remote_suffixes = pickle.loads(resp.read()) # nosec: B301
except (Exception, Timeout):
# all exceptions are logged here so that our caller can
# safely catch our exception and continue to the next node
@@ -1286,11 +1285,11 @@ def get_policy2devices(self):
policy2devices = {}
for policy in self.policies:
self.load_object_ring(policy)
- local_devices = list(six.moves.filter(
- lambda dev: dev and is_local_device(
+ local_devices = [
+ dev for dev in policy.object_ring.devs
+ if dev and is_local_device(
ips, self.port,
- dev['replication_ip'], dev['replication_port']),
- policy.object_ring.devs))
+ dev['replication_ip'], dev['replication_port'])]
policy2devices[policy] = local_devices
return policy2devices
diff --git a/swift/obj/replicator.py b/swift/obj/replicator.py
index 07e2815f66..332eaca8e0 100644
--- a/swift/obj/replicator.py
+++ b/swift/obj/replicator.py
@@ -22,8 +22,7 @@
import shutil
import time
import itertools
-from six import viewkeys
-import six.moves.cPickle as pickle
+import pickle # nosec: B403
import eventlet
from eventlet import GreenPool, queue, tpool, Timeout, sleep
@@ -554,8 +553,8 @@ def tpool_get_suffixes(path):
failure_devs_info.add((node['replication_ip'],
node['device']))
if success and node['region'] != job['region']:
- synced_remote_regions[node['region']] = viewkeys(
- candidates)
+ synced_remote_regions[node['region']] = \
+ candidates.keys()
responses.append(success)
for cand_objs in synced_remote_regions.values():
if delete_objs is None:
@@ -710,7 +709,8 @@ def update(self, job):
failure_devs_info.add((node['replication_ip'],
node['device']))
continue
- remote_hash = pickle.loads(resp.read())
+ remote_hash = pickle.loads(
+ resp.read()) # nosec: B301
finally:
conn.close()
del resp
diff --git a/swift/obj/server.py b/swift/obj/server.py
index 1870515204..b4bf640f74 100644
--- a/swift/obj/server.py
+++ b/swift/obj/server.py
@@ -15,9 +15,8 @@
""" Object Server for Swift """
-import six
-import six.moves.cPickle as pickle
-from six.moves.urllib.parse import unquote
+import pickle # nosec: B403
+from urllib.parse import unquote
import json
import os
import multiprocessing
@@ -200,8 +199,8 @@ def __init__(self, conf, logger=None):
# disk_chunk_size parameter. However, it affects all created sockets
# using this class so we have chosen to tie it to the
# network_chunk_size parameter value instead.
- if six.PY2:
- socket._fileobject.default_bufsize = self.network_chunk_size
+ # if six.PY2:
+ # socket._fileobject.default_bufsize = self.network_chunk_size
# TODO: find a way to enable similar functionality in py3
# Provide further setup specific to an object server implementation.
diff --git a/swift/obj/ssync_receiver.py b/swift/obj/ssync_receiver.py
index de75eaa9d4..ab821f8680 100644
--- a/swift/obj/ssync_receiver.py
+++ b/swift/obj/ssync_receiver.py
@@ -17,7 +17,7 @@
import eventlet.greenio
import eventlet.wsgi
from eventlet import sleep
-from six.moves import urllib
+import urllib
from swift.common import exceptions
from swift.common import http
diff --git a/swift/obj/ssync_sender.py b/swift/obj/ssync_sender.py
index 2ebfbd8512..6b3d8e77a3 100644
--- a/swift/obj/ssync_sender.py
+++ b/swift/obj/ssync_sender.py
@@ -14,8 +14,7 @@
# limitations under the License.
from eventlet import sleep
-import six
-from six.moves import urllib
+import urllib
from swift.common import bufferedhttp
from swift.common import exceptions
@@ -306,7 +305,7 @@ def missing_check(self, connection, response):
frag_index=self.job.get('frag_index'),
frag_prefs=frag_prefs)
if self.remote_check_objs is not None:
- hash_gen = six.moves.filter(
+ hash_gen = filter(
lambda objhash_timestamps:
objhash_timestamps[0] in
self.remote_check_objs, hash_gen)
@@ -353,11 +352,10 @@ def missing_check(self, connection, response):
if line == b':MISSING_CHECK: START':
break
elif line:
- if not six.PY2:
- try:
- line = line.decode('ascii')
- except UnicodeDecodeError:
- pass
+ try:
+ line = line.decode('ascii')
+ except UnicodeDecodeError:
+ pass
raise exceptions.ReplicationException(
'Unexpected response: %r' % utils.cap_length(line, 1024))
while True:
@@ -442,11 +440,10 @@ def updates(self, connection, response, send_map):
if line == b':UPDATES: START':
break
elif line:
- if not six.PY2:
- try:
- line = line.decode('ascii')
- except UnicodeDecodeError:
- pass
+ try:
+ line = line.decode('ascii')
+ except UnicodeDecodeError:
+ pass
raise exceptions.ReplicationException(
'Unexpected response: %r' % utils.cap_length(line, 1024))
while True:
@@ -459,11 +456,10 @@ def updates(self, connection, response, send_map):
if line == b':UPDATES: END':
break
elif line:
- if not six.PY2:
- try:
- line = line.decode('ascii')
- except UnicodeDecodeError:
- pass
+ try:
+ line = line.decode('ascii')
+ except UnicodeDecodeError:
+ pass
raise exceptions.ReplicationException(
'Unexpected response: %r' % utils.cap_length(line, 1024))
diff --git a/swift/obj/updater.py b/swift/obj/updater.py
index 2500e73df3..4222feee14 100644
--- a/swift/obj/updater.py
+++ b/swift/obj/updater.py
@@ -12,9 +12,9 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-from six.moves import queue
+import queue
-import six.moves.cPickle as pickle
+import pickle # nosec: B403
import errno
import os
import signal
@@ -62,8 +62,6 @@ def __len__(self):
def __bool__(self):
return bool(self.deque)
- __nonzero__ = __bool__ # py2
-
def __lt__(self, other):
# used to sort RateLimiterBuckets by readiness
if isinstance(other, RateLimiterBucket):
@@ -145,7 +143,7 @@ def _bucket_key(self, update):
def _get_time(self):
return time.time()
- def next(self):
+ def __next__(self):
# first iterate over the wrapped iterator...
for update_ctx in self.iterator:
bucket = self.buckets[self._bucket_key(update_ctx['update'])]
@@ -213,8 +211,6 @@ def next(self):
raise StopIteration()
- __next__ = next
-
class OldestAsyncPendingTracker:
"""
@@ -648,7 +644,7 @@ def aggregate_and_dump_recon(self, devices, elapsed, now):
def _load_update(self, device, update_path):
try:
- return pickle.load(open(update_path, 'rb'))
+ return pickle.load(open(update_path, 'rb')) # nosec: B301
except Exception as e:
if getattr(e, 'errno', None) == errno.ENOENT:
return
diff --git a/swift/proxy/controllers/account.py b/swift/proxy/controllers/account.py
index d59306c693..340e14384b 100644
--- a/swift/proxy/controllers/account.py
+++ b/swift/proxy/controllers/account.py
@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from six.moves.urllib.parse import unquote
+from urllib.parse import unquote
from swift.account.utils import account_listing_response
from swift.common.middleware.acl import parse_acl, format_acl
diff --git a/swift/proxy/controllers/base.py b/swift/proxy/controllers/base.py
index 17f497c8fd..a2cba72816 100644
--- a/swift/proxy/controllers/base.py
+++ b/swift/proxy/controllers/base.py
@@ -24,7 +24,7 @@
# These shenanigans are to ensure all related objects can be garbage
# collected. We've seen objects hang around forever otherwise.
-from six.moves.urllib.parse import quote
+from urllib.parse import quote
import time
import json
@@ -34,10 +34,8 @@
import operator
import random
from copy import deepcopy
-from sys import exc_info
from eventlet.timeout import Timeout
-import six
from swift.common.memcached import MemcacheConnectionError
from swift.common.wsgi import make_pre_authed_env, make_pre_authed_request
@@ -626,16 +624,10 @@ def get_cache_key(account, container=None, obj=None, shard=None):
with obj)
:returns: a (native) string cache_key
"""
- if six.PY2:
- def to_native(s):
- if s is None or isinstance(s, str):
- return s
- return s.encode('utf8')
- else:
- def to_native(s):
- if s is None or isinstance(s, str):
- return s
- return s.decode('utf8', 'surrogateescape')
+ def to_native(s):
+ if s is None or isinstance(s, str):
+ return s
+ return s.decode('utf8', 'surrogateescape')
account = to_native(account)
container = to_native(container)
@@ -844,27 +836,6 @@ def _get_info_from_memcache(app, env, account, container=None):
else:
info = memcache.get(cache_key)
cache_state = 'hit' if info else 'miss'
- if info and six.PY2:
- # Get back to native strings
- new_info = {}
- for key in info:
- new_key = key.encode("utf-8") if isinstance(
- key, six.text_type) else key
- if isinstance(info[key], six.text_type):
- new_info[new_key] = info[key].encode("utf-8")
- elif isinstance(info[key], dict):
- new_info[new_key] = {}
- for subkey, value in info[key].items():
- new_subkey = subkey.encode("utf-8") if isinstance(
- subkey, six.text_type) else subkey
- if isinstance(value, six.text_type):
- new_info[new_key][new_subkey] = \
- value.encode("utf-8")
- else:
- new_info[new_key][new_subkey] = value
- else:
- new_info[new_key] = info[key]
- info = new_info
if info:
env.setdefault('swift.infocache', {})[cache_key] = info
return info, cache_state
@@ -921,12 +892,6 @@ def get_namespaces_from_cache(req, cache_key, skip_chance):
cache_state = 'error'
if bounds:
- if six.PY2:
- # json.loads() in memcache.get will convert json 'string' to
- # 'unicode' with python2, here we cast 'unicode' back to 'str'
- bounds = [
- [lower.encode('utf-8'), name.encode('utf-8')]
- for lower, name in bounds]
ns_bound_list = NamespaceBoundList(bounds)
infocache[cache_key] = ns_bound_list
else:
@@ -1439,14 +1404,13 @@ def _iter_bytes_from_response_part(self, part_file, nbytes):
chunk = part_file.read(self.app.object_chunk_size)
if nbytes is not None:
nbytes -= len(chunk)
- except (ChunkReadTimeout, ShortReadError):
- exc_type, exc_value, exc_traceback = exc_info()
+ except (ChunkReadTimeout, ShortReadError) as e:
if self.newest or self.server_type != 'Object':
raise
try:
self.fast_forward(self.bytes_used_from_backend)
except (HTTPException, ValueError):
- six.reraise(exc_type, exc_value, exc_traceback)
+ raise e
except RangeAlreadyComplete:
break
if self._replace_source(
@@ -1458,10 +1422,10 @@ def _iter_bytes_from_response_part(self, part_file, nbytes):
# Tried to find a new node from which to
# finish the GET, but failed. There's
# nothing more we can do here.
- six.reraise(exc_type, exc_value, exc_traceback)
+ raise e
part_file = ByteCountEnforcer(part_file, nbytes)
else:
- six.reraise(exc_type, exc_value, exc_traceback)
+ raise e
else:
if not chunk:
break
@@ -1880,7 +1844,7 @@ def _annotate_node(self, node):
return dict(node, use_replication=is_use_replication_network(
self.request.headers))
- def next(self):
+ def __next__(self):
node = None
if self._node_provider:
# give node provider the opportunity to inject a node
@@ -1889,9 +1853,6 @@ def next(self):
node = next(self._node_iter)
return self._annotate_node(node)
- def __next__(self):
- return self.next()
-
class Controller(object):
"""Base WSGI controller class for the proxy"""
diff --git a/swift/proxy/controllers/container.py b/swift/proxy/controllers/container.py
index 6226b7a703..dcbbcc7851 100644
--- a/swift/proxy/controllers/container.py
+++ b/swift/proxy/controllers/container.py
@@ -15,8 +15,7 @@
import json
-import six
-from six.moves.urllib.parse import unquote
+from urllib.parse import unquote
from swift.common.utils import public, private, csv_append, Timestamp, \
config_true_value, cache_from_env, filter_namespaces, NamespaceBoundList
@@ -508,8 +507,6 @@ def _get_from_shards(self, req, resp, namespaces):
else:
last_name = objects[-1]['name']
- if six.PY2:
- last_name = last_name.encode('utf8')
params['marker'] = str_to_wsgi(last_name)
elif marker:
params['marker'] = str_to_wsgi(marker)
@@ -594,8 +591,6 @@ def _get_from_shards(self, req, resp, namespaces):
break
last_name = objects[-1].get('name',
objects[-1].get('subdir', u''))
- if six.PY2:
- last_name = last_name.encode('utf8')
if end_marker and reverse and end_marker >= last_name:
break
if end_marker and not reverse and end_marker <= last_name:
diff --git a/swift/proxy/controllers/obj.py b/swift/proxy/controllers/obj.py
index c26fef6d45..61523fa814 100644
--- a/swift/proxy/controllers/obj.py
+++ b/swift/proxy/controllers/obj.py
@@ -24,9 +24,7 @@
# These shenanigans are to ensure all related objects can be garbage
# collected. We've seen objects hang around forever otherwise.
-import six
-from six.moves.urllib.parse import quote, unquote
-from six.moves import zip
+from urllib.parse import quote, unquote
import collections
import itertools
@@ -35,7 +33,6 @@
import time
import math
import random
-import sys
from greenlet import GreenletExit
from eventlet import GreenPile
@@ -1301,8 +1298,6 @@ def __iter__(self):
def __next__(self):
return next(self.stashed_iter)
- next = __next__ # py2
-
def _real_iter(self, req, resp_headers):
if not self.range_specs:
client_asked_for_range = False
@@ -2490,13 +2485,12 @@ def _iter_bytes_from_response_part(self, part_file, nbytes):
buf += chunk
if nbytes is not None:
nbytes -= len(chunk)
- except (ChunkReadTimeout, ShortReadError):
- exc_type, exc_value, exc_traceback = sys.exc_info()
+ except (ChunkReadTimeout, ShortReadError) as e:
try:
self.fast_forward(self.bytes_used_from_backend)
except (HTTPException, ValueError):
self.logger.exception('Unable to fast forward')
- six.reraise(exc_type, exc_value, exc_traceback)
+ raise e
except RangeAlreadyComplete:
break
buf = b''
@@ -2509,10 +2503,10 @@ def _iter_bytes_from_response_part(self, part_file, nbytes):
# it's not clear to me how to make
# _get_next_response_part raise StopIteration for the
# first doc part of a new request
- six.reraise(exc_type, exc_value, exc_traceback)
+ raise e
part_file = ByteCountEnforcer(part_file, nbytes)
else:
- six.reraise(exc_type, exc_value, exc_traceback)
+ raise e
else:
if buf and self.skip_bytes:
if self.skip_bytes < len(buf):
diff --git a/test/__init__.py b/test/__init__.py
index 2974b465f9..e31ed458a4 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -18,7 +18,6 @@
from contextlib import contextmanager
import os
-from six import reraise
from unittest.util import safe_repr
@@ -105,15 +104,15 @@ def annotate_failure(msg):
try:
yield
except AssertionError as err:
- err_typ, err_val, err_tb = sys.exc_info()
- if err_val.args:
- msg = '%s Failed with %s' % (msg, err_val.args[0])
- err_val.args = (msg, ) + err_val.args[1:]
+ if err.args:
+ msg = '%s Failed with %s' % (msg, err.args[0])
+ err.args = (msg, ) + err.args[1:]
+ raise err
else:
# workaround for some IDE's raising custom AssertionErrors
- err_val = '%s Failed with %s' % (msg, err)
- err_typ = AssertionError
- reraise(err_typ, err_val, err_tb)
+ raise AssertionError(
+ '%s Failed with %s' % (msg, err)
+ ).with_traceback(err.__traceback__) from err.__cause__
class BaseTestCase(unittest.TestCase):
diff --git a/test/cors/main.py b/test/cors/main.py
index 063f967247..5d483c7835 100755
--- a/test/cors/main.py
+++ b/test/cors/main.py
@@ -24,9 +24,9 @@
import time
import traceback
-from six.moves import urllib
-from six.moves import socketserver
-from six.moves import SimpleHTTPServer
+import urllib.parse
+import socketserver
+import http.server
try:
import selenium.webdriver
@@ -51,12 +51,14 @@
STEPS = 500
-# Hack up stdlib so SimpleHTTPRequestHandler works well on py2, too
-this_dir = os.path.realpath(os.path.dirname(__file__))
-os.getcwd = lambda: this_dir
+class CORSSiteHandler(http.server.SimpleHTTPRequestHandler):
+ def __init__(self, *args, **kwargs):
+ super().__init__(
+ *args,
+ directory=os.path.realpath(os.path.dirname(__file__)),
+ **kwargs,
+ )
-
-class CORSSiteHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def log_message(self, fmt, *args):
pass # quiet, you!
@@ -67,7 +69,7 @@ class CORSSiteServer(socketserver.TCPServer):
class CORSSite(threading.Thread):
def __init__(self, bind_port=8000):
- super(CORSSite, self).__init__()
+ super().__init__()
self.server = None
self.bind_port = bind_port
diff --git a/test/functional/__init__.py b/test/functional/__init__.py
index ef8ca9dc77..73f3d4cb47 100644
--- a/test/functional/__init__.py
+++ b/test/functional/__init__.py
@@ -20,8 +20,7 @@
import mock
import os
-import six
-from six.moves.urllib.parse import urlparse, urlsplit, urlunsplit
+from urllib.parse import urlparse, urlsplit, urlunsplit
import sys
import pickle
import socket
@@ -39,9 +38,9 @@
from tempfile import mkdtemp
from unittest import SkipTest
-from six.moves.configparser import ConfigParser
-from six.moves import http_client
-from six.moves.http_client import HTTPException
+from configparser import ConfigParser
+import http.client
+from http.client import HTTPException
from swift.common.middleware.memcache import MemcacheMiddleware
from swift.common.storage_policy import parse_storage_policies, PolicyError
@@ -65,7 +64,7 @@
from swift.obj import server as object_server, mem_server as mem_object_server
import swift.proxy.controllers.obj
-http_client._MAXHEADERS = constraints.MAX_HEADER_COUNT
+http.client._MAXHEADERS = constraints.MAX_HEADER_COUNT
DEBUG = True
# In order to get the proper blocking behavior of sockets without using
@@ -357,9 +356,7 @@ def _load_encryption(proxy_conf_file, swift_conf_file, **kwargs):
conf,
"proxy-logging proxy-server",
"keymaster encryption proxy-logging proxy-server")
- root_secret = base64.b64encode(os.urandom(32))
- if not six.PY2:
- root_secret = root_secret.decode('ascii')
+ root_secret = base64.b64encode(os.urandom(32)).decode('ascii')
conf.set('filter:keymaster', 'encryption_root_secret', root_secret)
conf.set('filter:versioned_writes', 'allow_object_versioning', 'true')
conf.set('filter:etag-quoter', 'enable_by_default', 'true')
@@ -1129,10 +1126,6 @@ def get_url_token(user_index, os_options):
swift_test_user[user_index],
swift_test_key[user_index],
**authargs)
- if six.PY2 and not isinstance(url, bytes):
- url = url.encode('utf-8')
- if six.PY2 and not isinstance(token, bytes):
- token = token.encode('utf-8')
return url, token
diff --git a/test/functional/s3api/s3_test_client.py b/test/functional/s3api/s3_test_client.py
index 9be79304bb..3f437a663c 100644
--- a/test/functional/s3api/s3_test_client.py
+++ b/test/functional/s3api/s3_test_client.py
@@ -15,7 +15,7 @@
import logging
import os
-from six.moves.urllib.parse import urlparse
+from urllib.parse import urlparse
import test.functional as tf
import boto3
from botocore.exceptions import ClientError
@@ -27,7 +27,6 @@
)
except ImportError:
S3Connection = OrdinaryCallingFormat = S3ResponseError = None
-import six
import sys
import traceback
@@ -96,21 +95,11 @@ def reset(self):
break
for bucket in buckets:
- if six.PY2 and not isinstance(bucket.name, bytes):
- bucket.name = bucket.name.encode('utf-8')
-
try:
for upload in bucket.list_multipart_uploads():
upload.cancel_upload()
for obj in bucket.list_versions():
- if six.PY2:
- if not isinstance(obj.name, bytes):
- obj.name = obj.name.encode('utf-8')
- if obj.version_id is not None and \
- not isinstance(obj.version_id, bytes):
- obj.version_id = \
- obj.version_id.encode('utf-8')
bucket.delete_key(
obj.name, version_id=obj.version_id)
diff --git a/test/functional/s3api/test_multi_delete.py b/test/functional/s3api/test_multi_delete.py
index ac15927d66..be32a530ff 100644
--- a/test/functional/s3api/test_multi_delete.py
+++ b/test/functional/s3api/test_multi_delete.py
@@ -13,7 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import six
import unittest
import os
import test.functional as tf
@@ -83,8 +82,6 @@ def _test_delete_multi_objects(self, with_non_ascii=False):
self.assertEqual(len(resp_objects), len(req_objects))
for o in resp_objects:
key = o.find('Key').text
- if six.PY2:
- key = key.decode('utf-8')
self.assertTrue(key in req_objects)
# Delete 2 objects via MultiDelete API
@@ -101,8 +98,6 @@ def _test_delete_multi_objects(self, with_non_ascii=False):
self.assertEqual(len(resp_objects), len(req_objects))
for o in resp_objects:
key = o.find('Key').text
- if six.PY2:
- key = key.decode('utf-8')
self.assertTrue(key in req_objects)
if with_non_ascii:
@@ -124,8 +119,6 @@ def _test_delete_multi_objects(self, with_non_ascii=False):
self.assertEqual(len(resp_objects), len(req_objects))
for o in resp_objects:
key = o.find('Key').text
- if six.PY2:
- key = key.decode('utf-8')
self.assertTrue(key in req_objects)
# Delete 2 objects via MultiDelete API but no objects exist
@@ -142,8 +135,6 @@ def _test_delete_multi_objects(self, with_non_ascii=False):
self.assertEqual(len(resp_objects), len(req_objects))
for o in resp_objects:
key = o.find('Key').text
- if six.PY2:
- key = key.decode('utf-8')
self.assertTrue(key in req_objects)
def test_delete_multi_objects(self):
diff --git a/test/functional/s3api/test_multi_upload.py b/test/functional/s3api/test_multi_upload.py
index 82df2419b3..74cbdff0fb 100644
--- a/test/functional/s3api/test_multi_upload.py
+++ b/test/functional/s3api/test_multi_upload.py
@@ -17,8 +17,8 @@
import binascii
import unittest
-import six
-from six.moves import urllib, zip, zip_longest
+import urllib.parse
+from itertools import zip_longest
import test.functional as tf
from swift.common.middleware.s3api.etree import fromstring, tostring, \
@@ -135,8 +135,6 @@ def test_object_multi_upload(self):
elem = fromstring(body, 'InitiateMultipartUploadResult')
self.assertEqual(elem.find('Bucket').text, bucket)
key = elem.find('Key').text
- if six.PY2:
- expected_key = expected_key.encode('utf-8')
self.assertEqual(expected_key, key)
upload_id = elem.find('UploadId').text
self.assertIsNotNone(upload_id)
@@ -475,10 +473,7 @@ def check_obj(req_headers, exp_status):
resp_objects = list(elem.findall('./Contents'))
self.assertEqual(len(resp_objects), 1)
o = resp_objects[0]
- if six.PY2:
- expected_key = keys[0].encode('utf-8')
- else:
- expected_key = keys[0]
+ expected_key = keys[0]
self.assertEqual(o.find('Key').text, expected_key)
self.assertIsNotNone(o.find('LastModified').text)
self.assertRegex(
diff --git a/test/functional/s3api/test_object.py b/test/functional/s3api/test_object.py
index d3ceef8344..eefe4888dc 100644
--- a/test/functional/s3api/test_object.py
+++ b/test/functional/s3api/test_object.py
@@ -20,7 +20,6 @@
import email.parser
from email.utils import formatdate, parsedate
from time import mktime
-import six
import test.functional as tf
from swift.common import utils
@@ -787,10 +786,7 @@ def test_get_object_range(self):
# TODO: Using swift.common.utils.multipart_byteranges_to_document_iters
# could be easy enough.
- if six.PY2:
- parser = email.parser.FeedParser()
- else:
- parser = email.parser.BytesFeedParser()
+ parser = email.parser.BytesFeedParser()
parser.feed(
b"Content-Type: multipart/byterange; boundary=%s\r\n\r\n" %
boundary_str.encode('ascii'))
diff --git a/test/functional/s3api/test_xxe_injection.py b/test/functional/s3api/test_xxe_injection.py
index 07f8603797..af0a433a88 100644
--- a/test/functional/s3api/test_xxe_injection.py
+++ b/test/functional/s3api/test_xxe_injection.py
@@ -15,7 +15,6 @@
# limitations under the License.
import requests
-import six
import botocore
@@ -62,11 +61,10 @@ def _presign_url(self, method, key=None, **kwargs):
finally:
self.conn.meta.events.unregister(
'before-sign.s3.*', self._clear_data)
- if not params.get('Key') and '/?' not in url and not six.PY2:
+ if not params.get('Key') and '/?' not in url:
# Some combination of dependencies seems to cause bucket requests
# to not get the trailing slash despite signing with it? But only
- # new-enough versions sign with the trailing slash; py2 is stuck
- # with old.
+ # new-enough versions sign with the trailing slash
url = url.replace('?', '/?')
return url
diff --git a/test/functional/swift_test_client.py b/test/functional/swift_test_client.py
index 5998215a04..5b01b411a0 100644
--- a/test/functional/swift_test_client.py
+++ b/test/functional/swift_test_client.py
@@ -25,9 +25,8 @@
from unittest import SkipTest
from xml.dom import minidom
-import six
-from six.moves import http_client
-from six.moves import urllib
+import http.client
+import urllib.parse
from swiftclient import get_auth
from swift.common import constraints
@@ -37,7 +36,7 @@
from test import safe_repr
-http_client._MAXHEADERS = constraints.MAX_HEADER_COUNT
+http.client._MAXHEADERS = constraints.MAX_HEADER_COUNT
class AuthenticationFailed(Exception):
@@ -138,10 +137,10 @@ def putrequest(self, method, url, skip_host=False, skip_accept_encoding=False):
and self._HTTPConnection__response.isclosed():
self._HTTPConnection__response = None
- if self._HTTPConnection__state == http_client._CS_IDLE:
- self._HTTPConnection__state = http_client._CS_REQ_STARTED
+ if self._HTTPConnection__state == http.client._CS_IDLE:
+ self._HTTPConnection__state = http.client._CS_REQ_STARTED
else:
- raise http_client.CannotSendRequest(self._HTTPConnection__state)
+ raise http.client.CannotSendRequest(self._HTTPConnection__state)
self._method = method
if not url:
@@ -225,15 +224,12 @@ def storage_url(self):
@storage_url.setter
def storage_url(self, value):
- if six.PY2 and not isinstance(value, bytes):
- value = value.encode('utf-8')
-
url = urllib.parse.urlparse(value)
if url.scheme == 'http':
- self.conn_class = http_client.HTTPConnection
+ self.conn_class = http.client.HTTPConnection
elif url.scheme == 'https':
- self.conn_class = http_client.HTTPSConnection
+ self.conn_class = http.client.HTTPSConnection
else:
raise ValueError('unexpected protocol %s' % (url.scheme))
@@ -250,7 +246,7 @@ def storage_url(self, value):
def storage_scheme(self):
if self.conn_class is None:
return None
- if issubclass(self.conn_class, http_client.HTTPSConnection):
+ if issubclass(self.conn_class, http.client.HTTPSConnection):
return 'https'
return 'http'
@@ -411,7 +407,7 @@ def request_with_retry(self, try_request):
except socket.timeout as e:
fail_messages.append(safe_repr(e))
continue
- except http_client.HTTPException as e:
+ except http.client.HTTPException as e:
fail_messages.append(safe_repr(e))
continue
@@ -500,7 +496,7 @@ def is_int_header(header):
'x-container-bytes-used',
)
- # NB: on py2, headers are always lower; on py3, they match the bytes
+ # NB: on py2, headers were always lower; on py3, they match the bytes
# on the wire
headers = dict((wsgi_to_str(h).lower(), wsgi_to_str(v))
for h, v in self.conn.response.getheaders())
@@ -568,9 +564,6 @@ def containers(self, hdrs=None, parms=None, cfg=None):
if status == 200:
if format_type == 'json':
conts = json.loads(self.conn.response.read())
- if six.PY2:
- for cont in conts:
- cont['name'] = cont['name'].encode('utf-8')
return conts
elif format_type == 'xml':
conts = []
@@ -582,8 +575,6 @@ def containers(self, hdrs=None, parms=None, cfg=None):
childNodes[0].nodeValue
conts.append(cont)
for cont in conts:
- if six.PY2:
- cont['name'] = cont['name'].encode('utf-8')
for key in ('count', 'bytes'):
cont[key] = int(cont[key])
return conts
@@ -591,8 +582,6 @@ def containers(self, hdrs=None, parms=None, cfg=None):
lines = self.conn.response.read().split(b'\n')
if lines and not lines[-1]:
lines = lines[:-1]
- if six.PY2:
- return lines
return [line.decode('utf-8') for line in lines]
elif status == 204:
return []
@@ -716,15 +705,7 @@ def files(self, hdrs=None, parms=None, cfg=None, tolerate_missing=False):
parms=parms, cfg=cfg)
if status == 200:
if format_type == 'json' or 'versions' in parms:
- files = json.loads(self.conn.response.read())
-
- if six.PY2:
- for file_item in files:
- for key in ('name', 'subdir', 'content_type',
- 'version_id'):
- if key in file_item:
- file_item[key] = file_item[key].encode('utf-8')
- return files
+ return json.loads(self.conn.response.read())
elif format_type == 'xml':
files = []
tree = minidom.parseString(self.conn.response.read())
@@ -745,15 +726,7 @@ def files(self, hdrs=None, parms=None, cfg=None, tolerate_missing=False):
files.append(file_item)
for file_item in files:
- if 'subdir' in file_item:
- if six.PY2:
- file_item['subdir'] = \
- file_item['subdir'].encode('utf-8')
- else:
- if six.PY2:
- file_item.update({
- k: file_item[k].encode('utf-8')
- for k in ('name', 'content_type')})
+ if 'bytes' in file_item:
file_item['bytes'] = int(file_item['bytes'])
return files
else:
@@ -762,8 +735,6 @@ def files(self, hdrs=None, parms=None, cfg=None, tolerate_missing=False):
lines = content.split(b'\n')
if lines and not lines[-1]:
lines = lines[:-1]
- if six.PY2:
- return lines
return [line.decode('utf-8') for line in lines]
else:
return []
diff --git a/test/functional/test_access_control.py b/test/functional/test_access_control.py
index 7bc3e479a2..accf1b1ea0 100644
--- a/test/functional/test_access_control.py
+++ b/test/functional/test_access_control.py
@@ -15,7 +15,7 @@
# limitations under the License.
import unittest
-from six.moves.urllib.parse import urlparse, urlunparse
+from urllib.parse import urlparse, urlunparse
import uuid
from random import shuffle
diff --git a/test/functional/test_account.py b/test/functional/test_account.py
index dab6ad9908..9a40a14a07 100644
--- a/test/functional/test_account.py
+++ b/test/functional/test_account.py
@@ -17,11 +17,10 @@
import unittest
import json
+import urllib.parse
from uuid import uuid4
from string import ascii_letters
-import six
-from six.moves import range, urllib
from swift.common.middleware.acl import format_acl
from swift.common.utils import distribute_evenly
@@ -756,40 +755,18 @@ def post(url, token, parsed, conn, name, value):
def head(url, token, parsed, conn):
conn.request('HEAD', parsed.path, '', {'X-Auth-Token': token})
return check_response(conn)
- uni_key = u'X-Account-Meta-uni\u0E12'
uni_value = u'uni\u0E12'
# Note that py3 has issues with non-ascii header names; see
- # https://bugs.python.org/issue37093
- if (tf.web_front_end == 'integral' and six.PY2):
- resp = retry(post, uni_key, '1')
- resp.read()
- self.assertIn(resp.status, (201, 204))
- resp = retry(head)
- resp.read()
- self.assertIn(resp.status, (200, 204))
- self.assertEqual(resp.getheader(uni_key.encode('utf-8')), '1')
+ # https://bugs.python.org/issue37093 -- so we won't test with unicode
+ # header names
resp = retry(post, 'X-Account-Meta-uni', uni_value)
resp.read()
self.assertEqual(resp.status, 204)
resp = retry(head)
resp.read()
self.assertIn(resp.status, (200, 204))
- if six.PY2:
- self.assertEqual(resp.getheader('X-Account-Meta-uni'),
- uni_value.encode('utf8'))
- else:
- self.assertEqual(resp.getheader('X-Account-Meta-uni'),
- uni_value)
- # See above note about py3 and non-ascii header names
- if (tf.web_front_end == 'integral' and six.PY2):
- resp = retry(post, uni_key, uni_value)
- resp.read()
- self.assertEqual(resp.status, 204)
- resp = retry(head)
- resp.read()
- self.assertIn(resp.status, (200, 204))
- self.assertEqual(resp.getheader(uni_key.encode('utf-8')),
- uni_value.encode('utf-8'))
+ self.assertEqual(resp.getheader('X-Account-Meta-uni'),
+ uni_value)
def test_multi_metadata(self):
if tf.skip:
diff --git a/test/functional/test_container.py b/test/functional/test_container.py
index 879bd0b06e..658e9a6c85 100644
--- a/test/functional/test_container.py
+++ b/test/functional/test_container.py
@@ -17,15 +17,13 @@
import json
import unittest
+import urllib.parse
from uuid import uuid4
from test.functional import check_response, cluster_info, retry, \
requires_acls, load_constraint, requires_policies, SkipTest
import test.functional as tf
-import six
-from six.moves import range, urllib
-
def setUpModule():
tf.setup_package()
@@ -72,11 +70,7 @@ def get(url, token, parsed, conn, container):
return check_response(conn)
def delete(url, token, parsed, conn, container, obj):
- if six.PY2:
- obj_name = obj['name'].encode('utf8')
- else:
- obj_name = obj['name']
- path = '/'.join([parsed.path, container, obj_name])
+ path = '/'.join([parsed.path, container, obj['name']])
conn.request('DELETE', path, '', {'X-Auth-Token': token})
return check_response(conn)
@@ -219,40 +213,18 @@ def head(url, token, parsed, conn):
{'X-Auth-Token': token})
return check_response(conn)
- uni_key = u'X-Container-Meta-uni\u0E12'
uni_value = u'uni\u0E12'
# Note that py3 has issues with non-ascii header names; see
- # https://bugs.python.org/issue37093
- if (tf.web_front_end == 'integral' and six.PY2):
- resp = retry(post, uni_key, '1')
- resp.read()
- self.assertEqual(resp.status, 204)
- resp = retry(head)
- resp.read()
- self.assertIn(resp.status, (200, 204))
- self.assertEqual(resp.getheader(uni_key.encode('utf-8')), '1')
+ # https://bugs.python.org/issue37093 -- so we won't test with unicode
+ # header names
resp = retry(post, 'X-Container-Meta-uni', uni_value)
resp.read()
self.assertEqual(resp.status, 204)
resp = retry(head)
resp.read()
self.assertIn(resp.status, (200, 204))
- if six.PY2:
- self.assertEqual(resp.getheader('X-Container-Meta-uni'),
- uni_value.encode('utf-8'))
- else:
- self.assertEqual(resp.getheader('X-Container-Meta-uni'),
- uni_value)
- # See above note about py3 and non-ascii header names
- if (tf.web_front_end == 'integral' and six.PY2):
- resp = retry(post, uni_key, uni_value)
- resp.read()
- self.assertEqual(resp.status, 204)
- resp = retry(head)
- resp.read()
- self.assertIn(resp.status, (200, 204))
- self.assertEqual(resp.getheader(uni_key.encode('utf-8')),
- uni_value.encode('utf-8'))
+ self.assertEqual(resp.getheader('X-Container-Meta-uni'),
+ uni_value)
def test_PUT_metadata(self):
if tf.skip:
@@ -844,9 +816,7 @@ def put(url, token, parsed, conn, name):
# read-only can list containers
resp = retry(get, use_account=3)
- listing = resp.read()
- if not six.PY2:
- listing = listing.decode('utf8')
+ listing = resp.read().decode('utf8')
self.assertEqual(resp.status, 200)
self.assertIn(self.name, listing)
@@ -861,9 +831,7 @@ def put(url, token, parsed, conn, name):
resp.read()
self.assertEqual(resp.status, 201)
resp = retry(get, use_account=3)
- listing = resp.read()
- if not six.PY2:
- listing = listing.decode('utf8')
+ listing = resp.read().decode('utf8')
self.assertEqual(resp.status, 200)
self.assertIn(new_container_name, listing)
@@ -963,9 +931,7 @@ def delete(url, token, parsed, conn, name):
# can list containers
resp = retry(get, use_account=3)
- listing = resp.read()
- if not six.PY2:
- listing = listing.decode('utf8')
+ listing = resp.read().decode('utf8')
self.assertEqual(resp.status, 200)
self.assertIn(self.name, listing)
@@ -975,9 +941,7 @@ def delete(url, token, parsed, conn, name):
resp.read()
self.assertIn(resp.status, (201, 202))
resp = retry(get, use_account=3)
- listing = resp.read()
- if not six.PY2:
- listing = listing.decode('utf8')
+ listing = resp.read().decode('utf8')
self.assertEqual(resp.status, 200)
self.assertIn(new_container_name, listing)
@@ -986,9 +950,7 @@ def delete(url, token, parsed, conn, name):
resp.read()
self.assertIn(resp.status, (204, 404))
resp = retry(get, use_account=3)
- listing = resp.read()
- if not six.PY2:
- listing = listing.decode('utf8')
+ listing = resp.read().decode('utf8')
self.assertEqual(resp.status, 200)
self.assertNotIn(new_container_name, listing)
@@ -1111,9 +1073,7 @@ def delete(url, token, parsed, conn, name):
# can list containers
resp = retry(get, use_account=3)
- listing = resp.read()
- if not six.PY2:
- listing = listing.decode('utf8')
+ listing = resp.read().decode('utf8')
self.assertEqual(resp.status, 200)
self.assertIn(self.name, listing)
@@ -1123,9 +1083,7 @@ def delete(url, token, parsed, conn, name):
resp.read()
self.assertEqual(resp.status, 201)
resp = retry(get, use_account=3)
- listing = resp.read()
- if not six.PY2:
- listing = listing.decode('utf8')
+ listing = resp.read().decode('utf8')
self.assertEqual(resp.status, 200)
self.assertIn(new_container_name, listing)
@@ -1134,9 +1092,7 @@ def delete(url, token, parsed, conn, name):
resp.read()
self.assertEqual(resp.status, 204)
resp = retry(get, use_account=3)
- listing = resp.read()
- if not six.PY2:
- listing = listing.decode('utf8')
+ listing = resp.read().decode('utf8')
self.assertEqual(resp.status, 200)
self.assertNotIn(new_container_name, listing)
diff --git a/test/functional/test_dlo.py b/test/functional/test_dlo.py
index 4de2c17c77..58f2004f99 100644
--- a/test/functional/test_dlo.py
+++ b/test/functional/test_dlo.py
@@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from six.moves import urllib
+import urllib
from swift.common.swob import str_to_wsgi
import test.functional as tf
diff --git a/test/functional/test_domain_remap.py b/test/functional/test_domain_remap.py
index 1313efcfa1..178fab459b 100644
--- a/test/functional/test_domain_remap.py
+++ b/test/functional/test_domain_remap.py
@@ -15,7 +15,6 @@
# limitations under the License.
from unittest import SkipTest
-import six
import test.functional as tf
from test.functional import cluster_info
@@ -117,9 +116,7 @@ def test_GET_remapped_account(self):
hdrs={'Host': domain},
cfg={'absolute_path': True})
self.assert_status(200)
- body = self.env.account.conn.response.read()
- if not six.PY2:
- body = body.decode('utf8')
+ body = self.env.account.conn.response.read().decode('utf8')
self.assertIn(self.env.container.name, body.split('\n'))
path = '/'.join(['', self.env.container.name])
@@ -127,9 +124,7 @@ def test_GET_remapped_account(self):
hdrs={'Host': domain},
cfg={'absolute_path': True})
self.assert_status(200)
- body = self.env.account.conn.response.read()
- if not six.PY2:
- body = body.decode('utf8')
+ body = self.env.account.conn.response.read().decode('utf8')
self.assertIn(self.env.obj.name, body.split('\n'))
self.assertIn(self.env.obj_slash.name, body.split('\n'))
@@ -170,9 +165,7 @@ def test_GET_remapped_container(self):
hdrs={'Host': domain},
cfg={'absolute_path': True})
self.assert_status(200)
- body = self.env.account.conn.response.read()
- if not six.PY2:
- body = body.decode('utf8')
+ body = self.env.account.conn.response.read().decode('utf8')
self.assertIn(self.env.obj.name, body.split('\n'))
self.assertIn(self.env.obj_slash.name, body.split('\n'))
diff --git a/test/functional/test_object.py b/test/functional/test_object.py
index 24dd8d7291..33d8052214 100644
--- a/test/functional/test_object.py
+++ b/test/functional/test_object.py
@@ -23,9 +23,6 @@
from unittest import SkipTest
from xml.dom import minidom
-import six
-from six.moves import range
-
from swift.common.header_key_dict import HeaderKeyDict
from test.functional import check_response, retry, requires_acls, \
requires_policies, requires_bulk
@@ -109,11 +106,7 @@ def get(url, token, parsed, conn, container):
# delete an object
def delete(url, token, parsed, conn, container, obj):
- if six.PY2:
- obj_name = obj['name'].encode('utf8')
- else:
- obj_name = obj['name']
- path = '/'.join([parsed.path, container, obj_name])
+ path = '/'.join([parsed.path, container, obj['name']])
conn.request('DELETE', path, '', {'X-Auth-Token': token})
return check_response(conn)
@@ -1261,9 +1254,7 @@ def delete(url, token, parsed, conn, name):
# can list objects
resp = retry(get_listing, use_account=3)
- listing = resp.read()
- if not six.PY2:
- listing = listing.decode('utf8')
+ listing = resp.read().decode('utf8')
self.assertEqual(resp.status, 200)
self.assertIn(self.obj, listing.split('\n'))
@@ -1286,9 +1277,7 @@ def delete(url, token, parsed, conn, name):
# sanity with account1
resp = retry(get_listing, use_account=3)
- listing = resp.read()
- if not six.PY2:
- listing = listing.decode('utf8')
+ listing = resp.read().decode('utf8')
self.assertEqual(resp.status, 200)
self.assertNotIn(obj_name, listing.split('\n'))
self.assertIn(self.obj, listing.split('\n'))
@@ -1346,9 +1335,7 @@ def delete(url, token, parsed, conn, name):
# can list objects
resp = retry(get_listing, use_account=3)
- listing = resp.read()
- if not six.PY2:
- listing = listing.decode('utf8')
+ listing = resp.read().decode('utf8')
self.assertEqual(resp.status, 200)
self.assertIn(self.obj, listing.split('\n'))
@@ -1371,9 +1358,7 @@ def delete(url, token, parsed, conn, name):
# sanity with account1
resp = retry(get_listing, use_account=3)
- listing = resp.read()
- if not six.PY2:
- listing = listing.decode('utf8')
+ listing = resp.read().decode('utf8')
self.assertEqual(resp.status, 200)
self.assertIn(obj_name, listing.split('\n'))
self.assertNotIn(self.obj, listing.split('\n'))
@@ -1431,9 +1416,7 @@ def delete(url, token, parsed, conn, name):
# can list objects
resp = retry(get_listing, use_account=3)
- listing = resp.read()
- if not six.PY2:
- listing = listing.decode('utf8')
+ listing = resp.read().decode('utf8')
self.assertEqual(resp.status, 200)
self.assertIn(self.obj, listing.split('\n'))
@@ -1456,9 +1439,7 @@ def delete(url, token, parsed, conn, name):
# sanity with account1
resp = retry(get_listing, use_account=3)
- listing = resp.read()
- if not six.PY2:
- listing = listing.decode('utf8')
+ listing = resp.read().decode('utf8')
self.assertEqual(resp.status, 200)
self.assertIn(obj_name, listing.split('\n'))
self.assertNotIn(self.obj, listing)
@@ -1961,9 +1942,7 @@ def get_obj(url, token, parsed, conn, container, obj):
for c, o, body in validate_requests:
resp = retry(get_obj, c, o)
self.assertEqual(resp.status, 200)
- if not six.PY2:
- body = body.encode('utf8')
- self.assertEqual(body, resp.read())
+ self.assertEqual(body.encode('utf8'), resp.read())
@requires_bulk
def test_bulk_delete(self):
diff --git a/test/functional/test_object_versioning.py b/test/functional/test_object_versioning.py
index 32d0641165..a822a71a72 100644
--- a/test/functional/test_object_versioning.py
+++ b/test/functional/test_object_versioning.py
@@ -18,10 +18,9 @@
import hmac
import json
import time
-import six
from copy import deepcopy
-from six.moves.urllib.parse import quote, unquote
+from urllib.parse import quote, unquote
from unittest import SkipTest
import test.functional as tf
@@ -64,13 +63,7 @@ def setUp(cls):
cls.conn2 = Connection(config2)
cls.conn2.authenticate()
- if six.PY2:
- # avoid getting a prefix that stops halfway through an encoded
- # character
- prefix = Utils.create_name().decode("utf-8")[:10].encode("utf-8")
- else:
- prefix = Utils.create_name()[:10]
-
+ prefix = Utils.create_name()[:10]
cls.container = cls.account.container(prefix + "-objs")
container_headers = {cls.versions_header_key: 'True'}
if not cls.container.create(hdrs=container_headers):
@@ -2344,7 +2337,7 @@ def _assert_is_manifest(self, file_item, seg_name, version_id=None):
for k_client, k_slo in key_map.items():
self.assertEqual(self.seg_info[seg_name][k_client],
- Utils.encode_if_py2(manifest[0][k_slo]))
+ manifest[0][k_slo])
def _assert_is_object(self, file_item, seg_data, version_id=None):
if version_id:
@@ -2591,13 +2584,7 @@ class TestVersionsLocationWithVersioning(TestObjectVersioningBase):
def setUp(self):
super(TestVersionsLocationWithVersioning, self).setUp()
- if six.PY2:
- # avoid getting a prefix that stops halfway through an encoded
- # character
- prefix = Utils.create_name().decode("utf-8")[:10].encode("utf-8")
- else:
- prefix = Utils.create_name()[:10]
-
+ prefix = Utils.create_name()[:10]
self.versions_container = self.env.account.container(
prefix + "-versions")
if not self.versions_container.create():
@@ -2725,10 +2712,9 @@ def setUp(self):
def tempurl_parms(self, method, expires, path, key):
path = unquote(path)
- if not six.PY2:
- method = method.encode('utf8')
- path = path.encode('utf8')
- key = key.encode('utf8')
+ method = method.encode('utf8')
+ path = path.encode('utf8')
+ key = key.encode('utf8')
sig = hmac.new(
key,
b'%s\n%d\n%s' % (method, expires, path),
@@ -2838,10 +2824,9 @@ def setUp(self):
def tempurl_sig(self, method, expires, path, key):
path = unquote(path)
- if not six.PY2:
- method = method.encode('utf8')
- path = path.encode('utf8')
- key = key.encode('utf8')
+ method = method.encode('utf8')
+ path = path.encode('utf8')
+ key = key.encode('utf8')
return hmac.new(
key,
b'%s\n%d\n%s' % (method, expires, path),
diff --git a/test/functional/test_slo.py b/test/functional/test_slo.py
index 4a040dc011..011ae84488 100644
--- a/test/functional/test_slo.py
+++ b/test/functional/test_slo.py
@@ -22,9 +22,7 @@
from copy import deepcopy
from unittest import SkipTest
-import six
-from six.moves import urllib
-
+import urllib
from swift.common.swob import normalize_etag
from swift.common.utils import md5, config_true_value
@@ -782,10 +780,7 @@ def test_slo_multi_ranged_get(self):
hdrs={"Range": "bytes=1048571-1048580,2097147-2097156"})
# See testMultiRangeGets for explanation
- if six.PY2:
- parser = email.parser.FeedParser()
- else:
- parser = email.parser.BytesFeedParser()
+ parser = email.parser.BytesFeedParser()
parser.feed((
"Content-Type: %s\r\n\r\n" % file_item.content_type).encode())
parser.feed(file_contents)
@@ -1501,8 +1496,6 @@ def test_slo_get_the_manifest_with_details_from_server(self):
value[0]['hash'],
md5(b'd' * 1024 * 1024, usedforsecurity=False).hexdigest())
expected_name = '/%s/seg_d' % self.env.container.name
- if six.PY2:
- expected_name = expected_name.decode("utf-8")
self.assertEqual(value[0]['name'], expected_name)
self.assertEqual(value[1]['bytes'], 1024 * 1024)
@@ -1510,8 +1503,6 @@ def test_slo_get_the_manifest_with_details_from_server(self):
value[1]['hash'],
md5(b'b' * 1024 * 1024, usedforsecurity=False).hexdigest())
expected_name = '/%s/seg_b' % self.env.container.name
- if six.PY2:
- expected_name = expected_name.decode("utf-8")
self.assertEqual(value[1]['name'], expected_name)
def test_slo_get_raw_the_manifest_with_details_from_server(self):
@@ -1537,16 +1528,12 @@ def test_slo_get_raw_the_manifest_with_details_from_server(self):
value[0]['etag'],
md5(b'd' * 1024 * 1024, usedforsecurity=False).hexdigest())
expected_name = '/%s/seg_d' % self.env.container.name
- if six.PY2:
- expected_name = expected_name.decode("utf-8")
self.assertEqual(value[0]['path'], expected_name)
self.assertEqual(value[1]['size_bytes'], 1024 * 1024)
self.assertEqual(
value[1]['etag'],
md5(b'b' * 1024 * 1024, usedforsecurity=False).hexdigest())
expected_name = '/%s/seg_b' % self.env.container.name
- if six.PY2:
- expected_name = expected_name.decode("utf-8")
self.assertEqual(value[1]['path'], expected_name)
file_item = self.env.container.file("manifest-from-get-raw")
diff --git a/test/functional/test_staticweb.py b/test/functional/test_staticweb.py
index b26f98f37f..a98f4ba861 100644
--- a/test/functional/test_staticweb.py
+++ b/test/functional/test_staticweb.py
@@ -16,10 +16,9 @@
import functools
import hashlib
-import six
import time
from unittest import SkipTest
-from six.moves.urllib.parse import unquote
+from urllib.parse import unquote
from swift.common.middleware import tempurl
from swift.common.utils import quote
from swift.common.swob import str_to_wsgi
@@ -223,9 +222,7 @@ def _test_get_path(self, host, path, anonymous=False, expected_status=200,
hdrs={'X-Web-Mode': str(not anonymous), 'Host': host},
cfg={'no_auth_token': anonymous, 'absolute_path': True})
self.assert_status(expected_status)
- body = self.env.account.conn.response.read()
- if not six.PY2:
- body = body.decode('utf8')
+ body = self.env.account.conn.response.read().decode('utf8')
for string in expected_in:
self.assertIn(string, body)
for string in expected_not_in:
@@ -565,9 +562,7 @@ def test_get_root(self):
parms=self.whole_container_parms,
cfg={'no_auth_token': True})
self.assertEqual(status, 200)
- body = self.env.conn.response.read()
- if not six.PY2:
- body = body.decode('utf-8')
+ body = self.env.conn.response.read().decode('utf-8')
self.assertIn('Listing of /v1/', body)
self.assertNotIn('href="..', body)
self.assertIn(self.link('dir/'), body)
@@ -579,9 +574,7 @@ def test_get_dir(self):
parms=self.whole_container_parms,
cfg={'no_auth_token': True})
self.assertEqual(status, 200)
- body = self.env.conn.response.read()
- if not six.PY2:
- body = body.decode('utf-8')
+ body = self.env.conn.response.read().decode('utf-8')
self.assertIn('Listing of /v1/', body)
self.assertIn('href="..', body)
self.assertIn(self.link('dir/obj'), body)
@@ -599,9 +592,7 @@ def test_get_dir_with_iso_expiry(self):
parms=iso_parms,
cfg={'no_auth_token': True})
self.assertEqual(status, 200)
- body = self.env.conn.response.read()
- if not six.PY2:
- body = body.decode('utf-8')
+ body = self.env.conn.response.read().decode('utf-8')
self.assertIn('Listing of /v1/', body)
self.assertIn('href="..', body)
self.assertIn(self.link('dir/obj', iso_parms), body)
@@ -619,9 +610,7 @@ def test_get_limited_dir(self):
self.env.container.path + [self.env.objects['dir/'].name, ''],
parms=parms, cfg={'no_auth_token': True})
self.assertEqual(status, 200)
- body = self.env.conn.response.read()
- if not six.PY2:
- body = body.decode('utf-8')
+ body = self.env.conn.response.read().decode('utf-8')
self.assertIn('Listing of /v1/', body)
self.assertNotIn('href="..', body)
self.assertIn(self.link('dir/obj', parms), body)
@@ -632,9 +621,7 @@ def test_get_limited_dir(self):
self.env.objects['dir/subdir/'].name, ''],
parms=parms, cfg={'no_auth_token': True})
self.assertEqual(status, 200)
- body = self.env.conn.response.read()
- if not six.PY2:
- body = body.decode('utf-8')
+ body = self.env.conn.response.read().decode('utf-8')
self.assertIn('Listing of /v1/', body)
self.assertIn('href="..', body)
self.assertIn(self.link('dir/subdir/obj', parms), body)
diff --git a/test/functional/test_symlink.py b/test/functional/test_symlink.py
index eee6465761..c1c86044be 100755
--- a/test/functional/test_symlink.py
+++ b/test/functional/test_symlink.py
@@ -18,10 +18,9 @@
import unittest
import itertools
import hashlib
-import six
import time
-from six.moves import urllib
+import urllib.parse
from uuid import uuid4
from swift.common.http import is_success
@@ -2293,10 +2292,9 @@ def setUp(self):
def tempurl_parms(self, method, expires, path, key):
path = urllib.parse.unquote(path)
- if not six.PY2:
- method = method.encode('utf8')
- path = path.encode('utf8')
- key = key.encode('utf8')
+ method = method.encode('utf8')
+ path = path.encode('utf8')
+ key = key.encode('utf8')
sig = hmac.new(
key,
b'%s\n%d\n%s' % (method, expires, path),
@@ -2391,10 +2389,9 @@ def setUp(self):
def tempurl_sig(self, method, expires, path, key):
path = urllib.parse.unquote(path)
- if not six.PY2:
- method = method.encode('utf8')
- path = path.encode('utf8')
- key = key.encode('utf8')
+ method = method.encode('utf8')
+ path = path.encode('utf8')
+ key = key.encode('utf8')
return hmac.new(
key,
b'%s\n%d\n%s' % (method, expires, path),
diff --git a/test/functional/test_tempurl.py b/test/functional/test_tempurl.py
index feb36b23a8..d95f6be199 100644
--- a/test/functional/test_tempurl.py
+++ b/test/functional/test_tempurl.py
@@ -20,8 +20,7 @@
import hashlib
import json
from copy import deepcopy
-import six
-from six.moves import urllib
+import urllib.parse
from time import time, strftime, gmtime
from unittest import SkipTest
@@ -36,13 +35,9 @@
def tempurl_parms(method, expires, path, key, digest=None):
path = urllib.parse.unquote(path)
- if not six.PY2:
- method = method.encode('utf8')
- path = path.encode('utf8')
- key = key.encode('utf8')
sig = hmac.new(
- key,
- b'%s\n%d\n%s' % (method, expires, path),
+ key.encode('utf8'),
+ b'%s\n%d\n%s' % (method.encode('utf8'), expires, path.encode('utf8')),
digest or hashlib.sha256).hexdigest()
return {'temp_url_sig': sig, 'temp_url_expires': str(expires)}
@@ -349,10 +344,7 @@ def tempurl_parms(self, method, expires, path, key,
if prefix is None:
# Choose the first 4 chars of object name as prefix.
- if six.PY2:
- prefix = path_parts[4].decode('utf8')[:4].encode('utf8')
- else:
- prefix = path_parts[4][:4]
+ prefix = path_parts[4][:4]
prefix_to_hash = '/'.join(path_parts[0:4]) + '/' + prefix
parms = tempurl_parms(
method, expires,
@@ -490,10 +482,9 @@ def setUp(self):
def tempurl_sig(self, method, expires, path, key):
path = urllib.parse.unquote(path)
- if not six.PY2:
- method = method.encode('utf8')
- path = path.encode('utf8')
- key = key.encode('utf8')
+ method = method.encode('utf8')
+ path = path.encode('utf8')
+ key = key.encode('utf8')
return hmac.new(
key,
b'%s\n%d\n%s' % (method, expires, path),
@@ -757,10 +748,9 @@ def setUp(self):
def tempurl_sig(self, method, expires, path, key):
path = urllib.parse.unquote(path)
- if not six.PY2:
- method = method.encode('utf8')
- path = path.encode('utf8')
- key = key.encode('utf8')
+ method = method.encode('utf8')
+ path = path.encode('utf8')
+ key = key.encode('utf8')
return hmac.new(
key,
b'%s\n%d\n%s' % (method, expires, path),
@@ -815,11 +805,8 @@ def setUp(self):
def get_sig(self, expires, digest, encoding):
path = urllib.parse.unquote(self.env.conn.make_path(self.env.obj.path))
- if six.PY2:
- key = self.env.tempurl_key
- else:
- path = path.encode('utf8')
- key = self.env.tempurl_key.encode('utf8')
+ path = path.encode('utf8')
+ key = self.env.tempurl_key.encode('utf8')
sig = hmac.new(
key,
b'GET\n%d\n%s' % (expires, path),
diff --git a/test/functional/test_versioned_writes.py b/test/functional/test_versioned_writes.py
index 1f8023729d..dd65a83834 100644
--- a/test/functional/test_versioned_writes.py
+++ b/test/functional/test_versioned_writes.py
@@ -18,8 +18,7 @@
import json
import time
import unittest
-import six
-from six.moves.urllib.parse import quote, unquote
+from urllib.parse import quote, unquote
from unittest import SkipTest
import test.functional as tf
@@ -56,13 +55,7 @@ def setUp(cls):
cls.conn2 = Connection(config2)
cls.conn2.authenticate()
- if six.PY2:
- # avoid getting a prefix that stops halfway through an encoded
- # character
- prefix = Utils.create_name().decode("utf-8")[:10].encode("utf-8")
- else:
- prefix = Utils.create_name()[:10]
-
+ prefix = Utils.create_name()[:10]
cls.versions_container = cls.account.container(prefix + "-versions")
if not cls.versions_container.create():
raise ResponseError(cls.conn.response)
@@ -148,13 +141,7 @@ def setUp(cls):
cls.conn2 = Connection(config2)
cls.conn2.authenticate()
- if six.PY2:
- # avoid getting a prefix that stops halfway through an encoded
- # character
- prefix = Utils.create_name().decode("utf-8")[:10].encode("utf-8")
- else:
- prefix = Utils.create_name()[:10]
-
+ prefix = Utils.create_name()[:10]
cls.versions_container = cls.account.container(prefix + "-versions")
if not cls.versions_container.create(
{'X-Storage-Policy': policy['name']}):
@@ -432,7 +419,7 @@ def test_overwriting_with_url_encoded_object_name(self):
def assert_most_recent_version(self, obj_name, content,
should_be_dlo=False):
- name_len = len(obj_name if six.PY2 else obj_name.encode('utf8'))
+ name_len = len(obj_name.encode('utf8'))
archive_versions = self.env.versions_container.files(parms={
'prefix': '%03x%s/' % (name_len, obj_name),
'reverse': 'yes'})
@@ -926,7 +913,7 @@ def test_versioning_dlo(self):
expected = [b'old content', b'112233', b'new content', b'']
- name_len = len(obj_name if six.PY2 else obj_name.encode('utf8'))
+ name_len = len(obj_name.encode('utf8'))
bodies = [
self.env.versions_container.file(f).read()
for f in self.env.versions_container.files(parms={
@@ -1047,12 +1034,8 @@ def _assert_is_manifest(self, file_item, seg_name):
for k_client, k_slo in key_map.items():
self.assertEqual(self.seg_info[seg_name][k_client],
manifest[0][k_slo])
- if six.PY2:
- self.assertEqual(self.seg_info[seg_name]['path'].decode('utf8'),
- manifest[0]['name'])
- else:
- self.assertEqual(self.seg_info[seg_name]['path'],
- manifest[0]['name'])
+ self.assertEqual(self.seg_info[seg_name]['path'],
+ manifest[0]['name'])
def _assert_is_object(self, file_item, seg_data):
file_contents = file_item.read()
diff --git a/test/functional/tests.py b/test/functional/tests.py
index 948647feba..7825a84282 100644
--- a/test/functional/tests.py
+++ b/test/functional/tests.py
@@ -18,8 +18,7 @@
import io
import locale
import random
-import six
-from six.moves import urllib
+import urllib.parse
import time
import unittest
import uuid
@@ -30,10 +29,7 @@
from swift.common.utils import md5
from email.utils import parsedate
-if six.PY2:
- from email.parser import FeedParser
-else:
- from email.parser import BytesFeedParser as FeedParser
+from email.parser import BytesFeedParser as FeedParser
import mock
@@ -53,12 +49,6 @@ def tearDownModule():
class Utils(object):
- @classmethod
- def encode_if_py2(cls, value):
- if six.PY2 and isinstance(value, six.text_type):
- return value.encode('utf8')
- return value
-
@classmethod
def create_ascii_name(cls, length=None):
return uuid.uuid4().hex
@@ -75,9 +65,8 @@ def create_utf8_name(cls, length=None):
u'\u1802\u0901\uF111\uD20F\uB30D\u940B\u850A\u5607'\
u'\u3705\u1803\u0902\uF112\uD210\uB30E\u940C\u850B'\
u'\u5608\u3706\u1804\u0903\u03A9\u2603'
- ustr = u''.join([random.choice(utf8_chars)
+ return u''.join([random.choice(utf8_chars)
for x in range(length)])
- return cls.encode_if_py2(ustr)
create_name = create_ascii_name
@@ -190,11 +179,8 @@ def testNoAuthToken(self):
def testInvalidUTF8Path(self):
valid_utf8 = Utils.create_utf8_name()
- if six.PY2:
- invalid_utf8 = valid_utf8[::-1]
- else:
- invalid_utf8 = (valid_utf8.encode('utf8')[::-1]).decode(
- 'utf-8', 'surrogateescape')
+ invalid_utf8 = (valid_utf8.encode('utf8')[::-1]).decode(
+ 'utf-8', 'surrogateescape')
container = self.env.account.container(invalid_utf8)
self.assertFalse(container.create(cfg={'no_path_quote': True}))
self.assert_status(412)
@@ -778,11 +764,8 @@ def testContainerFileListOnContainerThatDoesNotExist(self):
def testUtf8Container(self):
valid_utf8 = Utils.create_utf8_name()
- if six.PY2:
- invalid_utf8 = valid_utf8[::-1]
- else:
- invalid_utf8 = (valid_utf8.encode('utf8')[::-1]).decode(
- 'utf-8', 'surrogateescape')
+ invalid_utf8 = (valid_utf8.encode('utf8')[::-1]).decode(
+ 'utf-8', 'surrogateescape')
container = self.env.account.container(valid_utf8)
self.assertTrue(container.create(cfg={'no_path_quote': True}))
self.assertIn(container.name, self.env.account.containers())
@@ -804,14 +787,9 @@ def testCreateOnExisting(self):
self.assert_status(202)
def testSlashInName(self):
- if six.PY2:
- cont_name = list(Utils.create_name().decode('utf-8'))
- else:
- cont_name = list(Utils.create_name())
+ cont_name = list(Utils.create_name())
cont_name[random.randint(2, len(cont_name) - 2)] = '/'
cont_name = ''.join(cont_name)
- if six.PY2:
- cont_name = cont_name.encode('utf-8')
cont = self.env.account.container(cont_name)
self.assertFalse(cont.create(cfg={'no_path_quote': True}),
@@ -2031,11 +2009,8 @@ def testMetadataNumberLimit(self):
if len(key) > j:
key = key[:j]
# NB: we'll likely write object metadata that's *not* UTF-8
- if six.PY2:
- val = val[:j]
- else:
- val = val.encode('utf8')[:j].decode(
- 'utf8', 'surrogateescape')
+ val = val.encode('utf8')[:j].decode(
+ 'utf8', 'surrogateescape')
metadata[key] = val
diff --git a/test/probe/brain.py b/test/probe/brain.py
index 64cce6df94..cdd29e1840 100644
--- a/test/probe/brain.py
+++ b/test/probe/brain.py
@@ -20,8 +20,7 @@
from optparse import OptionParser
import random
-import six
-from six.moves.urllib.parse import urlparse, parse_qs, quote
+from urllib.parse import urlparse, parse_qs, quote
from swift.common.manager import Manager
from swift.common import utils, ring
@@ -68,8 +67,7 @@ def command(f):
return f
-@six.add_metaclass(meta_command)
-class BaseBrain(object):
+class BaseBrain(object, metaclass=meta_command):
def _setup(self, account, container_name, object_name,
server_type, policy):
self.account = account
diff --git a/test/probe/common.py b/test/probe/common.py
index e980f99f46..a6120c560b 100644
--- a/test/probe/common.py
+++ b/test/probe/common.py
@@ -29,9 +29,8 @@
import unittest
from uuid import uuid4
import shutil
-import six
-from six.moves.http_client import HTTPConnection
-from six.moves.urllib.parse import urlparse
+from http.client import HTTPConnection
+from urllib.parse import urlparse
from swiftclient import get_auth, head_account, client
from swift.common import internal_client, direct_client, utils
@@ -342,9 +341,6 @@ def __next__(self):
self.hasher.update(rv)
return rv
- # for py2 compat:
- next = __next__
-
def exclude_nodes(nodes, *excludes):
"""
@@ -723,16 +719,9 @@ def direct_get(self, node, part, require_durable=True, extra_headers=None):
if not require_durable:
req_headers.update(
{'X-Backend-Fragment-Preferences': json.dumps([])})
- # node dict has unicode values so utf8 decode our path parts too in
- # case they have non-ascii characters
- if six.PY2:
- acc, con, obj = (s.decode('utf8') for s in (
- self.account, self.container_name, self.object_name))
- else:
- acc, con, obj = self.account, self.container_name, self.object_name
headers, data = direct_client.direct_get_object(
- node, part, acc, con, obj, headers=req_headers,
- resp_chunk_size=64 * 2 ** 20)
+ node, part, self.account, self.container_name, self.object_name,
+ headers=req_headers, resp_chunk_size=64 * 2 ** 20)
hasher = md5(usedforsecurity=False)
for chunk in data:
hasher.update(chunk)
diff --git a/test/probe/test_account_get_fake_responses_match.py b/test/probe/test_account_get_fake_responses_match.py
index a0d58ffd56..5276049fad 100644
--- a/test/probe/test_account_get_fake_responses_match.py
+++ b/test/probe/test_account_get_fake_responses_match.py
@@ -17,8 +17,8 @@
import re
import unittest
-from six.moves import http_client
-from six.moves.urllib.parse import urlparse
+import http.client
+from urllib.parse import urlparse
from swiftclient import get_auth
from test.probe import PROXY_BASE_URL
from test.probe.common import ReplProbeTest
@@ -53,9 +53,9 @@ def _account_request(self, account, method, headers=None):
port = int(port)
if scheme == 'https':
- conn = http_client.HTTPSConnection(host, port)
+ conn = http.client.HTTPSConnection(host, port)
else:
- conn = http_client.HTTPConnection(host, port)
+ conn = http.client.HTTPConnection(host, port)
conn.request(method, self._account_path(account), headers=headers)
resp = conn.getresponse()
if resp.status // 100 != 2:
diff --git a/test/probe/test_container_sync.py b/test/probe/test_container_sync.py
index a6d521b0ec..b5aca19fc8 100644
--- a/test/probe/test_container_sync.py
+++ b/test/probe/test_container_sync.py
@@ -16,7 +16,7 @@
import random
import unittest
-from six.moves.urllib.parse import urlparse
+from urllib.parse import urlparse
from swiftclient import client, ClientException
from swift.common.http import HTTP_NOT_FOUND
diff --git a/test/probe/test_dark_data.py b/test/probe/test_dark_data.py
index e45474c290..dcd6cff53b 100644
--- a/test/probe/test_dark_data.py
+++ b/test/probe/test_dark_data.py
@@ -22,7 +22,7 @@
import shutil
from datetime import datetime
-from six.moves.configparser import ConfigParser
+from configparser import ConfigParser
from test.probe.brain import BrainSplitter
from test.probe.common import ReplProbeTest
diff --git a/test/probe/test_object_async_update.py b/test/probe/test_object_async_update.py
index 6bd404ec4a..b2d71185aa 100644
--- a/test/probe/test_object_async_update.py
+++ b/test/probe/test_object_async_update.py
@@ -30,7 +30,7 @@
from swiftclient import client
from swiftclient.exceptions import ClientException
-from six.moves.configparser import ConfigParser
+from configparser import ConfigParser
from swift.common import direct_client, manager
from swift.common.manager import Manager, Server
from swift.common.swob import normalize_etag
diff --git a/test/probe/test_reconstructor_rebuild.py b/test/probe/test_reconstructor_rebuild.py
index a5e14ea398..d54fe25ae9 100644
--- a/test/probe/test_reconstructor_rebuild.py
+++ b/test/probe/test_reconstructor_rebuild.py
@@ -19,7 +19,6 @@
import uuid
import random
import time
-import six
from swift.common.direct_client import DirectClientException
from swift.common.manager import Manager
@@ -54,9 +53,6 @@ def __next__(self):
self.hasher.update(self.chunk)
return self.chunk
- # for py2 compat
- next = __next__
-
class TestReconstructorRebuild(ECProbeTest):
@@ -526,15 +522,15 @@ def test_rebuild_quarantines_lonely_frag(self):
self.assertEqual([], lines)
-if six.PY2:
- # The non-ASCII chars in metadata cause test hangs in
- # _assert_all_nodes_have_frag because of https://bugs.python.org/issue37093
-
- class TestReconstructorRebuildUTF8(TestReconstructorRebuild):
+class TestReconstructorRebuildUTF8(TestReconstructorRebuild):
- def _make_name(self, prefix):
- return b'%s\xc3\xa8-%s' % (
- prefix.encode(), str(uuid.uuid4()).encode())
+ def _make_name(self, prefix):
+ # The non-ASCII chars in metadata cause test hangs in
+ # _assert_all_nodes_have_frag because of
+ # https://bugs.python.org/issue37093
+ raise unittest.SkipTest('This never got fixed on py3')
+ return b'%s\xc3\xa8-%s' % (
+ prefix.encode(), str(uuid.uuid4()).encode())
if __name__ == "__main__":
diff --git a/test/probe/test_sharder.py b/test/probe/test_sharder.py
index efef292081..d41baf771a 100644
--- a/test/probe/test_sharder.py
+++ b/test/probe/test_sharder.py
@@ -21,8 +21,7 @@
import uuid
from unittest import SkipTest
-import six
-from six.moves.urllib.parse import quote
+from urllib.parse import quote
from swift.common import direct_client, utils
from swift.common.header_key_dict import HeaderKeyDict
@@ -352,8 +351,7 @@ def assert_container_listing(self, expected_listing, req_hdrs=None):
self.assertIn('x-container-object-count', headers)
expected_obj_count = len(expected_listing)
self.assertEqual(expected_listing, [
- x['name'].encode('utf-8') if six.PY2 else x['name']
- for x in actual_listing])
+ x['name'] for x in actual_listing])
self.assertEqual(str(expected_obj_count),
headers['x-container-object-count'])
return headers, actual_listing
@@ -519,8 +517,7 @@ def check_listing(objects, req_hdrs=None, **params):
headers, listing = client.get_container(
self.url, self.token, self.container_name, query_string=qs,
headers=req_hdrs)
- listing = [x['name'].encode('utf-8') if six.PY2 else x['name']
- for x in listing]
+ listing = [x['name'] for x in listing]
if params.get('reverse'):
marker = params.get('marker', ShardRange.MAX)
end_marker = params.get('end_marker', ShardRange.MIN)
@@ -716,9 +713,7 @@ def _make_object_names(self, number, start=0):
obj_names = []
for x in range(start, start + number):
name = (u'obj-\u00e4\u00ea\u00ec\u00f2\u00fb\u1234-%04d' % x)
- name = name.encode('utf8').ljust(name_length, b'o')
- if not six.PY2:
- name = name.decode('utf8')
+ name = name.encode('utf8').ljust(name_length, b'o').decode('utf8')
obj_names.append(name)
return obj_names
@@ -728,9 +723,8 @@ def _setup_container_name(self):
name_length = self.cluster_info['swift']['max_container_name_length']
cont_name = \
self.container_name + u'-\u00e4\u00ea\u00ec\u00f2\u00fb\u1234'
- self.container_name = cont_name.encode('utf8').ljust(name_length, b'x')
- if not six.PY2:
- self.container_name = self.container_name.decode('utf8')
+ self.container_name = cont_name.encode('utf8').ljust(
+ name_length, b'x').decode('utf8')
class TestContainerShardingObjectVersioning(BaseAutoContainerSharding):
@@ -783,8 +777,7 @@ def check_listing(objects, **params):
qs = '&'.join('%s=%s' % param for param in params.items())
headers, listing = client.get_container(
self.url, self.token, self.container_name, query_string=qs)
- listing = [(x['name'].encode('utf-8') if six.PY2 else x['name'],
- x['version_id'])
+ listing = [(x['name'], x['version_id'])
for x in listing]
if params.get('reverse'):
marker = (
@@ -958,8 +951,7 @@ def _test_sharded_listing(self, run_replicators=False):
headers, pre_sharding_listing = client.get_container(
self.url, self.token, self.container_name)
self.assertEqual(obj_names, [
- x['name'].encode('utf-8') if six.PY2 else x['name']
- for x in pre_sharding_listing]) # sanity
+ x['name'] for x in pre_sharding_listing]) # sanity
# Shard it
client.post_container(self.url, self.admin_token, self.container_name,
@@ -1595,9 +1587,7 @@ def test_async_pendings(self):
shard_listings = self.direct_get_container(sr.account,
sr.container)
for node, (hdrs, listing) in shard_listings.items():
- shard_listing_names = [
- o['name'].encode('utf-8') if six.PY2 else o['name']
- for o in listing]
+ shard_listing_names = [o['name'] for o in listing]
for obj in obj_names[4::5]:
if obj in sr:
self.assertIn(obj, shard_listing_names)
@@ -1612,29 +1602,25 @@ def test_async_pendings(self):
start_listing = [
o for o in obj_names if o <= expected_shard_ranges[1].upper]
self.assertEqual(
- [x['name'].encode('utf-8') if six.PY2 else x['name']
- for x in listing[:len(start_listing)]],
+ [x['name'] for x in listing[:len(start_listing)]],
start_listing)
# we can't assert much about the remaining listing, other than that
# there should be something
self.assertTrue(
- [x['name'].encode('utf-8') if six.PY2 else x['name']
- for x in listing[len(start_listing):]])
+ [x['name'] for x in listing[len(start_listing):]])
self.assertIn('x-container-object-count', headers)
self.assertEqual(str(len(listing)),
headers['x-container-object-count'])
headers, listing = client.get_container(self.url, self.token,
self.container_name,
query_string='reverse=on')
- self.assertEqual([x['name'].encode('utf-8') if six.PY2 else x['name']
- for x in listing[-len(start_listing):]],
+ self.assertEqual([x['name'] for x in listing[-len(start_listing):]],
list(reversed(start_listing)))
self.assertIn('x-container-object-count', headers)
self.assertEqual(str(len(listing)),
headers['x-container-object-count'])
self.assertTrue(
- [x['name'].encode('utf-8') if six.PY2 else x['name']
- for x in listing[:-len(start_listing)]])
+ [x['name'] for x in listing[:-len(start_listing)]])
# Run the sharders again to get everything to settle
self.sharders.once()
@@ -1644,8 +1630,7 @@ def test_async_pendings(self):
# now all shards have been cleaved we should get the complete listing
headers, listing = client.get_container(self.url, self.token,
self.container_name)
- self.assertEqual([x['name'].encode('utf-8') if six.PY2 else x['name']
- for x in listing],
+ self.assertEqual([x['name'] for x in listing],
obj_names)
# Create a few more objects in async pending. Check them, they should
@@ -1669,16 +1654,13 @@ def test_async_pendings(self):
# they don't exist yet
headers, listing = client.get_container(self.url, self.token,
self.container_name)
- self.assertEqual([x['name'].encode('utf-8') if six.PY2 else x['name']
- for x in listing],
- obj_names)
+ self.assertEqual([x['name'] for x in listing], obj_names)
# Now clear them out and they should now exist where we expect.
Manager(['object-updater']).once()
headers, listing = client.get_container(self.url, self.token,
self.container_name)
- self.assertEqual([x['name'].encode('utf-8') if six.PY2 else x['name']
- for x in listing],
+ self.assertEqual([x['name'] for x in listing],
obj_names + more_obj_names)
# And they're cleared up
@@ -3202,9 +3184,7 @@ def _make_object_names(self, number, start=0):
obj_names = []
for x in range(start, start + number):
name = (u'obj-\u00e4\u00ea\u00ec\u00f2\u00fb-%04d' % x)
- name = name.encode('utf8').ljust(name_length, b'o')
- if not six.PY2:
- name = name.decode('utf8')
+ name = name.encode('utf8').ljust(name_length, b'o').decode('utf8')
obj_names.append(name)
return obj_names
@@ -3214,9 +3194,8 @@ def _setup_container_name(self):
name_length = self.cluster_info['swift']['max_container_name_length']
cont_name = \
self.container_name + u'-\u00e4\u00ea\u00ec\u00f2\u00fb\u1234'
- self.container_name = cont_name.encode('utf8').ljust(name_length, b'x')
- if not six.PY2:
- self.container_name = self.container_name.decode('utf8')
+ self.container_name = cont_name.encode('utf8').ljust(
+ name_length, b'x').decode('utf8')
class TestManagedContainerSharding(BaseTestContainerSharding):
diff --git a/test/probe/test_signals.py b/test/probe/test_signals.py
index 761c53d2e2..1fd3facee6 100644
--- a/test/probe/test_signals.py
+++ b/test/probe/test_signals.py
@@ -25,8 +25,8 @@
import time
from uuid import uuid4
-from six.moves import http_client as httplib
-from six.moves.urllib.parse import urlparse
+import http.client
+from urllib.parse import urlparse
from swift.common.ring import Ring
from swift.common.manager import Manager
@@ -113,8 +113,8 @@ def assert4xx(self, resp):
def get_conn(self):
scheme, ip, port = self.get_scheme_ip_port()
if scheme == 'https':
- return httplib.HTTPSConnection('%s:%s' % (ip, port))
- return httplib.HTTPConnection('%s:%s' % (ip, port))
+ return http.client.HTTPSConnection('%s:%s' % (ip, port))
+ return http.client.HTTPConnection('%s:%s' % (ip, port))
def _check_reload(self):
conn = self.get_conn()
diff --git a/test/s3api/__init__.py b/test/s3api/__init__.py
index 14ce43166f..8eaa65567e 100644
--- a/test/s3api/__init__.py
+++ b/test/s3api/__init__.py
@@ -21,7 +21,7 @@
import boto3
from botocore.exceptions import ClientError
-from six.moves import urllib
+import urllib.parse
from swift.common.utils import config_true_value, readconf
diff --git a/test/s3api/test_input_errors.py b/test/s3api/test_input_errors.py
index b260e6d564..45938ec602 100644
--- a/test/s3api/test_input_errors.py
+++ b/test/s3api/test_input_errors.py
@@ -21,7 +21,7 @@
import os
import requests
import requests.models
-from six.moves.urllib.parse import urlsplit, urlunsplit, quote
+from urllib.parse import urlsplit, urlunsplit, quote
from swift.common import bufferedhttp
from swift.common.utils import UTC
diff --git a/test/s3api/test_versioning.py b/test/s3api/test_versioning.py
index ec06594fa8..01c242ff45 100644
--- a/test/s3api/test_versioning.py
+++ b/test/s3api/test_versioning.py
@@ -17,7 +17,7 @@
from collections import defaultdict
from botocore.exceptions import ClientError
-import six
+import io
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.utils import md5
@@ -125,7 +125,7 @@ def test_upload_fileobj_versioned(self):
obj_data = self.create_name('some-data').encode('ascii')
obj_etag = md5(obj_data, usedforsecurity=False).hexdigest()
obj_name = self.create_name('versioned-obj')
- self.client.upload_fileobj(six.BytesIO(obj_data),
+ self.client.upload_fileobj(io.BytesIO(obj_data),
self.bucket_name, obj_name)
# object is in the listing
@@ -158,7 +158,7 @@ def test_upload_fileobj_versioned(self):
# overwrite the object
new_obj_data = self.create_name('some-new-data').encode('ascii')
new_obj_etag = md5(new_obj_data, usedforsecurity=False).hexdigest()
- self.client.upload_fileobj(six.BytesIO(new_obj_data),
+ self.client.upload_fileobj(io.BytesIO(new_obj_data),
self.bucket_name, obj_name)
# new object is in the listing
@@ -200,7 +200,7 @@ def test_delete_versioned_objects(self):
for i in range(3):
obj_data = self.create_name('some-data-%s' % i).encode('ascii')
etags.insert(0, md5(obj_data, usedforsecurity=False).hexdigest())
- self.client.upload_fileobj(six.BytesIO(obj_data),
+ self.client.upload_fileobj(io.BytesIO(obj_data),
self.bucket_name, obj_name)
# only one object appears in the listing
@@ -320,7 +320,7 @@ def test_delete_versioned_deletes(self):
for i in range(3):
obj_data = self.create_name('some-data-%s' % i).encode('ascii')
etags.insert(0, md5(obj_data, usedforsecurity=False).hexdigest())
- self.client.upload_fileobj(six.BytesIO(obj_data),
+ self.client.upload_fileobj(io.BytesIO(obj_data),
self.bucket_name, obj_name)
# and make a delete marker
self.client.delete_object(Bucket=self.bucket_name, Key=obj_name)
@@ -492,7 +492,7 @@ def test_get_versioned_object(self):
# TODO: pull etag from response instead
etags.insert(0, md5(obj_data, usedforsecurity=False).hexdigest())
self.client.upload_fileobj(
- six.BytesIO(obj_data), self.bucket_name, obj_name)
+ io.BytesIO(obj_data), self.bucket_name, obj_name)
resp = self.client.list_object_versions(Bucket=self.bucket_name)
objs = resp.get('Versions', [])
@@ -574,13 +574,13 @@ def test_get_versioned_object_key_marker(self):
etags.insert(0, '"%s"' % md5(
obj_data, usedforsecurity=False).hexdigest())
self.client.upload_fileobj(
- six.BytesIO(obj_data), self.bucket_name, obj01_name)
+ io.BytesIO(obj_data), self.bucket_name, obj01_name)
for i in range(3):
obj_data = self.create_name('some-data-%s' % i).encode('ascii')
etags.insert(0, '"%s"' % md5(
obj_data, usedforsecurity=False).hexdigest())
self.client.upload_fileobj(
- six.BytesIO(obj_data), self.bucket_name, obj00_name)
+ io.BytesIO(obj_data), self.bucket_name, obj00_name)
resp = self.client.list_object_versions(Bucket=self.bucket_name)
versions = []
objs = []
@@ -658,7 +658,7 @@ def test_list_objects(self):
etags[obj_name].insert(0, md5(
obj_data, usedforsecurity=False).hexdigest())
self.client.upload_fileobj(
- six.BytesIO(obj_data), self.bucket_name, obj_name)
+ io.BytesIO(obj_data), self.bucket_name, obj_name)
# both unversioned list_objects responses are similar
expected = []
@@ -714,7 +714,7 @@ def test_copy_object(self):
etags.insert(0, md5(
obj_data, usedforsecurity=False).hexdigest())
self.client.upload_fileobj(
- six.BytesIO(obj_data), self.bucket_name, obj_name)
+ io.BytesIO(obj_data), self.bucket_name, obj_name)
resp = self.client.list_object_versions(Bucket=self.bucket_name)
objs = resp.get('Versions', [])
diff --git a/test/unit/__init__.py b/test/unit/__init__.py
index 484f934eed..a8659b6762 100644
--- a/test/unit/__init__.py
+++ b/test/unit/__init__.py
@@ -23,10 +23,7 @@
import sys
from contextlib import contextmanager, closing
from collections import defaultdict
-try:
- from collections.abc import Iterable
-except ImportError:
- from collections import Iterable # py2
+from collections.abc import Iterable
import itertools
from numbers import Number
from tempfile import NamedTemporaryFile
@@ -43,12 +40,8 @@
import xattr
from io import BytesIO
from uuid import uuid4
-
-import six
-import six.moves.cPickle as pickle
-from six.moves import range
-from six.moves.http_client import HTTPException
-from six.moves import configparser
+import pickle
+from http.client import HTTPException
from swift.common import storage_policy, swob, utils, exceptions
from swift.common.memcached import MemcacheConnectionError
@@ -492,8 +485,6 @@ def __next__(self):
self.next_call_count += 1
return next(self.values)
- next = __next__ # py2
-
def close(self):
self.close_call_count += 1
@@ -984,14 +975,9 @@ def connect(*args, **ckwargs):
if 'give_connect' in kwargs:
give_conn_fn = kwargs['give_connect']
- if six.PY2:
- argspec = inspect.getargspec(give_conn_fn)
- if argspec.keywords or 'connection_id' in argspec.args:
- ckwargs['connection_id'] = i
- else:
- argspec = inspect.getfullargspec(give_conn_fn)
- if argspec.varkw or 'connection_id' in argspec.args:
- ckwargs['connection_id'] = i
+ argspec = inspect.getfullargspec(give_conn_fn)
+ if argspec.varkw or 'connection_id' in argspec.args:
+ ckwargs['connection_id'] = i
give_conn_fn(*args, **ckwargs)
etag = next(etag_iter)
headers = next(headers_iter)
@@ -1024,8 +1010,6 @@ def mocked_http_conn(*args, **kwargs):
responses = []
def capture_requests(ip, port, method, path, headers, qs, ssl):
- if six.PY2 and not isinstance(ip, bytes):
- ip = ip.encode('ascii')
req = {
'ip': ip,
'port': port,
@@ -1435,39 +1419,6 @@ def generate_db_path(tempdir, server_type):
'%s-%s.db' % (server_type, uuid4()))
-class ConfigAssertMixin(object):
- """
- Use this with a TestCase to get py2/3 compatible assert for DuplicateOption
- """
- def assertDuplicateOption(self, app_config, option_name, option_value):
- """
- PY3 added a DuplicateOptionError, PY2 didn't seem to care
- """
- if six.PY3:
- self.assertDuplicateOptionError(app_config, option_name)
- else:
- self.assertDuplicateOptionOK(app_config, option_name, option_value)
-
- def assertDuplicateOptionError(self, app_config, option_name):
- with self.assertRaises(
- configparser.DuplicateOptionError) as ctx:
- app_config()
- msg = str(ctx.exception)
- self.assertIn(option_name, msg)
- self.assertIn('already exists', msg)
-
- def assertDuplicateOptionOK(self, app_config, option_name, option_value):
- app = app_config()
- if hasattr(app, 'conf'):
- found_value = app.conf[option_name]
- else:
- if hasattr(app, '_pipeline_final_app'):
- # special case for proxy app!
- app = app._pipeline_final_app
- found_value = getattr(app, option_name)
- self.assertEqual(found_value, option_value)
-
-
class FakeSource(object):
def __init__(self, chunks, headers=None, body=b''):
self.chunks = list(chunks)
@@ -1526,12 +1477,10 @@ def _capture_call(self):
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
self._capture_call()
return next(self.wrapped_iter)
- __next__ = next
-
def __del__(self):
self._capture_call()
diff --git a/test/unit/account/test_backend.py b/test/unit/account/test_backend.py
index 000a45417f..4cfde189c0 100644
--- a/test/unit/account/test_backend.py
+++ b/test/unit/account/test_backend.py
@@ -29,8 +29,6 @@
import base64
import shutil
-import six
-
from swift.account.backend import AccountBroker
from swift.common.utils import Timestamp
from test.unit import patch_policies, with_tempdir, make_timestamp_iter
@@ -190,7 +188,7 @@ def test_batched_reclaim(self):
now = time()
top_of_the_minute = now - (now % 60)
c = itertools.cycle([True, False])
- for m, is_deleted in six.moves.zip(range(num_of_containers), c):
+ for m, is_deleted in zip(range(num_of_containers), c):
offset = top_of_the_minute - (m * 60)
container_specs.append((Timestamp(offset), is_deleted))
random.seed(now)
@@ -847,7 +845,7 @@ def test_chexor(self):
text = '%s-%s' % ('b', "%s-%s-%s-%s" % (
Timestamp(2).internal, Timestamp(0).internal, 0, 0))
hashb = md5(text.encode('ascii'), usedforsecurity=False).digest()
- hashc = ''.join(('%02x' % (ord(a) ^ ord(b) if six.PY2 else a ^ b)
+ hashc = ''.join(('%02x' % (a ^ b)
for a, b in zip(hasha, hashb)))
self.assertEqual(broker.get_info()['hash'], hashc)
broker.put_container('b', Timestamp(3).internal,
@@ -856,7 +854,7 @@ def test_chexor(self):
text = '%s-%s' % ('b', "%s-%s-%s-%s" % (
Timestamp(3).internal, Timestamp(0).internal, 0, 0))
hashb = md5(text.encode('ascii'), usedforsecurity=False).digest()
- hashc = ''.join(('%02x' % (ord(a) ^ ord(b) if six.PY2 else a ^ b)
+ hashc = ''.join(('%02x' % (a ^ b)
for a, b in zip(hasha, hashb)))
self.assertEqual(broker.get_info()['hash'], hashc)
@@ -886,8 +884,6 @@ def test_merge_items(self):
def test_merge_items_overwrite_unicode(self):
snowman = u'\N{SNOWMAN}'
- if six.PY2:
- snowman = snowman.encode('utf-8')
broker1 = AccountBroker(self.get_db_path(), account='a')
broker1.initialize(Timestamp('1').internal, 0)
id1 = broker1.get_info()['id']
diff --git a/test/unit/account/test_server.py b/test/unit/account/test_server.py
index ddb877c150..63ee07fb69 100644
--- a/test/unit/account/test_server.py
+++ b/test/unit/account/test_server.py
@@ -22,11 +22,10 @@
from shutil import rmtree
import itertools
import random
-from io import BytesIO
+from io import BytesIO, StringIO
import json
-from six import StringIO
-from six.moves.urllib.parse import quote
+from urllib.parse import quote
import xml.dom.minidom
from swift import __version__ as swift_version
diff --git a/test/unit/cli/test_container_deleter.py b/test/unit/cli/test_container_deleter.py
index b7819c9dd5..38046f09cd 100644
--- a/test/unit/cli/test_container_deleter.py
+++ b/test/unit/cli/test_container_deleter.py
@@ -14,7 +14,6 @@
import itertools
import json
import mock
-import six
import unittest
from swift.cli import container_deleter
@@ -91,11 +90,6 @@ def test_make_delete_jobs_native_utf8(self):
ucont = cont = u'cont-\N{SNOWMAN}'
uobj1 = obj1 = u'obj-\N{GREEK CAPITAL LETTER ALPHA}'
uobj2 = obj2 = u'/obj-\N{GREEK CAPITAL LETTER OMEGA}'
- if six.PY2:
- acct = acct.encode('utf8')
- cont = cont.encode('utf8')
- obj1 = obj1.encode('utf8')
- obj2 = obj2.encode('utf8')
self.assertEqual(
container_deleter.make_delete_jobs(
acct, cont, [obj1, obj2], utils.Timestamp(ts)),
diff --git a/test/unit/cli/test_form_signature.py b/test/unit/cli/test_form_signature.py
index 944589145b..daeb15fa91 100644
--- a/test/unit/cli/test_form_signature.py
+++ b/test/unit/cli/test_form_signature.py
@@ -14,10 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import io
import hashlib
import hmac
import mock
-import six
import unittest
from swift.cli import form_signature
@@ -26,7 +26,7 @@
class TestFormSignature(unittest.TestCase):
def test_prints_signature(self):
the_time = 1406143563.020043
- key = 'secret squirrel'
+ key = b'secret squirrel'
expires = 3600
path = '/v1/a/c/o'
redirect = 'https://example.com/done.html'
@@ -35,17 +35,11 @@ def test_prints_signature(self):
data = "\n".join((
path, redirect, max_file_size, max_file_count,
- str(int(the_time + expires))))
-
- if six.PY3:
- data = data if isinstance(data, six.binary_type) else \
- data.encode('utf8')
- key = key if isinstance(key, six.binary_type) else \
- key.encode('utf8')
+ str(int(the_time + expires)))).encode('utf8')
expected_signature = hmac.new(key, data, hashlib.sha1).hexdigest()
- out = six.StringIO()
+ out = io.StringIO()
with mock.patch('swift.cli.form_signature.time', lambda: the_time):
with mock.patch('sys.stdout', out):
exitcode = form_signature.main([
@@ -64,7 +58,7 @@ def test_prints_signature(self):
self.assertIn(sig_input, out.getvalue())
def test_too_few_args(self):
- out = six.StringIO()
+ out = io.StringIO()
with mock.patch('sys.stdout', out):
exitcode = form_signature.main([
'/path/to/swift-form-signature',
@@ -75,7 +69,7 @@ def test_too_few_args(self):
self.assertIn(usage, out.getvalue())
def test_invalid_filesize_arg(self):
- out = six.StringIO()
+ out = io.StringIO()
key = 'secret squirrel'
with mock.patch('sys.stdout', out):
exitcode = form_signature.main([
@@ -84,7 +78,7 @@ def test_invalid_filesize_arg(self):
self.assertNotEqual(exitcode, 0)
def test_invalid_filecount_arg(self):
- out = six.StringIO()
+ out = io.StringIO()
key = 'secret squirrel'
with mock.patch('sys.stdout', out):
exitcode = form_signature.main([
@@ -93,7 +87,7 @@ def test_invalid_filecount_arg(self):
self.assertNotEqual(exitcode, 0)
def test_invalid_path_arg(self):
- out = six.StringIO()
+ out = io.StringIO()
key = 'secret squirrel'
with mock.patch('sys.stdout', out):
exitcode = form_signature.main([
@@ -102,7 +96,7 @@ def test_invalid_path_arg(self):
self.assertNotEqual(exitcode, 0)
def test_invalid_seconds_arg(self):
- out = six.StringIO()
+ out = io.StringIO()
key = 'secret squirrel'
with mock.patch('sys.stdout', out):
exitcode = form_signature.main([
diff --git a/test/unit/cli/test_info.py b/test/unit/cli/test_info.py
index a2a17c8647..5899e14bab 100644
--- a/test/unit/cli/test_info.py
+++ b/test/unit/cli/test_info.py
@@ -19,8 +19,7 @@
from shutil import rmtree
from tempfile import mkdtemp
-import six
-from six.moves import cStringIO as StringIO
+from io import StringIO
from test.unit import patch_policies, write_fake_ring, skip_if_no_xattrs
from swift.common import ring, utils
@@ -423,12 +422,8 @@ def test_print_db_info_metadata_with_shard_ranges_bis(self):
out = StringIO()
with mock.patch('sys.stdout', out):
print_db_info_metadata('container', info, {}, verbose=True)
- if six.PY2:
- s_a = '\\xe3\\x82\\xa2'
- s_ya = '\\xe3\\x83\\xa4'
- else:
- s_a = '\u30a2'
- s_ya = '\u30e4'
+ s_a = '\u30a2'
+ s_ya = '\u30e4'
exp_out = '''Path: /acct/cont
Account: acct
Container: cont
diff --git a/test/unit/cli/test_manage_shard_ranges.py b/test/unit/cli/test_manage_shard_ranges.py
index 9efcf2ad2f..05f44e1051 100644
--- a/test/unit/cli/test_manage_shard_ranges.py
+++ b/test/unit/cli/test_manage_shard_ranges.py
@@ -21,8 +21,7 @@
from shutil import rmtree
from tempfile import mkdtemp
-import six
-from six.moves import cStringIO as StringIO
+from io import StringIO
from swift.cli.manage_shard_ranges import main
from swift.common import utils
@@ -660,8 +659,7 @@ def test_info(self):
'}',
'Metadata:',
' X-Container-Sysmeta-Sharding = True']
- # The json.dumps() in py2 produces trailing space, not in py3.
- result = [x.rstrip() for x in out.getvalue().splitlines()]
+ result = [x for x in out.getvalue().splitlines()]
self.assertEqual(expected, result)
self.assertEqual(['Loaded db broker for a/c'],
err.getvalue().splitlines())
@@ -2909,17 +2907,10 @@ def test_subcommand_required(self):
err = StringIO()
with mock.patch('sys.stdout', out), \
mock.patch('sys.stderr', err):
- if six.PY2:
- with self.assertRaises(SystemExit) as cm:
- main(['db file'])
- err_lines = err.getvalue().split('\n')
- self.assertIn('too few arguments', ' '.join(err_lines))
- self.assertEqual(2, cm.exception.code)
- else:
- ret = main(['db file'])
- self.assertEqual(2, ret)
- err_lines = err.getvalue().split('\n')
- self.assertIn('A sub-command is required.', err_lines)
+ ret = main(['db file'])
+ self.assertEqual(2, ret)
+ err_lines = err.getvalue().split('\n')
+ self.assertIn('A sub-command is required.', err_lines)
def test_dry_run_and_yes_is_invalid(self):
out = StringIO()
diff --git a/test/unit/cli/test_recon.py b/test/unit/cli/test_recon.py
index 541bdc0047..c29d2b0b8b 100644
--- a/test/unit/cli/test_recon.py
+++ b/test/unit/cli/test_recon.py
@@ -24,11 +24,10 @@
import shutil
import string
import sys
-import six
from eventlet.green import socket
-from six import StringIO
-from six.moves import urllib
+from io import StringIO
+import urllib
from swift.cli import recon
from swift.common import utils
@@ -37,12 +36,8 @@
from swift.common.storage_policy import StoragePolicy, POLICIES
from test.unit import patch_policies
-if six.PY3:
- from eventlet.green.urllib import request as urllib2
- GREEN_URLLIB_URLOPEN = 'eventlet.green.urllib.request.urlopen'
-else:
- from eventlet.green import urllib2
- GREEN_URLLIB_URLOPEN = 'eventlet.green.urllib2.urlopen'
+from eventlet.green.urllib import request as urllib_request
+GREEN_URLLIB_URLOPEN = 'eventlet.green.urllib.request.urlopen'
class TestHelpers(unittest.TestCase):
@@ -81,21 +76,21 @@ def test_scout_ok(self, mock_urlopen):
@mock.patch(GREEN_URLLIB_URLOPEN)
def test_scout_url_error(self, mock_urlopen):
- mock_urlopen.side_effect = urllib2.URLError("")
+ mock_urlopen.side_effect = urllib_request.URLError("")
url, content, status, ts_start, ts_end = self.scout_instance.scout(
("127.0.0.1", "8080"))
- self.assertIsInstance(content, urllib2.URLError)
+ self.assertIsInstance(content, urllib_request.URLError)
self.assertEqual(url, self.url)
self.assertEqual(status, -1)
@mock.patch(GREEN_URLLIB_URLOPEN)
def test_scout_http_error(self, mock_urlopen):
- mock_urlopen.side_effect = urllib2.HTTPError(
+ mock_urlopen.side_effect = urllib_request.HTTPError(
self.url, 404, "Internal error", None, None)
url, content, status, ts_start, ts_end = self.scout_instance.scout(
("127.0.0.1", "8080"))
self.assertEqual(url, self.url)
- self.assertIsInstance(content, urllib2.HTTPError)
+ self.assertIsInstance(content, urllib_request.HTTPError)
self.assertEqual(status, 404)
@mock.patch(GREEN_URLLIB_URLOPEN)
@@ -121,21 +116,21 @@ def getheader(name):
@mock.patch(GREEN_URLLIB_URLOPEN)
def test_scout_server_type_url_error(self, mock_urlopen):
- mock_urlopen.side_effect = urllib2.URLError("")
+ mock_urlopen.side_effect = urllib_request.URLError("")
url, content, status = self.scout_instance.scout_server_type(
("127.0.0.1", "8080"))
- self.assertIsInstance(content, urllib2.URLError)
+ self.assertIsInstance(content, urllib_request.URLError)
self.assertEqual(url, self.server_type_url)
self.assertEqual(status, -1)
@mock.patch(GREEN_URLLIB_URLOPEN)
def test_scout_server_type_http_error(self, mock_urlopen):
- mock_urlopen.side_effect = urllib2.HTTPError(
+ mock_urlopen.side_effect = urllib_request.HTTPError(
self.server_type_url, 404, "Internal error", None, None)
url, content, status = self.scout_instance.scout_server_type(
("127.0.0.1", "8080"))
self.assertEqual(url, self.server_type_url)
- self.assertIsInstance(content, urllib2.HTTPError)
+ self.assertIsInstance(content, urllib_request.HTTPError)
self.assertEqual(status, 404)
@mock.patch(GREEN_URLLIB_URLOPEN)
@@ -711,7 +706,7 @@ def fake_urlopen(url, timeout):
resp = mock.MagicMock()
resp.read = mock.MagicMock(side_effect=[
- response_body if six.PY2 else response_body.encode('utf8')])
+ response_body.encode('utf8')])
return resp
return mock.patch(GREEN_URLLIB_URLOPEN, fake_urlopen)
@@ -912,18 +907,16 @@ def dummy_request(*args, **kwargs):
mock.call(' 90% 1 **********************************'),
mock.call('Disk usage: space used: 260 of 300'),
mock.call('Disk usage: space free: 40 of 300'),
- mock.call('Disk usage: lowest: 85.0%, ' +
- 'highest: 90.0%%, avg: %s' %
- ('86.6666666667%' if six.PY2 else
- '86.66666666666667%')),
+ mock.call('Disk usage: lowest: 85.0%, '
+ 'highest: 90.0%, avg: 86.66666666666667%'),
mock.call('=' * 79),
]
- with mock.patch('six.moves.builtins.print') as mock_print:
+ with mock.patch('builtins.print') as mock_print:
cli.disk_usage([('127.0.0.1', 6010)])
mock_print.assert_has_calls(default_calls)
- with mock.patch('six.moves.builtins.print') as mock_print:
+ with mock.patch('builtins.print') as mock_print:
expected_calls = default_calls + [
mock.call('LOWEST 5'),
mock.call('85.00% 127.0.0.1 sdc1'),
@@ -933,7 +926,7 @@ def dummy_request(*args, **kwargs):
cli.disk_usage([('127.0.0.1', 6010)], 0, 5)
mock_print.assert_has_calls(expected_calls)
- with mock.patch('six.moves.builtins.print') as mock_print:
+ with mock.patch('builtins.print') as mock_print:
expected_calls = default_calls + [
mock.call('TOP 5'),
mock.call('90.00% 127.0.0.1 sdb1'),
@@ -943,7 +936,7 @@ def dummy_request(*args, **kwargs):
cli.disk_usage([('127.0.0.1', 6010)], 5, 0)
mock_print.assert_has_calls(expected_calls)
- @mock.patch('six.moves.builtins.print')
+ @mock.patch('builtins.print')
@mock.patch('time.time')
def test_replication_check(self, mock_now, mock_print):
now = 1430000000.0
@@ -998,7 +991,7 @@ def dummy_request(*args, **kwargs):
# that is returned from the recon middleware, thus can't rely on it
mock_print.assert_has_calls(default_calls, any_order=True)
- @mock.patch('six.moves.builtins.print')
+ @mock.patch('builtins.print')
@mock.patch('time.time')
def test_sharding_check(self, mock_now, mock_print):
now = 1430000000.0
@@ -1106,7 +1099,7 @@ def dummy_request(*args, **kwargs):
cli.sharding_check([('127.0.0.1', 6011), ('127.0.0.1', 6021)])
mock_print.assert_has_calls(default_calls, any_order=True)
- @mock.patch('six.moves.builtins.print')
+ @mock.patch('builtins.print')
@mock.patch('time.time')
def test_reconstruction_check(self, mock_now, mock_print):
now = 1430000000.0
@@ -1141,7 +1134,7 @@ def dummy_request(*args, **kwargs):
# that is returned from the recon middleware, thus can't rely on it
mock_print.assert_has_calls(default_calls, any_order=True)
- @mock.patch('six.moves.builtins.print')
+ @mock.patch('builtins.print')
@mock.patch('time.time')
def test_load_check(self, mock_now, mock_print):
now = 1430000000.0
@@ -1175,7 +1168,7 @@ def dummy_request(*args, **kwargs):
# that is returned from the recon middleware, thus can't rely on it
mock_print.assert_has_calls(default_calls, any_order=True)
- @mock.patch('six.moves.builtins.print')
+ @mock.patch('builtins.print')
@mock.patch('time.time')
def test_time_check(self, mock_now, mock_print):
now = 1430000000.0
@@ -1207,7 +1200,7 @@ def dummy_request(*args, **kwargs):
# that is returned from the recon middleware, thus can't rely on it
mock_print.assert_has_calls(default_calls, any_order=True)
- @mock.patch('six.moves.builtins.print')
+ @mock.patch('builtins.print')
@mock.patch('time.time')
def test_time_check_mismatch(self, mock_now, mock_print):
now = 1430000000.0
@@ -1243,7 +1236,7 @@ def dummy_request(*args, **kwargs):
# that is returned from the recon middleware, thus can't rely on it
mock_print.assert_has_calls(default_calls, any_order=True)
- @mock.patch('six.moves.builtins.print')
+ @mock.patch('builtins.print')
@mock.patch('time.time')
def test_time_check_jitter(self, mock_now, mock_print):
now = 1430000000.0
@@ -1275,7 +1268,7 @@ def dummy_request(*args, **kwargs):
# that is returned from the recon middleware, thus can't rely on it
mock_print.assert_has_calls(default_calls, any_order=True)
- @mock.patch('six.moves.builtins.print')
+ @mock.patch('builtins.print')
def test_version_check(self, mock_print):
version = "2.7.1.dev144"
@@ -1306,7 +1299,7 @@ def dummy_request(*args, **kwargs):
# that is returned from the recon middleware, thus can't rely on it
mock_print.assert_has_calls(default_calls, any_order=True)
- @mock.patch('six.moves.builtins.print')
+ @mock.patch('builtins.print')
@mock.patch('time.time')
def test_time_check_jitter_mismatch(self, mock_now, mock_print):
now = 1430000000.0
@@ -1344,7 +1337,7 @@ def dummy_request(*args, **kwargs):
# that is returned from the recon middleware, thus can't rely on it
mock_print.assert_has_calls(default_calls, any_order=True)
- @mock.patch('six.moves.builtins.print')
+ @mock.patch('builtins.print')
def test_version_check_differs(self, mock_print):
def dummy_request(*args, **kwargs):
return [
@@ -1373,7 +1366,7 @@ def dummy_request(*args, **kwargs):
# that is returned from the recon middleware, thus can't rely on it
mock_print.assert_has_calls(default_calls, any_order=True)
- @mock.patch('six.moves.builtins.print')
+ @mock.patch('builtins.print')
@mock.patch('swift.cli.recon.SwiftRecon.get_hosts')
def test_multiple_server_types(self, mock_get_hosts, mock_print):
mock_get_hosts.return_value = set([('127.0.0.1', 10000)])
diff --git a/test/unit/cli/test_relinker.py b/test/unit/cli/test_relinker.py
index b6bd7e0e14..9ca18c3316 100644
--- a/test/unit/cli/test_relinker.py
+++ b/test/unit/cli/test_relinker.py
@@ -27,7 +27,7 @@
import unittest
import uuid
-from six.moves import cStringIO as StringIO
+from io import StringIO
from swift.cli import relinker
from swift.common import ring, utils
diff --git a/test/unit/cli/test_reload.py b/test/unit/cli/test_reload.py
index 33fbc15a67..5ccd59391d 100644
--- a/test/unit/cli/test_reload.py
+++ b/test/unit/cli/test_reload.py
@@ -15,11 +15,10 @@
import mock
import signal
-import six
import subprocess
import unittest
-from six.moves import StringIO
+from io import StringIO
from swift.cli import reload
@@ -213,8 +212,5 @@ def test_needs_pid(self):
self.assertEqual(caught.exception.args, (reload.EXIT_BAD_PID,))
msg = 'usage: \nSafely reload WSGI servers'
self.assertEqual(self.mock_stderr.getvalue()[:len(msg)], msg)
- if six.PY2:
- msg = '\n: error: too few arguments\n'
- else:
- msg = '\n: error: the following arguments are required: pid\n'
+ msg = '\n: error: the following arguments are required: pid\n'
self.assertEqual(self.mock_stderr.getvalue()[-len(msg):], msg)
diff --git a/test/unit/cli/test_ring_builder_analyzer.py b/test/unit/cli/test_ring_builder_analyzer.py
index 3b7ca8030d..0d56a8054f 100644
--- a/test/unit/cli/test_ring_builder_analyzer.py
+++ b/test/unit/cli/test_ring_builder_analyzer.py
@@ -17,7 +17,7 @@
import os
import json
import mock
-from six import StringIO
+from io import StringIO
import unittest
from test.unit import with_tempdir
diff --git a/test/unit/cli/test_ringbuilder.py b/test/unit/cli/test_ringbuilder.py
index 11a2d40ae8..00b3b344af 100644
--- a/test/unit/cli/test_ringbuilder.py
+++ b/test/unit/cli/test_ringbuilder.py
@@ -19,7 +19,7 @@
import mock
import os
import re
-import six
+import io
import tempfile
import unittest
import uuid
@@ -44,11 +44,11 @@
class RunSwiftRingBuilderMixin(object):
def run_srb(self, *argv, **kwargs):
- if len(argv) == 1 and isinstance(argv[0], six.string_types):
+ if len(argv) == 1 and isinstance(argv[0], str):
# convert a single string to a list
argv = shlex.split(argv[0])
- mock_stdout = six.StringIO()
- mock_stderr = six.StringIO()
+ mock_stdout = io.StringIO()
+ mock_stderr = io.StringIO()
if 'exp_results' in kwargs:
exp_results = kwargs['exp_results']
@@ -1732,7 +1732,7 @@ def test_validate_composite_builder_file(self):
cb_file = os.path.join(self.tmpdir, 'composite.builder')
cb.save(cb_file)
argv = ["", cb_file, "validate"]
- with mock.patch("sys.stdout", six.StringIO()) as mock_stdout:
+ with mock.patch("sys.stdout", io.StringIO()) as mock_stdout:
self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
lines = mock_stdout.getvalue().strip().split('\n')
self.assertIn("Ring Builder file is invalid", lines[0])
@@ -1742,7 +1742,7 @@ def test_validate_composite_builder_file(self):
def test_validate_empty_file(self):
open(self.tmpfile, 'a').close
argv = ["", self.tmpfile, "validate"]
- with mock.patch("sys.stdout", six.StringIO()) as mock_stdout:
+ with mock.patch("sys.stdout", io.StringIO()) as mock_stdout:
self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
lines = mock_stdout.getvalue().strip().split('\n')
self.assertIn("Ring Builder file is invalid", lines[0])
@@ -1761,7 +1761,7 @@ def test_validate_corrupted_file(self):
# corrupt the file
with open(self.tmpfile, 'wb') as f:
f.write(os.urandom(1024))
- with mock.patch("sys.stdout", six.StringIO()) as mock_stdout:
+ with mock.patch("sys.stdout", io.StringIO()) as mock_stdout:
self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
lines = mock_stdout.getvalue().strip().split('\n')
self.assertIn("Ring Builder file is invalid", lines[0])
@@ -1772,7 +1772,7 @@ def test_validate_corrupted_file(self):
def test_validate_non_existent_file(self):
rand_file = '%s/%s' % (tempfile.gettempdir(), str(uuid.uuid4()))
argv = ["", rand_file, "validate"]
- with mock.patch("sys.stdout", six.StringIO()) as mock_stdout:
+ with mock.patch("sys.stdout", io.StringIO()) as mock_stdout:
self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
lines = mock_stdout.getvalue().strip().split('\n')
self.assertIn("Ring Builder file does not exist", lines[0])
@@ -1785,7 +1785,7 @@ def test_validate_non_accessible_file(self):
RingBuilder, 'load',
mock.Mock(side_effect=exceptions.PermissionError("boom"))):
argv = ["", self.tmpfile, "validate"]
- with mock.patch("sys.stdout", six.StringIO()) as mock_stdout:
+ with mock.patch("sys.stdout", io.StringIO()) as mock_stdout:
self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
lines = mock_stdout.getvalue().strip().split('\n')
self.assertIn("boom", lines[0])
@@ -2100,8 +2100,8 @@ def test_ipv6_output(self):
self.assertOutputStub(out, builder_id=ring.id)
def test_default_show_removed(self):
- mock_stdout = six.StringIO()
- mock_stderr = six.StringIO()
+ mock_stdout = io.StringIO()
+ mock_stderr = io.StringIO()
ring = self.create_sample_ring()
@@ -2146,8 +2146,8 @@ def test_default_show_removed(self):
self.assertEqual(expected, mock_stdout.getvalue())
def test_default_sorted_output(self):
- mock_stdout = six.StringIO()
- mock_stderr = six.StringIO()
+ mock_stdout = io.StringIO()
+ mock_stderr = io.StringIO()
# Create a sample ring and remove/add some devices.
now = time.time()
@@ -2186,8 +2186,8 @@ def test_default_ringfile_check(self):
self.create_sample_ring()
# ring file not created
- mock_stdout = six.StringIO()
- mock_stderr = six.StringIO()
+ mock_stdout = io.StringIO()
+ mock_stderr = io.StringIO()
argv = ["", self.tmpfile]
with mock.patch("sys.stdout", mock_stdout):
with mock.patch("sys.stderr", mock_stderr):
@@ -2199,7 +2199,7 @@ def test_default_ringfile_check(self):
argv = ["", self.tmpfile, "rebalance"]
self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
# ring file is up-to-date
- mock_stdout = six.StringIO()
+ mock_stdout = io.StringIO()
argv = ["", self.tmpfile]
with mock.patch("sys.stdout", mock_stdout):
with mock.patch("sys.stderr", mock_stderr):
@@ -2213,7 +2213,7 @@ def test_default_ringfile_check(self):
argv = ["", self.tmpfile, "set_weight", "0", "--id", "3"]
self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
# ring file is obsolete after set_weight
- mock_stdout = six.StringIO()
+ mock_stdout = io.StringIO()
argv = ["", self.tmpfile]
with mock.patch("sys.stdout", mock_stdout):
with mock.patch("sys.stderr", mock_stderr):
@@ -2225,7 +2225,7 @@ def test_default_ringfile_check(self):
argv = ["", self.tmpfile, "write_ring"]
self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
# ring file up-to-date again
- mock_stdout = six.StringIO()
+ mock_stdout = io.StringIO()
argv = ["", self.tmpfile]
with mock.patch("sys.stdout", mock_stdout):
with mock.patch("sys.stderr", mock_stderr):
@@ -2235,7 +2235,7 @@ def test_default_ringfile_check(self):
# Break ring file e.g. just make it empty
open('%s.ring.gz' % self.tmpfile, 'w').close()
# ring file is invalid
- mock_stdout = six.StringIO()
+ mock_stdout = io.StringIO()
argv = ["", self.tmpfile]
with mock.patch("sys.stdout", mock_stdout):
with mock.patch("sys.stderr", mock_stderr):
@@ -2247,16 +2247,16 @@ def test_default_no_device_ring_without_exception(self):
self.create_sample_ring()
# remove devices from ring file
- mock_stdout = six.StringIO()
- mock_stderr = six.StringIO()
+ mock_stdout = io.StringIO()
+ mock_stderr = io.StringIO()
for device in ["d0", "d1", "d2", "d3"]:
argv = ["", self.tmpfile, "remove", device]
with mock.patch("sys.stdout", mock_stdout):
with mock.patch("sys.stderr", mock_stderr):
self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
# default ring file without exception
- mock_stdout = six.StringIO()
- mock_stderr = six.StringIO()
+ mock_stdout = io.StringIO()
+ mock_stderr = io.StringIO()
argv = ["", self.tmpfile, "default"]
with mock.patch("sys.stdout", mock_stdout):
with mock.patch("sys.stderr", mock_stderr):
@@ -2281,8 +2281,8 @@ def test_empty_ring(self):
self.create_sample_ring(empty=True)
# default ring file without exception
- mock_stdout = six.StringIO()
- mock_stderr = six.StringIO()
+ mock_stdout = io.StringIO()
+ mock_stderr = io.StringIO()
argv = ["", self.tmpfile, "default"]
with mock.patch("sys.stdout", mock_stdout):
with mock.patch("sys.stderr", mock_stderr):
@@ -2515,7 +2515,7 @@ def test_rebalance_min_part_hours_not_passed(self):
ring = RingBuilder.load(self.tmpfile)
last_replica2part2dev = ring._replica2part2dev
- mock_stdout = six.StringIO()
+ mock_stdout = io.StringIO()
argv = ["", self.tmpfile, "rebalance", "3"]
with mock.patch("sys.stdout", mock_stdout):
self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)
@@ -2736,8 +2736,8 @@ def test_dispersion_command_recalculate(self):
self.assertEqual(rb.version, old_version + 1)
def test_use_ringfile_as_builderfile(self):
- mock_stdout = six.StringIO()
- mock_stderr = six.StringIO()
+ mock_stdout = io.StringIO()
+ mock_stderr = io.StringIO()
argv = ["", self.tmpfile, "rebalance", "3"],
self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
@@ -2810,8 +2810,8 @@ def tearDown(self):
pass
def run_srb(self, *argv):
- mock_stdout = six.StringIO()
- mock_stderr = six.StringIO()
+ mock_stdout = io.StringIO()
+ mock_stderr = io.StringIO()
srb_args = ["", self.tempfile] + [str(s) for s in argv]
diff --git a/test/unit/cli/test_ringcomposer.py b/test/unit/cli/test_ringcomposer.py
index 8183f7f89f..5ff7b4d062 100644
--- a/test/unit/cli/test_ringcomposer.py
+++ b/test/unit/cli/test_ringcomposer.py
@@ -10,6 +10,7 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+import io
import json
import os
@@ -17,7 +18,6 @@
import tempfile
import unittest
-import six
from mock import mock
from swift.cli import ringcomposer
@@ -37,8 +37,8 @@ def tearDown(self):
shutil.rmtree(self.tmpdir)
def _run_composer(self, args):
- mock_stdout = six.StringIO()
- mock_stderr = six.StringIO()
+ mock_stdout = io.StringIO()
+ mock_stderr = io.StringIO()
with mock.patch("sys.stdout", mock_stdout):
with mock.patch("sys.stderr", mock_stderr):
with self.assertRaises(SystemExit) as cm:
diff --git a/test/unit/common/middleware/crypto/test_encrypter.py b/test/unit/common/middleware/crypto/test_encrypter.py
index 5d77cdde89..0b95fd4552 100644
--- a/test/unit/common/middleware/crypto/test_encrypter.py
+++ b/test/unit/common/middleware/crypto/test_encrypter.py
@@ -21,7 +21,7 @@
import mock
-from six.moves.urllib import parse as urlparse
+import urllib.parse
from swift.common.middleware.crypto import encrypter
from swift.common.middleware.crypto.crypto_utils import (
CRYPTO_KEY_CALLBACK, Crypto)
@@ -53,7 +53,7 @@ def _verify_user_metadata(self, req_hdrs, name, value, key):
param = param.strip()
self.assertTrue(param.startswith('swift_meta='))
actual_meta = json.loads(
- urlparse.unquote_plus(param[len('swift_meta='):]))
+ urllib.parse.unquote_plus(param[len('swift_meta='):]))
self.assertEqual(Crypto.cipher, actual_meta['cipher'])
meta_iv = base64.b64decode(actual_meta['iv'])
self.assertEqual(FAKE_IV, meta_iv)
@@ -62,7 +62,7 @@ def _verify_user_metadata(self, req_hdrs, name, value, key):
wsgi_to_bytes(enc_val))
# if there is any encrypted user metadata then this header should exist
self.assertIn('X-Object-Transient-Sysmeta-Crypto-Meta', req_hdrs)
- common_meta = json.loads(urlparse.unquote_plus(
+ common_meta = json.loads(urllib.parse.unquote_plus(
req_hdrs['X-Object-Transient-Sysmeta-Crypto-Meta']))
self.assertDictEqual({'cipher': Crypto.cipher,
'key_id': {'v': 'fake', 'path': '/a/c/fake'}},
@@ -102,7 +102,7 @@ def test_PUT_req(self):
# verify body crypto meta
actual = req_hdrs['X-Object-Sysmeta-Crypto-Body-Meta']
- actual = json.loads(urlparse.unquote_plus(actual))
+ actual = json.loads(urllib.parse.unquote_plus(actual))
self.assertEqual(Crypto().cipher, actual['cipher'])
self.assertEqual(FAKE_IV, base64.b64decode(actual['iv']))
@@ -121,7 +121,7 @@ def test_PUT_req(self):
req_hdrs['X-Object-Sysmeta-Crypto-Etag'].partition('; swift_meta=')
# verify crypto_meta was appended to this etag
self.assertTrue(etag_meta)
- actual_meta = json.loads(urlparse.unquote_plus(etag_meta))
+ actual_meta = json.loads(urllib.parse.unquote_plus(etag_meta))
self.assertEqual(Crypto().cipher, actual_meta['cipher'])
# verify encrypted version of plaintext etag
@@ -151,7 +151,7 @@ def test_PUT_req(self):
crypto_meta_tag = 'swift_meta='
self.assertTrue(param.startswith(crypto_meta_tag), param)
actual_meta = json.loads(
- urlparse.unquote_plus(param[len(crypto_meta_tag):]))
+ urllib.parse.unquote_plus(param[len(crypto_meta_tag):]))
self.assertEqual(Crypto().cipher, actual_meta['cipher'])
self.assertEqual(fetch_crypto_keys()['id'], actual_meta['key_id'])
@@ -282,7 +282,7 @@ def _test_PUT_with_other_footers(self, override_etag):
encrypted_etag, _junk, etag_meta = \
req_hdrs['X-Object-Sysmeta-Crypto-Etag'].partition('; swift_meta=')
self.assertTrue(etag_meta)
- actual_meta = json.loads(urlparse.unquote_plus(etag_meta))
+ actual_meta = json.loads(urllib.parse.unquote_plus(etag_meta))
self.assertEqual(Crypto().cipher, actual_meta['cipher'])
self.assertEqual(ciphertext_etag, req_hdrs['Etag'])
@@ -303,7 +303,7 @@ def _test_PUT_with_other_footers(self, override_etag):
crypto_meta_tag = 'swift_meta='
self.assertTrue(param.startswith(crypto_meta_tag), param)
actual_meta = json.loads(
- urlparse.unquote_plus(param[len(crypto_meta_tag):]))
+ urllib.parse.unquote_plus(param[len(crypto_meta_tag):]))
self.assertEqual(Crypto().cipher, actual_meta['cipher'])
cont_key = fetch_crypto_keys()['container']
@@ -315,7 +315,7 @@ def _test_PUT_with_other_footers(self, override_etag):
# verify body crypto meta
actual = req_hdrs['X-Object-Sysmeta-Crypto-Body-Meta']
- actual = json.loads(urlparse.unquote_plus(actual))
+ actual = json.loads(urllib.parse.unquote_plus(actual))
self.assertEqual(Crypto().cipher, actual['cipher'])
self.assertEqual(FAKE_IV, base64.b64decode(actual['iv']))
@@ -374,7 +374,7 @@ def _test_PUT_with_etag_override_in_headers(self, override_etag):
crypto_meta_tag = 'swift_meta='
self.assertTrue(param.startswith(crypto_meta_tag), param)
actual_meta = json.loads(
- urlparse.unquote_plus(param[len(crypto_meta_tag):]))
+ urllib.parse.unquote_plus(param[len(crypto_meta_tag):]))
self.assertEqual(Crypto().cipher, actual_meta['cipher'])
self.assertEqual(fetch_crypto_keys()['id'], actual_meta['key_id'])
@@ -569,7 +569,7 @@ def __call__(self, env, start_response):
crypto_meta_tag = 'swift_meta='
self.assertTrue(param.startswith(crypto_meta_tag), param)
actual_meta = json.loads(
- urlparse.unquote_plus(param[len(crypto_meta_tag):]))
+ urllib.parse.unquote_plus(param[len(crypto_meta_tag):]))
self.assertEqual(Crypto().cipher, actual_meta['cipher'])
self.assertEqual(fetch_crypto_keys()['id'], actual_meta['key_id'])
diff --git a/test/unit/common/middleware/crypto/test_keymaster.py b/test/unit/common/middleware/crypto/test_keymaster.py
index 882f88b550..54db3db266 100644
--- a/test/unit/common/middleware/crypto/test_keymaster.py
+++ b/test/unit/common/middleware/crypto/test_keymaster.py
@@ -20,7 +20,6 @@
import os
import mock
-import six
import unittest
from getpass import getuser
@@ -147,10 +146,7 @@ def verify_keys_for_path(self, wsgi_path, expected_keys, key_id=None):
self.assertIn('id', keys)
id = keys.pop('id')
path = swob.wsgi_to_str(wsgi_path)
- if six.PY2:
- self.assertEqual(path, id['path'])
- else:
- self.assertEqual(swob.str_to_wsgi(path), id['path'])
+ self.assertEqual(swob.str_to_wsgi(path), id['path'])
self.assertEqual('2', id['v'])
keys.pop('all_ids')
self.assertListEqual(sorted(expected_keys), sorted(keys.keys()),
@@ -189,10 +185,7 @@ def verify_v1_keys_for_path(self, wsgi_path, expected_keys, key_id=None):
path = swob.wsgi_to_str(wsgi_path)
if '//' in path:
path = path[path.index('//') + 1:]
- if six.PY2:
- self.assertEqual(path, id['path'])
- else:
- self.assertEqual(swob.str_to_wsgi(path), id['path'])
+ self.assertEqual(swob.str_to_wsgi(path), id['path'])
self.assertEqual('1', id['v'])
keys.pop('all_ids')
self.assertListEqual(sorted(expected_keys), sorted(keys.keys()),
@@ -686,30 +679,20 @@ def mock_create_key(path, secret_id=None):
container = u'\N{SNOWMAN}'
obj = u'\N{SNOWFLAKE}'
- if six.PY2:
- container = container.encode('utf-8')
- obj = obj.encode('utf-8')
good_con_path = '/a/%s' % container
good_path = '/a/%s/%s' % (container, obj)
- if six.PY2:
- mangled_con_path = ('/a/%s' % container).decode(
- 'latin-1').encode('utf-8')
- mangled_path = ('/a/%s/%s' % (
- container, obj)).decode('latin-1').encode('utf-8')
- else:
- mangled_con_path = ('/a/%s' % container).encode(
- 'utf-8').decode('latin-1')
- mangled_path = ('/a/%s/%s' % (
- container, obj)).encode('utf-8').decode('latin-1')
+ mangled_con_path = ('/a/%s' % container).encode(
+ 'utf-8').decode('latin-1')
+ mangled_path = ('/a/%s/%s' % (
+ container, obj)).encode('utf-8').decode('latin-1')
context = keymaster.KeyMasterContext(self.app, 'a', container, obj)
for version in ('1', '2', '3'):
with mock.patch.object(self.app, 'create_key', mock_create_key):
keys = context.fetch_crypto_keys(key_id={
'v': version, 'path': good_path})
- key_id_path = (good_path if version == '3' or six.PY2
- else mangled_path)
+ key_id_path = (good_path if version == '3' else mangled_path)
expected_keys = {
'container': hmac.new(secrets[None], b'/a/\xe2\x98\x83',
digestmod=hashlib.sha256).digest(),
@@ -729,7 +712,7 @@ def mock_create_key(path, secret_id=None):
with mock.patch.object(self.app, 'create_key', mock_create_key):
keys = context.fetch_crypto_keys(key_id={
'v': version, 'path': mangled_path})
- key_id_path = (good_path if six.PY2 else mangled_path)
+ key_id_path = mangled_path
expected_keys = {
'container': hmac.new(secrets[None], b'/a/\xe2\x98\x83',
digestmod=hashlib.sha256).digest(),
diff --git a/test/unit/common/middleware/helpers.py b/test/unit/common/middleware/helpers.py
index a3f77395ae..58e391420c 100644
--- a/test/unit/common/middleware/helpers.py
+++ b/test/unit/common/middleware/helpers.py
@@ -16,7 +16,7 @@
# This stuff can't live in test/unit/__init__.py due to its swob dependency.
from collections import defaultdict, namedtuple
-from six.moves.urllib import parse
+from urllib import parse
from swift.common import swob
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.request_helpers import is_user_meta, \
@@ -49,8 +49,6 @@ def __next__(self):
self.mark_read(self.key)
raise
- next = __next__ # for py2
-
def close(self):
self.mark_closed(self.key)
diff --git a/test/unit/common/middleware/s3api/test_bucket.py b/test/unit/common/middleware/s3api/test_bucket.py
index 3385aa9357..2534d8d363 100644
--- a/test/unit/common/middleware/s3api/test_bucket.py
+++ b/test/unit/common/middleware/s3api/test_bucket.py
@@ -17,8 +17,7 @@
import mock
from hashlib import sha256
-import six
-from six.moves.urllib.parse import quote, parse_qsl
+from urllib.parse import quote, parse_qsl
from swift.common import swob
from swift.common.middleware.proxy_logging import ProxyLoggingMiddleware
@@ -535,7 +534,7 @@ def test_bucket_GET(self):
self.assertEqual('2011-01-05T02:19:15.000Z',
o.find('./LastModified').text)
expected = [
- (i[0].encode('utf-8') if six.PY2 else i[0],
+ (i[0],
PFS_ETAG if i[0] == 'pfs-obj' else
'"0-N"' if i[0] == 'slo' else '"0"')
for i in self.objects
@@ -646,12 +645,8 @@ def test_bucket_GET_is_truncated(self):
status, headers, body = self.call_s3api(req)
elem = fromstring(body, 'ListBucketResult')
self.assertEqual(elem.find('./IsTruncated').text, 'true')
- if six.PY2:
- self.assertEqual(elem.find('./NextMarker').text,
- u'but-\u062a/'.encode('utf-8'))
- else:
- self.assertEqual(elem.find('./NextMarker').text,
- u'but-\u062a/')
+ self.assertEqual(elem.find('./NextMarker').text,
+ u'but-\u062a/')
def test_bucket_GET_is_truncated_url_encoded(self):
bucket_name = 'junk'
@@ -1023,10 +1018,7 @@ def test_bucket_GET_with_versions_versioning_not_configured(self):
self.assertEqual(elem.findall('./DeleteMarker'), [])
versions = elem.findall('./Version')
objects = list(self.objects)
- if six.PY2:
- expected = [v[0].encode('utf-8') for v in objects]
- else:
- expected = [v[0] for v in objects]
+ expected = [v[0] for v in objects]
self.assertEqual([v.find('./Key').text for v in versions], expected)
self.assertEqual([v.find('./IsLatest').text for v in versions],
['true' for v in objects])
@@ -1067,8 +1059,6 @@ def test_bucket_GET_with_versions(self):
expected = []
for o in self.objects_list:
name = o['name']
- if six.PY2:
- name = name.encode('utf8')
expected.append((name, 'true', 'null'))
if name == 'rose':
expected.append((name, 'false', '1'))
@@ -1097,8 +1087,6 @@ def test_bucket_GET_with_versions_with_max_keys(self):
expected = []
for o in self.objects_list[:5]:
name = o['name']
- if six.PY2:
- name = name.encode('utf8')
expected.append((name, 'true', 'null'))
if name == 'rose':
expected.append((name, 'false', '1'))
@@ -1265,7 +1253,7 @@ def test_bucket_GET_versions_with_version_id_marker(self):
self.assertEqual(expected, discovered)
expected = [
('lily', 'true', 'null'),
- (b'lily-\xd8\xaa', 'true', 'null'),
+ ('lily-\u062a', 'true', 'null'),
('mu', 'true', 'null'),
('pfs-obj', 'true', 'null'),
('rose', 'true', 'null'),
@@ -1275,10 +1263,6 @@ def test_bucket_GET_versions_with_version_id_marker(self):
('with space', 'true', 'null'),
('with%20space', 'true', 'null'),
]
- if not six.PY2:
- item = list(expected[1])
- item[0] = item[0].decode('utf8')
- expected[1] = tuple(item)
discovered = [
tuple(e.find('./%s' % key).text for key in (
diff --git a/test/unit/common/middleware/s3api/test_etree.py b/test/unit/common/middleware/s3api/test_etree.py
index dd8e9f80ee..fea608e35b 100644
--- a/test/unit/common/middleware/s3api/test_etree.py
+++ b/test/unit/common/middleware/s3api/test_etree.py
@@ -15,8 +15,6 @@
import unittest
-import six
-
from swift.common.middleware.s3api import etree
@@ -67,10 +65,7 @@ def test_fromstring_with_nonascii_text(self):
b'The " - b"server is currently unavailable. Please try again at a " - b"later time.
'") - else: - last_line = ( - b":ERROR: 503 b'The " - b"server is currently unavailable. Please try again at a " - b"later time.
'") + last_line = ( + b":ERROR: 503 b'The " + b"server is currently unavailable. Please try again at a " + b"later time.
'") self.assertEqual( self.body_lines(resp.body), [last_line]) @@ -353,7 +344,7 @@ def _concurrent_ssync(path1, path2): body_lines1 = [] body_lines2 = [] - for chunk1, chunk2 in six.moves.zip_longest(rcvr1(), rcvr2()): + for chunk1, chunk2 in itertools.zip_longest(rcvr1(), rcvr2()): if chunk1 and chunk1.strip(): body_lines1.append(chunk1.strip()) if chunk2 and chunk2.strip(): @@ -1586,12 +1577,8 @@ def _DELETE(request): 'DELETE /a/c/o\r\n\r\n' 'DELETE /a/c/o\r\n\r\n') resp = req.get_response(self.controller) - if six.PY2: - final_line = (b":ERROR: 500 'ERROR: With :UPDATES: " - b"3 failures to 0 successes'") - else: - final_line = (b":ERROR: 500 b'ERROR: With :UPDATES: " - b"3 failures to 0 successes'") + final_line = (b":ERROR: 500 b'ERROR: With :UPDATES: " + b"3 failures to 0 successes'") self.assertEqual( self.body_lines(resp.body), [b':MISSING_CHECK: START', b':MISSING_CHECK: END', final_line]) @@ -1650,12 +1637,8 @@ def _DELETE(request): 'DELETE /a/c/o\r\n\r\n' ':UPDATES: END\r\n') resp = req.get_response(self.controller) - if six.PY2: - final_line = (b":ERROR: 500 'ERROR: With :UPDATES: " - b"4 failures to 3 successes'") - else: - final_line = (b":ERROR: 500 b'ERROR: With :UPDATES: " - b"4 failures to 3 successes'") + final_line = (b":ERROR: 500 b'ERROR: With :UPDATES: " + b"4 failures to 3 successes'") self.assertEqual( self.body_lines(resp.body), [b':MISSING_CHECK: START', b':MISSING_CHECK: END', @@ -2254,12 +2237,8 @@ def readline(self, hint=-1): '1') req.environ['wsgi.input'] = _IgnoreReadlineHint(req.body) resp = req.get_response(self.controller) - if six.PY2: - final_line = (b":ERROR: 500 'ERROR: With :UPDATES: " - b"2 failures to 0 successes'") - else: - final_line = (b":ERROR: 500 b'ERROR: With :UPDATES: " - b"2 failures to 0 successes'") + final_line = (b":ERROR: 500 b'ERROR: With :UPDATES: " + b"2 failures to 0 successes'") self.assertEqual( self.body_lines(resp.body), [b':MISSING_CHECK: START', b':MISSING_CHECK: END', final_line]) @@ -2354,7 +2333,7 @@ def test_SSYNC_disconnect(self): swob.HTTPInternalServerError() success, _ = sender() self.assertFalse(success) - stderr = six.StringIO() + stderr = io.StringIO() with mock.patch('sys.stderr', stderr): # let gc and eventlet spin a bit del sender diff --git a/test/unit/obj/test_ssync_sender.py b/test/unit/obj/test_ssync_sender.py index 2de393a4d1..f15c2f6e98 100644 --- a/test/unit/obj/test_ssync_sender.py +++ b/test/unit/obj/test_ssync_sender.py @@ -19,7 +19,7 @@ import eventlet import mock -import six +import urllib.parse from swift.common import exceptions, utils from swift.common.storage_policy import POLICIES @@ -59,8 +59,7 @@ class FakeResponse(ssync_sender.SsyncBufferedHTTPResponse): def __init__(self, chunk_body='', headers=None): self.status = 200 self.close_called = False - if not six.PY2: - chunk_body = chunk_body.encode('ascii') + chunk_body = chunk_body.encode('ascii') if chunk_body: self.fp = io.BytesIO( b'%x\r\n%s\r\n0\r\n\r\n' % (len(chunk_body), chunk_body)) @@ -1706,11 +1705,11 @@ def _check_send_put(self, obj_name, meta_value, extra_metadata=extra_metadata, commit=durable) expected = dict(df.get_metadata()) - expected['body'] = body if six.PY2 else body.decode('ascii') + expected['body'] = body.decode('ascii') expected['chunk_size'] = len(body) expected['meta'] = meta_value expected['meta_name'] = meta_name - path = six.moves.urllib.parse.quote(expected['name']) + path = urllib.parse.quote(expected['name']) expected['path'] = path no_commit = '' if durable else 'X-Backend-No-Commit: True\r\n' expected['no_commit'] = no_commit @@ -1773,7 +1772,7 @@ def _check_send_post(self, obj_name, meta_value): # Note that diskfile expects obj_name to be a native string # but metadata to be wsgi strings df.write_metadata(newer_metadata) - path = six.moves.urllib.parse.quote(df.read_metadata()['name']) + path = urllib.parse.quote(df.read_metadata()['name']) wire_meta = wsgi_to_bytes(meta_value) length = format(61 + len(path) + len(wire_meta), 'x') diff --git a/test/unit/obj/test_updater.py b/test/unit/obj/test_updater.py index c4bea6a352..e9a10c346f 100644 --- a/test/unit/obj/test_updater.py +++ b/test/unit/obj/test_updater.py @@ -13,8 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. import eventlet -import six.moves.cPickle as pickle -from six.moves.queue import PriorityQueue +import pickle +from queue import PriorityQueue import mock import os import unittest diff --git a/test/unit/proxy/controllers/test_base.py b/test/unit/proxy/controllers/test_base.py index f168996219..a3ad0c29e4 100644 --- a/test/unit/proxy/controllers/test_base.py +++ b/test/unit/proxy/controllers/test_base.py @@ -21,8 +21,6 @@ import unittest import mock -import six - from swift.proxy import server as proxy_server from swift.proxy.controllers.base import headers_to_container_info, \ headers_to_account_info, headers_to_object_info, get_container_info, \ @@ -585,8 +583,6 @@ def test_get_container_info_no_cache(self): self.assertEqual(resp['bytes'], 6666) self.assertEqual(resp['object_count'], 1000) expected = u'\U0001F334' - if six.PY2: - expected = expected.encode('utf8') self.assertEqual(resp['versions'], expected) def test_get_container_info_no_account(self): @@ -659,8 +655,6 @@ def test_get_container_info_cache(self): self.assertEqual(resp['object_count'], 10) self.assertEqual(resp['status'], 404) expected = u'\U0001F4A9' - if six.PY2: - expected = expected.encode('utf8') self.assertEqual(resp['versions'], expected) for subdict in resp.values(): @@ -702,8 +696,6 @@ def test_get_container_info_only_lookup_cache(self): self.assertEqual(resp['object_count'], 10) self.assertEqual(resp['status'], 404) expected = u'\U0001F4A9' - if six.PY2: - expected = expected.encode('utf8') self.assertEqual(resp['versions'], expected) for subdict in resp.values(): if isinstance(subdict, dict): @@ -726,8 +718,6 @@ def test_get_cache_key(self): # Expected result should always be native string expected = u'container/\N{SNOWMAN}/\U0001F334' - if six.PY2: - expected = expected.encode('utf8') self.assertEqual(get_cache_key(u"\N{SNOWMAN}", u"\U0001F334"), expected) @@ -1724,7 +1714,7 @@ def mock_find_source(): resp = handler.get_working_response() resp.app_iter.close() # verify that iter exited - self.assertEqual({1: ['next', 'close', '__del__']}, + self.assertEqual({1: ['__next__', 'close', '__del__']}, factory.captured_calls) self.assertEqual(["Client disconnected on read of 'some-path'"], self.logger.get_lines_for_level('info')) @@ -1742,7 +1732,7 @@ def mock_find_source(): resp = handler.get_working_response() next(resp.app_iter) resp.app_iter.close() - self.assertEqual({1: ['next', 'close', '__del__']}, + self.assertEqual({1: ['__next__', 'close', '__del__']}, factory.captured_calls) self.assertEqual([], self.logger.get_lines_for_level('warning')) self.assertEqual([], self.logger.get_lines_for_level('info')) diff --git a/test/unit/proxy/controllers/test_container.py b/test/unit/proxy/controllers/test_container.py index b94c6f4804..74b4f18e9f 100644 --- a/test/unit/proxy/controllers/test_container.py +++ b/test/unit/proxy/controllers/test_container.py @@ -19,12 +19,8 @@ import unittest from eventlet import Timeout -import six -from six.moves import urllib -if six.PY2: - from itertools import izip_longest as zip_longest -else: - from itertools import zip_longest +import urllib.parse +from itertools import zip_longest from swift.common.constraints import CONTAINER_LISTING_LIMIT from swift.common.swob import Request, bytes_to_wsgi, str_to_wsgi, wsgi_quote @@ -537,18 +533,12 @@ def _make_shard_resp_hdrs(self, sr_objs, extra_hdrs=None): return hdrs def _make_shard_objects(self, shard_range): - if six.PY2: - lower = ord(shard_range.lower.decode('utf8')[0] - if shard_range.lower else '@') - upper = ord(shard_range.upper.decode('utf8')[0] - if shard_range.upper else u'\U0001ffff') - else: - lower = ord(shard_range.lower[0] if shard_range.lower else '@') - upper = ord(shard_range.upper[0] if shard_range.upper - else '\U0001ffff') + lower = ord(shard_range.lower[0] if shard_range.lower else '@') + upper = ord(shard_range.upper[0] if shard_range.upper + else '\U0001ffff') - objects = [{'name': six.unichr(i), 'bytes': i, - 'hash': 'hash%s' % six.unichr(i), + objects = [{'name': chr(i), 'bytes': i, + 'hash': 'hash%s' % chr(i), 'content_type': 'text/plain', 'deleted': 0, 'last_modified': next(self.ts_iter).isoformat} for i in range(lower + 1, upper + 1)][:1024] @@ -603,11 +593,8 @@ def name(obj): with annotate_failure('Request check at index %d.' % i): # strip off /sdx/0/ from path self.assertEqual(exp_path, req['path'][7:]) - if six.PY2: - got_params = dict(urllib.parse.parse_qsl(req['qs'], True)) - else: - got_params = dict(urllib.parse.parse_qsl( - req['qs'], True, encoding='latin1')) + got_params = dict(urllib.parse.parse_qsl( + req['qs'], True, encoding='latin1')) self.assertEqual(dict(exp_params, format='json'), got_params) for k, v in exp_headers.items(): self.assertIn(k, req['headers']) @@ -3126,12 +3113,8 @@ def _check_backend_req(self, req, backend_req, extra_params=None, expected_params = {'states': 'listing', 'format': 'json'} if extra_params: expected_params.update(extra_params) - if six.PY2: - backend_params = dict(urllib.parse.parse_qsl( - backend_req['qs'], True)) - else: - backend_params = dict(urllib.parse.parse_qsl( - backend_req['qs'], True, encoding='latin1')) + backend_params = dict(urllib.parse.parse_qsl( + backend_req['qs'], True, encoding='latin1')) self.assertEqual(expected_params, backend_params) backend_hdrs = backend_req['headers'] diff --git a/test/unit/proxy/controllers/test_obj.py b/test/unit/proxy/controllers/test_obj.py index da76d907b4..f434a96c3a 100644 --- a/test/unit/proxy/controllers/test_obj.py +++ b/test/unit/proxy/controllers/test_obj.py @@ -29,14 +29,9 @@ from eventlet import Timeout, sleep from eventlet.queue import Empty -import six -from six import StringIO -from six.moves import range -from six.moves.urllib.parse import quote, parse_qsl -if six.PY2: - from email.parser import FeedParser as EmailFeedParser -else: - from email.parser import BytesFeedParser as EmailFeedParser +from io import StringIO +from urllib.parse import quote, parse_qsl +from email.parser import BytesFeedParser as EmailFeedParser import swift from swift.common import utils, swob, exceptions @@ -1814,35 +1809,23 @@ def do_test(statuses): req, log_lines = do_test((201, (100, Exception('boom')), 201)) self.assertIn('ERROR with Object server', log_lines[0]) - if six.PY3: - self.assertIn(req.path, log_lines[0]) - else: - self.assertIn(req.path.decode('utf-8'), log_lines[0]) + self.assertIn(req.path, log_lines[0]) self.assertIn('Trying to get final status of PUT', log_lines[0]) req, log_lines = do_test((201, (100, Timeout()), 201)) self.assertIn('ERROR with Object server', log_lines[0]) - if six.PY3: - self.assertIn(req.path, log_lines[0]) - else: - self.assertIn(req.path.decode('utf-8'), log_lines[0]) + self.assertIn(req.path, log_lines[0]) self.assertIn('Trying to get final status of PUT', log_lines[0]) req, log_lines = do_test((201, (100, 507), 201)) self.assertIn('ERROR Insufficient Storage', log_lines[0]) req, log_lines = do_test((201, (100, 500), 201)) - if six.PY3: - # We allow the b'' in logs because we want to see bad characters. - self.assertIn( - "ERROR 500 b'' Trying to PUT /v1/AUTH_kilroy/%ED%88%8E/" - "%E9%90%89 From Object Server", log_lines[0]) - self.assertIn(req.path, log_lines[0]) - else: - self.assertIn( - 'ERROR 500 Trying to PUT /v1/AUTH_kilroy/%ED%88%8E/%E9%90%89 ' - 'From Object Server', log_lines[0]) - self.assertIn(req.path.decode('utf-8'), log_lines[0]) + # We allow the b'' in logs because we want to see bad characters. + self.assertIn( + "ERROR 500 b'' Trying to PUT /v1/AUTH_kilroy/%ED%88%8E/" + "%E9%90%89 From Object Server", log_lines[0]) + self.assertIn(req.path, log_lines[0]) def test_DELETE_errors(self): # verify logged errors with and without non-ascii characters in path @@ -1863,19 +1846,13 @@ def do_test(path, statuses): req, log_lines = do_test('/AUTH_kilroy/ascii/ascii', (201, 500, 201, 201)) self.assertIn('Trying to DELETE', log_lines[0]) - if six.PY3: - self.assertIn(req.swift_entity_path, log_lines[0]) - else: - self.assertIn(req.swift_entity_path.decode('utf-8'), log_lines[0]) + self.assertIn(req.swift_entity_path, log_lines[0]) self.assertIn(' From Object Server', log_lines[0]) req, log_lines = do_test('/AUTH_kilroy/%ED%88%8E/%E9%90%89', (201, 500, 201, 201)) self.assertIn('Trying to DELETE', log_lines[0]) - if six.PY3: - self.assertIn(req.swift_entity_path, log_lines[0]) - else: - self.assertIn(req.swift_entity_path.decode('utf-8'), log_lines[0]) + self.assertIn(req.swift_entity_path, log_lines[0]) self.assertIn(' From Object Server', log_lines[0]) req, log_lines = do_test('/AUTH_kilroy/ascii/ascii', @@ -1889,19 +1866,13 @@ def do_test(path, statuses): req, log_lines = do_test('/AUTH_kilroy/ascii/ascii', (201, Exception(), 201, 201)) self.assertIn('Trying to DELETE', log_lines[0]) - if six.PY3: - self.assertIn(req.swift_entity_path, log_lines[0]) - else: - self.assertIn(req.swift_entity_path.decode('utf-8'), log_lines[0]) + self.assertIn(req.swift_entity_path, log_lines[0]) self.assertIn('ERROR with Object server', log_lines[0]) req, log_lines = do_test('/AUTH_kilroy/%ED%88%8E/%E9%90%89', (201, Exception(), 201, 201)) self.assertIn('Trying to DELETE', log_lines[0]) - if six.PY3: - self.assertIn(req.swift_entity_path, log_lines[0]) - else: - self.assertIn(req.swift_entity_path.decode('utf-8'), log_lines[0]) + self.assertIn(req.swift_entity_path, log_lines[0]) self.assertIn('ERROR with Object server', log_lines[0]) def test_DELETE_with_write_affinity(self): @@ -3158,7 +3129,7 @@ def _make_ec_archive_bodies(self, test_body, policy=None): def _make_ec_object_stub(self, pattern='test', policy=None, timestamp=None): policy = policy or self.policy - if isinstance(pattern, six.text_type): + if isinstance(pattern, str): pattern = pattern.encode('utf-8') test_body = pattern * policy.ec_segment_size test_body = test_body[:-random.randint(1, 1000)] @@ -3895,7 +3866,7 @@ def test_GET_with_body(self): self.assertEqual(len(real_body), len(sanity_body)) self.assertEqual(real_body, sanity_body) - # list(zip(...)) for py3 compatibility (zip is lazy there) + # list(zip(...)) since zip is lazy node_fragments = list(zip(*fragment_payloads)) self.assertEqual(len(node_fragments), self.replicas()) # sanity headers = {'X-Object-Sysmeta-Ec-Content-Length': str(len(real_body))} @@ -8121,10 +8092,7 @@ def test_get_namespaces_empty_body(self): 'includes': '1_test', 'states': 'updating'}, actual_params) - if six.PY2: - self.assertIn('No JSON', err) - else: - self.assertIn('JSONDecodeError', err) + self.assertIn('JSONDecodeError', err) self.assertFalse(error_lines[1:]) def test_get_namespaces_not_a_list(self): diff --git a/test/unit/proxy/test_server.py b/test/unit/proxy/test_server.py index 13d2ce3f1e..fadc735d65 100644 --- a/test/unit/proxy/test_server.py +++ b/test/unit/proxy/test_server.py @@ -45,12 +45,10 @@ import mock from eventlet import sleep, spawn, wsgi, Timeout, debug -from eventlet.green import httplib +from eventlet.green.http import client as http_client from io import BytesIO -import six -from six.moves import range -from six.moves.urllib.parse import quote, parse_qsl +from urllib.parse import quote, parse_qsl from test import listen_zero from test.debug_logger import debug_logger, FakeStatsdClient @@ -147,13 +145,10 @@ def sortHeaderNames(headerNames): def parse_headers_string(headers_str): headers_dict = HeaderKeyDict() - for line in headers_str.split(b'\r\n'): - if b': ' in line: - header, value = line.split(b': ', 1) - if six.PY2: - headers_dict[header] = value - else: - headers_dict[header.decode('utf8')] = value.decode('utf8') + for line in headers_str.decode('utf8').split('\r\n'): + if ': ' in line: + header, value = line.split(': ', 1) + headers_dict[header] = value return headers_dict @@ -1190,7 +1185,7 @@ def test_exception_occurred_replication_ip_port_logging(self): for node in annotated_nodes])) def test_exception_occurred(self): - def do_test(additional_info): + def do_test(expected_info): logger = debug_logger('test') suppression_limit = 10 app = proxy_server.Application( @@ -1202,11 +1197,6 @@ def do_test(additional_info): node_key = app.error_limiter.node_key(node) self.assertNotIn(node_key, app.error_limiter.stats) # sanity - if six.PY2: - expected_info = additional_info.decode('utf8') - else: - expected_info = additional_info - incremented_limit_samples = [] for i in range(suppression_limit + 1): try: @@ -1214,7 +1204,7 @@ def do_test(additional_info): except Exception as err: caught_exc = err app.exception_occurred( - node, 'server-type', additional_info) + node, 'server-type', expected_info) self.assertEqual(i + 1, node_error_count(app, node)) line = logger.get_lines_for_level('error')[i] self.assertIn('server-type server', line) @@ -1251,10 +1241,7 @@ def do_test(msg): node_key = app.error_limiter.node_key(node) self.assertNotIn(node_key, app.error_limiter.stats) # sanity - if six.PY2: - expected_msg = msg.decode('utf8') - else: - expected_msg = msg + expected_msg = msg incremented_limit_samples = [] for i in range(suppression_limit + 1): app.error_occurred(node, msg) @@ -6978,10 +6965,7 @@ def request_init(self, *args, **kwargs): exp = b'HTTP/1.1 200' self.assertEqual(headers[:len(exp)], exp) fd.read(1) - if six.PY2: - sock.fd._sock.close() - else: - sock.fd._real_close() + sock.fd._real_close() # Make sure the GC is run again for pythons without reference # counting for i in range(4): @@ -8590,10 +8574,7 @@ def __exit__(self, typ, value, tb): # read most of the object, and disconnect fd.read(10) - if six.PY2: - sock.fd._sock.close() - else: - sock.fd._real_close() + sock.fd._real_close() self._sleep_enough( lambda: _test_servers[0].logger.get_lines_for_level('warning')) @@ -9293,7 +9274,7 @@ def _check_disconnect_cleans_up(self, policy_name, is_chunked=False): proxy_port = _test_sockets[0].getsockname()[1] def put(path, headers=None, body=None): - conn = httplib.HTTPConnection('localhost', proxy_port) + conn = http_client.HTTPConnection('localhost', proxy_port) try: conn.connect() conn.putrequest('PUT', path) @@ -9310,10 +9291,7 @@ def put(path, headers=None, body=None): finally: # seriously - shut this mother down if conn.sock: - if six.PY2: - conn.sock.fd._sock.close() - else: - conn.sock.fd._real_close() + conn.sock.fd._real_close() return resp, body # ensure container @@ -9509,10 +9487,7 @@ def _get_obj(self, range_value, obj_name=None, ignore_range_if=''): return (status_code, headers, gotten_obj) def _parse_multipart(self, content_type, body): - if six.PY2: - parser = email.parser.FeedParser() - else: - parser = email.parser.BytesFeedParser() + parser = email.parser.BytesFeedParser() if not isinstance(content_type, bytes): content_type = content_type.encode('utf8') parser.feed(b"Content-Type: %s\r\n\r\n" % content_type) @@ -9627,9 +9602,7 @@ def test_unsatisfiable_socket_leak(self): class LeakTrackingHTTPResponse(BufferedHTTPResponse): def begin(self): - # no super(); we inherit from an old-style class (it's - # httplib's fault; don't try and fix it). - retval = BufferedHTTPResponse.begin(self) + retval = super(BufferedHTTPResponse, self).begin() if self.status != 204: # This mock is overly broad and catches account and # container HEAD requests too. We don't care about diff --git a/test/unit/proxy/test_sysmeta.py b/test/unit/proxy/test_sysmeta.py index c7f433ca3f..c672140d37 100644 --- a/test/unit/proxy/test_sysmeta.py +++ b/test/unit/proxy/test_sysmeta.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from six.moves.urllib.parse import quote +from urllib.parse import quote import unittest import os