From de6554d9e53f01551e07297395fcb61d5649ec81 Mon Sep 17 00:00:00 2001 From: Alexandre Detiste Date: Mon, 2 Oct 2023 22:25:16 +0200 Subject: [PATCH] remove six dependency (#324) remove six dependency This requires adjustments to exception handling in fixtures to properly re-raise them. --- gabbi/case.py | 27 +++++++++---------- gabbi/fixture.py | 6 ++--- gabbi/handlers/base.py | 2 +- gabbi/handlers/jsonhandler.py | 10 +++---- .../handlers/yaml_disk_loading_jsonhandler.py | 4 +-- gabbi/httpclient.py | 5 +--- gabbi/runner.py | 2 -- gabbi/suitemaker.py | 2 +- gabbi/tests/__init__.py | 16 ----------- gabbi/tests/simple_wsgi.py | 5 ++-- gabbi/tests/test_fixtures.py | 3 +-- gabbi/tests/test_inner_fixture.py | 2 +- gabbi/tests/test_load_data_file.py | 3 +-- gabbi/tests/test_runner.py | 2 +- gabbi/tests/test_suite.py | 2 ++ gabbi/tests/test_use_prior_test.py | 3 +-- gabbi/utils.py | 12 +++------ requirements.txt | 1 - 18 files changed, 35 insertions(+), 72 deletions(-) diff --git a/gabbi/case.py b/gabbi/case.py index e46bfbc..af291f7 100644 --- a/gabbi/case.py +++ b/gabbi/case.py @@ -20,16 +20,15 @@ from collections import OrderedDict import copy import functools +from http import cookies import os import re import sys import time import unittest from unittest import result as unitresult +import urllib.parse as urlparse -import six -from six.moves import http_cookies -from six.moves.urllib import parse as urlparse import wsgi_intercept from gabbi import __version__ @@ -298,10 +297,10 @@ def _cookie_replacer(self, match): referred_case = self.history[case] else: referred_case = self.prior - response_cookies = referred_case.response['set-cookie'] - cookies = http_cookies.SimpleCookie() - cookies.load(response_cookies) - cookie_string = cookies.output(attrs=[], header='', sep=',').strip() + response_cookie = referred_case.response['set-cookie'] + cookie = cookies.SimpleCookie() + cookie.load(response_cookie) + cookie_string = cookie.output(attrs=[], header='', sep=',').strip() return cookie_string def _headers_replace(self, message, escape_regex=False): @@ -482,7 +481,7 @@ def _response_replacer(self, match, preserve=False): return self._cast_value(result, match.string) return result else: - return six.text_type(result) + return str(result) def _run_request( self, @@ -514,8 +513,8 @@ def _run_request( ) except wsgi_intercept.WSGIAppError as exc: # Extract and re-raise the wrapped exception. - six.reraise(exc.exception_type, exc.exception_value, - exc.traceback) + raise (exc.exception_type, exc.exception_value, + exc.traceback) # Set headers and location attributes for follow on requests self.response = response @@ -582,7 +581,7 @@ def _run_test(self): # ensure body is bytes, encoding as UTF-8 because that's # what we do here - if isinstance(body, six.text_type): + if isinstance(body, str): body = body.encode('UTF-8') if test['poll']: @@ -637,10 +636,10 @@ def _test_data_to_string(self, data, content_type): """ dumper_class = self.get_content_handler(content_type) if not _is_complex_type(data): - if isinstance(data, six.string_types) and data.startswith('<@'): + if isinstance(data, str) and data.startswith('<@'): info = self.load_data_file(data.replace('<@', '', 1)) if utils.not_binary(content_type): - data = six.text_type(info, 'UTF-8') + data = str(info, 'UTF-8') else: # Return early we are binary content return info @@ -661,7 +660,7 @@ def _test_data_to_string(self, data, content_type): # If the result after template handling is not a string, dump # it if there is a suitable dumper. - if dumper_class and not isinstance(data, six.string_types): + if dumper_class and not isinstance(data, str): # If there are errors dumping we want them to raise to the # test harness. data = dumper_class.dumps(data, test=self) diff --git a/gabbi/fixture.py b/gabbi/fixture.py index ef4ffcd..bc03ebd 100644 --- a/gabbi/fixture.py +++ b/gabbi/fixture.py @@ -16,15 +16,13 @@ import sys from unittest import case -import six - class GabbiFixtureError(Exception): """Generic exception for GabbiFixture.""" pass -class GabbiFixture(object): +class GabbiFixture: """A context manager that operates as a fixture. Subclasses must implement ``start_fixture`` and ``stop_fixture``, each @@ -97,4 +95,4 @@ def nest(fixtures): except Exception: exc = sys.exc_info() if exc != (None, None, None): - six.reraise(exc[0], exc[1], exc[2]) + raise exc[1].with_traceback(exc[2]) diff --git a/gabbi/handlers/base.py b/gabbi/handlers/base.py index ea54b6d..1bbafe0 100644 --- a/gabbi/handlers/base.py +++ b/gabbi/handlers/base.py @@ -15,7 +15,7 @@ from gabbi.exception import GabbiFormatError -class ResponseHandler(object): +class ResponseHandler: """Add functionality for making assertions about an HTTP response. A subclass may implement two methods: ``action`` and ``preprocess``. diff --git a/gabbi/handlers/jsonhandler.py b/gabbi/handlers/jsonhandler.py index 6177779..34dc7ae 100644 --- a/gabbi/handlers/jsonhandler.py +++ b/gabbi/handlers/jsonhandler.py @@ -14,8 +14,6 @@ import json -import six - from gabbi.exception import GabbiDataLoadError from gabbi.handlers import base from gabbi import json_parser @@ -68,7 +66,7 @@ def loads(data): @staticmethod def load_data_file(test, file_path): info = test.load_data_file(file_path) - info = six.text_type(info, 'UTF-8') + info = str(info, 'UTF-8') return json.loads(info) @staticmethod @@ -103,7 +101,7 @@ def action(self, test, path, value=None): '%s' % (path, test.response_data)) # read data from disk if the value starts with '<@' - if isinstance(value, six.string_types) and value.startswith('<@'): + if isinstance(value, str) and value.startswith('<@'): # Do template expansion in the rhs if rhs_path is provided. if ':' in value: value, rhs_path = value.split(':$', 1) @@ -120,7 +118,7 @@ def action(self, test, path, value=None): 'match %s' % (rhs_path, value)) # If expected is a string, check to see if it is a regex. - is_regex = (isinstance(value, six.string_types) and + is_regex = (isinstance(value, str) and value.startswith('/') and value.endswith('/') and len(value) > 1) @@ -130,7 +128,7 @@ def action(self, test, path, value=None): if is_regex and not rhs_match: expected = expected[1:-1] # match may be a number so stringify - match = six.text_type(match) + match = str(match) test.assertRegex( match, expected, 'Expect jsonpath %s to match /%s/, got %s' % diff --git a/gabbi/handlers/yaml_disk_loading_jsonhandler.py b/gabbi/handlers/yaml_disk_loading_jsonhandler.py index a30169e..15179c2 100644 --- a/gabbi/handlers/yaml_disk_loading_jsonhandler.py +++ b/gabbi/handlers/yaml_disk_loading_jsonhandler.py @@ -14,8 +14,6 @@ import yaml -import six - from gabbi.handlers import jsonhandler @@ -36,5 +34,5 @@ class YAMLDiskLoadingJSONHandler(jsonhandler.JSONHandler): @staticmethod def load_data_file(test, file_path): info = test.load_data_file(file_path) - info = six.text_type(info, 'UTF-8') + info = str(info, 'UTF-8') return yaml.safe_load(info) diff --git a/gabbi/httpclient.py b/gabbi/httpclient.py index b5475ba..9491d54 100644 --- a/gabbi/httpclient.py +++ b/gabbi/httpclient.py @@ -11,13 +11,10 @@ # License for the specific language governing permissions and limitations # under the License. -from __future__ import print_function - import os import sys import certifi -import six import urllib3 from gabbi.handlers import jsonhandler @@ -154,7 +151,7 @@ def _print_body(self, headers, content): content_type = utils.extract_content_type(headers, 'text/plain')[0] if self._show_body and utils.not_binary(content_type): content = utils.decode_response_content(headers, content) - if isinstance(content, six.binary_type): + if isinstance(content, bytes): content = content.decode('utf-8') # TODO(cdent): Using the JSONHandler here instead of # just the json module to make it clear that eventually diff --git a/gabbi/runner.py b/gabbi/runner.py index f5a9832..480c69c 100644 --- a/gabbi/runner.py +++ b/gabbi/runner.py @@ -12,8 +12,6 @@ # under the License. """Implementation of a command-line runner for gabbi files (AKA suites).""" -from __future__ import print_function - import argparse from importlib import import_module import os diff --git a/gabbi/suitemaker.py b/gabbi/suitemaker.py index 0b7a70b..d88d767 100644 --- a/gabbi/suitemaker.py +++ b/gabbi/suitemaker.py @@ -27,7 +27,7 @@ from gabbi import suite -class TestMaker(object): +class TestMaker: """A class for encapsulating test invariants. All of the tests in a single gabbi file have invariants which are diff --git a/gabbi/tests/__init__.py b/gabbi/tests/__init__.py index d17f718..e69de29 100644 --- a/gabbi/tests/__init__.py +++ b/gabbi/tests/__init__.py @@ -1,16 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - -six.add_move(six.MovedModule('mock', 'mock', 'unittest.mock')) diff --git a/gabbi/tests/simple_wsgi.py b/gabbi/tests/simple_wsgi.py index a6025c2..38b81b1 100644 --- a/gabbi/tests/simple_wsgi.py +++ b/gabbi/tests/simple_wsgi.py @@ -16,15 +16,14 @@ """ import json - -from six.moves.urllib import parse as urlparse +import urllib.parse as urlparse CURRENT_POLL = 0 METHODS = ['GET', 'PUT', 'POST', 'DELETE', 'PATCH'] -class SimpleWsgi(object): +class SimpleWsgi: """A simple wsgi application to use in tests.""" def __call__(self, environ, start_response): diff --git a/gabbi/tests/test_fixtures.py b/gabbi/tests/test_fixtures.py index 9028a45..23a53a3 100644 --- a/gabbi/tests/test_fixtures.py +++ b/gabbi/tests/test_fixtures.py @@ -14,8 +14,7 @@ """ import unittest - -from six.moves import mock +from unittest import mock from gabbi import fixture diff --git a/gabbi/tests/test_inner_fixture.py b/gabbi/tests/test_inner_fixture.py index 601a264..ed6d9f8 100644 --- a/gabbi/tests/test_inner_fixture.py +++ b/gabbi/tests/test_inner_fixture.py @@ -43,7 +43,7 @@ def stop_fixture(self): assert COUNT_OUTER == 1 -class InnerFixture(object): +class InnerFixture: """Test that setUp is called 3 times.""" def setUp(self): diff --git a/gabbi/tests/test_load_data_file.py b/gabbi/tests/test_load_data_file.py index 0281d4a..a347e51 100644 --- a/gabbi/tests/test_load_data_file.py +++ b/gabbi/tests/test_load_data_file.py @@ -14,8 +14,7 @@ """ import unittest - -from six.moves import mock +from unittest import mock from gabbi import case diff --git a/gabbi/tests/test_runner.py b/gabbi/tests/test_runner.py index 51b3c8e..87c4219 100644 --- a/gabbi/tests/test_runner.py +++ b/gabbi/tests/test_runner.py @@ -13,11 +13,11 @@ """Test that the CLI works as expected """ +from io import StringIO import sys import unittest from uuid import uuid4 -from six import StringIO from wsgi_intercept.interceptor import Urllib3Interceptor from gabbi import exception diff --git a/gabbi/tests/test_suite.py b/gabbi/tests/test_suite.py index d550a4a..e9a301d 100644 --- a/gabbi/tests/test_suite.py +++ b/gabbi/tests/test_suite.py @@ -20,6 +20,7 @@ from gabbi import suitemaker VALUE_ERROR = 'value error sentinel' +FIXTURE_METHOD = 'start_fixture' class FakeFixture(fixture.GabbiFixture): @@ -54,3 +55,4 @@ def test_suite_catches_fixture_fail(self): self.assertIn('foo_alpha', str(errored_test)) self.assertIn(VALUE_ERROR, trace) + self.assertIn(FIXTURE_METHOD, trace) diff --git a/gabbi/tests/test_use_prior_test.py b/gabbi/tests/test_use_prior_test.py index b91cf76..699bd23 100644 --- a/gabbi/tests/test_use_prior_test.py +++ b/gabbi/tests/test_use_prior_test.py @@ -15,8 +15,7 @@ import copy import unittest - -from six.moves import mock +from unittest import mock from gabbi import case diff --git a/gabbi/utils.py b/gabbi/utils.py index 82fcb76..ea238bf 100644 --- a/gabbi/utils.py +++ b/gabbi/utils.py @@ -14,18 +14,12 @@ import io import os +import urllib.parse as urlparse import colorama -import six -from six.moves.urllib import parse as urlparse import yaml - -try: # Python 3 - ConnectionRefused = ConnectionRefusedError -except NameError: # Python 2 - import socket - ConnectionRefused = socket.error +ConnectionRefused = ConnectionRefusedError def create_url(base_url, host, port=None, prefix='', ssl=False): @@ -72,7 +66,7 @@ def decode_response_content(header_dict, content): """Decode content to a proper string.""" content_type, charset = extract_content_type(header_dict) - if not_binary(content_type) and isinstance(content, six.binary_type): + if not_binary(content_type) and isinstance(content, bytes): return content.decode(charset) else: return content diff --git a/requirements.txt b/requirements.txt index 935fa10..8b6602d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,5 @@ pbr pytest -six PyYAML urllib3>=1.26.9,<2.0.0 certifi