mirror of
https://github.com/django/django.git
synced 2025-10-31 09:41:08 +00:00
Refs #32365 -- Removed support for pytz timezones per deprecation timeline.
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 ""
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user