diff options
author | Alex Grönholm <alex.gronholm@nextday.fi> | 2022-04-20 01:00:57 +0300 |
---|---|---|
committer | Alex Grönholm <alex.gronholm@nextday.fi> | 2022-04-20 01:11:20 +0300 |
commit | b20f62d929eed84ad18020bb82dd43d8cb70da4d (patch) | |
tree | c42bf1877dd54755c55c649269e1254995bdf0c9 /src/apscheduler/triggers | |
parent | 82992cd427a9ab2351d8e0719b82d826dff5a521 (diff) | |
download | apscheduler-b20f62d929eed84ad18020bb82dd43d8cb70da4d.tar.gz |
Switched to Black for code formatting
Diffstat (limited to 'src/apscheduler/triggers')
-rw-r--r-- | src/apscheduler/triggers/calendarinterval.py | 47 | ||||
-rw-r--r-- | src/apscheduler/triggers/combining.py | 38 | ||||
-rw-r--r-- | src/apscheduler/triggers/cron/__init__.py | 128 | ||||
-rw-r--r-- | src/apscheduler/triggers/cron/expressions.py | 101 | ||||
-rw-r--r-- | src/apscheduler/triggers/cron/fields.py | 77 | ||||
-rw-r--r-- | src/apscheduler/triggers/date.py | 10 | ||||
-rw-r--r-- | src/apscheduler/triggers/interval.py | 68 |
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: |