summaryrefslogtreecommitdiff
path: root/src/apscheduler/triggers
diff options
context:
space:
mode:
authorAlex Grönholm <alex.gronholm@nextday.fi>2022-04-20 01:00:57 +0300
committerAlex Grönholm <alex.gronholm@nextday.fi>2022-04-20 01:11:20 +0300
commitb20f62d929eed84ad18020bb82dd43d8cb70da4d (patch)
treec42bf1877dd54755c55c649269e1254995bdf0c9 /src/apscheduler/triggers
parent82992cd427a9ab2351d8e0719b82d826dff5a521 (diff)
downloadapscheduler-b20f62d929eed84ad18020bb82dd43d8cb70da4d.tar.gz
Switched to Black for code formatting
Diffstat (limited to 'src/apscheduler/triggers')
-rw-r--r--src/apscheduler/triggers/calendarinterval.py47
-rw-r--r--src/apscheduler/triggers/combining.py38
-rw-r--r--src/apscheduler/triggers/cron/__init__.py128
-rw-r--r--src/apscheduler/triggers/cron/expressions.py101
-rw-r--r--src/apscheduler/triggers/cron/fields.py77
-rw-r--r--src/apscheduler/triggers/date.py10
-rw-r--r--src/apscheduler/triggers/interval.py68
7 files changed, 305 insertions, 164 deletions
diff --git a/src/apscheduler/triggers/calendarinterval.py b/src/apscheduler/triggers/calendarinterval.py
index fbb5896..0aedd15 100644
--- a/src/apscheduler/triggers/calendarinterval.py
+++ b/src/apscheduler/triggers/calendarinterval.py
@@ -6,7 +6,12 @@ from typing import Any
import attrs
from ..abc import Trigger
-from ..marshalling import marshal_date, marshal_timezone, unmarshal_date, unmarshal_timezone
+from ..marshalling import (
+ marshal_date,
+ marshal_timezone,
+ unmarshal_date,
+ unmarshal_timezone,
+)
from ..util import timezone_repr
from ..validators import as_date, as_timezone, require_state_version
@@ -65,7 +70,7 @@ class CalendarIntervalTrigger(Trigger):
second: int = 0
start_date: date = attrs.field(converter=as_date, factory=date.today)
end_date: date | None = attrs.field(converter=as_date, default=None)
- timezone: tzinfo = attrs.field(converter=as_timezone, default='local')
+ timezone: tzinfo = attrs.field(converter=as_timezone, default="local")
_time: time = attrs.field(init=False, eq=False)
_last_fire_date: date | None = attrs.field(init=False, eq=False, default=None)
@@ -73,10 +78,10 @@ class CalendarIntervalTrigger(Trigger):
self._time = time(self.hour, self.minute, self.second, tzinfo=self.timezone)
if self.years == self.months == self.weeks == self.days == 0:
- raise ValueError('interval must be at least 1 day long')
+ raise ValueError("interval must be at least 1 day long")
if self.start_date and self.end_date and self.start_date > self.end_date:
- raise ValueError('end_date cannot be earlier than start_date')
+ raise ValueError("end_date cannot be earlier than start_date")
def next(self) -> datetime | None:
previous_date: date = self._last_fire_date
@@ -114,35 +119,35 @@ class CalendarIntervalTrigger(Trigger):
def __getstate__(self) -> dict[str, Any]:
return {
- 'version': 1,
- 'interval': [self.years, self.months, self.weeks, self.days],
- 'time': [self._time.hour, self._time.minute, self._time.second],
- 'start_date': marshal_date(self.start_date),
- 'end_date': marshal_date(self.end_date),
- 'timezone': marshal_timezone(self.timezone),
- 'last_fire_date': marshal_date(self._last_fire_date)
+ "version": 1,
+ "interval": [self.years, self.months, self.weeks, self.days],
+ "time": [self._time.hour, self._time.minute, self._time.second],
+ "start_date": marshal_date(self.start_date),
+ "end_date": marshal_date(self.end_date),
+ "timezone": marshal_timezone(self.timezone),
+ "last_fire_date": marshal_date(self._last_fire_date),
}
def __setstate__(self, state: dict[str, Any]) -> None:
require_state_version(self, state, 1)
- self.years, self.months, self.weeks, self.days = state['interval']
- self.start_date = unmarshal_date(state['start_date'])
- self.end_date = unmarshal_date(state['end_date'])
- self.timezone = unmarshal_timezone(state['timezone'])
- self._time = time(*state['time'], tzinfo=self.timezone)
- self._last_fire_date = unmarshal_date(state['last_fire_date'])
+ self.years, self.months, self.weeks, self.days = state["interval"]
+ self.start_date = unmarshal_date(state["start_date"])
+ self.end_date = unmarshal_date(state["end_date"])
+ self.timezone = unmarshal_timezone(state["timezone"])
+ self._time = time(*state["time"], tzinfo=self.timezone)
+ self._last_fire_date = unmarshal_date(state["last_fire_date"])
def __repr__(self) -> str:
fields = []
- for field in 'years', 'months', 'weeks', 'days':
+ for field in "years", "months", "weeks", "days":
value = getattr(self, field)
if value > 0:
- fields.append(f'{field}={value}')
+ fields.append(f"{field}={value}")
- fields.append(f'time={self._time.isoformat()!r}')
+ fields.append(f"time={self._time.isoformat()!r}")
fields.append(f"start_date='{self.start_date}'")
if self.end_date:
fields.append(f"end_date='{self.end_date}'")
- fields.append(f'timezone={timezone_repr(self.timezone)!r}')
+ fields.append(f"timezone={timezone_repr(self.timezone)!r}")
return f'{self.__class__.__name__}({", ".join(fields)})'
diff --git a/src/apscheduler/triggers/combining.py b/src/apscheduler/triggers/combining.py
index bcee64a..efe99c9 100644
--- a/src/apscheduler/triggers/combining.py
+++ b/src/apscheduler/triggers/combining.py
@@ -15,19 +15,23 @@ from ..validators import as_timedelta, require_state_version
@attrs.define
class BaseCombiningTrigger(Trigger):
triggers: list[Trigger]
- _next_fire_times: list[datetime | None] = attrs.field(init=False, eq=False, factory=list)
+ _next_fire_times: list[datetime | None] = attrs.field(
+ init=False, eq=False, factory=list
+ )
def __getstate__(self) -> dict[str, Any]:
return {
- 'version': 1,
- 'triggers': [marshal_object(trigger) for trigger in self.triggers],
- 'next_fire_times': self._next_fire_times
+ "version": 1,
+ "triggers": [marshal_object(trigger) for trigger in self.triggers],
+ "next_fire_times": self._next_fire_times,
}
@abstractmethod
def __setstate__(self, state: dict[str, Any]) -> None:
- self.triggers = [unmarshal_object(*trigger_state) for trigger_state in state['triggers']]
- self._next_fire_times = state['next_fire_times']
+ self.triggers = [
+ unmarshal_object(*trigger_state) for trigger_state in state["triggers"]
+ ]
+ self._next_fire_times = state["next_fire_times"]
@attrs.define
@@ -87,19 +91,21 @@ class AndTrigger(BaseCombiningTrigger):
def __getstate__(self) -> dict[str, Any]:
state = super().__getstate__()
- state['threshold'] = self.threshold.total_seconds()
- state['max_iterations'] = self.max_iterations
+ state["threshold"] = self.threshold.total_seconds()
+ state["max_iterations"] = self.max_iterations
return state
def __setstate__(self, state: dict[str, Any]) -> None:
require_state_version(self, state, 1)
super().__setstate__(state)
- self.threshold = timedelta(seconds=state['threshold'])
- self.max_iterations = state['max_iterations']
+ self.threshold = timedelta(seconds=state["threshold"])
+ self.max_iterations = state["max_iterations"]
def __repr__(self) -> str:
- return f'{self.__class__.__name__}({self.triggers}, ' \
- f'threshold={self.threshold.total_seconds()}, max_iterations={self.max_iterations})'
+ return (
+ f"{self.__class__.__name__}({self.triggers}, "
+ f"threshold={self.threshold.total_seconds()}, max_iterations={self.max_iterations})"
+ )
@attrs.define
@@ -120,8 +126,10 @@ class OrTrigger(BaseCombiningTrigger):
self._next_fire_times = [t.next() for t in self.triggers]
# Find out the earliest of the fire times
- earliest_time: datetime | None = min((fire_time for fire_time in self._next_fire_times
- if fire_time is not None), default=None)
+ earliest_time: datetime | None = min(
+ (fire_time for fire_time in self._next_fire_times if fire_time is not None),
+ default=None,
+ )
if earliest_time is not None:
# Generate new fire times for the trigger(s) that generated the earliest fire time
for i, fire_time in enumerate(self._next_fire_times):
@@ -135,4 +143,4 @@ class OrTrigger(BaseCombiningTrigger):
super().__setstate__(state)
def __repr__(self) -> str:
- return f'{self.__class__.__name__}({self.triggers})'
+ return f"{self.__class__.__name__}({self.triggers})"
diff --git a/src/apscheduler/triggers/cron/__init__.py b/src/apscheduler/triggers/cron/__init__.py
index df1f9e5..1bd2be1 100644
--- a/src/apscheduler/triggers/cron/__init__.py
+++ b/src/apscheduler/triggers/cron/__init__.py
@@ -7,11 +7,22 @@ import attrs
from tzlocal import get_localzone
from ...abc import Trigger
-from ...marshalling import marshal_date, marshal_timezone, unmarshal_date, unmarshal_timezone
+from ...marshalling import (
+ marshal_date,
+ marshal_timezone,
+ unmarshal_date,
+ unmarshal_timezone,
+)
from ...util import timezone_repr
from ...validators import as_aware_datetime, as_timezone, require_state_version
from .fields import (
- DEFAULT_VALUES, BaseField, DayOfMonthField, DayOfWeekField, MonthField, WeekField)
+ DEFAULT_VALUES,
+ BaseField,
+ DayOfMonthField,
+ DayOfWeekField,
+ MonthField,
+ WeekField,
+)
@attrs.define(kw_only=True)
@@ -37,14 +48,14 @@ class CronTrigger(Trigger):
"""
FIELDS_MAP: ClassVar[list[tuple[str, type[BaseField]]]] = [
- ('year', BaseField),
- ('month', MonthField),
- ('day', DayOfMonthField),
- ('week', WeekField),
- ('day_of_week', DayOfWeekField),
- ('hour', BaseField),
- ('minute', BaseField),
- ('second', BaseField)
+ ("year", BaseField),
+ ("month", MonthField),
+ ("day", DayOfMonthField),
+ ("week", WeekField),
+ ("day_of_week", DayOfWeekField),
+ ("hour", BaseField),
+ ("minute", BaseField),
+ ("second", BaseField),
]
year: int | str | None = None
@@ -55,32 +66,46 @@ class CronTrigger(Trigger):
hour: int | str | None = None
minute: int | str | None = None
second: int | str | None = None
- start_time: datetime = attrs.field(converter=as_aware_datetime, factory=datetime.now)
+ start_time: datetime = attrs.field(
+ converter=as_aware_datetime, factory=datetime.now
+ )
end_time: datetime | None = None
timezone: tzinfo | str = attrs.field(converter=as_timezone, factory=get_localzone)
_fields: list[BaseField] = attrs.field(init=False, eq=False, factory=list)
_last_fire_time: datetime | None = attrs.field(init=False, eq=False, default=None)
def __attrs_post_init__(self) -> None:
- self._set_fields([self.year, self.month, self.day, self.week, self.day_of_week, self.hour,
- self.minute, self.second])
+ self._set_fields(
+ [
+ self.year,
+ self.month,
+ self.day,
+ self.week,
+ self.day_of_week,
+ self.hour,
+ self.minute,
+ self.second,
+ ]
+ )
self._last_fire_time: datetime | None = None
def _set_fields(self, values: Sequence[int | str | None]) -> None:
self._fields = []
- assigned_values = {field_name: value
- for (field_name, _), value in zip(self.FIELDS_MAP, values)
- if value is not None}
+ assigned_values = {
+ field_name: value
+ for (field_name, _), value in zip(self.FIELDS_MAP, values)
+ if value is not None
+ }
for field_name, field_class in self.FIELDS_MAP:
exprs = assigned_values.pop(field_name, None)
if exprs is None:
- exprs = '*' if assigned_values else DEFAULT_VALUES[field_name]
+ exprs = "*" if assigned_values else DEFAULT_VALUES[field_name]
field = field_class(field_name, exprs)
self._fields.append(field)
@classmethod
- def from_crontab(cls, expr: str, timezone: str | tzinfo = 'local') -> CronTrigger:
+ def from_crontab(cls, expr: str, timezone: str | tzinfo = "local") -> CronTrigger:
"""
Create a :class:`~CronTrigger` from a standard crontab expression.
@@ -93,12 +118,20 @@ class CronTrigger(Trigger):
"""
values = expr.split()
if len(values) != 5:
- raise ValueError(f'Wrong number of fields; got {len(values)}, expected 5')
-
- return cls(minute=values[0], hour=values[1], day=values[2], month=values[3],
- day_of_week=values[4], timezone=timezone)
-
- def _increment_field_value(self, dateval: datetime, fieldnum: int) -> tuple[datetime, int]:
+ raise ValueError(f"Wrong number of fields; got {len(values)}, expected 5")
+
+ return cls(
+ minute=values[0],
+ hour=values[1],
+ day=values[2],
+ month=values[3],
+ day_of_week=values[4],
+ timezone=timezone,
+ )
+
+ def _increment_field_value(
+ self, dateval: datetime, fieldnum: int
+ ) -> tuple[datetime, int]:
"""
Increments the designated field and resets all less significant fields to their minimum
values.
@@ -136,11 +169,14 @@ class CronTrigger(Trigger):
i += 1
difference = datetime(**values) - dateval.replace(tzinfo=None)
- dateval = datetime.fromtimestamp(dateval.timestamp() + difference.total_seconds(),
- self.timezone)
+ dateval = datetime.fromtimestamp(
+ dateval.timestamp() + difference.total_seconds(), self.timezone
+ )
return dateval, fieldnum
- def _set_field_value(self, dateval: datetime, fieldnum: int, new_value: int) -> datetime:
+ def _set_field_value(
+ self, dateval: datetime, fieldnum: int, new_value: int
+ ) -> datetime:
values = {}
for i, field in enumerate(self._fields):
if field.real:
@@ -168,14 +204,18 @@ class CronTrigger(Trigger):
if next_value is None:
# No valid value was found
- next_time, fieldnum = self._increment_field_value(next_time, fieldnum - 1)
+ next_time, fieldnum = self._increment_field_value(
+ next_time, fieldnum - 1
+ )
elif next_value > curr_value:
# A valid, but higher than the starting value, was found
if field.real:
next_time = self._set_field_value(next_time, fieldnum, next_value)
fieldnum += 1
else:
- next_time, fieldnum = self._increment_field_value(next_time, fieldnum)
+ next_time, fieldnum = self._increment_field_value(
+ next_time, fieldnum
+ )
else:
# A valid value was found, no changes necessary
fieldnum += 1
@@ -190,29 +230,29 @@ class CronTrigger(Trigger):
def __getstate__(self) -> dict[str, Any]:
return {
- 'version': 1,
- 'timezone': marshal_timezone(self.timezone),
- 'fields': [str(f) for f in self._fields],
- 'start_time': marshal_date(self.start_time),
- 'end_time': marshal_date(self.end_time),
- 'last_fire_time': marshal_date(self._last_fire_time)
+ "version": 1,
+ "timezone": marshal_timezone(self.timezone),
+ "fields": [str(f) for f in self._fields],
+ "start_time": marshal_date(self.start_time),
+ "end_time": marshal_date(self.end_time),
+ "last_fire_time": marshal_date(self._last_fire_time),
}
def __setstate__(self, state: dict[str, Any]) -> None:
require_state_version(self, state, 1)
- self.timezone = unmarshal_timezone(state['timezone'])
- self.start_time = unmarshal_date(state['start_time'])
- self.end_time = unmarshal_date(state['end_time'])
- self._last_fire_time = unmarshal_date(state['last_fire_time'])
- self._set_fields(state['fields'])
+ self.timezone = unmarshal_timezone(state["timezone"])
+ self.start_time = unmarshal_date(state["start_time"])
+ self.end_time = unmarshal_date(state["end_time"])
+ self._last_fire_time = unmarshal_date(state["last_fire_time"])
+ self._set_fields(state["fields"])
def __repr__(self) -> str:
- fields = [f'{field.name}={str(field)!r}' for field in self._fields]
- fields.append(f'start_time={self.start_time.isoformat()!r}')
+ fields = [f"{field.name}={str(field)!r}" for field in self._fields]
+ fields.append(f"start_time={self.start_time.isoformat()!r}")
if self.end_time:
- fields.append(f'end_time={self.end_time.isoformat()!r}')
+ fields.append(f"end_time={self.end_time.isoformat()!r}")
- fields.append(f'timezone={timezone_repr(self.timezone)!r}')
+ fields.append(f"timezone={timezone_repr(self.timezone)!r}")
return f'CronTrigger({", ".join(fields)})'
diff --git a/src/apscheduler/triggers/cron/expressions.py b/src/apscheduler/triggers/cron/expressions.py
index 5c94afa..6d39a45 100644
--- a/src/apscheduler/triggers/cron/expressions.py
+++ b/src/apscheduler/triggers/cron/expressions.py
@@ -7,32 +7,47 @@ from datetime import datetime
from ...validators import as_int
-WEEKDAYS = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
-MONTHS = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
+WEEKDAYS = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
+MONTHS = [
+ "jan",
+ "feb",
+ "mar",
+ "apr",
+ "may",
+ "jun",
+ "jul",
+ "aug",
+ "sep",
+ "oct",
+ "nov",
+ "dec",
+]
def get_weekday_index(weekday: str) -> int:
try:
return WEEKDAYS.index(weekday.lower())
except ValueError:
- raise ValueError(f'Invalid weekday name {weekday!r}') from None
+ raise ValueError(f"Invalid weekday name {weekday!r}") from None
class AllExpression:
- __slots__ = 'step'
+ __slots__ = "step"
- value_re = re.compile(r'\*(?:/(?P<step>\d+))?$')
+ value_re = re.compile(r"\*(?:/(?P<step>\d+))?$")
def __init__(self, step: str | int | None = None):
self.step = as_int(step)
if self.step == 0:
- raise ValueError('Step must be higher than 0')
+ raise ValueError("Step must be higher than 0")
def validate_range(self, field_name: str, min_value: int, max_value: int) -> None:
value_range = max_value - min_value
if self.step and self.step > value_range:
- raise ValueError(f'the step value ({self.step}) is higher than the total range of the '
- f'expression ({value_range})')
+ raise ValueError(
+ f"the step value ({self.step}) is higher than the total range of the "
+ f"expression ({value_range})"
+ )
def get_next_value(self, dateval: datetime, field) -> int | None:
start = field.get_value(dateval)
@@ -49,16 +64,20 @@ class AllExpression:
return nextval if nextval <= maxval else None
def __str__(self):
- return f'*/{self.step}' if self.step else '*'
+ return f"*/{self.step}" if self.step else "*"
class RangeExpression(AllExpression):
- __slots__ = 'first', 'last'
+ __slots__ = "first", "last"
- value_re = re.compile(r'(?P<first>\d+)(?:-(?P<last>\d+))?(?:/(?P<step>\d+))?$')
+ value_re = re.compile(r"(?P<first>\d+)(?:-(?P<last>\d+))?(?:/(?P<step>\d+))?$")
- def __init__(self, first: str | int, last: str | int | None = None,
- step: str | int | None = None):
+ def __init__(
+ self,
+ first: str | int,
+ last: str | int | None = None,
+ step: str | int | None = None,
+ ):
super().__init__(step)
self.first = as_int(first)
self.last = as_int(last)
@@ -66,20 +85,28 @@ class RangeExpression(AllExpression):
if self.last is None and self.step is None:
self.last = self.first
if self.last is not None and self.first > self.last:
- raise ValueError('The minimum value in a range must not be higher than the maximum')
+ raise ValueError(
+ "The minimum value in a range must not be higher than the maximum"
+ )
def validate_range(self, field_name: str, min_value: int, max_value: int) -> None:
super().validate_range(field_name, min_value, max_value)
if self.first < min_value:
- raise ValueError(f'the first value ({self.first}) is lower than the minimum value '
- f'({min_value})')
+ raise ValueError(
+ f"the first value ({self.first}) is lower than the minimum value "
+ f"({min_value})"
+ )
if self.last is not None and self.last > max_value:
- raise ValueError(f'the last value ({self.last}) is higher than the maximum value '
- f'({max_value})')
+ raise ValueError(
+ f"the last value ({self.last}) is higher than the maximum value "
+ f"({max_value})"
+ )
value_range = (self.last or max_value) - self.first
if self.step and self.step > value_range:
- raise ValueError(f'the step value ({self.step}) is higher than the total range of the '
- f'expression ({value_range})')
+ raise ValueError(
+ f"the step value ({self.step}) is higher than the total range of the "
+ f"expression ({value_range})"
+ )
def get_next_value(self, date, field):
startval = field.get_value(date)
@@ -100,12 +127,12 @@ class RangeExpression(AllExpression):
def __str__(self):
if self.last != self.first and self.last is not None:
- rangeval = f'{self.first}-{self.last}'
+ rangeval = f"{self.first}-{self.last}"
else:
rangeval = str(self.first)
if self.step:
- return f'{rangeval}/{self.step}'
+ return f"{rangeval}/{self.step}"
return rangeval
@@ -113,19 +140,19 @@ class RangeExpression(AllExpression):
class MonthRangeExpression(RangeExpression):
__slots__ = ()
- value_re = re.compile(r'(?P<first>[a-z]+)(?:-(?P<last>[a-z]+))?', re.IGNORECASE)
+ value_re = re.compile(r"(?P<first>[a-z]+)(?:-(?P<last>[a-z]+))?", re.IGNORECASE)
def __init__(self, first, last=None):
try:
first_num = MONTHS.index(first.lower()) + 1
except ValueError:
- raise ValueError(f'Invalid month name {first!r}') from None
+ raise ValueError(f"Invalid month name {first!r}") from None
if last:
try:
last_num = MONTHS.index(last.lower()) + 1
except ValueError:
- raise ValueError(f'Invalid month name {last!r}') from None
+ raise ValueError(f"Invalid month name {last!r}") from None
else:
last_num = None
@@ -133,7 +160,7 @@ class MonthRangeExpression(RangeExpression):
def __str__(self):
if self.last != self.first and self.last is not None:
- return f'{MONTHS[self.first - 1]}-{MONTHS[self.last - 1]}'
+ return f"{MONTHS[self.first - 1]}-{MONTHS[self.last - 1]}"
return MONTHS[self.first - 1]
@@ -141,7 +168,7 @@ class MonthRangeExpression(RangeExpression):
class WeekdayRangeExpression(RangeExpression):
__slots__ = ()
- value_re = re.compile(r'(?P<first>[a-z]+)(?:-(?P<last>[a-z]+))?', re.IGNORECASE)
+ value_re = re.compile(r"(?P<first>[a-z]+)(?:-(?P<last>[a-z]+))?", re.IGNORECASE)
def __init__(self, first: str, last: str | None = None):
first_num = get_weekday_index(first)
@@ -150,17 +177,19 @@ class WeekdayRangeExpression(RangeExpression):
def __str__(self):
if self.last != self.first and self.last is not None:
- return f'{WEEKDAYS[self.first]}-{WEEKDAYS[self.last]}'
+ return f"{WEEKDAYS[self.first]}-{WEEKDAYS[self.last]}"
return WEEKDAYS[self.first]
class WeekdayPositionExpression(AllExpression):
- __slots__ = 'option_num', 'weekday'
+ __slots__ = "option_num", "weekday"
- options = ['1st', '2nd', '3rd', '4th', '5th', 'last']
- value_re = re.compile(r'(?P<option_name>%s) +(?P<weekday_name>(?:\d+|\w+))' %
- '|'.join(options), re.IGNORECASE)
+ options = ["1st", "2nd", "3rd", "4th", "5th", "last"]
+ value_re = re.compile(
+ r"(?P<option_name>%s) +(?P<weekday_name>(?:\d+|\w+))" % "|".join(options),
+ re.IGNORECASE,
+ )
def __init__(self, option_name: str, weekday_name: str):
super().__init__(None)
@@ -168,7 +197,7 @@ class WeekdayPositionExpression(AllExpression):
try:
self.weekday = WEEKDAYS.index(weekday_name.lower())
except ValueError:
- raise ValueError(f'Invalid weekday name {weekday_name!r}') from None
+ raise ValueError(f"Invalid weekday name {weekday_name!r}") from None
def get_next_value(self, dateval: datetime, field) -> int | None:
# Figure out the weekday of the month's first day and the number of days in that month
@@ -191,13 +220,13 @@ class WeekdayPositionExpression(AllExpression):
return None
def __str__(self):
- return f'{self.options[self.option_num]} {WEEKDAYS[self.weekday]}'
+ return f"{self.options[self.option_num]} {WEEKDAYS[self.weekday]}"
class LastDayOfMonthExpression(AllExpression):
__slots__ = ()
- value_re = re.compile(r'last', re.IGNORECASE)
+ value_re = re.compile(r"last", re.IGNORECASE)
def __init__(self):
super().__init__(None)
@@ -206,4 +235,4 @@ class LastDayOfMonthExpression(AllExpression):
return monthrange(dateval.year, dateval.month)[1]
def __str__(self):
- return 'last'
+ return "last"
diff --git a/src/apscheduler/triggers/cron/fields.py b/src/apscheduler/triggers/cron/fields.py
index e68fdca..b70f643 100644
--- a/src/apscheduler/triggers/cron/fields.py
+++ b/src/apscheduler/triggers/cron/fields.py
@@ -7,20 +7,51 @@ from datetime import datetime
from typing import Any, ClassVar, Sequence
from .expressions import (
- WEEKDAYS, AllExpression, LastDayOfMonthExpression, MonthRangeExpression, RangeExpression,
- WeekdayPositionExpression, WeekdayRangeExpression, get_weekday_index)
-
-MIN_VALUES = {'year': 1970, 'month': 1, 'day': 1, 'week': 1, 'day_of_week': 0, 'hour': 0,
- 'minute': 0, 'second': 0}
-MAX_VALUES = {'year': 9999, 'month': 12, 'day': 31, 'week': 53, 'day_of_week': 7, 'hour': 23,
- 'minute': 59, 'second': 59}
-DEFAULT_VALUES = {'year': '*', 'month': 1, 'day': 1, 'week': '*', 'day_of_week': '*', 'hour': 0,
- 'minute': 0, 'second': 0}
-SEPARATOR = re.compile(' *, *')
+ WEEKDAYS,
+ AllExpression,
+ LastDayOfMonthExpression,
+ MonthRangeExpression,
+ RangeExpression,
+ WeekdayPositionExpression,
+ WeekdayRangeExpression,
+ get_weekday_index,
+)
+
+MIN_VALUES = {
+ "year": 1970,
+ "month": 1,
+ "day": 1,
+ "week": 1,
+ "day_of_week": 0,
+ "hour": 0,
+ "minute": 0,
+ "second": 0,
+}
+MAX_VALUES = {
+ "year": 9999,
+ "month": 12,
+ "day": 31,
+ "week": 53,
+ "day_of_week": 7,
+ "hour": 23,
+ "minute": 59,
+ "second": 59,
+}
+DEFAULT_VALUES = {
+ "year": "*",
+ "month": 1,
+ "day": 1,
+ "week": "*",
+ "day_of_week": "*",
+ "hour": 0,
+ "minute": 0,
+ "second": 0,
+}
+SEPARATOR = re.compile(" *, *")
class BaseField:
- __slots__ = 'name', 'expressions'
+ __slots__ = "name", "expressions"
real: ClassVar[bool] = True
compilers: ClassVar[Any] = (AllExpression, RangeExpression)
@@ -61,19 +92,22 @@ class BaseField:
compiled_expr = compiler(**match.groupdict())
try:
- compiled_expr.validate_range(self.name, MIN_VALUES[self.name],
- MAX_VALUES[self.name])
+ compiled_expr.validate_range(
+ self.name, MIN_VALUES[self.name], MAX_VALUES[self.name]
+ )
except ValueError as exc:
- raise ValueError(f'Error validating expression {expr!r}: {exc}') from exc
+ raise ValueError(
+ f"Error validating expression {expr!r}: {exc}"
+ ) from exc
self.expressions.append(compiled_expr)
return
- raise ValueError(f'Unrecognized expression {expr!r} for field {self.name!r}')
+ raise ValueError(f"Unrecognized expression {expr!r} for field {self.name!r}")
def __str__(self):
expr_strings = (str(e) for e in self.expressions)
- return ','.join(expr_strings)
+ return ",".join(expr_strings)
class WeekField(BaseField, real=False):
@@ -83,8 +117,9 @@ class WeekField(BaseField, real=False):
return dateval.isocalendar()[1]
-class DayOfMonthField(BaseField,
- extra_compilers=(WeekdayPositionExpression, LastDayOfMonthExpression)):
+class DayOfMonthField(
+ BaseField, extra_compilers=(WeekdayPositionExpression, LastDayOfMonthExpression)
+):
__slots__ = ()
def get_max(self, dateval: datetime) -> int:
@@ -107,7 +142,7 @@ class DayOfWeekField(BaseField, real=False, extra_compilers=(WeekdayRangeExpress
else:
last = first
- expr = f'{WEEKDAYS[first]}-{WEEKDAYS[last]}'
+ expr = f"{WEEKDAYS[first]}-{WEEKDAYS[last]}"
# For expressions like Sun-Tue or Sat-Mon, add two expressions that together cover the
# expected weekdays
@@ -117,8 +152,8 @@ class DayOfWeekField(BaseField, real=False, extra_compilers=(WeekdayRangeExpress
first_index = get_weekday_index(groups[0])
last_index = get_weekday_index(groups[1])
if first_index > last_index:
- super().append_expression(f'{WEEKDAYS[0]}-{groups[1]}')
- super().append_expression(f'{groups[0]}-{WEEKDAYS[-1]}')
+ super().append_expression(f"{WEEKDAYS[0]}-{groups[1]}")
+ super().append_expression(f"{groups[0]}-{WEEKDAYS[-1]}")
return
super().append_expression(expr)
diff --git a/src/apscheduler/triggers/date.py b/src/apscheduler/triggers/date.py
index 173c972..b55028a 100644
--- a/src/apscheduler/triggers/date.py
+++ b/src/apscheduler/triggers/date.py
@@ -30,15 +30,15 @@ class DateTrigger(Trigger):
def __getstate__(self) -> dict[str, Any]:
return {
- 'version': 1,
- 'run_time': marshal_date(self.run_time),
- 'completed': self._completed
+ "version": 1,
+ "run_time": marshal_date(self.run_time),
+ "completed": self._completed,
}
def __setstate__(self, state: dict[str, Any]) -> None:
require_state_version(self, state, 1)
- self.run_time = unmarshal_date(state['run_time'])
- self._completed = state['completed']
+ self.run_time = unmarshal_date(state["run_time"])
+ self._completed = state["completed"]
def __repr__(self) -> str:
return f"{self.__class__.__name__}('{self.run_time}')"
diff --git a/src/apscheduler/triggers/interval.py b/src/apscheduler/triggers/interval.py
index 629499b..fe410bd 100644
--- a/src/apscheduler/triggers/interval.py
+++ b/src/apscheduler/triggers/interval.py
@@ -36,21 +36,28 @@ class IntervalTrigger(Trigger):
minutes: float = 0
seconds: float = 0
microseconds: float = 0
- start_time: datetime = attrs.field(converter=as_aware_datetime, factory=datetime.now)
+ start_time: datetime = attrs.field(
+ converter=as_aware_datetime, factory=datetime.now
+ )
end_time: datetime | None = attrs.field(converter=as_aware_datetime, default=None)
_interval: timedelta = attrs.field(init=False, eq=False, repr=False)
_last_fire_time: datetime | None = attrs.field(init=False, eq=False, default=None)
def __attrs_post_init__(self) -> None:
- self._interval = timedelta(weeks=self.weeks, days=self.days, hours=self.hours,
- minutes=self.minutes, seconds=self.seconds,
- microseconds=self.microseconds)
+ self._interval = timedelta(
+ weeks=self.weeks,
+ days=self.days,
+ hours=self.hours,
+ minutes=self.minutes,
+ seconds=self.seconds,
+ microseconds=self.microseconds,
+ )
if self._interval.total_seconds() <= 0:
- raise ValueError('The time interval must be positive')
+ raise ValueError("The time interval must be positive")
if self.end_time and self.end_time < self.start_time:
- raise ValueError('end_time cannot be earlier than start_time')
+ raise ValueError("end_time cannot be earlier than start_time")
def next(self) -> datetime | None:
if self._last_fire_time is None:
@@ -65,31 +72,48 @@ class IntervalTrigger(Trigger):
def __getstate__(self) -> dict[str, Any]:
return {
- 'version': 1,
- 'interval': [self.weeks, self.days, self.hours, self.minutes, self.seconds,
- self.microseconds],
- 'start_time': marshal_date(self.start_time),
- 'end_time': marshal_date(self.end_time),
- 'last_fire_time': marshal_date(self._last_fire_time)
+ "version": 1,
+ "interval": [
+ self.weeks,
+ self.days,
+ self.hours,
+ self.minutes,
+ self.seconds,
+ self.microseconds,
+ ],
+ "start_time": marshal_date(self.start_time),
+ "end_time": marshal_date(self.end_time),
+ "last_fire_time": marshal_date(self._last_fire_time),
}
def __setstate__(self, state: dict[str, Any]) -> None:
require_state_version(self, state, 1)
- self.weeks, self.days, self.hours, self.minutes, self.seconds, self.microseconds = \
- state['interval']
- self.start_time = unmarshal_date(state['start_time'])
- self.end_time = unmarshal_date(state['end_time'])
- self._last_fire_time = unmarshal_date(state['last_fire_time'])
- self._interval = timedelta(weeks=self.weeks, days=self.days, hours=self.hours,
- minutes=self.minutes, seconds=self.seconds,
- microseconds=self.microseconds)
+ (
+ self.weeks,
+ self.days,
+ self.hours,
+ self.minutes,
+ self.seconds,
+ self.microseconds,
+ ) = state["interval"]
+ self.start_time = unmarshal_date(state["start_time"])
+ self.end_time = unmarshal_date(state["end_time"])
+ self._last_fire_time = unmarshal_date(state["last_fire_time"])
+ self._interval = timedelta(
+ weeks=self.weeks,
+ days=self.days,
+ hours=self.hours,
+ minutes=self.minutes,
+ seconds=self.seconds,
+ microseconds=self.microseconds,
+ )
def __repr__(self) -> str:
fields = []
- for field in 'weeks', 'days', 'hours', 'minutes', 'seconds', 'microseconds':
+ for field in "weeks", "days", "hours", "minutes", "seconds", "microseconds":
value = getattr(self, field)
if value > 0:
- fields.append(f'{field}={value}')
+ fields.append(f"{field}={value}")
fields.append(f"start_time='{self.start_time}'")
if self.end_time: