From 918eef73541503570270ae228e4736a3f1e3e0d8 Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauld.mccarthy@gmail.com> Date: Tue, 29 Mar 2016 14:16:15 +0100 Subject: [PATCH] Removed fsl.utils.trace module (it has been moved to the props project) --- apidoc/fsl.utils.trace.rst | 9 -- fsl/__init__.py | 4 +- fsl/utils/__init__.py | 1 - fsl/utils/trace.py | 290 ------------------------------------- 4 files changed, 2 insertions(+), 302 deletions(-) delete mode 100644 apidoc/fsl.utils.trace.rst delete mode 100644 fsl/utils/trace.py diff --git a/apidoc/fsl.utils.trace.rst b/apidoc/fsl.utils.trace.rst deleted file mode 100644 index 757d1041f..000000000 --- a/apidoc/fsl.utils.trace.rst +++ /dev/null @@ -1,9 +0,0 @@ -:orphan: - -fsl.utils.trace module -====================== - -.. automodule:: fsl.utils.trace - :members: - :undoc-members: - :show-inheritance: diff --git a/fsl/__init__.py b/fsl/__init__.py index 7dea070a8..2db3ef495 100644 --- a/fsl/__init__.py +++ b/fsl/__init__.py @@ -511,9 +511,9 @@ def _parseTopLevelArgs(argv, allTools): # things if its logging level has been # set to DEBUG, so we import it now so # it can set itself up. - traceLogger = logging.getLogger('fsl.utils.trace') + traceLogger = logging.getLogger('props.trace') if traceLogger.getEffectiveLevel() <= logging.DEBUG: - import fsl.utils.trace + import props.trace fslTool = _loadFSLTool(namespace.tool) diff --git a/fsl/utils/__init__.py b/fsl/utils/__init__.py index adc72952d..299bbaf0f 100644 --- a/fsl/utils/__init__.py +++ b/fsl/utils/__init__.py @@ -19,7 +19,6 @@ things. ~fsl.utils.dialog ~fsl.utils.runwindow ~fsl.utils.webpage - ~fsl.utils.trace ~fsl.utils.status ~fsl.utils.memoize ~fsl.utils.async diff --git a/fsl/utils/trace.py b/fsl/utils/trace.py deleted file mode 100644 index c06723be5..000000000 --- a/fsl/utils/trace.py +++ /dev/null @@ -1,290 +0,0 @@ -#!/usr/bin/env python -# -# trace.py - debugging functions -# -# Author: Paul McCarthy <pauldmccarthy@gmail.com> -# -"""This module provides some useful logging/debugging functions. - -.. warning:: This module is not intended for general use - it is solely for - development/debugging purposes. Do not use it unless you know - know what you are doing. - - -.. warning:: When this module is imported, it monkey patches the - :class:`props.callqueue.CallQueue` class in a devious and - dangerous manner to allow for more informative debug statements. - Therefore it's a bad idea to even import this module, unless - you really know what you are doing. - - -.. warning:: Just don't import this module, ok? - - -The functions provided by this module are as follows: - -.. autosummary:: - trace - setcause - propchange -""" - -import logging -import inspect -import os.path as op - - -log = logging.getLogger(__name__) - - -# If trace debugging is enabled, we're going to -# do some funky stuff to the props callqueue -# object, so we can get some extra information -# in the propchange function. -if log.getEffectiveLevel() == logging.DEBUG: - - log.debug('Monkey-patching props.properties_value.queue instance') - - import props - import Queue - - # The problem that I am addressing here is the - # fact that, when a property value listener is - # called, the cause of the call (i.e. the point - # at which the property value was changed) does - # not necessarily exist in the stack. This is - # because when a PV instance passes all of its - # listeners to the CallQueue (CQ) to call, the - # CQ will queue them immediately, but will not - # necessarily call them - they are only called - # if the CQ is not already processing the - # listeners from another PV change. - - # A single CallQueue instance is shared - # by all PropertyValue instances to queue/ - # call property value listeners. - theQ = props.properties_value.PropertyValue.queue - - - def tracePop(*args, **kwargs): - - # When the CallQueue calls its _pop - # method, it will call the returned - # function. For debugging purposes, - # we'll pop the associated cause - # (enqueued in the tracePush function - # below), so the propchange function - # can print it out. - # - # This will throw Queue.EmptyError if - # the _causes queue is empty, but - # that is what the real _pop method - # does anyway. - try: theQ._currentCause = theQ._causes.get_nowait() - except: theQ._currentCause = None - - return theQ._realPop(*args, **kwargs) - - - def tracePush(*args, **kwargs): - - pushed = theQ._realPush(*args, **kwargs) - - # If the real _push method returns False, - # it means that the function was not enqueued - if not pushed: - return False - - frames = inspect.stack()[1:] - - # We search for the first frame in the stack - # which is not in the props package - this - # will be the point of the PV change which - # caused this listener to be enqueued - triggerFrame = None - for frame in frames: - if 'props/props' not in frame[1]: - triggerFrame = frame - break - - # This should never happen, - # but in case it does, we - # put a dummy value into - # the causes queue, so it - # is the same length as the - # reall call queue - if triggerFrame is None: - theQ._causes.put_nowait(None) - - # Store the cause of the listener - # push on the causes queue - else: - - cause = [triggerFrame[1], - triggerFrame[2], - triggerFrame[3]] - if triggerFrame[4] is not None: - cause.append(triggerFrame[4][triggerFrame[5]]) - else: - cause.append('<input>') - theQ._causes.put_nowait(cause) - - return True - - # Patch the CallQueue instance with - # our push/pop implementations - theQ._causes = Queue.Queue() - theQ._realPush = theQ._CallQueue__push - theQ._realPop = theQ._CallQueue__pop - theQ._CallQueue__push = tracePush - theQ._CallQueue__pop = tracePop - - -def trace(desc): - """Outputs a log message containing the given description and the current - stack trace. - """ - - if log.getEffectiveLevel() != logging.DEBUG: - return - - stack = inspect.stack()[1:] - lines = '{}\n'.format(desc) - - for i, frame in enumerate(stack): - - srcMod = frame[1] - srcLineNo = frame[2] - - if frame[4] is not None: srcLine = frame[4][frame[5]] - else: srcLine = '<native>' - - lines = lines + '{}{}:{}: {}\n'.format( - ' ' * (i + 1), - srcMod, srcLineNo, - srcLine.strip()) - - log.debug(lines) - - return lines - - -def propchange(*args): - """Intended to be called from a :class:`props.PropertyValue` listener - function. - - If this function is called due to a change, attempts to determine the line - of code which triggered the change. Prints some informative log messages. - - :arg args: The arguments that were passed to the listener function. - """ - - - if log.getEffectiveLevel() != logging.DEBUG: - return - - import props - - theQ = props.properties_value.PropertyValue.queue - stack = inspect.stack() - - listenerFile = stack[1][1] - listenerLine = stack[1][2] - listenerFunc = stack[1][3] - - triggerFile = None - - if len(args) != 4: - triggerFile = stack[2][1] - triggerLine = stack[2][2] - triggerFunc = stack[2][3] - triggerSrc = stack[2][4][stack[2][5]] - else: - triggerFile = theQ._currentCause[0] - triggerLine = theQ._currentCause[1] - triggerFunc = theQ._currentCause[2] - triggerSrc = theQ._currentCause[3] - - if triggerFile is None: - log.debug('Listener {} ({}:{}) was called ' - 'due to an unknown process'.format( - listenerFunc, - op.basename(listenerFile), - listenerLine)) - - else: - - if len(args) != 4: - reason = 'manually called from' - else: - value, valid, ctx, name = args - reason = 'called due to a value change of {}.{} ({}) at'.format( - type(ctx).__name__, - name, - value) - - log.debug('Listener {} ({}:{}) was {} ' - '{} ({}:{}:{})'.format( - listenerFunc, - op.basename(listenerFile), - listenerLine, - reason, - triggerFunc, - op.basename(triggerFile), - triggerLine, - triggerSrc.strip())) - - -def setcause(desc): - """I can't quite remember the difference betwen this function and the - :func:`propchange` function. - """ - - if log.getEffectiveLevel() != logging.DEBUG: - return - - stack = inspect.stack()[1:] - causeFrame = None - ultCauseFrame = None - - for i, frame in enumerate(stack): - - if 'props/props' not in frame[1]: - causeFrame = frame - break - - if causeFrame is not None: - for i, frame in reversed(list(enumerate(stack))): - if 'props/props' in frame[1]: - ultCauseFrame = stack[i + 1] - break - - if causeFrame is None: - log.debug('{}: Unknown cause'.format(desc)) - else: - causeFile = causeFrame[1] - causeLine = causeFrame[2] - causeFunc = causeFrame[3] - causeSrc = causeFrame[4][causeFrame[5]] - - line = '{}: Caused by {} ({}:{}:{})'.format( - desc, - causeFunc, - op.basename(causeFile), - causeLine, - causeSrc.strip()) - - if ultCauseFrame is not None: - - causeFile = ultCauseFrame[1] - causeLine = ultCauseFrame[2] - causeFunc = ultCauseFrame[3] - causeSrc = ultCauseFrame[4][ultCauseFrame[5]] - line = '{} (ultimately caused by {} ({}:{}:{})'.format( - line, - causeFunc, - op.basename(causeFile), - causeLine, - causeSrc.strip()) - - log.debug(line) -- GitLab