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