Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
from .SequenceTypes import *
from .Modules import OutputModule, EDProducer, EDFilter, EDAnalyzer, Service, ESProducer, ESSource, _Module
from .Mixins import _Labelable

# Use this on Tasks in the Schedule
class ScheduleTaskValidator(object):
    def __init__(self):
        pass
    def enter(self,visitee):
        if visitee.isLeaf():
            if isinstance(visitee, _Labelable):
                if not visitee.hasLabel_():
                    raise ValueError("A task associated with the Schedule contains a module of type '"+visitee.type_()+"'\nwhich has no assigned label.")
            elif isinstance(visitee, Service):
                if not visitee._inProcess:
                    raise ValueError("A task associated with the Schedule contains a service of type '"+visitee.type_()+"'\nwhich is not attached to the process.")
    def leave(self,visitee):
        pass

# Use this on Paths
class PathValidator(object):
    def __init__(self):
        self.__label = ''
    def setLabel(self,label:str):
        self.__label = "'"+label+"' "
    def enter(self,visitee):
        if isinstance(visitee,OutputModule):
            raise ValueError("Path "+self.__label+"cannot contain an OutputModule, '"+visitee.type_()+"', with label '"+visitee.label_()+"'")
        if visitee.isLeaf():
            if isinstance(visitee, _Labelable):
                if not visitee.hasLabel_():
                    raise ValueError("Path "+self.__label+"contains a module of type '"+visitee.type_()+"' which has no assigned label.")
            elif isinstance(visitee, Service):
                if not visitee._inProcess:
                    raise ValueError("Path "+self.__label+"contains a service of type '"+visitee.type_()+"' which is not attached to the process.\n")
    def leave(self,visitee):
        pass

# Use this on EndPaths
class EndPathValidator(object):
    _presetFilters = ["TriggerResultsFilter", "HLTPrescaler"]
    def __init__(self):   
        self.filtersOnEndpaths = []
        self.__label = ''
        self._levelInTasks = 0
    def setLabel(self,label:str):
        self.__label = "'"+label+"' "
    def enter(self,visitee):
        if visitee.isLeaf():
            if isinstance(visitee, _Labelable):
                if not visitee.hasLabel_():
                    raise ValueError("EndPath "+self.__label+"contains a module of type '"+visitee.type_()+"' which has\nno assigned label.")
            elif isinstance(visitee, Service):
                if not visitee._inProcess:
                    raise ValueError("EndPath "+self.__label+"contains a service of type '"+visitee.type_()+"' which is not attached to the process.\n")
        if isinstance(visitee, Task):
            self._levelInTasks += 1
        if self._levelInTasks > 0:
            return
        if isinstance(visitee,EDFilter):
            if (visitee.type_() in self._presetFilters):
                if (visitee.type_() not in self.filtersOnEndpaths):
                    self.filtersOnEndpaths.append(visitee.type_())
    def leave(self,visitee):
        if self._levelInTasks > 0:
            if isinstance(visitee, Task):
                self._levelInTasks -= 1

class NodeVisitor(object):
    """Form sets of all modules, ESProducers, ESSources and Services in visited objects. Can be used
    to visit Paths, EndPaths, Sequences or Tasks. Includes in sets objects on sub-Sequences and sub-Tasks"""
    def __init__(self):
        self.modules = set()
        self.esProducers = set()
        self.esSources = set()
        self.services = set()
    def enter(self,visitee):
        if visitee.isLeaf():
            if isinstance(visitee, _Module):
                self.modules.add(visitee)
            elif isinstance(visitee, ESProducer):
                self.esProducers.add(visitee)
            elif isinstance(visitee, ESSource):
                self.esSources.add(visitee)
            elif isinstance(visitee, Service):
                self.services.add(visitee)
    def leave(self,visitee):
        pass

class CompositeVisitor(object):
    """ Combines 3 different visitor classes in 1 so we only have to visit all the paths and endpaths once"""
    def __init__(self, validator, node, decorated, optional=None):
        self._validator = validator
        self._node = node
        self._decorated = decorated
        self._optional = optional
    def enter(self, visitee):
        self._validator.enter(visitee)
        self._node.enter(visitee)
        self._decorated.enter(visitee)
        if self._optional:
          self._optional.enter(visitee)
    def leave(self, visitee):
        self._validator.leave(visitee)
        # The node visitor leave function does nothing
        #self._node.leave(visitee)
        self._decorated.leave(visitee)
        if self._optional:
          self._optional.leave(visitee)

class ModuleNamesFromGlobalsVisitor(object):
    """Fill a list with the names of Event module types in a sequence. The names are determined
    by using globals() to lookup the variable names assigned to the modules. This
    allows the determination of the labels before the modules have been attached to a Process."""
    def __init__(self,globals_,l):
        self._moduleToName = { v[1]:v[0] for v in globals_.items() if isinstance(v[1],_Module) }
        self._names =l
    def enter(self,node):
        if isinstance(node,_Module):
            self._names.append(self._moduleToName[node])
    def leave(self,node):
        return

if __name__=="__main__":
    import unittest
    class TestModuleCommand(unittest.TestCase):
        def setUp(self):
            """Nothing to do """
            pass
        def testValidators(self):
            producer = EDProducer("Producer")
            analyzer = EDAnalyzer("Analyzer")
            output = OutputModule("Out")
            filter = EDFilter("Filter")
            unlabeled = EDAnalyzer("UnLabeled")
            producer.setLabel("producer")
            analyzer.setLabel("analyzer")
            output.setLabel("output")
            filter.setLabel("filter")
            s1 = Sequence(analyzer*producer)
            s2 = Sequence(output+filter)
            p1 = Path(s1)
            p2 = Path(s1*s2)
            p3 = Path(s1+unlabeled)
            ep1 = EndPath(producer+output+analyzer)
            ep2 = EndPath(filter+output)
            ep3 = EndPath(s2)
            ep4 = EndPath(unlabeled)
            pathValidator = PathValidator()
            endpathValidator = EndPathValidator()
            p1.visit(pathValidator)
            self.assertRaises(ValueError, p2.visit, pathValidator) 
            self.assertRaises(ValueError, p3.visit, pathValidator) 
            ep1.visit(endpathValidator) 
            ep2.visit(endpathValidator) 
            ep3.visit(endpathValidator) 
            self.assertRaises(ValueError, ep4.visit, endpathValidator) 

    unittest.main()