Revision ed54b47e qa/qa_utils.py

b/qa/qa_utils.py
39 39
_RESET_SEQ = None
40 40

  
41 41

  
42
# List of all hooks
43
_hooks = []
44

  
45

  
46 42
def _SetupColours():
47 43
  """Initializes the colour constants.
48 44

  
......
225 221
FormatWarning = lambda text: _FormatWithColor(text, _WARNING_SEQ)
226 222
FormatError = lambda text: _FormatWithColor(text, _ERROR_SEQ)
227 223
FormatInfo = lambda text: _FormatWithColor(text, _INFO_SEQ)
228

  
229

  
230
def LoadHooks():
231
  """Load all QA hooks.
232

  
233
  """
234
  hooks_dir = qa_config.get('options', {}).get('hooks-dir', None)
235
  if not hooks_dir:
236
    return
237
  if hooks_dir not in sys.path:
238
    sys.path.insert(0, hooks_dir)
239
  for name in utils.ListVisibleFiles(hooks_dir):
240
    if name.endswith('.py'):
241
      # Load and instanciate hook
242
      print "Loading hook %s" % name
243
      _hooks.append(__import__(name[:-3], None, None, ['']).hook())
244

  
245

  
246
class QaHookContext:
247
  """Definition of context passed to hooks.
248

  
249
  """
250
  name = None
251
  phase = None
252
  success = None
253
  args = None
254
  kwargs = None
255

  
256

  
257
def _CallHooks(ctx):
258
  """Calls all hooks with the given context.
259

  
260
  """
261
  if not _hooks:
262
    return
263

  
264
  name = "%s-%s" % (ctx.phase, ctx.name)
265
  if ctx.success is not None:
266
    msg = "%s (success=%s)" % (name, ctx.success)
267
  else:
268
    msg = name
269
  print FormatInfo("Begin %s" % msg)
270
  for hook in _hooks:
271
    hook.run(ctx)
272
  print FormatInfo("End %s" % name)
273

  
274

  
275
def DefineHook(name):
276
  """Wraps a function with calls to hooks.
277

  
278
  Usage: prefix function with @qa_utils.DefineHook(...)
279

  
280
  This is based on PEP 318, "Decorators for Functions and Methods".
281

  
282
  """
283
  def wrapper(fn):
284
    def new_f(*args, **kwargs):
285
      # Create context
286
      ctx = QaHookContext()
287
      ctx.name = name
288
      ctx.phase = 'pre'
289
      ctx.args = args
290
      ctx.kwargs = kwargs
291

  
292
      _CallHooks(ctx)
293
      try:
294
        ctx.phase = 'post'
295
        ctx.success = True
296
        try:
297
          # Call real function
298
          return fn(*args, **kwargs)
299
        except:
300
          ctx.success = False
301
          raise
302
      finally:
303
        _CallHooks(ctx)
304

  
305
    # Override function metadata
306
    new_f.func_name = fn.func_name
307
    new_f.func_doc = fn.func_doc
308

  
309
    return new_f
310

  
311
  return wrapper

Also available in: Unified diff