diff options
| author | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2023-01-09 09:03:38 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2023-01-17 11:49:15 +0100 |
| commit | e6f82438d4e3750e8d299bfd79dac98eebe9f1e0 (patch) | |
| tree | 4ee0cbf2c0be9822416aa3d65105f35a9784fd94 /django | |
| parent | 8d98f99a4ab5de6f2c730399f53eba8bf6bea470 (diff) | |
Refs #32365 -- Removed support for pytz timezones per deprecation timeline.
Diffstat (limited to 'django')
| -rw-r--r-- | django/conf/__init__.py | 11 | ||||
| -rw-r--r-- | django/conf/global_settings.py | 5 | ||||
| -rw-r--r-- | django/contrib/admin/templatetags/admin_list.py | 15 | ||||
| -rw-r--r-- | django/db/backends/base/base.py | 11 | ||||
| -rw-r--r-- | django/db/backends/sqlite3/_functions.py | 10 | ||||
| -rw-r--r-- | django/forms/utils.py | 4 | ||||
| -rw-r--r-- | django/templatetags/tz.py | 29 | ||||
| -rw-r--r-- | django/utils/timezone.py | 72 |
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) |
