From 0bc26e22b458ec0f013c467ef6206130257d03be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Sat, 30 Jul 2022 22:26:31 +0300 Subject: Made the apscheduler.structures module private and re-exported its code --- src/apscheduler/__init__.py | 7 + src/apscheduler/_structures.py | 233 ++++++++++++++++++++++++ src/apscheduler/abc.py | 5 +- src/apscheduler/datastores/async_adapter.py | 2 +- src/apscheduler/datastores/async_sqlalchemy.py | 4 +- src/apscheduler/datastores/memory.py | 3 +- src/apscheduler/datastores/mongodb.py | 4 +- src/apscheduler/datastores/sqlalchemy.py | 4 +- src/apscheduler/schedulers/async_.py | 4 +- src/apscheduler/schedulers/sync.py | 2 +- src/apscheduler/structures.py | 235 ------------------------- src/apscheduler/workers/async_.py | 4 +- src/apscheduler/workers/sync.py | 2 +- tests/test_datastores.py | 11 +- tests/test_schedulers.py | 10 +- tests/test_workers.py | 5 +- 16 files changed, 268 insertions(+), 267 deletions(-) create mode 100644 src/apscheduler/_structures.py delete mode 100644 src/apscheduler/structures.py diff --git a/src/apscheduler/__init__.py b/src/apscheduler/__init__.py index e2ad001..630ca51 100644 --- a/src/apscheduler/__init__.py +++ b/src/apscheduler/__init__.py @@ -5,15 +5,21 @@ __all__ = [ "ConflictPolicy", "ConflictingIdError", "DeserializationError", + "Job", "JobCancelled", "JobDeadlineMissed", + "JobInfo", "JobLookupError", "JobOutcome", + "JobResult", "JobResultNotReady", "MaxIterationsReached", + "RetrySettings", "RunState", + "Schedule", "ScheduleLookupError", "SerializationError", + "Task", "TaskLookupError", ] @@ -32,6 +38,7 @@ from ._exceptions import ( SerializationError, TaskLookupError, ) +from ._structures import Job, JobInfo, JobResult, RetrySettings, Schedule, Task # Re-export imports, so they look like they live directly in this package value: Any diff --git a/src/apscheduler/_structures.py b/src/apscheduler/_structures.py new file mode 100644 index 0000000..1835112 --- /dev/null +++ b/src/apscheduler/_structures.py @@ -0,0 +1,233 @@ +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from functools import partial +from typing import TYPE_CHECKING, Any, Callable +from uuid import UUID, uuid4 + +import attrs +import tenacity.stop +import tenacity.wait +from attrs.validators import instance_of + +from ._converters import as_enum, as_timedelta +from ._enums import CoalescePolicy, JobOutcome +from .marshalling import callable_from_ref, callable_to_ref + +if TYPE_CHECKING: + from .abc import Serializer, Trigger + + +def serialize(inst, field, value): + if isinstance(value, frozenset): + return list(value) + + return value + + +@attrs.define(kw_only=True) +class Task: + id: str + func: Callable = attrs.field(eq=False, order=False) + max_running_jobs: int | None = attrs.field(eq=False, order=False, default=None) + misfire_grace_time: timedelta | None = attrs.field( + eq=False, order=False, default=None + ) + state: Any = None + + def marshal(self, serializer: Serializer) -> dict[str, Any]: + marshalled = attrs.asdict(self, value_serializer=serialize) + marshalled["func"] = callable_to_ref(self.func) + marshalled["state"] = serializer.serialize(self.state) if self.state else None + return marshalled + + @classmethod + def unmarshal(cls, serializer: Serializer, marshalled: dict[str, Any]) -> Task: + marshalled["func"] = callable_from_ref(marshalled["func"]) + if marshalled["state"] is not None: + marshalled["state"] = serializer.deserialize(marshalled["state"]) + + return cls(**marshalled) + + +@attrs.define(kw_only=True) +class Schedule: + id: str + task_id: str = attrs.field(eq=False, order=False) + trigger: Trigger = attrs.field(eq=False, order=False) + args: tuple = attrs.field(eq=False, order=False, converter=tuple, default=()) + kwargs: dict[str, Any] = attrs.field( + eq=False, order=False, converter=dict, default=() + ) + coalesce: CoalescePolicy = attrs.field( + eq=False, + order=False, + default=CoalescePolicy.latest, + converter=as_enum(CoalescePolicy), + ) + misfire_grace_time: timedelta | None = attrs.field( + eq=False, order=False, default=None, converter=as_timedelta + ) + max_jitter: timedelta | None = attrs.field( + eq=False, order=False, converter=as_timedelta, default=None + ) + tags: frozenset[str] = attrs.field( + eq=False, order=False, converter=frozenset, default=() + ) + next_fire_time: datetime | None = attrs.field(eq=False, order=False, default=None) + last_fire_time: datetime | None = attrs.field(eq=False, order=False, default=None) + acquired_by: str | None = attrs.field(eq=False, order=False, default=None) + acquired_until: datetime | None = attrs.field(eq=False, order=False, default=None) + + def marshal(self, serializer: Serializer) -> dict[str, Any]: + marshalled = attrs.asdict(self, value_serializer=serialize) + marshalled["trigger"] = serializer.serialize(self.trigger) + marshalled["args"] = serializer.serialize(self.args) + marshalled["kwargs"] = serializer.serialize(self.kwargs) + if not self.acquired_by: + del marshalled["acquired_by"] + del marshalled["acquired_until"] + + return marshalled + + @classmethod + def unmarshal(cls, serializer: Serializer, marshalled: dict[str, Any]) -> Schedule: + marshalled["trigger"] = serializer.deserialize(marshalled["trigger"]) + marshalled["args"] = serializer.deserialize(marshalled["args"]) + marshalled["kwargs"] = serializer.deserialize(marshalled["kwargs"]) + return cls(**marshalled) + + @property + def next_deadline(self) -> datetime | None: + if self.next_fire_time and self.misfire_grace_time: + return self.next_fire_time + self.misfire_grace_time + + return None + + +@attrs.define(kw_only=True) +class Job: + id: UUID = attrs.field(factory=uuid4) + task_id: str = attrs.field(eq=False, order=False) + args: tuple = attrs.field(eq=False, order=False, converter=tuple, default=()) + kwargs: dict[str, Any] = attrs.field( + eq=False, order=False, converter=dict, default=() + ) + schedule_id: str | None = attrs.field(eq=False, order=False, default=None) + scheduled_fire_time: datetime | None = attrs.field( + eq=False, order=False, default=None + ) + jitter: timedelta = attrs.field( + eq=False, order=False, converter=as_timedelta, factory=timedelta + ) + start_deadline: datetime | None = attrs.field(eq=False, order=False, default=None) + tags: frozenset[str] = attrs.field( + eq=False, order=False, converter=frozenset, default=() + ) + created_at: datetime = attrs.field( + eq=False, order=False, factory=partial(datetime.now, timezone.utc) + ) + started_at: datetime | None = attrs.field(eq=False, order=False, default=None) + acquired_by: str | None = attrs.field(eq=False, order=False, default=None) + acquired_until: datetime | None = attrs.field(eq=False, order=False, default=None) + + @property + def original_scheduled_time(self) -> datetime | None: + """The scheduled time without any jitter included.""" + if self.scheduled_fire_time is None: + return None + + return self.scheduled_fire_time - self.jitter + + def marshal(self, serializer: Serializer) -> dict[str, Any]: + marshalled = attrs.asdict(self, value_serializer=serialize) + marshalled["args"] = serializer.serialize(self.args) + marshalled["kwargs"] = serializer.serialize(self.kwargs) + if not self.acquired_by: + del marshalled["acquired_by"] + del marshalled["acquired_until"] + + return marshalled + + @classmethod + def unmarshal(cls, serializer: Serializer, marshalled: dict[str, Any]) -> Job: + marshalled["args"] = serializer.deserialize(marshalled["args"]) + marshalled["kwargs"] = serializer.deserialize(marshalled["kwargs"]) + return cls(**marshalled) + + +@attrs.define(kw_only=True) +class JobInfo: + job_id: UUID + task_id: str + schedule_id: str | None + scheduled_fire_time: datetime | None + jitter: timedelta + start_deadline: datetime | None + tags: frozenset[str] + + @classmethod + def from_job(cls, job: Job) -> JobInfo: + return cls( + job_id=job.id, + task_id=job.task_id, + schedule_id=job.schedule_id, + scheduled_fire_time=job.scheduled_fire_time, + jitter=job.jitter, + start_deadline=job.start_deadline, + tags=job.tags, + ) + + +@attrs.define(kw_only=True, frozen=True) +class JobResult: + job_id: UUID + outcome: JobOutcome = attrs.field( + eq=False, order=False, converter=as_enum(JobOutcome) + ) + finished_at: datetime = attrs.field( + eq=False, order=False, factory=partial(datetime.now, timezone.utc) + ) + exception: BaseException | None = attrs.field(eq=False, order=False, default=None) + return_value: Any = attrs.field(eq=False, order=False, default=None) + + def marshal(self, serializer: Serializer) -> dict[str, Any]: + marshalled = attrs.asdict(self, value_serializer=serialize) + if self.outcome is JobOutcome.error: + marshalled["exception"] = serializer.serialize(self.exception) + else: + del marshalled["exception"] + + if self.outcome is JobOutcome.success: + marshalled["return_value"] = serializer.serialize(self.return_value) + else: + del marshalled["return_value"] + + return marshalled + + @classmethod + def unmarshal(cls, serializer: Serializer, marshalled: dict[str, Any]) -> JobResult: + if marshalled.get("exception"): + marshalled["exception"] = serializer.deserialize(marshalled["exception"]) + elif marshalled.get("return_value"): + marshalled["return_value"] = serializer.deserialize( + marshalled["return_value"] + ) + + return cls(**marshalled) + + +@attrs.define(kw_only=True, frozen=True) +class RetrySettings: + stop: tenacity.stop.stop_base = attrs.field( + validator=instance_of(tenacity.stop.stop_base), + default=tenacity.stop_after_delay(60), + ) + wait: tenacity.wait.wait_base = attrs.field( + validator=instance_of(tenacity.wait.wait_base), + default=tenacity.wait_exponential(min=0.5, max=20), + ) + + @classmethod + def fail_immediately(cls) -> RetrySettings: + return cls(stop=tenacity.stop_after_attempt(1)) diff --git a/src/apscheduler/abc.py b/src/apscheduler/abc.py index dad6e47..e277158 100644 --- a/src/apscheduler/abc.py +++ b/src/apscheduler/abc.py @@ -6,10 +6,9 @@ from datetime import datetime from typing import TYPE_CHECKING, Any, Callable, Iterable, Iterator from uuid import UUID -from ._enums import ConflictPolicy -from .structures import Job, JobResult, Schedule, Task - if TYPE_CHECKING: + from ._enums import ConflictPolicy + from ._structures import Job, JobResult, Schedule, Task from .events import Event diff --git a/src/apscheduler/datastores/async_adapter.py b/src/apscheduler/datastores/async_adapter.py index e155116..d16ae56 100644 --- a/src/apscheduler/datastores/async_adapter.py +++ b/src/apscheduler/datastores/async_adapter.py @@ -10,9 +10,9 @@ from anyio import to_thread from anyio.from_thread import BlockingPortal from .._enums import ConflictPolicy +from .._structures import Job, JobResult, Schedule, Task from ..abc import AsyncEventBroker, DataStore from ..eventbrokers.async_adapter import AsyncEventBrokerAdapter, SyncEventBrokerAdapter -from ..structures import Job, JobResult, Schedule, Task from .base import BaseAsyncDataStore diff --git a/src/apscheduler/datastores/async_sqlalchemy.py b/src/apscheduler/datastores/async_sqlalchemy.py index 2f2f37e..fbf55d9 100644 --- a/src/apscheduler/datastores/async_sqlalchemy.py +++ b/src/apscheduler/datastores/async_sqlalchemy.py @@ -19,7 +19,8 @@ from sqlalchemy.sql.elements import BindParameter from .._enums import ConflictPolicy from .._exceptions import ConflictingIdError, SerializationError, TaskLookupError -from ..abc import AsyncEventBroker, Job, Schedule +from .._structures import Job, JobResult, Schedule, Task +from ..abc import AsyncEventBroker from ..events import ( DataStoreEvent, JobAcquired, @@ -34,7 +35,6 @@ from ..events import ( TaskUpdated, ) from ..marshalling import callable_to_ref -from ..structures import JobResult, Task from .base import BaseAsyncDataStore from .sqlalchemy import _BaseSQLAlchemyDataStore diff --git a/src/apscheduler/datastores/memory.py b/src/apscheduler/datastores/memory.py index d131327..dbc7672 100644 --- a/src/apscheduler/datastores/memory.py +++ b/src/apscheduler/datastores/memory.py @@ -11,7 +11,7 @@ import attrs from .._enums import ConflictPolicy from .._exceptions import ConflictingIdError, TaskLookupError -from ..abc import Job, Schedule +from .._structures import Job, JobResult, Schedule, Task from ..events import ( JobAcquired, JobAdded, @@ -23,7 +23,6 @@ from ..events import ( TaskRemoved, TaskUpdated, ) -from ..structures import JobResult, Task from .base import BaseDataStore max_datetime = datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, tzinfo=timezone.utc) diff --git a/src/apscheduler/datastores/mongodb.py b/src/apscheduler/datastores/mongodb.py index 5f0b5ef..4a1339a 100644 --- a/src/apscheduler/datastores/mongodb.py +++ b/src/apscheduler/datastores/mongodb.py @@ -24,7 +24,8 @@ from .._exceptions import ( SerializationError, TaskLookupError, ) -from ..abc import EventBroker, Job, Schedule, Serializer +from .._structures import Job, JobResult, RetrySettings, Schedule, Task +from ..abc import EventBroker, Serializer from ..eventbrokers.local import LocalEventBroker from ..events import ( DataStoreEvent, @@ -39,7 +40,6 @@ from ..events import ( TaskUpdated, ) from ..serializers.pickle import PickleSerializer -from ..structures import JobResult, RetrySettings, Task from .base import BaseDataStore diff --git a/src/apscheduler/datastores/sqlalchemy.py b/src/apscheduler/datastores/sqlalchemy.py index c920d52..3110e4d 100644 --- a/src/apscheduler/datastores/sqlalchemy.py +++ b/src/apscheduler/datastores/sqlalchemy.py @@ -33,7 +33,8 @@ from sqlalchemy.sql.elements import BindParameter, literal from .._enums import CoalescePolicy, ConflictPolicy, JobOutcome from .._exceptions import ConflictingIdError, SerializationError, TaskLookupError -from ..abc import EventBroker, Job, Schedule, Serializer +from .._structures import Job, JobResult, RetrySettings, Schedule, Task +from ..abc import EventBroker, Serializer from ..events import ( Event, JobAcquired, @@ -50,7 +51,6 @@ from ..events import ( ) from ..marshalling import callable_to_ref from ..serializers.pickle import PickleSerializer -from ..structures import JobResult, RetrySettings, Task from .base import BaseDataStore diff --git a/src/apscheduler/schedulers/async_.py b/src/apscheduler/schedulers/async_.py index ca8ab37..cbe8887 100644 --- a/src/apscheduler/schedulers/async_.py +++ b/src/apscheduler/schedulers/async_.py @@ -22,7 +22,8 @@ from .._exceptions import ( JobLookupError, ScheduleLookupError, ) -from ..abc import AsyncDataStore, AsyncEventBroker, Job, Schedule, Subscription, Trigger +from .._structures import Job, JobResult, Schedule, Task +from ..abc import AsyncDataStore, AsyncEventBroker, Subscription, Trigger from ..context import current_scheduler from ..datastores.memory import MemoryDataStore from ..eventbrokers.async_local import LocalAsyncEventBroker @@ -35,7 +36,6 @@ from ..events import ( ScheduleUpdated, ) from ..marshalling import callable_to_ref -from ..structures import JobResult, Task from ..workers.async_ import AsyncWorker _microsecond_delta = timedelta(microseconds=1) diff --git a/src/apscheduler/schedulers/sync.py b/src/apscheduler/schedulers/sync.py index c3e9207..162e6b9 100644 --- a/src/apscheduler/schedulers/sync.py +++ b/src/apscheduler/schedulers/sync.py @@ -22,6 +22,7 @@ from .._exceptions import ( JobLookupError, ScheduleLookupError, ) +from .._structures import Job, JobResult, Schedule, Task from ..abc import DataStore, EventBroker, Trigger from ..context import current_scheduler from ..datastores.memory import MemoryDataStore @@ -35,7 +36,6 @@ from ..events import ( ScheduleUpdated, ) from ..marshalling import callable_to_ref -from ..structures import Job, JobResult, Schedule, Task from ..workers.sync import Worker _microsecond_delta = timedelta(microseconds=1) diff --git a/src/apscheduler/structures.py b/src/apscheduler/structures.py deleted file mode 100644 index 148f0db..0000000 --- a/src/apscheduler/structures.py +++ /dev/null @@ -1,235 +0,0 @@ -from __future__ import annotations - -from datetime import datetime, timedelta, timezone -from functools import partial -from typing import Any, Callable -from uuid import UUID, uuid4 - -import attrs -import tenacity.stop -import tenacity.wait -from attrs.validators import instance_of - -from . import abc -from ._converters import as_enum, as_timedelta -from ._enums import CoalescePolicy, JobOutcome -from .marshalling import callable_from_ref, callable_to_ref - - -def serialize(inst, field, value): - if isinstance(value, frozenset): - return list(value) - - return value - - -@attrs.define(kw_only=True) -class Task: - id: str - func: Callable = attrs.field(eq=False, order=False) - max_running_jobs: int | None = attrs.field(eq=False, order=False, default=None) - misfire_grace_time: timedelta | None = attrs.field( - eq=False, order=False, default=None - ) - state: Any = None - - def marshal(self, serializer: abc.Serializer) -> dict[str, Any]: - marshalled = attrs.asdict(self, value_serializer=serialize) - marshalled["func"] = callable_to_ref(self.func) - marshalled["state"] = serializer.serialize(self.state) if self.state else None - return marshalled - - @classmethod - def unmarshal(cls, serializer: abc.Serializer, marshalled: dict[str, Any]) -> Task: - marshalled["func"] = callable_from_ref(marshalled["func"]) - if marshalled["state"] is not None: - marshalled["state"] = serializer.deserialize(marshalled["state"]) - - return cls(**marshalled) - - -@attrs.define(kw_only=True) -class Schedule: - id: str - task_id: str = attrs.field(eq=False, order=False) - trigger: abc.Trigger = attrs.field(eq=False, order=False) - args: tuple = attrs.field(eq=False, order=False, converter=tuple, default=()) - kwargs: dict[str, Any] = attrs.field( - eq=False, order=False, converter=dict, default=() - ) - coalesce: CoalescePolicy = attrs.field( - eq=False, - order=False, - default=CoalescePolicy.latest, - converter=as_enum(CoalescePolicy), - ) - misfire_grace_time: timedelta | None = attrs.field( - eq=False, order=False, default=None, converter=as_timedelta - ) - max_jitter: timedelta | None = attrs.field( - eq=False, order=False, converter=as_timedelta, default=None - ) - tags: frozenset[str] = attrs.field( - eq=False, order=False, converter=frozenset, default=() - ) - next_fire_time: datetime | None = attrs.field(eq=False, order=False, default=None) - last_fire_time: datetime | None = attrs.field(eq=False, order=False, default=None) - acquired_by: str | None = attrs.field(eq=False, order=False, default=None) - acquired_until: datetime | None = attrs.field(eq=False, order=False, default=None) - - def marshal(self, serializer: abc.Serializer) -> dict[str, Any]: - marshalled = attrs.asdict(self, value_serializer=serialize) - marshalled["trigger"] = serializer.serialize(self.trigger) - marshalled["args"] = serializer.serialize(self.args) - marshalled["kwargs"] = serializer.serialize(self.kwargs) - if not self.acquired_by: - del marshalled["acquired_by"] - del marshalled["acquired_until"] - - return marshalled - - @classmethod - def unmarshal( - cls, serializer: abc.Serializer, marshalled: dict[str, Any] - ) -> Schedule: - marshalled["trigger"] = serializer.deserialize(marshalled["trigger"]) - marshalled["args"] = serializer.deserialize(marshalled["args"]) - marshalled["kwargs"] = serializer.deserialize(marshalled["kwargs"]) - return cls(**marshalled) - - @property - def next_deadline(self) -> datetime | None: - if self.next_fire_time and self.misfire_grace_time: - return self.next_fire_time + self.misfire_grace_time - - return None - - -@attrs.define(kw_only=True) -class Job: - id: UUID = attrs.field(factory=uuid4) - task_id: str = attrs.field(eq=False, order=False) - args: tuple = attrs.field(eq=False, order=False, converter=tuple, default=()) - kwargs: dict[str, Any] = attrs.field( - eq=False, order=False, converter=dict, default=() - ) - schedule_id: str | None = attrs.field(eq=False, order=False, default=None) - scheduled_fire_time: datetime | None = attrs.field( - eq=False, order=False, default=None - ) - jitter: timedelta = attrs.field( - eq=False, order=False, converter=as_timedelta, factory=timedelta - ) - start_deadline: datetime | None = attrs.field(eq=False, order=False, default=None) - tags: frozenset[str] = attrs.field( - eq=False, order=False, converter=frozenset, default=() - ) - created_at: datetime = attrs.field( - eq=False, order=False, factory=partial(datetime.now, timezone.utc) - ) - started_at: datetime | None = attrs.field(eq=False, order=False, default=None) - acquired_by: str | None = attrs.field(eq=False, order=False, default=None) - acquired_until: datetime | None = attrs.field(eq=False, order=False, default=None) - - @property - def original_scheduled_time(self) -> datetime | None: - """The scheduled time without any jitter included.""" - if self.scheduled_fire_time is None: - return None - - return self.scheduled_fire_time - self.jitter - - def marshal(self, serializer: abc.Serializer) -> dict[str, Any]: - marshalled = attrs.asdict(self, value_serializer=serialize) - marshalled["args"] = serializer.serialize(self.args) - marshalled["kwargs"] = serializer.serialize(self.kwargs) - if not self.acquired_by: - del marshalled["acquired_by"] - del marshalled["acquired_until"] - - return marshalled - - @classmethod - def unmarshal(cls, serializer: abc.Serializer, marshalled: dict[str, Any]) -> Job: - marshalled["args"] = serializer.deserialize(marshalled["args"]) - marshalled["kwargs"] = serializer.deserialize(marshalled["kwargs"]) - return cls(**marshalled) - - -@attrs.define(kw_only=True) -class JobInfo: - job_id: UUID - task_id: str - schedule_id: str | None - scheduled_fire_time: datetime | None - jitter: timedelta - start_deadline: datetime | None - tags: frozenset[str] - - @classmethod - def from_job(cls, job: Job) -> JobInfo: - return cls( - job_id=job.id, - task_id=job.task_id, - schedule_id=job.schedule_id, - scheduled_fire_time=job.scheduled_fire_time, - jitter=job.jitter, - start_deadline=job.start_deadline, - tags=job.tags, - ) - - -@attrs.define(kw_only=True, frozen=True) -class JobResult: - job_id: UUID - outcome: JobOutcome = attrs.field( - eq=False, order=False, converter=as_enum(JobOutcome) - ) - finished_at: datetime = attrs.field( - eq=False, order=False, factory=partial(datetime.now, timezone.utc) - ) - exception: BaseException | None = attrs.field(eq=False, order=False, default=None) - return_value: Any = attrs.field(eq=False, order=False, default=None) - - def marshal(self, serializer: abc.Serializer) -> dict[str, Any]: - marshalled = attrs.asdict(self, value_serializer=serialize) - if self.outcome is JobOutcome.error: - marshalled["exception"] = serializer.serialize(self.exception) - else: - del marshalled["exception"] - - if self.outcome is JobOutcome.success: - marshalled["return_value"] = serializer.serialize(self.return_value) - else: - del marshalled["return_value"] - - return marshalled - - @classmethod - def unmarshal( - cls, serializer: abc.Serializer, marshalled: dict[str, Any] - ) -> JobResult: - if marshalled.get("exception"): - marshalled["exception"] = serializer.deserialize(marshalled["exception"]) - elif marshalled.get("return_value"): - marshalled["return_value"] = serializer.deserialize( - marshalled["return_value"] - ) - - return cls(**marshalled) - - -@attrs.define(kw_only=True, frozen=True) -class RetrySettings: - stop: tenacity.stop.stop_base = attrs.field( - validator=instance_of(tenacity.stop.stop_base), - default=tenacity.stop_after_delay(60), - ) - wait: tenacity.wait.wait_base = attrs.field( - validator=instance_of(tenacity.wait.wait_base), - default=tenacity.wait_exponential(min=0.5, max=20), - ) - - @classmethod - def fail_immediately(cls) -> RetrySettings: - return cls(stop=tenacity.stop_after_attempt(1)) diff --git a/src/apscheduler/workers/async_.py b/src/apscheduler/workers/async_.py index 601fc4e..ffd6e4d 100644 --- a/src/apscheduler/workers/async_.py +++ b/src/apscheduler/workers/async_.py @@ -22,12 +22,12 @@ from anyio.abc import CancelScope, TaskGroup from .._converters import as_async_datastore, as_async_eventbroker from .._enums import JobOutcome, RunState +from .._structures import Job, JobInfo, JobResult from .._validators import positive_integer -from ..abc import AsyncDataStore, AsyncEventBroker, Job +from ..abc import AsyncDataStore, AsyncEventBroker from ..context import current_worker, job_info from ..eventbrokers.async_local import LocalAsyncEventBroker from ..events import JobAdded, WorkerStarted, WorkerStopped -from ..structures import JobInfo, JobResult @attrs.define(eq=False) diff --git a/src/apscheduler/workers/sync.py b/src/apscheduler/workers/sync.py index 686cb26..61f23ad 100644 --- a/src/apscheduler/workers/sync.py +++ b/src/apscheduler/workers/sync.py @@ -16,12 +16,12 @@ from uuid import UUID import attrs from .._enums import JobOutcome, RunState +from .._structures import Job, JobInfo, JobResult from .._validators import positive_integer from ..abc import DataStore, EventBroker from ..context import current_worker, job_info from ..eventbrokers.local import LocalEventBroker from ..events import JobAdded, WorkerStarted, WorkerStopped -from ..structures import Job, JobInfo, JobResult @attrs.define(eq=False) diff --git a/tests/test_datastores.py b/tests/test_datastores.py index 3e23828..51e11b4 100644 --- a/tests/test_datastores.py +++ b/tests/test_datastores.py @@ -15,14 +15,8 @@ from freezegun.api import FrozenDateTimeFactory from pytest_lazyfixture import lazy_fixture from apscheduler import CoalescePolicy, ConflictPolicy, JobOutcome, TaskLookupError -from apscheduler.abc import ( - AsyncDataStore, - AsyncEventBroker, - DataStore, - EventBroker, - Job, - Schedule, -) +from apscheduler._structures import Job, JobResult, Schedule, Task +from apscheduler.abc import AsyncDataStore, AsyncEventBroker, DataStore, EventBroker from apscheduler.datastores.async_adapter import AsyncDataStoreAdapter from apscheduler.datastores.memory import MemoryDataStore from apscheduler.eventbrokers.async_local import LocalAsyncEventBroker @@ -35,7 +29,6 @@ from apscheduler.events import ( TaskAdded, TaskUpdated, ) -from apscheduler.structures import JobResult, Task from apscheduler.triggers.date import DateTrigger diff --git a/tests/test_schedulers.py b/tests/test_schedulers.py index b093e74..cd64b34 100644 --- a/tests/test_schedulers.py +++ b/tests/test_schedulers.py @@ -11,7 +11,14 @@ import pytest from anyio import fail_after from pytest_mock import MockerFixture -from apscheduler import JobLookupError, JobOutcome, ScheduleLookupError +from apscheduler import ( + Job, + JobLookupError, + JobOutcome, + Schedule, + ScheduleLookupError, + Task, +) from apscheduler.context import current_scheduler, current_worker, job_info from apscheduler.events import ( Event, @@ -23,7 +30,6 @@ from apscheduler.events import ( ) from apscheduler.schedulers.async_ import AsyncScheduler from apscheduler.schedulers.sync import Scheduler -from apscheduler.structures import Job, Schedule, Task from apscheduler.triggers.date import DateTrigger from apscheduler.triggers.interval import IntervalTrigger from apscheduler.workers.async_ import AsyncWorker diff --git a/tests/test_workers.py b/tests/test_workers.py index de9958c..7f86aca 100644 --- a/tests/test_workers.py +++ b/tests/test_workers.py @@ -8,8 +8,8 @@ import anyio import pytest from anyio import fail_after -from apscheduler import JobOutcome -from apscheduler.abc import Job +from apscheduler import Job, JobOutcome +from apscheduler._structures import Task from apscheduler.datastores.memory import MemoryDataStore from apscheduler.events import ( Event, @@ -19,7 +19,6 @@ from apscheduler.events import ( TaskAdded, WorkerStopped, ) -from apscheduler.structures import Task from apscheduler.workers.async_ import AsyncWorker from apscheduler.workers.sync import Worker -- cgit v1.2.1