1
+ """ ClassAd Class - a light purely Python representation of the
2
+ Condor ClassAd library.
3
+ """
4
+
5
+
6
+ class ClassAd :
7
+ def __init__ (self , jdl ):
8
+ """ClassAd constructor from a JDL string"""
9
+ self .contents = {}
10
+ result = self .__analyse_jdl (jdl )
11
+ if result :
12
+ self .contents = result
13
+
14
+ def __analyse_jdl (self , jdl , index = 0 ):
15
+ """Analyse one [] jdl enclosure"""
16
+
17
+ jdl = jdl .strip ()
18
+
19
+ # Strip all the blanks first
20
+ # temp = jdl.replace(' ','').replace('\n','')
21
+ temp = jdl
22
+
23
+ result = {}
24
+
25
+ if temp [0 ] != "[" or temp [- 1 ] != "]" :
26
+ print ("Invalid JDL: it should start with [ and end with ]" )
27
+ return result
28
+
29
+ # Parse the jdl string now
30
+ body = temp [1 :- 1 ]
31
+ index = 0
32
+ namemode = 1
33
+ valuemode = 0
34
+ while index < len (body ):
35
+ if namemode :
36
+ ind = body .find ("=" , index )
37
+ if ind != - 1 :
38
+ name = body [index :ind ]
39
+ index = ind + 1
40
+ valuemode = 1
41
+ namemode = 0
42
+ else :
43
+ break
44
+ elif valuemode :
45
+ ind1 = body .find ("[" , index )
46
+ ind2 = body .find (";" , index )
47
+ if ind1 != - 1 and ind1 < ind2 :
48
+ value , newind = self .__find_subjdl (body , ind1 )
49
+ elif ind1 == - 1 and ind2 == - 1 :
50
+ value = body [index :]
51
+ newind = len (body )
52
+ else :
53
+ if index == ind2 :
54
+ return {}
55
+ else :
56
+ value = body [index :ind2 ]
57
+ newind = ind2 + 1
58
+
59
+ result [name .strip ()] = value .strip ().replace ("\n " , "" )
60
+ index = newind
61
+ valuemode = 0
62
+ namemode = 1
63
+
64
+ return result
65
+
66
+ def __find_subjdl (self , body , index ):
67
+ """Find a full [] enclosure starting from index"""
68
+ result = ""
69
+ if body [index ] != "[" :
70
+ return (result , 0 )
71
+
72
+ depth = 0
73
+ ind = index
74
+ while depth < 10 :
75
+ ind1 = body .find ("]" , ind + 1 )
76
+ ind2 = body .find ("[" , ind + 1 )
77
+ if ind2 != - 1 and ind2 < ind1 :
78
+ depth += 1
79
+ ind = ind2
80
+ else :
81
+ if depth > 0 :
82
+ depth -= 1
83
+ ind = ind1
84
+ else :
85
+ result = body [index : ind1 + 1 ]
86
+ if body [ind1 + 1 ] == ";" :
87
+ return (result , ind1 + 2 )
88
+ return result , 0
89
+
90
+ return result , 0
91
+
92
+ def insertAttributeInt (self , name , attribute ):
93
+ """Insert a named integer attribute"""
94
+
95
+ self .contents [name ] = str (attribute )
96
+
97
+ def insertAttributeBool (self , name , attribute ):
98
+ """Insert a named boolean attribute"""
99
+
100
+ if attribute :
101
+ self .contents [name ] = "true"
102
+ else :
103
+ self .contents [name ] = "false"
104
+
105
+ def insertAttributeString (self , name , attribute ):
106
+ """Insert a named string attribute"""
107
+
108
+ self .contents [name ] = '"' + str (attribute ) + '"'
109
+
110
+ def insertAttributeVectorString (self , name , attributelist ):
111
+ """Insert a named string list attribute"""
112
+
113
+ tmp = ['"' + x + '"' for x in attributelist ]
114
+ tmpstr = "," .join (tmp )
115
+ self .contents [name ] = "{" + tmpstr + "}"
116
+
117
+ def insertAttributeVectorInt (self , name , attributelist ):
118
+ """Insert a named string list attribute"""
119
+
120
+ tmp = [str (x ) for x in attributelist ]
121
+ tmpstr = "," .join (tmp )
122
+ self .contents [name ] = "{" + tmpstr + "}"
123
+
124
+ def insertAttributeVectorStringList (self , name , attributelist ):
125
+ """Insert a named list of string lists"""
126
+
127
+ listOfLists = []
128
+ for stringList in attributelist :
129
+ # tmp = map ( lambda x : '"' + x + '"', stringList )
130
+ tmpstr = "," .join (stringList )
131
+ listOfLists .append ("{" + tmpstr + "}" )
132
+ self .contents [name ] = "{" + "," .join (listOfLists ) + "}"
133
+
134
+ def lookupAttribute (self , name ):
135
+ """Check the presence of the given attribute"""
136
+
137
+ return name in self .contents
138
+
139
+ def set_expression (self , name , attribute ):
140
+ """Insert a named expression attribute"""
141
+
142
+ self .contents [name ] = str (attribute )
143
+
144
+ def get_expression (self , name ):
145
+ """Get expression corresponding to a named attribute"""
146
+
147
+ if name in self .contents :
148
+ if isinstance (self .contents [name ], int ):
149
+ return str (self .contents [name ])
150
+ return self .contents [name ]
151
+ return ""
152
+
153
+ def isAttributeList (self , name ):
154
+ """Check if the given attribute is of the List type"""
155
+ attribute = self .get_expression (name ).strip ()
156
+ return attribute .startswith ("{" )
157
+
158
+ def getListFromExpression (self , name ):
159
+ """Get a list of strings from a given expression"""
160
+
161
+ tempString = self .get_expression (name ).strip ()
162
+ listMode = False
163
+ if tempString .startswith ("{" ):
164
+ tempString = tempString [1 :- 1 ]
165
+ listMode = True
166
+
167
+ tempString = tempString .replace (" " , "" ).replace ("\n " , "" )
168
+ if tempString .find ("{" ) < 0 :
169
+ if not listMode :
170
+ tempString = tempString .replace ('"' , "" )
171
+ if not tempString :
172
+ return []
173
+ return tempString .split ("," )
174
+
175
+ resultList = []
176
+ while tempString :
177
+ if tempString .find ("{" ) == 0 :
178
+ end = tempString .find ("}" )
179
+ resultList .append (tempString [: end + 1 ])
180
+ tempString = tempString [end + 1 :]
181
+ if tempString .startswith ("," ):
182
+ tempString = tempString [1 :]
183
+ elif tempString .find ('"' ) == 0 :
184
+ end = tempString [1 :].find ('"' )
185
+ resultList .append (tempString [1 : end + 1 ])
186
+ tempString = tempString [end + 2 :]
187
+ if tempString .startswith ("," ):
188
+ tempString = tempString [1 :]
189
+ else :
190
+ end = tempString .find ("," )
191
+ if end < 0 :
192
+ resultList .append (tempString .replace ('"' , "" ).replace (" " , "" ))
193
+ break
194
+ else :
195
+ resultList .append (tempString [:end ].replace ('"' , "" ).replace (" " , "" ))
196
+ tempString = tempString [end + 1 :]
197
+
198
+ return resultList
199
+
200
+ def getDictionaryFromSubJDL (self , name ):
201
+ """Get a dictionary of the JDL attributes from a subsection"""
202
+
203
+ tempList = self .get_expression (name )[1 :- 1 ]
204
+ resDict = {}
205
+ for item in tempList .split (";" ):
206
+ if len (item .split ("=" )) == 2 :
207
+ resDict [item .split ("=" )[0 ].strip ()] = item .split ("=" )[1 ].strip ().replace ('"' , "" )
208
+ else :
209
+ return {}
210
+
211
+ return resDict
212
+
213
+ def deleteAttribute (self , name ):
214
+ """Delete a named attribute"""
215
+
216
+ if name in self .contents :
217
+ del self .contents [name ]
218
+ return 1
219
+ return 0
220
+
221
+ def isOK (self ):
222
+ """Check the JDL validity - to be defined"""
223
+
224
+ if self .contents :
225
+ return 1
226
+ return 0
227
+
228
+ def asJDL (self ):
229
+ """Convert the JDL description into a string"""
230
+
231
+ result = []
232
+ for name , value in sorted (self .contents .items ()):
233
+ if value [0 :1 ] == "{" :
234
+ result += [4 * " " + name + " = \n " ]
235
+ result += [8 * " " + "{\n " ]
236
+ strings = value [1 :- 1 ].split ("," )
237
+ for st in strings :
238
+ result += [12 * " " + st .strip () + ",\n " ]
239
+ result [- 1 ] = result [- 1 ][:- 2 ]
240
+ result += ["\n " + 8 * " " + "};\n " ]
241
+ elif value [0 :1 ] == "[" :
242
+ tempad = ClassAd (value )
243
+ tempjdl = tempad .asJDL () + ";"
244
+ lines = tempjdl .split ("\n " )
245
+ result += [4 * " " + name + " = \n " ]
246
+ for line in lines :
247
+ result += [8 * " " + line + "\n " ]
248
+
249
+ else :
250
+ result += [4 * " " + name + " = " + str (value ) + ";\n " ]
251
+ if result :
252
+ result [- 1 ] = result [- 1 ][:- 1 ]
253
+ return "[ \n " + "" .join (result ) + "\n ]"
254
+
255
+ def getAttributeString (self , name ):
256
+ """Get String type attribute value"""
257
+ value = ""
258
+ if self .lookupAttribute (name ):
259
+ value = self .get_expression (name ).replace ('"' , "" )
260
+ return value
261
+
262
+ def getAttributeInt (self , name ):
263
+ """Get Integer type attribute value"""
264
+ value = None
265
+ if self .lookupAttribute (name ):
266
+ try :
267
+ value = int (self .get_expression (name ).replace ('"' , "" ))
268
+ except Exception :
269
+ value = None
270
+ return value
271
+
272
+ def getAttributeBool (self , name ):
273
+ """Get Boolean type attribute value"""
274
+ if not self .lookupAttribute (name ):
275
+ return False
276
+
277
+ value = self .get_expression (name ).replace ('"' , "" )
278
+ return value .lower () == "true"
279
+
280
+ def getAttributeFloat (self , name ):
281
+ """Get Float type attribute value"""
282
+ value = None
283
+ if self .lookupAttribute (name ):
284
+ try :
285
+ value = float (self .get_expression (name ).replace ('"' , "" ))
286
+ except Exception :
287
+ value = None
288
+ return value
289
+
290
+ def getAttributes (self ) -> list [str ]:
291
+ """Get the list of all the attribute names
292
+
293
+ :return: list of names as strings
294
+ """
295
+ return list (self .contents )
0 commit comments