1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4""" 5Backend management. 6 7 8Creating new backends 9--------------------- 10 11A new backend named 'foo-bar' corresponds to Python module 12'tracetool/backend/foo_bar.py'. 13 14A backend module should provide a docstring, whose first non-empty line will be 15considered its short description. 16 17All backends must generate their contents through the 'tracetool.out' routine. 18 19 20Backend attributes 21------------------ 22 23========= ==================================================================== 24Attribute Description 25========= ==================================================================== 26PUBLIC If exists and is set to 'True', the backend is considered "public". 27========= ==================================================================== 28 29 30Backend functions 31----------------- 32 33======== ======================================================================= 34Function Description 35======== ======================================================================= 36<format> Called to generate the format- and backend-specific code for each of 37 the specified events. If the function does not exist, the backend is 38 considered not compatible with the given format. 39======== ======================================================================= 40""" 41 42__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" 43__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>" 44__license__ = "GPL version 2 or (at your option) any later version" 45 46__maintainer__ = "Stefan Hajnoczi" 47__email__ = "stefanha@linux.vnet.ibm.com" 48 49 50import os 51 52import tracetool 53 54 55def get_list(only_public = False): 56 """Get a list of (name, description) pairs.""" 57 res = [("nop", "Tracing disabled.")] 58 modnames = [] 59 for filename in os.listdir(tracetool.backend.__path__[0]): 60 if filename.endswith('.py') and filename != '__init__.py': 61 modnames.append(filename.rsplit('.', 1)[0]) 62 for modname in modnames: 63 module = tracetool.try_import("tracetool.backend." + modname) 64 65 # just in case; should never fail unless non-module files are put there 66 if not module[0]: 67 continue 68 module = module[1] 69 70 public = getattr(module, "PUBLIC", False) 71 if only_public and not public: 72 continue 73 74 doc = module.__doc__ 75 if doc is None: 76 doc = "" 77 doc = doc.strip().split("\n")[0] 78 79 name = modname.replace("_", "-") 80 res.append((name, doc)) 81 return res 82 83 84def exists(name): 85 """Return whether the given backend exists.""" 86 if len(name) == 0: 87 return False 88 if name == "nop": 89 return True 90 name = name.replace("-", "_") 91 return tracetool.try_import("tracetool.backend." + name)[1] 92 93 94def compatible(backend, format): 95 """Whether a backend is compatible with the given format.""" 96 if not exists(backend): 97 raise ValueError("unknown backend: %s" % backend) 98 99 backend = backend.replace("-", "_") 100 format = format.replace("-", "_") 101 102 if backend == "nop": 103 return True 104 else: 105 func = tracetool.try_import("tracetool.backend." + backend, 106 format, None)[1] 107 return func is not None 108 109 110def _empty(events): 111 pass 112 113def generate(backend, format, events): 114 """Generate the per-event output for the given (backend, format) pair.""" 115 if not compatible(backend, format): 116 raise ValueError("backend '%s' not compatible with format '%s'" % 117 (backend, format)) 118 119 backend = backend.replace("-", "_") 120 format = format.replace("-", "_") 121 122 if backend == "nop": 123 func = tracetool.try_import("tracetool.format." + format, 124 "nop", _empty)[1] 125 else: 126 func = tracetool.try_import("tracetool.backend." + backend, 127 format, None)[1] 128 129 func(events) 130