diff options
author | noptuno <repollo.marrero@gmail.com> | 2023-04-28 02:40:47 +0200 |
---|---|---|
committer | noptuno <repollo.marrero@gmail.com> | 2023-04-28 02:40:47 +0200 |
commit | 6f6a73987201c9c303047c61389b82ad98b15597 (patch) | |
tree | bf67eb590d49979d6740bc1e94b4018df48bce98 /venv/lib/python3.9/site-packages/pytz_deprecation_shim | |
parent | Resolved merge conflicts and merged pr_218 into STREAMLIT_CHAT_IMPLEMENTATION (diff) | |
parent | Merging PR_218 openai_rev package with new streamlit chat app (diff) | |
download | gpt4free-6f6a73987201c9c303047c61389b82ad98b15597.tar gpt4free-6f6a73987201c9c303047c61389b82ad98b15597.tar.gz gpt4free-6f6a73987201c9c303047c61389b82ad98b15597.tar.bz2 gpt4free-6f6a73987201c9c303047c61389b82ad98b15597.tar.lz gpt4free-6f6a73987201c9c303047c61389b82ad98b15597.tar.xz gpt4free-6f6a73987201c9c303047c61389b82ad98b15597.tar.zst gpt4free-6f6a73987201c9c303047c61389b82ad98b15597.zip |
Diffstat (limited to 'venv/lib/python3.9/site-packages/pytz_deprecation_shim')
8 files changed, 624 insertions, 0 deletions
diff --git a/venv/lib/python3.9/site-packages/pytz_deprecation_shim/__init__.py b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/__init__.py new file mode 100644 index 00000000..8b451620 --- /dev/null +++ b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/__init__.py @@ -0,0 +1,34 @@ +__all__ = [ + "AmbiguousTimeError", + "NonExistentTimeError", + "InvalidTimeError", + "UnknownTimeZoneError", + "PytzUsageWarning", + "FixedOffset", + "UTC", + "utc", + "build_tzinfo", + "timezone", + "fixed_offset_timezone", + "wrap_zone", +] + +from . import helpers +from ._exceptions import ( + AmbiguousTimeError, + InvalidTimeError, + NonExistentTimeError, + PytzUsageWarning, + UnknownTimeZoneError, +) +from ._impl import ( + UTC, + build_tzinfo, + fixed_offset_timezone, + timezone, + wrap_zone, +) + +# Compatibility aliases +utc = UTC +FixedOffset = fixed_offset_timezone diff --git a/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_common.py b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_common.py new file mode 100644 index 00000000..ace322e9 --- /dev/null +++ b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_common.py @@ -0,0 +1,13 @@ +import sys + +_PYTZ_IMPORTED = False + + +def pytz_imported(): + """Detects whether or not pytz has been imported without importing pytz.""" + global _PYTZ_IMPORTED + + if not _PYTZ_IMPORTED and "pytz" in sys.modules: + _PYTZ_IMPORTED = True + + return _PYTZ_IMPORTED diff --git a/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_compat.py b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_compat.py new file mode 100644 index 00000000..5b734592 --- /dev/null +++ b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_compat.py @@ -0,0 +1,15 @@ +import sys + +if sys.version_info[0] == 2: + from . import _compat_py2 as _compat_impl +else: + from . import _compat_py3 as _compat_impl + +UTC = _compat_impl.UTC +get_timezone = _compat_impl.get_timezone +get_timezone_file = _compat_impl.get_timezone_file +get_fixed_offset_zone = _compat_impl.get_fixed_offset_zone +is_ambiguous = _compat_impl.is_ambiguous +is_imaginary = _compat_impl.is_imaginary +enfold = _compat_impl.enfold +get_fold = _compat_impl.get_fold diff --git a/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_compat_py2.py b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_compat_py2.py new file mode 100644 index 00000000..f473d267 --- /dev/null +++ b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_compat_py2.py @@ -0,0 +1,43 @@ +from datetime import timedelta + +from dateutil import tz + +UTC = tz.UTC + + +def get_timezone(key): + if not key: + raise KeyError("Unknown time zone: %s" % key) + + try: + rv = tz.gettz(key) + except Exception: + rv = None + + if rv is None or not isinstance(rv, (tz.tzutc, tz.tzfile)): + raise KeyError("Unknown time zone: %s" % key) + + return rv + + +def get_timezone_file(f, key=None): + return tz.tzfile(f) + + +def get_fixed_offset_zone(offset): + return tz.tzoffset(None, timedelta(minutes=offset)) + + +def is_ambiguous(dt): + return tz.datetime_ambiguous(dt) + + +def is_imaginary(dt): + return not tz.datetime_exists(dt) + + +enfold = tz.enfold + + +def get_fold(dt): + return getattr(dt, "fold", 0) diff --git a/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_compat_py3.py b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_compat_py3.py new file mode 100644 index 00000000..8881abac --- /dev/null +++ b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_compat_py3.py @@ -0,0 +1,58 @@ +# Note: This file could use Python 3-only syntax, but at the moment this breaks +# the coverage job on Python 2. Until we make it so that coverage can ignore +# this file only on Python 2, we'll have to stick to 2/3-compatible syntax. +try: + import zoneinfo +except ImportError: + from backports import zoneinfo + +import datetime + +UTC = datetime.timezone.utc + + +def get_timezone(key): + try: + return zoneinfo.ZoneInfo(key) + except (ValueError, OSError): + # TODO: Use `from e` when this file can use Python 3 syntax + raise KeyError(key) + + +def get_timezone_file(f, key=None): + return zoneinfo.ZoneInfo.from_file(f, key=key) + + +def get_fixed_offset_zone(offset): + return datetime.timezone(datetime.timedelta(minutes=offset)) + + +def is_imaginary(dt): + dt_rt = dt.astimezone(UTC).astimezone(dt.tzinfo) + + return not (dt == dt_rt) + + +def is_ambiguous(dt): + if is_imaginary(dt): + return False + + wall_0 = dt + wall_1 = dt.replace(fold=not dt.fold) + + # Ambiguous datetimes can only exist if the offset changes, so we don't + # actually have to check whether dst() or tzname() are different. + same_offset = wall_0.utcoffset() == wall_1.utcoffset() + + return not same_offset + + +def enfold(dt, fold=1): + if dt.fold != fold: + return dt.replace(fold=fold) + else: + return dt + + +def get_fold(dt): + return dt.fold diff --git a/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_exceptions.py b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_exceptions.py new file mode 100644 index 00000000..58d7af0a --- /dev/null +++ b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_exceptions.py @@ -0,0 +1,75 @@ +from ._common import pytz_imported + + +class PytzUsageWarning(RuntimeWarning): + """Warning raised when accessing features specific to ``pytz``'s interface. + + This warning is used to direct users of ``pytz``-specific features like the + ``localize`` and ``normalize`` methods towards using the standard + ``tzinfo`` interface, so that these shims can be replaced with one of the + underlying libraries they are wrapping. + """ + + +class UnknownTimeZoneError(KeyError): + """Raised when no time zone is found for a specified key.""" + + +class InvalidTimeError(Exception): + """The base class for exceptions related to folds and gaps.""" + + +class AmbiguousTimeError(InvalidTimeError): + """Exception raised when ``is_dst=None`` for an ambiguous time (fold).""" + + +class NonExistentTimeError(InvalidTimeError): + """Exception raised when ``is_dst=None`` for a non-existent time (gap).""" + + +PYTZ_BASE_ERROR_MAPPING = {} + + +def _make_pytz_derived_errors( + InvalidTimeError_=InvalidTimeError, + AmbiguousTimeError_=AmbiguousTimeError, + NonExistentTimeError_=NonExistentTimeError, + UnknownTimeZoneError_=UnknownTimeZoneError, +): + if PYTZ_BASE_ERROR_MAPPING or not pytz_imported(): + return + + import pytz + + class InvalidTimeError(InvalidTimeError_, pytz.InvalidTimeError): + pass + + class AmbiguousTimeError(AmbiguousTimeError_, pytz.AmbiguousTimeError): + pass + + class NonExistentTimeError( + NonExistentTimeError_, pytz.NonExistentTimeError + ): + pass + + class UnknownTimeZoneError( + UnknownTimeZoneError_, pytz.UnknownTimeZoneError + ): + pass + + PYTZ_BASE_ERROR_MAPPING.update( + { + InvalidTimeError_: InvalidTimeError, + AmbiguousTimeError_: AmbiguousTimeError, + NonExistentTimeError_: NonExistentTimeError, + UnknownTimeZoneError_: UnknownTimeZoneError, + } + ) + + +def get_exception(exc_type, msg): + _make_pytz_derived_errors() + + out_exc_type = PYTZ_BASE_ERROR_MAPPING.get(exc_type, exc_type) + + return out_exc_type(msg) diff --git a/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_impl.py b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_impl.py new file mode 100644 index 00000000..54430479 --- /dev/null +++ b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/_impl.py @@ -0,0 +1,296 @@ +# -*- coding: utf-8 -*- +import warnings +from datetime import tzinfo + +from . import _compat +from ._exceptions import ( + AmbiguousTimeError, + NonExistentTimeError, + PytzUsageWarning, + UnknownTimeZoneError, + get_exception, +) + +IS_DST_SENTINEL = object() +KEY_SENTINEL = object() + + +def timezone(key, _cache={}): + """Builds an IANA database time zone shim. + + This is the equivalent of ``pytz.timezone``. + + :param key: + A valid key from the IANA time zone database. + + :raises UnknownTimeZoneError: + If an unknown value is passed, this will raise an exception that can be + caught by :exc:`pytz_deprecation_shim.UnknownTimeZoneError` or + ``pytz.UnknownTimeZoneError``. Like + :exc:`zoneinfo.ZoneInfoNotFoundError`, both of those are subclasses of + :exc:`KeyError`. + """ + instance = _cache.get(key, None) + if instance is None: + if len(key) == 3 and key.lower() == "utc": + instance = _cache.setdefault(key, UTC) + else: + try: + zone = _compat.get_timezone(key) + except KeyError: + raise get_exception(UnknownTimeZoneError, key) + instance = _cache.setdefault(key, wrap_zone(zone, key=key)) + + return instance + + +def fixed_offset_timezone(offset, _cache={}): + """Builds a fixed offset time zone shim. + + This is the equivalent of ``pytz.FixedOffset``. An alias is available as + ``pytz_deprecation_shim.FixedOffset`` as well. + + :param offset: + A fixed offset from UTC, in minutes. This must be in the range ``-1439 + <= offset <= 1439``. + + :raises ValueError: + For offsets whose absolute value is greater than or equal to 24 hours. + + :return: + A shim time zone. + """ + if not (-1440 < offset < 1440): + raise ValueError("absolute offset is too large", offset) + + instance = _cache.get(offset, None) + if instance is None: + if offset == 0: + instance = _cache.setdefault(offset, UTC) + else: + zone = _compat.get_fixed_offset_zone(offset) + instance = _cache.setdefault(offset, wrap_zone(zone, key=None)) + + return instance + + +def build_tzinfo(zone, fp): + """Builds a shim object from a TZif file. + + This is a shim for ``pytz.build_tzinfo``. Given a value to use as the zone + IANA key and a file-like object containing a valid TZif file (i.e. + conforming to :rfc:`8536`), this builds a time zone object and wraps it in + a shim class. + + The argument names are chosen to match those in ``pytz.build_tzinfo``. + + :param zone: + A string to be used as the time zone object's IANA key. + + :param fp: + A readable file-like object emitting bytes, pointing to a valid TZif + file. + + :return: + A shim time zone. + """ + zone_file = _compat.get_timezone_file(fp) + + return wrap_zone(zone_file, key=zone) + + +def wrap_zone(tz, key=KEY_SENTINEL, _cache={}): + """Wrap an existing time zone object in a shim class. + + This is likely to be useful if you would like to work internally with + non-``pytz`` zones, but you expose an interface to callers relying on + ``pytz``'s interface. It may also be useful for passing non-``pytz`` zones + to libraries expecting to use ``pytz``'s interface. + + :param tz: + A :pep:`495`-compatible time zone, such as those provided by + :mod:`dateutil.tz` or :mod:`zoneinfo`. + + :param key: + The value for the IANA time zone key. This is optional for ``zoneinfo`` + zones, but required for ``dateutil.tz`` zones. + + :return: + A shim time zone. + """ + if key is KEY_SENTINEL: + key = getattr(tz, "key", KEY_SENTINEL) + + if key is KEY_SENTINEL: + raise TypeError( + "The `key` argument is required when wrapping zones that do not " + + "have a `key` attribute." + ) + + instance = _cache.get((id(tz), key), None) + if instance is None: + instance = _cache.setdefault((id(tz), key), _PytzShimTimezone(tz, key)) + + return instance + + +class _PytzShimTimezone(tzinfo): + # Add instance variables for _zone and _key because this will make error + # reporting with partially-initialized _BasePytzShimTimezone objects + # work better. + _zone = None + _key = None + + def __init__(self, zone, key): + self._key = key + self._zone = zone + + def utcoffset(self, dt): + return self._zone.utcoffset(dt) + + def dst(self, dt): + return self._zone.dst(dt) + + def tzname(self, dt): + return self._zone.tzname(dt) + + def fromutc(self, dt): + # The default fromutc implementation only works if tzinfo is "self" + dt_base = dt.replace(tzinfo=self._zone) + dt_out = self._zone.fromutc(dt_base) + + return dt_out.replace(tzinfo=self) + + def __str__(self): + if self._key is not None: + return str(self._key) + else: + return repr(self) + + def __repr__(self): + return "%s(%s, %s)" % ( + self.__class__.__name__, + repr(self._zone), + repr(self._key), + ) + + def unwrap_shim(self): + """Returns the underlying class that the shim is a wrapper for. + + This is a shim-specific method equivalent to + :func:`pytz_deprecation_shim.helpers.upgrade_tzinfo`. It is provided as + a method to allow end-users to upgrade shim timezones without requiring + an explicit dependency on ``pytz_deprecation_shim``, e.g.: + + .. code-block:: python + + if getattr(tz, "unwrap_shim", None) is None: + tz = tz.unwrap_shim() + """ + return self._zone + + @property + def zone(self): + warnings.warn( + "The zone attribute is specific to pytz's interface; " + + "please migrate to a new time zone provider. " + + "For more details on how to do so, see %s" + % PYTZ_MIGRATION_GUIDE_URL, + PytzUsageWarning, + stacklevel=2, + ) + + return self._key + + def localize(self, dt, is_dst=IS_DST_SENTINEL): + warnings.warn( + "The localize method is no longer necessary, as this " + + "time zone supports the fold attribute (PEP 495). " + + "For more details on migrating to a PEP 495-compliant " + + "implementation, see %s" % PYTZ_MIGRATION_GUIDE_URL, + PytzUsageWarning, + stacklevel=2, + ) + + if dt.tzinfo is not None: + raise ValueError("Not naive datetime (tzinfo is already set)") + + dt_out = dt.replace(tzinfo=self) + + if is_dst is IS_DST_SENTINEL: + return dt_out + + dt_ambiguous = _compat.is_ambiguous(dt_out) + dt_imaginary = ( + _compat.is_imaginary(dt_out) if not dt_ambiguous else False + ) + + if is_dst is None: + if dt_imaginary: + raise get_exception( + NonExistentTimeError, dt.replace(tzinfo=None) + ) + + if dt_ambiguous: + raise get_exception(AmbiguousTimeError, dt.replace(tzinfo=None)) + + elif dt_ambiguous or dt_imaginary: + # Start by normalizing the folds; dt_out may have fold=0 or fold=1, + # but we need to know the DST offset on both sides anyway, so we + # will get one datetime representing each side of the fold, then + # decide which one we're going to return. + if _compat.get_fold(dt_out): + dt_enfolded = dt_out + dt_out = _compat.enfold(dt_out, fold=0) + else: + dt_enfolded = _compat.enfold(dt_out, fold=1) + + # Now we want to decide whether the fold=0 or fold=1 represents + # what pytz would return for `is_dst=True` + enfolded_dst = bool(dt_enfolded.dst()) + if bool(dt_out.dst()) == enfolded_dst: + # If this is not a transition between standard time and + # daylight saving time, pytz will consider the larger offset + # the DST offset. + enfolded_dst = dt_enfolded.utcoffset() > dt_out.utcoffset() + + # The default we've established is that dt_out is fold=0; swap it + # for the fold=1 datetime if is_dst == True and the enfolded side + # is DST or if is_dst == False and the enfolded side is *not* DST. + if is_dst == enfolded_dst: + dt_out = dt_enfolded + + return dt_out + + def normalize(self, dt): + warnings.warn( + "The normalize method is no longer necessary, as this " + + "time zone supports the fold attribute (PEP 495). " + + "For more details on migrating to a PEP 495-compliant " + + "implementation, see %s" % PYTZ_MIGRATION_GUIDE_URL, + PytzUsageWarning, + stacklevel=2, + ) + + if dt.tzinfo is None: + raise ValueError("Naive time - no tzinfo set") + + if dt.tzinfo is self: + return dt + + return dt.astimezone(self) + + def __copy__(self): + return self + + def __deepcopy__(self, memo=None): + return self + + def __reduce__(self): + return wrap_zone, (self._zone, self._key) + + +UTC = wrap_zone(_compat.UTC, "UTC") +PYTZ_MIGRATION_GUIDE_URL = ( + "https://pytz-deprecation-shim.readthedocs.io/en/latest/migration.html" +) diff --git a/venv/lib/python3.9/site-packages/pytz_deprecation_shim/helpers.py b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/helpers.py new file mode 100644 index 00000000..6b05b130 --- /dev/null +++ b/venv/lib/python3.9/site-packages/pytz_deprecation_shim/helpers.py @@ -0,0 +1,90 @@ +""" +This module contains helper functions to ease the transition from ``pytz`` to +another :pep:`495`-compatible library. +""" +from . import _common, _compat +from ._impl import _PytzShimTimezone + +_PYTZ_BASE_CLASSES = None + + +def is_pytz_zone(tz): + """Check if a time zone is a ``pytz`` time zone. + + This will only import ``pytz`` if it has already been imported, and does + not rely on the existence of the ``localize`` or ``normalize`` methods + (since the shim classes also have these methods, but are not ``pytz`` + zones). + """ + + # If pytz is not in sys.modules, then we will assume the time zone is not a + # pytz zone. It is possible that someone has manipulated sys.modules to + # remove pytz, but that's the kind of thing that causes all kinds of other + # problems anyway, so we'll call that an unsupported configuration. + if not _common.pytz_imported(): + return False + + if _PYTZ_BASE_CLASSES is None: + _populate_pytz_base_classes() + + return isinstance(tz, _PYTZ_BASE_CLASSES) + + +def upgrade_tzinfo(tz): + """Convert a ``pytz`` or shim timezone into its modern equivalent. + + The shim classes are thin wrappers around :mod:`zoneinfo` or + :mod:`dateutil.tz` implementations of the :class:`datetime.tzinfo` base + class. This function removes the shim and returns the underlying "upgraded" + time zone. + + When passed a ``pytz`` zone (not a shim), this returns the non-``pytz`` + equivalent. This may fail if ``pytz`` is using a data source incompatible + with the upgraded provider's data source, or if the ``pytz`` zone was built + from a file rather than an IANA key. + + When passed an object that is not a shim or a ``pytz`` zone, this returns + the original object. + + :param tz: + A :class:`datetime.tzinfo` object. + + :raises KeyError: + If a ``pytz`` zone is passed to the function with no equivalent in the + :pep:`495`-compatible library's version of the Olson database. + + :return: + A :pep:`495`-compatible equivalent of any ``pytz`` or shim + class, or the original object. + """ + if isinstance(tz, _PytzShimTimezone): + return tz._zone + + if is_pytz_zone(tz): + if tz.zone is None: + # This is a fixed offset zone + offset = tz.utcoffset(None) + offset_minutes = offset.total_seconds() / 60 + + return _compat.get_fixed_offset_zone(offset_minutes) + + if tz.zone == "UTC": + return _compat.UTC + + return _compat.get_timezone(tz.zone) + + return tz + + +def _populate_pytz_base_classes(): + import pytz + from pytz.tzinfo import BaseTzInfo + + base_classes = (BaseTzInfo, pytz._FixedOffset) + + # In releases prior to 2018.4, pytz.UTC was not a subclass of BaseTzInfo + if not isinstance(pytz.UTC, BaseTzInfo): # pragma: nocover + base_classes = base_classes + (type(pytz.UTC),) + + global _PYTZ_BASE_CLASSES + _PYTZ_BASE_CLASSES = base_classes |