newcronixPy 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.
- newcronixpy-0.1.0/LICENSE +0 -0
- newcronixpy-0.1.0/PKG-INFO +17 -0
- newcronixpy-0.1.0/README.md +5 -0
- newcronixpy-0.1.0/newcronixPy/__init__.py +4 -0
- newcronixpy-0.1.0/newcronixPy/builder.py +76 -0
- newcronixpy-0.1.0/newcronixPy/core.py +51 -0
- newcronixpy-0.1.0/newcronixPy/executor.py +13 -0
- newcronixpy-0.1.0/newcronixPy/tasks.py +70 -0
- newcronixpy-0.1.0/newcronixPy/utils.py +5 -0
- newcronixpy-0.1.0/newcronixPy.egg-info/PKG-INFO +17 -0
- newcronixpy-0.1.0/newcronixPy.egg-info/SOURCES.txt +14 -0
- newcronixpy-0.1.0/newcronixPy.egg-info/dependency_links.txt +1 -0
- newcronixpy-0.1.0/newcronixPy.egg-info/top_level.txt +1 -0
- newcronixpy-0.1.0/pyproject.toml +19 -0
- newcronixpy-0.1.0/setup.cfg +4 -0
- newcronixpy-0.1.0/tests/test_scheduler.py +1 -0
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: newcronixPy
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Simple and flexible task scheduler
|
|
5
|
+
Author-email: Kirill Zimin <ki822979@gmail.com>
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Requires-Python: >=3.8
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Dynamic: license-file
|
|
12
|
+
|
|
13
|
+
# newcronixPy
|
|
14
|
+
|
|
15
|
+
Simple Python task scheduler.
|
|
16
|
+
|
|
17
|
+
## Look for examples folder for examples
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from .tasks import IntervalTask, DailyTask, WeeklyTask, OneTimeTask
|
|
3
|
+
from .core import add_task
|
|
4
|
+
from .utils import parse_time
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TaskBuilder:
|
|
8
|
+
def __init__(self, mode, value=None):
|
|
9
|
+
self.mode = mode
|
|
10
|
+
self.value = value
|
|
11
|
+
self.unit = None
|
|
12
|
+
self.at_time = None
|
|
13
|
+
self.weekday = None
|
|
14
|
+
|
|
15
|
+
def seconds(self):
|
|
16
|
+
self.unit = "seconds"
|
|
17
|
+
return self
|
|
18
|
+
|
|
19
|
+
def minutes(self):
|
|
20
|
+
self.unit = "minutes"
|
|
21
|
+
return self
|
|
22
|
+
|
|
23
|
+
def hours(self):
|
|
24
|
+
self.unit = "hours"
|
|
25
|
+
return self
|
|
26
|
+
|
|
27
|
+
def day(self):
|
|
28
|
+
self.unit = "day"
|
|
29
|
+
return self
|
|
30
|
+
|
|
31
|
+
def monday(self): return self._set_weekday(0)
|
|
32
|
+
def tuesday(self): return self._set_weekday(1)
|
|
33
|
+
def wednesday(self): return self._set_weekday(2)
|
|
34
|
+
def thursday(self): return self._set_weekday(3)
|
|
35
|
+
def friday(self): return self._set_weekday(4)
|
|
36
|
+
|
|
37
|
+
def _set_weekday(self, day):
|
|
38
|
+
self.unit = "weekday"
|
|
39
|
+
self.weekday = day
|
|
40
|
+
return self
|
|
41
|
+
|
|
42
|
+
def at(self, time_str):
|
|
43
|
+
parse_time(time_str)
|
|
44
|
+
self.at_time = time_str
|
|
45
|
+
return self
|
|
46
|
+
|
|
47
|
+
def do(self, func, *args):
|
|
48
|
+
task = None
|
|
49
|
+
|
|
50
|
+
if self.mode == "in":
|
|
51
|
+
task = OneTimeTask(time.monotonic() + self.value, func, args)
|
|
52
|
+
|
|
53
|
+
elif self.mode == "every" and self.unit in ["seconds", "minutes", "hours"]:
|
|
54
|
+
mult = {"seconds": 1, "minutes": 60, "hours": 3600}[self.unit]
|
|
55
|
+
task = IntervalTask(self.value * mult, func, args)
|
|
56
|
+
|
|
57
|
+
elif self.mode == "every" and self.unit == "day":
|
|
58
|
+
h, m = map(int, self.at_time.split(":"))
|
|
59
|
+
task = DailyTask(h, m, func, args)
|
|
60
|
+
|
|
61
|
+
elif self.mode == "every" and self.unit == "weekday":
|
|
62
|
+
h, m = map(int, self.at_time.split(":"))
|
|
63
|
+
task = WeeklyTask(self.weekday, h, m, func, args)
|
|
64
|
+
|
|
65
|
+
if task:
|
|
66
|
+
add_task(task)
|
|
67
|
+
|
|
68
|
+
return task
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def every(value=None):
|
|
72
|
+
return TaskBuilder("every", value)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def in_(seconds):
|
|
76
|
+
return TaskBuilder("in", seconds)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
import time
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from .executor import run_task
|
|
5
|
+
|
|
6
|
+
_tasks = []
|
|
7
|
+
_lock = threading.Lock()
|
|
8
|
+
_running = False
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def start():
|
|
12
|
+
global _running
|
|
13
|
+
if not _running:
|
|
14
|
+
_running = True
|
|
15
|
+
threading.Thread(target=_loop, daemon=True).start()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def stop():
|
|
19
|
+
global _running
|
|
20
|
+
_running = False
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def add_task(task):
|
|
24
|
+
with _lock:
|
|
25
|
+
_tasks.append(task)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _loop():
|
|
29
|
+
global _running
|
|
30
|
+
while _running:
|
|
31
|
+
now = datetime.now()
|
|
32
|
+
to_remove = []
|
|
33
|
+
|
|
34
|
+
with _lock:
|
|
35
|
+
for task in _tasks:
|
|
36
|
+
if task.cancelled:
|
|
37
|
+
to_remove.append(task)
|
|
38
|
+
continue
|
|
39
|
+
|
|
40
|
+
if task.should_run(now):
|
|
41
|
+
run_task(task.func, task.args)
|
|
42
|
+
task.last_run = now
|
|
43
|
+
|
|
44
|
+
if task.one_time:
|
|
45
|
+
to_remove.append(task)
|
|
46
|
+
|
|
47
|
+
for t in to_remove:
|
|
48
|
+
if t in _tasks:
|
|
49
|
+
_tasks.remove(t)
|
|
50
|
+
|
|
51
|
+
time.sleep(0.5)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
2
|
+
|
|
3
|
+
_executor = ThreadPoolExecutor(max_workers=10)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def run_task(func, args):
|
|
7
|
+
def safe():
|
|
8
|
+
try:
|
|
9
|
+
func(*args)
|
|
10
|
+
except Exception as e:
|
|
11
|
+
print(f"[newcronixPy] Task error: {e}")
|
|
12
|
+
|
|
13
|
+
_executor.submit(safe)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class BaseTask:
|
|
6
|
+
def __init__(self, func, args):
|
|
7
|
+
self.func = func
|
|
8
|
+
self.args = args
|
|
9
|
+
self.last_run = None
|
|
10
|
+
self.cancelled = False
|
|
11
|
+
self.one_time = False
|
|
12
|
+
|
|
13
|
+
def should_run(self, now: datetime):
|
|
14
|
+
raise NotImplementedError
|
|
15
|
+
|
|
16
|
+
def cancel(self):
|
|
17
|
+
self.cancelled = True
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class IntervalTask(BaseTask):
|
|
21
|
+
def __init__(self, interval, func, args):
|
|
22
|
+
super().__init__(func, args)
|
|
23
|
+
self.interval = interval
|
|
24
|
+
self.next_run = time.monotonic() + interval
|
|
25
|
+
|
|
26
|
+
def should_run(self, now):
|
|
27
|
+
if time.monotonic() >= self.next_run:
|
|
28
|
+
self.next_run = time.monotonic() + self.interval
|
|
29
|
+
return True
|
|
30
|
+
return False
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class DailyTask(BaseTask):
|
|
34
|
+
def __init__(self, hour, minute, func, args):
|
|
35
|
+
super().__init__(func, args)
|
|
36
|
+
self.hour = hour
|
|
37
|
+
self.minute = minute
|
|
38
|
+
|
|
39
|
+
def should_run(self, now):
|
|
40
|
+
return (
|
|
41
|
+
now.hour == self.hour
|
|
42
|
+
and now.minute == self.minute
|
|
43
|
+
and self.last_run != now.date()
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class WeeklyTask(BaseTask):
|
|
48
|
+
def __init__(self, weekday, hour, minute, func, args):
|
|
49
|
+
super().__init__(func, args)
|
|
50
|
+
self.weekday = weekday
|
|
51
|
+
self.hour = hour
|
|
52
|
+
self.minute = minute
|
|
53
|
+
|
|
54
|
+
def should_run(self, now):
|
|
55
|
+
return (
|
|
56
|
+
now.weekday() == self.weekday
|
|
57
|
+
and now.hour == self.hour
|
|
58
|
+
and now.minute == self.minute
|
|
59
|
+
and self.last_run != now.date()
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class OneTimeTask(BaseTask):
|
|
64
|
+
def __init__(self, run_at, func, args):
|
|
65
|
+
super().__init__(func, args)
|
|
66
|
+
self.run_at = run_at
|
|
67
|
+
self.one_time = True
|
|
68
|
+
|
|
69
|
+
def should_run(self, now):
|
|
70
|
+
return time.monotonic() >= self.run_at
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: newcronixPy
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Simple and flexible task scheduler
|
|
5
|
+
Author-email: Kirill Zimin <ki822979@gmail.com>
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Requires-Python: >=3.8
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Dynamic: license-file
|
|
12
|
+
|
|
13
|
+
# newcronixPy
|
|
14
|
+
|
|
15
|
+
Simple Python task scheduler.
|
|
16
|
+
|
|
17
|
+
## Look for examples folder for examples
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
newcronixPy/__init__.py
|
|
5
|
+
newcronixPy/builder.py
|
|
6
|
+
newcronixPy/core.py
|
|
7
|
+
newcronixPy/executor.py
|
|
8
|
+
newcronixPy/tasks.py
|
|
9
|
+
newcronixPy/utils.py
|
|
10
|
+
newcronixPy.egg-info/PKG-INFO
|
|
11
|
+
newcronixPy.egg-info/SOURCES.txt
|
|
12
|
+
newcronixPy.egg-info/dependency_links.txt
|
|
13
|
+
newcronixPy.egg-info/top_level.txt
|
|
14
|
+
tests/test_scheduler.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
newcronixPy
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "newcronixPy"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Simple and flexible task scheduler"
|
|
9
|
+
authors = [
|
|
10
|
+
{ name = "Kirill Zimin", email='ki822979@gmail.com' }
|
|
11
|
+
]
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.8"
|
|
14
|
+
dependencies = []
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
]
|
|
19
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# dont touch this, please~!
|