From 1e20f4e510b808a8b09b8cfa41a265f0bd17b723 Mon Sep 17 00:00:00 2001 From: Andreas Maier Date: Sun, 18 Aug 2024 17:07:28 +0200 Subject: [PATCH] Upgraded code to Python 3.8 Signed-off-by: Andreas Maier --- docs/conf.py | 12 +++---- nocasedict/__init__.py | 1 - nocasedict/_hashable.py | 1 - nocasedict/_keyableby.py | 1 - nocasedict/_nocasedict.py | 43 ++++++------------------- setup.py | 7 ++-- tests/unittest/test_hashable.py | 5 ++- tests/unittest/test_keyableby.py | 1 - tests/unittest/test_nocasedict.py | 5 ++- tests/utils/import_installed.py | 9 +++--- tests/utils/simplified_test_function.py | 3 +- 11 files changed, 27 insertions(+), 61 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 5bf4a1d..3a96e45 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -31,7 +31,7 @@ def get_version(version_file): requirements list of this package (otherwise it cannot be executed in a fresh Python environment). """ - with open(version_file, 'r') as fp: + with open(version_file) as fp: version_source = fp.read() globals = {} exec(version_source, globals) @@ -97,12 +97,12 @@ def get_version(version_file): os.environ['BUILDING_DOCS'] = '1' # General information about the project. -project = u'nocasedict' +project = 'nocasedict' #copyright = u'' -author = u"Andreas Maier" +author = "Andreas Maier" # The short description of the package. -_short_description = u"A case-insensitive ordered dictionary for Python" +_short_description = "A case-insensitive ordered dictionary for Python" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -582,7 +582,7 @@ def __init__(self, *args, **kwargs): self._logger = logging.getLogger(__name__) # requires Sphinx 1.6.1 self._log_prefix = "conf.py/AutoAutoSummary" self._excluded_classes = ['BaseException'] - super(AutoAutoSummary, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def _get_members(self, class_obj, member_type, include_in_public=None): """ @@ -690,7 +690,7 @@ def run(self): self._log_prefix, exc.__class__.__name__, exc) finally: - return super(AutoAutoSummary, self).run() + return super().run() def setup(app): diff --git a/nocasedict/__init__.py b/nocasedict/__init__.py index 0d9f436..c0ff654 100644 --- a/nocasedict/__init__.py +++ b/nocasedict/__init__.py @@ -2,7 +2,6 @@ nocasedict - A case-insensitive ordered dictionary for Python """ -from __future__ import absolute_import from ._version import __version__ # noqa: F401 from ._nocasedict import * # noqa: F403,F401 diff --git a/nocasedict/_hashable.py b/nocasedict/_hashable.py index 98bcf4a..b2677b0 100644 --- a/nocasedict/_hashable.py +++ b/nocasedict/_hashable.py @@ -2,7 +2,6 @@ This module provides class HashableMixin. """ -from __future__ import print_function, absolute_import from typing import Any from ._nocasedict import NocaseDict diff --git a/nocasedict/_keyableby.py b/nocasedict/_keyableby.py index 14567a0..6d5c65a 100644 --- a/nocasedict/_keyableby.py +++ b/nocasedict/_keyableby.py @@ -3,7 +3,6 @@ class NocaseDict. """ -from __future__ import print_function, absolute_import from typing import Type diff --git a/nocasedict/_nocasedict.py b/nocasedict/_nocasedict.py index f2c7a55..d82c174 100644 --- a/nocasedict/_nocasedict.py +++ b/nocasedict/_nocasedict.py @@ -30,7 +30,6 @@ The only class exposed by this package is :class:`nocasedict.NocaseDict`. """ -from __future__ import print_function, absolute_import import sys import os @@ -43,14 +42,9 @@ __all__ = ['NocaseDict'] -# Starting with Python 3.7, the standard dict is guaranteed to be ordered. -# Note: In CPython, that already happened in 3.6, but it was not guaranteed -# for all implementations. -# pylint: disable=invalid-name -if sys.version_info[0:2] >= (3, 7): - _ODICT_TYPE = dict -else: - _ODICT_TYPE = OrderedDict +# Note: Since the minimum version for nocasedict is Python 3.8, the standard +# dict is guaranteed to be ordered and the implementation uses dict when an +# ordered dict is needed. Key = Optional[AnyStr] @@ -263,7 +257,7 @@ def __init__(self, *args, **kwargs) -> None: # The internal dictionary, with casefolded keys. An item in this dict # is the tuple (original key, value). - self._data: Dict[Key, Any] = _ODICT_TYPE() + self._data: Dict[Key, Any] = dict() self.update(*args, **kwargs) @@ -597,23 +591,12 @@ def update(self, *args, **kwargs) -> None: if args: if len(args) > 1: raise TypeError( - "Expected at most 1 positional argument, got {n}". - format(n=len(args))) + f"Expected at most 1 positional argument, got {len(args)}") other = args[0] try: # Try mapping / dictionary for key in other.keys(): self[key] = other[key] - # pylint: disable=unidiomatic-typecheck - if type(other) is dict and _ODICT_TYPE is not dict and \ - len(other.keys()) > 1: - warnings.warn( - "Before Python 3.7, initializing or updating a " - "NocaseDict object from a dict object with more than " - "one item is not guaranteed to preserve the order of " - "its items", - UserWarning, - stacklevel=_stacklevel_above_nocasedict()) except AttributeError: # Expecting an iterable @@ -632,9 +615,8 @@ def update(self, *args, **kwargs) -> None: key, value = item except ValueError as exc: value_error = ValueError( - "Cannot unpack positional argument item #{i} " - "of type {t} into key, value: {exc}". - format(i=i, t=type(item), exc=exc)) + f"Cannot unpack positional argument item #{i} " + f"of type {type(item)} into key, value: {exc}") value_error.__cause__ = None # Suppress 'During..' # pylint: disable=raise-missing-from raise value_error @@ -642,13 +624,6 @@ def update(self, *args, **kwargs) -> None: for key, val in kwargs.items(): self[key] = val - if len(kwargs) > 1 and _ODICT_TYPE is not dict: - warnings.warn( - "Before Python 3.7, initializing or updating a NocaseDict " - "object from more than one keyword argument is not guaranteed " - "to preserve their order", - UserWarning, - stacklevel=_stacklevel_above_nocasedict()) def clear(self) -> None: """ @@ -723,8 +698,8 @@ def _raise_ordering_not_supported(self, other: Any, op: str) -> NoReturn: is not supported. """ raise TypeError( - "'{}' not supported between instances of '{}' and '{}'". - format(op, type(self), type(other))) + f"'{op}' not supported between instances of '{type(self)}' and " + f"'{type(other)}'") def __lt__(self, other: Any) -> NoReturn: self._raise_ordering_not_supported(other, '<') diff --git a/setup.py b/setup.py index 609fbe6..7a577d9 100755 --- a/setup.py +++ b/setup.py @@ -5,7 +5,6 @@ import sys import os -import io import re from typing import Optional @@ -21,7 +20,7 @@ def get_version(version_file): requirements list of this package (otherwise it cannot be executed in a fresh Python environment). """ - with io.open(version_file, 'r', encoding='utf-8') as fp: + with open(version_file, encoding='utf-8') as fp: version_source = fp.read() _globals = {} exec(version_source, _globals) # pylint: disable=exec-used @@ -34,7 +33,7 @@ def get_requirements(requirements_file): non-comment lines. The returned lines are without any trailing newline characters. """ - with io.open(requirements_file, 'r', encoding='utf-8') as fp: + with open(requirements_file, encoding='utf-8') as fp: lines = fp.readlines() reqs = [] for line in lines: @@ -48,7 +47,7 @@ def read_file(a_file): """ Read the specified file and return its content as one string. """ - with io.open(a_file, 'r', encoding='utf-8') as fp: + with open(a_file, encoding='utf-8') as fp: content = fp.read() return content diff --git a/tests/unittest/test_hashable.py b/tests/unittest/test_hashable.py index 7b82b51..9e11399 100644 --- a/tests/unittest/test_hashable.py +++ b/tests/unittest/test_hashable.py @@ -2,7 +2,6 @@ Test the HashableMixin mixin class. """ -from __future__ import absolute_import import os import pytest @@ -155,7 +154,7 @@ def __hash__(self): "Comparing unicode value with bytes value", dict( obj1=MyNocaseDict([('k1', b'v1')]), - obj2=MyNocaseDict([('k2', u'v2')]), + obj2=MyNocaseDict([('k2', 'v2')]), exp_obj_equal=False, ), None, None, True @@ -164,7 +163,7 @@ def __hash__(self): "Matching unicode key with string key", dict( obj1=MyNocaseDict([('k1', 'v1')]), - obj2=MyNocaseDict([(u'k2', 'v2')]), + obj2=MyNocaseDict([('k2', 'v2')]), exp_obj_equal=False, ), None, None, True diff --git a/tests/unittest/test_keyableby.py b/tests/unittest/test_keyableby.py index feae3ba..58746af 100644 --- a/tests/unittest/test_keyableby.py +++ b/tests/unittest/test_keyableby.py @@ -2,7 +2,6 @@ Test the KeyableByMixin() mixin function. """ -from __future__ import absolute_import import os import pytest diff --git a/tests/unittest/test_nocasedict.py b/tests/unittest/test_nocasedict.py index 16ad7d3..11907e2 100755 --- a/tests/unittest/test_nocasedict.py +++ b/tests/unittest/test_nocasedict.py @@ -2,7 +2,6 @@ Test the NocaseDict class. """ -from __future__ import absolute_import import sys import os @@ -2679,7 +2678,7 @@ def test_NocaseDict_copy(testcase, "Comparing unicode value with bytes value", dict( obj1=NocaseDict([('k1', b'v1')]), - obj2=NocaseDict([('k2', u'v2')]), + obj2=NocaseDict([('k2', 'v2')]), exp_obj_equal=False, ), None, None, True @@ -2688,7 +2687,7 @@ def test_NocaseDict_copy(testcase, "Matching unicode key with string key", dict( obj1=NocaseDict([('k1', 'v1')]), - obj2=NocaseDict([(u'k2', 'v2')]), + obj2=NocaseDict([('k2', 'v2')]), exp_obj_equal=False, ), None, None, True diff --git a/tests/utils/import_installed.py b/tests/utils/import_installed.py index b71f21f..e742edc 100644 --- a/tests/utils/import_installed.py +++ b/tests/utils/import_installed.py @@ -3,7 +3,6 @@ package. """ -from __future__ import absolute_import, print_function import sys import os @@ -79,11 +78,11 @@ def import_installed(module_name): if module_name not in sys.modules: module = __import__(module_name, level=0) # only absolute imports if test_installed == 'DEBUG': - print("Debug: {0} module newly loaded from: {1}". - format(module_name, module.__file__)) + print(f"Debug: {module_name} module newly loaded from: " + f"{module.__file__}") else: module = sys.modules[module_name] if test_installed == 'DEBUG': - print("Debug: {0} module was already loaded from: {1}". - format(module_name, module.__file__)) + print(f"Debug: {module_name} module was already loaded from: " + f"{module.__file__}") return module diff --git a/tests/utils/simplified_test_function.py b/tests/utils/simplified_test_function.py index b31ef80..340eb8d 100644 --- a/tests/utils/simplified_test_function.py +++ b/tests/utils/simplified_test_function.py @@ -2,7 +2,6 @@ simplified_test_function - Pytest extension for simplifying test functions. """ -from __future__ import absolute_import import functools import warnings @@ -174,7 +173,7 @@ def wrapper_func(desc, kwargs, exp_exc_types, exp_warn_types, condition): for w in rec_warnings: tup = (w.filename, w.lineno, w.category.__name__, str(w.message)) - line = "{t[0]}:{t[1]}: {t[2]}: {t[3]}".format(t=tup) + line = f"{tup[0]}:{tup[1]}: {tup[2]}: {tup[3]}" if line not in lines: lines.append(line) msg = "Unexpected warnings:\n{}".format(