commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnue] r9760 - trunk/gnue-common/src/base


From: reinhard
Subject: [gnue] r9760 - trunk/gnue-common/src/base
Date: Mon, 16 Jul 2007 16:48:40 -0500 (CDT)

Author: reinhard
Date: 2007-07-16 16:48:40 -0500 (Mon, 16 Jul 2007)
New Revision: 9760

Modified:
   trunk/gnue-common/src/base/log.py
Log:
Added function logging decorator.

issue123 in-progress


Modified: trunk/gnue-common/src/base/log.py
===================================================================
--- trunk/gnue-common/src/base/log.py   2007-07-13 22:22:52 UTC (rev 9759)
+++ trunk/gnue-common/src/base/log.py   2007-07-16 21:48:40 UTC (rev 9760)
@@ -35,12 +35,11 @@
 
 from gnue.common.base import utils
 
-__all__ = ['debug', 'info', 'warning', 'deprecated', 'error', 'critical',
-        'exception', 'debug_n', 'info_n', 'warning_n', 'deprecated_n',
-        'error_n', 'critical_n', 'exception_n']
+__all__ = ['logged_f', 'debug', 'info', 'warning', 'deprecated', 'error',
+        'critical', 'exception', 'debug_n', 'info_n', 'warning_n',
+        'deprecated_n', 'error_n', 'critical_n', 'exception_n']
 
 # TODO:
-# - function for enter() and leave(), maybe as decorator?
 # - function to declare function as deprecated, maybe as decorator?
 # - Exception hook
 # - allow for __gnue_logger__ module global variable to use as a logger name
@@ -49,6 +48,105 @@
 
 
 # -----------------------------------------------------------------------------
+# Log function entry and exit
+# -----------------------------------------------------------------------------
+
+def logged_f(func):
+    """
+    Decorator to activate logging for a function.
+
+    If this decorator is applied to a function, every call to that function is
+    logged on C{DEBUG} level.
+
+    Usage with Python 2.4 or later::
+        @logged_f
+        myfunction(self, foo, bar):
+            :
+
+    Usage with Python 2.3::
+        myfunction(self, foo, bar):
+            :
+        myfunction=logged_f(myfunction)
+    """
+    def new_f(*args, **kwargs):
+        name = func.func_globals['__name__']
+        __enter(name, func)
+        result = func(*args, **kwargs)
+        __leave(name, func, result)
+        return result
+    return new_f
+
+# -----------------------------------------------------------------------------
+
+def __enter(name, func):
+
+    # Get the caller's frame
+    frame = inspect.currentframe().f_back
+    while not frame.f_code.co_name == 'new_f':
+        frame = frame.f_back
+
+    try:
+        fname = __func_name(func, frame)
+
+        args = frame.f_locals['args']
+        kwargs = frame.f_locals['kwargs']
+
+        params = []
+        # Arguments
+        params.extend([repr(item) for item in args])
+        # Keyword arguments
+        params.extend(["%s=%r" % (k, v) for (k, v) in kwargs.items()])
+
+        msg = "Calling function %s(%s)" % (fname, ", ".join(params))
+
+    finally:
+        # Frame object has to be deleted manually.
+        del frame
+
+    debug_n(name, msg)
+    return True
+  
+# -----------------------------------------------------------------------------
+
+def __leave(name, func, result):
+
+    # Get the caller's frame
+    frame = inspect.currentframe().f_back
+    while not frame.f_code.co_name == 'new_f':
+        frame = frame.f_back
+
+    try:
+        msg = "Returning from function " + __func_name(func, frame) + "() -> " 
\
+                + repr(result)
+    finally:
+        # Frame object has to be deleted manually.
+        del frame
+
+    debug_n(name, msg)
+    return True
+  
+# -----------------------------------------------------------------------------
+
+def __func_name(func, frame):
+    # It seems like there is no way to find out the name of the class that
+    # defined a method. To print out the class name in the log, we need to
+    # inspect the 'self' parameter.
+    fname = func.__name__
+    code = func.func_code
+    if code.co_argcount > 0 and code.co_names[0] == 'self':
+        klass = frame.f_locals['args'][0].__class__
+        if isinstance(klass, str):
+            # Old stle class
+            fname = klass + '.' + fname
+        else:
+            # New style class
+            fname = klass.__module__ + '.' + klass.__name__ + '.' + fname
+    else:
+        fname = func.func_globals['__name__'] + '.' + fname
+    return fname
+
+
+# -----------------------------------------------------------------------------
 # Log to the logger named after the calling module
 # -----------------------------------------------------------------------------
 





reply via email to

[Prev in Thread] Current Thread [Next in Thread]