00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 __facility__ = "Online"
00011 __abstract__ = "Script engine suite base class"
00012 __author__ = "S. Tuvi <stuvi@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online"
00013 __date__ = "2005/07/15 00:08:27"
00014 __updated__ = "$Date: 2006/04/04 02:27:50 $"
00015 __version__ = "$Revision: 1.8 $"
00016 __release__ = "$Name: HEAD $"
00017 __credits__ = "SLAC"
00018
00019 import LICOS.copyright_SLAC
00020
00021 from threading import Event
00022 import logging as log
00023
00024 from LICOS.scriptEngine.FSM import FSM
00025 from LICOS.scriptEngine import rcUtil
00026 from LICOS.lib.scriptEngine.seAppBase import seAppBase
00027
00028 class seSuiteBase(FSM):
00029 """!\brief Script engine base class for suites.
00030
00031 """
00032
00033
00034 __suiteStack = []
00035
00036 def __init__(self, common):
00037 """!\brief seSuiteBase constructor
00038
00039 \param common ScriptEngineCommon instance
00040 """
00041 FSM.__init__(self, 'SUITE STOPPED', None)
00042 self.set_default_transition( self.error, None)
00043 self.add_transition ('SETUP', 'SUITE STOPPED', self.seSetup, 'SUITE IN PROGRESS')
00044 self.add_transition ('RUN', 'SUITE IN PROGRESS', self.seRun, 'SUITE COMPLETE')
00045 self.add_transition ('STOP_RUN', 'SUITE COMPLETE', self.seStopRun, 'SUITE STOPPED')
00046 self.add_transition ('ABORT', 'SUITE IN PROGRESS', self.seAbort, 'SUITE STOPPED')
00047 self.add_transition ('PAUSE', 'SUITE IN PROGRESS', self.sePause, 'SUITE PAUSED')
00048 self.add_transition ('RESUME', 'SUITE PAUSED', self.seResume, 'SUITE IN PROGRESS')
00049
00050 self.common = common
00051 self.prefs = self.common.preferences()
00052
00053 self.gui = common.getGUI()
00054
00055 self.__suiteStart = None
00056 self.__stopRequested = False
00057 self.__parentSuite = None
00058 self.__scriptSeq = 0
00059
00060 self.__script = None
00061 self.__resumeEvent = Event()
00062 self.__paused = False
00063 self.__suiteID = None
00064
00065 def getRunSequence(self):
00066 """!\brief Return the order of transitions for this type of application.
00067
00068 \return A list of transitions
00069 """
00070 return ['SETUP', 'RUN', 'STOP_RUN']
00071
00072 def doAbort(self):
00073 """!\brief Request stop of execution.
00074
00075 \return Result of the transition
00076 """
00077 if self.__paused:
00078 status = self.doResume()
00079 if status is not None: return status
00080 if self.get_transition("ABORT", self.current_state)[1] is not None:
00081 return self.process('ABORT')
00082
00083 def doPause(self):
00084 """!\brief Request pause of execution.
00085
00086 \return Result of the transition
00087 """
00088 if self.get_transition("PAUSE", self.current_state)[1] is not None:
00089 return self.process('PAUSE')
00090
00091 def doResume(self):
00092 """!\brief Request resume of execution.
00093
00094 \return Result of the transition
00095 """
00096 if self.get_transition("RESUME", self.current_state)[1] is not None:
00097 return self.process('RESUME')
00098
00099 def error(self):
00100 """!\brief This method is called when an undefined transition is requested.
00101
00102 """
00103 log.error(self.__class__.__name__ + " - Undefined transition: %s from state %s" % \
00104 (self.input_symbol, self.current_state))
00105
00106 def seSetup(self):
00107 """!\brief SETUP transition method
00108
00109 Calls self.setup()
00110
00111 \return None for success or
00112 False if there is an exception or
00113 status returned by the suite.
00114 """
00115 self.__paused = False
00116 self.__stopRequested = False
00117 self.__scriptSeq = 0
00118 self.__updateGUI()
00119
00120
00121
00122
00123 self.__suiteStart = suiteStart(self.common)
00124 self.__suiteStart.setParentSuite(self)
00125
00126 return self.setup()
00127
00128 def seRun(self):
00129 """!\brief RUN transition method
00130
00131 Calls self.run()
00132
00133 \return None for success or
00134 False if there is an exception or
00135 status returned by the suite.
00136 """
00137 self.__updateGUI()
00138
00139 self.scriptRun(self.__suiteStart)
00140 return self.run()
00141
00142 def sePause(self):
00143 """!\brief PAUSE transition method
00144
00145 Calls self.pause()
00146
00147 \return None for success or
00148 False if there is an exception or
00149 status returned by the suite.
00150 """
00151 if self.__resumeEvent.isSet():
00152 self.__resumeEvent.clear()
00153 self.gui.execGUImethodNR(self.gui.updateState, "PAUSING SUITE")
00154 if self.__script is not None and 'doPause' in dir(self.__script):
00155 status = self.__script.doPause()
00156 if status is not None: return status
00157 return self.pause()
00158
00159 def seResume(self):
00160 """!\brief RESUME transition method
00161
00162 Calls self.resume()
00163
00164 \return None for success or
00165 False if there is an exception or
00166 status returned by the suite.
00167 """
00168 if self.__paused:
00169 if self.__script is not None and 'doResume' in dir(self.__script):
00170 self.__script.doResume()
00171 self.__resumeEvent.set()
00172 return self.resume()
00173
00174 def seStopRun(self):
00175 """!\brief STOP_RUN transition method
00176
00177 Calls self.stopRun()
00178
00179 \return None for success or
00180 False if there is an exception or
00181 status returned by the suite.
00182 """
00183 if self.__paused:
00184 self.process('RESUME')
00185 self.__updateGUI()
00186 status = self.stopRun()
00187 self.__suiteID = None
00188 return status
00189
00190
00191 def seAbort(self):
00192 """!\brief ABORT transition method
00193
00194 Calls self.abort()
00195
00196 \return None for success or
00197 False if there is an exception or
00198 status returned by the suite.
00199 """
00200 self.setStopRequested()
00201 if self.__script is not None and 'doAbort' in dir(self.__script):
00202 self.__script.doAbort()
00203 return self.abort()
00204
00205 def __updateGUI(self):
00206 """!\brief Update the state of the run on the GUI.
00207
00208 """
00209 if self.gui is not None:
00210 self.gui.execGUImethodNR(self.gui.updateState, self.current_state)
00211
00212 def setup(self):
00213 """!\brief Transition method to be overridden by the suite.
00214
00215 """
00216 pass
00217
00218 def stopRun(self):
00219 """!\brief Transition method to be overridden by the suite.
00220
00221 """
00222 pass
00223
00224 def pause(self):
00225 """!\brief Transition method to be overridden by the suite.
00226
00227 """
00228 pass
00229
00230 def resume(self):
00231 """!\brief Transition method to be overridden by the suite.
00232
00233 """
00234 pass
00235
00236 def abort(self):
00237 """!\brief Transition method to be overridden by the suite.
00238
00239 """
00240 pass
00241
00242 def scriptLoad(self, script, *args, **kwargs):
00243 """!\brief Load and instantiate an seAppBase or seSuiteBase based script.
00244
00245 \param script Script module name or Python source path
00246 \param args Positional arguments passed to the script
00247 \param kwargs Keyword arguments passed to the script
00248
00249 \return Instantiated script object
00250 """
00251 (self.__module, self.__filename,
00252 self.__script) = rcUtil.scriptLoad(script, self.common,
00253 0, *args, **kwargs)
00254 if self.__script is not None:
00255 self.__script.setParentSuite(self)
00256 return self.__script
00257
00258 def scriptRun(self, script=None):
00259 """!\brief Start the run of the specified script.
00260
00261 \param script Instantiated script object.
00262 If None, the last instantiated script is used.
00263 """
00264 if script == None:
00265 script = self.__script
00266 else:
00267 self.__script = script
00268 self.__scriptSeq += 1
00269
00270 log.debug("script subclass: %s" % isinstance(script, seSuiteBase))
00271 if isinstance(script, seSuiteBase):
00272 script.setSuiteID(self.getSuiteID())
00273
00274 self.__resumeEvent.set()
00275 rcUtil.scriptRun(script)
00276 if self.isPauseRequested():
00277 self.__updateGUI()
00278 self.setPaused(True)
00279 self.__resumeEvent.wait()
00280 self.setPaused(False)
00281
00282 def getName(self):
00283 """!\brief Retrieve the class name of the script.
00284
00285 \return Name of the script class
00286 """
00287 return self.__class__.__name__
00288
00289 def getScript(self):
00290 """!\brief Retrieve the script object.
00291
00292 \return Script object instance.
00293 """
00294 return self.__script
00295
00296 def getType(self):
00297 """!\brief Return the type of test based on this class.
00298
00299 Used for logging purposes.
00300
00301 \return Test type
00302 """
00303 return 'Suite'
00304
00305 def isStopRequested(self):
00306 """!\brief Is stop requested?
00307
00308 \return Boolean flag indicating whether a stop was requested
00309 """
00310 return self.__stopRequested
00311
00312 def setStopRequested(self):
00313 """!\brief Set the stop requested flag.
00314
00315 """
00316 self.__stopRequested = True
00317
00318 def isPauseRequested(self):
00319 """!\brief Is pause requested?
00320
00321 \return Boolean flag indicating whether a pause was requested
00322 """
00323 return not self.__resumeEvent.isSet()
00324
00325 def isPaused(self):
00326 """!\brief Retrieve the paused status of the script.
00327
00328 \param paused Boolean indicating whether the script is paused or not
00329 """
00330 return self.__paused
00331
00332 def setPaused(self, paused):
00333 """!\brief Mark the script and its parent suites as paused or unpaused.
00334
00335 \param paused Boolean indicating whether the script is paused or not
00336 """
00337 self.__paused = paused
00338 if self.__parentSuite is not None:
00339 self.__parentSuite.setPaused(paused)
00340
00341 def setParentSuite(self, suite):
00342 """!\brief Set the parent suite instance.
00343
00344 \param Suite instance
00345 """
00346 self.__parentSuite = suite
00347
00348 def getParentSuite(self):
00349 """!\brief Retrieve the parent suite instance.
00350
00351 \return Suite instance
00352 """
00353 return self.__parentSuite
00354
00355 def getParentSuiteName(self):
00356 """!\brief Retrieve the parent suite name.
00357
00358 \return Parent suite name.
00359 """
00360 if self.__parentSuite is not None:
00361 return self.__parentSuite.getName()
00362
00363 def isRunFromSuite(self):
00364 """!\brief Check if the script is being run from a suite.
00365
00366 \return True If the script is being run from a suite,
00367 False otherwise.
00368 """
00369 return self.__parentSuite is not None
00370
00371 def getScriptSequence(self):
00372 """!\brief Retrieve the sequence number for the running suite script.
00373
00374 The script sequence is incremented for each scriptRun called in the suite.
00375 This method is provided so that the suite author and the script engine
00376 can keep track of which script is the first script being run (which will
00377 have a script sequence of 1).
00378
00379 \return Suite script sequence
00380 """
00381 return self.__scriptSeq
00382
00383 def getSuiteID(self):
00384 """!\brief Retrieve the suite identifier
00385
00386 As an aid to linking runs in suites together, a LICOS activity has
00387 the concept of a suite identifier. This number is identically the
00388 runID of the first run of a suite (which is implemented in
00389 seSuiteBase.py).
00390
00391 \return Suite identifier (integer string)
00392 """
00393 return self.__suiteID
00394
00395 def setSuiteID(self, suiteID):
00396 """!\brief Set the suite identifier
00397
00398 \param suiteID Suite identifier (integer or numeric string)
00399 """
00400 self.__suiteID = str(suiteID)
00401
00402 def setSessionVar(self, key, value):
00403 """!\brief Set a session variable.
00404
00405 Do not use variable names beginning
00406 with the underscore ('_') character since these are reserved for ScriptEngine
00407 """
00408 sessionVars = self.common.getDBN()
00409 if sessionVars is not None:
00410 sessionVars[key] = value
00411 else:
00412 raise RuntimeError, "Database node does not exist"
00413
00414 def getSessionVar(self, key):
00415 """!\brief Retrieve the values of the session variable indicated by \a key.
00416
00417 \return Session variable value
00418 """
00419 sessionVars = self.common.getDBN()
00420 if sessionVars is not None and sessionVars.has_key(key):
00421 return sessionVars[key]
00422 else:
00423 return None
00424
00425 class suiteStart(seAppBase):
00426 """!\brief Dummy run to indicate that a suite has started
00427 """
00428 def __init__(self, common, fromVal=None, toVal=None):
00429 """!\brief suiteStart constructor.
00430
00431 \param fromVal from value
00432 \param toVal to value
00433 """
00434 seAppBase.__init__(self, common)
00435 self.__fromVal = fromVal
00436 self.__toVal = toVal
00437
00438 def setup(self):
00439 """!\brief SETUP transition method.
00440
00441 \return Transition result
00442 """
00443
00444 return None
00445
00446 def teardown(self):
00447 """!\brief START_RUN transition method
00448
00449 Sets the suite identifier for the controlling suite
00450 """
00451 self.getParentSuite().setSuiteID(self.runId)
00452
00453 def stopRun(self):
00454 """!\brief STOP_RUN transition method
00455
00456 \return Transition result
00457 """
00458 self.setCompletionStatus(self.COMPL_STATUS_PASSED)
00459 return None