[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as
From: |
Alon Levy |
Subject: |
Re: [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as python modules |
Date: |
Tue, 27 Mar 2012 17:21:53 +0200 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
On Mon, Mar 26, 2012 at 07:37:50PM +0200, Lluís Vilanova wrote:
An additional comment I forgot to add.
> Signed-off-by: Lluís Vilanova <address@hidden>
> ---
[snip]
> + def __str__(self):
> + """String suitable for declaring function arguments."""
> + if len(self._args) == 0:
> + return "void"
> + else:
> + return ", ".join([ " ".join([t, n]) for t,n in self._args ])
> +
Nice to have addition (for debugging mainly):
+ def __repr__(self):
+ """String suitable to recreate this instance."""
+ return '%s("%s")' % (self.__class__.__name__, str(self))
+
> + def names(self):
> + """List of argument names."""
> + return [ name for _, name in self._args ]
> +
> + def types(self):
> + """List of argument types."""
> + return [ type_ for type_, _ in self._args ]
> +
> +
> +class Event(object):
> + """Event description.
> +
> + Parameters
> + ----------
> + line : str
> + Line describing the event.
> +
> + Attributes
> + ----------
> + name : str
> + The event name.
> + fmt : str
> + The event format string.
> + properties : set(str)
> + Properties of the event.
> + args : Arguments
> + The event arguments.
> + """
> +
> + _CRE =
> re.compile("((?P<props>.*)\s+)?(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?")
> +
> + _VALID_PROPS = set(["disable"])
> +
> + def __init__(self, line):
> + m = self._CRE.match(line)
> + assert m is not None
> + groups = m.groupdict('')
> + self.name = groups["name"]
> + self.fmt = groups["fmt"]
> + self.properties = groups["props"].split()
> + self.args = Arguments(groups["args"])
> +
> + unknown_props = set(self.properties) - self._VALID_PROPS
> + if len(unknown_props) > 0:
> + raise ValueError("Unknown properties: %s" % ",
> ".join(unknown_props))
> +
> +
> +def _read_events(fobj):
> + res = []
> + for line in fobj:
> + if not line.strip():
> + continue
> + if line.lstrip().startswith('#'):
> + continue
> + res.append(Event(line))
> + return res
> +
> +
> +class TracetoolError (Exception):
> + """Exception for calls to generate."""
> + pass
> +
> +
> +def try_import(mod_name, attr_name = None, attr_default = None):
> + """Try to import a module and get an attribute from it.
> +
> + Parameters
> + ----------
> + mod_name : str
> + Module name.
> + attr_name : str, optional
> + Name of an attribute in the module.
> + attr_default : optional
> + Default value if the attribute does not exist in the module.
> +
> + Returns
> + -------
> + A pair indicating whether the module could be imported and the module or
> + object or attribute value.
> + """
> + mod_name = mod_name.replace("-", "_")
> + try:
> + module = __import__(mod_name, fromlist=["__package__"])
> + if attr_name is None:
> + return True, module
> + return True, getattr(module, str(attr_name), attr_default)
> + except ImportError:
> + return False, None
> +
> +
> +def generate(fevents, format, backend, **options):
> + """Generate the output for the given (format, backend) pair."""
> + # fix strange python error (UnboundLocalError tracetool)
> + import tracetool
> +
> + if len(options) > 0:
> + raise ValueError("unknown options: " + ", ".join(options))
> +
> + format = str(format)
> + if len(format) is 0:
> + raise TracetoolError("format not set")
> + mformat = format.replace("-", "_")
> + if not tracetool.format.exists(mformat):
> + raise TracetoolError("unknown format: %s" % format)
> +
> + backend = str(backend)
> + if len(backend) is 0:
> + raise TracetoolError("backend not set")
> + mbackend = backend.replace("-", "_")
> + if not tracetool.backend.exists(mbackend):
> + raise TracetoolError("unknown backend: %s" % backend)
> +
> + if not tracetool.backend.compatible(mbackend, mformat):
> + raise TracetoolError("backend '%s' not compatible with format '%s'" %
> + (backend, format))
> +
> + events = _read_events(fevents)
> +
> + if backend == "nop":
> + ( e.properies.add("disable") for e in events )
> +
> + tracetool.format.generate_begin(mformat, events)
> + tracetool.backend.generate("nop", format,
> + [ e
> + for e in events
> + if "disable" in e.properties ])
> + tracetool.backend.generate(backend, format,
> + [ e
> + for e in events
> + if "disable" not in e.properties ])
> + tracetool.format.generate_end(mformat, events)
> diff --git a/scripts/tracetool/backend/__init__.py
> b/scripts/tracetool/backend/__init__.py
> new file mode 100644
> index 0000000..23cad9f
> --- /dev/null
> +++ b/scripts/tracetool/backend/__init__.py
> @@ -0,0 +1,114 @@
> +#!/usr/bin/env python
> +# -*- coding: utf-8 -*-
> +
> +"""
> +Backend management.
> +
> +
> +Creating new backends
> +---------------------
> +
> +A new backend named 'foo-bar' corresponds to Python module
> +'tracetool/backend/foo_bar.py'.
> +
> +A backend module should provide a docstring, whose first non-empty line will
> be
> +considered its short description.
> +
> +All backends must generate their contents through the 'tracetool.out'
> routine.
> +
> +
> +Backend attributes
> +------------------
> +
> +=========
> ====================================================================
> +Attribute Description
> +=========
> ====================================================================
> +PUBLIC If exists and is set to 'True', the backend is considered "public".
> +=========
> ====================================================================
> +
> +
> +Backend functions
> +-----------------
> +
> +========
> =======================================================================
> +Function Description
> +========
> =======================================================================
> +<format> Called to generate the format- and backend-specific code for each of
> + the specified events. If the function does not exist, the backend is
> + considered not compatible with the given format.
> +========
> =======================================================================
> +"""
> +
> +__author__ = "Lluís Vilanova <address@hidden>"
> +__copyright__ = "Copyright 2012, Lluís Vilanova <address@hidden>"
> +__license__ = "GPL version 2 or (at your option) any later version"
> +
> +__maintainer__ = "Stefan Hajnoczi"
> +__email__ = "address@hidden"
> +
> +
> +import pkgutil
> +
> +import tracetool
> +
> +
> +def get_list(only_public = False):
> + """Get a list of (name, description) pairs."""
> + res = [("nop", "Tracing disabled.")]
> + for _, modname, _ in pkgutil.iter_modules(tracetool.backend.__path__):
> + module = tracetool.try_import("tracetool.backend." + modname)[1]
> +
> + public = getattr(module, "PUBLIC", False)
> + if only_public and not public:
> + continue
> +
> + doc = module.__doc__
> + if doc is None:
> + doc = ""
> + doc = doc.strip().split("\n")[0]
> +
> + name = modname.replace("_", "-")
> + res.append((name, doc))
> + return res
> +
> +
> +def exists(name):
> + """Return whether the given backend exists."""
> + if len(name) == 0:
> + return False
> + name = name.replace("-", "_")
> + if name == "nop":
> + return True
> + return tracetool.try_import("tracetool.backend." + name)[1]
> +
> +
> +def compatible(backend, format):
> + """Whether a backend is compatible with the given format."""
> + if not exists(backend):
> + raise ValueError("unknown backend: %s" % backend)
> +
> + if backend == "nop":
> + return True
> + else:
> + func = tracetool.try_import("tracetool.backend." + backend,
> + format, None)[1]
> + return func is not None
> +
> +
> +def _empty(events):
> + pass
> +
> +def generate(backend, format, events):
> + """Generate the per-event output for the given (backend, format) pair."""
> + if not compatible(backend, format):
> + raise ValueError("backend '%s' not compatible with format '%s'" %
> + (backend, format))
> +
> + if backend == "nop":
> + func = tracetool.try_import("tracetool.format." + format,
> + "nop", _empty)[1]
> + else:
> + func = tracetool.try_import("tracetool.backend." + backend,
> + format, None)[1]
> +
> + func(events)
> diff --git a/scripts/tracetool/format/__init__.py
> b/scripts/tracetool/format/__init__.py
> new file mode 100644
> index 0000000..5b37c00
> --- /dev/null
> +++ b/scripts/tracetool/format/__init__.py
> @@ -0,0 +1,91 @@
> +#!/usr/bin/env python
> +# -*- coding: utf-8 -*-
> +
> +"""
> +Format management.
> +
> +
> +Creating new formats
> +--------------------
> +
> +A new format named 'foo-bar' corresponds to Python module
> +'tracetool/frontend/foo_bar.py'.
> +
> +A frontend module should provide a docstring, whose first non-empty line
> will be
> +considered its short description.
> +
> +All formats must generate their contents through the 'tracetool.out' routine.
> +
> +
> +Format functions
> +----------------
> +
> +All the following functions are optional, and no output will be generated if
> +they do not exist.
> +
> +========
> =======================================================================
> +Function Description
> +========
> =======================================================================
> +begin Called to generate the format-specific file header.
> +end Called to generate the format-specific file footer.
> +nop Called to generate the per-event contents when the event is
> disabled or
> + the selected backend is 'nop'.
> +========
> =======================================================================
> +"""
> +
> +__author__ = "Lluís Vilanova <address@hidden>"
> +__copyright__ = "Copyright 2012, Lluís Vilanova <address@hidden>"
> +__license__ = "GPL version 2 or (at your option) any later version"
> +
> +__maintainer__ = "Stefan Hajnoczi"
> +__email__ = "address@hidden"
> +
> +
> +import pkgutil
> +
> +import tracetool
> +
> +
> +def get_list():
> + """Get a list of (name, description) pairs."""
> + res = []
> + for _, modname, _ in pkgutil.iter_modules(tracetool.format.__path__):
> + module = tracetool.try_import("tracetool.format." + modname)[1]
> +
> + doc = module.__doc__
> + if doc is None:
> + doc = ""
> + doc = doc.strip().split("\n")[0]
> +
> + name = modname.replace("_", "-")
> + res.append((name, doc))
> + return res
> +
> +
> +def exists(name):
> + """Return whether the given format exists."""
> + if len(name) == 0:
> + return False
> + return tracetool.try_import("tracetool.format." + name)[1]
> +
> +
> +def _empty(events):
> + pass
> +
> +def generate_begin(name, events):
> + """Generate the header of the format-specific file."""
> + if not exists(name):
> + raise ValueError("unknown format: %s" % name)
> +
> + func = tracetool.try_import("tracetool.format." + name,
> + "begin", _empty)[1]
> + func(events)
> +
> +def generate_end(name, events):
> + """Generate the footer of the format-specific file."""
> + if not exists(name):
> + raise ValueError("unknown format: %s" % name)
> +
> + func = tracetool.try_import("tracetool.format." + name,
> + "end", _empty)[1]
> + func(events)
>
>
- [Qemu-devel] [RFC PATCH v2 0/8] Rewrite tracetool using python modules, Lluís Vilanova, 2012/03/26
- [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as python modules, Lluís Vilanova, 2012/03/26
- Re: [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as python modules, Alon Levy, 2012/03/27
- Re: [Qemu-devel] [RFC PATCH v2 1/8] tracetool: Rewrite infrastructure as python modules,
Alon Levy <=
- [Qemu-devel] [PATCH] tracetool.py: always pass --binary, --target-arch, --target-type, Alon Levy, 2012/03/27
- Re: [Qemu-devel] [PATCH] tracetool.py: always pass --binary, --target-arch, --target-type, Lluís Vilanova, 2012/03/27
- Re: [Qemu-devel] [PATCH] tracetool.py: always pass --binary, --target-arch, --target-type, Alon Levy, 2012/03/28
- Re: [Qemu-devel] [PATCH] tracetool.py: always pass --binary, --target-arch, --target-type, Lluís Vilanova, 2012/03/28
[Qemu-devel] [RFC PATCH v2 2/8] tracetool: Add module for the 'c' format, Lluís Vilanova, 2012/03/26
[Qemu-devel] [RFC PATCH v2 3/8] tracetool: Add module for the 'h' format, Lluís Vilanova, 2012/03/26
[Qemu-devel] [RFC PATCH v2 4/8] tracetool: Add support for the 'stderr' backend, Lluís Vilanova, 2012/03/26
[Qemu-devel] [RFC PATCH v2 5/8] tracetool: Add support for the 'simple' backend, Lluís Vilanova, 2012/03/26
[Qemu-devel] [RFC PATCH v2 6/8] tracetool: Add support for the 'ust' backend, Lluís Vilanova, 2012/03/26
[Qemu-devel] [RFC PATCH v2 8/8] tracetool: Add MAINTAINERS info, Lluís Vilanova, 2012/03/26