Bump apscheduler from 3.10.1 to 3.10.4 (#2133)

* Bump apscheduler from 3.10.1 to 3.10.4

Bumps [apscheduler](https://github.com/agronholm/apscheduler) from 3.10.1 to 3.10.4.
- [Changelog](https://github.com/agronholm/apscheduler/blob/3.10.4/docs/versionhistory.rst)
- [Commits](https://github.com/agronholm/apscheduler/compare/3.10.1...3.10.4)

---
updated-dependencies:
- dependency-name: apscheduler
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update apscheduler==3.10.4

---------

Signed-off-by: dependabot[bot] <support@github.com>
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:
dependabot[bot] 2023-08-24 12:10:08 -07:00 committed by GitHub
parent 3debeada2a
commit 2c42150799
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 855 additions and 825 deletions

View file

@ -1,10 +1,15 @@
from pkg_resources import get_distribution, DistributionNotFound
import sys
if sys.version_info >= (3, 8):
import importlib.metadata as importlib_metadata
else:
import importlib_metadata
try:
release = get_distribution('APScheduler').version.split('-')[0]
except DistributionNotFound:
release = importlib_metadata.version('APScheduler').split('-')[0]
except importlib_metadata.PackageNotFoundError:
release = '3.5.0'
version_info = tuple(int(x) if x.isdigit() else x for x in release.split('.'))
version = __version__ = '.'.join(str(x) for x in version_info[:3])
del get_distribution, DistributionNotFound
del sys, importlib_metadata

View file

@ -7,7 +7,6 @@ from logging import getLogger
import warnings
import sys
from pkg_resources import iter_entry_points
from tzlocal import get_localzone
import six
@ -31,6 +30,11 @@ try:
except ImportError:
from collections import MutableMapping
try:
from importlib.metadata import entry_points
except ModuleNotFoundError:
from importlib_metadata import entry_points
#: constant indicating a scheduler's stopped state
STATE_STOPPED = 0
#: constant indicating a scheduler's running state (started and processing jobs)
@ -62,12 +66,18 @@ class BaseScheduler(six.with_metaclass(ABCMeta)):
.. seealso:: :ref:`scheduler-config`
"""
# The `group=...` API is only available in the backport, used in <=3.7, and in std>=3.10.
if (3, 8) <= sys.version_info < (3, 10):
_trigger_plugins = {ep.name: ep for ep in entry_points()['apscheduler.triggers']}
_executor_plugins = {ep.name: ep for ep in entry_points()['apscheduler.executors']}
_jobstore_plugins = {ep.name: ep for ep in entry_points()['apscheduler.jobstores']}
else:
_trigger_plugins = {ep.name: ep for ep in entry_points(group='apscheduler.triggers')}
_executor_plugins = {ep.name: ep for ep in entry_points(group='apscheduler.executors')}
_jobstore_plugins = {ep.name: ep for ep in entry_points(group='apscheduler.jobstores')}
_trigger_plugins = dict((ep.name, ep) for ep in iter_entry_points('apscheduler.triggers'))
_trigger_classes = {}
_executor_plugins = dict((ep.name, ep) for ep in iter_entry_points('apscheduler.executors'))
_executor_classes = {}
_jobstore_plugins = dict((ep.name, ep) for ep in iter_entry_points('apscheduler.jobstores'))
_jobstore_classes = {}
#
@ -1019,6 +1029,7 @@ class BaseScheduler(six.with_metaclass(ABCMeta)):
wait_seconds = None
self._logger.debug('No jobs; waiting until a job is added')
else:
now = datetime.now(self.timezone)
wait_seconds = min(max(timedelta_seconds(next_wakeup_time - now), 0), TIMEOUT_MAX)
self._logger.debug('Next wakeup is due at %s (in %f seconds)', next_wakeup_time,
wait_seconds)

View file

@ -1,24 +1,22 @@
from __future__ import absolute_import
from importlib import import_module
from itertools import product
from apscheduler.schedulers.base import BaseScheduler
try:
from PyQt5.QtCore import QObject, QTimer
except (ImportError, RuntimeError): # pragma: nocover
for version, pkgname in product(range(6, 1, -1), ("PySide", "PyQt")):
try:
from PyQt4.QtCore import QObject, QTimer
qtcore = import_module(pkgname + str(version) + ".QtCore")
except ImportError:
try:
from PySide6.QtCore import QObject, QTimer # noqa
except ImportError:
try:
from PySide2.QtCore import QObject, QTimer # noqa
except ImportError:
try:
from PySide.QtCore import QObject, QTimer # noqa
except ImportError:
raise ImportError('QtScheduler requires either PyQt5, PyQt4, PySide6, PySide2 '
'or PySide installed')
pass
else:
QTimer = qtcore.QTimer
break
else:
raise ImportError(
"QtScheduler requires either PySide/PyQt (v6 to v2) installed"
)
class QtScheduler(BaseScheduler):

View file

@ -6,7 +6,7 @@ from asyncio import iscoroutinefunction
from datetime import date, datetime, time, timedelta, tzinfo
from calendar import timegm
from functools import partial
from inspect import isclass, ismethod
from inspect import isbuiltin, isclass, isfunction, ismethod
import re
import sys
@ -214,28 +214,15 @@ def get_callable_name(func):
:rtype: str
"""
# the easy case (on Python 3.3+)
if hasattr(func, '__qualname__'):
if ismethod(func):
self = func.__self__
cls = self if isclass(self) else type(self)
return f"{cls.__qualname__}.{func.__name__}"
elif isclass(func) or isfunction(func) or isbuiltin(func):
return func.__qualname__
# class methods, bound and unbound methods
f_self = getattr(func, '__self__', None) or getattr(func, 'im_self', None)
if f_self and hasattr(func, '__name__'):
f_class = f_self if isclass(f_self) else f_self.__class__
else:
f_class = getattr(func, 'im_class', None)
if f_class and hasattr(func, '__name__'):
return '%s.%s' % (f_class.__name__, func.__name__)
# class or class instance
if hasattr(func, '__call__'):
# class
if hasattr(func, '__name__'):
return func.__name__
elif hasattr(func, '__call__') and callable(func.__call__):
# instance of a class with a __call__ method
return func.__class__.__name__
return type(func).__qualname__
raise TypeError('Unable to determine a name for %r -- maybe it is not a callable?' % func)
@ -260,16 +247,10 @@ def obj_to_ref(obj):
raise ValueError('Cannot create a reference to a nested function')
if ismethod(obj):
if hasattr(obj, 'im_self') and obj.im_self:
# bound method
module = obj.im_self.__module__
elif hasattr(obj, 'im_class') and obj.im_class:
# unbound method
module = obj.im_class.__module__
else:
module = obj.__module__
module = obj.__self__.__module__
else:
module = obj.__module__
return '%s:%s' % (module, name)

View file

@ -9,5 +9,12 @@ if sys.platform == "win32":
else:
from tzlocal.unix import get_localzone, get_localzone_name, reload_localzone
from tzlocal.utils import assert_tz_offset
__all__ = ["get_localzone", "get_localzone_name", "reload_localzone"]
__all__ = [
"get_localzone",
"get_localzone_name",
"reload_localzone",
"assert_tz_offset",
]

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
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

View file

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
import logging
import os
import time
import datetime
import calendar
import pytz_deprecation_shim as pds
import warnings
try:
import zoneinfo # pragma: no cover
@ -12,35 +12,7 @@ except ImportError:
from tzlocal import windows_tz
class ZoneInfoNotFoundError(pds.UnknownTimeZoneError, zoneinfo.ZoneInfoNotFoundError):
"""An exception derived from both pytz and zoneinfo
This exception will be trappable both by pytz expecting clients and
zoneinfo expecting clients.
"""
def get_system_offset():
"""Get system's timezone offset using built-in library time.
For the Timezone constants (altzone, daylight, timezone, and tzname), the
value is determined by the timezone rules in effect at module load time or
the last time tzset() is called and may be incorrect for times in the past.
To keep compatibility with Windows, we're always importing time module here.
"""
localtime = calendar.timegm(time.localtime())
gmtime = calendar.timegm(time.gmtime())
offset = gmtime - localtime
# We could get the localtime and gmtime on either side of a second switch
# so we check that the difference is less than one minute, because nobody
# has that small DST differences.
if abs(offset - time.altzone) < 60:
return -time.altzone # pragma: no cover
else:
return -time.timezone # pragma: no cover
log = logging.getLogger("tzlocal")
def get_tz_offset(tz):
@ -48,19 +20,27 @@ def get_tz_offset(tz):
return int(datetime.datetime.now(tz).utcoffset().total_seconds())
def assert_tz_offset(tz):
def assert_tz_offset(tz, error=True):
"""Assert that system's timezone offset equals to the timezone offset found.
If they don't match, we probably have a misconfiguration, for example, an
incorrect timezone set in /etc/timezone file in systemd distributions."""
incorrect timezone set in /etc/timezone file in systemd distributions.
If error is True, this method will raise a ValueError, otherwise it will
emit a warning.
"""
tz_offset = get_tz_offset(tz)
system_offset = get_system_offset()
if tz_offset != system_offset:
system_offset = calendar.timegm(time.localtime()) - calendar.timegm(time.gmtime())
# No one has timezone offsets less than a minute, so this should be close enough:
if abs(tz_offset - system_offset) > 60:
msg = (
"Timezone offset does not match system offset: {} != {}. "
"Please, check your config files."
).format(tz_offset, system_offset)
if error:
raise ValueError(msg)
warnings.warn(msg)
def _tz_name_from_env(tzenv=None):
@ -70,6 +50,8 @@ def _tz_name_from_env(tzenv=None):
if not tzenv:
return None
log.debug(f"Found a TZ environment: {tzenv}")
if tzenv[0] == ":":
tzenv = tzenv[1:]
@ -92,6 +74,9 @@ def _tz_name_from_env(tzenv=None):
# Indeed
return parts[-1]
log.debug("TZ does not contain a time zone name")
return None
def _tz_from_env(tzenv=None):
if tzenv is None:
@ -112,17 +97,16 @@ def _tz_from_env(tzenv=None):
# Nope, not a standard timezone name, just take the filename
tzname = tzenv.split(os.sep)[-1]
with open(tzenv, "rb") as tzfile:
zone = zoneinfo.ZoneInfo.from_file(tzfile, key=tzname)
return pds.wrap_zone(zone)
return zoneinfo.ZoneInfo.from_file(tzfile, key=tzname)
# TZ must specify a zoneinfo zone.
try:
tz = pds.timezone(tzenv)
tz = zoneinfo.ZoneInfo(tzenv)
# That worked, so we return this:
return tz
except pds.UnknownTimeZoneError:
except zoneinfo.ZoneInfoNotFoundError:
# Nope, it's something like "PST4DST" etc, we can't handle that.
raise ZoneInfoNotFoundError(
raise zoneinfo.ZoneInfoNotFoundError(
"tzlocal() does not support non-zoneinfo timezones like %s. \n"
"Please use a timezone in the form of Continent/City"
"Please use a timezone in the form of Continent/City" % tzenv
) from None

View file

@ -1,17 +1,24 @@
import logging
from datetime import datetime
import pytz_deprecation_shim as pds
try:
import _winreg as winreg
except ImportError:
import winreg
try:
import zoneinfo # pragma: no cover
except ImportError:
from backports import zoneinfo # pragma: no cover
from tzlocal.windows_tz import win_tz
from tzlocal import utils
_cache_tz = None
_cache_tz_name = None
log = logging.getLogger("tzlocal")
def valuestodict(key):
"""Convert a registry key's values to a dictionary."""
@ -48,6 +55,7 @@ def _get_localzone_name():
if tzenv:
return tzenv
log.debug("Looking up time zone info from registry")
handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
TZLOCALKEYNAME = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation"
@ -74,13 +82,13 @@ def _get_localzone_name():
# Return what we have.
if timezone is None:
raise utils.ZoneInfoNotFoundError(tzkeyname)
raise zoneinfo.ZoneInfoNotFoundError(tzkeyname)
if keyvalues.get("DynamicDaylightTimeDisabled", 0) == 1:
# DST is disabled, so don't return the timezone name,
# instead return Etc/GMT+offset
tz = pds.timezone(timezone)
tz = zoneinfo.ZoneInfo(timezone)
has_dst, std_offset, dst_offset = _get_dst_info(tz)
if not has_dst:
# The DST is turned off in the windows configuration,
@ -88,13 +96,15 @@ def _get_localzone_name():
return timezone
if std_offset is None:
raise utils.ZoneInfoNotFoundError(
f"{tzkeyname} claims to not have a non-DST time!?")
raise zoneinfo.ZoneInfoNotFoundError(
f"{tzkeyname} claims to not have a non-DST time!?"
)
if std_offset % 3600:
# I can't convert this to an hourly offset
raise utils.ZoneInfoNotFoundError(
f"tzlocal can't support disabling DST in the {timezone} zone.")
raise zoneinfo.ZoneInfoNotFoundError(
f"tzlocal can't support disabling DST in the {timezone} zone."
)
# This has whole hours as offset, return it as Etc/GMT
return f"Etc/GMT{-std_offset//3600:+.0f}"
@ -116,13 +126,13 @@ def get_localzone():
global _cache_tz
if _cache_tz is None:
_cache_tz = pds.timezone(get_localzone_name())
_cache_tz = zoneinfo.ZoneInfo(get_localzone_name())
if not utils._tz_name_from_env():
# If the timezone does NOT come from a TZ environment variable,
# verify that it's correct. If it's from the environment,
# we accept it, this is so you can run tests with different timezones.
utils.assert_tz_offset(_cache_tz)
utils.assert_tz_offset(_cache_tz, error=False)
return _cache_tz
@ -132,6 +142,6 @@ def reload_localzone():
global _cache_tz
global _cache_tz_name
_cache_tz_name = _get_localzone_name()
_cache_tz = pds.timezone(_cache_tz_name)
utils.assert_tz_offset(_cache_tz)
_cache_tz = zoneinfo.ZoneInfo(_cache_tz_name)
utils.assert_tz_offset(_cache_tz, error=False)
return _cache_tz

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
apscheduler==3.10.1
apscheduler==3.10.4
importlib-metadata==6.8.0
importlib-resources==6.0.1
pyinstaller==5.13.0

View file

@ -1,5 +1,5 @@
appdirs==1.4.4
apscheduler==3.10.1
apscheduler==3.10.4
arrow==1.2.3
backports.csv==1.0.7
backports.functools-lru-cache==1.6.6