Source code for radical.utils.tracer


__author__    = "Radical.Utils Development Team (Andre Merzky)"
__copyright__ = "Copyright 2013, RADICAL@Rutgers"
__license__   = "MIT"


import sys
import linecache

_trace_external  = True
_trace_namespace = 'radical'
_trace_logger    = None


# ------------------------------------------------------------------------------
#
'''
  kudos:
  http://www.dalkescientific.com/writings/diary/archive/2005/04/20/\
                                                        tracing_python_code.html


  This module will trace all python function calls, printing each line as it is
  being executed.  It will not print traces for system libraries (i.e. modules
  which are not in the configured namespace), but will indicate when the code
  descents to the system level.

  Python system traces are not following Python's `exec()` call (and
  derivatives), so the resulting trace may be incomplete.   The tracer
  may also fail to step through loaded plugins or adaptors.

  Use like this::

      def my_call(url):

          ru.tracer.trace('radical')

          u = radical.Url(url_str)
          print str(u)

          ru.tracer.untrace()

'''


# ------------------------------------------------------------------------------
#
def _tracer(frame, event, _):

    global _trace_external                               # pylint: disable=W0603

  # if  event == "call":
    if  event == "line":

        filename = frame.f_globals["__file__"]
        lineno   = frame.f_lineno

        if filename.endswith(".pyc") or \
           filename.endswith(".pyo"):
            filename = filename[:-1]

        line = linecache.getline(filename, lineno)

        if _trace_namespace in filename:

            idx  = filename.rindex(_trace_namespace)
            name = filename[idx:]
            if _trace_logger:
                _trace_logger.debug('[trace]: %s %4d %s', name, lineno, line.rstrip())
            else:
                print("%-60s:%4d: %s" % (name, lineno, line.rstrip()))
            _trace_external = False

        else:

            if not _trace_external:
                name = '/'.join(filename.split('/')[-3:])
                if _trace_logger:
                    _trace_logger.debug('[trace]: %s %4d %s', name, lineno, line.rstrip())
                else:
                    print("--> %-56s:%4d: %s" % (name, lineno, line.rstrip()))
            _trace_external = True

    return _tracer


# ------------------------------------------------------------------------------
[docs]def trace(namespace='radical', log=None): global _trace_namespace # pylint: disable=W0603 global _trace_logger # pylint: disable=W0603 _trace_namespace = namespace _trace_logger = log sys.stdout.write('---------------- start trace [%s]\n' % namespace) sys.stdout.flush() sys.settrace(_tracer)
# ------------------------------------------------------------------------------
[docs]def untrace(): sys.settrace(None) sys.stdout.write('---------------- stop trace\n') sys.stdout.flush()
# ------------------------------------------------------------------------------