Update tzlocal==5.0.1

This commit is contained in:
JonnyWong16 2023-08-25 11:33:56 -07:00
parent 80e6131a0d
commit 85bc9c39ae
No known key found for this signature in database
GPG key ID: B1F1F9807184697A
6 changed files with 807 additions and 772 deletions

View file

@ -1,20 +1,21 @@
import logging
import os
import re
import sys
import warnings
from datetime import timezone
import pytz_deprecation_shim as pds
from tzlocal import utils
if sys.version_info >= (3, 9):
from zoneinfo import ZoneInfo # pragma: no cover
import zoneinfo # pragma: no cover
else:
from backports.zoneinfo import ZoneInfo # pragma: no cover
from backports import zoneinfo # pragma: no cover
_cache_tz = None
_cache_tz_name = None
log = logging.getLogger("tzlocal")
def _get_localzone_name(_root="/"):
"""Tries to find the local timezone configuration.
@ -32,14 +33,21 @@ def _get_localzone_name(_root="/"):
# Are we under Termux on Android?
if os.path.exists(os.path.join(_root, "system/bin/getprop")):
log.debug("This looks like Termux")
import subprocess
androidtz = (
subprocess.check_output(["getprop", "persist.sys.timezone"])
.strip()
.decode()
)
return androidtz
try:
androidtz = (
subprocess.check_output(["getprop", "persist.sys.timezone"])
.strip()
.decode()
)
return androidtz
except (OSError, subprocess.CalledProcessError):
# proot environment or failed to getprop
log.debug("It's not termux?")
pass
# Now look for distribution specific configuration files
# that contain the timezone name.
@ -50,10 +58,11 @@ def _get_localzone_name(_root="/"):
for configfile in ("etc/timezone", "var/db/zoneinfo"):
tzpath = os.path.join(_root, configfile)
try:
with open(tzpath, "rt") as tzfile:
with open(tzpath) as tzfile:
data = tzfile.read()
log.debug(f"{tzpath} found, contents:\n {data}")
etctz = data.strip('/ \t\r\n')
etctz = data.strip("/ \t\r\n")
if not etctz:
# Empty file, skip
continue
@ -68,7 +77,7 @@ def _get_localzone_name(_root="/"):
found_configs[tzpath] = etctz.replace(" ", "_")
except (IOError, UnicodeDecodeError):
except (OSError, UnicodeDecodeError):
# File doesn't exist or is a directory, or it's a binary file.
continue
@ -86,6 +95,7 @@ def _get_localzone_name(_root="/"):
try:
with open(tzpath, "rt") as tzfile:
data = tzfile.readlines()
log.debug(f"{tzpath} found, contents:\n {data}")
for line in data:
# Look for the ZONE= setting.
@ -95,13 +105,13 @@ def _get_localzone_name(_root="/"):
match = timezone_re.match(line)
if match is not None:
# Some setting existed
line = line[match.end():]
line = line[match.end() :]
etctz = line[: end_re.search(line).start()]
# We found a timezone
found_configs[tzpath] = etctz.replace(" ", "_")
except (IOError, UnicodeDecodeError):
except (OSError, UnicodeDecodeError):
# UnicodeDecode handles when clock is symlink to /etc/localtime
continue
@ -109,30 +119,34 @@ def _get_localzone_name(_root="/"):
# see manpage of localtime(5) and timedatectl(1)
tzpath = os.path.join(_root, "etc/localtime")
if os.path.exists(tzpath) and os.path.islink(tzpath):
etctz = realtzpath = os.path.realpath(tzpath)
log.debug(f"{tzpath} found")
etctz = os.path.realpath(tzpath)
start = etctz.find("/") + 1
while start != 0:
etctz = etctz[start:]
try:
pds.timezone(etctz)
zoneinfo.ZoneInfo(etctz)
tzinfo = f"{tzpath} is a symlink to"
found_configs[tzinfo] = etctz.replace(" ", "_")
except pds.UnknownTimeZoneError:
# Only need first valid relative path in simlink.
break
except zoneinfo.ZoneInfoNotFoundError:
pass
start = etctz.find("/") + 1
if len(found_configs) > 0:
log.debug(f"{len(found_configs)} found:\n {found_configs}")
# We found some explicit config of some sort!
if len(found_configs) > 1:
# Uh-oh, multiple configs. See if they match:
unique_tzs = set()
zoneinfo = os.path.join(_root, "usr", "share", "zoneinfo")
directory_depth = len(zoneinfo.split(os.path.sep))
zoneinfopath = os.path.join(_root, "usr", "share", "zoneinfo")
directory_depth = len(zoneinfopath.split(os.path.sep))
for tzname in found_configs.values():
# Look them up in /usr/share/zoneinfo, and find what they
# really point to:
path = os.path.realpath(os.path.join(zoneinfo, *tzname.split("/")))
path = os.path.realpath(os.path.join(zoneinfopath, *tzname.split("/")))
real_zone_name = "/".join(path.split(os.path.sep)[directory_depth:])
unique_tzs.add(real_zone_name)
@ -141,7 +155,7 @@ def _get_localzone_name(_root="/"):
for key, value in found_configs.items():
message += f"{key}: {value}\n"
message += "Fix the configuration, or set the time zone in a TZ environment variable.\n"
raise utils.ZoneInfoNotFoundError(message)
raise zoneinfo.ZoneInfoNotFoundError(message)
# We found exactly one config! Use it.
return list(found_configs.values())[0]
@ -165,24 +179,25 @@ def _get_localzone(_root="/"):
tzname = _get_localzone_name(_root)
if tzname is None:
# No explicit setting existed. Use localtime
log.debug("No explicit setting existed. Use localtime")
for filename in ("etc/localtime", "usr/local/etc/localtime"):
tzpath = os.path.join(_root, filename)
if not os.path.exists(tzpath):
continue
with open(tzpath, "rb") as tzfile:
tz = pds.wrap_zone(ZoneInfo.from_file(tzfile, key="local"))
tz = zoneinfo.ZoneInfo.from_file(tzfile, key="local")
break
else:
warnings.warn("Can not find any timezone configuration, defaulting to UTC.")
tz = timezone.utc
else:
tz = pds.timezone(tzname)
tz = zoneinfo.ZoneInfo(tzname)
if _root == "/":
# We are using a file in etc to name the timezone.
# Verify that the timezone specified there is actually used:
utils.assert_tz_offset(tz)
utils.assert_tz_offset(tz, error=False)
return tz