scriptplan 0.9.0__py3-none-any.whl
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/__init__.py +22 -0
- scriptplan/cli/__init__.py +7 -0
- scriptplan/cli/main.py +546 -0
- scriptplan/core/__init__.py +0 -0
- scriptplan/core/account.py +125 -0
- scriptplan/core/allocation.py +69 -0
- scriptplan/core/booking.py +39 -0
- scriptplan/core/journal.py +377 -0
- scriptplan/core/leave.py +14 -0
- scriptplan/core/limits.py +354 -0
- scriptplan/core/project.py +924 -0
- scriptplan/core/property.py +1290 -0
- scriptplan/core/resource.py +198 -0
- scriptplan/core/resource_scenario.py +711 -0
- scriptplan/core/scenario.py +5 -0
- scriptplan/core/scenario_data.py +39 -0
- scriptplan/core/shift.py +71 -0
- scriptplan/core/task.py +77 -0
- scriptplan/core/task_scenario.py +1515 -0
- scriptplan/core/timesheet.py +457 -0
- scriptplan/core/working_hours.py +231 -0
- scriptplan/parser/__init__.py +0 -0
- scriptplan/parser/macro_processor.py +264 -0
- scriptplan/parser/tjp.lark +412 -0
- scriptplan/parser/tjp_parser.py +1904 -0
- scriptplan/py.typed +0 -0
- scriptplan/report/__init__.py +75 -0
- scriptplan/report/html_generator.py +477 -0
- scriptplan/report/report.py +466 -0
- scriptplan/report/report_base.py +397 -0
- scriptplan/report/report_context.py +248 -0
- scriptplan/report/resource_report.py +341 -0
- scriptplan/report/table_report.py +693 -0
- scriptplan/report/task_report.py +362 -0
- scriptplan/report/text_report.py +172 -0
- scriptplan/scheduler/__init__.py +0 -0
- scriptplan/scheduler/batch_processor.py +238 -0
- scriptplan/scheduler/scoreboard.py +120 -0
- scriptplan/utils/__init__.py +0 -0
- scriptplan/utils/data_cache.py +46 -0
- scriptplan/utils/logger.py +243 -0
- scriptplan/utils/message_handler.py +515 -0
- scriptplan/utils/time.py +195 -0
- scriptplan-0.9.0.dist-info/METADATA +161 -0
- scriptplan-0.9.0.dist-info/RECORD +49 -0
- scriptplan-0.9.0.dist-info/WHEEL +5 -0
- scriptplan-0.9.0.dist-info/entry_points.txt +2 -0
- scriptplan-0.9.0.dist-info/licenses/LICENSE +201 -0
- scriptplan-0.9.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from scriptplan.utils.message_handler import MessageHandler
|
|
2
|
+
|
|
3
|
+
class ScenarioData:
|
|
4
|
+
def __init__(self, property_node, idx, attributes):
|
|
5
|
+
self.property = property_node
|
|
6
|
+
self.project = property_node.project
|
|
7
|
+
self.scenarioIdx = idx
|
|
8
|
+
self.attributes = attributes
|
|
9
|
+
self.messageHandler = MessageHandler() # Should be singleton in real app
|
|
10
|
+
|
|
11
|
+
# Register the scenario with the property.
|
|
12
|
+
if self.property.data is None:
|
|
13
|
+
# Initialize if not present, assuming it's a list
|
|
14
|
+
# In PropertyTreeNode we initialized it as list of None
|
|
15
|
+
self.property.data = [None] * (self.project.scenarioCount() if hasattr(self.project, 'scenarioCount') else 1)
|
|
16
|
+
|
|
17
|
+
# Ensure list is big enough
|
|
18
|
+
while len(self.property.data) <= idx:
|
|
19
|
+
self.property.data.append(None)
|
|
20
|
+
|
|
21
|
+
self.property.data[idx] = self
|
|
22
|
+
|
|
23
|
+
def deep_clone(self):
|
|
24
|
+
return self
|
|
25
|
+
|
|
26
|
+
def a(self, attributeName):
|
|
27
|
+
return self.attributes[attributeName].get()
|
|
28
|
+
|
|
29
|
+
def error(self, id, text, sourceFileInfo=None, property_node=None):
|
|
30
|
+
# Delegating to message handler
|
|
31
|
+
# Simplified context passing
|
|
32
|
+
self.messageHandler.error(id, text, sourceFileInfo or self.property.sourceFileInfo)
|
|
33
|
+
|
|
34
|
+
def warning(self, id, text, sourceFileInfo=None, property_node=None):
|
|
35
|
+
self.messageHandler.warning(id, text, sourceFileInfo or self.property.sourceFileInfo)
|
|
36
|
+
|
|
37
|
+
def info(self, id, text, sourceFileInfo=None, property_node=None):
|
|
38
|
+
# Assuming info exists
|
|
39
|
+
print(f"INFO: {text}")
|
scriptplan/core/shift.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Shift module implementing work schedule definitions.
|
|
2
|
+
|
|
3
|
+
A shift is a definition of working hours for each day of the week.
|
|
4
|
+
It may also contain a list of intervals that define off-duty periods or leaves.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from scriptplan.core.property import PropertyTreeNode
|
|
8
|
+
from scriptplan.core.scenario_data import ScenarioData
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ShiftScenario(ScenarioData):
|
|
12
|
+
"""Handles the scenario-specific features of a Shift object."""
|
|
13
|
+
|
|
14
|
+
def __init__(self, shift, scenarioIdx, attributes):
|
|
15
|
+
super().__init__(shift, scenarioIdx, attributes)
|
|
16
|
+
|
|
17
|
+
def _get(self, attrName):
|
|
18
|
+
"""Get attribute value using property's attribute access."""
|
|
19
|
+
return self.property.get(attrName, self.scenarioIdx)
|
|
20
|
+
|
|
21
|
+
def onShift(self, date):
|
|
22
|
+
"""Returns True if the shift has working time defined for the date."""
|
|
23
|
+
workinghours = self._get('workinghours')
|
|
24
|
+
if workinghours:
|
|
25
|
+
return workinghours.onShift(date)
|
|
26
|
+
return False
|
|
27
|
+
|
|
28
|
+
def replace(self):
|
|
29
|
+
"""Returns the replace attribute value."""
|
|
30
|
+
return self._get('replace')
|
|
31
|
+
|
|
32
|
+
def onLeave(self, date):
|
|
33
|
+
"""Returns True if the shift has a vacation/leave defined for the date."""
|
|
34
|
+
leaves = self._get('leaves')
|
|
35
|
+
if leaves:
|
|
36
|
+
for leave in leaves:
|
|
37
|
+
if hasattr(leave, 'interval') and leave.interval.contains(date):
|
|
38
|
+
return True
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class Shift(PropertyTreeNode):
|
|
43
|
+
"""A shift is a definition of working hours for each day of the week.
|
|
44
|
+
|
|
45
|
+
It may also contain a list of intervals that define off-duty periods or leaves.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
def __init__(self, project, id, name, parent):
|
|
49
|
+
super().__init__(project.shifts, id, name, parent)
|
|
50
|
+
project.addShift(self)
|
|
51
|
+
|
|
52
|
+
# Initialize scenario data array
|
|
53
|
+
self.data = [None] * project.scenarioCount()
|
|
54
|
+
for i in range(project.scenarioCount()):
|
|
55
|
+
ShiftScenario(self, i, self._scenarioAttributes[i])
|
|
56
|
+
|
|
57
|
+
def scenario(self, scenarioIdx):
|
|
58
|
+
"""Return a reference to the scenarioIdx-th scenario."""
|
|
59
|
+
return self.data[scenarioIdx]
|
|
60
|
+
|
|
61
|
+
def onShift(self, scenarioIdx, date):
|
|
62
|
+
"""Check if shift is active on given date for the scenario."""
|
|
63
|
+
return self.data[scenarioIdx].onShift(date)
|
|
64
|
+
|
|
65
|
+
def onLeave(self, scenarioIdx, date):
|
|
66
|
+
"""Check if there is leave defined for the date in the scenario."""
|
|
67
|
+
return self.data[scenarioIdx].onLeave(date)
|
|
68
|
+
|
|
69
|
+
def replace(self, scenarioIdx):
|
|
70
|
+
"""Get the replace attribute for the scenario."""
|
|
71
|
+
return self.data[scenarioIdx].replace()
|
scriptplan/core/task.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from scriptplan.core.property import PropertyTreeNode
|
|
2
|
+
from scriptplan.core.task_scenario import TaskScenario
|
|
3
|
+
# from scriptplan.utils.rich_text import RichText, RTFHandlers # To be implemented
|
|
4
|
+
|
|
5
|
+
class Task(PropertyTreeNode):
|
|
6
|
+
def __init__(self, project, id, name, parent):
|
|
7
|
+
# super init calls project.tasks.addProperty(self)
|
|
8
|
+
super().__init__(project.tasks, id, name, parent)
|
|
9
|
+
|
|
10
|
+
# In Ruby: project.addTask(self)
|
|
11
|
+
# But PropertyTreeNode.__init__ already adds to propertySet.
|
|
12
|
+
# project.tasks IS the propertySet for tasks.
|
|
13
|
+
# So it might be redundant or project specific logic.
|
|
14
|
+
# We'll assume super() handles registration with project.tasks
|
|
15
|
+
|
|
16
|
+
# Initialize scenarios
|
|
17
|
+
scenario_count = self.project.scenarioCount() if hasattr(self.project, 'scenarioCount') else 1
|
|
18
|
+
self.data = [None] * scenario_count
|
|
19
|
+
|
|
20
|
+
for i in range(scenario_count):
|
|
21
|
+
# @scenarioAttributes is initialized in PropertyTreeNode
|
|
22
|
+
TaskScenario(self, i, self._scenarioAttributes[i])
|
|
23
|
+
|
|
24
|
+
def readyForScheduling(self, scenarioIdx):
|
|
25
|
+
if self.data[scenarioIdx]:
|
|
26
|
+
return self.data[scenarioIdx].readyForScheduling()
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
def prepareScheduling(self, scenarioIdx):
|
|
30
|
+
if self.data[scenarioIdx]:
|
|
31
|
+
# self.data[scenarioIdx] is TaskScenario
|
|
32
|
+
# TaskScenario doesn't implement prepareScheduling?
|
|
33
|
+
# Wait, ScenarioData might? Or TaskScenario should.
|
|
34
|
+
if hasattr(self.data[scenarioIdx], 'prepareScheduling'):
|
|
35
|
+
self.data[scenarioIdx].prepareScheduling()
|
|
36
|
+
|
|
37
|
+
def finishScheduling(self, scenarioIdx):
|
|
38
|
+
if self.data[scenarioIdx]:
|
|
39
|
+
if hasattr(self.data[scenarioIdx], 'finishScheduling'):
|
|
40
|
+
self.data[scenarioIdx].finishScheduling()
|
|
41
|
+
|
|
42
|
+
def schedule(self, scenarioIdx):
|
|
43
|
+
if self.data[scenarioIdx]:
|
|
44
|
+
return self.data[scenarioIdx].schedule()
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
def journalText(self, query, longVersion, recursive):
|
|
48
|
+
# Implementation of journalText logic
|
|
49
|
+
# Depends on project.journal, RichText, etc.
|
|
50
|
+
|
|
51
|
+
r_text = ""
|
|
52
|
+
|
|
53
|
+
# Mocking journal retrieval
|
|
54
|
+
journal = self.project.attributes.get('journal')
|
|
55
|
+
if not journal:
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
if recursive:
|
|
59
|
+
# entries = journal.entriesByTaskR(...)
|
|
60
|
+
entries = []
|
|
61
|
+
else:
|
|
62
|
+
# entries = journal.entriesByTask(...)
|
|
63
|
+
entries = []
|
|
64
|
+
|
|
65
|
+
# Sorting logic would go here
|
|
66
|
+
|
|
67
|
+
for entry in entries:
|
|
68
|
+
# Build r_text similar to Ruby
|
|
69
|
+
pass
|
|
70
|
+
|
|
71
|
+
if not r_text:
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
# Rich Text generation
|
|
75
|
+
# rti = RichText(r_text, ...).generateIntermediateFormat()
|
|
76
|
+
# query.rti = rti
|
|
77
|
+
pass
|