layers.py (5064B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 import traceback 5 6 from mozperftest.utils import MachLogger 7 8 9 class StopRunError(Exception): 10 pass 11 12 13 class Layer(MachLogger): 14 # layer name 15 name = "unset" 16 17 # activated by default ? 18 activated = False 19 20 # list of arguments grabbed by PerftestArgumentParser 21 arguments = {} 22 23 # If true, calls on_exception() on errors 24 user_exception = False 25 26 def __init__(self, env, mach_command): 27 MachLogger.__init__(self, mach_command) 28 self.return_code = 0 29 self.mach_cmd = mach_command 30 self.run_process = mach_command.run_process 31 self.env = env 32 33 def _normalize_arg(self, name): 34 if name.startswith("--"): 35 name = name[2:] 36 if not name.startswith(self.name): 37 name = "%s-%s" % (self.name, name) 38 return name.replace("-", "_") 39 40 def get_arg_names(self): 41 return [self._normalize_arg(arg) for arg in self.arguments] 42 43 def set_arg(self, name, value): 44 """Sets the argument""" 45 name = self._normalize_arg(name) 46 if name not in self.get_arg_names(): 47 raise KeyError( 48 "%r tried to set %r, but does not own it" % (self.name, name) 49 ) 50 return self.env.set_arg(name, value) 51 52 def get_arg(self, name, default=None): 53 return self.env.get_arg(name, default, self) 54 55 def __enter__(self): 56 self.info("Running %s:setup" % self.name) 57 self.setup() 58 return self 59 60 def __exit__(self, type, value, traceback): 61 # XXX deal with errors here 62 self.info("Running %s:teardown" % self.name) 63 self.teardown() 64 65 def __call__(self, metadata): 66 has_exc_handler = self.env.hooks.exists("on_exception") 67 self.info("Running %s:run" % self.name) 68 try: 69 metadata = self.run(metadata) 70 except Exception as e: 71 if self.user_exception and has_exc_handler: 72 self.error("User handled error") 73 for line in traceback.format_exc().splitlines(): 74 self.error(line) 75 resume_run = self.env.hooks.run("on_exception", self.env, self, e) 76 if resume_run: 77 return metadata 78 raise StopRunError() 79 else: 80 raise 81 return metadata 82 83 def setup(self): 84 pass 85 86 def teardown(self): 87 pass 88 89 def run(self, metadata): 90 return metadata 91 92 93 class Layers(Layer): 94 def __init__(self, env, mach_command, factories): 95 super().__init__(env, mach_command) 96 97 def _active(layer): 98 # if it's activated by default, see if we need to deactivate 99 # it by looking for the --no-layername option 100 if layer.activated: 101 return not env.get_arg("no-" + layer.name, False) 102 # if it's deactivated by default, we look for --layername 103 return env.get_arg(layer.name, False) 104 105 self.layers = [ 106 factory(env, mach_command) for factory in factories if _active(factory) 107 ] 108 self.env = env 109 self._counter = -1 110 111 def _normalize_arg(self, name): 112 if name.startswith("--"): 113 name = name[2:] 114 return name.replace("-", "_") 115 116 def get_layer(self, name): 117 for layer in self.layers: 118 if layer.name == name: 119 return layer 120 return None 121 122 @property 123 def name(self): 124 return " + ".join([l.name for l in self.layers]) 125 126 def __iter__(self): 127 self._counter = -1 128 return self 129 130 def __next__(self): 131 self._counter += 1 132 try: 133 return self.layers[self._counter] 134 except IndexError: 135 raise StopIteration 136 137 def __enter__(self): 138 self.setup() 139 return self 140 141 def __exit__(self, type, value, traceback): 142 # XXX deal with errors here 143 self.teardown() 144 145 def setup(self): 146 for layer in self.layers: 147 self.debug("Running %s:setup" % layer.name) 148 layer.setup() 149 150 def teardown(self): 151 for layer in self.layers: 152 self.debug("Running %s:teardown" % layer.name) 153 layer.teardown() 154 155 def __call__(self, metadata): 156 for layer in self.layers: 157 metadata = layer(metadata) 158 return metadata 159 160 def set_arg(self, name, value): 161 """Sets the argument""" 162 name = self._normalize_arg(name) 163 found = False 164 for layer in self.layers: 165 if name in layer.get_arg_names(): 166 found = True 167 break 168 169 if not found: 170 raise KeyError( 171 "%r tried to set %r, but does not own it" % (self.name, name) 172 ) 173 174 return self.env.set_arg(name, value) 175 176 def get_arg(self, name, default=None): 177 return self.env.get_arg(name, default)