Module EDPlugin
[hide private]
[frames] | no frames]

Source Code for Module EDPlugin

  1  # coding: utf8 
  2  # 
  3  #    Project: The EDNA Kernel 
  4  #             http://www.edna-site.org 
  5  # 
  6  #    Copyright (C) 2008-2012 European Synchrotron Radiation Facility 
  7  #                            Grenoble, France 
  8  # 
  9  #    Principal authors: Marie-Francoise Incardona (incardon@esrf.fr) 
 10  #                       Olof Svensson (svensson@esrf.fr)  
 11  #                       Jérôme Kieffer (Kieffer@esrf.fr) 
 12  # 
 13  #    This program is free software: you can redistribute it and/or modify 
 14  #    it under the terms of the GNU Lesser General Public License as published 
 15  #    by the Free Software Foundation, either version 3 of the License, or 
 16  #    (at your option) any later version. 
 17  # 
 18  #    This program is distributed in the hope that it will be useful, 
 19  #    but WITHOUT ANY WARRANTY; without even the implied warranty of 
 20  #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 21  #    GNU Lesser General Public License for more details. 
 22  # 
 23  #    You should have received a copy of the GNU General Public License 
 24  #    and the GNU Lesser General Public License  along with this program.   
 25  #    If not, see <http://www.gnu.org/licenses/>. 
 26  # 
 27   
 28  __authors__ = ["Marie-Francoise Incardona", "Olof Svensson", "Jérôme Kieffer"] 
 29  __contact__ = "svensson@esrf.fr" 
 30  __license__ = "LGPLv3+" 
 31  __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" 
 32   
 33  import os, tempfile, stat, types 
 34   
 35  from EDSlot                import EDSlot 
 36  from EDUtilsPath           import EDUtilsPath 
 37  from EDConfiguration       import EDConfiguration 
 38  from EDConfigurationStatic import EDConfigurationStatic 
 39  from EDUtilsFile           import EDUtilsFile 
 40  from EDStatus              import EDStatus 
 41  from EDAction              import EDAction 
 42  from EDDecorator           import deprecated 
 43  from XSDataCommon          import XSDataResult 
44 45 46 -class EDPlugin(EDAction):
47 """ 48 This is the EDNA plugin main class 49 An EDNA plugin class: 50 - is a configurable entity 51 - has a base name (<date>-<random number>-<base name>) 52 - handles input/output data (setter, getter, checker) 53 - has warning and error messages 54 - has a base and a working directory (both are configurable) 55 The working directory is the folder from which the plugin is launched 56 and should contain all associated files with the plugin execution (edna xml input/output, 3rd party output files) 57 The base directory is the parent directory of the working directory. 58 Example: the working directory of a control plugin is the base directory of the plugins that it invokes, 59 i.e. the plugins working directories has the control plugin working directory as parent. 60 - defines the method that generates an executive summary (user-related output summary) that sub-classes should implement 61 """ 62 CONF_BASE_DIR_LABEL = "baseDirectory" 63 CONF_WORKING_DIR_LABEL = "workingDirectory" 64 CONF_TIME_OUT = "timeOut" 65 CONF_WRITE_XML_INPUT_OUTPUT = "writeXMLInputOutput" 66 CONF_WRITE_XML_OUTPUT = "writeXMLOutput" 67 CONF_WRITE_XML_INPUT = "writeXMLInput" 68
69 - def __init__ (self):
70 """ 71 Initializes plugin related attributes described above 72 """ 73 EDAction.__init__(self) 74 self.__xsPluginItem = None 75 self.__dictXSDataInputClass = {} 76 self.__dictXSDataInput = {} 77 self.__dictXSDataOutput = {} 78 self.__strDefaultInputDataKey = "defaultInputData" 79 self.__strDefaultOutputDataKey = "defaultOutputData" 80 self.__edSlotExportDataOutput = EDSlot() 81 self.__strBaseDirectory = None 82 self.__strWorkingDirectory = None 83 self.__strBaseName = None 84 self.__listExecutiveSummaryLines = [] 85 self.__strExecutiveSummarySeparator = "-" * 80 86 self.__listErrorMessages = [] 87 self.__listWarningMessages = [] 88 self.__isRequiredToHaveConfiguration = False 89 self.__bWriteDataXMLInputOutput = True 90 self.__bWriteDataXMLOutput = True 91 self.__bWriteDataXMLInput = True 92 self.__strPluginId = "%s-%08i" % (self.getClassName(), self.getId()) 93 self.strPathDataInput = None 94 self.strPathDataOutput = None 95 self.__bUseWarningInsteadOfError = False 96 self.__edConfiguration = EDConfigurationStatic()
97 98
99 - def preProcess(self, _edObject=None):
100 """ 101 Writes xml data input in the working dir (if required) 102 Connects a slot for generating the executive summary after the plugin execution 103 Connects a slot for checking output data to the finally process 104 Initialize the base directory 105 Configures the plugin 106 Checks the input data 107 """ 108 EDAction.preProcess(self, _edObject) 109 self.DEBUG("EDPlugin.preProcess") 110 self.connectPostProcess(self.exportDataOutput) 111 if self.__bWriteDataXMLInputOutput: 112 if self.__bWriteDataXMLInput: 113 self.connectPreProcess(self.writeDataInput) 114 self.connectPostProcess(self.generateExecutiveSummary) 115 self.connectFinallyProcess(self.checkDataOutput) 116 if (self.__strBaseName is None): 117 self.setBaseName(self.createBaseName()) 118 EDStatus.tellRunning(self.__strPluginId) 119 self.connectFinallyProcess(self.tellFinished) 120 self.checkParameters()
121 122
123 - def tellFinished(self, _edObject=None):
124 """ 125 Tell EDStatus that the plugin has finished, either in success either in error 126 """ 127 if self.isFailure(): 128 EDStatus.tellFailure(self.__strPluginId) 129 else: 130 EDStatus.tellSuccess(self.__strPluginId)
131
132 - def checkDataOutput(self, _edObject=None):
133 """ 134 Checks if output data is available, if not issues a warning and sets an empty XSDataResult as output data 135 Writes xml data output in the working dir (if required) 136 """ 137 EDAction.finallyProcess(self, _edObject) 138 if self.__dictXSDataOutput == {}: 139 strWarningMessage = "Output data for plugin %s not set, using XSDataResult as output" % self.getPluginName() 140 self.WARNING(strWarningMessage) 141 self.addWarningMessage(strWarningMessage) 142 self.setDataOutput(XSDataResult()) 143 if self.__bWriteDataXMLInputOutput: 144 if self.__bWriteDataXMLOutput: 145 self.writeDataOutput()
146 147
148 - def synchronize(self):
149 """ 150 This method calls EDAction.synchronize and if a time-out occurs an error message 151 is added to the list of error messages. 152 """ 153 EDAction.synchronize(self) 154 if self.isTimeOut(): 155 strErrorMessage = "Timeout when waiting for %s to terminate." % self.getClassName() 156 self.addErrorMessage(strErrorMessage)
157 158 @deprecated
159 - def setConfiguration(self, _xsPluginItem):
160 """ 161 Receives a Plugin Configuration as XSPluginItem or python dict from the application. 162 """ 163 self.DEBUG("EDPlugin.setConfiguration") 164 self.__edConfiguration = EDConfiguration() 165 if isinstance(_xsPluginItem, dict): 166 self.__edConfiguration[self.getPluginName()] = _xsPluginItem 167 else: 168 self.__edConfiguration.setXSConfigurationItem(_xsPluginItem)
169 170 171 @deprecated
172 - def getConfiguration(self):
173 """ 174 Gets the Plugin Configuration as an XSPluginItem 175 """ 176 self.DEBUG("EDPlugin.getConfiguration") 177 return self.__edConfiguration.getXSConfigurationItem(self.getPluginName())
178 configuration = property(getConfiguration, setConfiguration) 179 180
181 - def getConfig(self):
182 """ 183 Gets the Plugin Configuration as a dictionary 184 """ 185 self.DEBUG("EDPlugin.getConfig") 186 return self.__edConfiguration.get(self.getPluginName(), {})
187
188 - def setConfig(self, _dict, _bLocal = False):
189 """ 190 Receives a dictionary (Plugin Configuration) from the application. 191 """ 192 self.DEBUG("EDPlugin.setConfiguration") 193 if _bLocal: 194 self.__edConfiguration = EDConfiguration() 195 if _dict is not None: 196 self.__edConfiguration[self.getPluginName()] = _dict 197 else: 198 self.__edConfiguration[self.getPluginName()] = {}
199 config = property(getConfig, setConfig) 200 201 202 @deprecated
203 - def getStringConfigurationParameterValue(self, _strConfigurationParameterName):
204 """ 205 This method returns a configuration parameter value if a corresponding configuration 206 parameter name can be found in the configuration file. 207 208 If an application wide configuration file is provided via EDApplication it will 209 override the product configuration file. 210 211 The configuration parameter is then searched in the configration file in following order: 212 - If a plugin configuration item exists and the configration parameter name is present it will be used. 213 - Otherwise if a product-wide (e.g. "mxPluginExec") configuration value exists it will be used. 214 """ 215 strParameterValue = self.__edConfiguration.getStringValue(self.getPluginName(), _strConfigurationParameterName) 216 self.DEBUG("EDPlugin.getConfigurationParameterValue: %s, %s = %s" % (self.getPluginName(), 217 _strConfigurationParameterName, 218 strParameterValue)) 219 return strParameterValue
220 221 @deprecated
222 - def getDoubleConfigurationParameterValue(self, _strConfigurationParameterName):
223 fParameterValue = None 224 strParameterValue = self.getStringConfigurationParameterValue(_strConfigurationParameterName) 225 try: 226 return float(strParameterValue) 227 except TypeError: 228 return 229 except ValueError: 230 self.ERROR("float() argument must be a string or a number, got %s" % strParameterValue)
231 232 233 @deprecated
234 - def getIntegerConfigurationParameterValue(self, _strConfigurationParameterName):
235 iParameterValue = None 236 strParameterValue = self.getStringConfigurationParameterValue(_strConfigurationParameterName) 237 try: 238 return int(strParameterValue) 239 except TypeError: 240 return 241 except ValueError: 242 self.ERROR("int() argument must be a string or a number, got %s" % strParameterValue)
243 244
245 - def configure(self):
246 """ 247 Should be overridden by the Final Plugin If needed 248 This method should set its proper members attributes from a Plugin configuration Object 249 """ 250 self.DEBUG("EDPlugin.configure : plugin name = %s, EDNA_SITE = %s" % (self.getPluginName(), EDUtilsPath.EDNA_SITE)) 251 252 # set Timeout if different from default one 253 if self.getTimeOut() == self.getDefaultTimeOut(): 254 # Try to get time out from plugin configuration 255 iTimeOut = self.config.get(EDPlugin.CONF_TIME_OUT, None) 256 if iTimeOut is not None: 257 self.DEBUG("EDPlugin.configure: Setting time out to %d s from plugin configuration." % iTimeOut) 258 self.setTimeOut(iTimeOut) 259 else: 260 self.DEBUG("EDPlugin.configure: timeout already set before plugin is configured.") 261 # Base directory 262 strBaseDirectory = self.getBaseDirectory() 263 if (strBaseDirectory is None): 264 # Try to get base directory from plugin configuration 265 strBaseDirectory = self.config.get(EDPlugin.CONF_BASE_DIR_LABEL, None) 266 if(strBaseDirectory is None): 267 # Try to get working directory from environment variable 268 strBaseDirectory = os.environ.get("EDNA_BASE_DIRECTORY") 269 if (strBaseDirectory is None): 270 self.DEBUG("EDPlugin.configure: Using current base directory as working directory.") 271 strBaseDirectory = os.getcwd() 272 else: 273 self.DEBUG("EDPlugin.configure: Setting base directory from $EDNA_WORKING_DIRECTORY.") 274 else: 275 if (strBaseDirectory == "."): 276 self.DEBUG("EDPlugin.configure: Using current base directory as working directory.") 277 strBaseDirectory = os.getcwd() 278 else: 279 strBaseDirectory = os.path.abspath(strBaseDirectory) 280 self.DEBUG("EDPlugin.configure: Setting base directory from plugin configuration.") 281 self.setBaseDirectory(strBaseDirectory) 282 else: 283 self.DEBUG("EDPlugin.configure: Base directory already set before plugin is configured.") 284 # Working directory 285 strWorkingDirectory = self.getWorkingDirectory() 286 if (strWorkingDirectory is None): 287 # Try to get working directory from plugin configuration 288 strWorkingDirectory = self.config.get(EDPlugin.CONF_WORKING_DIR_LABEL, None) 289 if(strWorkingDirectory is not None): 290 self.DEBUG("EDPlugin.configure: Setting working directory from plugin configuration.") 291 else: 292 self.DEBUG("EDPlugin.configure: Setting working directory as base directory + base name.") 293 strWorkingDirectory = os.path.join(self.getBaseDirectory(), self.getBaseName()) 294 self.setWorkingDirectory(strWorkingDirectory) 295 else: 296 self.DEBUG("EDPlugin.configure: Working directory already set before plugin is configured.") 297 # 298 self.__bWriteDataXMLInputOutput = bool(self.config.get(self.CONF_WRITE_XML_INPUT_OUTPUT, True)) 299 self.__bWriteDataXMLOutput = bool(self.config.get(self.CONF_WRITE_XML_OUTPUT, True)) 300 self.__bWriteDataXMLInput = bool(self.config.get(self.CONF_WRITE_XML_INPUT, True))
301 302
303 - def execute(self, _edObject=None):
304 # Configure the plugin before starting it's thread 305 self.configure() 306 EDAction.execute(self, _edObject)
307 308
309 - def checkParameters(self):
310 """ 311 Should be overridden by the Final Plugin If needed 312 This method should check that the data input are consistent 313 """ 314 self.DEBUG("EDPlugin.checkParameters")
315 316
317 - def setXSDataInputClass(self, _xsDataInputClass, _strDataInputKey=None):
318 """ 319 This method should be called in the constructor of the derived plugins 320 in order to set the XSData type of the input data, e.g. XSDataInputXXX 321 """ 322 strDataInputKey = _strDataInputKey 323 if (strDataInputKey is None): 324 strDataInputKey = self.__strDefaultInputDataKey 325 if (strDataInputKey in self.__dictXSDataInputClass.keys()): 326 strErrorMessage = "ERROR: " + self.getPluginName() + ".setXSDataInputClass, Data Input Class already defined for key: " + strDataInputKey 327 self.error(strErrorMessage) 328 self.addErrorMessage(strErrorMessage) 329 raise RuntimeError, strErrorMessage 330 self.__dictXSDataInputClass[ strDataInputKey ] = _xsDataInputClass
331 332
333 - def getXSDataInputClass(self, _strDataInputKey=None):
334 """ 335 Returns the XSData type of the input data. 336 """ 337 pyXSDataInputClass = None 338 strDataInputKey = _strDataInputKey 339 if (strDataInputKey is None): 340 strDataInputKey = self.__strDefaultInputDataKey 341 if (strDataInputKey in self.__dictXSDataInputClass.keys()): 342 pyXSDataInputClass = self.__dictXSDataInputClass[ strDataInputKey ] 343 return pyXSDataInputClass
344 345
346 - def setDataInput(self, _oDataInput, _strDataInputKey=None):
347 """ 348 Sets the plugin input data. 349 _oDataInput could be either an String XML or an XSData object. 350 351 The input data is stored in a dictionary with the key _strDataInputKey. 352 If the key is not provided a default key is used. 353 354 If not data input class is defined for the key an exception is raised. 355 356 If the key is not the default key, the data object is added to a list which 357 might contain already stored object(s). 358 359 If _oDataInput is None the list corresponding to a keyword is deleted. 360 """ 361 self.DEBUG("EDPlugin.setDataInput") 362 strDataInputKey = _strDataInputKey 363 if (strDataInputKey is None): 364 strDataInputKey = self.__strDefaultInputDataKey 365 # Allow for None input 366 if (_oDataInput is None): 367 self.DEBUG("EDPlugin.setDataInput: Data input is None") 368 self.__dictXSDataInput[ strDataInputKey ] = [] 369 elif (self.getXSDataInputClass(strDataInputKey) is None): 370 strErrorMessage = "ERROR: " + self.getPluginName() + ".setDataInput, Data Input Class not defined for key: " + strDataInputKey 371 self.error(strErrorMessage) 372 self.addErrorMessage(strErrorMessage) 373 raise RuntimeError, strErrorMessage 374 else: 375 # Check the type 376 xsDataInput = None 377 if isinstance(_oDataInput, (str, unicode)): 378 self.DEBUG("EDPlugin.setDataInput: Input Data is string ") 379 xsDataInput = self.getXSDataInputClass(strDataInputKey).parseString(_oDataInput) 380 elif (isinstance(_oDataInput, self.getXSDataInputClass(strDataInputKey))): 381 self.DEBUG("EDPlugin.setDataInput: Input Data is of type " + str(_oDataInput.__class__)) 382 xsDataInput = _oDataInput 383 else: 384 strErrorMessage = "ERROR: %s.setDataInput, wrong data type %r for data input key: %s, expected XML string or %r" % \ 385 (self.getPluginName(), _oDataInput.__class__, strDataInputKey, self.getXSDataInputClass(strDataInputKey)) 386 self.error(strErrorMessage) 387 self.addErrorMessage(strErrorMessage) 388 raise RuntimeError, strErrorMessage 389 # Add the object to a list if its key is not the default key 390 if (strDataInputKey != self.__strDefaultInputDataKey) : 391 # Check if there's already a list stored 392 if (not strDataInputKey in self.__dictXSDataInput.keys()): 393 self.__dictXSDataInput[ strDataInputKey ] = [] 394 self.__dictXSDataInput[ strDataInputKey ].append(xsDataInput) 395 else: 396 self.__dictXSDataInput[ strDataInputKey ] = xsDataInput
397 398
399 - def hasDataInput(self, _strDataInputKey=None):
400 """ 401 Returns True if the plugin has Input Data for a particular key. 402 If the key is not provided a default key is used. 403 """ 404 strDataInputKey = _strDataInputKey 405 if (strDataInputKey is None): 406 strDataInputKey = self.__strDefaultInputDataKey 407 if (strDataInputKey in self.__dictXSDataInput.keys()): 408 return True 409 else: 410 return False
411 412
413 - def getDataInput(self, _strDataInputKey=None):
414 """ 415 Returns the Plugin Input Data for a particular key. 416 If the key is not provided a default key is used. 417 """ 418 oValue = None 419 strDataInputKey = _strDataInputKey 420 if (strDataInputKey is None): 421 strDataInputKey = self.__strDefaultInputDataKey 422 if (strDataInputKey in self.__dictXSDataInput.keys()): 423 oValue = self.__dictXSDataInput[ strDataInputKey ] 424 else: 425 strErrorMessage = self.getPluginName() + ".getDataInput, no input data defined for key: " + strDataInputKey 426 self.warning(strErrorMessage) 427 self.addWarningMessage(strErrorMessage) 428 return oValue
429 430
431 - def delDataInput(self, _strDataInputKey=None):
432 """ 433 Deletes the data input for a particular key. 434 If the key is not provided a default key is used. 435 """ 436 strDataInputKey = _strDataInputKey 437 if (strDataInputKey is None): 438 strDataInputKey = self.__strDefaultInputDataKey 439 if (strDataInputKey in self.__dictXSDataInput.keys()): 440 self.__dictXSDataInput[ strDataInputKey ] = None 441 else: 442 strErrorMessage = self.getPluginName() + ".delDataInput, no input data defined for key: " + strDataInputKey 443 self.warning(strErrorMessage) 444 self.addWarningMessage(strErrorMessage)
445 446 # Property for dataInput 447 dataInput = property(getDataInput, setDataInput, delDataInput, "Property for dataInput") 448 449
450 - def setDataOutput(self, _xsDataOutput, _strDataOutputKey=None):
451 """ 452 Sets the plugin output data for a particular key. 453 If the key is not provided a default key is used. 454 455 If the key is already defined in the dictionary, the corresponding 456 data object is added to a list which contains the already stored object(s). 457 """ 458 strDataOutputKey = _strDataOutputKey 459 if (strDataOutputKey is None): 460 strDataOutputKey = self.__strDefaultOutputDataKey 461 # Add the object to a list if its key not the default key 462 if (strDataOutputKey == self.__strDefaultOutputDataKey): 463 self.__dictXSDataOutput[ strDataOutputKey ] = _xsDataOutput 464 else: 465 # Check if the _xsDataoutput object is already a list 466 if (type(_xsDataOutput) == types.ListType): 467 self.__dictXSDataOutput[ strDataOutputKey ] = _xsDataOutput 468 else: 469 # Check if the stored object contains already a list 470 if (not strDataOutputKey in self.__dictXSDataOutput.keys()): 471 self.__dictXSDataOutput[ strDataOutputKey ] = [] 472 self.__dictXSDataOutput[ strDataOutputKey ].append(_xsDataOutput)
473 474
475 - def getDataOutput(self, _strDataOutputKey=None):
476 """ 477 Returns the Plugin Output Data 478 """ 479 oValue = None 480 strDataOutputKey = _strDataOutputKey 481 if (strDataOutputKey is None): 482 strDataOutputKey = self.__strDefaultOutputDataKey 483 if (strDataOutputKey in self.__dictXSDataOutput.keys()): 484 oValue = self.__dictXSDataOutput[ strDataOutputKey ] 485 return oValue
486 487
488 - def hasDataOutput(self, _strDataOutputKey=None):
489 """ 490 Returns True if the plugin has the specified Output Data 491 """ 492 strDataOutputKey = _strDataOutputKey 493 if (strDataOutputKey is None): 494 strDataOutputKey = self.__strDefaultOutputDataKey 495 if (strDataOutputKey in self.__dictXSDataOutput.keys()): 496 return True 497 else: 498 return False
499 500
501 - def delDataOutput(self, _strDataOutputKey=None):
502 """ 503 Deletes the data output for a particular key. 504 If the key is not provided a default key is used. 505 """ 506 strDataOutputKey = _strDataOutputKey 507 if (strDataOutputKey is None): 508 strDataOutputKey = self.__strDefaultOutputDataKey 509 if (strDataOutputKey in self.__dictXSDataOutput.keys()): 510 self.__dictXSDataOutput[ strDataOutputKey ] = None 511 else: 512 strErrorMessage = self.getPluginName() + ".delDataOutput, no output data defined for key: " + _strDataOutputKey 513 self.warning(strErrorMessage) 514 self.addWarningMessage(strErrorMessage)
515 516 # Property for dataOutput 517 dataOutput = property(getDataOutput, setDataOutput, delDataOutput, "Property for dataOutput") 518 519
520 - def exportDataOutput(self, _edPlugin=None):
521 """ 522 Deprecated 523 Exports the Plugin Output Data to slot 524 """ 525 self.DEBUG("EDPlugin.exportDataOutput") 526 self.__edSlotExportDataOutput.call(self.__dictXSDataOutput)
527 528
529 - def connectExportDataOutput(self, _oMethod):
530 """ 531 Deprecated 532 """ 533 self.synchronizeOn() 534 if (_oMethod != None): 535 self.__edSlotExportDataOutput.connect(_oMethod) 536 self.synchronizeOff()
537 538
539 - def generateExecutiveSummary(self, _edPlugin):
540 """ 541 This method, which should be implemented by sub-classes, generates an executive summary (user-related output summary). 542 """ 543 self.DEBUG("EDPlugin.generateExecutiveSummary")
544 545
546 - def addErrorMessage(self, _strErrorMessage):
547 """ 548 Adds an error message to the error messages list 549 """ 550 self.__listErrorMessages.append(_strErrorMessage)
551 552
553 - def getErrorMessages(self):
554 """ 555 Returns the error messages list 556 OBS! This method is deprecated, please use getListOfErrorMessages instead. 557 """ 558 self.warning("Deprecation by Monday 7th June 2010 of EDPlugin, called getErrorMessages") 559 from EDImportLib import EDList 560 return EDList(self.__listErrorMessages)
561 562
563 - def getListOfErrorMessages(self):
564 """ 565 Returns the error messages list 566 """ 567 return self.__listErrorMessages
568 569
570 - def addWarningMessage(self, _strWarningMessage):
571 """ 572 Adds a warning message to the warning messages list 573 """ 574 self.DEBUG("EDPlugin.addWarningMessage : " + _strWarningMessage) 575 self.__listWarningMessages.append(_strWarningMessage)
576 577
578 - def getWarningMessages(self):
579 """ 580 Returns the warning messages list 581 OBS! This method is deprecated, please use getListOfWarningMessages instead. 582 """ 583 self.warning("Deprecation by Monday 7th June 2010 of EDPlugin, called getWarningMessages") 584 from EDImportLib import EDList 585 return EDList(self.__listWarningMessages)
586 587
588 - def getListOfWarningMessages(self):
589 """ 590 Returns the warning messages list 591 """ 592 return self.__listWarningMessages
593 594
595 - def writeDataInput(self, _edObject=None):
596 """ 597 Writes the input data object(s) into a working dir xml file 598 """ 599 self.DEBUG("EDPlugin.writeDataInput") 600 strBasename = os.path.join(self.getWorkingDirectory(), self.compactPluginName(self.getPluginName())) 601 for strKey in self.__dictXSDataInput.keys(): 602 if (strKey == self.__strDefaultInputDataKey): # "Old" style 603 xsDataInput = self.__dictXSDataInput[ self.__strDefaultInputDataKey ] 604 self.strPathDataInput = strBasename + "_dataInput.xml" 605 EDUtilsFile.writeFile(self.strPathDataInput, xsDataInput.marshal()) 606 else: # We have a list of objects 607 listXSDataInput = self.__dictXSDataInput[ strKey ] 608 for iIndex, xsDataInput in enumerate(listXSDataInput): 609 strPathDataInput = "%s_%s_%d_dataInput.xml" % (strBasename, strKey, iIndex) 610 EDUtilsFile.writeFile(strPathDataInput, xsDataInput.marshal())
611 612
613 - def writeDataOutput(self, _edObject=None):
614 """ 615 Writes the output data object(s) into a working dir xml file 616 """ 617 self.DEBUG("EDPlugin.writeDataOutput") 618 for strKey in self.__dictXSDataOutput.keys(): 619 if (strKey == self.__strDefaultOutputDataKey): # "Old" style 620 xsDataOutput = self.__dictXSDataOutput[ self.__strDefaultOutputDataKey ] 621 if (xsDataOutput is not None): 622 self.strPathDataOutput = os.path.join(self.getWorkingDirectory(), self.compactPluginName(self.getPluginName()) + "_dataOutput.xml") 623 EDUtilsFile.writeFile(self.strPathDataOutput, xsDataOutput.marshal()) 624 else: 625 listXSDataOutput = self.__dictXSDataOutput[ strKey ] 626 for iIndex, xsDataOutput in enumerate(listXSDataOutput): 627 if (xsDataOutput is not None): 628 strPathDataOutput = os.path.join(self.getWorkingDirectory(), self.compactPluginName(self.getPluginName()) + "_" + strKey + "_%d_dataOutput.xml" % iIndex) 629 EDUtilsFile.writeFile(strPathDataOutput, xsDataOutput.marshal())
630 631
632 - def getBaseName(self):
633 """ 634 Returns the plugin base name 635 """ 636 if (self.__strBaseName is None): 637 self.__strBaseName = self.createBaseName() 638 return self.__strBaseName
639 640
641 - def setBaseName(self, _strBaseName):
642 """ 643 Sets the plugin base name 644 """ 645 self.__strBaseName = self.compactPluginName(_strBaseName) 646 self.setName(self.__strBaseName) 647 # Create the directory baseDirectory/baseName which will be used as working directory 648 strWorkingDirPath = os.path.join(self.getBaseDirectory(), self.__strBaseName) 649 if not os.path.isdir(strWorkingDirPath): 650 os.mkdir(strWorkingDirPath) 651 self.setWorkingDirectory(strWorkingDirPath)
652 653
654 - def createBaseName(self):
655 """ 656 Generates the plugin base name: (<prefix>-<object ID>) 657 """ 658 # First try to use global instance ID from EDObject 659 strBaseName = "%s-%08d" % (self.compactPluginName(self.getPluginName()), self.getId()) 660 strBaseDir = os.path.join(self.getBaseDirectory(), strBaseName) 661 # Try to create the directory... 662 try: 663 os.mkdir(strBaseDir) 664 except BaseException, strErrorDetail: 665 self.error("EDPlugin.createBaseName: Could not create base directory %s because of %s" % (strBaseDir, strErrorDetail)) 666 self.warning("EDPlugin.createBaseName: Trying to create alternative base directory...") 667 self.writeErrorTrace() 668 strTempDir = tempfile.mkdtemp(prefix=strBaseName, dir=self.getBaseDirectory()) 669 os.chmod(strTempDir, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) 670 strBaseName = os.path.split(strTempDir)[1] 671 strBaseDir = os.path.join(self.getBaseDirectory(), strBaseName) 672 self.warning("EDPlugin.createBaseName: Alternative base directory created: %s" % strBaseDir) 673 self.DEBUG("EDPlugin.createBaseName : Directory created = " + strBaseDir) 674 return strBaseName
675 676
677 - def compactPluginName(self, _pluginName):
678 """ 679 The prefix is constructed from the plugin name with the following renaming: 680 EDPlugin -> "" 681 EDPluginExec -> "" 682 EDPluginControl -> "Control" 683 """ 684 strCompactName = _pluginName 685 if (strCompactName.startswith("EDPluginExec")): 686 strCompactName = strCompactName[12:] 687 elif (strCompactName.startswith("EDPluginControl")): 688 strCompactName = strCompactName[8:] 689 elif (strCompactName.startswith("EDPlugin")): 690 strCompactName = strCompactName[8:] 691 return strCompactName
692 693
694 - def setBaseDirectory(self, _strBaseDirectory):
695 """ 696 Sets the plugin base directory 697 """ 698 self.DEBUG("EDPlugin.setBaseDirectory : " + _strBaseDirectory) 699 if (not os.path.isdir(_strBaseDirectory)): 700 self.DEBUG("EDPlugin.setBaseDirectory: base directory %s does dot yet exist! Creating it." % _strBaseDirectory) 701 os.mkdir(_strBaseDirectory) 702 self.__strBaseDirectory = _strBaseDirectory
703 704
705 - def getBaseDirectory(self):
706 """ 707 Returns the plugin base directory 708 """ 709 self.DEBUG("EDPlugin.getBaseDirectory : %s" % self.__strBaseDirectory) 710 if (self.__strBaseDirectory is None): 711 self.__strBaseDirectory = os.getcwd() 712 return self.__strBaseDirectory
713 714
715 - def setWorkingDirectory(self, _strWorkingDirectory):
716 """ 717 Sets the plugin working directory 718 """ 719 self.DEBUG("EDPlugin.setWorkingDirectory : " + _strWorkingDirectory) 720 self.__strWorkingDirectory = _strWorkingDirectory 721 if not os.path.isdir(_strWorkingDirectory): 722 self.DEBUG("EDPlugin.setWorkingDirectory, creating working directory %s." % _strWorkingDirectory) 723 os.mkdir(self.__strWorkingDirectory)
724 725
726 - def getWorkingDirectory(self):
727 """ 728 Returns the plugin base directory 729 """ 730 self.DEBUG("EDPlugin.getWorkingDirectory : %s" % self.__strWorkingDirectory) 731 returnValue = None 732 if (self.__strWorkingDirectory is not None): 733 returnValue = self.__strWorkingDirectory 734 return returnValue
735 736
737 - def checkMandatoryParameters(self, _xsData, _strParamName):
738 """ 739 Checks that a mandatory parameter exists in the data 740 If not, an error message is added in the list and the plugin fails 741 """ 742 if _xsData is None or (hasattr(_xsData, '__len__') and len(_xsData) == 0): 743 strErrorMessage = "%s: input parameter is missing: %s" % (self.getPluginName(), _strParamName) 744 self.error(strErrorMessage) 745 self.addErrorMessage(strErrorMessage) 746 raise RuntimeError, strErrorMessage
747 748
749 - def checkImportantParameters(self, _xsData, _strParamName):
750 """ 751 Checks that a specific parameter exists in the data 752 If not, a warning message is added in the list 753 """ 754 if(_xsData == None): 755 strWarningMessage = "%s: input parameter is missing: %s" % (self.getPluginName(), _strParamName) 756 self.warning(strWarningMessage) 757 self.addWarningMessage(strWarningMessage)
758 759
760 - def addExecutiveSummaryLine(self, _strExecutiveSummaryLine):
761 """ 762 Add a line to the executive summary string. 763 """ 764 self.DEBUG("EDPlugin.addExecutiveSummaryLine : %r" % _strExecutiveSummaryLine) 765 strExecutiveSummaryLine = _strExecutiveSummaryLine 766 if (not strExecutiveSummaryLine == ""): 767 if (strExecutiveSummaryLine[-1] == "\n"): 768 strExecutiveSummaryLine = strExecutiveSummaryLine[:-1] 769 self.__listExecutiveSummaryLines.append(strExecutiveSummaryLine)
770 771
772 - def addExecutiveSummarySeparator(self, _strSeparator=None):
773 """ 774 Adds a separator to split the executive summary into different parts 775 Default is a dotted line 776 """ 777 strSeparator = _strSeparator 778 if (strSeparator is None): 779 strSeparator = self.__strExecutiveSummarySeparator 780 # Check that the last line doesn't already contain a separator 781 if self.__listExecutiveSummaryLines != []: 782 if self.__listExecutiveSummaryLines[-1] != strSeparator: 783 self.addExecutiveSummaryLine(strSeparator) 784 else: 785 self.addExecutiveSummaryLine(strSeparator)
786 787
789 """ 790 Returns the executive summary (list of text lines) 791 """ 792 return self.__listExecutiveSummaryLines
793 794
796 """ 797 Prints the executive summary on the screen 798 """ 799 for line in self.getListExecutiveSummaryLines(): 800 self.screen(line)
801
802 - def verboseDebug(self, _strMessage):
803 self.DEBUG(self.getPluginName() + " : " + _strMessage)
804 805
806 - def getPluginName(self):
807 return self.getClassName()
808 809
810 - def getListOfDataInputKeys(self):
811 return self.__dictXSDataInput.keys()
812 813
814 - def getListOfDataOutputKeys(self):
815 return self.__dictXSDataOutput.keys()
816 817
818 - def getDefaultInputDataKey(self):
819 return self.__strDefaultInputDataKey
820 821
822 - def getDefaultOutputDataKey(self):
823 return self.__strDefaultOutputDataKey
824 825
827 return self.__strExecutiveSummarySeparator
828 829
831 """ 832 If the return value from this method is true, the plugin 833 is required to have a configuration in order to be executed in a 834 plugin execution test case. 835 @return: RequiredToHaveConfiguration 836 @rtype: boolean 837 """ 838 return self.__isRequiredToHaveConfiguration
839 840
841 - def setRequiredToHaveConfiguration(self, _bValue=True):
842 """ 843 Sets or unsets the plugin to be required to have a configuration 844 for execution in a plugin execution test case. 845 plugin execution test case. 846 @param _bValue: RequiredToHaveConfiguration 847 @type: boolean 848 """ 849 self.__isRequiredToHaveConfiguration = _bValue
850 851
852 - def setWriteXMLInputOutput(self, _bValue=True):
853 """ 854 Sets or unsets the plugin to write XML input and output files. 855 @param _bValue: WriteDataXMLInputOutput 856 @type: boolean 857 """ 858 self.__bWriteDataXMLInputOutput = _bValue
859
860 - def setWriteXMLInput(self, _bValue=True):
861 """ 862 Sets or unsets the plugin to write XML input files. 863 @param _bValue: WriteDataXMLInput 864 @type: boolean 865 """ 866 self.__bWriteDataXMLInput = _bValue
867
868 - def setWriteXMLOutput(self, _bValue=True):
869 """ 870 Sets or unsets the plugin to write XML output files. 871 @param _bValue: WriteDataXMLOutput 872 @type: boolean 873 """ 874 self.__bWriteDataXMLOutput = _bValue
875 876
877 - def setUseWarningInsteadOfError(self, _bValue=True):
878 """ 879 Sets or unsets the plugin to use warning messages also for error messages. 880 @param _bValue: UseWarningInsteadOfError 881 @type: boolean 882 """ 883 self.__bUseWarningInsteadOfError = _bValue
884
885 - def error(self, _strErrorMessage):
886 """ 887 Overloaded from EDLogging. If self.__bUseWarningInsteadOfError is True 888 a warning message is issued instead of an error message. 889 """ 890 if self.__bUseWarningInsteadOfError: 891 self.warning(_strErrorMessage) 892 else: 893 EDAction.error(self, _strErrorMessage)
894
895 - def ERROR(self, _strErrorMessage):
896 """ 897 Uses the overloaded self.error method above. 898 """ 899 self.error(_strErrorMessage)
900