tickforge 0.1.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 tickforge contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,271 @@
1
+ Metadata-Version: 2.4
2
+ Name: tickforge
3
+ Version: 0.1.0
4
+ Summary: An advanced task scheduler with persistence, retries, cron/interval/date triggers and native async support.
5
+ Author: tickforge contributors
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 tickforge contributors
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ Project-URL: Homepage, https://github.com/scheduleforge/tickforge
28
+ Project-URL: Repository, https://github.com/scheduleforge/tickforge
29
+ Project-URL: Issues, https://github.com/scheduleforge/tickforge/issues
30
+ Keywords: scheduler,cron,async,asyncio,jobs,tasks,persistence
31
+ Classifier: Development Status :: 4 - Beta
32
+ Classifier: Intended Audience :: Developers
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Operating System :: OS Independent
35
+ Classifier: Programming Language :: Python :: 3
36
+ Classifier: Programming Language :: Python :: 3.8
37
+ Classifier: Programming Language :: Python :: 3.9
38
+ Classifier: Programming Language :: Python :: 3.10
39
+ Classifier: Programming Language :: Python :: 3.11
40
+ Classifier: Programming Language :: Python :: 3.12
41
+ Classifier: Topic :: System :: Systems Administration
42
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
43
+ Classifier: Typing :: Typed
44
+ Requires-Python: >=3.8
45
+ Description-Content-Type: text/markdown
46
+ License-File: LICENSE
47
+ Requires-Dist: click>=8.0
48
+ Requires-Dist: python-dateutil>=2.8.2
49
+ Provides-Extra: dev
50
+ Requires-Dist: pytest>=7.0; extra == "dev"
51
+ Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
52
+ Requires-Dist: black>=23.0; extra == "dev"
53
+ Requires-Dist: ruff>=0.1; extra == "dev"
54
+ Requires-Dist: mypy>=1.0; extra == "dev"
55
+ Requires-Dist: build>=1.0; extra == "dev"
56
+ Dynamic: license-file
57
+
58
+ # tickforge
59
+
60
+ An advanced task scheduler for Python with **persistence**, **native async support**,
61
+ retries, timeouts, misfire handling and a batteries-included CLI.
62
+
63
+ [![Python](https://img.shields.io/badge/python-3.8%2B-blue)](https://www.python.org/)
64
+ [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
65
+
66
+ ## Features
67
+
68
+ - **Three trigger types** — `IntervalTrigger`, `CronTrigger` (with timezone support), `DateTrigger`
69
+ - **Durable jobs** — SQLite, JSON file, or in-memory stores behind one interface
70
+ - **Async first** — `async def` jobs are awaited; sync jobs run in a thread pool
71
+ - **Reliability** — per-job retries, retry backoff delay, execution timeouts, misfire grace windows
72
+ - **Concurrency control** — global semaphore plus per-job overlap protection
73
+ - **Run history** — every execution recorded with duration, attempts, result and traceback
74
+ - **Event hooks** — subscribe to job and scheduler lifecycle events
75
+ - **Structured logging** — human-readable or JSON, with job context on every record
76
+ - **CLI** — register, inspect, preview, run and serve jobs without writing a driver script
77
+
78
+ ## Installation
79
+
80
+ ```bash
81
+ pip install tickforge
82
+ ```
83
+
84
+ From source:
85
+
86
+ ```bash
87
+ git clone https://github.com/example/tickforge
88
+ cd tickforge
89
+ pip install -e ".[dev]"
90
+ ```
91
+
92
+ Requires Python 3.8 or newer. Dependencies: `click`, `python-dateutil`.
93
+
94
+ ## Quick start
95
+
96
+ ### Async
97
+
98
+ ```python
99
+ import asyncio
100
+ from tickforge import AsyncScheduler, CronTrigger, IntervalTrigger, SQLiteJobStore
101
+
102
+ async def heartbeat():
103
+ print("alive")
104
+
105
+ def collect_metrics(source: str):
106
+ print("collecting from", source)
107
+
108
+ async def main():
109
+ scheduler = AsyncScheduler(store=SQLiteJobStore("jobs.db"))
110
+ await scheduler.add_job(heartbeat, IntervalTrigger(seconds=30), name="heartbeat")
111
+ await scheduler.add_job(
112
+ collect_metrics,
113
+ CronTrigger.from_string("*/5 * * * *", timezone="Europe/Paris"),
114
+ args=["edge-01"],
115
+ max_retries=3,
116
+ retry_delay=10,
117
+ timeout=60,
118
+ name="metrics",
119
+ )
120
+ await scheduler.run_forever()
121
+
122
+ asyncio.run(main())
123
+ ```
124
+
125
+ ### Synchronous
126
+
127
+ ```python
128
+ from tickforge import Scheduler, IntervalTrigger, MemoryJobStore
129
+
130
+ def report():
131
+ print("report generated")
132
+
133
+ with Scheduler(store=MemoryJobStore()) as scheduler:
134
+ scheduler.add_job(report, IntervalTrigger(minutes=15), name="report")
135
+ input("press enter to stop\n")
136
+ ```
137
+
138
+ ## Triggers
139
+
140
+ | Trigger | Purpose | Example |
141
+ | --- | --- | --- |
142
+ | `IntervalTrigger` | Fixed period, optional jitter and window | `IntervalTrigger(hours=2, jitter=30)` |
143
+ | `CronTrigger` | Calendar schedules, timezone aware | `CronTrigger(minute="0", hour="9", day_of_week="mon-fri")` |
144
+ | `DateTrigger` | One-shot execution | `DateTrigger(run_at="2026-01-01T00:00:00Z")` |
145
+
146
+ Cron fields are `minute hour day month day_of_week`, supporting `*`, `a-b`, `a,b`,
147
+ `*/n`, `a-b/n`, month and weekday names, and the macros `@hourly`, `@daily`,
148
+ `@weekly`, `@monthly`, `@yearly`.
149
+
150
+ **`day_of_week` uses Python semantics: `0` is Monday through `6` is Sunday.**
151
+ Names (`mon`, `fri`) and the legacy `7` for Sunday are also accepted. When both
152
+ `day` and `day_of_week` are restricted, classic cron OR semantics apply.
153
+
154
+ ## Stores
155
+
156
+ ```python
157
+ from tickforge import MemoryJobStore, JSONFileJobStore, SQLiteJobStore, create_store
158
+
159
+ MemoryJobStore() # volatile, ideal for tests
160
+ JSONFileJobStore("jobs.json") # human-readable, atomic writes
161
+ SQLiteJobStore("jobs.db") # durable, WAL, safe across threads and processes
162
+
163
+ create_store("sqlite:///var/lib/tickforge/jobs.db")
164
+ create_store("json:///tmp/jobs.json")
165
+ create_store("memory://")
166
+ ```
167
+
168
+ Because jobs are persisted as `module:callable` references, the target must be
169
+ importable from the process running the scheduler. Lambdas and locally defined
170
+ functions are rejected at registration time.
171
+
172
+ ## Reliability options
173
+
174
+ ```python
175
+ await scheduler.add_job(
176
+ flaky_task,
177
+ IntervalTrigger(minutes=5),
178
+ max_retries=3, # four attempts total
179
+ retry_delay=10, # seconds between attempts
180
+ timeout=120, # abort a single attempt after two minutes
181
+ misfire_grace_time=300, # drop slots older than five minutes
182
+ coalesce=True, # collapse a missed backlog into one run
183
+ allow_concurrent=False, # skip a slot if the previous run is still going
184
+ )
185
+ ```
186
+
187
+ ## Events
188
+
189
+ ```python
190
+ from tickforge import EventType
191
+
192
+ def on_error(event):
193
+ print("job failed:", event.job.name, event.run.error)
194
+
195
+ scheduler.add_listener(on_error, EventType.JOB_ERROR)
196
+ scheduler.add_listener(lambda e: print(e.to_dict())) # all events
197
+ ```
198
+
199
+ Available types: `SCHEDULER_STARTED`, `SCHEDULER_STOPPED`, `SCHEDULER_PAUSED`,
200
+ `SCHEDULER_RESUMED`, `JOB_ADDED`, `JOB_REMOVED`, `JOB_MODIFIED`, `JOB_SUBMITTED`,
201
+ `JOB_EXECUTED`, `JOB_ERROR`, `JOB_RETRY`, `JOB_MISSED`, `JOB_SKIPPED`, `JOB_FINISHED`.
202
+
203
+ ## Logging
204
+
205
+ ```python
206
+ from tickforge import configure_logging
207
+
208
+ configure_logging(level="DEBUG", fmt="json", log_file="/var/log/tickforge.log")
209
+ ```
210
+
211
+ Records emitted during a run carry `job_id`, `run_id` and `job_name` automatically.
212
+
213
+ ## CLI
214
+
215
+ ```bash
216
+ # register jobs
217
+ tickforge add myapp.tasks:cleanup --interval 1h --name nightly-cleanup
218
+ tickforge add myapp.tasks:report --cron "0 9 * * mon-fri" --timezone Europe/Paris
219
+ tickforge add myapp.tasks:ping --at "2026-06-01 12:00" --retries 2 --timeout 30
220
+
221
+ # inspect
222
+ tickforge list
223
+ tickforge show nightly-cleanup
224
+ tickforge next nightly-cleanup --count 10
225
+ tickforge history --limit 20
226
+
227
+ # control
228
+ tickforge pause nightly-cleanup
229
+ tickforge resume nightly-cleanup
230
+ tickforge run-now nightly-cleanup
231
+ tickforge remove nightly-cleanup --yes
232
+
233
+ # serve
234
+ tickforge start --poll 1 --concurrency 20
235
+ ```
236
+
237
+ Global options: `--db` (path or store URI, also read from `TICKFORGE_DB`),
238
+ `-v/-vv`, `-q`, `--log-format text|json`, `--log-file`.
239
+
240
+ The default store is `~/.tickforge/jobs.db`.
241
+
242
+ ## Running as a service
243
+
244
+ ```ini
245
+ [Unit]
246
+ Description=tickforge scheduler
247
+ After=network.target
248
+
249
+ [Service]
250
+ Environment=TICKFORGE_DB=/var/lib/tickforge/jobs.db
251
+ ExecStart=/usr/local/bin/tickforge --log-format json start
252
+ Restart=always
253
+ User=tickforge
254
+
255
+ [Install]
256
+ WantedBy=multi-user.target
257
+ ```
258
+
259
+ ## Development
260
+
261
+ ```bash
262
+ pip install -e ".[dev]"
263
+ pytest
264
+ ruff check src
265
+ black src
266
+ mypy src
267
+ ```
268
+
269
+ ## License
270
+
271
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,214 @@
1
+ # tickforge
2
+
3
+ An advanced task scheduler for Python with **persistence**, **native async support**,
4
+ retries, timeouts, misfire handling and a batteries-included CLI.
5
+
6
+ [![Python](https://img.shields.io/badge/python-3.8%2B-blue)](https://www.python.org/)
7
+ [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
8
+
9
+ ## Features
10
+
11
+ - **Three trigger types** — `IntervalTrigger`, `CronTrigger` (with timezone support), `DateTrigger`
12
+ - **Durable jobs** — SQLite, JSON file, or in-memory stores behind one interface
13
+ - **Async first** — `async def` jobs are awaited; sync jobs run in a thread pool
14
+ - **Reliability** — per-job retries, retry backoff delay, execution timeouts, misfire grace windows
15
+ - **Concurrency control** — global semaphore plus per-job overlap protection
16
+ - **Run history** — every execution recorded with duration, attempts, result and traceback
17
+ - **Event hooks** — subscribe to job and scheduler lifecycle events
18
+ - **Structured logging** — human-readable or JSON, with job context on every record
19
+ - **CLI** — register, inspect, preview, run and serve jobs without writing a driver script
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ pip install tickforge
25
+ ```
26
+
27
+ From source:
28
+
29
+ ```bash
30
+ git clone https://github.com/example/tickforge
31
+ cd tickforge
32
+ pip install -e ".[dev]"
33
+ ```
34
+
35
+ Requires Python 3.8 or newer. Dependencies: `click`, `python-dateutil`.
36
+
37
+ ## Quick start
38
+
39
+ ### Async
40
+
41
+ ```python
42
+ import asyncio
43
+ from tickforge import AsyncScheduler, CronTrigger, IntervalTrigger, SQLiteJobStore
44
+
45
+ async def heartbeat():
46
+ print("alive")
47
+
48
+ def collect_metrics(source: str):
49
+ print("collecting from", source)
50
+
51
+ async def main():
52
+ scheduler = AsyncScheduler(store=SQLiteJobStore("jobs.db"))
53
+ await scheduler.add_job(heartbeat, IntervalTrigger(seconds=30), name="heartbeat")
54
+ await scheduler.add_job(
55
+ collect_metrics,
56
+ CronTrigger.from_string("*/5 * * * *", timezone="Europe/Paris"),
57
+ args=["edge-01"],
58
+ max_retries=3,
59
+ retry_delay=10,
60
+ timeout=60,
61
+ name="metrics",
62
+ )
63
+ await scheduler.run_forever()
64
+
65
+ asyncio.run(main())
66
+ ```
67
+
68
+ ### Synchronous
69
+
70
+ ```python
71
+ from tickforge import Scheduler, IntervalTrigger, MemoryJobStore
72
+
73
+ def report():
74
+ print("report generated")
75
+
76
+ with Scheduler(store=MemoryJobStore()) as scheduler:
77
+ scheduler.add_job(report, IntervalTrigger(minutes=15), name="report")
78
+ input("press enter to stop\n")
79
+ ```
80
+
81
+ ## Triggers
82
+
83
+ | Trigger | Purpose | Example |
84
+ | --- | --- | --- |
85
+ | `IntervalTrigger` | Fixed period, optional jitter and window | `IntervalTrigger(hours=2, jitter=30)` |
86
+ | `CronTrigger` | Calendar schedules, timezone aware | `CronTrigger(minute="0", hour="9", day_of_week="mon-fri")` |
87
+ | `DateTrigger` | One-shot execution | `DateTrigger(run_at="2026-01-01T00:00:00Z")` |
88
+
89
+ Cron fields are `minute hour day month day_of_week`, supporting `*`, `a-b`, `a,b`,
90
+ `*/n`, `a-b/n`, month and weekday names, and the macros `@hourly`, `@daily`,
91
+ `@weekly`, `@monthly`, `@yearly`.
92
+
93
+ **`day_of_week` uses Python semantics: `0` is Monday through `6` is Sunday.**
94
+ Names (`mon`, `fri`) and the legacy `7` for Sunday are also accepted. When both
95
+ `day` and `day_of_week` are restricted, classic cron OR semantics apply.
96
+
97
+ ## Stores
98
+
99
+ ```python
100
+ from tickforge import MemoryJobStore, JSONFileJobStore, SQLiteJobStore, create_store
101
+
102
+ MemoryJobStore() # volatile, ideal for tests
103
+ JSONFileJobStore("jobs.json") # human-readable, atomic writes
104
+ SQLiteJobStore("jobs.db") # durable, WAL, safe across threads and processes
105
+
106
+ create_store("sqlite:///var/lib/tickforge/jobs.db")
107
+ create_store("json:///tmp/jobs.json")
108
+ create_store("memory://")
109
+ ```
110
+
111
+ Because jobs are persisted as `module:callable` references, the target must be
112
+ importable from the process running the scheduler. Lambdas and locally defined
113
+ functions are rejected at registration time.
114
+
115
+ ## Reliability options
116
+
117
+ ```python
118
+ await scheduler.add_job(
119
+ flaky_task,
120
+ IntervalTrigger(minutes=5),
121
+ max_retries=3, # four attempts total
122
+ retry_delay=10, # seconds between attempts
123
+ timeout=120, # abort a single attempt after two minutes
124
+ misfire_grace_time=300, # drop slots older than five minutes
125
+ coalesce=True, # collapse a missed backlog into one run
126
+ allow_concurrent=False, # skip a slot if the previous run is still going
127
+ )
128
+ ```
129
+
130
+ ## Events
131
+
132
+ ```python
133
+ from tickforge import EventType
134
+
135
+ def on_error(event):
136
+ print("job failed:", event.job.name, event.run.error)
137
+
138
+ scheduler.add_listener(on_error, EventType.JOB_ERROR)
139
+ scheduler.add_listener(lambda e: print(e.to_dict())) # all events
140
+ ```
141
+
142
+ Available types: `SCHEDULER_STARTED`, `SCHEDULER_STOPPED`, `SCHEDULER_PAUSED`,
143
+ `SCHEDULER_RESUMED`, `JOB_ADDED`, `JOB_REMOVED`, `JOB_MODIFIED`, `JOB_SUBMITTED`,
144
+ `JOB_EXECUTED`, `JOB_ERROR`, `JOB_RETRY`, `JOB_MISSED`, `JOB_SKIPPED`, `JOB_FINISHED`.
145
+
146
+ ## Logging
147
+
148
+ ```python
149
+ from tickforge import configure_logging
150
+
151
+ configure_logging(level="DEBUG", fmt="json", log_file="/var/log/tickforge.log")
152
+ ```
153
+
154
+ Records emitted during a run carry `job_id`, `run_id` and `job_name` automatically.
155
+
156
+ ## CLI
157
+
158
+ ```bash
159
+ # register jobs
160
+ tickforge add myapp.tasks:cleanup --interval 1h --name nightly-cleanup
161
+ tickforge add myapp.tasks:report --cron "0 9 * * mon-fri" --timezone Europe/Paris
162
+ tickforge add myapp.tasks:ping --at "2026-06-01 12:00" --retries 2 --timeout 30
163
+
164
+ # inspect
165
+ tickforge list
166
+ tickforge show nightly-cleanup
167
+ tickforge next nightly-cleanup --count 10
168
+ tickforge history --limit 20
169
+
170
+ # control
171
+ tickforge pause nightly-cleanup
172
+ tickforge resume nightly-cleanup
173
+ tickforge run-now nightly-cleanup
174
+ tickforge remove nightly-cleanup --yes
175
+
176
+ # serve
177
+ tickforge start --poll 1 --concurrency 20
178
+ ```
179
+
180
+ Global options: `--db` (path or store URI, also read from `TICKFORGE_DB`),
181
+ `-v/-vv`, `-q`, `--log-format text|json`, `--log-file`.
182
+
183
+ The default store is `~/.tickforge/jobs.db`.
184
+
185
+ ## Running as a service
186
+
187
+ ```ini
188
+ [Unit]
189
+ Description=tickforge scheduler
190
+ After=network.target
191
+
192
+ [Service]
193
+ Environment=TICKFORGE_DB=/var/lib/tickforge/jobs.db
194
+ ExecStart=/usr/local/bin/tickforge --log-format json start
195
+ Restart=always
196
+ User=tickforge
197
+
198
+ [Install]
199
+ WantedBy=multi-user.target
200
+ ```
201
+
202
+ ## Development
203
+
204
+ ```bash
205
+ pip install -e ".[dev]"
206
+ pytest
207
+ ruff check src
208
+ black src
209
+ mypy src
210
+ ```
211
+
212
+ ## License
213
+
214
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,73 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "tickforge"
7
+ version = "0.1.0"
8
+ description = "An advanced task scheduler with persistence, retries, cron/interval/date triggers and native async support."
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = { file = "LICENSE" }
12
+ authors = [{ name = "tickforge contributors" }]
13
+ keywords = ["scheduler", "cron", "async", "asyncio", "jobs", "tasks", "persistence"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Operating System :: OS Independent",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.8",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Topic :: System :: Systems Administration",
26
+ "Topic :: Software Development :: Libraries :: Python Modules",
27
+ "Typing :: Typed",
28
+ ]
29
+ dependencies = [
30
+ "click>=8.0",
31
+ "python-dateutil>=2.8.2",
32
+ ]
33
+
34
+ [project.optional-dependencies]
35
+ dev = [
36
+ "pytest>=7.0",
37
+ "pytest-asyncio>=0.21",
38
+ "black>=23.0",
39
+ "ruff>=0.1",
40
+ "mypy>=1.0",
41
+ "build>=1.0",
42
+ ]
43
+
44
+ [project.urls]
45
+ Homepage = "https://github.com/scheduleforge/tickforge"
46
+ Repository = "https://github.com/scheduleforge/tickforge"
47
+ Issues = "https://github.com/scheduleforge/tickforge/issues"
48
+
49
+ [project.scripts]
50
+ tickforge = "tickforge.cli:main"
51
+
52
+ [tool.setuptools.packages.find]
53
+ where = ["src"]
54
+
55
+ [tool.setuptools.package-data]
56
+ tickforge = ["py.typed"]
57
+
58
+ [tool.black]
59
+ line-length = 100
60
+ target-version = ["py38"]
61
+
62
+ [tool.ruff]
63
+ line-length = 100
64
+ target-version = "py38"
65
+
66
+ [tool.mypy]
67
+ python_version = "3.8"
68
+ warn_unused_ignores = true
69
+ ignore_missing_imports = true
70
+
71
+ [tool.pytest.ini_options]
72
+ testpaths = ["tests"]
73
+ asyncio_mode = "auto"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,107 @@
1
+ """tickforge: an advanced task scheduler with persistence and async support.
2
+
3
+ Quick start
4
+ -----------
5
+ import asyncio
6
+ from tickforge import AsyncScheduler, IntervalTrigger, SQLiteJobStore
7
+
8
+ async def ping():
9
+ print("pong")
10
+
11
+ async def main():
12
+ scheduler = AsyncScheduler(store=SQLiteJobStore("jobs.db"))
13
+ await scheduler.add_job(ping, IntervalTrigger(seconds=5), name="ping")
14
+ await scheduler.start()
15
+ await scheduler.wait_closed()
16
+
17
+ asyncio.run(main())
18
+ """
19
+
20
+ from .core import (
21
+ ConfigurationError,
22
+ CronTrigger,
23
+ DateTrigger,
24
+ IntervalTrigger,
25
+ Job,
26
+ JobExecutionError,
27
+ JobLookupError,
28
+ JobResult,
29
+ JobRun,
30
+ JobStatus,
31
+ SchedulePlusError,
32
+ SerializationError,
33
+ Trigger,
34
+ TriggerError,
35
+ build_trigger,
36
+ callable_ref,
37
+ coerce_datetime,
38
+ coerce_timezone,
39
+ resolve_callable,
40
+ trigger_from_dict,
41
+ utcnow,
42
+ )
43
+ from .logging import (
44
+ JSONFormatter,
45
+ TextFormatter,
46
+ configure_logging,
47
+ get_logger,
48
+ job_context,
49
+ )
50
+ from .persistence import (
51
+ JobStore,
52
+ JSONFileJobStore,
53
+ MemoryJobStore,
54
+ SQLiteJobStore,
55
+ create_store,
56
+ )
57
+ from .scheduler import (
58
+ AsyncScheduler,
59
+ EventType,
60
+ Scheduler,
61
+ SchedulerConfig,
62
+ SchedulerEvent,
63
+ SchedulerState,
64
+ )
65
+
66
+ __version__ = "0.1.0"
67
+
68
+ __all__ = [
69
+ "__version__",
70
+ "SchedulePlusError",
71
+ "TriggerError",
72
+ "JobLookupError",
73
+ "JobExecutionError",
74
+ "SerializationError",
75
+ "ConfigurationError",
76
+ "Trigger",
77
+ "DateTrigger",
78
+ "IntervalTrigger",
79
+ "CronTrigger",
80
+ "Job",
81
+ "JobRun",
82
+ "JobResult",
83
+ "JobStatus",
84
+ "build_trigger",
85
+ "trigger_from_dict",
86
+ "resolve_callable",
87
+ "callable_ref",
88
+ "coerce_datetime",
89
+ "coerce_timezone",
90
+ "utcnow",
91
+ "JobStore",
92
+ "MemoryJobStore",
93
+ "SQLiteJobStore",
94
+ "JSONFileJobStore",
95
+ "create_store",
96
+ "AsyncScheduler",
97
+ "Scheduler",
98
+ "SchedulerConfig",
99
+ "SchedulerState",
100
+ "SchedulerEvent",
101
+ "EventType",
102
+ "configure_logging",
103
+ "get_logger",
104
+ "job_context",
105
+ "JSONFormatter",
106
+ "TextFormatter",
107
+ ]