asyncz 0.13.2__tar.gz → 0.13.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. {asyncz-0.13.2 → asyncz-0.13.4}/PKG-INFO +5 -6
  2. asyncz-0.13.4/asyncz/__init__.py +1 -0
  3. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/datastructures.py +2 -1
  4. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/executors/base.py +2 -1
  5. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/schedulers/asgi.py +2 -2
  6. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/schedulers/base.py +2 -2
  7. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/schedulers/types.py +2 -2
  8. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/schedulers/utils.py +2 -1
  9. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/stores/redis.py +8 -8
  10. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/tasks/base.py +2 -2
  11. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/tasks/types.py +2 -2
  12. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/triggers/cron/expressions.py +3 -3
  13. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/triggers/cron/trigger.py +2 -0
  14. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/triggers/interval.py +1 -0
  15. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/utils.py +2 -1
  16. {asyncz-0.13.2 → asyncz-0.13.4}/pyproject.toml +18 -8
  17. asyncz-0.13.2/asyncz/__init__.py +0 -1
  18. {asyncz-0.13.2 → asyncz-0.13.4}/.gitignore +0 -0
  19. {asyncz-0.13.2 → asyncz-0.13.4}/LICENSE +0 -0
  20. {asyncz-0.13.2 → asyncz-0.13.4}/README.md +0 -0
  21. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/enums.py +0 -0
  22. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/events/__init__.py +0 -0
  23. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/events/base.py +0 -0
  24. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/events/constants.py +0 -0
  25. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/exceptions.py +0 -0
  26. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/executors/__init__.py +0 -0
  27. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/executors/asyncio.py +0 -0
  28. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/executors/debug.py +0 -0
  29. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/executors/pool.py +0 -0
  30. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/executors/process_pool.py +0 -0
  31. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/executors/types.py +0 -0
  32. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/file_locking.py +0 -0
  33. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/locks.py +0 -0
  34. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/protocols.py +0 -0
  35. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/py.typed +0 -0
  36. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/schedulers/__init__.py +0 -0
  37. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/schedulers/asyncio.py +0 -0
  38. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/schedulers/datastructures.py +0 -0
  39. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/schedulers/defaults.py +0 -0
  40. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/state.py +0 -0
  41. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/stores/__init__.py +0 -0
  42. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/stores/base.py +0 -0
  43. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/stores/file.py +0 -0
  44. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/stores/memory.py +0 -0
  45. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/stores/mongo.py +0 -0
  46. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/stores/sqlalchemy.py +0 -0
  47. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/stores/types.py +0 -0
  48. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/tasks/__init__.py +0 -0
  49. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/triggers/__init__.py +0 -0
  50. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/triggers/base.py +0 -0
  51. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/triggers/combination.py +0 -0
  52. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/triggers/cron/__init__.py +0 -0
  53. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/triggers/cron/constants.py +0 -0
  54. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/triggers/cron/fields.py +0 -0
  55. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/triggers/cron/types.py +0 -0
  56. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/triggers/date.py +0 -0
  57. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/triggers/shutdown.py +0 -0
  58. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/triggers/types.py +0 -0
  59. {asyncz-0.13.2 → asyncz-0.13.4}/asyncz/typing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: asyncz
3
- Version: 0.13.2
3
+ Version: 0.13.4
4
4
  Summary: The scheduler that nobody wants but every application needs.
5
5
  Project-URL: Homepage, https://github.com/dymmond/asyncz
6
6
  Project-URL: Documentation, https://asyncz.dymmond.com/
@@ -22,8 +22,6 @@ Classifier: Operating System :: OS Independent
22
22
  Classifier: Programming Language :: Python
23
23
  Classifier: Programming Language :: Python :: 3
24
24
  Classifier: Programming Language :: Python :: 3 :: Only
25
- Classifier: Programming Language :: Python :: 3.8
26
- Classifier: Programming Language :: Python :: 3.9
27
25
  Classifier: Programming Language :: Python :: 3.10
28
26
  Classifier: Programming Language :: Python :: 3.11
29
27
  Classifier: Programming Language :: Python :: 3.12
@@ -36,7 +34,7 @@ Classifier: Topic :: Software Development :: Libraries
36
34
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
37
35
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
38
36
  Classifier: Typing :: Typed
39
- Requires-Python: >=3.9
37
+ Requires-Python: >=3.10
40
38
  Requires-Dist: cryptography
41
39
  Requires-Dist: pydantic<3.0.0,>=2.5.3
42
40
  Provides-Extra: localtime
@@ -45,17 +43,18 @@ Provides-Extra: loguru
45
43
  Requires-Dist: loguru<0.8.0,>=0.7.0; extra == 'loguru'
46
44
  Provides-Extra: testing
47
45
  Requires-Dist: esmerald>=3.7.5; extra == 'testing'
46
+ Requires-Dist: freezegun; extra == 'testing'
48
47
  Requires-Dist: httpx; extra == 'testing'
49
48
  Requires-Dist: lilya; extra == 'testing'
50
49
  Requires-Dist: loguru<0.8.0,>=0.7.0; extra == 'testing'
51
50
  Requires-Dist: mypy<2.0.0,>=0.982; extra == 'testing'
52
51
  Requires-Dist: pymongo<5.0.0,>=4.3.3; extra == 'testing'
53
- Requires-Dist: pytest-asyncio<1.0.0,>=0.23.0; extra == 'testing'
52
+ Requires-Dist: pytest-asyncio<2.0.0,>=1.0; extra == 'testing'
54
53
  Requires-Dist: pytest-cov<7.0.0,>=2.12.0; extra == 'testing'
55
54
  Requires-Dist: pytest-loguru<1,>=0.2.0; extra == 'testing'
56
55
  Requires-Dist: pytest<9.0.0,>=7.1.3; extra == 'testing'
57
56
  Requires-Dist: pytz>=2022.6; extra == 'testing'
58
- Requires-Dist: redis<6.0.0,>=4.4.0; extra == 'testing'
57
+ Requires-Dist: redis<7.0.0,>=4.4.0; extra == 'testing'
59
58
  Requires-Dist: sqlalchemy; extra == 'testing'
60
59
  Requires-Dist: starlette; extra == 'testing'
61
60
  Requires-Dist: tzlocal; extra == 'testing'
@@ -0,0 +1 @@
1
+ __version__ = "0.13.4"
@@ -1,5 +1,6 @@
1
+ from collections.abc import Callable
1
2
  from datetime import datetime, timedelta, tzinfo
2
- from typing import TYPE_CHECKING, Any, Callable, Optional, Union
3
+ from typing import TYPE_CHECKING, Any, Optional, Union
3
4
 
4
5
  from pydantic import BaseModel, ConfigDict
5
6
 
@@ -1,11 +1,12 @@
1
1
  import logging
2
2
  import sys
3
3
  import traceback
4
+ from collections.abc import Callable
4
5
  from datetime import datetime, timedelta
5
6
  from datetime import timezone as tz
6
7
  from threading import RLock
7
8
  from traceback import format_tb
8
- from typing import TYPE_CHECKING, Any, Callable, cast
9
+ from typing import TYPE_CHECKING, Any, cast
9
10
 
10
11
  from asyncz.events import TaskExecutionEvent
11
12
  from asyncz.events.constants import TASK_ERROR, TASK_EXECUTED, TASK_MISSED
@@ -1,10 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Awaitable
3
+ from collections.abc import Awaitable, Callable
4
4
  from contextlib import suppress
5
5
  from dataclasses import dataclass
6
6
  from inspect import isawaitable
7
- from typing import TYPE_CHECKING, Callable
7
+ from typing import TYPE_CHECKING
8
8
 
9
9
  from asyncz.typing import DictStrAny
10
10
 
@@ -8,12 +8,12 @@ import sys
8
8
  import warnings
9
9
  from abc import abstractmethod
10
10
  from collections import defaultdict
11
- from collections.abc import Mapping, Sequence
11
+ from collections.abc import Callable, Mapping, Sequence
12
12
  from datetime import datetime, timedelta
13
13
  from functools import partial
14
14
  from importlib import import_module
15
15
  from threading import TIMEOUT_MAX, Lock, RLock
16
- from typing import TYPE_CHECKING, Any, Callable, Optional, Union, cast, overload
16
+ from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload
17
17
 
18
18
  from asyncz.enums import PluginInstance, SchedulerState
19
19
  from asyncz.events.base import SchedulerEvent, TaskEvent, TaskSubmissionEvent
@@ -1,9 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from abc import ABC, abstractmethod
4
- from collections.abc import Awaitable
4
+ from collections.abc import Awaitable, Callable
5
5
  from inspect import isawaitable
6
- from typing import TYPE_CHECKING, Any, Callable, Optional, Union
6
+ from typing import TYPE_CHECKING, Any, Optional, Union
7
7
 
8
8
  from asyncz.events.constants import (
9
9
  ALL_EVENTS,
@@ -1,5 +1,6 @@
1
+ from collections.abc import Callable
1
2
  from functools import partial, wraps
2
- from typing import Any, Callable
3
+ from typing import Any
3
4
 
4
5
 
5
6
  def run_in_event_loop(fn: Callable[..., Any]) -> Any:
@@ -37,7 +37,7 @@ class RedisStore(BaseStore):
37
37
  database: int = 0,
38
38
  tasks_key: str = "asyncz.tasks",
39
39
  run_times_key: str = "asyncz.run_times",
40
- pickle_protocol: Optional[int] = pickle.HIGHEST_PROTOCOL,
40
+ pickle_protocol: int | None = pickle.HIGHEST_PROTOCOL,
41
41
  **kwargs: Any,
42
42
  ):
43
43
  super().__init__(**kwargs)
@@ -71,7 +71,7 @@ class RedisStore(BaseStore):
71
71
  if not ids:
72
72
  return []
73
73
  states: list[Any] = self.redis.hmget(self.tasks_key, ids) # type: ignore
74
- return self.rebuild_tasks(zip(ids, states))
74
+ return self.rebuild_tasks(zip(ids, states, strict=False))
75
75
 
76
76
  def rebuild_tasks(self, states: Iterable[tuple[str, Any]]) -> list["TaskType"]:
77
77
  tasks = []
@@ -90,11 +90,11 @@ class RedisStore(BaseStore):
90
90
  with self.redis.pipeline() as pipe:
91
91
  pipe.hdel(self.tasks_key, *failed_task_ids)
92
92
  pipe.zrem(self.run_times_key, *failed_task_ids)
93
- pipe.execute() # type: ignore
93
+ pipe.execute()
94
94
 
95
95
  return tasks
96
96
 
97
- def get_next_run_time(self) -> Optional[datetime]:
97
+ def get_next_run_time(self) -> datetime | None:
98
98
  next_run_time: Any = self.redis.zrange(self.run_times_key, 0, 0, withscores=True)
99
99
  if next_run_time:
100
100
  return utc_timestamp_to_datetime(cast(float, next_run_time[0][1]))
@@ -124,7 +124,7 @@ class RedisStore(BaseStore):
124
124
  self.run_times_key,
125
125
  {task.id: datetime_to_utc_timestamp(task.next_run_time)},
126
126
  )
127
- pipe.execute() # type: ignore
127
+ pipe.execute()
128
128
 
129
129
  def update_task(self, task: "TaskType") -> None:
130
130
  assert task.id
@@ -145,7 +145,7 @@ class RedisStore(BaseStore):
145
145
  else:
146
146
  pipe.zrem(self.run_times_key, task.id)
147
147
 
148
- pipe.execute() # type: ignore
148
+ pipe.execute()
149
149
 
150
150
  def delete_task(self, task_id: str) -> None:
151
151
  if not self.redis.hexists(self.tasks_key, task_id):
@@ -154,13 +154,13 @@ class RedisStore(BaseStore):
154
154
  with self.redis.pipeline() as pipe:
155
155
  pipe.hdel(self.tasks_key, task_id)
156
156
  pipe.zrem(self.run_times_key, task_id)
157
- pipe.execute() # type: ignore
157
+ pipe.execute()
158
158
 
159
159
  def remove_all_tasks(self) -> None:
160
160
  with self.redis.pipeline() as pipe:
161
161
  pipe.delete(self.tasks_key)
162
162
  pipe.delete(self.run_times_key)
163
- pipe.execute() # type: ignore
163
+ pipe.execute()
164
164
 
165
165
  def shutdown(self) -> None:
166
166
  self.redis.connection_pool.disconnect()
@@ -1,7 +1,7 @@
1
1
  import inspect
2
- from collections.abc import Iterable, Mapping, Sequence
2
+ from collections.abc import Callable, Iterable, Mapping, Sequence
3
3
  from datetime import datetime, tzinfo
4
- from typing import Any, Callable, Optional, Union, cast
4
+ from typing import Any, Optional, Union, cast
5
5
  from uuid import uuid4
6
6
 
7
7
  from pydantic import Field
@@ -1,9 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from abc import ABC, abstractmethod
4
- from collections.abc import Sequence
4
+ from collections.abc import Callable, Sequence
5
5
  from datetime import datetime, tzinfo
6
- from typing import Any, Callable, Optional, TypeVar
6
+ from typing import Any, Optional, TypeVar
7
7
 
8
8
  from asyncz.schedulers.types import SchedulerType
9
9
  from asyncz.triggers.types import TriggerType
@@ -54,7 +54,7 @@ class AllExpression(BaseExpression):
54
54
 
55
55
  def __str__(self) -> str:
56
56
  if self.step:
57
- return "*/%d" % self.step
57
+ return f"*/{self.step}"
58
58
  return "*"
59
59
 
60
60
  def __repr__(self) -> str:
@@ -131,12 +131,12 @@ class RangeExpression(AllExpression):
131
131
 
132
132
  def __str__(self) -> str:
133
133
  if self.last != self.first and self.last is not None:
134
- range = "%d-%d" % (self.first, self.last)
134
+ range = f"{self.first}-{self.last}"
135
135
  else:
136
136
  range = str(self.first)
137
137
 
138
138
  if self.step:
139
- return "%s/%d" % (range, self.step)
139
+ return f"{range}/{self.step}"
140
140
  return range
141
141
 
142
142
  def __repr__(self) -> str:
@@ -223,6 +223,7 @@ class CronTrigger(BaseTrigger):
223
223
  def get_next_trigger_time(
224
224
  self, timezone: tzinfo, previous_time: Optional[datetime], now: Optional[datetime] = None
225
225
  ) -> Union[datetime, None]:
226
+ timezone = self.timezone or timezone
226
227
  if now is None:
227
228
  now = datetime.now(timezone)
228
229
  start_at_field = (
@@ -246,6 +247,7 @@ class CronTrigger(BaseTrigger):
246
247
 
247
248
  fieldnum = 0
248
249
  next_date = datetime_ceil(start_at)
250
+
249
251
  while 0 <= fieldnum < len(self.fields):
250
252
  field = self.fields[fieldnum]
251
253
  curr_value = field.get_value(next_date)
@@ -68,6 +68,7 @@ class IntervalTrigger(BaseTrigger):
68
68
  previous_time: Optional[datetime],
69
69
  now: Union[datetime, None] = None,
70
70
  ) -> Union[datetime, None]:
71
+ timezone = self.timezone or timezone
71
72
  if now is None:
72
73
  now = datetime.now(timezone)
73
74
  next_trigger_time: Optional[datetime]
@@ -1,9 +1,10 @@
1
1
  import inspect
2
2
  import re
3
+ from collections.abc import Callable
3
4
  from datetime import date, datetime, time, timedelta, tzinfo
4
5
  from datetime import timezone as dttz
5
6
  from functools import partial
6
- from typing import Any, Callable, Optional, Union, cast, overload
7
+ from typing import Any, Optional, Union, cast, overload
7
8
 
8
9
  from asyncz.exceptions import AsynczException, AsynczLookupError
9
10
 
@@ -7,7 +7,7 @@ name = "asyncz"
7
7
  description = "The scheduler that nobody wants but every application needs."
8
8
  long_description = "The scheduler that nobody wants but every application needs."
9
9
  readme = "README.md"
10
- requires-python = ">=3.9"
10
+ requires-python = ">=3.10"
11
11
  dynamic = ['version']
12
12
  authors = [{ name = "Tiago Silva", email = "tiago.arasilva@gmail.com" }]
13
13
  classifiers = [
@@ -29,8 +29,6 @@ classifiers = [
29
29
  "Intended Audience :: Developers",
30
30
  "License :: OSI Approved :: BSD License",
31
31
  "Programming Language :: Python :: 3 :: Only",
32
- "Programming Language :: Python :: 3.8",
33
- "Programming Language :: Python :: 3.9",
34
32
  "Programming Language :: Python :: 3.10",
35
33
  "Programming Language :: Python :: 3.11",
36
34
  "Programming Language :: Python :: 3.12",
@@ -73,9 +71,9 @@ testing = [
73
71
  "pymongo>=4.3.3,<5.0.0",
74
72
  "pytest>=7.1.3,<9.0.0",
75
73
  "pytest-cov >=2.12.0,<7.0.0",
76
- "pytest-asyncio >=0.23.0,<1.0.0",
74
+ "pytest-asyncio >=1.0,<2.0.0",
77
75
  "pytest-loguru>=0.2.0,<1",
78
- "redis>=4.4.0,<6.0.0",
76
+ "redis>=4.4.0,<7.0.0",
79
77
  "mypy>=0.982,<2.0.0",
80
78
  "esmerald>=3.7.5",
81
79
  "starlette",
@@ -83,6 +81,7 @@ testing = [
83
81
  "sqlalchemy",
84
82
  "httpx",
85
83
  "pytz>=2022.6",
84
+ "freezegun"
86
85
  ]
87
86
 
88
87
  [tool.hatch.envs.default.scripts]
@@ -124,6 +123,12 @@ dependencies = [
124
123
  build = "mkdocs build"
125
124
  serve = "mkdocs serve --dev-addr localhost:8000"
126
125
 
126
+ [tool.hatch.envs.hatch-static-analysis]
127
+ # disables custom ruff rules, required to align with pre-commit
128
+ config-path = "none"
129
+ dependencies = ["ruff==0.12.5"]
130
+
131
+
127
132
  [tool.hatch.version]
128
133
  path = "asyncz/__init__.py"
129
134
 
@@ -140,7 +145,7 @@ disallow_any_generics = false
140
145
  implicit_reexport = false
141
146
  show_error_codes = true
142
147
  disallow_incomplete_defs = true
143
- disable_error_code = "attr-defined"
148
+ disable_error_code = "attr-defined,no-untyped-call"
144
149
  warn_unused_ignores = true
145
150
  warn_redundant_casts = true
146
151
 
@@ -148,8 +153,8 @@ warn_redundant_casts = true
148
153
  line-length=99
149
154
 
150
155
  [tool.ruff.lint]
151
- select = ["E", "W", "F", "C", "B", "I", "UP", "SIM"]
152
- ignore = ["E501", "B008", "C901", "B026"]
156
+ select = ["E", "W", "F", "C", "B", "I", "UP", "SIM", "FA"]
157
+ ignore = ["E501", "B008", "C901", "B026", "UP006", "UP038", "UP045", "UP007"]
153
158
 
154
159
  exclude = ["docs_src/*", ".pdbrc"]
155
160
 
@@ -187,6 +192,11 @@ module = [
187
192
  ignore_missing_imports = true
188
193
  ignore_errors = true
189
194
 
195
+ [[tool.mypy.overrides]]
196
+ module = "tests.*"
197
+ ignore_errors = true
198
+
199
+
190
200
  [tool.pytest.ini_options]
191
201
  addopts = ["--strict-config", "--strict-markers"]
192
202
  xfail_strict = true
@@ -1 +0,0 @@
1
- __version__ = "0.13.2"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes