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.
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,5 @@
1
+ # newcronixPy
2
+
3
+ Simple Python task scheduler.
4
+
5
+ ## Look for examples folder for examples
@@ -0,0 +1,4 @@
1
+ from .core import start, stop
2
+ from .builder import every, in_
3
+
4
+ __all__ = ["start", "stop", "every", "in_"]
@@ -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,5 @@
1
+ from datetime import datetime
2
+
3
+
4
+ def parse_time(time_str: str):
5
+ return datetime.strptime(time_str, "%H:%M")
@@ -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
+ 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,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ # dont touch this, please~!