DIRACCommon 9.0.0a66__py3-none-any.whl → 9.0.0a67__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.
- DIRACCommon/Core/Utilities/ClassAd/ClassAdLight.py +295 -0
- DIRACCommon/Core/Utilities/ClassAd/__init__.py +1 -0
- DIRACCommon/Core/Utilities/JDL.py +199 -0
- DIRACCommon/Core/Utilities/List.py +127 -0
- DIRACCommon/{Utils → Core/Utilities}/ReturnValues.py +1 -1
- DIRACCommon/Core/Utilities/StateMachine.py +185 -0
- DIRACCommon/Core/Utilities/TimeUtilities.py +259 -0
- DIRACCommon/Core/__init__.py +1 -0
- DIRACCommon/WorkloadManagementSystem/Client/JobState/JobManifest.py +235 -0
- DIRACCommon/WorkloadManagementSystem/Client/JobState/__init__.py +0 -0
- DIRACCommon/WorkloadManagementSystem/Client/JobStatus.py +95 -0
- DIRACCommon/WorkloadManagementSystem/Client/__init__.py +1 -0
- DIRACCommon/WorkloadManagementSystem/DB/JobDBUtils.py +170 -0
- DIRACCommon/WorkloadManagementSystem/DB/__init__.py +1 -0
- DIRACCommon/WorkloadManagementSystem/Utilities/JobModel.py +236 -0
- DIRACCommon/WorkloadManagementSystem/Utilities/JobStatusUtility.py +93 -0
- DIRACCommon/WorkloadManagementSystem/Utilities/ParametricJob.py +179 -0
- DIRACCommon/WorkloadManagementSystem/Utilities/__init__.py +1 -0
- DIRACCommon/WorkloadManagementSystem/__init__.py +1 -0
- {diraccommon-9.0.0a66.dist-info → diraccommon-9.0.0a67.dist-info}/METADATA +9 -4
- diraccommon-9.0.0a67.dist-info/RECORD +25 -0
- diraccommon-9.0.0a66.dist-info/RECORD +0 -7
- /DIRACCommon/{Utils → Core/Utilities}/DErrno.py +0 -0
- /DIRACCommon/{Utils → Core/Utilities}/__init__.py +0 -0
- {diraccommon-9.0.0a66.dist-info → diraccommon-9.0.0a67.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
""" Utilities to process parametric job definitions and generate
|
|
2
|
+
bunches of parametric jobs. It exposes the following functions:
|
|
3
|
+
|
|
4
|
+
getParameterVectorLength() - to get the total size of the bunch of parametric jobs
|
|
5
|
+
generateParametricJobs() - to get a list of expanded descriptions of all the jobs
|
|
6
|
+
"""
|
|
7
|
+
import re
|
|
8
|
+
|
|
9
|
+
from DIRACCommon.Core.Utilities.ClassAd.ClassAdLight import ClassAd
|
|
10
|
+
from DIRACCommon.Core.Utilities.ReturnValues import S_OK, S_ERROR
|
|
11
|
+
from DIRACCommon.Core.Utilities.DErrno import EWMSJDL
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def __getParameterSequence(nPar, parList=[], parStart=1, parStep=0, parFactor=1):
|
|
15
|
+
if parList:
|
|
16
|
+
if nPar != len(parList):
|
|
17
|
+
return []
|
|
18
|
+
else:
|
|
19
|
+
parameterList = list(parList)
|
|
20
|
+
else:
|
|
21
|
+
# The first parameter must have the same type as the other ones even if not defined explicitly
|
|
22
|
+
parameterList = [parStart * type(parFactor)(1) + type(parStep)(0)]
|
|
23
|
+
for np in range(1, nPar):
|
|
24
|
+
parameterList.append(parameterList[np - 1] * parFactor + parStep)
|
|
25
|
+
|
|
26
|
+
return parameterList
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def getParameterVectorLength(jobClassAd):
|
|
30
|
+
"""Get the length of parameter vector in the parametric job description
|
|
31
|
+
|
|
32
|
+
:param jobClassAd: ClassAd job description object
|
|
33
|
+
:return: result structure with the Value: int number of parameter values, None if not a parametric job
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
nParValues = None
|
|
37
|
+
attributes = jobClassAd.getAttributes()
|
|
38
|
+
for attribute in attributes:
|
|
39
|
+
if attribute.startswith("Parameters"):
|
|
40
|
+
if jobClassAd.isAttributeList(attribute):
|
|
41
|
+
parameterList = jobClassAd.getListFromExpression(attribute)
|
|
42
|
+
nThisParValues = len(parameterList)
|
|
43
|
+
else:
|
|
44
|
+
nThisParValues = jobClassAd.getAttributeInt(attribute)
|
|
45
|
+
if nParValues is not None and nParValues != nThisParValues:
|
|
46
|
+
return S_ERROR(
|
|
47
|
+
EWMSJDL,
|
|
48
|
+
"Different length of parameter vectors: for %s, %s != %d" % (attribute, nParValues, nThisParValues),
|
|
49
|
+
)
|
|
50
|
+
nParValues = nThisParValues
|
|
51
|
+
if nParValues is not None and nParValues <= 0:
|
|
52
|
+
return S_ERROR(EWMSJDL, "Illegal number of job parameters %d" % (nParValues))
|
|
53
|
+
return S_OK(nParValues)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def __updateAttribute(classAd, attribute, parName, parValue):
|
|
57
|
+
# If there is something to do:
|
|
58
|
+
pattern = r"%%\(%s\)s" % parName
|
|
59
|
+
if parName == "0":
|
|
60
|
+
pattern = "%s"
|
|
61
|
+
expr = classAd.get_expression(attribute)
|
|
62
|
+
if not re.search(pattern, expr):
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
pattern = "%%(%s)s" % parName
|
|
66
|
+
if parName == "0":
|
|
67
|
+
pattern = "%s"
|
|
68
|
+
|
|
69
|
+
parValue = parValue.strip()
|
|
70
|
+
if classAd.isAttributeList(attribute):
|
|
71
|
+
parValue = parValue.strip()
|
|
72
|
+
if parValue.startswith("{"):
|
|
73
|
+
parValue = parValue.lstrip("{").rstrip("}").strip()
|
|
74
|
+
|
|
75
|
+
expr = classAd.get_expression(attribute)
|
|
76
|
+
newexpr = expr.replace(pattern, str(parValue))
|
|
77
|
+
classAd.set_expression(attribute, newexpr)
|
|
78
|
+
return True
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def generateParametricJobs(jobClassAd):
|
|
82
|
+
"""Generate a series of ClassAd job descriptions expanding
|
|
83
|
+
job parameters
|
|
84
|
+
|
|
85
|
+
:param jobClassAd: ClassAd job description object
|
|
86
|
+
:return: list of ClassAd job description objects
|
|
87
|
+
"""
|
|
88
|
+
if not jobClassAd.lookupAttribute("Parameters"):
|
|
89
|
+
return S_OK([jobClassAd.asJDL()])
|
|
90
|
+
|
|
91
|
+
result = getParameterVectorLength(jobClassAd)
|
|
92
|
+
if not result["OK"]:
|
|
93
|
+
return result
|
|
94
|
+
nParValues = result["Value"]
|
|
95
|
+
if nParValues is None:
|
|
96
|
+
return S_ERROR(EWMSJDL, "Can not determine the number of job parameters")
|
|
97
|
+
|
|
98
|
+
parameterDict = {}
|
|
99
|
+
attributes = jobClassAd.getAttributes()
|
|
100
|
+
for attribute in attributes:
|
|
101
|
+
for key in ["Parameters", "ParameterStart", "ParameterStep", "ParameterFactor"]:
|
|
102
|
+
if attribute.startswith(key):
|
|
103
|
+
seqID = "0" if "." not in attribute else attribute.split(".")[1]
|
|
104
|
+
parameterDict.setdefault(seqID, {})
|
|
105
|
+
if key == "Parameters":
|
|
106
|
+
if jobClassAd.isAttributeList(attribute):
|
|
107
|
+
parList = jobClassAd.getListFromExpression(attribute)
|
|
108
|
+
if len(parList) != nParValues:
|
|
109
|
+
return S_ERROR(EWMSJDL, "Inconsistent parametric job description")
|
|
110
|
+
parameterDict[seqID]["ParameterList"] = parList
|
|
111
|
+
else:
|
|
112
|
+
if attribute != "Parameters":
|
|
113
|
+
return S_ERROR(EWMSJDL, "Inconsistent parametric job description")
|
|
114
|
+
nPar = jobClassAd.getAttributeInt(attribute)
|
|
115
|
+
if nPar is None:
|
|
116
|
+
value = jobClassAd.get_expression(attribute)
|
|
117
|
+
return S_ERROR(EWMSJDL, f"Inconsistent parametric job description: {attribute}={value}")
|
|
118
|
+
parameterDict[seqID]["Parameters"] = nPar
|
|
119
|
+
else:
|
|
120
|
+
value = jobClassAd.getAttributeInt(attribute)
|
|
121
|
+
if value is None:
|
|
122
|
+
value = jobClassAd.getAttributeFloat(attribute)
|
|
123
|
+
if value is None:
|
|
124
|
+
value = jobClassAd.get_expression(attribute)
|
|
125
|
+
return S_ERROR(f"Illegal value for {attribute} JDL field: {value}")
|
|
126
|
+
parameterDict[seqID][key] = value
|
|
127
|
+
|
|
128
|
+
if "0" in parameterDict and not parameterDict.get("0"):
|
|
129
|
+
parameterDict.pop("0")
|
|
130
|
+
|
|
131
|
+
parameterLists = {}
|
|
132
|
+
for seqID in parameterDict:
|
|
133
|
+
parList = __getParameterSequence(
|
|
134
|
+
nParValues,
|
|
135
|
+
parList=parameterDict[seqID].get("ParameterList", []),
|
|
136
|
+
parStart=parameterDict[seqID].get("ParameterStart", 1),
|
|
137
|
+
parStep=parameterDict[seqID].get("ParameterStep", 0),
|
|
138
|
+
parFactor=parameterDict[seqID].get("ParameterFactor", 1),
|
|
139
|
+
)
|
|
140
|
+
if not parList:
|
|
141
|
+
return S_ERROR(EWMSJDL, "Inconsistent parametric job description")
|
|
142
|
+
|
|
143
|
+
parameterLists[seqID] = parList
|
|
144
|
+
|
|
145
|
+
jobDescList = []
|
|
146
|
+
jobDesc = jobClassAd.asJDL()
|
|
147
|
+
# Width of the sequential parameter number
|
|
148
|
+
zLength = len(str(nParValues - 1))
|
|
149
|
+
for n in range(nParValues):
|
|
150
|
+
newJobDesc = jobDesc
|
|
151
|
+
newJobDesc = newJobDesc.replace("%n", str(n).zfill(zLength))
|
|
152
|
+
newClassAd = ClassAd(newJobDesc)
|
|
153
|
+
for seqID in parameterLists:
|
|
154
|
+
parameter = parameterLists[seqID][n]
|
|
155
|
+
for attribute in newClassAd.getAttributes():
|
|
156
|
+
__updateAttribute(newClassAd, attribute, seqID, str(parameter))
|
|
157
|
+
|
|
158
|
+
for seqID in parameterLists:
|
|
159
|
+
for attribute in ["Parameters", "ParameterStart", "ParameterStep", "ParameterFactor"]:
|
|
160
|
+
if seqID == "0":
|
|
161
|
+
newClassAd.deleteAttribute(attribute)
|
|
162
|
+
else:
|
|
163
|
+
newClassAd.deleteAttribute(f"{attribute}.{seqID}")
|
|
164
|
+
|
|
165
|
+
parameter = parameterLists[seqID][n]
|
|
166
|
+
if seqID == "0":
|
|
167
|
+
attribute = "Parameter"
|
|
168
|
+
else:
|
|
169
|
+
attribute = f"Parameter.{seqID}"
|
|
170
|
+
if isinstance(parameter, str) and parameter.startswith("{"):
|
|
171
|
+
newClassAd.insertAttributeInt(attribute, str(parameter))
|
|
172
|
+
else:
|
|
173
|
+
newClassAd.insertAttributeString(attribute, str(parameter))
|
|
174
|
+
|
|
175
|
+
newClassAd.insertAttributeInt("ParameterNumber", n)
|
|
176
|
+
newJDL = newClassAd.asJDL()
|
|
177
|
+
jobDescList.append(newJDL)
|
|
178
|
+
|
|
179
|
+
return S_OK(jobDescList)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""DIRACCommon WorkloadManagementSystem utilities"""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""DIRACCommon WorkloadManagementSystem utilities"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: DIRACCommon
|
|
3
|
-
Version: 9.0.
|
|
3
|
+
Version: 9.0.0a67
|
|
4
4
|
Summary: Stateless utilities extracted from DIRAC for use by DiracX and other projects
|
|
5
5
|
Project-URL: Homepage, https://github.com/DIRACGrid/DIRAC
|
|
6
6
|
Project-URL: Documentation, https://dirac.readthedocs.io/
|
|
@@ -14,6 +14,8 @@ Classifier: Programming Language :: Python :: 3
|
|
|
14
14
|
Classifier: Topic :: Scientific/Engineering
|
|
15
15
|
Classifier: Topic :: System :: Distributed Computing
|
|
16
16
|
Requires-Python: >=3.11
|
|
17
|
+
Requires-Dist: diraccfg
|
|
18
|
+
Requires-Dist: pydantic>=2.0.0
|
|
17
19
|
Requires-Dist: typing-extensions>=4.0.0
|
|
18
20
|
Provides-Extra: testing
|
|
19
21
|
Requires-Dist: pytest-cov>=4.0.0; extra == 'testing'
|
|
@@ -30,8 +32,11 @@ This package solves the circular dependency issue where DiracX needs DIRAC utili
|
|
|
30
32
|
|
|
31
33
|
## Contents
|
|
32
34
|
|
|
33
|
-
- `DIRACCommon.
|
|
34
|
-
- `DIRACCommon.
|
|
35
|
+
- `DIRACCommon.Core.Utilities.ReturnValues`: DIRAC's S_OK/S_ERROR return value system
|
|
36
|
+
- `DIRACCommon.Core.Utilities.DErrno`: DIRAC error codes and utilities
|
|
37
|
+
- `DIRACCommon.Core.Utilities.ClassAd.ClassAdLight`: JDL parsing utilities
|
|
38
|
+
- `DIRACCommon.WorkloadManagementSystem.DB.JobDBUtils`: Job database utilities
|
|
39
|
+
- `DIRACCommon.WorkloadManagementSystem.Utilities.ParametricJob`: Parametric job utilities
|
|
35
40
|
|
|
36
41
|
## Installation
|
|
37
42
|
|
|
@@ -42,7 +47,7 @@ pip install DIRACCommon
|
|
|
42
47
|
## Usage
|
|
43
48
|
|
|
44
49
|
```python
|
|
45
|
-
from DIRACCommon.
|
|
50
|
+
from DIRACCommon.Core.Utilities.ReturnValues import S_OK, S_ERROR
|
|
46
51
|
|
|
47
52
|
def my_function():
|
|
48
53
|
if success:
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
DIRACCommon/__init__.py,sha256=o31FFvmIiU2Wsc9nfsPZVaXYK9d3KTN0vOa8mZS6x5E,587
|
|
2
|
+
DIRACCommon/Core/__init__.py,sha256=Kv_Rkbm9hOPmHSnTG0_i7QR5Tck8bldITONhsoT2syg,33
|
|
3
|
+
DIRACCommon/Core/Utilities/DErrno.py,sha256=LUaIcKkjuioTMO3O7H9T9Pk5pHUS63Nzx3FcaP40n5c,7998
|
|
4
|
+
DIRACCommon/Core/Utilities/JDL.py,sha256=z4RID730tbCmbgldKfhSFc9ADfXDhUfjaBG8RpuK2Bs,6724
|
|
5
|
+
DIRACCommon/Core/Utilities/List.py,sha256=AahQrlQqfnh8tyA1GjGqYJfo_3v5N77IQreA8VCNXks,3758
|
|
6
|
+
DIRACCommon/Core/Utilities/ReturnValues.py,sha256=YDZEZrYLtI_Aa8qTnHX633F1cRupQ_UTAnI7aSlf0sI,8733
|
|
7
|
+
DIRACCommon/Core/Utilities/StateMachine.py,sha256=5Pwpc2wmCgb6PwyUH2qe9HZwBMyzkhFTBA7cixso1Sg,6767
|
|
8
|
+
DIRACCommon/Core/Utilities/TimeUtilities.py,sha256=wXuYIwECbLSFdVoNM0iSYoCrz6_iL-JrMV1yVv3FloA,9026
|
|
9
|
+
DIRACCommon/Core/Utilities/__init__.py,sha256=hwOqqYwQDINF-D3eKKBC1r-B_jEnQ5ZSdJvc7rIv_fY,56
|
|
10
|
+
DIRACCommon/Core/Utilities/ClassAd/ClassAdLight.py,sha256=7450ECzxnJQpIjzbaE-uFp3ISE55iL6YM-TRqyebZTY,9597
|
|
11
|
+
DIRACCommon/Core/Utilities/ClassAd/__init__.py,sha256=z0yRe-wRxIHE-Sp3tnyC37S6z38dZHCxuqf3ZV1OyzQ,40
|
|
12
|
+
DIRACCommon/WorkloadManagementSystem/__init__.py,sha256=XMOUD0OcPVo-mjuA0vU-mbtf9K0kBMy5I5sELrX3HEs,53
|
|
13
|
+
DIRACCommon/WorkloadManagementSystem/Client/JobStatus.py,sha256=lBfPYa_RRjJlWEU5eqrbWFaSl1081CqSDjhI6B7-qeA,2813
|
|
14
|
+
DIRACCommon/WorkloadManagementSystem/Client/__init__.py,sha256=ssMppR0P3iXlUaqWPjl1Y5AlQ6LgUAsRa9-5lVkBsL0,60
|
|
15
|
+
DIRACCommon/WorkloadManagementSystem/Client/JobState/JobManifest.py,sha256=E3DVRzAHUFAFa9baqEbAMr-4cu6tTXuVRVdl7XgUX7I,7380
|
|
16
|
+
DIRACCommon/WorkloadManagementSystem/Client/JobState/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
+
DIRACCommon/WorkloadManagementSystem/DB/JobDBUtils.py,sha256=YU97uk0fjwYN6O8nkD6XjnZ7k9ovhSLYjytqI3oLRfU,5777
|
|
18
|
+
DIRACCommon/WorkloadManagementSystem/DB/__init__.py,sha256=CXWy4bdKeG6ml9T5r8-E7EyfDBNE79I_bs13qYI7yY8,56
|
|
19
|
+
DIRACCommon/WorkloadManagementSystem/Utilities/JobModel.py,sha256=kpvsxQnR-j9Y9I38qUWLD7coFRssLwtJCtSNAbjFh1Y,8973
|
|
20
|
+
DIRACCommon/WorkloadManagementSystem/Utilities/JobStatusUtility.py,sha256=Kf4o1bp25JLsRb-Vsc4NuM6w1Io2hg_ALtIyqBk-Qhw,3628
|
|
21
|
+
DIRACCommon/WorkloadManagementSystem/Utilities/ParametricJob.py,sha256=iYd29TgGXZk31pQLPw_frIhcmZB9X-RmuDmIRxzgiww,7405
|
|
22
|
+
DIRACCommon/WorkloadManagementSystem/Utilities/__init__.py,sha256=XMOUD0OcPVo-mjuA0vU-mbtf9K0kBMy5I5sELrX3HEs,53
|
|
23
|
+
diraccommon-9.0.0a67.dist-info/METADATA,sha256=NA1PLIfXlFQ4tWmuf1m_7mSvSlHBuHVudhsOIC_VRDs,2575
|
|
24
|
+
diraccommon-9.0.0a67.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
25
|
+
diraccommon-9.0.0a67.dist-info/RECORD,,
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
DIRACCommon/__init__.py,sha256=o31FFvmIiU2Wsc9nfsPZVaXYK9d3KTN0vOa8mZS6x5E,587
|
|
2
|
-
DIRACCommon/Utils/DErrno.py,sha256=LUaIcKkjuioTMO3O7H9T9Pk5pHUS63Nzx3FcaP40n5c,7998
|
|
3
|
-
DIRACCommon/Utils/ReturnValues.py,sha256=9lEFPeu5MV1zCWTOgvd2779QMZeCKSnTW0LWa873eBE,8724
|
|
4
|
-
DIRACCommon/Utils/__init__.py,sha256=hwOqqYwQDINF-D3eKKBC1r-B_jEnQ5ZSdJvc7rIv_fY,56
|
|
5
|
-
diraccommon-9.0.0a66.dist-info/METADATA,sha256=0ci1O9p3PmrdZAmamil4OG-rXoZLygLuLXJuqsd3JJU,2248
|
|
6
|
-
diraccommon-9.0.0a66.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
7
|
-
diraccommon-9.0.0a66.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|