mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-06 05:01:14 -07:00
Bump apscheduler from 3.8.0 to 3.9.1 (#1675)
* Bump apscheduler from 3.8.0 to 3.9.1 Bumps [apscheduler](https://github.com/agronholm/apscheduler) from 3.8.0 to 3.9.1. - [Release notes](https://github.com/agronholm/apscheduler/releases) - [Changelog](https://github.com/agronholm/apscheduler/blob/3.9.1/docs/versionhistory.rst) - [Commits](https://github.com/agronholm/apscheduler/compare/3.8.0...3.9.1) --- updated-dependencies: - dependency-name: apscheduler dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Update apscheduler==3.9.1 * Update pytz==2022.1 * Add pytz-deprecation-shim==0.1.0.post0 * Update tzdata==2022.1 * Update tzlocal==4.2 * Update requirements.txt Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: JonnyWong16 <9099342+JonnyWong16@users.noreply.github.com> [skip ci]
This commit is contained in:
parent
942e09e59e
commit
54c9214b03
46 changed files with 1029 additions and 223 deletions
|
@ -1,97 +1,75 @@
|
|||
import os
|
||||
import pytz
|
||||
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
|
||||
else:
|
||||
from backports.zoneinfo import ZoneInfo # pragma: no cover
|
||||
|
||||
_cache_tz = None
|
||||
_cache_tz_name = None
|
||||
|
||||
|
||||
def _tz_from_env(tzenv):
|
||||
if tzenv[0] == ':':
|
||||
tzenv = tzenv[1:]
|
||||
|
||||
# TZ specifies a file
|
||||
if os.path.isabs(tzenv) and os.path.exists(tzenv):
|
||||
with open(tzenv, 'rb') as tzfile:
|
||||
return pytz.tzfile.build_tzinfo('local', tzfile)
|
||||
|
||||
# TZ specifies a zoneinfo zone.
|
||||
try:
|
||||
tz = pytz.timezone(tzenv)
|
||||
# That worked, so we return this:
|
||||
return tz
|
||||
except pytz.UnknownTimeZoneError:
|
||||
raise pytz.UnknownTimeZoneError(
|
||||
"tzlocal() does not support non-zoneinfo timezones like %s. \n"
|
||||
"Please use a timezone in the form of Continent/City")
|
||||
|
||||
|
||||
def _try_tz_from_env():
|
||||
tzenv = os.environ.get('TZ')
|
||||
if tzenv:
|
||||
try:
|
||||
return _tz_from_env(tzenv)
|
||||
except pytz.UnknownTimeZoneError:
|
||||
pass
|
||||
|
||||
|
||||
def _get_localzone(_root='/'):
|
||||
def _get_localzone_name(_root="/"):
|
||||
"""Tries to find the local timezone configuration.
|
||||
|
||||
This method prefers finding the timezone name and passing that to pytz,
|
||||
over passing in the localtime file, as in the later case the zoneinfo
|
||||
name is unknown.
|
||||
This method finds the timezone name, if it can, or it returns None.
|
||||
|
||||
The parameter _root makes the function look for files like /etc/localtime
|
||||
beneath the _root directory. This is primarily used by the tests.
|
||||
In normal usage you call the function without parameters."""
|
||||
|
||||
tzenv = _try_tz_from_env()
|
||||
# First try the ENV setting.
|
||||
tzenv = utils._tz_name_from_env()
|
||||
if tzenv:
|
||||
return tzenv
|
||||
|
||||
# Are we under Termux on Android?
|
||||
if os.path.exists('/system/bin/getprop'):
|
||||
if os.path.exists(os.path.join(_root, "system/bin/getprop")):
|
||||
import subprocess
|
||||
androidtz = subprocess.check_output(['getprop', 'persist.sys.timezone']).strip().decode()
|
||||
return pytz.timezone(androidtz)
|
||||
|
||||
androidtz = (
|
||||
subprocess.check_output(["getprop", "persist.sys.timezone"])
|
||||
.strip()
|
||||
.decode()
|
||||
)
|
||||
return androidtz
|
||||
|
||||
# Now look for distribution specific configuration files
|
||||
# that contain the timezone name.
|
||||
for configfile in ('etc/timezone', 'var/db/zoneinfo'):
|
||||
|
||||
# Stick all of them in a dict, to compare later.
|
||||
found_configs = {}
|
||||
|
||||
for configfile in ("etc/timezone", "var/db/zoneinfo"):
|
||||
tzpath = os.path.join(_root, configfile)
|
||||
try:
|
||||
with open(tzpath, 'rb') as tzfile:
|
||||
with open(tzpath, "rt") as tzfile:
|
||||
data = tzfile.read()
|
||||
|
||||
# Issue #3 was that /etc/timezone was a zoneinfo file.
|
||||
# That's a misconfiguration, but we need to handle it gracefully:
|
||||
if data[:5] == b'TZif2':
|
||||
continue
|
||||
|
||||
etctz = data.strip().decode()
|
||||
etctz = data.strip('/ \t\r\n')
|
||||
if not etctz:
|
||||
# Empty file, skip
|
||||
continue
|
||||
for etctz in data.decode().splitlines():
|
||||
for etctz in etctz.splitlines():
|
||||
# Get rid of host definitions and comments:
|
||||
if ' ' in etctz:
|
||||
etctz, dummy = etctz.split(' ', 1)
|
||||
if '#' in etctz:
|
||||
etctz, dummy = etctz.split('#', 1)
|
||||
if " " in etctz:
|
||||
etctz, dummy = etctz.split(" ", 1)
|
||||
if "#" in etctz:
|
||||
etctz, dummy = etctz.split("#", 1)
|
||||
if not etctz:
|
||||
continue
|
||||
tz = pytz.timezone(etctz.replace(' ', '_'))
|
||||
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)
|
||||
return tz
|
||||
|
||||
except IOError:
|
||||
# File doesn't exist or is a directory
|
||||
found_configs[tzpath] = etctz.replace(" ", "_")
|
||||
|
||||
except (IOError, UnicodeDecodeError):
|
||||
# File doesn't exist or is a directory, or it's a binary file.
|
||||
continue
|
||||
|
||||
# CentOS has a ZONE setting in /etc/sysconfig/clock,
|
||||
|
@ -99,14 +77,14 @@ def _get_localzone(_root='/'):
|
|||
# Gentoo has a TIMEZONE setting in /etc/conf.d/clock
|
||||
# We look through these files for a timezone:
|
||||
|
||||
zone_re = re.compile(r'\s*ZONE\s*=\s*\"')
|
||||
timezone_re = re.compile(r'\s*TIMEZONE\s*=\s*\"')
|
||||
end_re = re.compile('\"')
|
||||
zone_re = re.compile(r"\s*ZONE\s*=\s*\"")
|
||||
timezone_re = re.compile(r"\s*TIMEZONE\s*=\s*\"")
|
||||
end_re = re.compile('"')
|
||||
|
||||
for filename in ('etc/sysconfig/clock', 'etc/conf.d/clock'):
|
||||
for filename in ("etc/sysconfig/clock", "etc/conf.d/clock"):
|
||||
tzpath = os.path.join(_root, filename)
|
||||
try:
|
||||
with open(tzpath, 'rt') as tzfile:
|
||||
with open(tzpath, "rt") as tzfile:
|
||||
data = tzfile.readlines()
|
||||
|
||||
for line in data:
|
||||
|
@ -118,48 +96,108 @@ def _get_localzone(_root='/'):
|
|||
if match is not None:
|
||||
# Some setting existed
|
||||
line = line[match.end():]
|
||||
etctz = line[:end_re.search(line).start()]
|
||||
etctz = line[: end_re.search(line).start()]
|
||||
|
||||
# We found a timezone
|
||||
tz = pytz.timezone(etctz.replace(' ', '_'))
|
||||
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)
|
||||
return tz
|
||||
found_configs[tzpath] = etctz.replace(" ", "_")
|
||||
|
||||
except IOError:
|
||||
# File doesn't exist or is a directory
|
||||
except (IOError, UnicodeDecodeError):
|
||||
# UnicodeDecode handles when clock is symlink to /etc/localtime
|
||||
continue
|
||||
|
||||
# systemd distributions use symlinks that include the zone name,
|
||||
# see manpage of localtime(5) and timedatectl(1)
|
||||
tzpath = os.path.join(_root, 'etc/localtime')
|
||||
tzpath = os.path.join(_root, "etc/localtime")
|
||||
if os.path.exists(tzpath) and os.path.islink(tzpath):
|
||||
tzpath = os.path.realpath(tzpath)
|
||||
start = tzpath.find("/")+1
|
||||
etctz = realtzpath = os.path.realpath(tzpath)
|
||||
start = etctz.find("/") + 1
|
||||
while start != 0:
|
||||
tzpath = tzpath[start:]
|
||||
etctz = etctz[start:]
|
||||
try:
|
||||
return pytz.timezone(tzpath)
|
||||
except pytz.UnknownTimeZoneError:
|
||||
pds.timezone(etctz)
|
||||
tzinfo = f"{tzpath} is a symlink to"
|
||||
found_configs[tzinfo] = etctz.replace(" ", "_")
|
||||
except pds.UnknownTimeZoneError:
|
||||
pass
|
||||
start = tzpath.find("/")+1
|
||||
start = etctz.find("/") + 1
|
||||
|
||||
# No explicit setting existed. Use localtime
|
||||
for filename in ('etc/localtime', 'usr/local/etc/localtime'):
|
||||
tzpath = os.path.join(_root, filename)
|
||||
if len(found_configs) > 0:
|
||||
# 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))
|
||||
|
||||
if not os.path.exists(tzpath):
|
||||
continue
|
||||
with open(tzpath, 'rb') as tzfile:
|
||||
return pytz.tzfile.build_tzinfo('local', tzfile)
|
||||
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("/")))
|
||||
real_zone_name = "/".join(path.split(os.path.sep)[directory_depth:])
|
||||
unique_tzs.add(real_zone_name)
|
||||
|
||||
if len(unique_tzs) != 1:
|
||||
message = "Multiple conflicting time zone configurations found:\n"
|
||||
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)
|
||||
|
||||
# We found exactly one config! Use it.
|
||||
return list(found_configs.values())[0]
|
||||
|
||||
|
||||
def _get_localzone(_root="/"):
|
||||
"""Creates a timezone object from the timezone name.
|
||||
|
||||
If there is no timezone config, it will try to create a file from the
|
||||
localtime timezone, and if there isn't one, it will default to UTC.
|
||||
|
||||
The parameter _root makes the function look for files like /etc/localtime
|
||||
beneath the _root directory. This is primarily used by the tests.
|
||||
In normal usage you call the function without parameters."""
|
||||
|
||||
# First try the ENV setting.
|
||||
tzenv = utils._tz_from_env()
|
||||
if tzenv:
|
||||
return tzenv
|
||||
|
||||
tzname = _get_localzone_name(_root)
|
||||
if tzname is None:
|
||||
# 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"))
|
||||
break
|
||||
else:
|
||||
warnings.warn("Can not find any timezone configuration, defaulting to UTC.")
|
||||
tz = timezone.utc
|
||||
else:
|
||||
tz = pds.timezone(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)
|
||||
return tz
|
||||
|
||||
|
||||
def get_localzone_name():
|
||||
"""Get the computers configured local timezone name, if any."""
|
||||
global _cache_tz_name
|
||||
if _cache_tz_name is None:
|
||||
_cache_tz_name = _get_localzone_name()
|
||||
|
||||
return _cache_tz_name
|
||||
|
||||
warnings.warn('Can not find any timezone configuration, defaulting to UTC.')
|
||||
return pytz.utc
|
||||
|
||||
def get_localzone():
|
||||
"""Get the computers configured local timezone, if any."""
|
||||
|
||||
global _cache_tz
|
||||
if _cache_tz is None:
|
||||
_cache_tz = _get_localzone()
|
||||
|
@ -169,6 +207,9 @@ def get_localzone():
|
|||
|
||||
def reload_localzone():
|
||||
"""Reload the cached localzone. You need to call this if the timezone has changed."""
|
||||
global _cache_tz_name
|
||||
global _cache_tz
|
||||
_cache_tz_name = _get_localzone_name()
|
||||
_cache_tz = _get_localzone()
|
||||
|
||||
return _cache_tz
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue