diff --git a/passlib/apache.py b/passlib/apache.py index da0cf01f..aec7a141 100644 --- a/passlib/apache.py +++ b/passlib/apache.py @@ -8,7 +8,7 @@ import os from os import PathLike -from typing import Literal +from typing import Literal, Optional from warnings import warn @@ -182,7 +182,7 @@ def load_if_changed(self): self.load() return True - def load(self, path: PathLike | None = None) -> Literal[True]: + def load(self, path: Optional[PathLike] = None) -> Literal[True]: """Load state from local file. If no path is specified, attempts to load from ``self.path``. diff --git a/passlib/ext/django/utils.py b/passlib/ext/django/utils.py index 1cfe4704..129b8a86 100644 --- a/passlib/ext/django/utils.py +++ b/passlib/ext/django/utils.py @@ -5,6 +5,7 @@ import weakref from collections import OrderedDict from functools import update_wrapper, wraps, lru_cache +from typing import Union from warnings import warn from passlib import exc, registry from passlib.context import CryptContext @@ -12,7 +13,7 @@ from passlib.utils.compat import get_method_function from passlib.utils.decor import memoized_property -DJANGO_VERSION: tuple[int | str, ...] +DJANGO_VERSION: tuple[Union[int, str], ...] try: from django import VERSION as DJANGO_VERSION diff --git a/passlib/utils/handlers.py b/passlib/utils/handlers.py index 4298444b..35307877 100644 --- a/passlib/utils/handlers.py +++ b/passlib/utils/handlers.py @@ -7,6 +7,7 @@ import inspect import math import threading +from typing import Optional, Union from warnings import warn from passlib import exc @@ -638,23 +639,23 @@ class GenericHandler(MinimalHandler): # class attr # =================================================================== # this must be provided by the actual class. - setting_kwds: tuple[str, ...] | None = None + setting_kwds: Optional[tuple[str, ...]] = None # providing default since most classes don't use this at all. context_kwds = () # optional prefix that uniquely identifies hash - ident: str | None = None + ident: Optional[str] = None # optional regexp for recognizing hashes, # used by default identify() if .ident isn't specified. _hash_regex = None # if specified, _norm_checksum will require this length - checksum_size: int | None = None + checksum_size: Optional[int] = None # if specified, _norm_checksum() will validate this - checksum_chars: str | None = None + checksum_chars: Optional[str] = None # private flag used by HasRawChecksum _checksum_is_bytes = False @@ -1329,8 +1330,8 @@ class HasSalt(GenericHandler): # =================================================================== min_salt_size = 0 - max_salt_size: int | None = None - salt_chars: str | None = None + max_salt_size: Optional[int] = None + salt_chars: Optional[str] = None @classproperty def default_salt_size(cls): @@ -1662,7 +1663,7 @@ class HasRounds(GenericHandler): # XXX: rename to min_valid_rounds / max_valid_rounds, # to clarify role compared to min_desired_rounds / max_desired_rounds? min_rounds: int = 0 - max_rounds: int | None = None + max_rounds: Optional[int] = None rounds_cost: str = "linear" # default to the common case # hack to pass info to _CryptRecord (will be removed in passlib 2.0) @@ -1680,7 +1681,7 @@ class HasRounds(GenericHandler): # ----------------- min_desired_rounds = None max_desired_rounds = None - default_rounds: int | None = None + default_rounds: Optional[int] = None vary_rounds = None # =================================================================== @@ -1697,7 +1698,7 @@ def using( min_desired_rounds=None, max_desired_rounds=None, default_rounds=None, - vary_rounds: str | float | None = None, + vary_rounds: Union[str, float, None] = None, min_rounds=None, max_rounds=None, rounds=None, # aliases used by CryptContext diff --git a/tests/utils.py b/tests/utils.py index 6b61369a..6a95831c 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -9,6 +9,7 @@ from functools import wraps, partial import hashlib import logging +from typing import Optional, Union from unittest import SkipTest import random @@ -342,7 +343,7 @@ class TestCase(unittest.TestCase): # --------------------------------------------------------------- # string prepended to all tests in TestCase - descriptionPrefix: str | None = None + descriptionPrefix: Optional[str] = None def shortDescription(self): """wrap shortDescription() method to prepend descriptionPrefix""" @@ -827,7 +828,7 @@ class HandlerCase(TestCase): # --------------------------------------------------------------- # handler class to test [required] - handler: type[PasswordHash] | PrefixWrapper = None + handler: Union[type[PasswordHash], PrefixWrapper] = None # if set, run tests against specified backend backend = None