dargslan-cron-parser 1.0.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.
- dargslan_cron_parser-1.0.0/PKG-INFO +62 -0
- dargslan_cron_parser-1.0.0/README.md +41 -0
- dargslan_cron_parser-1.0.0/dargslan_cron_parser/__init__.py +162 -0
- dargslan_cron_parser-1.0.0/dargslan_cron_parser/cli.py +86 -0
- dargslan_cron_parser-1.0.0/dargslan_cron_parser.egg-info/PKG-INFO +62 -0
- dargslan_cron_parser-1.0.0/dargslan_cron_parser.egg-info/SOURCES.txt +9 -0
- dargslan_cron_parser-1.0.0/dargslan_cron_parser.egg-info/dependency_links.txt +1 -0
- dargslan_cron_parser-1.0.0/dargslan_cron_parser.egg-info/entry_points.txt +2 -0
- dargslan_cron_parser-1.0.0/dargslan_cron_parser.egg-info/top_level.txt +1 -0
- dargslan_cron_parser-1.0.0/pyproject.toml +31 -0
- dargslan_cron_parser-1.0.0/setup.cfg +4 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dargslan-cron-parser
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Crontab expression parser — next run calculation, natural language explanation, and schedule validation.
|
|
5
|
+
Author-email: Dargslan <info@dargslan.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://dargslan.com
|
|
8
|
+
Project-URL: Documentation, https://dargslan.com/blog
|
|
9
|
+
Project-URL: Repository, https://github.com/Dargslan
|
|
10
|
+
Project-URL: Free Cheat Sheets, https://dargslan.com/cheat-sheets
|
|
11
|
+
Project-URL: Linux & DevOps Books, https://dargslan.com/books
|
|
12
|
+
Keywords: linux,cron,crontab,scheduler,parser,sysadmin,devops
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Intended Audience :: System Administrators
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Topic :: System :: Systems Administration
|
|
19
|
+
Requires-Python: >=3.7
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# dargslan-cron-parser
|
|
23
|
+
|
|
24
|
+
Crontab expression parser — next run calculation, natural language explanation, and schedule validation.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install dargslan-cron-parser
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
dargslan-cron explain "*/5 * * * *" # Natural language
|
|
36
|
+
dargslan-cron next "0 2 * * *" # Next 5 runs
|
|
37
|
+
dargslan-cron validate "0 25 * * *" # Validate
|
|
38
|
+
dargslan-cron parse "0 */6 * * 1-5" # Parse fields
|
|
39
|
+
dargslan-cron json "0 0 1 * *" # JSON output
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
- Natural language explanation of cron expressions
|
|
45
|
+
- Next N run calculations
|
|
46
|
+
- Expression validation with error messages
|
|
47
|
+
- Support for @yearly, @monthly, @daily, etc.
|
|
48
|
+
- Field expansion and range support
|
|
49
|
+
- Zero dependencies — pure Python
|
|
50
|
+
|
|
51
|
+
## Part of dargslan-toolkit
|
|
52
|
+
|
|
53
|
+
Install all 54 Linux sysadmin tools: `pip install dargslan-toolkit`
|
|
54
|
+
|
|
55
|
+
## Links
|
|
56
|
+
|
|
57
|
+
- [Free Linux Cheat Sheets](https://dargslan.com/cheat-sheets)
|
|
58
|
+
- [Linux & DevOps Books](https://dargslan.com/books)
|
|
59
|
+
|
|
60
|
+
## License
|
|
61
|
+
|
|
62
|
+
MIT
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# dargslan-cron-parser
|
|
2
|
+
|
|
3
|
+
Crontab expression parser — next run calculation, natural language explanation, and schedule validation.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install dargslan-cron-parser
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
dargslan-cron explain "*/5 * * * *" # Natural language
|
|
15
|
+
dargslan-cron next "0 2 * * *" # Next 5 runs
|
|
16
|
+
dargslan-cron validate "0 25 * * *" # Validate
|
|
17
|
+
dargslan-cron parse "0 */6 * * 1-5" # Parse fields
|
|
18
|
+
dargslan-cron json "0 0 1 * *" # JSON output
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- Natural language explanation of cron expressions
|
|
24
|
+
- Next N run calculations
|
|
25
|
+
- Expression validation with error messages
|
|
26
|
+
- Support for @yearly, @monthly, @daily, etc.
|
|
27
|
+
- Field expansion and range support
|
|
28
|
+
- Zero dependencies — pure Python
|
|
29
|
+
|
|
30
|
+
## Part of dargslan-toolkit
|
|
31
|
+
|
|
32
|
+
Install all 54 Linux sysadmin tools: `pip install dargslan-toolkit`
|
|
33
|
+
|
|
34
|
+
## Links
|
|
35
|
+
|
|
36
|
+
- [Free Linux Cheat Sheets](https://dargslan.com/cheat-sheets)
|
|
37
|
+
- [Linux & DevOps Books](https://dargslan.com/books)
|
|
38
|
+
|
|
39
|
+
## License
|
|
40
|
+
|
|
41
|
+
MIT
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""dargslan-cron-parser — Crontab expression parser and scheduler."""
|
|
2
|
+
|
|
3
|
+
__version__ = "1.0.0"
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
import json
|
|
7
|
+
from datetime import datetime, timedelta
|
|
8
|
+
from calendar import monthrange
|
|
9
|
+
|
|
10
|
+
FIELD_NAMES = ["minute", "hour", "day_of_month", "month", "day_of_week"]
|
|
11
|
+
FIELD_RANGES = [(0, 59), (0, 23), (1, 31), (1, 12), (0, 7)]
|
|
12
|
+
MONTH_NAMES = {
|
|
13
|
+
"jan": 1, "feb": 2, "mar": 3, "apr": 4, "may": 5, "jun": 6,
|
|
14
|
+
"jul": 7, "aug": 8, "sep": 9, "oct": 10, "nov": 11, "dec": 12
|
|
15
|
+
}
|
|
16
|
+
DOW_NAMES = {
|
|
17
|
+
"sun": 0, "mon": 1, "tue": 2, "wed": 3, "thu": 4, "fri": 5, "sat": 6
|
|
18
|
+
}
|
|
19
|
+
SPECIAL_EXPRESSIONS = {
|
|
20
|
+
"@yearly": "0 0 1 1 *", "@annually": "0 0 1 1 *",
|
|
21
|
+
"@monthly": "0 0 1 * *", "@weekly": "0 0 * * 0",
|
|
22
|
+
"@daily": "0 0 * * *", "@midnight": "0 0 * * *",
|
|
23
|
+
"@hourly": "0 * * * *",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def expand_field(field, min_val, max_val):
|
|
28
|
+
if max_val == 7 and field == "7":
|
|
29
|
+
field = "0"
|
|
30
|
+
values = set()
|
|
31
|
+
for part in field.split(","):
|
|
32
|
+
step = 1
|
|
33
|
+
if "/" in part:
|
|
34
|
+
part, step_str = part.split("/", 1)
|
|
35
|
+
step = int(step_str)
|
|
36
|
+
if part == "*":
|
|
37
|
+
values.update(range(min_val, max_val + 1, step))
|
|
38
|
+
elif "-" in part:
|
|
39
|
+
start, end = part.split("-", 1)
|
|
40
|
+
start, end = int(start), int(end)
|
|
41
|
+
values.update(range(start, end + 1, step))
|
|
42
|
+
else:
|
|
43
|
+
part_lower = part.lower()
|
|
44
|
+
if part_lower in MONTH_NAMES:
|
|
45
|
+
values.add(MONTH_NAMES[part_lower])
|
|
46
|
+
elif part_lower in DOW_NAMES:
|
|
47
|
+
values.add(DOW_NAMES[part_lower])
|
|
48
|
+
else:
|
|
49
|
+
values.add(int(part))
|
|
50
|
+
return sorted(v for v in values if min_val <= v <= max_val)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def parse_expression(expr):
|
|
54
|
+
expr = expr.strip()
|
|
55
|
+
if expr.startswith("@"):
|
|
56
|
+
expr = SPECIAL_EXPRESSIONS.get(expr.lower(), expr)
|
|
57
|
+
parts = expr.split()
|
|
58
|
+
if len(parts) != 5:
|
|
59
|
+
return None
|
|
60
|
+
fields = {}
|
|
61
|
+
for i, (part, name) in enumerate(zip(parts, FIELD_NAMES)):
|
|
62
|
+
fields[name] = expand_field(part, FIELD_RANGES[i][0], FIELD_RANGES[i][1])
|
|
63
|
+
return fields
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def explain(expr):
|
|
67
|
+
expr_orig = expr.strip()
|
|
68
|
+
if expr_orig.startswith("@"):
|
|
69
|
+
mapped = SPECIAL_EXPRESSIONS.get(expr_orig.lower())
|
|
70
|
+
if mapped:
|
|
71
|
+
labels = {
|
|
72
|
+
"@yearly": "Once a year at midnight on January 1st",
|
|
73
|
+
"@annually": "Once a year at midnight on January 1st",
|
|
74
|
+
"@monthly": "Once a month at midnight on the 1st",
|
|
75
|
+
"@weekly": "Once a week at midnight on Sunday",
|
|
76
|
+
"@daily": "Once a day at midnight",
|
|
77
|
+
"@midnight": "Once a day at midnight",
|
|
78
|
+
"@hourly": "Once an hour at the beginning of the hour",
|
|
79
|
+
}
|
|
80
|
+
return labels.get(expr_orig.lower(), f"Equivalent to: {mapped}")
|
|
81
|
+
fields = parse_expression(expr)
|
|
82
|
+
if not fields:
|
|
83
|
+
return "Invalid cron expression"
|
|
84
|
+
parts = []
|
|
85
|
+
mins = fields["minute"]
|
|
86
|
+
hrs = fields["hour"]
|
|
87
|
+
doms = fields["day_of_month"]
|
|
88
|
+
mons = fields["month"]
|
|
89
|
+
dows = fields["day_of_week"]
|
|
90
|
+
dow_names_rev = {0: "Sunday", 1: "Monday", 2: "Tuesday", 3: "Wednesday", 4: "Thursday", 5: "Friday", 6: "Saturday"}
|
|
91
|
+
month_names_rev = {1: "January", 2: "February", 3: "March", 4: "April", 5: "May", 6: "June", 7: "July", 8: "August", 9: "September", 10: "October", 11: "November", 12: "December"}
|
|
92
|
+
if len(mins) == 1:
|
|
93
|
+
parts.append(f"At minute {mins[0]}")
|
|
94
|
+
elif len(mins) == 60:
|
|
95
|
+
parts.append("Every minute")
|
|
96
|
+
else:
|
|
97
|
+
parts.append(f"At minutes {', '.join(str(m) for m in mins)}")
|
|
98
|
+
if len(hrs) == 1:
|
|
99
|
+
parts.append(f"past hour {hrs[0]}")
|
|
100
|
+
elif len(hrs) < 24:
|
|
101
|
+
parts.append(f"past hours {', '.join(str(h) for h in hrs)}")
|
|
102
|
+
if len(doms) < 31:
|
|
103
|
+
parts.append(f"on day(s) {', '.join(str(d) for d in doms)}")
|
|
104
|
+
if len(mons) < 12:
|
|
105
|
+
parts.append(f"in {', '.join(month_names_rev.get(m, str(m)) for m in mons)}")
|
|
106
|
+
if len(dows) < 7:
|
|
107
|
+
parts.append(f"on {', '.join(dow_names_rev.get(d, str(d)) for d in dows)}")
|
|
108
|
+
return " ".join(parts)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def next_run(expr, after=None, count=5):
|
|
112
|
+
fields = parse_expression(expr)
|
|
113
|
+
if not fields:
|
|
114
|
+
return []
|
|
115
|
+
if after is None:
|
|
116
|
+
after = datetime.now()
|
|
117
|
+
current = after.replace(second=0, microsecond=0) + timedelta(minutes=1)
|
|
118
|
+
results = []
|
|
119
|
+
max_iter = 525600
|
|
120
|
+
for _ in range(max_iter):
|
|
121
|
+
if (current.minute in fields["minute"] and
|
|
122
|
+
current.hour in fields["hour"] and
|
|
123
|
+
current.day in fields["day_of_month"] and
|
|
124
|
+
current.month in fields["month"] and
|
|
125
|
+
(current.weekday() + 1) % 7 in fields["day_of_week"]):
|
|
126
|
+
results.append(current.isoformat())
|
|
127
|
+
if len(results) >= count:
|
|
128
|
+
break
|
|
129
|
+
current += timedelta(minutes=1)
|
|
130
|
+
return results
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def validate(expr):
|
|
134
|
+
issues = []
|
|
135
|
+
expr = expr.strip()
|
|
136
|
+
if expr.startswith("@"):
|
|
137
|
+
if expr.lower() not in SPECIAL_EXPRESSIONS:
|
|
138
|
+
issues.append(f"Unknown special expression: {expr}")
|
|
139
|
+
return issues
|
|
140
|
+
parts = expr.split()
|
|
141
|
+
if len(parts) != 5:
|
|
142
|
+
issues.append(f"Expected 5 fields, got {len(parts)}")
|
|
143
|
+
return issues
|
|
144
|
+
for i, (part, name) in enumerate(zip(parts, FIELD_NAMES)):
|
|
145
|
+
try:
|
|
146
|
+
vals = expand_field(part, FIELD_RANGES[i][0], FIELD_RANGES[i][1])
|
|
147
|
+
if not vals:
|
|
148
|
+
issues.append(f"Field '{name}' ({part}) expands to empty set")
|
|
149
|
+
except (ValueError, IndexError):
|
|
150
|
+
issues.append(f"Invalid field '{name}': {part}")
|
|
151
|
+
return issues
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def generate_report(expr):
|
|
155
|
+
return {
|
|
156
|
+
"expression": expr,
|
|
157
|
+
"explanation": explain(expr),
|
|
158
|
+
"validation": validate(expr),
|
|
159
|
+
"is_valid": len(validate(expr)) == 0,
|
|
160
|
+
"next_runs": next_run(expr),
|
|
161
|
+
"parsed_fields": parse_expression(expr),
|
|
162
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""CLI for dargslan-cron-parser."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
import json
|
|
5
|
+
from . import explain, next_run, validate, parse_expression, generate_report, __version__
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def main():
|
|
9
|
+
args = sys.argv[1:]
|
|
10
|
+
if not args or args[0] in ("-h", "--help"):
|
|
11
|
+
print(f"dargslan-cron-parser v{__version__}")
|
|
12
|
+
print(f"Crontab expression parser and scheduler")
|
|
13
|
+
print(f"\nUsage: dargslan-cron <command> <expression>")
|
|
14
|
+
print(f"\nCommands:")
|
|
15
|
+
print(f" explain \"*/5 * * * *\" Natural language explanation")
|
|
16
|
+
print(f" next \"0 2 * * *\" Next 5 scheduled runs")
|
|
17
|
+
print(f" validate \"0 25 * * *\" Validate expression")
|
|
18
|
+
print(f" parse \"0 */6 * * 1-5\" Parse into field values")
|
|
19
|
+
print(f" report \"0 0 1 * *\" Full analysis report")
|
|
20
|
+
print(f" json \"* * * * *\" Full report as JSON")
|
|
21
|
+
print(f" version Show version")
|
|
22
|
+
print(f"\nhttps://dargslan.com — Linux & DevOps Books")
|
|
23
|
+
return
|
|
24
|
+
|
|
25
|
+
cmd = args[0]
|
|
26
|
+
if cmd == "version":
|
|
27
|
+
print(f"dargslan-cron-parser v{__version__}")
|
|
28
|
+
return
|
|
29
|
+
|
|
30
|
+
if len(args) < 2:
|
|
31
|
+
print("Error: Please provide a cron expression.")
|
|
32
|
+
print("Example: dargslan-cron explain \"*/5 * * * *\"")
|
|
33
|
+
sys.exit(1)
|
|
34
|
+
|
|
35
|
+
expr = args[1]
|
|
36
|
+
if cmd == "explain":
|
|
37
|
+
print(explain(expr))
|
|
38
|
+
elif cmd == "next":
|
|
39
|
+
count = 5
|
|
40
|
+
if "-n" in args:
|
|
41
|
+
idx = args.index("-n")
|
|
42
|
+
if idx + 1 < len(args):
|
|
43
|
+
count = int(args[idx + 1])
|
|
44
|
+
runs = next_run(expr, count=count)
|
|
45
|
+
print(f"Next {len(runs)} runs for: {expr}")
|
|
46
|
+
print(f" {explain(expr)}")
|
|
47
|
+
for r in runs:
|
|
48
|
+
print(f" {r}")
|
|
49
|
+
elif cmd == "validate":
|
|
50
|
+
issues = validate(expr)
|
|
51
|
+
if not issues:
|
|
52
|
+
print(f"Valid: {expr}")
|
|
53
|
+
print(f" {explain(expr)}")
|
|
54
|
+
else:
|
|
55
|
+
print(f"Invalid: {expr}")
|
|
56
|
+
for i in issues:
|
|
57
|
+
print(f" [ERROR] {i}")
|
|
58
|
+
elif cmd == "parse":
|
|
59
|
+
fields = parse_expression(expr)
|
|
60
|
+
if fields:
|
|
61
|
+
for name, vals in fields.items():
|
|
62
|
+
print(f" {name}: {vals}")
|
|
63
|
+
else:
|
|
64
|
+
print("Invalid expression")
|
|
65
|
+
elif cmd == "report":
|
|
66
|
+
r = generate_report(expr)
|
|
67
|
+
print(f"Cron Expression: {r['expression']}")
|
|
68
|
+
print(f"Explanation: {r['explanation']}")
|
|
69
|
+
print(f"Valid: {r['is_valid']}")
|
|
70
|
+
if r['validation']:
|
|
71
|
+
print(f"Issues:")
|
|
72
|
+
for i in r['validation']:
|
|
73
|
+
print(f" {i}")
|
|
74
|
+
print(f"\nNext runs:")
|
|
75
|
+
for run in r['next_runs']:
|
|
76
|
+
print(f" {run}")
|
|
77
|
+
print(f"\nMore Linux tools: https://dargslan.com/cheat-sheets")
|
|
78
|
+
elif cmd == "json":
|
|
79
|
+
print(json.dumps(generate_report(expr), indent=2))
|
|
80
|
+
else:
|
|
81
|
+
print(f"Unknown command: {cmd}. Use --help for usage.")
|
|
82
|
+
sys.exit(1)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
if __name__ == "__main__":
|
|
86
|
+
main()
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dargslan-cron-parser
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Crontab expression parser — next run calculation, natural language explanation, and schedule validation.
|
|
5
|
+
Author-email: Dargslan <info@dargslan.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://dargslan.com
|
|
8
|
+
Project-URL: Documentation, https://dargslan.com/blog
|
|
9
|
+
Project-URL: Repository, https://github.com/Dargslan
|
|
10
|
+
Project-URL: Free Cheat Sheets, https://dargslan.com/cheat-sheets
|
|
11
|
+
Project-URL: Linux & DevOps Books, https://dargslan.com/books
|
|
12
|
+
Keywords: linux,cron,crontab,scheduler,parser,sysadmin,devops
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Intended Audience :: System Administrators
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Topic :: System :: Systems Administration
|
|
19
|
+
Requires-Python: >=3.7
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# dargslan-cron-parser
|
|
23
|
+
|
|
24
|
+
Crontab expression parser — next run calculation, natural language explanation, and schedule validation.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install dargslan-cron-parser
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
dargslan-cron explain "*/5 * * * *" # Natural language
|
|
36
|
+
dargslan-cron next "0 2 * * *" # Next 5 runs
|
|
37
|
+
dargslan-cron validate "0 25 * * *" # Validate
|
|
38
|
+
dargslan-cron parse "0 */6 * * 1-5" # Parse fields
|
|
39
|
+
dargslan-cron json "0 0 1 * *" # JSON output
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
- Natural language explanation of cron expressions
|
|
45
|
+
- Next N run calculations
|
|
46
|
+
- Expression validation with error messages
|
|
47
|
+
- Support for @yearly, @monthly, @daily, etc.
|
|
48
|
+
- Field expansion and range support
|
|
49
|
+
- Zero dependencies — pure Python
|
|
50
|
+
|
|
51
|
+
## Part of dargslan-toolkit
|
|
52
|
+
|
|
53
|
+
Install all 54 Linux sysadmin tools: `pip install dargslan-toolkit`
|
|
54
|
+
|
|
55
|
+
## Links
|
|
56
|
+
|
|
57
|
+
- [Free Linux Cheat Sheets](https://dargslan.com/cheat-sheets)
|
|
58
|
+
- [Linux & DevOps Books](https://dargslan.com/books)
|
|
59
|
+
|
|
60
|
+
## License
|
|
61
|
+
|
|
62
|
+
MIT
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
dargslan_cron_parser/__init__.py
|
|
4
|
+
dargslan_cron_parser/cli.py
|
|
5
|
+
dargslan_cron_parser.egg-info/PKG-INFO
|
|
6
|
+
dargslan_cron_parser.egg-info/SOURCES.txt
|
|
7
|
+
dargslan_cron_parser.egg-info/dependency_links.txt
|
|
8
|
+
dargslan_cron_parser.egg-info/entry_points.txt
|
|
9
|
+
dargslan_cron_parser.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
dargslan_cron_parser
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "dargslan-cron-parser"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Crontab expression parser — next run calculation, natural language explanation, and schedule validation."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.7"
|
|
12
|
+
authors = [{name = "Dargslan", email = "info@dargslan.com"}]
|
|
13
|
+
keywords = ["linux", "cron", "crontab", "scheduler", "parser", "sysadmin", "devops"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 5 - Production/Stable",
|
|
16
|
+
"Intended Audience :: System Administrators",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Operating System :: POSIX :: Linux",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Topic :: System :: Systems Administration",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.urls]
|
|
24
|
+
Homepage = "https://dargslan.com"
|
|
25
|
+
Documentation = "https://dargslan.com/blog"
|
|
26
|
+
Repository = "https://github.com/Dargslan"
|
|
27
|
+
"Free Cheat Sheets" = "https://dargslan.com/cheat-sheets"
|
|
28
|
+
"Linux & DevOps Books" = "https://dargslan.com/books"
|
|
29
|
+
|
|
30
|
+
[project.scripts]
|
|
31
|
+
dargslan-cron = "dargslan_cron_parser.cli:main"
|