diff options
-rw-r--r-- | pyproject.toml | 2 | ||||
-rw-r--r-- | src/apscheduler/_validators.py | 9 | ||||
-rw-r--r-- | src/apscheduler/abc.py | 66 | ||||
-rw-r--r-- | src/apscheduler/datastores/async_sqlalchemy.py | 6 | ||||
-rw-r--r-- | src/apscheduler/datastores/memory.py | 4 | ||||
-rw-r--r-- | src/apscheduler/marshalling.py | 9 | ||||
-rw-r--r-- | src/apscheduler/schedulers/sync.py | 4 | ||||
-rw-r--r-- | src/apscheduler/triggers/calendarinterval.py | 62 | ||||
-rw-r--r-- | src/apscheduler/triggers/combining.py | 32 | ||||
-rw-r--r-- | src/apscheduler/triggers/cron/__init__.py | 21 | ||||
-rw-r--r-- | src/apscheduler/triggers/cron/expressions.py | 3 | ||||
-rw-r--r-- | src/apscheduler/triggers/cron/fields.py | 9 | ||||
-rw-r--r-- | src/apscheduler/triggers/interval.py | 12 | ||||
-rw-r--r-- | tests/test_datastores.py | 30 | ||||
-rw-r--r-- | tests/test_schedulers.py | 3 | ||||
-rw-r--r-- | tests/triggers/test_calendarinterval.py | 8 | ||||
-rw-r--r-- | tests/triggers/test_combining.py | 5 | ||||
-rw-r--r-- | tests/triggers/test_cron.py | 8 |
18 files changed, 164 insertions, 129 deletions
diff --git a/pyproject.toml b/pyproject.toml index f3bf18a..c89d6c1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,7 +91,7 @@ skip_gitignore = true profile = "black" [tool.flake8] -max-line-length = 99 +max-line-length = 88 [tool.mypy] python_version = "3.10" diff --git a/src/apscheduler/_validators.py b/src/apscheduler/_validators.py index 69df656..4197edf 100644 --- a/src/apscheduler/_validators.py +++ b/src/apscheduler/_validators.py @@ -169,10 +169,11 @@ def require_state_version( try: if state["version"] > max_version: raise DeserializationError( - f"{trigger.__class__.__name__} received a serialized state with version " - f'{state["version"]}, but it only supports up to version {max_version}. ' - f"This can happen when an older version of APScheduler is being used with a data " - f"store that was previously used with a newer APScheduler version." + f"{trigger.__class__.__name__} received a serialized state with " + f'version {state["version"]}, but it only supports up to version ' + f"{max_version}. This can happen when an older version of APScheduler " + f"is being used with a data store that was previously used with a " + f"newer APScheduler version." ) except KeyError as exc: raise DeserializationError( diff --git a/src/apscheduler/abc.py b/src/apscheduler/abc.py index ec4c523..4110cd6 100644 --- a/src/apscheduler/abc.py +++ b/src/apscheduler/abc.py @@ -13,7 +13,9 @@ if TYPE_CHECKING: class Trigger(Iterator[datetime], metaclass=ABCMeta): - """Abstract base class that defines the interface that every trigger must implement.""" + """ + Abstract base class that defines the interface that every trigger must implement. + """ __slots__ = () @@ -86,7 +88,9 @@ class Subscription(metaclass=ABCMeta): class EventSource(metaclass=ABCMeta): - """Interface for objects that can deliver notifications to interested subscribers.""" + """ + Interface for objects that can deliver notifications to interested subscribers. + """ @abstractmethod def subscribe( @@ -99,9 +103,11 @@ class EventSource(metaclass=ABCMeta): """ Subscribe to events from this event source. - :param callback: callable to be called with the event object when an event is published + :param callback: callable to be called with the event object when an event is + published :param event_types: an iterable of concrete Event classes to subscribe to - :param one_shot: if ``True``, automatically unsubscribe after the first matching event + :param one_shot: if ``True``, automatically unsubscribe after the first matching + event """ @@ -167,8 +173,8 @@ class DataStore: """ Add the given task to the store. - If a task with the same ID already exists, it replaces the old one but does NOT affect - task accounting (# of running jobs). + If a task with the same ID already exists, it replaces the old one but does NOT + affect task accounting (# of running jobs). :param task: the task to be added """ @@ -205,7 +211,8 @@ class DataStore: """ Get schedules from the data store. - :param ids: a specific set of schedule IDs to return, or ``None`` to return all schedules + :param ids: a specific set of schedule IDs to return, or ``None`` to return all + schedules :return: the list of matching schedules, in unspecified order """ @@ -215,8 +222,8 @@ class DataStore: Add or update the given schedule in the data store. :param schedule: schedule to be added - :param conflict_policy: policy that determines what to do if there is an existing schedule - with the same ID + :param conflict_policy: policy that determines what to do if there is an + existing schedule with the same ID """ @abstractmethod @@ -232,8 +239,8 @@ class DataStore: """ Acquire unclaimed due schedules for processing. - This method claims up to the requested number of schedules for the given scheduler and - returns them. + This method claims up to the requested number of schedules for the given + scheduler and returns them. :param scheduler_id: unique identifier of the scheduler :param limit: maximum number of schedules to claim @@ -252,8 +259,8 @@ class DataStore: @abstractmethod def get_next_schedule_run_time(self) -> datetime | None: """ - Return the earliest upcoming run time of all the schedules in the store, or ``None`` if - there are no active schedules. + Return the earliest upcoming run time of all the schedules in the store, or + ``None`` if there are no active schedules. """ @abstractmethod @@ -270,7 +277,8 @@ class DataStore: Get the list of pending jobs. :param ids: a specific set of job IDs to return, or ``None`` to return all jobs - :return: the list of matching pending jobs, in the order they will be given to workers + :return: the list of matching pending jobs, in the order they will be given to + workers """ @abstractmethod @@ -278,8 +286,8 @@ class DataStore: """ Acquire unclaimed jobs for execution. - This method claims up to the requested number of jobs for the given worker and returns - them. + This method claims up to the requested number of jobs for the given worker and + returns them. :param worker_id: unique identifier of the worker :param limit: maximum number of jobs to claim and return @@ -327,8 +335,8 @@ class AsyncDataStore: """ Add the given task to the store. - If a task with the same ID already exists, it replaces the old one but does NOT affect - task accounting (# of running jobs). + If a task with the same ID already exists, it replaces the old one but does NOT + affect task accounting (# of running jobs). :param task: the task to be added """ @@ -365,7 +373,8 @@ class AsyncDataStore: """ Get schedules from the data store. - :param ids: a specific set of schedule IDs to return, or ``None`` to return all schedules + :param ids: a specific set of schedule IDs to return, or ``None`` to return all + schedules :return: the list of matching schedules, in unspecified order """ @@ -377,8 +386,8 @@ class AsyncDataStore: Add or update the given schedule in the data store. :param schedule: schedule to be added - :param conflict_policy: policy that determines what to do if there is an existing schedule - with the same ID + :param conflict_policy: policy that determines what to do if there is an + existing schedule with the same ID """ @abstractmethod @@ -394,8 +403,8 @@ class AsyncDataStore: """ Acquire unclaimed due schedules for processing. - This method claims up to the requested number of schedules for the given scheduler and - returns them. + This method claims up to the requested number of schedules for the given + scheduler and returns them. :param scheduler_id: unique identifier of the scheduler :param limit: maximum number of schedules to claim @@ -416,8 +425,8 @@ class AsyncDataStore: @abstractmethod async def get_next_schedule_run_time(self) -> datetime | None: """ - Return the earliest upcoming run time of all the schedules in the store, or ``None`` if - there are no active schedules. + Return the earliest upcoming run time of all the schedules in the store, or + ``None`` if there are no active schedules. """ @abstractmethod @@ -434,7 +443,8 @@ class AsyncDataStore: Get the list of pending jobs. :param ids: a specific set of job IDs to return, or ``None`` to return all jobs - :return: the list of matching pending jobs, in the order they will be given to workers + :return: the list of matching pending jobs, in the order they will be given to + workers """ @abstractmethod @@ -442,8 +452,8 @@ class AsyncDataStore: """ Acquire unclaimed jobs for execution. - This method claims up to the requested number of jobs for the given worker and returns - them. + This method claims up to the requested number of jobs for the given worker and + returns them. :param worker_id: unique identifier of the worker :param limit: maximum number of jobs to claim and return diff --git a/src/apscheduler/datastores/async_sqlalchemy.py b/src/apscheduler/datastores/async_sqlalchemy.py index 74742f8..0c165b8 100644 --- a/src/apscheduler/datastores/async_sqlalchemy.py +++ b/src/apscheduler/datastores/async_sqlalchemy.py @@ -120,7 +120,8 @@ class AsyncSQLAlchemyDataStore(_BaseSQLAlchemyDataStore, BaseAsyncDataStore): elif version > 1: raise RuntimeError( f"Unexpected schema version ({version}); " - f"only version 1 is supported by this version of APScheduler" + f"only version 1 is supported by this version of " + f"APScheduler" ) async def _deserialize_schedules(self, result: Result) -> list[Schedule]: @@ -407,7 +408,8 @@ class AsyncSQLAlchemyDataStore(_BaseSQLAlchemyDataStore, BaseAsyncDataStore): ) update_events.append(event) - # Remove schedules that have no next fire time or failed to serialize + # Remove schedules that have no next fire time or failed to + # serialize if finished_schedule_ids: delete = self.t_schedules.delete().where( self.t_schedules.c.id.in_(finished_schedule_ids) diff --git a/src/apscheduler/datastores/memory.py b/src/apscheduler/datastores/memory.py index fb29ad9..a9ff3cb 100644 --- a/src/apscheduler/datastores/memory.py +++ b/src/apscheduler/datastores/memory.py @@ -194,8 +194,8 @@ class MemoryDataStore(BaseDataStore): break elif state.acquired_by is not None: if state.acquired_by != scheduler_id and now <= state.acquired_until: - # The schedule has been acquired by another scheduler and the timeout has not - # expired yet + # The schedule has been acquired by another scheduler and the + # timeout has not expired yet continue schedules.append(state.schedule) diff --git a/src/apscheduler/marshalling.py b/src/apscheduler/marshalling.py index 0398fa7..357a973 100644 --- a/src/apscheduler/marshalling.py +++ b/src/apscheduler/marshalling.py @@ -80,8 +80,9 @@ def callable_to_ref(func: Callable) -> str: """ Return a reference to the given callable. - :raises SerializationError: if the given object is not callable, is a partial(), lambda or - local function or does not have the ``__module__`` and ``__qualname__`` attributes + :raises SerializationError: if the given object is not callable, is a partial(), + lambda or local function or does not have the ``__module__`` and + ``__qualname__`` attributes """ if isinstance(func, partial): @@ -103,8 +104,8 @@ def callable_from_ref(ref: str) -> Callable: """ Return the callable pointed to by ``ref``. - :raises DeserializationError: if the reference could not be resolved or the looked up object is - not callable + :raises DeserializationError: if the reference could not be resolved or the looked + up object is not callable """ if ":" not in ref: diff --git a/src/apscheduler/schedulers/sync.py b/src/apscheduler/schedulers/sync.py index 7ed6d3f..c821a6a 100644 --- a/src/apscheduler/schedulers/sync.py +++ b/src/apscheduler/schedulers/sync.py @@ -487,8 +487,8 @@ class Scheduler: fire_time = calculate_next() except Exception: self.logger.exception( - "Error computing next fire time for schedule %r of task %r – " - "removing schedule", + "Error computing next fire time for schedule %r of " + "task %r – removing schedule", schedule.id, schedule.task_id, ) diff --git a/src/apscheduler/triggers/calendarinterval.py b/src/apscheduler/triggers/calendarinterval.py index 61fde4b..20a8832 100644 --- a/src/apscheduler/triggers/calendarinterval.py +++ b/src/apscheduler/triggers/calendarinterval.py @@ -19,35 +19,39 @@ from ..marshalling import ( @attrs.define(kw_only=True) class CalendarIntervalTrigger(Trigger): """ - Runs the task on specified calendar-based intervals always at the same exact time of day. - - When calculating the next date, the ``years`` and ``months`` parameters are first added to the - previous date while keeping the day of the month constant. This is repeated until the resulting - date is valid. After that, the ``weeks`` and ``days`` parameters are added to that date. - Finally, the date is combined with the given time (hour, minute, second) to form the final - datetime. - - This means that if the ``days`` or ``weeks`` parameters are not used, the task will always be - executed on the same day of the month at the same wall clock time, assuming the date and time - are valid. - - If the resulting datetime is invalid due to a daylight saving forward shift, the date is - discarded and the process moves on to the next date. If instead the datetime is ambiguous due - to a backward DST shift, the earlier of the two resulting datetimes is used. - - If no previous run time is specified when requesting a new run time (like when starting for the - first time or resuming after being paused), ``start_date`` is used as a reference and the next - valid datetime equal to or later than the current time will be returned. Otherwise, the next - valid datetime starting from the previous run time is returned, even if it's in the past. - - .. warning:: Be wary of setting a start date near the end of the month (29. – 31.) if you have - ``months`` specified in your interval, as this will skip the months where those days do not - exist. Likewise, setting the start date on the leap day (February 29th) and having - ``years`` defined may cause some years to be skipped. - - Users are also discouraged from using a time inside the target timezone's DST switching - period (typically around 2 am) since a date could either be skipped or repeated due to the - specified wall clock time either occurring twice or not at all. + Runs the task on specified calendar-based intervals always at the same exact time of + day. + + When calculating the next date, the ``years`` and ``months`` parameters are first + added to the previous date while keeping the day of the month constant. This is + repeated until the resulting date is valid. After that, the ``weeks`` and ``days`` + parameters are added to that date. Finally, the date is combined with the given time + (hour, minute, second) to form the final datetime. + + This means that if the ``days`` or ``weeks`` parameters are not used, the task will + always be executed on the same day of the month at the same wall clock time, + assuming the date and time are valid. + + If the resulting datetime is invalid due to a daylight saving forward shift, the + date is discarded and the process moves on to the next date. If instead the datetime + is ambiguous due to a backward DST shift, the earlier of the two resulting datetimes + is used. + + If no previous run time is specified when requesting a new run time (like when + starting for the first time or resuming after being paused), ``start_date`` is used + as a reference and the next valid datetime equal to or later than the current time + will be returned. Otherwise, the next valid datetime starting from the previous run + time is returned, even if it's in the past. + + .. warning:: Be wary of setting a start date near the end of the month (29. – 31.) + if you have ``months`` specified in your interval, as this will skip the months + when those days do not exist. Likewise, setting the start date on the leap day + (February 29th) and having `years`` defined may cause some years to be skipped. + + Users are also discouraged from using a time inside the target timezone's DST + switching period (typically around 2 am) since a date could either be skipped or + repeated due to the specified wall clock time either occurring twice or not at + all. :param years: number of years to wait :param months: number of months to wait diff --git a/src/apscheduler/triggers/combining.py b/src/apscheduler/triggers/combining.py index 738fb30..3490863 100644 --- a/src/apscheduler/triggers/combining.py +++ b/src/apscheduler/triggers/combining.py @@ -37,21 +37,23 @@ class BaseCombiningTrigger(Trigger): @attrs.define class AndTrigger(BaseCombiningTrigger): """ - Fires on times produced by the enclosed triggers whenever the fire times are within the given - threshold. + Fires on times produced by the enclosed triggers whenever the fire times are within + the given threshold. - If the produced fire times are not within the given threshold of each other, the trigger(s) - that produced the earliest fire time will be asked for their next fire time and the iteration - is restarted. If instead all of the triggers agree on a fire time, all the triggers are asked - for their next fire times and the earliest of the previously produced fire times will be - returned. + If the produced fire times are not within the given threshold of each other, the + trigger(s) that produced the earliest fire time will be asked for their next fire + time and the iteration is restarted. If instead all the triggers agree on a fire + time, all the triggers are asked for their next fire times and the earliest of the + previously produced fire times will be returned. This trigger will be finished when any of the enclosed trigger has finished. :param triggers: triggers to combine - :param threshold: maximum time difference between the next fire times of the triggers in order - for the earliest of them to be returned from :meth:`next` (in seconds, or as timedelta) - :param max_iterations: maximum number of iterations of fire time calculations before giving up + :param threshold: maximum time difference between the next fire times of the + triggers in order for the earliest of them to be returned from :meth:`next` (in + seconds, or as timedelta) + :param max_iterations: maximum number of iterations of fire time calculations before + giving up """ threshold: timedelta = attrs.field(converter=as_timedelta, default=1) @@ -104,7 +106,8 @@ class AndTrigger(BaseCombiningTrigger): def __repr__(self) -> str: return ( f"{self.__class__.__name__}({self.triggers}, " - f"threshold={self.threshold.total_seconds()}, max_iterations={self.max_iterations})" + f"threshold={self.threshold.total_seconds()}, " + f"max_iterations={self.max_iterations})" ) @@ -114,8 +117,8 @@ class OrTrigger(BaseCombiningTrigger): Fires on every fire time of every trigger in chronological order. If two or more triggers produce the same fire time, it will only be used once. - This trigger will be finished when none of the enclosed triggers can produce any new fire - times. + This trigger will be finished when none of the enclosed triggers can produce any new + fire times. :param triggers: triggers to combine """ @@ -131,7 +134,8 @@ class OrTrigger(BaseCombiningTrigger): default=None, ) if earliest_time is not None: - # Generate new fire times for the trigger(s) that generated the earliest fire time + # Generate new fire times for the trigger(s) that generated the earliest + # fire time for i, fire_time in enumerate(self._next_fire_times): if fire_time == earliest_time: self._next_fire_times[i] = self.triggers[i].next() diff --git a/src/apscheduler/triggers/cron/__init__.py b/src/apscheduler/triggers/cron/__init__.py index d518aac..e249418 100644 --- a/src/apscheduler/triggers/cron/__init__.py +++ b/src/apscheduler/triggers/cron/__init__.py @@ -28,18 +28,20 @@ from .fields import ( @attrs.define(kw_only=True) class CronTrigger(Trigger): """ - Triggers when current time matches all specified time constraints, similarly to how the UNIX - cron scheduler works. + Triggers when current time matches all specified time constraints, similarly to how + the UNIX cron scheduler works. :param year: 4-digit year :param month: month (1-12) :param day: day of the (1-31) :param week: ISO week (1-53) - :param day_of_week: number or name of weekday (0-7 or sun,mon,tue,wed,thu,fri,sat,sun) + :param day_of_week: number or name of weekday (0-7 or sun,mon,tue,wed,thu,fri,sat, + sun) :param hour: hour (0-23) :param minute: minute (0-59) :param second: second (0-59) - :param start_time: earliest possible date/time to trigger on (defaults to current time) + :param start_time: earliest possible date/time to trigger on (defaults to current + time) :param end_time: latest possible date/time to trigger on :param timezone: time zone to use for the date/time calculations (defaults to the local timezone) @@ -109,7 +111,8 @@ class CronTrigger(Trigger): """ Create a :class:`~CronTrigger` from a standard crontab expression. - See https://en.wikipedia.org/wiki/Cron for more information on the format accepted here. + See https://en.wikipedia.org/wiki/Cron for more information on the format + accepted here. :param expr: minute, hour, day of month, month, day of week :param timezone: time zone to use for the date/time calculations @@ -133,11 +136,11 @@ class CronTrigger(Trigger): self, dateval: datetime, fieldnum: int ) -> tuple[datetime, int]: """ - Increments the designated field and resets all less significant fields to their minimum - values. + Increments the designated field and resets all less significant fields to their + minimum values. - :return: a tuple containing the new date, and the number of the field that was actually - incremented + :return: a tuple containing the new date, and the number of the field that was + actually incremented """ values = {} diff --git a/src/apscheduler/triggers/cron/expressions.py b/src/apscheduler/triggers/cron/expressions.py index ddb2209..8f8c94c 100644 --- a/src/apscheduler/triggers/cron/expressions.py +++ b/src/apscheduler/triggers/cron/expressions.py @@ -200,7 +200,8 @@ class WeekdayPositionExpression(AllExpression): 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 + # Figure out the weekday of the month's first day and the number of days in that + # month first_day_wday, last_day = monthrange(dateval.year, dateval.month) # Calculate which day of the month is the first of the target weekdays diff --git a/src/apscheduler/triggers/cron/fields.py b/src/apscheduler/triggers/cron/fields.py index b70f643..285e09b 100644 --- a/src/apscheduler/triggers/cron/fields.py +++ b/src/apscheduler/triggers/cron/fields.py @@ -1,4 +1,7 @@ -"""Fields represent CronTrigger options which map to :class:`~datetime.datetime` fields.""" +""" +Fields represent CronTrigger options which map to :class:`~datetime.datetime` fields. +""" + from __future__ import annotations import re @@ -144,8 +147,8 @@ class DayOfWeekField(BaseField, real=False, extra_compilers=(WeekdayRangeExpress expr = f"{WEEKDAYS[first]}-{WEEKDAYS[last]}" - # For expressions like Sun-Tue or Sat-Mon, add two expressions that together cover the - # expected weekdays + # For expressions like Sun-Tue or Sat-Mon, add two expressions that together + # cover the expected weekdays match = WeekdayRangeExpression.value_re.match(expr) if match and match.groups()[1]: groups = match.groups() diff --git a/src/apscheduler/triggers/interval.py b/src/apscheduler/triggers/interval.py index 37f3456..8d0d8d4 100644 --- a/src/apscheduler/triggers/interval.py +++ b/src/apscheduler/triggers/interval.py @@ -15,10 +15,11 @@ class IntervalTrigger(Trigger): """ Triggers on specified intervals. - The first trigger time is on ``start_time`` which is the moment the trigger was created unless - specifically overridden. If ``end_time`` is specified, the last trigger time will be at or - before that time. If no ``end_time`` has been given, the trigger will produce new trigger times - as long as the resulting datetimes are valid datetimes in Python. + The first trigger time is on ``start_time`` which is the moment the trigger was + created unless specifically overridden. If ``end_time`` is specified, the last + trigger time will be at or before that time. If no ``end_time`` has been given, the + trigger will produce new trigger times as long as the resulting datetimes are valid + datetimes in Python. :param weeks: number of weeks to wait :param days: number of days to wait @@ -26,7 +27,8 @@ class IntervalTrigger(Trigger): :param minutes: number of minutes to wait :param seconds: number of seconds to wait :param microseconds: number of microseconds to wait - :param start_time: first trigger date/time (defaults to current date/time if omitted) + :param start_time: first trigger date/time (defaults to current date/time if + omitted) :param end_time: latest possible date/time to trigger on """ diff --git a/tests/test_datastores.py b/tests/test_datastores.py index 40fad27..3159a9e 100644 --- a/tests/test_datastores.py +++ b/tests/test_datastores.py @@ -323,8 +323,8 @@ class TestDataStores: schedules3 = datastore.acquire_schedules("dummy-id3", 1) assert not schedules3 - # Update the schedules and check that the job store actually deletes the first - # one and updates the second one + # Update the schedules and check that the job store actually deletes the + # first one and updates the second one schedules1[0].next_fire_time = None schedules2[0].next_fire_time = datetime(2020, 9, 15, tzinfo=timezone.utc) @@ -388,8 +388,8 @@ class TestDataStores: self, datastore: DataStore, schedules: list[Schedule], freezer ) -> None: """ - Test that a scheduler can acquire schedules that were acquired by another scheduler but - not released within the lock timeout period. + Test that a scheduler can acquire schedules that were acquired by another + scheduler but not released within the lock timeout period. """ datastore.add_schedule(schedules[0], ConflictPolicy.exception) @@ -542,8 +542,8 @@ class TestDataStores: self, datastore: DataStore, freezer: FrozenDateTimeFactory ) -> None: """ - Test that a worker can acquire jobs that were acquired by another scheduler but not - released within the lock timeout period. + Test that a worker can acquire jobs that were acquired by another scheduler but + not released within the lock timeout period. """ datastore.add_task(Task(id="task1", func=asynccontextmanager)) @@ -574,7 +574,8 @@ class TestDataStores: for job in jobs: datastore.add_job(job) - # Check that only 2 jobs are returned from acquire_jobs() even though the limit wqas 3 + # Check that only 2 jobs are returned from acquire_jobs() even though the limit + # wqas 3 acquired_jobs = datastore.acquire_jobs("worker1", 3) assert [job.id for job in acquired_jobs] == [job.id for job in jobs[:2]] @@ -784,8 +785,8 @@ class TestAsyncDataStores: schedules3 = await datastore.acquire_schedules("dummy-id3", 1) assert not schedules3 - # Update the schedules and check that the job store actually deletes the first - # one and updates the second one + # Update the schedules and check that the job store actually deletes the + # first one and updates the second one schedules1[0].next_fire_time = None schedules2[0].next_fire_time = datetime(2020, 9, 15, tzinfo=timezone.utc) @@ -851,8 +852,8 @@ class TestAsyncDataStores: self, datastore: AsyncDataStore, schedules: list[Schedule], freezer ) -> None: """ - Test that a scheduler can acquire schedules that were acquired by another scheduler but - not released within the lock timeout period. + Test that a scheduler can acquire schedules that were acquired by another + scheduler but not released within the lock timeout period. """ await datastore.add_schedule(schedules[0], ConflictPolicy.exception) @@ -1002,8 +1003,8 @@ class TestAsyncDataStores: self, datastore: AsyncDataStore, freezer: FrozenDateTimeFactory ) -> None: """ - Test that a worker can acquire jobs that were acquired by another scheduler but not - released within the lock timeout period. + Test that a worker can acquire jobs that were acquired by another scheduler but + not released within the lock timeout period. """ await datastore.add_task(Task(id="task1", func=asynccontextmanager)) @@ -1036,7 +1037,8 @@ class TestAsyncDataStores: for job in jobs: await datastore.add_job(job) - # Check that only 2 jobs are returned from acquire_jobs() even though the limit wqas 3 + # Check that only 2 jobs are returned from acquire_jobs() even though the limit + # wqas 3 acquired_jobs = await datastore.acquire_jobs("worker1", 3) assert [job.id for job in acquired_jobs] == [job.id for job in jobs[:2]] diff --git a/tests/test_schedulers.py b/tests/test_schedulers.py index f57cbeb..589b753 100644 --- a/tests/test_schedulers.py +++ b/tests/test_schedulers.py @@ -393,7 +393,8 @@ class TestSyncScheduler: fake_uniform.assert_called_once_with(0, expected_upper_bound) - # Check that the job was created with the proper amount of jitter in its scheduled time + # Check that the job was created with the proper amount of jitter in its + # scheduled time jobs = scheduler.data_store.get_jobs({job_id}) assert jobs[0].jitter == timedelta(seconds=jitter) assert jobs[0].scheduled_fire_time == orig_start_time + timedelta( diff --git a/tests/triggers/test_calendarinterval.py b/tests/triggers/test_calendarinterval.py index 4466c34..ea929af 100644 --- a/tests/triggers/test_calendarinterval.py +++ b/tests/triggers/test_calendarinterval.py @@ -39,8 +39,8 @@ def test_end_date(timezone, serializer): def test_missing_time(timezone, serializer): """ - Test that if the designated time does not exist on a day due to a forward DST shift, the day is - skipped entirely. + Test that if the designated time does not exist on a day due to a forward DST shift, + the day is skipped entirely. """ trigger = CalendarIntervalTrigger( @@ -54,8 +54,8 @@ def test_missing_time(timezone, serializer): def test_repeated_time(timezone, serializer): """ - Test that if the designated time is repeated during a day due to a backward DST shift, the task - is executed on the earlier occurrence of that time. + Test that if the designated time is repeated during a day due to a backward DST + shift, the task is executed on the earlier occurrence of that time. """ trigger = CalendarIntervalTrigger( diff --git a/tests/triggers/test_combining.py b/tests/triggers/test_combining.py index 942bf49..8be7387 100644 --- a/tests/triggers/test_combining.py +++ b/tests/triggers/test_combining.py @@ -57,8 +57,9 @@ class TestAndTrigger: assert repr(trigger) == ( "AndTrigger([IntervalTrigger(seconds=4, " - "start_time='2020-05-16 14:17:30.254212+02:00'), IntervalTrigger(seconds=4, " - "start_time='2020-05-16 14:17:32.254212+02:00')], threshold=1.0, max_iterations=10000)" + "start_time='2020-05-16 14:17:30.254212+02:00'), IntervalTrigger(" + "seconds=4, start_time='2020-05-16 14:17:32.254212+02:00')], " + "threshold=1.0, max_iterations=10000)" ) diff --git a/tests/triggers/test_cron.py b/tests/triggers/test_cron.py index eb832e7..76e3b62 100644 --- a/tests/triggers/test_cron.py +++ b/tests/triggers/test_cron.py @@ -227,8 +227,8 @@ def test_last_weekday(timezone, serializer): def test_increment_weekday(timezone, serializer): """ - Tests that incrementing the weekday field in the process of calculating the next matching - date won't cause problems. + Tests that incrementing the weekday field in the process of calculating the next + matching date won't cause problems. """ start_time = datetime(2009, 9, 25, 7, tzinfo=timezone) @@ -386,8 +386,8 @@ def test_dst_change( ): """ Making sure that CronTrigger works correctly when crossing the DST switch threshold. - Note that you should explicitly compare datetimes as strings to avoid the internal datetime - comparison which would test for equality in the UTC timezone. + Note that you should explicitly compare datetimes as strings to avoid the internal + datetime comparison which would test for equality in the UTC timezone. """ timezone = ZoneInfo("US/Eastern") |