diff --git a/composed_configuration/_allauth.py b/composed_configuration/_allauth.py index 0ae64e9..69e0fdb 100644 --- a/composed_configuration/_allauth.py +++ b/composed_configuration/_allauth.py @@ -1,5 +1,3 @@ -from typing import Type - from ._base import ComposedConfiguration, ConfigMixin @@ -11,7 +9,7 @@ class AllauthMixin(ConfigMixin): """ @staticmethod - def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: + def mutate_configuration(configuration: type[ComposedConfiguration]) -> None: configuration.INSTALLED_APPS += [ 'django.contrib.sites', 'allauth', diff --git a/composed_configuration/_allauth_support/createsuperuser.py b/composed_configuration/_allauth_support/createsuperuser.py index cd9137f..4b423e4 100644 --- a/composed_configuration/_allauth_support/createsuperuser.py +++ b/composed_configuration/_allauth_support/createsuperuser.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import ClassVar, List, Optional +from typing import ClassVar from django.contrib.auth.management.commands import createsuperuser from django.contrib.auth.models import User, UserManager @@ -30,9 +30,9 @@ class EmailAsUsernameProxyUserManager(UserManager): # This version of "create_superuser" makes the "username" argument optional def create_superuser( self, - username: Optional[str] = None, - email: Optional[str] = None, - password: Optional[str] = None, + username: str | None = None, + email: str | None = None, + password: str | None = None, **extra_fields, ) -> EmailAsUsernameProxyUser: # Practically, email will always be provided @@ -55,7 +55,7 @@ class Meta(User.Meta): # Don't include "email" in "REQUIRED_FIELDS", to prevent adding that field twice to the # "createsuperuser.Command" argument parser - REQUIRED_FIELDS: ClassVar[List[str]] = [] + REQUIRED_FIELDS: ClassVar[list[str]] = [] @classmethod def normalize_username(cls, username: str) -> str: diff --git a/composed_configuration/_allauth_support/management/commands/createsuperuser.py b/composed_configuration/_allauth_support/management/commands/createsuperuser.py index 741a79f..0fda7d0 100644 --- a/composed_configuration/_allauth_support/management/commands/createsuperuser.py +++ b/composed_configuration/_allauth_support/management/commands/createsuperuser.py @@ -1,4 +1,4 @@ -from typing import Type, cast +from typing import cast from allauth.account import app_settings as allauth_settings from django.contrib.auth import get_user_model @@ -20,13 +20,13 @@ # If using email as username if not allauth_settings.USERNAME_REQUIRED: # Expose the modified command - Command: Type[BaseCommand] = allauth_support_createsuperuser.Command - user_model: Type[AbstractUser] = allauth_support_createsuperuser.EmailAsUsernameProxyUser + Command: type[BaseCommand] = allauth_support_createsuperuser.Command + user_model: type[AbstractUser] = allauth_support_createsuperuser.EmailAsUsernameProxyUser else: # Expose the pristine upstream version of the command Command = django_createsuperuser.Command - user_model = cast(Type[AbstractUser], get_user_model()) + user_model = cast(type[AbstractUser], get_user_model()) # Always automatically verify email addresses of newly created superusers post_save.connect(verify_email_address_on_user_post_save, sender=user_model) diff --git a/composed_configuration/_allauth_support/receiver.py b/composed_configuration/_allauth_support/receiver.py index 5aa0f6b..b1e6179 100644 --- a/composed_configuration/_allauth_support/receiver.py +++ b/composed_configuration/_allauth_support/receiver.py @@ -1,5 +1,4 @@ import logging -from typing import Type from allauth.account.models import EmailAddress from django.contrib.auth.models import AbstractUser @@ -8,7 +7,7 @@ def verify_email_address_on_user_post_save( - sender: Type[AbstractUser], + sender: type[AbstractUser], instance: AbstractUser, created: bool, **kwargs, diff --git a/composed_configuration/_base.py b/composed_configuration/_base.py index ed3bf52..3b05664 100644 --- a/composed_configuration/_base.py +++ b/composed_configuration/_base.py @@ -1,5 +1,4 @@ import contextlib -from typing import Type import warnings from configurations import Configuration, values @@ -62,7 +61,7 @@ class ConfigMixin: """Abstract mixin for composable Config sections.""" @staticmethod - def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: + def mutate_configuration(configuration: type[ComposedConfiguration]) -> None: """ Mutate the configuration before values are fully bound with environment variables. diff --git a/composed_configuration/_configuration.py b/composed_configuration/_configuration.py index a00d902..046521b 100644 --- a/composed_configuration/_configuration.py +++ b/composed_configuration/_configuration.py @@ -1,5 +1,3 @@ -from typing import List, Optional, Tuple - from configurations import values from ._allauth import AllauthMixin @@ -68,7 +66,7 @@ class TestingBaseConfiguration(MinioStorageMixin, _BaseConfiguration): SECRET_KEY = 'testingsecret' # Testing will add 'testserver' to ALLOWED_HOSTS - ALLOWED_HOSTS: List[str] = [] + ALLOWED_HOSTS: list[str] = [] MINIO_STORAGE_MEDIA_BUCKET_NAME = 'test-django-storage' @@ -97,7 +95,7 @@ class _HerokuMixin: environ_name='CLOUDAMQP_URL', environ_prefix=None, environ_required=True ) # https://help.heroku.com/J2R1S4T8/can-heroku-force-an-application-to-use-ssl-tls - SECURE_PROXY_SSL_HEADER: Optional[Tuple[str, str]] = ('HTTP_X_FORWARDED_PROTO', 'https') + SECURE_PROXY_SSL_HEADER: tuple[str, str] | None = ('HTTP_X_FORWARDED_PROTO', 'https') # This may be provided by https://github.com/ianpurvis/heroku-buildpack-version or similar # The commit SHA is the preferred release tag for Git-based projects: # https://docs.sentry.io/platforms/python/configuration/releases/#bind-the-version diff --git a/composed_configuration/_cors.py b/composed_configuration/_cors.py index f21df62..2a2c568 100644 --- a/composed_configuration/_cors.py +++ b/composed_configuration/_cors.py @@ -1,5 +1,3 @@ -from typing import Type - from configurations import values from ._base import ComposedConfiguration, ConfigMixin @@ -18,7 +16,7 @@ class CorsMixin(ConfigMixin): """ @staticmethod - def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: + def mutate_configuration(configuration: type[ComposedConfiguration]) -> None: configuration.INSTALLED_APPS += ['corsheaders'] # CorsMiddleware must be added immediately before WhiteNoiseMiddleware, so this can diff --git a/composed_configuration/_database.py b/composed_configuration/_database.py index 19bf1fb..718dd20 100644 --- a/composed_configuration/_database.py +++ b/composed_configuration/_database.py @@ -1,5 +1,3 @@ -from typing import Type - from configurations import values from ._base import ComposedConfiguration, ConfigMixin @@ -16,7 +14,7 @@ class DatabaseMixin(ConfigMixin): """ @staticmethod - def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: + def mutate_configuration(configuration: type[ComposedConfiguration]) -> None: configuration.INSTALLED_APPS += ['django.contrib.postgres'] # This cannot have a default value, since the password and database diff --git a/composed_configuration/_debug.py b/composed_configuration/_debug.py index 2ae00fb..6bd24dd 100644 --- a/composed_configuration/_debug.py +++ b/composed_configuration/_debug.py @@ -1,5 +1,3 @@ -from typing import Type - from ._base import ComposedConfiguration, ConfigMixin @@ -11,7 +9,7 @@ class DebugMixin(ConfigMixin): """ @staticmethod - def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: + def mutate_configuration(configuration: type[ComposedConfiguration]) -> None: configuration.INSTALLED_APPS += ['debug_toolbar'] # Include Debug Toolbar middleware as early as possible in the list. diff --git a/composed_configuration/_django.py b/composed_configuration/_django.py index fc72d63..2b063ad 100644 --- a/composed_configuration/_django.py +++ b/composed_configuration/_django.py @@ -1,4 +1,4 @@ -from typing import NoReturn, Type +from typing import NoReturn from configurations import values @@ -21,7 +21,7 @@ class DjangoMixin(ConfigMixin): """ @staticmethod - def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: + def mutate_configuration(configuration: type[ComposedConfiguration]) -> None: # These are often extended, so update their values to avoid fragility due to mixin ordering configuration.INSTALLED_APPS += [ 'django.contrib.admin', diff --git a/composed_configuration/_docker.py b/composed_configuration/_docker.py index c9f272e..2d8b281 100644 --- a/composed_configuration/_docker.py +++ b/composed_configuration/_docker.py @@ -21,7 +21,7 @@ def _is_docker() -> bool: return False -class _AlwaysContains(object): +class _AlwaysContains: """An object which always returns True for `x in _AlwaysContains()` operations.""" def __contains__(self, item) -> bool: diff --git a/composed_configuration/_email.py b/composed_configuration/_email.py index d0ced01..8ec9637 100644 --- a/composed_configuration/_email.py +++ b/composed_configuration/_email.py @@ -1,4 +1,4 @@ -from typing import Dict, Type, cast +from typing import cast from configurations import values @@ -23,9 +23,9 @@ class SmtpEmailMixin(_EmailMixin): """ @staticmethod - def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: + def mutate_configuration(configuration: type[ComposedConfiguration]) -> None: email = cast( - Dict[str, str], + dict[str, str], values.EmailURLValue( environ_name='EMAIL_URL', environ_prefix='DJANGO', diff --git a/composed_configuration/_extensions.py b/composed_configuration/_extensions.py index 42a6434..0f1e946 100644 --- a/composed_configuration/_extensions.py +++ b/composed_configuration/_extensions.py @@ -1,5 +1,3 @@ -from typing import Type - from ._base import ComposedConfiguration, ConfigMixin @@ -11,7 +9,7 @@ class ExtensionsMixin(ConfigMixin): """ @staticmethod - def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: + def mutate_configuration(configuration: type[ComposedConfiguration]) -> None: configuration.INSTALLED_APPS += ['django_extensions'] SHELL_PLUS_PRINT_SQL = True diff --git a/composed_configuration/_filter.py b/composed_configuration/_filter.py index 08a06f2..3b348c8 100644 --- a/composed_configuration/_filter.py +++ b/composed_configuration/_filter.py @@ -1,5 +1,3 @@ -from typing import Type - from ._base import ComposedConfiguration, ConfigMixin @@ -11,5 +9,5 @@ class FilterMixin(ConfigMixin): """ @staticmethod - def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: + def mutate_configuration(configuration: type[ComposedConfiguration]) -> None: configuration.INSTALLED_APPS += ['django_filters'] diff --git a/composed_configuration/_girder_utils.py b/composed_configuration/_girder_utils.py index 00342d3..0859110 100644 --- a/composed_configuration/_girder_utils.py +++ b/composed_configuration/_girder_utils.py @@ -1,5 +1,3 @@ -from typing import Type - from ._base import ComposedConfiguration, ConfigMixin @@ -11,5 +9,5 @@ class GirderUtilsMixin(ConfigMixin): """ @staticmethod - def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: + def mutate_configuration(configuration: type[ComposedConfiguration]) -> None: configuration.INSTALLED_APPS += ['girder_utils'] diff --git a/composed_configuration/_https.py b/composed_configuration/_https.py index e45ad76..f2f8474 100644 --- a/composed_configuration/_https.py +++ b/composed_configuration/_https.py @@ -1,5 +1,3 @@ -from typing import Optional, Tuple - from ._base import ConfigMixin @@ -9,7 +7,7 @@ class HttpsMixin(ConfigMixin): SECURE_SSL_REDIRECT = True # This must be set when deployed behind a proxy - SECURE_PROXY_SSL_HEADER: Optional[Tuple[str, str]] = None + SECURE_PROXY_SSL_HEADER: tuple[str, str] | None = None SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True diff --git a/composed_configuration/_logging.py b/composed_configuration/_logging.py index edf2df4..649aa70 100644 --- a/composed_configuration/_logging.py +++ b/composed_configuration/_logging.py @@ -1,5 +1,4 @@ import logging -from typing import Optional from django.http import HttpRequest @@ -8,7 +7,7 @@ def _filter_favicon_requests(record: logging.LogRecord) -> bool: if record.name == 'django.request': - request: Optional[HttpRequest] = getattr(record, 'request', None) + request: HttpRequest | None = getattr(record, 'request', None) if request and request.path == '/favicon.ico': return False diff --git a/composed_configuration/_rest_framework.py b/composed_configuration/_rest_framework.py index fd43b7d..7f22493 100644 --- a/composed_configuration/_rest_framework.py +++ b/composed_configuration/_rest_framework.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Type +from typing import Any from ._base import ComposedConfiguration, ConfigMixin @@ -12,7 +12,7 @@ class RestFrameworkMixin(ConfigMixin): """ @staticmethod - def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: + def mutate_configuration(configuration: type[ComposedConfiguration]) -> None: configuration.INSTALLED_APPS += [ 'rest_framework', 'rest_framework.authtoken', @@ -106,7 +106,7 @@ def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: 'REFRESH_TOKEN_EXPIRE_SECONDS': 30 * 24 * 60 * 60, } - SWAGGER_SETTINGS: Dict[str, Any] = { + SWAGGER_SETTINGS: dict[str, Any] = { # The default security definition ("basic") is not supported by this DRF configuration, # so expect all logins to come via the Django session, which there's no OpenAPI # security definition for. @@ -114,4 +114,4 @@ def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: 'USE_SESSION_AUTH': True, } - REDOC_SETTINGS: Dict[str, Any] = {} + REDOC_SETTINGS: dict[str, Any] = {} diff --git a/composed_configuration/_sentry.py b/composed_configuration/_sentry.py index 58b687e..008d153 100644 --- a/composed_configuration/_sentry.py +++ b/composed_configuration/_sentry.py @@ -1,5 +1,3 @@ -from typing import Type - from configurations import values from ._base import ComposedConfiguration, ConfigMixin @@ -18,7 +16,7 @@ class SentryMixin(ConfigMixin): """ @staticmethod - def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: + def mutate_configuration(configuration: type[ComposedConfiguration]) -> None: configuration.INSTALLED_APPS += [ 'composed_configuration.sentry.apps.SentryConfig', ] diff --git a/composed_configuration/_static.py b/composed_configuration/_static.py index bec0dc2..62078bc 100644 --- a/composed_configuration/_static.py +++ b/composed_configuration/_static.py @@ -1,5 +1,4 @@ from pathlib import Path -from typing import Type from ._base import ComposedConfiguration, ConfigMixin from ._values import DirectoryPathValue @@ -41,7 +40,7 @@ def STATIC_ROOT(self): # noqa: N802 ) @staticmethod - def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: + def mutate_configuration(configuration: type[ComposedConfiguration]) -> None: configuration.INSTALLED_APPS += ['django.contrib.staticfiles'] @@ -53,7 +52,7 @@ class WhitenoiseStaticFileMixin(StaticFileMixin): """ @staticmethod - def mutate_configuration(configuration: Type[ComposedConfiguration]) -> None: + def mutate_configuration(configuration: type[ComposedConfiguration]) -> None: # Insert immediately before staticfiles app staticfiles_index = configuration.INSTALLED_APPS.index('django.contrib.staticfiles') configuration.INSTALLED_APPS.insert(staticfiles_index, 'whitenoise.runserver_nostatic')