Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
__init__.py168 linesDownload Raw Back to zoneinfo
1# -*- coding: utf-8 -*-2import warnings3import json4 5from tarfile import TarFile6from pkgutil import get_data7from io import BytesIO8 9from dateutil.tz import tzfile as _tzfile10 11__all__ = ["get_zonefile_instance", "gettz", "gettz_db_metadata"]12 13ZONEFILENAME = "dateutil-zoneinfo.tar.gz"14METADATA_FN = 'METADATA'15 16 17class tzfile(_tzfile):18    def __reduce__(self):19        return (gettz, (self._filename,))20 21 22def getzoneinfofile_stream():23    try:24        return BytesIO(get_data(__name__, ZONEFILENAME))25    except IOError as e:  # TODO  switch to FileNotFoundError?26        warnings.warn("I/O error({0}): {1}".format(e.errno, e.strerror))27        return None28 29 30class ZoneInfoFile(object):31    def __init__(self, zonefile_stream=None):32        if zonefile_stream is not None:33            with TarFile.open(fileobj=zonefile_stream) as tf:34                self.zones = {zf.name: tzfile(tf.extractfile(zf), filename=zf.name)35                              for zf in tf.getmembers()36                              if zf.isfile() and zf.name != METADATA_FN}37                # deal with links: They'll point to their parent object. Less38                # waste of memory39                links = {zl.name: self.zones[zl.linkname]40                         for zl in tf.getmembers() if41                         zl.islnk() or zl.issym()}42                self.zones.update(links)43                try:44                    metadata_json = tf.extractfile(tf.getmember(METADATA_FN))45                    metadata_str = metadata_json.read().decode('UTF-8')46                    self.metadata = json.loads(metadata_str)47                except KeyError:48                    # no metadata in tar file49                    self.metadata = None50        else:51            self.zones = {}52            self.metadata = None53 54    def get(self, name, default=None):55        """56        Wrapper for :func:`ZoneInfoFile.zones.get`. This is a convenience method57        for retrieving zones from the zone dictionary.58 59        :param name:60            The name of the zone to retrieve. (Generally IANA zone names)61 62        :param default:63            The value to return in the event of a missing key.64 65        .. versionadded:: 2.6.066 67        """68        return self.zones.get(name, default)69 70 71# The current API has gettz as a module function, although in fact it taps into72# a stateful class. So as a workaround for now, without changing the API, we73# will create a new "global" class instance the first time a user requests a74# timezone. Ugly, but adheres to the api.75#76# TODO: Remove after deprecation period.77_CLASS_ZONE_INSTANCE = []78 79 80def get_zonefile_instance(new_instance=False):81    """82    This is a convenience function which provides a :class:`ZoneInfoFile`83    instance using the data provided by the ``dateutil`` package. By default, it84    caches a single instance of the ZoneInfoFile object and returns that.85 86    :param new_instance:87        If ``True``, a new instance of :class:`ZoneInfoFile` is instantiated and88        used as the cached instance for the next call. Otherwise, new instances89        are created only as necessary.90 91    :return:92        Returns a :class:`ZoneInfoFile` object.93 94    .. versionadded:: 2.695    """96    if new_instance:97        zif = None98    else:99        zif = getattr(get_zonefile_instance, '_cached_instance', None)100 101    if zif is None:102        zif = ZoneInfoFile(getzoneinfofile_stream())103 104        get_zonefile_instance._cached_instance = zif105 106    return zif107 108 109def gettz(name):110    """111    This retrieves a time zone from the local zoneinfo tarball that is packaged112    with dateutil.113 114    :param name:115        An IANA-style time zone name, as found in the zoneinfo file.116 117    :return:118        Returns a :class:`dateutil.tz.tzfile` time zone object.119 120    .. warning::121        It is generally inadvisable to use this function, and it is only122        provided for API compatibility with earlier versions. This is *not*123        equivalent to ``dateutil.tz.gettz()``, which selects an appropriate124        time zone based on the inputs, favoring system zoneinfo. This is ONLY125        for accessing the dateutil-specific zoneinfo (which may be out of126        date compared to the system zoneinfo).127 128    .. deprecated:: 2.6129        If you need to use a specific zoneinfofile over the system zoneinfo,130        instantiate a :class:`dateutil.zoneinfo.ZoneInfoFile` object and call131        :func:`dateutil.zoneinfo.ZoneInfoFile.get(name)` instead.132 133        Use :func:`get_zonefile_instance` to retrieve an instance of the134        dateutil-provided zoneinfo.135    """136    warnings.warn("zoneinfo.gettz() will be removed in future versions, "137                  "to use the dateutil-provided zoneinfo files, instantiate a "138                  "ZoneInfoFile object and use ZoneInfoFile.zones.get() "139                  "instead. See the documentation for details.",140                  DeprecationWarning)141 142    if len(_CLASS_ZONE_INSTANCE) == 0:143        _CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream()))144    return _CLASS_ZONE_INSTANCE[0].zones.get(name)145 146 147def gettz_db_metadata():148    """ Get the zonefile metadata149 150    See `zonefile_metadata`_151 152    :returns:153        A dictionary with the database metadata154 155    .. deprecated:: 2.6156        See deprecation warning in :func:`zoneinfo.gettz`. To get metadata,157        query the attribute ``zoneinfo.ZoneInfoFile.metadata``.158    """159    warnings.warn("zoneinfo.gettz_db_metadata() will be removed in future "160                  "versions, to use the dateutil-provided zoneinfo files, "161                  "ZoneInfoFile object and query the 'metadata' attribute "162                  "instead. See the documentation for details.",163                  DeprecationWarning)164 165    if len(_CLASS_ZONE_INSTANCE) == 0:166        _CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream()))167    return _CLASS_ZONE_INSTANCE[0].metadata168 
codekingpro/portable-devtools · Team Ai