summaryrefslogtreecommitdiff
path: root/django/utils
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2023-01-18 09:46:01 +0100
committerGitHub <noreply@github.com>2023-01-18 09:46:01 +0100
commit3bbe22dafcc69c5ffa79707f5a74eb1faf466e12 (patch)
tree4bec6a7016732be33f2e1cddd80c18478cb2dee9 /django/utils
parentd54717118360e8679aa2bd0c5a1625f3e84712ba (diff)
Fixed #34233 -- Dropped support for Python 3.8 and 3.9.
Diffstat (limited to 'django/utils')
-rw-r--r--django/utils/asyncio.py25
-rw-r--r--django/utils/cache.py2
-rw-r--r--django/utils/crypto.py17
-rw-r--r--django/utils/http.py80
-rw-r--r--django/utils/timezone.py7
5 files changed, 5 insertions, 126 deletions
diff --git a/django/utils/asyncio.py b/django/utils/asyncio.py
index eea2df48e2..1e79f90c2c 100644
--- a/django/utils/asyncio.py
+++ b/django/utils/asyncio.py
@@ -37,28 +37,3 @@ def async_unsafe(message):
return decorator(func)
else:
return decorator
-
-
-try:
- from contextlib import aclosing
-except ImportError:
- # TODO: Remove when dropping support for PY39.
- from contextlib import AbstractAsyncContextManager
-
- # Backport of contextlib.aclosing() from Python 3.10. Copyright (C) Python
- # Software Foundation (see LICENSE.python).
- class aclosing(AbstractAsyncContextManager):
- """
- Async context manager for safely finalizing an asynchronously
- cleaned-up resource such as an async generator, calling its
- ``aclose()`` method.
- """
-
- def __init__(self, thing):
- self.thing = thing
-
- async def __aenter__(self):
- return self.thing
-
- async def __aexit__(self, *exc_info):
- await self.thing.aclose()
diff --git a/django/utils/cache.py b/django/utils/cache.py
index 2dd2c7796c..d4574217f4 100644
--- a/django/utils/cache.py
+++ b/django/utils/cache.py
@@ -16,11 +16,11 @@ An example: i18n middleware would need to distinguish caches by the
"""
import time
from collections import defaultdict
+from hashlib import md5
from django.conf import settings
from django.core.cache import caches
from django.http import HttpResponse, HttpResponseNotModified
-from django.utils.crypto import md5
from django.utils.http import http_date, parse_etags, parse_http_date_safe, quote_etag
from django.utils.log import log_response
from django.utils.regex_helper import _lazy_re_compile
diff --git a/django/utils/crypto.py b/django/utils/crypto.py
index 341cb742c1..1c0e7001c6 100644
--- a/django/utils/crypto.py
+++ b/django/utils/crypto.py
@@ -7,7 +7,6 @@ import secrets
from django.conf import settings
from django.utils.encoding import force_bytes
-from django.utils.inspect import func_supports_parameter
class InvalidAlgorithm(ValueError):
@@ -75,19 +74,3 @@ def pbkdf2(password, salt, iterations, dklen=0, digest=None):
password = force_bytes(password)
salt = force_bytes(salt)
return hashlib.pbkdf2_hmac(digest().name, password, salt, iterations, dklen)
-
-
-# TODO: Remove when dropping support for PY38. inspect.signature() is used to
-# detect whether the usedforsecurity argument is available as this fix may also
-# have been applied by downstream package maintainers to other versions in
-# their repositories.
-if func_supports_parameter(hashlib.md5, "usedforsecurity"):
- md5 = hashlib.md5
- new_hash = hashlib.new
-else:
-
- def md5(data=b"", *, usedforsecurity=True):
- return hashlib.md5(data)
-
- def new_hash(hash_algorithm, *, usedforsecurity=True):
- return hashlib.new(hash_algorithm)
diff --git a/django/utils/http.py b/django/utils/http.py
index 3e7acb5835..8fd40c27af 100644
--- a/django/utils/http.py
+++ b/django/utils/http.py
@@ -4,18 +4,9 @@ import re
import unicodedata
from binascii import Error as BinasciiError
from email.utils import formatdate
-from urllib.parse import (
- ParseResult,
- SplitResult,
- _coerce_args,
- _splitnetloc,
- _splitparams,
- quote,
- scheme_chars,
- unquote,
-)
+from urllib.parse import quote, unquote
from urllib.parse import urlencode as original_urlencode
-from urllib.parse import uses_params
+from urllib.parse import urlparse
from django.utils.datastructures import MultiValueDict
from django.utils.regex_helper import _lazy_re_compile
@@ -47,10 +38,6 @@ ASCTIME_DATE = _lazy_re_compile(r"^\w{3} %s %s %s %s$" % (__M, __D2, __T, __Y))
RFC3986_GENDELIMS = ":/?#[]@"
RFC3986_SUBDELIMS = "!$&'()*+,;="
-# TODO: Remove when dropping support for PY38.
-# Unsafe bytes to be removed per WHATWG spec.
-_UNSAFE_URL_BYTES_TO_REMOVE = ["\t", "\r", "\n"]
-
def urlencode(query, doseq=False):
"""
@@ -283,74 +270,13 @@ def url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False):
)
-# TODO: Remove when dropping support for PY38.
-# Copied from urllib.parse.urlparse() but uses fixed urlsplit() function.
-def _urlparse(url, scheme="", allow_fragments=True):
- """Parse a URL into 6 components:
- <scheme>://<netloc>/<path>;<params>?<query>#<fragment>
- Return a 6-tuple: (scheme, netloc, path, params, query, fragment).
- Note that we don't break the components up in smaller bits
- (e.g. netloc is a single string) and we don't expand % escapes."""
- url, scheme, _coerce_result = _coerce_args(url, scheme)
- splitresult = _urlsplit(url, scheme, allow_fragments)
- scheme, netloc, url, query, fragment = splitresult
- if scheme in uses_params and ";" in url:
- url, params = _splitparams(url)
- else:
- params = ""
- result = ParseResult(scheme, netloc, url, params, query, fragment)
- return _coerce_result(result)
-
-
-# TODO: Remove when dropping support for PY38.
-def _remove_unsafe_bytes_from_url(url):
- for b in _UNSAFE_URL_BYTES_TO_REMOVE:
- url = url.replace(b, "")
- return url
-
-
-# TODO: Remove when dropping support for PY38.
-# Backport of urllib.parse.urlsplit() from Python 3.9.
-def _urlsplit(url, scheme="", allow_fragments=True):
- """Parse a URL into 5 components:
- <scheme>://<netloc>/<path>?<query>#<fragment>
- Return a 5-tuple: (scheme, netloc, path, query, fragment).
- Note that we don't break the components up in smaller bits
- (e.g. netloc is a single string) and we don't expand % escapes."""
- url, scheme, _coerce_result = _coerce_args(url, scheme)
- url = _remove_unsafe_bytes_from_url(url)
- scheme = _remove_unsafe_bytes_from_url(scheme)
-
- netloc = query = fragment = ""
- i = url.find(":")
- if i > 0:
- for c in url[:i]:
- if c not in scheme_chars:
- break
- else:
- scheme, url = url[:i].lower(), url[i + 1 :]
-
- if url[:2] == "//":
- netloc, url = _splitnetloc(url, 2)
- if ("[" in netloc and "]" not in netloc) or (
- "]" in netloc and "[" not in netloc
- ):
- raise ValueError("Invalid IPv6 URL")
- if allow_fragments and "#" in url:
- url, fragment = url.split("#", 1)
- if "?" in url:
- url, query = url.split("?", 1)
- v = SplitResult(scheme, netloc, url, query, fragment)
- return _coerce_result(v)
-
-
def _url_has_allowed_host_and_scheme(url, allowed_hosts, require_https=False):
# Chrome considers any URL with more than two slashes to be absolute, but
# urlparse is not so flexible. Treat any url with three slashes as unsafe.
if url.startswith("///"):
return False
try:
- url_info = _urlparse(url)
+ url_info = urlparse(url)
except ValueError: # e.g. invalid IPv6 addresses
return False
# Forbid URLs like http:///example.com - with a scheme, but without a hostname.
diff --git a/django/utils/timezone.py b/django/utils/timezone.py
index ca9c817345..102562b254 100644
--- a/django/utils/timezone.py
+++ b/django/utils/timezone.py
@@ -3,12 +3,7 @@ Timezone-related classes and functions.
"""
import functools
-
-try:
- import zoneinfo
-except ImportError:
- from backports import zoneinfo
-
+import zoneinfo
from contextlib import ContextDecorator
from datetime import datetime, timedelta, timezone, tzinfo