From 6cb932e47f1763f0dcdd0c1f838236997772b351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20K=C3=A4ufl?= Date: Mon, 18 Jan 2021 10:56:47 +0100 Subject: [PATCH] Run pyupgrade on the code But don't touch string formatting. https://pypi.org/project/pyupgrade/ --- configurations/base.py | 9 +-- configurations/importer.py | 4 +- configurations/utils.py | 103 ++++++++----------------- configurations/values.py | 58 +++++++------- docs/conf.py | 26 +++---- docs/patterns.rst | 2 +- setup.py | 3 +- tests/docs/conf.py | 1 - tests/settings/main.py | 2 +- tests/settings/mixin_inheritance.py | 10 +-- tests/settings/multiple_inheritance.py | 2 +- tests/settings/single_inheritance.py | 2 +- tests/setup_test.py | 5 +- tests/test_env.py | 2 +- tests/test_inheritance.py | 2 +- tests/test_main.py | 2 +- tests/test_sphinx.py | 1 - tests/test_values.py | 12 +-- 18 files changed, 97 insertions(+), 149 deletions(-) diff --git a/configurations/base.py b/configurations/base.py index 07f96df..b1bc1e9 100644 --- a/configurations/base.py +++ b/configurations/base.py @@ -1,6 +1,5 @@ import os import re -import six from django.conf import global_settings from django.core.exceptions import ImproperlyConfigured @@ -37,14 +36,14 @@ def __new__(cls, name, bases, attrs): # https://github.com/django/django/commit/226ebb17290b604ef29e82fb5c1fbac3594ac163#diff-ec2bed07bb264cb95a80f08d71a47c06R163-R170 if "PASSWORD_RESET_TIMEOUT_DAYS" in attrs and "PASSWORD_RESET_TIMEOUT" in attrs: attrs.pop("PASSWORD_RESET_TIMEOUT_DAYS") - return super(ConfigurationBase, cls).__new__(cls, name, bases, attrs) + return super().__new__(cls, name, bases, attrs) def __repr__(self): return "".format(self.__module__, self.__name__) -class Configuration(six.with_metaclass(ConfigurationBase)): +class Configuration(metaclass=ConfigurationBase): """ The base configuration class to inherit from. @@ -91,10 +90,10 @@ def load_dotenv(cls): try: with open(dotenv, 'r') as f: content = f.read() - except IOError as e: + except OSError as e: raise ImproperlyConfigured("Couldn't read .env file " "with the path {}. Error: " - "{}".format(dotenv, e)) + "{}".format(dotenv, e)) from e else: for line in content.splitlines(): m1 = re.match(r'\A([A-Za-z_0-9]+)=(.*)\Z', line) diff --git a/configurations/importer.py b/configurations/importer.py index 353b589..e3573f4 100644 --- a/configurations/importer.py +++ b/configurations/importer.py @@ -51,7 +51,7 @@ def create_parser(self, prog_name, subcommand): installed = True -class ConfigurationImporter(object): +class ConfigurationImporter: modvar = SETTINGS_ENVIRONMENT_VARIABLE namevar = CONFIGURATION_ENVIRONMENT_VARIABLE error_msg = ("Configuration cannot be imported, " @@ -134,7 +134,7 @@ def find_module(self, fullname, path=None): return None -class ConfigurationLoader(object): +class ConfigurationLoader: def __init__(self, name, location): self.name = name diff --git a/configurations/utils.py b/configurations/utils.py index 7f972e7..da57a3f 100644 --- a/configurations/utils.py +++ b/configurations/utils.py @@ -1,7 +1,7 @@ import inspect -import six import sys +from functools import partial from importlib import import_module from django.core.exceptions import ImproperlyConfigured @@ -12,8 +12,7 @@ def isuppercase(name): def uppercase_attributes(obj): - return dict((name, getattr(obj, name)) - for name in filter(isuppercase, dir(obj))) + return {name: getattr(obj, name) for name in dir(obj) if isuppercase(name)} def import_by_path(dotted_path, error_prefix=''): @@ -36,8 +35,7 @@ def import_by_path(dotted_path, error_prefix=''): msg = '{0}Error importing module {1}: "{2}"'.format(error_prefix, module_path, err) - six.reraise(ImproperlyConfigured, ImproperlyConfigured(msg), - sys.exc_info()[2]) + raise ImproperlyConfigured(msg).with_traceback(sys.exc_info()[2]) try: attr = getattr(module, class_name) except AttributeError: @@ -61,77 +59,40 @@ def reraise(exc, prefix=None, suffix=None): elif not (suffix.startswith('(') and suffix.endswith(')')): suffix = '(' + suffix + ')' exc.args = ('{0} {1} {2}'.format(prefix, args[0], suffix),) + args[1:] - raise + raise exc # Copied over from Sphinx -if sys.version_info >= (3, 0): - from functools import partial - - def getargspec(func): - """Like inspect.getargspec but supports functools.partial as well.""" - if inspect.ismethod(func): - func = func.__func__ - if type(func) is partial: - orig_func = func.func - argspec = getargspec(orig_func) - args = list(argspec[0]) - defaults = list(argspec[3] or ()) - kwoargs = list(argspec[4]) - kwodefs = dict(argspec[5] or {}) - if func.args: - args = args[len(func.args):] - for arg in func.keywords or (): - try: - i = args.index(arg) - len(args) - del args[i] - try: - del defaults[i] - except IndexError: - pass - except ValueError: # must be a kwonly arg - i = kwoargs.index(arg) - del kwoargs[i] - del kwodefs[arg] - return inspect.FullArgSpec(args, argspec[1], argspec[2], - tuple(defaults), kwoargs, - kwodefs, argspec[6]) - while hasattr(func, '__wrapped__'): - func = func.__wrapped__ - if not inspect.isfunction(func): - raise TypeError('%r is not a Python function' % func) - return inspect.getfullargspec(func) - -else: # 2.6, 2.7 - from functools import partial - - def getargspec(func): - """Like inspect.getargspec but supports functools.partial as well.""" - if inspect.ismethod(func): - func = func.im_func - parts = 0, () - if type(func) is partial: - keywords = func.keywords - if keywords is None: - keywords = {} - parts = len(func.args), keywords.keys() - func = func.func - if not inspect.isfunction(func): - raise TypeError('%r is not a Python function' % func) - args, varargs, varkw = inspect.getargs(func.func_code) - func_defaults = func.func_defaults - if func_defaults is None: - func_defaults = [] - else: - func_defaults = list(func_defaults) - if parts[0]: - args = args[parts[0]:] - if parts[1]: - for arg in parts[1]: +def getargspec(func): + """Like inspect.getargspec but supports functools.partial as well.""" + if inspect.ismethod(func): + func = func.__func__ + if type(func) is partial: + orig_func = func.func + argspec = getargspec(orig_func) + args = list(argspec[0]) + defaults = list(argspec[3] or ()) + kwoargs = list(argspec[4]) + kwodefs = dict(argspec[5] or {}) + if func.args: + args = args[len(func.args):] + for arg in func.keywords or (): + try: i = args.index(arg) - len(args) del args[i] try: - del func_defaults[i] + del defaults[i] except IndexError: pass - return inspect.ArgSpec(args, varargs, varkw, func_defaults) + except ValueError: # must be a kwonly arg + i = kwoargs.index(arg) + del kwoargs[i] + del kwodefs[arg] + return inspect.FullArgSpec(args, argspec[1], argspec[2], + tuple(defaults), kwoargs, + kwodefs, argspec[6]) + while hasattr(func, '__wrapped__'): + func = func.__wrapped__ + if not inspect.isfunction(func): + raise TypeError('%r is not a Python function' % func) + return inspect.getfullargspec(func) diff --git a/configurations/values.py b/configurations/values.py index 8f10338..0761c5d 100644 --- a/configurations/values.py +++ b/configurations/values.py @@ -2,7 +2,6 @@ import copy import decimal import os -import six import sys from django.core import validators @@ -20,7 +19,7 @@ def setup_value(target, name, value): setattr(target, multiple_name, multiple_value) -class Value(object): +class Value: """ A single settings value that is able to interpret env variables and implements a simple validation scheme. @@ -117,7 +116,7 @@ def to_python(self, value): return value -class MultipleMixin(object): +class MultipleMixin: multiple = True @@ -126,7 +125,7 @@ class BooleanValue(Value): false_values = ('no', 'n', 'false', '0', '') def __init__(self, *args, **kwargs): - super(BooleanValue, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.default not in (True, False): raise ValueError('Default value {0!r} is not a ' 'boolean value'.format(self.default)) @@ -142,13 +141,13 @@ def to_python(self, value): 'boolean value {0!r}'.format(value)) -class CastingMixin(object): +class CastingMixin: exception = (TypeError, ValueError) message = 'Cannot interpret value {0!r}' def __init__(self, *args, **kwargs): - super(CastingMixin, self).__init__(*args, **kwargs) - if isinstance(self.caster, six.string_types): + super().__init__(*args, **kwargs) + if isinstance(self.caster, str): self._caster = import_by_path(self.caster) elif callable(self.caster): self._caster = self.caster @@ -158,9 +157,7 @@ def __init__(self, *args, **kwargs): raise ValueError(error) try: arg_names = getargspec(self._caster)[0] - self._params = dict((name, kwargs[name]) - for name in arg_names - if name in kwargs) + self._params = {name: kwargs[name] for name in arg_names if name in kwargs} except TypeError: self._params = {} @@ -181,7 +178,7 @@ class IntegerValue(CastingMixin, Value): class PositiveIntegerValue(IntegerValue): def to_python(self, value): - int_value = super(PositiveIntegerValue, self).to_python(value) + int_value = super().to_python(value) if int_value < 0: raise ValueError(self.message.format(value)) return int_value @@ -213,7 +210,7 @@ def __init__(self, *args, **kwargs): converter = kwargs.pop('converter', None) if converter is not None: self.converter = converter - super(SequenceValue, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # make sure the default is the correct sequence type if self.default is None: self.default = self.sequence_type() @@ -257,7 +254,7 @@ class SingleNestedSequenceValue(SequenceValue): def __init__(self, *args, **kwargs): self.seq_separator = kwargs.pop('seq_separator', ';') - super(SingleNestedSequenceValue, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def _convert(self, items): # This could receive either a bare or nested sequence @@ -266,8 +263,7 @@ def _convert(self, items): super(SingleNestedSequenceValue, self)._convert(i) for i in items ] return self.sequence_type(converted_sequences) - return self.sequence_type( - super(SingleNestedSequenceValue, self)._convert(items)) + return self.sequence_type(super()._convert(items)) def to_python(self, value): split_value = [ @@ -295,7 +291,7 @@ def converter(self, value): try: import_by_path(value) except ImproperlyConfigured as err: - six.reraise(ValueError, ValueError(err), sys.exc_info()[2]) + raise ValueError(err).with_traceback(sys.exc_info()[2]) return value @@ -303,28 +299,28 @@ class SetValue(ListValue): message = 'Cannot interpret set item {0!r} in set {1!r}' def __init__(self, *args, **kwargs): - super(SetValue, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.default is None: self.default = set() else: self.default = set(self.default) def to_python(self, value): - return set(super(SetValue, self).to_python(value)) + return set(super().to_python(value)) class DictValue(Value): message = 'Cannot interpret dict value {0!r}' def __init__(self, *args, **kwargs): - super(DictValue, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.default is None: self.default = {} else: self.default = dict(self.default) def to_python(self, value): - value = super(DictValue, self).to_python(value) + value = super().to_python(value) if not value: return {} try: @@ -336,11 +332,11 @@ def to_python(self, value): return evaled_value -class ValidationMixin(object): +class ValidationMixin: def __init__(self, *args, **kwargs): - super(ValidationMixin, self).__init__(*args, **kwargs) - if isinstance(self.validator, six.string_types): + super().__init__(*args, **kwargs) + if isinstance(self.validator, str): self._validator = import_by_path(self.validator) elif callable(self.validator): self._validator = self.validator @@ -380,16 +376,16 @@ class RegexValue(ValidationMixin, Value): def __init__(self, *args, **kwargs): regex = kwargs.pop('regex', None) self.validator = validators.RegexValidator(regex=regex) - super(RegexValue, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) class PathValue(Value): def __init__(self, *args, **kwargs): self.check_exists = kwargs.pop('check_exists', True) - super(PathValue, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def setup(self, name): - value = super(PathValue, self).setup(name) + value = super().setup(name) value = os.path.expanduser(value) if self.check_exists and not os.path.exists(value): raise ValueError('Path {0!r} does not exist.'.format(value)) @@ -401,13 +397,13 @@ class SecretValue(Value): def __init__(self, *args, **kwargs): kwargs['environ'] = True kwargs['environ_required'] = True - super(SecretValue, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.default is not None: raise ValueError('Secret values are only allowed to ' 'be set as environment variables') def setup(self, name): - value = super(SecretValue, self).setup(name) + value = super().setup(name) if not value: raise ValueError('Secret value {0!r} is not set'.format(name)) return value @@ -422,7 +418,7 @@ def __init__(self, *args, **kwargs): kwargs.setdefault('environ', True) kwargs.setdefault('environ_prefix', None) kwargs.setdefault('environ_name', 'EMAIL_URL') - super(EmailURLValue, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.default is None: self.default = {} else: @@ -437,14 +433,14 @@ def __init__(self, *args, **kwargs): kwargs.setdefault('environ', True) kwargs.setdefault('environ_prefix', None) kwargs.setdefault('environ_name', self.environ_name) - super(DictBackendMixin, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.default is None: self.default = {} else: self.default = self.to_python(self.default) def to_python(self, value): - value = super(DictBackendMixin, self).to_python(value) + value = super().to_python(value) return {self.alias: value} diff --git a/docs/conf.py b/docs/conf.py index 00b1c69..a0613cc 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# # django-configurations documentation build configuration file, created by # sphinx-quickstart on Sat Jul 21 15:03:23 2012. # @@ -43,8 +41,8 @@ master_doc = 'index' # General information about the project. -project = u'django-configurations' -copyright = u'2012-2014, Jannis Leidel and other contributors' +project = 'django-configurations' +copyright = '2012-2014, Jannis Leidel and other contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -186,8 +184,8 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'django-configurations.tex', u'django-configurations Documentation', - u'Jannis Leidel', 'manual'), + ('index', 'django-configurations.tex', 'django-configurations Documentation', + 'Jannis Leidel', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -216,8 +214,8 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'django-configurations', u'django-configurations Documentation', - [u'Jannis Leidel'], 1) + ('index', 'django-configurations', 'django-configurations Documentation', + ['Jannis Leidel'], 1) ] # If true, show URL addresses after external links. @@ -230,8 +228,8 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'django-configurations', u'django-configurations Documentation', - u'Jannis Leidel', 'django-configurations', 'One line description of project.', + ('index', 'django-configurations', 'django-configurations Documentation', + 'Jannis Leidel', 'django-configurations', 'One line description of project.', 'Miscellaneous'), ] @@ -248,10 +246,10 @@ # -- Options for Epub output --------------------------------------------------- # Bibliographic Dublin Core info. -epub_title = u'django-configurations' -epub_author = u'Jannis Leidel' -epub_publisher = u'Jannis Leidel' -epub_copyright = u'2012, Jannis Leidel' +epub_title = 'django-configurations' +epub_author = 'Jannis Leidel' +epub_publisher = 'Jannis Leidel' +epub_copyright = '2012, Jannis Leidel' # The language of the text. It defaults to the language option # or en if the language is not set. diff --git a/docs/patterns.rst b/docs/patterns.rst index 6811f98..d2070b8 100644 --- a/docs/patterns.rst +++ b/docs/patterns.rst @@ -91,7 +91,7 @@ a few mixin you re-use multiple times: .. code-block:: python - class FullPageCaching(object): + class FullPageCaching: USE_ETAGS = True Then import that mixin class in your site settings module and use it with diff --git a/setup.py b/setup.py index 5c78d1b..e479db9 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,3 @@ -from __future__ import print_function import os import codecs from setuptools import setup @@ -27,7 +26,7 @@ def read(*parts): 'django-cadmin = configurations.management:execute_from_command_line', ], }, - install_requires=['six'], + install_requires=[], extras_require={ 'cache': ['django-cache-url'], 'database': ['dj-database-url'], diff --git a/tests/docs/conf.py b/tests/docs/conf.py index 4025988..66ce758 100644 --- a/tests/docs/conf.py +++ b/tests/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import sys diff --git a/tests/settings/main.py b/tests/settings/main.py index 90e252f..9ea2091 100644 --- a/tests/settings/main.py +++ b/tests/settings/main.py @@ -41,7 +41,7 @@ class Test(Configuration): @property def ALLOWED_HOSTS(self): - allowed_hosts = super(Test, self).ALLOWED_HOSTS[:] + allowed_hosts = super().ALLOWED_HOSTS[:] allowed_hosts.append('base') return allowed_hosts diff --git a/tests/settings/mixin_inheritance.py b/tests/settings/mixin_inheritance.py index 88b4cb6..6018ac2 100644 --- a/tests/settings/mixin_inheritance.py +++ b/tests/settings/mixin_inheritance.py @@ -1,19 +1,19 @@ from configurations import Configuration -class Mixin1(object): +class Mixin1: @property def ALLOWED_HOSTS(self): - allowed_hosts = super(Mixin1, self).ALLOWED_HOSTS[:] + allowed_hosts = super().ALLOWED_HOSTS[:] allowed_hosts.append('test1') return allowed_hosts -class Mixin2(object): +class Mixin2: @property def ALLOWED_HOSTS(self): - allowed_hosts = super(Mixin2, self).ALLOWED_HOSTS[:] + allowed_hosts = super().ALLOWED_HOSTS[:] allowed_hosts.append('test2') return allowed_hosts @@ -21,6 +21,6 @@ def ALLOWED_HOSTS(self): class Inheritance(Mixin2, Mixin1, Configuration): def ALLOWED_HOSTS(self): - allowed_hosts = super(Inheritance, self).ALLOWED_HOSTS[:] + allowed_hosts = super().ALLOWED_HOSTS[:] allowed_hosts.append('test3') return allowed_hosts diff --git a/tests/settings/multiple_inheritance.py b/tests/settings/multiple_inheritance.py index 6eb29f3..6152e0a 100644 --- a/tests/settings/multiple_inheritance.py +++ b/tests/settings/multiple_inheritance.py @@ -4,6 +4,6 @@ class Inheritance(BaseInheritance): def ALLOWED_HOSTS(self): - allowed_hosts = super(Inheritance, self).ALLOWED_HOSTS[:] + allowed_hosts = super().ALLOWED_HOSTS[:] allowed_hosts.append('test-test') return allowed_hosts diff --git a/tests/settings/single_inheritance.py b/tests/settings/single_inheritance.py index 34d4852..5364346 100644 --- a/tests/settings/single_inheritance.py +++ b/tests/settings/single_inheritance.py @@ -5,6 +5,6 @@ class Inheritance(Base): @property def ALLOWED_HOSTS(self): - allowed_hosts = super(Inheritance, self).ALLOWED_HOSTS[:] + allowed_hosts = super().ALLOWED_HOSTS[:] allowed_hosts.append('test') return allowed_hosts diff --git a/tests/setup_test.py b/tests/setup_test.py index cb156e6..59f15b1 100644 --- a/tests/setup_test.py +++ b/tests/setup_test.py @@ -1,9 +1,6 @@ """Used by tests to ensure logging is kept when calling setup() twice.""" -try: - from unittest import mock -except ImportError: - from mock import mock +from unittest import mock import configurations diff --git a/tests/test_env.py b/tests/test_env.py index 47286d0..8066eea 100644 --- a/tests/test_env.py +++ b/tests/test_env.py @@ -1,6 +1,6 @@ import os from django.test import TestCase -from mock import patch +from unittest.mock import patch class DotEnvLoadingTests(TestCase): diff --git a/tests/test_inheritance.py b/tests/test_inheritance.py index b40bfd3..0fe4a28 100644 --- a/tests/test_inheritance.py +++ b/tests/test_inheritance.py @@ -2,7 +2,7 @@ from django.test import TestCase -from mock import patch +from unittest.mock import patch class InheritanceTests(TestCase): diff --git a/tests/test_main.py b/tests/test_main.py index fe0e6ce..7cbedbe 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -5,7 +5,7 @@ from django.test import TestCase from django.core.exceptions import ImproperlyConfigured -from mock import patch +from unittest.mock import patch from configurations.importer import ConfigurationImporter diff --git a/tests/test_sphinx.py b/tests/test_sphinx.py index 47519c4..6dc300c 100644 --- a/tests/test_sphinx.py +++ b/tests/test_sphinx.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import subprocess import os diff --git a/tests/test_values.py b/tests/test_values.py index 853b4be..2547e50 100644 --- a/tests/test_values.py +++ b/tests/test_values.py @@ -5,7 +5,7 @@ from django.test import TestCase from django.core.exceptions import ImproperlyConfigured -from mock import patch +from unittest.mock import patch from configurations.values import (Value, BooleanValue, IntegerValue, FloatValue, DecimalValue, ListValue, @@ -270,9 +270,9 @@ def test_single_nested_tuple_values_converter_default(self): def test_set_values_default(self): value = SetValue() with env(DJANGO_TEST='2,2'): - self.assertEqual(value.setup('TEST'), set(['2', '2'])) + self.assertEqual(value.setup('TEST'), {'2', '2'}) with env(DJANGO_TEST='2, 2 ,'): - self.assertEqual(value.setup('TEST'), set(['2', '2'])) + self.assertEqual(value.setup('TEST'), {'2', '2'}) with env(DJANGO_TEST=''): self.assertEqual(value.setup('TEST'), set()) @@ -485,12 +485,12 @@ def test_set_value(self): self.assertEqual(value.value, set()) value = SetValue([1, 2]) - self.assertEqual(value.default, set([1, 2])) - self.assertEqual(value.value, set([1, 2])) + self.assertEqual(value.default, {1, 2}) + self.assertEqual(value.value, {1, 2}) def test_setup_value(self): - class Target(object): + class Target: pass value = EmailURLValue()