CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_9_patch3/src/FWCore/GuiBrowsers/python/EnablePSetHistory.py

Go to the documentation of this file.
00001 from copy import deepcopy
00002 import inspect
00003 
00004 ACTIVATE_INSPECTION=True
00005 
00006 #### helpers for inspection ####
00007 
00008 def auto_inspect():
00009     if not ACTIVATE_INSPECTION:
00010         return [("unknown","unknown","unknown")]
00011     stack = inspect.stack()
00012     while len(stack)>=1 and len(stack[0])>=2 and ('FWCore/ParameterSet' in stack[0][1] or 'FWCore/GuiBrowsers' in stack[0][1]):
00013         stack = stack[1:]
00014     if len(stack)>=1 and len(stack[0])>=3:
00015        return stack
00016     else:
00017        return [("unknown","unknown","unknown")]
00018 
00019 #### patches needed for deepcopy of process ####
00020 
00021 import FWCore.ParameterSet.DictTypes as typ
00022     
00023 def new_SortedKeysDict__copy__(self):
00024     return self.__class__(self)
00025 typ.SortedKeysDict.__copy__ = new_SortedKeysDict__copy__
00026 
00027 def new_SortedKeysDict__deepcopy__(self, memo=None):
00028     from copy import deepcopy
00029     if memo is None:
00030         memo = {}
00031     d = memo.get(id(self), None)
00032     if d is not None:
00033         return d
00034     memo[id(self)] = d = self.__class__()
00035     d.__init__(deepcopy(self.items(), memo))
00036     return d
00037 typ.SortedKeysDict.__deepcopy__ = new_SortedKeysDict__deepcopy__
00038 
00039 #### process history ####
00040 
00041 import FWCore.ParameterSet.Config as cms
00042 
00043 def new___init__(self,name):
00044     self.old___init__(name)
00045     self.__dict__['_Process__history'] = []
00046     self.__dict__['_Process__enableRecording'] = 0
00047     self.__dict__['_Process__modifiedobjects'] = []
00048     self.__dict__['_Process__modifiedcheckpoint'] = None
00049     self.__dict__['_Process__modifications'] = []
00050 cms.Process.old___init__=cms.Process.__init__
00051 cms.Process.__init__=new___init__
00052 
00053 def new_modifiedObjects(self):
00054     return self.__dict__['_Process__modifiedobjects']
00055 cms.Process.modifiedObjects=new_modifiedObjects
00056 
00057 def new_resetModifiedObjects(self):
00058     self.__dict__['_Process__modifiedobjects'] = []
00059 cms.Process.resetModifiedObjects=new_resetModifiedObjects
00060 
00061 def new__place(self, name, mod, d):
00062     self.old__place(name, mod, d)
00063     if self._okToPlace(name, mod, d):
00064         self.__dict__['_Process__modifiedobjects'].append(mod)
00065 cms.Process.old__place=cms.Process._place
00066 cms.Process._place=new__place
00067 
00068 def new__placeSource(self, name, mod):
00069     self.old__placeSource(name, mod)
00070     self.__dict__['_Process__modifiedobjects'].append(mod)
00071 cms.Process.old__placeSource=cms.Process._placeSource
00072 cms.Process._placeSource=new__placeSource
00073 
00074 def new__placeLooper(self, name, mod):
00075     self.old__placeLooper(name, mod)
00076     self.__dict__['_Process__modifiedobjects'].append(mod)
00077 cms.Process.old__placeLooper=cms.Process._placeLooper
00078 cms.Process._placeLooper=new__placeLooper
00079 
00080 def new__placeService(self, typeName, mod):
00081     self.old__placeService(typeName, mod)
00082     self.__dict__['_Process__modifiedobjects'].append(mod)
00083 cms.Process.old__placeService=cms.Process._placeService
00084 cms.Process._placeService=new__placeService
00085 
00086 def new_setSchedule_(self, sch):
00087     self.old_setSchedule_(sch)
00088     self.__dict__['_Process__modifiedobjects'].append(sch)
00089 cms.Process.old_setSchedule_=cms.Process.setSchedule_
00090 cms.Process.setSchedule_=new_setSchedule_
00091 
00092 def new_setLooper_(self, lpr):
00093     self.old_setLooper_(lpr)
00094     self.__dict__['_Process__modifiedobjects'].append(lpr)
00095 cms.Process.old_setLooper_=cms.Process.setLooper_
00096 cms.Process.setLooper_=new_setLooper_
00097 
00098 def new_history(self, removeDuplicates=False):
00099     return self.__dict__['_Process__history']+self.dumpModificationsWithObjects(removeDuplicates)
00100 cms.Process.history=new_history
00101 
00102 def new_resetHistory(self):
00103     self.__dict__['_Process__history'] = []
00104     self.resetModified()
00105     self.resetModifiedObjects()
00106 cms.Process.resetHistory=new_resetHistory
00107 
00108 def new_dumpHistory(self,withImports=True):
00109     dumpHistory=[]
00110     for item,objects in self.history():
00111         if isinstance(item,(str,unicode)):
00112             dumpHistory.append(item +"\n")
00113         else: # isTool
00114             print item
00115             dump=item.dumpPython()
00116             if isinstance(dump,tuple):
00117                 if withImports and dump[0] not in dumpHistory:
00118                     dumpHistory.append(dump[0])
00119                 dumpHistory.append(dump[1] +"\n")
00120             else:
00121                 dumpHistory.append(dump +"\n")
00122            
00123     return ''.join(dumpHistory)
00124 cms.Process.dumpHistory=new_dumpHistory
00125 
00126 def new_addAction(self,tool):
00127     if self.__dict__['_Process__enableRecording'] == 0:
00128         modifiedObjects=self.modifiedObjects()
00129         for m,o in self.dumpModificationsWithObjects():
00130             modifiedObjects+=o
00131         self.__dict__['_Process__history'].append((tool,modifiedObjects))
00132         self.resetModified()
00133         self.resetModifiedObjects()
00134 cms.Process.addAction=new_addAction
00135 
00136 def new_deleteAction(self,i):
00137     del self.__dict__['_Process__history'][i]
00138 cms.Process.deleteAction=new_deleteAction
00139 
00140 def new_disableRecording(self):
00141     if self.__dict__['_Process__enableRecording'] == 0:
00142         # remember modifications in history
00143         self.__dict__['_Process__history']+=self.dumpModificationsWithObjects()
00144         self.resetModified()
00145         self.resetModifiedObjects()
00146     self.__dict__['_Process__enableRecording'] += 1
00147 cms.Process.disableRecording=new_disableRecording
00148 
00149 def new_enableRecording(self):
00150     self.__dict__['_Process__enableRecording'] -= 1
00151 cms.Process.enableRecording=new_enableRecording
00152 
00153 def new_checkRecording(self):
00154     return self.__dict__['_Process__enableRecording']==0
00155 cms.Process.checkRecording=new_checkRecording
00156 
00157 def new_setattr(self, name, value):
00158     """
00159     This catches modifications that occur during process.load,
00160     and only records a modification if there was an existing object
00161     and the version after __setattr__ has a different id().
00162     This does not mean that the object is different, only redefined.
00163     We still really need a recursive-comparison function for parameterizeable
00164     objects to determine if a real change has been made.
00165     """
00166     old = None
00167     existing = False
00168     if not name.startswith('_Process__'):
00169         existing = hasattr(self, name)
00170         if existing:
00171             old = getattr(self, name)
00172     self.old__setattr__(name, value)
00173     if existing:
00174         if id(getattr(self, name)) != id(old):
00175             stack = auto_inspect()
00176             self.__dict__['_Process__modifications'] += [{'name': name,
00177                                                           'old': deepcopy(old), 
00178                                                           'new': deepcopy(getattr(self, name)),
00179                                                           'file':stack[0][1],'line':stack[0][2],
00180                                                           'action': 'replace'}]
00181 cms.Process.old__setattr__ = cms.Process.__setattr__
00182 cms.Process.__setattr__ = new_setattr
00183 
00184 def new_recurseResetModified_(self, o):
00185     """
00186     Empty all the _modifications lists for
00187     all objects beneath this one.
00188     """
00189     properties = []
00190     if isinstance(o, cms._ModuleSequenceType):
00191         o.resetModified()
00192     if isinstance(o, cms._Parameterizable):
00193         o.resetModified()
00194         for key in o.parameterNames_():
00195             value = getattr(o,key)
00196             self.recurseResetModified_(value)
00197     if isinstance(o, cms._ValidatingListBase):
00198         for index,item in enumerate(o):
00199             self.recurseResetModified_(item)
00200 cms.Process.recurseResetModified_=new_recurseResetModified_
00201 
00202 def new_recurseDumpModifications_(self, name, o):
00203     """
00204     Recursively return a standardised list of modifications
00205     from the object hierarchy.
00206     """
00207     modifications = []
00208     if isinstance(o, cms._ModuleSequenceType):
00209         if o._isModified:
00210             for mod in o._modifications:
00211                 modifications.append({'name':name,
00212                                       'action':mod['action'],
00213                                       'old': mod['old'],
00214                                       'new': mod['new'],
00215                                       'file': mod['file'],
00216                                       'line': mod['line'],
00217                                       'dump': o.dumpPython({}),
00218                                       'type': 'seq'})
00219     
00220     if isinstance(o, cms._Parameterizable):
00221         for mod in o._modifications:
00222             paramname = mod['name']
00223             if hasattr(o, paramname):
00224                 paramvalue = getattr(o, paramname)
00225             else:
00226                 paramvalue = None
00227             if isinstance(paramvalue,cms._ParameterTypeBase):
00228                 dump = paramvalue.dumpPython()
00229             else:
00230                 dump = paramvalue
00231             modifications.append({'name': '%s.%s' %(name, paramname),
00232                                   'old': mod['old'],
00233                                   'new': mod['new'],
00234                                   'file': mod['file'],
00235                                   'line': mod['line'],
00236                                   'action': mod['action'],
00237                                   'dump': dump,
00238                                   'type': 'param'})
00239             
00240         # Loop over any child elements
00241         for key in o.parameterNames_():
00242             value = getattr(o,key)
00243             modifications += self.recurseDumpModifications_("%s.%s" % (name, key), value)
00244     
00245     if isinstance(o, cms._ValidatingListBase):
00246         for index, item in enumerate(o):
00247             modifications += self.recurseDumpModifications_("%s[%s]" % (name, index), item)
00248     if isinstance(o, cms.Process):
00249         for mod in o.__dict__['_Process__modifications']:
00250             if hasattr(o, mod['name']) and hasattr(getattr(o, mod['name']), 'dumpPython'):
00251                 dump = getattr(o, mod['name']).dumpPython()
00252             else:
00253                 dump = None
00254             modifications.append({'name': mod['name'],
00255                                   'action': mod['action'],
00256                                   'old': mod['old'],
00257                                   'new': mod['new'],
00258                                   'dump': dump,
00259                                   'file': mod['file'],
00260                                   'line': mod['line'],
00261                                   'type': 'process'})
00262     return modifications
00263 cms.Process.recurseDumpModifications_=new_recurseDumpModifications_
00264 
00265 def new_modificationCheckpoint(self):
00266     """
00267     Set a checkpoint, ie get the current list of all known
00268     top-level names and store them. Later, when we print out
00269     modifications we ignore any modifications that do not affect
00270     something in this list.
00271 
00272     There is currently no way of clearing this, but I think this
00273     is generally a use-once feature.
00274     """
00275     existing_names = set()
00276     for item in self.items_():
00277         existing_names.add(item[0])
00278     self.__dict__['_Process__modifiedcheckpoint'] = list(existing_names)
00279 cms.Process.modificationCheckpoint=new_modificationCheckpoint
00280 
00281 def new_resetModified(self):
00282     """
00283     Empty out all the modification lists, so we only see changes that
00284     happen from now onwards.
00285     """
00286     self.__dict__['_Process__modified'] = []
00287     for name, o in self.items_():
00288         self.recurseResetModified_(o)
00289 cms.Process.resetModified=new_resetModified
00290 
00291 def new_dumpModifications(self, comments=True, process=True, module=False, sequence=True, value=True, sort=True, group=True):
00292     """
00293     Return some text describing all the modifications that have been made.
00294 
00295     * comments: print out comments describing the file and line which triggered
00296                 the modification, if determined.
00297     * process: print "process." in front of every name
00298     * module: only print out one entry per top-level module that has been
00299               changed, rather than the details
00300     * sequence: include changes to sequences
00301     * value: print out the latest value of each name
00302     * sort: whether to sort all the names before printing (otherwise they're in
00303             more-or-less time order, within each category)
00304     """
00305     modifications = self.recurseDumpModifications_('', self)
00306     text = []
00307     for name, o in self.items_():
00308         modifications += self.recurseDumpModifications_(name, o)
00309     if not sequence:
00310         modifications = filter(lambda x: not x['type'] == 'seq', modifications)
00311     checkpoint = self.__dict__['_Process__modifiedcheckpoint']
00312     if not checkpoint == None:
00313         modifications = filter(lambda x: any([x['name'].startswith(check) for check in checkpoint]), modifications)
00314     if module:
00315         value = False
00316         comments = False
00317         modules = list(set([m['name'].split('.')[0] for m in modifications]))
00318         if sort:
00319             modules = sorted(modules)
00320         if process:
00321             text = ['process.%s' % m for m in modules]
00322         else:
00323             text = modules
00324     else:
00325         if sort:
00326             modifications = sorted(modifications, key=lambda x: x['name'])
00327         for i, m in enumerate(modifications):
00328             t = ''
00329             if comments:
00330                 if m['action'] == 'replace':
00331                     t += '# %(file)s:%(line)s replace %(old)s->%(new)s\n' % m
00332                 elif m['action'] == 'remove':
00333                     t += '# %(file)s:%(line)s remove %(old)s\n' % m
00334                 elif m['action'] == 'append':
00335                     t += '# %(file)s:%(line)s append %(new)s\n' % m
00336             if not group or i==len(modifications)-1 or not modifications[i+1]['name'] == m['name']:
00337                 if process and value:
00338                     t += 'process.%s = %s' % (m['name'], m['dump'])
00339                 elif value:
00340                     t += '%s = %s' % (m['name'], m['dump'])
00341                 elif process:
00342                     t += 'process.%s' % (m['name'])
00343                 else:
00344                     t += '%s' % (m['name'])
00345             text += [t]
00346     return '\n'.join(text)+'\n'
00347 cms.Process.dumpModifications=new_dumpModifications
00348 
00349 def new_dumpModificationsWithObjects(self, removeDuplicates=False):
00350     modifications = []
00351     last_modification=""
00352     for name, o in self.items_():
00353         for m in self.recurseDumpModifications_(name, o):
00354             # remove duplicate modifications
00355             if removeDuplicates and last_modification==m['name']:
00356                 modifications.pop()
00357             last_modification=m['name']
00358             # add changes
00359             text = 'process.%s = %s' % (m['name'], m['dump'])
00360             modifications += [(text,[o])]
00361     return modifications
00362 cms.Process.dumpModificationsWithObjects=new_dumpModificationsWithObjects
00363 
00364 def new_moduleItems_(self):
00365     items = []
00366     items += self.producers.items()
00367     items += self.filters.items()
00368     items += self.analyzers.items()
00369     return tuple(items)
00370 cms.Process.moduleItems_=new_moduleItems_
00371 
00372 def new_items_(self):
00373     items = []
00374     if self.source:
00375         items += [("source", self.source)]
00376     if self.looper:
00377         items += [("looper", self.looper)]
00378     items += self.moduleItems_()
00379     items += self.outputModules.items()
00380     items += self.sequences.items()
00381     items += self.paths.iteritems()
00382     items += self.endpaths.items()
00383     items += self.services.items()
00384     items += self.es_producers.items()
00385     items += self.es_sources.items()
00386     items += self.es_prefers.items()
00387     items += self.psets.items()
00388     items += self.vpsets.items()
00389     if self.schedule:
00390         items += [("schedule", self.schedule)]
00391     return tuple(items)
00392 cms.Process.items_=new_items_
00393 
00394 #### parameterizable history ####
00395 
00396 def new_Parameterizable_init(self,*a,**k):
00397   self.__dict__['_modifications'] = []
00398   self.old__init__(*a,**k)
00399   self._modifications = []
00400 cms._Parameterizable.old__init__ = cms._Parameterizable.__init__
00401 cms._Parameterizable.__init__ = new_Parameterizable_init
00402 
00403 def new_Parameterizable_addParameter(self, name, value):
00404   self.old__addParameter(name,value)
00405   stack = auto_inspect()
00406   self._modifications.append({'file':stack[0][1],'line':stack[0][2],'name':name,'old':None,'new':deepcopy(value),'action':'add'})
00407 cms._Parameterizable.old__addParameter = cms._Parameterizable._Parameterizable__addParameter
00408 cms._Parameterizable._Parameterizable__addParameter = new_Parameterizable_addParameter
00409 
00410 def new_Parameterizable_setattr(self, name, value):
00411   if (not self.isFrozen()) and (not name.startswith('_')) and (name in self.__dict__):
00412     stack = auto_inspect()
00413     self._modifications.append({'file':stack[0][1],'line':stack[0][2],'name':name,'old':deepcopy(self.__dict__[name]),'new':deepcopy(value),'action':'replace'})
00414     self._isModified = True
00415   self.old__setattr__(name,value)
00416 cms._Parameterizable.old__setattr__ = cms._Parameterizable.__setattr__
00417 cms._Parameterizable.__setattr__ = new_Parameterizable_setattr
00418 
00419 def new_Parameterizeable_delattr(self, name):
00420     if not self.isFrozen():
00421         stack = auto_inspect()
00422         self._modifications.append({'file':stack[0][1],'line':stack[0][2],'name':name,'old':deepcopy(self.__dict__[name]), 'new':None,'action':'delete'})
00423     self.old__delattr__(name)
00424 cms._Parameterizable.old__delattr__ = cms._Parameterizable.__delattr__
00425 cms._Parameterizable.__delattr__ = new_Parameterizeable_delattr
00426 
00427 
00428 def new_Parameterizable_resetModified(self):
00429     self._isModified=False
00430     self._modifications = []
00431     for name in self.parameterNames_():
00432         param = self.__dict__[name]
00433         if isinstance(param, cms._Parameterizable):
00434             param.resetModified()
00435 cms._Parameterizable.resetModified = new_Parameterizable_resetModified
00436 
00437 def new_ParameterTypeBase_resetModified(self):
00438     self._isModified=False
00439     self._modifications = []
00440 cms._ParameterTypeBase.resetModified = new_ParameterTypeBase_resetModified
00441 
00442 #### sequence history ####
00443 
00444 def new__Sequenceable_name(self):
00445     return ''
00446 cms._Sequenceable._name_ = new__Sequenceable_name
00447 
00448 try:
00449     # for backwards-compatibility with CMSSW_3_10_X
00450     from FWCore.ParameterSet.SequenceTypes import _SequenceOperator
00451 
00452     def new__SequenceOperator_name(self):
00453         return str(self._left._name_())+str(self._pySymbol)+str(self._right._name_())
00454     _SequenceOperator._name_ = new__SequenceOperator_name    
00455 except:
00456     pass
00457 
00458 from FWCore.ParameterSet.SequenceTypes import _SequenceNegation, _SequenceIgnore, SequencePlaceholder
00459 
00460 def new__SequencePlaceholder_name(self):
00461     return self._name
00462 SequencePlaceholder._name_ = new__SequencePlaceholder_name
00463 
00464 def new__SequenceNegation_name(self):
00465     if self._operand:
00466         return '~'+str(self._operand._name_())
00467     else:
00468         return '~()'
00469 _SequenceNegation._name_ = new__SequenceNegation_name    
00470 
00471 def new__SequenceIgnore_name(self):
00472     if self._operand:
00473         return '-'+str(self._operand._name_())
00474     else:
00475         return '-()'
00476 _SequenceIgnore._name_ = new__SequenceIgnore_name
00477 
00478 def new_Sequence_name(self):
00479     if self._seq:
00480         return '('+str(self._seq._name_())+')'
00481     else:
00482         return '()'
00483 cms.Sequence._name_ = new_Sequence_name
00484 
00485 def new__Module_name(self):
00486   if hasattr(self,'_Labelable__label'):
00487     return getattr(self,'_Labelable__label')
00488   elif hasattr(self,'_TypedParameterizable__type'):
00489     return 'unnamed(%s)'%getattr(self,'_TypedParameterizable__type')
00490   return type(self).__name__
00491 cms._Module._name_ = new__Module_name
00492 
00493 def new__ModuleSequenceType__init__(self,*arg,**argv):
00494     self._modifications = []
00495     self.old__init__(*arg,**argv)
00496 cms._ModuleSequenceType.old__init__ = cms._ModuleSequenceType.__init__
00497 cms._ModuleSequenceType.__init__ = new__ModuleSequenceType__init__
00498     
00499 def new__ModuleSequenceType_resetModified(self):
00500     self._isModified=False
00501     self._modifications = []
00502 cms._ModuleSequenceType.resetModified = new__ModuleSequenceType_resetModified
00503 
00504 def new__ModuleSequenceType_isModified(self):
00505     return self._isModified
00506 cms._ModuleSequenceType.isModified = new__ModuleSequenceType_isModified
00507 
00508 def new__ModuleSequenceType_copy(self):
00509     returnValue = cms._ModuleSequenceType.__new__(type(self))
00510     returnValue.__init__(self._seq)
00511     returnValue._isModified = self._isModified
00512     returnValue._modifications = deepcopy(self._modifications)
00513     return returnValue
00514 cms._ModuleSequenceType.copy = new__ModuleSequenceType_copy
00515 
00516 def new__ModuleSequenceType_replace(self, original, replacement):
00517     stack = auto_inspect()
00518     self._isModified=True
00519     self._modifications.append({'file':stack[0][1],'line':stack[0][2],'action':'replace','old':original._name_(),'new':replacement._name_()})
00520     return self.old_replace(original, replacement)
00521 cms._ModuleSequenceType.old_replace = cms._ModuleSequenceType.replace
00522 cms._ModuleSequenceType.replace = new__ModuleSequenceType_replace
00523 
00524 def new__ModuleSequenceType_remove(self, original):
00525     stack = auto_inspect()
00526     self._isModified=True
00527     self._modifications.append({'file':stack[0][1],'line':stack[0][2],'action':'remove','old':original._name_(),'new':None})
00528     return self.old_remove(original)
00529 cms._ModuleSequenceType.old_remove = cms._ModuleSequenceType.remove
00530 cms._ModuleSequenceType.remove = new__ModuleSequenceType_remove
00531 
00532 def new__ModuleSequenceType__imul__(self,other):
00533     stack = auto_inspect()
00534     self._modifications.append({'file':stack[0][1],'line':stack[0][2],'action':'append','new':other._name_(),'old':None})
00535     self._isModified=True
00536     return self.old__iadd__(other)
00537 cms._ModuleSequenceType.old__imul__ = cms._ModuleSequenceType.__imul__
00538 cms._ModuleSequenceType.__imul__ = new__ModuleSequenceType__imul__
00539 
00540 def new__ModuleSequenceType__iadd__(self,other):
00541     stack = auto_inspect()
00542     self._isModified=True
00543     self._modifications.append({'file':stack[0][1],'line':stack[0][2],'action':'append','new':other._name_(),'old':None})
00544     return self.old__iadd__(other)
00545 cms._ModuleSequenceType.old__iadd__ = cms._ModuleSequenceType.__iadd__
00546 cms._ModuleSequenceType.__iadd__ = new__ModuleSequenceType__iadd__
00547 
00548 from FWCore.ParameterSet.Modules  import Source
00549 from FWCore.GuiBrowsers.editorTools import changeSource
00550             
00551 if __name__=='__main__':
00552     import unittest
00553     class TestModificationTracking(unittest.TestCase):
00554         def setUp(self):
00555             pass
00556         def testPSet(self):
00557             ex = cms.EDAnalyzer("Example",
00558                 one = cms.double(0),
00559                 two = cms.bool(True),
00560                 ps = cms.PSet(
00561                     three = cms.int32(10),
00562                     four = cms.string('abc')
00563                 ),
00564                 vps = cms.VPSet(
00565                     cms.PSet(
00566                         five = cms.InputTag('alpha')
00567                     ),
00568                     cms.PSet(
00569                         six = cms.vint32(1,2,3)
00570                     )
00571                 ),
00572                 seven = cms.vstring('alpha','bravo','charlie'),
00573                 eight = cms.vuint32(range(10)),
00574                 nine = cms.int32(0)
00575             )
00576             ex.zero = cms.string('hello')
00577             self.assertEqual(ex._modifications[-1]['name'],'zero')
00578             ex.one = cms.double(1)
00579             ex.one = cms.double(2)
00580             ex.one = cms.double(3)
00581             self.assertEqual(ex._modifications[-1]['name'],'one')
00582             self.assertEqual(ex._modifications[-2]['name'],'one')
00583             self.assertEqual(ex._modifications[-3]['name'],'one')
00584             ex.two = False
00585             self.assertEqual(ex._modifications[-1]['name'],'two')
00586             ex.ps.three.setValue(100) # MISSED
00587             #self.assertEqual(ex.ps._modifications.pop()['name'],'three')
00588             ex.ps.four = 'def'
00589             self.assertEqual(ex.ps._modifications[-1]['name'],'four')
00590             ex.vps[0].five = cms.string('beta')
00591             self.assertEqual(ex.vps[0]._modifications[-1]['name'],'five')
00592             ex.vps[1].__dict__['six'] = cms.vint32(1,4,9) # MISSED
00593             #self.assertEqual(ex.vps[1]._modifications[-1]['name'],'six')
00594             ex.seven[0] = 'delta' # MISSED
00595             #self.assertEqual(ex._modifications[-1]['name'],'seven')
00596             ex.eight.pop() # MISSED
00597             #self.assertEqual(ex._modifications[-1]['name'],'eight')
00598             del ex.nine
00599             #self.assertEqual(ex._modifications[-1]['name'],'nine')
00600             ex.newvpset = cms.VPSet()
00601             self.assertEqual(ex._modifications[-1]['name'],'newvpset')
00602             
00603             process = cms.Process('unittest')
00604             process.ex = ex
00605             mods = process.dumpModifications()
00606             self.assert_('process.ex.zero' in mods)
00607             self.assert_('process.ex.one' in mods)
00608             self.assert_('process.ex.two' in mods)
00609             #self.assert_('process.ex.three' in mods)
00610             self.assert_('process.ex.ps.four' in mods)
00611             self.assert_('process.ex.vps[0].five' in mods)
00612             #self.assert_('process.ex.vps[1].six' in mods)
00613             #self.assert_('process.ex.seven[0]' in mods)
00614             #self.assert_('process.ex.eight' in mods)
00615             self.assert_('process.ex.nine' in mods)
00616             self.assert_('process.ex.newvpset' in mods)
00617             
00618             
00619 
00620         def testSeq(self):
00621             process = cms.Process('unittest')
00622             for i in range(10):
00623               setattr(process,'f%s'%i,cms.EDFilter('f%s'%i))
00624             process.seq1 = cms.Sequence(process.f1*process.f2*process.f3)
00625             self.assertEqual(process.seq1._modifications,[])
00626             process.seq2 = cms.Sequence(process.f4+process.f5+process.f6)
00627             self.assertEqual(process.seq2._modifications,[])
00628             
00629             process.seq1.replace(process.f1,process.f0*process.f1)
00630             self.assertEqual(process.seq1._modifications[-1]['action'],'replace')
00631             
00632             process.seq2.remove(process.f5)
00633             self.assertEqual(process.seq2._modifications[-1]['action'],'remove')
00634             
00635             process.path = cms.Path(process.seq1*process.f7)
00636             self.assertEqual(process.path._modifications,[])
00637             
00638             process.path *= process.seq2
00639             self.assertEqual(process.path._modifications[-1]['action'],'append')
00640             process.path.remove(process.f6)
00641             self.assertEqual(process.path._modifications[-1]['action'],'remove')
00642             process.path.replace(process.f2,~process.f2)
00643             self.assertEqual(process.path._modifications[-1]['action'],'replace')
00644             
00645             mods = process.dumpModifications()
00646             self.assert_('process.seq1' in mods)
00647             self.assert_('process.seq2' in mods)
00648             self.assert_('process.path' in mods)
00649             
00650         def testdumpHistory(self):
00651             process = cms.Process('unittest')
00652             process.source=Source("PoolSource",fileNames = cms.untracked.string("file:file.root"))
00653             
00654             changeSource(process,"file:filename.root")
00655             self.assertEqual(changeSource._parameters['source'].value,"file:filename.root")
00656             
00657             changeSource(process,"file:filename2.root")
00658             self.assertEqual(changeSource._parameters['source'].value,"file:filename2.root")
00659             
00660             changeSource(process,"file:filename3.root")
00661             self.assertEqual(changeSource._parameters['source'].value,"file:filename3.root")
00662     
00663             self.assertEqual(process.dumpHistory(),"\nfrom FWCore.GuiBrowsers.editorTools import *\n\nchangeSource(process , 'file:filename.root')\n\n\nchangeSource(process , 'file:filename2.root')\n\n\nchangeSource(process , 'file:filename3.root')\n\n")
00664             
00665             process.source.fileNames=cms.untracked.vstring("file:replacedfile.root") 
00666             self.assertEqual(process.dumpHistory(),"\nfrom FWCore.GuiBrowsers.editorTools import *\n\nchangeSource(process , 'file:filename.root')\n\n\nchangeSource(process , 'file:filename2.root')\n\n\nchangeSource(process , 'file:filename3.root')\n\nprocess.source.fileNames = cms.untracked.vstring('file:replacedfile.root')\n")
00667             
00668             process.disableRecording()
00669             changeSource.setParameter('source',"file:filename4.root")
00670             action=changeSource.__copy__()
00671             process.addAction(action)
00672             self.assertEqual(process.dumpHistory(),"\nfrom FWCore.GuiBrowsers.editorTools import *\n\nchangeSource(process , 'file:filename.root')\n\n\nchangeSource(process , 'file:filename2.root')\n\n\nchangeSource(process , 'file:filename3.root')\n\nprocess.source.fileNames = cms.untracked.vstring('file:replacedfile.root')\n")
00673             
00674             process.enableRecording()
00675             changeSource.setParameter('source',"file:filename5.root")
00676             action=changeSource.__copy__()
00677             process.addAction(action)
00678             process.deleteAction(3)
00679             self.assertEqual(process.dumpHistory(),"\nfrom FWCore.GuiBrowsers.editorTools import *\n\nchangeSource(process , 'file:filename.root')\n\n\nchangeSource(process , 'file:filename2.root')\n\n\nchangeSource(process , 'file:filename3.root')\n\n\nchangeSource(process , 'file:filename5.root')\n\n")
00680 
00681             process.deleteAction(0)
00682             self.assertEqual(process.dumpHistory(),"\nfrom FWCore.GuiBrowsers.editorTools import *\n\nchangeSource(process , 'file:filename2.root')\n\n\nchangeSource(process , 'file:filename3.root')\n\n\nchangeSource(process , 'file:filename5.root')\n\n")
00683             
00684         def testModifiedObjectsHistory(self):
00685             process = cms.Process('unittest')
00686             process.source=Source("PoolSource",fileNames = cms.untracked.string("file:file.root"))
00687             
00688             changeSource(process,"file:filename.root")
00689             self.assertEqual(len(process.history()[0][1]),1)
00690             
00691             process.source.fileNames=cms.untracked.vstring("file:replacedfile.root") 
00692             self.assertEqual(len(process.history()[0][1]),1)
00693             self.assertEqual(len(process.history()[1][1]),1)
00694 
00695             process.source.fileNames=["test2"]
00696             self.assertEqual(len(process.history()[0][1]),1)
00697             self.assertEqual(len(process.history()[1][1]),1)
00698 
00699             changeSource(process,"file:filename2.root")
00700             self.assertEqual(len(process.history()[0][1]),1)
00701             self.assertEqual(len(process.history()[1][1]),1)
00702             self.assertEqual(len(process.history()[2][1]),1)
00703             
00704             process.source.fileNames=cms.untracked.vstring("file:replacedfile2.root") 
00705             self.assertEqual(len(process.history()[0][1]),1)
00706             self.assertEqual(len(process.history()[1][1]),1)
00707             self.assertEqual(len(process.history()[2][1]),1)
00708             self.assertEqual(len(process.history()[3][1]),1)
00709             
00710     unittest.main()
00711