summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2023-01-09 09:03:38 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-01-17 11:49:15 +0100
commite6f82438d4e3750e8d299bfd79dac98eebe9f1e0 (patch)
tree4ee0cbf2c0be9822416aa3d65105f35a9784fd94 /django
parent8d98f99a4ab5de6f2c730399f53eba8bf6bea470 (diff)
Refs #32365 -- Removed support for pytz timezones per deprecation timeline.
Diffstat (limited to 'django')
-rw-r--r--django/conf/__init__.py11
-rw-r--r--django/conf/global_settings.py5
-rw-r--r--django/contrib/admin/templatetags/admin_list.py15
-rw-r--r--django/db/backends/base/base.py11
-rw-r--r--django/db/backends/sqlite3/_functions.py10
-rw-r--r--django/forms/utils.py4
-rw-r--r--django/templatetags/tz.py29
-rw-r--r--django/utils/timezone.py72
8 files changed, 21 insertions, 136 deletions
diff --git a/django/conf/__init__.py b/django/conf/__init__.py
index 3d1d65c44d..ea63a0dfb2 100644
--- a/django/conf/__init__.py
+++ b/django/conf/__init__.py
@@ -24,12 +24,6 @@ DEFAULT_STORAGE_ALIAS = "default"
STATICFILES_STORAGE_ALIAS = "staticfiles"
# RemovedInDjango50Warning
-USE_DEPRECATED_PYTZ_DEPRECATED_MSG = (
- "The USE_DEPRECATED_PYTZ setting, and support for pytz timezones is "
- "deprecated in favor of the stdlib zoneinfo module. Please update your "
- "code to use zoneinfo and remove the USE_DEPRECATED_PYTZ setting."
-)
-
CSRF_COOKIE_MASKED_DEPRECATED_MSG = (
"The CSRF_COOKIE_MASKED transitional setting is deprecated. Support for "
"it will be removed in Django 5.0."
@@ -217,9 +211,6 @@ class Settings:
setattr(self, setting, setting_value)
self._explicit_settings.add(setting)
- if self.is_overridden("USE_DEPRECATED_PYTZ"):
- warnings.warn(USE_DEPRECATED_PYTZ_DEPRECATED_MSG, RemovedInDjango50Warning)
-
if self.is_overridden("CSRF_COOKIE_MASKED"):
warnings.warn(CSRF_COOKIE_MASKED_DEPRECATED_MSG, RemovedInDjango50Warning)
@@ -294,8 +285,6 @@ class UserSettingsHolder:
}
warnings.warn(STATICFILES_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning)
super().__setattr__(name, value)
- if name == "USE_DEPRECATED_PYTZ":
- warnings.warn(USE_DEPRECATED_PYTZ_DEPRECATED_MSG, RemovedInDjango50Warning)
# RemovedInDjango51Warning.
if name == "STORAGES":
self.STORAGES.setdefault(
diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py
index 411a5a4fe2..6d4ea3db5c 100644
--- a/django/conf/global_settings.py
+++ b/django/conf/global_settings.py
@@ -43,11 +43,6 @@ TIME_ZONE = "America/Chicago"
# If you set this to True, Django will use timezone-aware datetimes.
USE_TZ = True
-# RemovedInDjango50Warning: It's a transitional setting helpful in migrating
-# from pytz tzinfo to ZoneInfo(). Set True to continue using pytz tzinfo
-# objects during the Django 4.x release cycle.
-USE_DEPRECATED_PYTZ = False
-
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = "en-us"
diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py
index 5865843dce..ee6f3a7666 100644
--- a/django/contrib/admin/templatetags/admin_list.py
+++ b/django/contrib/admin/templatetags/admin_list.py
@@ -1,6 +1,5 @@
import datetime
-from django.conf import settings
from django.contrib.admin.templatetags.admin_urls import add_preserved_filters
from django.contrib.admin.utils import (
display_for_field,
@@ -357,10 +356,8 @@ def date_hierarchy(cl):
field = get_fields_from_path(cl.model, field_name)[-1]
if isinstance(field, models.DateTimeField):
dates_or_datetimes = "datetimes"
- qs_kwargs = {"is_dst": True} if settings.USE_DEPRECATED_PYTZ else {}
else:
dates_or_datetimes = "dates"
- qs_kwargs = {}
year_field = "%s__year" % field_name
month_field = "%s__month" % field_name
day_field = "%s__day" % field_name
@@ -401,9 +398,7 @@ def date_hierarchy(cl):
],
}
elif year_lookup and month_lookup:
- days = getattr(cl.queryset, dates_or_datetimes)(
- field_name, "day", **qs_kwargs
- )
+ days = getattr(cl.queryset, dates_or_datetimes)(field_name, "day")
return {
"show": True,
"back": {
@@ -425,9 +420,7 @@ def date_hierarchy(cl):
],
}
elif year_lookup:
- months = getattr(cl.queryset, dates_or_datetimes)(
- field_name, "month", **qs_kwargs
- )
+ months = getattr(cl.queryset, dates_or_datetimes)(field_name, "month")
return {
"show": True,
"back": {"link": link({}), "title": _("All dates")},
@@ -444,9 +437,7 @@ def date_hierarchy(cl):
],
}
else:
- years = getattr(cl.queryset, dates_or_datetimes)(
- field_name, "year", **qs_kwargs
- )
+ years = getattr(cl.queryset, dates_or_datetimes)(field_name, "year")
return {
"show": True,
"back": None,
diff --git a/django/db/backends/base/base.py b/django/db/backends/base/base.py
index 3b845ec9b3..5f2e7bcd4d 100644
--- a/django/db/backends/base/base.py
+++ b/django/db/backends/base/base.py
@@ -32,15 +32,6 @@ RAN_DB_VERSION_CHECK = set()
logger = logging.getLogger("django.db.backends.base")
-# RemovedInDjango50Warning
-def timezone_constructor(tzname):
- if settings.USE_DEPRECATED_PYTZ:
- import pytz
-
- return pytz.timezone(tzname)
- return zoneinfo.ZoneInfo(tzname)
-
-
class BaseDatabaseWrapper:
"""Represent a database connection."""
@@ -166,7 +157,7 @@ class BaseDatabaseWrapper:
elif self.settings_dict["TIME_ZONE"] is None:
return datetime.timezone.utc
else:
- return timezone_constructor(self.settings_dict["TIME_ZONE"])
+ return zoneinfo.ZoneInfo(self.settings_dict["TIME_ZONE"])
@cached_property
def timezone_name(self):
diff --git a/django/db/backends/sqlite3/_functions.py b/django/db/backends/sqlite3/_functions.py
index b590111ec5..c60549f8af 100644
--- a/django/db/backends/sqlite3/_functions.py
+++ b/django/db/backends/sqlite3/_functions.py
@@ -26,7 +26,6 @@ from math import (
)
from re import search as re_search
-from django.db.backends.base.base import timezone_constructor
from django.db.backends.utils import (
split_tzname_delta,
typecast_time,
@@ -36,6 +35,11 @@ from django.utils import timezone
from django.utils.crypto import md5
from django.utils.duration import duration_microseconds
+try:
+ import zoneinfo
+except ImportError:
+ from backports import zoneinfo
+
def register(connection):
create_deterministic_function = functools.partial(
@@ -111,14 +115,14 @@ def _sqlite_datetime_parse(dt, tzname=None, conn_tzname=None):
except (TypeError, ValueError):
return None
if conn_tzname:
- dt = dt.replace(tzinfo=timezone_constructor(conn_tzname))
+ dt = dt.replace(tzinfo=zoneinfo.ZoneInfo(conn_tzname))
if tzname is not None and tzname != conn_tzname:
tzname, sign, offset = split_tzname_delta(tzname)
if offset:
hours, minutes = offset.split(":")
offset_delta = timedelta(hours=int(hours), minutes=int(minutes))
dt += offset_delta if sign == "+" else -offset_delta
- dt = timezone.localtime(dt, timezone_constructor(tzname))
+ dt = timezone.localtime(dt, zoneinfo.ZoneInfo(tzname))
return dt
diff --git a/django/forms/utils.py b/django/forms/utils.py
index 905babce4d..7577c0bbda 100644
--- a/django/forms/utils.py
+++ b/django/forms/utils.py
@@ -215,9 +215,7 @@ def from_current_timezone(value):
if settings.USE_TZ and value is not None and timezone.is_naive(value):
current_timezone = timezone.get_current_timezone()
try:
- if not timezone._is_pytz_zone(
- current_timezone
- ) and timezone._datetime_ambiguous_or_imaginary(value, current_timezone):
+ if timezone._datetime_ambiguous_or_imaginary(value, current_timezone):
raise ValueError("Ambiguous or non-existent time.")
return timezone.make_aware(value, current_timezone)
except Exception as exc:
diff --git a/django/templatetags/tz.py b/django/templatetags/tz.py
index cb7d22e5f2..92240b2a39 100644
--- a/django/templatetags/tz.py
+++ b/django/templatetags/tz.py
@@ -7,34 +7,12 @@ try:
except ImportError:
from backports import zoneinfo
-from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from django.utils import timezone
register = Library()
-# RemovedInDjango50Warning: shim to allow catching the exception in the calling
-# scope if pytz is not installed.
-class UnknownTimezoneException(BaseException):
- pass
-
-
-# RemovedInDjango50Warning
-def timezone_constructor(tzname):
- if settings.USE_DEPRECATED_PYTZ:
- import pytz
-
- try:
- return pytz.timezone(tzname)
- except pytz.UnknownTimeZoneError:
- raise UnknownTimezoneException
- try:
- return zoneinfo.ZoneInfo(tzname)
- except zoneinfo.ZoneInfoNotFoundError:
- raise UnknownTimezoneException
-
-
# HACK: datetime instances cannot be assigned new attributes. Define a subclass
# in order to define new attributes in do_timezone().
class datetimeobject(datetime):
@@ -79,8 +57,7 @@ def do_timezone(value, arg):
if timezone.is_naive(value):
default_timezone = timezone.get_default_timezone()
value = timezone.make_aware(value, default_timezone)
- # Filters must never raise exceptions, and pytz' exceptions inherit
- # Exception directly, not a specific subclass. So catch everything.
+ # Filters must never raise exceptionsm, so catch everything.
except Exception:
return ""
@@ -89,8 +66,8 @@ def do_timezone(value, arg):
tz = arg
elif isinstance(arg, str):
try:
- tz = timezone_constructor(arg)
- except UnknownTimezoneException:
+ tz = zoneinfo.ZoneInfo(arg)
+ except zoneinfo.ZoneInfoNotFoundError:
return ""
else:
return ""
diff --git a/django/utils/timezone.py b/django/utils/timezone.py
index f3eac0e7b2..73813fa20e 100644
--- a/django/utils/timezone.py
+++ b/django/utils/timezone.py
@@ -3,7 +3,6 @@ Timezone-related classes and functions.
"""
import functools
-import sys
import warnings
try:
@@ -75,10 +74,6 @@ def get_default_timezone():
This is the time zone defined by settings.TIME_ZONE.
"""
- if settings.USE_DEPRECATED_PYTZ:
- import pytz
-
- return pytz.timezone(settings.TIME_ZONE)
return zoneinfo.ZoneInfo(settings.TIME_ZONE)
@@ -125,12 +120,7 @@ def activate(timezone):
if isinstance(timezone, tzinfo):
_active.value = timezone
elif isinstance(timezone, str):
- if settings.USE_DEPRECATED_PYTZ:
- import pytz
-
- _active.value = pytz.timezone(timezone)
- else:
- _active.value = zoneinfo.ZoneInfo(timezone)
+ _active.value = zoneinfo.ZoneInfo(timezone)
else:
raise ValueError("Invalid timezone: %r" % timezone)
@@ -282,15 +272,11 @@ def make_aware(value, timezone=None, is_dst=NOT_PASSED):
)
if timezone is None:
timezone = get_current_timezone()
- if _is_pytz_zone(timezone):
- # This method is available for pytz time zones.
- return timezone.localize(value, is_dst=is_dst)
- else:
- # Check that we won't overwrite the timezone of an aware datetime.
- if is_aware(value):
- raise ValueError("make_aware expects a naive datetime, got %s" % value)
- # This may be wrong around DST changes!
- return value.replace(tzinfo=timezone)
+ # Check that we won't overwrite the timezone of an aware datetime.
+ if is_aware(value):
+ raise ValueError("make_aware expects a naive datetime, got %s" % value)
+ # This may be wrong around DST changes!
+ return value.replace(tzinfo=timezone)
def make_naive(value, timezone=None):
@@ -303,53 +289,7 @@ def make_naive(value, timezone=None):
return value.astimezone(timezone).replace(tzinfo=None)
-_PYTZ_IMPORTED = False
-
-
-def _pytz_imported():
- """
- Detects whether or not pytz has been imported without importing pytz.
-
- Copied from pytz_deprecation_shim with thanks to Paul Ganssle.
- """
- global _PYTZ_IMPORTED
-
- if not _PYTZ_IMPORTED and "pytz" in sys.modules:
- _PYTZ_IMPORTED = True
-
- return _PYTZ_IMPORTED
-
-
-def _is_pytz_zone(tz):
- """Checks if a zone is a pytz zone."""
- # See if pytz was already imported rather than checking
- # settings.USE_DEPRECATED_PYTZ to *allow* manually passing a pytz timezone,
- # which some of the test cases (at least) rely on.
- if not _pytz_imported():
- return False
-
- # If tz could be pytz, then pytz is needed here.
- import pytz
-
- _PYTZ_BASE_CLASSES = (pytz.tzinfo.BaseTzInfo, pytz._FixedOffset)
- # In releases prior to 2018.4, pytz.UTC was not a subclass of BaseTzInfo
- if not isinstance(pytz.UTC, pytz._FixedOffset):
- _PYTZ_BASE_CLASSES += (type(pytz.UTC),)
-
- return isinstance(tz, _PYTZ_BASE_CLASSES)
-
-
def _datetime_ambiguous_or_imaginary(dt, tz):
- if _is_pytz_zone(tz):
- import pytz
-
- try:
- tz.utcoffset(dt)
- except (pytz.AmbiguousTimeError, pytz.NonExistentTimeError):
- return True
- else:
- return False
-
return tz.utcoffset(dt.replace(fold=not dt.fold)) != tz.utcoffset(dt)