scriptplan 0.9.0__tar.gz → 0.9.2__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.
- {scriptplan-0.9.0/scriptplan.egg-info → scriptplan-0.9.2}/PKG-INFO +102 -10
- scriptplan-0.9.2/README.md +208 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/pyproject.toml +31 -7
- scriptplan-0.9.2/scriptplan/__init__.py +26 -0
- scriptplan-0.9.2/scriptplan/_cython/__init__.py +45 -0
- scriptplan-0.9.2/scriptplan/_cython/scoreboard_cy.c +11547 -0
- scriptplan-0.9.2/scriptplan/_cython/scoreboard_cy.pyx +174 -0
- scriptplan-0.9.2/scriptplan/_cython/time_utils_cy.c +11618 -0
- scriptplan-0.9.2/scriptplan/_cython/time_utils_cy.pyx +149 -0
- scriptplan-0.9.2/scriptplan/_cython/working_hours_cy.c +11742 -0
- scriptplan-0.9.2/scriptplan/_cython/working_hours_cy.pyx +150 -0
- scriptplan-0.9.2/scriptplan/cli/__init__.py +7 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/cli/main.py +133 -135
- scriptplan-0.9.2/scriptplan/cli/plan.py +659 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/core/account.py +48 -40
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/core/allocation.py +37 -25
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/core/booking.py +19 -14
- scriptplan-0.9.2/scriptplan/core/exceptions.py +319 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/core/journal.py +74 -53
- scriptplan-0.9.2/scriptplan/core/leave.py +17 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/core/limits.py +64 -49
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/core/project.py +425 -401
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/core/property.py +366 -333
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/core/resource.py +35 -32
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/core/resource_scenario.py +123 -115
- scriptplan-0.9.2/scriptplan/core/scenario.py +11 -0
- scriptplan-0.9.2/scriptplan/core/scenario_data.py +66 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/core/shift.py +28 -19
- scriptplan-0.9.2/scriptplan/core/task.py +80 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/core/task_scenario.py +343 -268
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/core/timesheet.py +141 -121
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/core/working_hours.py +50 -26
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/parser/macro_processor.py +39 -38
- scriptplan-0.9.2/scriptplan/parser/tjp_parser.py +1845 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/report/__init__.py +29 -29
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/report/report.py +72 -161
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/report/report_base.py +98 -118
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/report/report_context.py +32 -32
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/report/resource_report.py +47 -61
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/report/table_report.py +188 -224
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/report/task_report.py +57 -67
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/report/text_report.py +49 -52
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/scheduler/batch_processor.py +44 -49
- scriptplan-0.9.2/scriptplan/scheduler/scoreboard.py +179 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/utils/data_cache.py +22 -18
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/utils/logger.py +39 -36
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/utils/message_handler.py +229 -155
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/utils/time.py +79 -66
- {scriptplan-0.9.0 → scriptplan-0.9.2/scriptplan.egg-info}/PKG-INFO +102 -10
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan.egg-info/SOURCES.txt +10 -3
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan.egg-info/entry_points.txt +1 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan.egg-info/requires.txt +6 -0
- scriptplan-0.9.2/setup.py +66 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_account.py +2 -1
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_attribute_base.py +3 -3
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_batch_processor.py +2 -3
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_cli.py +3 -9
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_core_allocation.py +5 -3
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_core_booking.py +8 -6
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_core_project.py +4 -2
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_core_resource.py +5 -3
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_core_scenario.py +6 -4
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_core_task.py +7 -5
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_journal.py +2 -1
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_logger.py +3 -2
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_macro_processor.py +1 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_message_handler.py +11 -6
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_parser.py +4 -2
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_property_list.py +2 -1
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_property_set.py +7 -6
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_property_tree_node.py +7 -6
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_report.py +77 -57
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_scheduling.py +4 -3
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_scheduling_validation.py +28 -20
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_scoreboard.py +11 -9
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_shift.py +1 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_timesheet.py +2 -1
- {scriptplan-0.9.0 → scriptplan-0.9.2}/tests/test_utils_time.py +7 -5
- scriptplan-0.9.0/README.md +0 -123
- scriptplan-0.9.0/scriptplan/__init__.py +0 -22
- scriptplan-0.9.0/scriptplan/cli/__init__.py +0 -7
- scriptplan-0.9.0/scriptplan/core/leave.py +0 -14
- scriptplan-0.9.0/scriptplan/core/scenario.py +0 -5
- scriptplan-0.9.0/scriptplan/core/scenario_data.py +0 -39
- scriptplan-0.9.0/scriptplan/core/task.py +0 -77
- scriptplan-0.9.0/scriptplan/parser/tjp_parser.py +0 -1904
- scriptplan-0.9.0/scriptplan/report/html_generator.py +0 -477
- scriptplan-0.9.0/scriptplan/scheduler/scoreboard.py +0 -120
- scriptplan-0.9.0/tests/test_html_generator.py +0 -268
- scriptplan-0.9.0/tests/test_html_report_integration.py +0 -199
- {scriptplan-0.9.0 → scriptplan-0.9.2}/LICENSE +0 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/MANIFEST.in +0 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/core/__init__.py +0 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/parser/__init__.py +0 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/parser/tjp.lark +0 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/py.typed +0 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/scheduler/__init__.py +0 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan/utils/__init__.py +0 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan.egg-info/dependency_links.txt +0 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/scriptplan.egg-info/top_level.txt +0 -0
- {scriptplan-0.9.0 → scriptplan-0.9.2}/setup.cfg +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scriptplan
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.2
|
|
4
4
|
Summary: A precise project scheduling engine with minute-level accuracy for resource allocation and dependency management.
|
|
5
5
|
Author-email: Farshid Ashouri <farsheed.ashouri@gmail.com>
|
|
6
6
|
Maintainer-email: Farshid Ashouri <farsheed.ashouri@gmail.com>
|
|
7
7
|
License-Expression: Apache-2.0
|
|
8
|
-
Project-URL: Homepage, https://github.com/
|
|
9
|
-
Project-URL: Documentation, https://github.com/
|
|
10
|
-
Project-URL: Bug Tracker, https://github.com/
|
|
11
|
-
Project-URL: Source, https://github.com/
|
|
8
|
+
Project-URL: Homepage, https://github.com/rodmena-limited/scriptplan
|
|
9
|
+
Project-URL: Documentation, https://github.com/rodmena-limited/scriptplan#readme
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/rodmena-limited/scriptplan/issues
|
|
11
|
+
Project-URL: Source, https://github.com/rodmena-limited/scriptplan
|
|
12
12
|
Keywords: scheduling,project-management,resource-allocation,gantt,critical-path
|
|
13
13
|
Classifier: Development Status :: 4 - Beta
|
|
14
14
|
Classifier: Intended Audience :: Developers
|
|
@@ -19,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
23
|
Classifier: Operating System :: OS Independent
|
|
23
24
|
Classifier: Topic :: Office/Business :: Scheduling
|
|
24
25
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
@@ -28,16 +29,32 @@ Description-Content-Type: text/markdown
|
|
|
28
29
|
License-File: LICENSE
|
|
29
30
|
Requires-Dist: lark>=1.0.0
|
|
30
31
|
Requires-Dist: python-dateutil>=2.8.0
|
|
32
|
+
Requires-Dist: click>=8.0.0
|
|
31
33
|
Provides-Extra: dev
|
|
32
34
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
33
35
|
Requires-Dist: pytest-xdist>=3.0.0; extra == "dev"
|
|
34
36
|
Requires-Dist: pandas>=1.5.0; extra == "dev"
|
|
37
|
+
Requires-Dist: types-python-dateutil>=2.8.0; extra == "dev"
|
|
38
|
+
Requires-Dist: types-pytz>=2022.1.0; extra == "dev"
|
|
35
39
|
Requires-Dist: build; extra == "dev"
|
|
36
40
|
Requires-Dist: twine; extra == "dev"
|
|
41
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
42
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
43
|
+
Requires-Dist: cython>=3.0.0; extra == "dev"
|
|
37
44
|
Dynamic: license-file
|
|
38
45
|
|
|
46
|
+
<p align="center">
|
|
47
|
+
<img src="https://raw.githubusercontent.com/rodmena-limited/scriptplan/main/icons/logo.svg" alt="ScriptPlan" width="400"/>
|
|
48
|
+
</p>
|
|
49
|
+
|
|
39
50
|
# ScriptPlan
|
|
40
51
|
|
|
52
|
+

|
|
53
|
+

|
|
54
|
+

|
|
55
|
+

|
|
56
|
+

|
|
57
|
+
|
|
41
58
|
A precise project scheduling engine with minute-level accuracy for resource allocation and dependency management. The syntax is compatible with TaskJuggler (.tjp files).
|
|
42
59
|
|
|
43
60
|
## Installation
|
|
@@ -46,15 +63,59 @@ A precise project scheduling engine with minute-level accuracy for resource allo
|
|
|
46
63
|
pip install scriptplan
|
|
47
64
|
```
|
|
48
65
|
|
|
49
|
-
##
|
|
66
|
+
## Quick Start
|
|
50
67
|
|
|
51
|
-
###
|
|
68
|
+
### Report Generation (Unix-style)
|
|
52
69
|
|
|
53
70
|
```bash
|
|
54
|
-
|
|
55
|
-
|
|
71
|
+
# Generate JSON report to stdout
|
|
72
|
+
plan report project.tjp
|
|
73
|
+
|
|
74
|
+
# Generate CSV report
|
|
75
|
+
plan report --csv project.tjp
|
|
76
|
+
|
|
77
|
+
# Save to file
|
|
78
|
+
plan report project.tjp > output.json
|
|
79
|
+
plan report --csv project.tjp > output.csv
|
|
80
|
+
|
|
81
|
+
# Read from stdin
|
|
82
|
+
cat project.tjp | plan report
|
|
83
|
+
plan report - < project.tjp
|
|
84
|
+
|
|
85
|
+
# Pipe to other tools
|
|
86
|
+
plan report project.tjp | jq '.data[0]'
|
|
87
|
+
plan report --csv project.tjp | csvkit
|
|
88
|
+
|
|
89
|
+
# Process multiple files
|
|
90
|
+
for f in projects/*.tjp; do
|
|
91
|
+
plan report "$f" | jq -r '.report_id'
|
|
92
|
+
done
|
|
56
93
|
```
|
|
57
94
|
|
|
95
|
+
**Output Format** (JSON):
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"data": [
|
|
99
|
+
{
|
|
100
|
+
"id": "project.task1",
|
|
101
|
+
"start": "2024-01-01-09:00",
|
|
102
|
+
"end": "2024-01-05-17:00"
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
"columns": ["id", "start", "end"],
|
|
106
|
+
"report_id": "ea3f901dd6426dfa58288d945819c75485fd9ff1875db59def350f219e2d62ca"
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Features**:
|
|
111
|
+
- Output to stdout (Unix philosophy)
|
|
112
|
+
- Messages to stderr
|
|
113
|
+
- SHA256 report_id (content-based hash)
|
|
114
|
+
- Lowercase column names
|
|
115
|
+
- No HTML metadata
|
|
116
|
+
- No file pollution (uses temp directories)
|
|
117
|
+
- Safe for concurrent execution (100+ instances)
|
|
118
|
+
|
|
58
119
|
### Python API
|
|
59
120
|
|
|
60
121
|
```python
|
|
@@ -71,6 +132,20 @@ for task in project.tasks:
|
|
|
71
132
|
print(f"{task.id}: {start} -> {end}")
|
|
72
133
|
```
|
|
73
134
|
|
|
135
|
+
## System Certified
|
|
136
|
+
|
|
137
|
+
**Certification Level**: Airport-Grade / Mission Critical
|
|
138
|
+
|
|
139
|
+
**Capabilities Verified**:
|
|
140
|
+
|
|
141
|
+
- **Temporal Physics**: Floating point precision, Timezones, DST awareness, Date Line crossing.
|
|
142
|
+
|
|
143
|
+
- **Resource Constraints**: Daily/Weekly limits, Hierarchical quotas, Shift intersections.
|
|
144
|
+
|
|
145
|
+
- **Advanced Scheduling**: ALAP (Backward pass), Priority preemption, Smart Resource Selection (Failover).
|
|
146
|
+
|
|
147
|
+
- **Workflow Logic**: Atomicity (Contiguous), Perishability (Max Gap), Zero-Buffer Synchronization.
|
|
148
|
+
|
|
74
149
|
## Features
|
|
75
150
|
|
|
76
151
|
- Minute-level scheduling precision
|
|
@@ -158,4 +233,21 @@ delivery.assemble_b: 2025-07-16-08:00 -> 2025-07-17-16:00
|
|
|
158
233
|
|
|
159
234
|
## License
|
|
160
235
|
|
|
161
|
-
Apache
|
|
236
|
+
Apache-2.0
|
|
237
|
+
|
|
238
|
+
## Acknowledgments
|
|
239
|
+
|
|
240
|
+
ScriptPlan references [TaskJuggler](https://taskjuggler.org/) solely for **file format compatibility**. We have not used, modified, or copied any TaskJuggler source code. ScriptPlan is an independent, clean-room implementation.
|
|
241
|
+
|
|
242
|
+
- The `.tjp` file format is documented publicly and widely used in the project management community
|
|
243
|
+
- All scheduling algorithms, parser, and report generation in ScriptPlan are original implementations
|
|
244
|
+
- TaskJuggler is mentioned only to indicate that ScriptPlan can read the same project file format
|
|
245
|
+
|
|
246
|
+
If you're looking for the original TaskJuggler with its full feature set including interactive HTML reports and GUI tools, please visit [taskjuggler.org](https://taskjuggler.org/).
|
|
247
|
+
|
|
248
|
+
## Why ScriptPlan?
|
|
249
|
+
|
|
250
|
+
This scheduler is part of Highway Workflow Engine's worker capacity management system. I decided to open-source it for the community to benefit from its precise scheduling capabilities. Thanks to TaskJuggler's established syntax, users can easily adopt ScriptPlan without learning a new format.
|
|
251
|
+
|
|
252
|
+
Yours,
|
|
253
|
+
Farshid.
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/rodmena-limited/scriptplan/main/icons/logo.svg" alt="ScriptPlan" width="400"/>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# ScriptPlan
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+

|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
A precise project scheduling engine with minute-level accuracy for resource allocation and dependency management. The syntax is compatible with TaskJuggler (.tjp files).
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install scriptplan
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### Report Generation (Unix-style)
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Generate JSON report to stdout
|
|
27
|
+
plan report project.tjp
|
|
28
|
+
|
|
29
|
+
# Generate CSV report
|
|
30
|
+
plan report --csv project.tjp
|
|
31
|
+
|
|
32
|
+
# Save to file
|
|
33
|
+
plan report project.tjp > output.json
|
|
34
|
+
plan report --csv project.tjp > output.csv
|
|
35
|
+
|
|
36
|
+
# Read from stdin
|
|
37
|
+
cat project.tjp | plan report
|
|
38
|
+
plan report - < project.tjp
|
|
39
|
+
|
|
40
|
+
# Pipe to other tools
|
|
41
|
+
plan report project.tjp | jq '.data[0]'
|
|
42
|
+
plan report --csv project.tjp | csvkit
|
|
43
|
+
|
|
44
|
+
# Process multiple files
|
|
45
|
+
for f in projects/*.tjp; do
|
|
46
|
+
plan report "$f" | jq -r '.report_id'
|
|
47
|
+
done
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Output Format** (JSON):
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"data": [
|
|
54
|
+
{
|
|
55
|
+
"id": "project.task1",
|
|
56
|
+
"start": "2024-01-01-09:00",
|
|
57
|
+
"end": "2024-01-05-17:00"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"columns": ["id", "start", "end"],
|
|
61
|
+
"report_id": "ea3f901dd6426dfa58288d945819c75485fd9ff1875db59def350f219e2d62ca"
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Features**:
|
|
66
|
+
- Output to stdout (Unix philosophy)
|
|
67
|
+
- Messages to stderr
|
|
68
|
+
- SHA256 report_id (content-based hash)
|
|
69
|
+
- Lowercase column names
|
|
70
|
+
- No HTML metadata
|
|
71
|
+
- No file pollution (uses temp directories)
|
|
72
|
+
- Safe for concurrent execution (100+ instances)
|
|
73
|
+
|
|
74
|
+
### Python API
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from scriptplan.parser.tjp_parser import ProjectFileParser
|
|
78
|
+
|
|
79
|
+
parser = ProjectFileParser()
|
|
80
|
+
project = parser.parse(open('project.tjp').read())
|
|
81
|
+
|
|
82
|
+
# Access scheduled tasks
|
|
83
|
+
for task in project.tasks:
|
|
84
|
+
if task.leaf():
|
|
85
|
+
start = task.get('start', 0)
|
|
86
|
+
end = task.get('end', 0)
|
|
87
|
+
print(f"{task.id}: {start} -> {end}")
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## System Certified
|
|
91
|
+
|
|
92
|
+
**Certification Level**: Airport-Grade / Mission Critical
|
|
93
|
+
|
|
94
|
+
**Capabilities Verified**:
|
|
95
|
+
|
|
96
|
+
- **Temporal Physics**: Floating point precision, Timezones, DST awareness, Date Line crossing.
|
|
97
|
+
|
|
98
|
+
- **Resource Constraints**: Daily/Weekly limits, Hierarchical quotas, Shift intersections.
|
|
99
|
+
|
|
100
|
+
- **Advanced Scheduling**: ALAP (Backward pass), Priority preemption, Smart Resource Selection (Failover).
|
|
101
|
+
|
|
102
|
+
- **Workflow Logic**: Atomicity (Contiguous), Perishability (Max Gap), Zero-Buffer Synchronization.
|
|
103
|
+
|
|
104
|
+
## Features
|
|
105
|
+
|
|
106
|
+
- Minute-level scheduling precision
|
|
107
|
+
- ASAP and ALAP scheduling modes
|
|
108
|
+
- Resource allocation with contention handling
|
|
109
|
+
- Working hours and shift definitions
|
|
110
|
+
- Dependency chains with gap constraints
|
|
111
|
+
- Leap year and timezone handling
|
|
112
|
+
|
|
113
|
+
## Accuracy
|
|
114
|
+
|
|
115
|
+
ScriptPlan uses integer arithmetic for all time calculations, avoiding floating-point drift. The scheduler correctly handles:
|
|
116
|
+
|
|
117
|
+
- Non-standard shift boundaries (e.g., 08:13 - 11:59, 13:07 - 17:47)
|
|
118
|
+
- Prime-number effort durations with prime-number gaps
|
|
119
|
+
- Resource contention across multi-day tasks
|
|
120
|
+
- Calendar gaps (weekends, holidays) vs working time gaps
|
|
121
|
+
|
|
122
|
+
Example: A chain of 500 tasks, each with 73-minute effort and 29-minute gaps, scheduled across leap year boundaries with non-standard shifts, produces exact minute-aligned results.
|
|
123
|
+
|
|
124
|
+
## Example Project
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
project "Manufacturing" 2025-07-01 +1m {
|
|
128
|
+
timezone "Etc/UTC"
|
|
129
|
+
timeformat "%Y-%m-%d %H:%M"
|
|
130
|
+
scheduling alap
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
shift factory_hours "Factory Hours" {
|
|
134
|
+
workinghours mon - fri 08:00 - 16:00
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
resource machine "Press" {
|
|
138
|
+
workinghours factory_hours
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
task delivery "Product Launch" {
|
|
142
|
+
end 2025-07-18-16:00
|
|
143
|
+
|
|
144
|
+
task pack "Packaging" {
|
|
145
|
+
effort 8h
|
|
146
|
+
allocate machine
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
task assemble_b "Body Assembly" {
|
|
150
|
+
effort 16h
|
|
151
|
+
allocate machine
|
|
152
|
+
depends !!pack { onstart }
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
task assemble_a "Engine Assembly" {
|
|
156
|
+
effort 16h
|
|
157
|
+
allocate machine
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
task connection_setup "Logic" {
|
|
162
|
+
task set_deps "Apply" {
|
|
163
|
+
depends !delivery.assemble_a, !delivery.assemble_b
|
|
164
|
+
precedes !delivery.pack
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
taskreport output "output" {
|
|
169
|
+
formats csv
|
|
170
|
+
columns id, start, end
|
|
171
|
+
timeformat "%Y-%m-%d-%H:%M"
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
This project schedules backward from the delivery deadline (ALAP mode). The scheduler:
|
|
176
|
+
|
|
177
|
+
1. Anchors packaging to end at 16:00 on July 18
|
|
178
|
+
2. Schedules both assembly tasks to complete before packaging starts
|
|
179
|
+
3. Resolves resource contention (single machine) by sequencing assemblies back-to-back
|
|
180
|
+
4. Respects weekend boundaries (Mon-Fri working hours)
|
|
181
|
+
|
|
182
|
+
Result:
|
|
183
|
+
```
|
|
184
|
+
delivery.pack: 2025-07-18-08:00 -> 2025-07-18-16:00
|
|
185
|
+
delivery.assemble_a: 2025-07-14-08:00 -> 2025-07-15-16:00
|
|
186
|
+
delivery.assemble_b: 2025-07-16-08:00 -> 2025-07-17-16:00
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
Apache-2.0
|
|
192
|
+
|
|
193
|
+
## Acknowledgments
|
|
194
|
+
|
|
195
|
+
ScriptPlan references [TaskJuggler](https://taskjuggler.org/) solely for **file format compatibility**. We have not used, modified, or copied any TaskJuggler source code. ScriptPlan is an independent, clean-room implementation.
|
|
196
|
+
|
|
197
|
+
- The `.tjp` file format is documented publicly and widely used in the project management community
|
|
198
|
+
- All scheduling algorithms, parser, and report generation in ScriptPlan are original implementations
|
|
199
|
+
- TaskJuggler is mentioned only to indicate that ScriptPlan can read the same project file format
|
|
200
|
+
|
|
201
|
+
If you're looking for the original TaskJuggler with its full feature set including interactive HTML reports and GUI tools, please visit [taskjuggler.org](https://taskjuggler.org/).
|
|
202
|
+
|
|
203
|
+
## Why ScriptPlan?
|
|
204
|
+
|
|
205
|
+
This scheduler is part of Highway Workflow Engine's worker capacity management system. I decided to open-source it for the community to benefit from its precise scheduling capabilities. Thanks to TaskJuggler's established syntax, users can easily adopt ScriptPlan without learning a new format.
|
|
206
|
+
|
|
207
|
+
Yours,
|
|
208
|
+
Farshid.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["setuptools>=61.0", "wheel"]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel", "cython>=3.0.0"]
|
|
3
3
|
build-backend = "setuptools.build_meta"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "scriptplan"
|
|
7
|
-
version = "0.9.
|
|
7
|
+
version = "0.9.2"
|
|
8
8
|
description = "A precise project scheduling engine with minute-level accuracy for resource allocation and dependency management."
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Farshid Ashouri", email = "farsheed.ashouri@gmail.com" },
|
|
@@ -26,6 +26,7 @@ classifiers = [
|
|
|
26
26
|
"Programming Language :: Python :: 3.11",
|
|
27
27
|
"Programming Language :: Python :: 3.12",
|
|
28
28
|
"Programming Language :: Python :: 3.13",
|
|
29
|
+
"Programming Language :: Python :: 3.14",
|
|
29
30
|
"Operating System :: OS Independent",
|
|
30
31
|
"Topic :: Office/Business :: Scheduling",
|
|
31
32
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
@@ -35,6 +36,7 @@ keywords = ["scheduling", "project-management", "resource-allocation", "gantt",
|
|
|
35
36
|
dependencies = [
|
|
36
37
|
"lark>=1.0.0",
|
|
37
38
|
"python-dateutil>=2.8.0",
|
|
39
|
+
"click>=8.0.0",
|
|
38
40
|
]
|
|
39
41
|
|
|
40
42
|
[project.optional-dependencies]
|
|
@@ -42,18 +44,24 @@ dev = [
|
|
|
42
44
|
"pytest>=7.0.0",
|
|
43
45
|
"pytest-xdist>=3.0.0",
|
|
44
46
|
"pandas>=1.5.0",
|
|
47
|
+
"types-python-dateutil>=2.8.0",
|
|
48
|
+
"types-pytz>=2022.1.0",
|
|
45
49
|
"build",
|
|
46
50
|
"twine",
|
|
51
|
+
"ruff>=0.1.0",
|
|
52
|
+
"mypy>=1.0.0",
|
|
53
|
+
"cython>=3.0.0",
|
|
47
54
|
]
|
|
48
55
|
|
|
49
56
|
[project.scripts]
|
|
50
57
|
scriptplan = "scriptplan.cli.main:main"
|
|
58
|
+
plan = "scriptplan.cli.plan:main"
|
|
51
59
|
|
|
52
60
|
[project.urls]
|
|
53
|
-
"Homepage" = "https://github.com/
|
|
54
|
-
"Documentation" = "https://github.com/
|
|
55
|
-
"Bug Tracker" = "https://github.com/
|
|
56
|
-
"Source" = "https://github.com/
|
|
61
|
+
"Homepage" = "https://github.com/rodmena-limited/scriptplan"
|
|
62
|
+
"Documentation" = "https://github.com/rodmena-limited/scriptplan#readme"
|
|
63
|
+
"Bug Tracker" = "https://github.com/rodmena-limited/scriptplan/issues"
|
|
64
|
+
"Source" = "https://github.com/rodmena-limited/scriptplan"
|
|
57
65
|
|
|
58
66
|
[tool.setuptools]
|
|
59
67
|
include-package-data = true
|
|
@@ -63,7 +71,7 @@ where = ["."]
|
|
|
63
71
|
include = ["scriptplan*"]
|
|
64
72
|
|
|
65
73
|
[tool.setuptools.package-data]
|
|
66
|
-
scriptplan = ["py.typed", "parser/*.lark"]
|
|
74
|
+
scriptplan = ["py.typed", "parser/*.lark", "_cython/*.pyx"]
|
|
67
75
|
|
|
68
76
|
[tool.pytest.ini_options]
|
|
69
77
|
testpaths = ["tests"]
|
|
@@ -75,3 +83,19 @@ filterwarnings = [
|
|
|
75
83
|
"ignore::DeprecationWarning",
|
|
76
84
|
"ignore::PendingDeprecationWarning",
|
|
77
85
|
]
|
|
86
|
+
|
|
87
|
+
[tool.ruff]
|
|
88
|
+
line-length = 120
|
|
89
|
+
target-version = "py39"
|
|
90
|
+
|
|
91
|
+
[tool.ruff.lint]
|
|
92
|
+
select = ["E", "F", "W", "I", "UP", "B", "C4", "SIM", "RUF"]
|
|
93
|
+
# N rules ignored: codebase uses camelCase for TaskJuggler API compatibility
|
|
94
|
+
ignore = ["E501"] # Line length handled separately
|
|
95
|
+
|
|
96
|
+
[tool.mypy]
|
|
97
|
+
python_version = "3.9"
|
|
98
|
+
strict = true
|
|
99
|
+
warn_return_any = true
|
|
100
|
+
warn_unused_configs = true
|
|
101
|
+
ignore_missing_imports = true
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ScriptPlan - A Python implementation inspired by TaskJuggler.
|
|
3
|
+
|
|
4
|
+
This package provides project scheduling and resource management capabilities
|
|
5
|
+
compatible with the TaskJuggler Project Definition Language (.tjp files).
|
|
6
|
+
|
|
7
|
+
ScriptPlan owes its existence to TaskJuggler (https://taskjuggler.org/),
|
|
8
|
+
the pioneering open-source project management tool created by Chris Schlaeger.
|
|
9
|
+
The TJP file format and scheduling concepts originate from TaskJuggler.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
__version__ = "0.9.2"
|
|
13
|
+
__author__ = "ScriptPlan Team"
|
|
14
|
+
|
|
15
|
+
from scriptplan.core.project import Project
|
|
16
|
+
from scriptplan.core.resource import Resource
|
|
17
|
+
from scriptplan.core.scenario import Scenario
|
|
18
|
+
from scriptplan.core.task import Task
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"Project",
|
|
22
|
+
"Resource",
|
|
23
|
+
"Scenario",
|
|
24
|
+
"Task",
|
|
25
|
+
"__version__",
|
|
26
|
+
]
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Cython-optimized modules for ScriptPlan.
|
|
3
|
+
|
|
4
|
+
This package contains Cython implementations of performance-critical code.
|
|
5
|
+
Pure Python fallbacks are used if Cython extensions are not compiled.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
# Track which optimized modules are available
|
|
9
|
+
CYTHON_AVAILABLE = {
|
|
10
|
+
"scoreboard": False,
|
|
11
|
+
"time_utils": False,
|
|
12
|
+
"working_hours": False,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
# Try to import Cython modules
|
|
16
|
+
try:
|
|
17
|
+
from scriptplan._cython import scoreboard_cy # noqa: F401
|
|
18
|
+
|
|
19
|
+
CYTHON_AVAILABLE["scoreboard"] = True
|
|
20
|
+
except ImportError:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
from scriptplan._cython import time_utils_cy # noqa: F401
|
|
25
|
+
|
|
26
|
+
CYTHON_AVAILABLE["time_utils"] = True
|
|
27
|
+
except ImportError:
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
from scriptplan._cython import working_hours_cy # noqa: F401
|
|
32
|
+
|
|
33
|
+
CYTHON_AVAILABLE["working_hours"] = True
|
|
34
|
+
except ImportError:
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def is_optimized(module: str) -> bool:
|
|
39
|
+
"""Check if a Cython-optimized module is available."""
|
|
40
|
+
return CYTHON_AVAILABLE.get(module, False)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_available_optimizations() -> list[str]:
|
|
44
|
+
"""Get list of available Cython optimizations."""
|
|
45
|
+
return [k for k, v in CYTHON_AVAILABLE.items() if v]
|