document and replace debugged by a contextmanager/decorator class
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Sat, 01 Aug 2009 16:17:18 +0200
changeset 2628 a2cc32c1d982
parent 2627 d710278e0c1c
child 2629 0d445c2171e4
document and replace debugged by a contextmanager/decorator class
server/__init__.py
--- a/server/__init__.py	Sat Aug 01 16:16:06 2009 +0200
+++ b/server/__init__.py	Sat Aug 01 16:17:18 2009 +0200
@@ -14,39 +14,76 @@
 from os.path import join, exists
 
 from logilab.common.modutils import LazyObject
+from logilab.common.textutils import get_csv
 
 # server-side debugging #########################################################
 
-# server debugging flag
-DBG_RQL = 1 # rql execution information
-DBG_SQL = 2 # executed sql
+# server debugging flags. They may be combined using binary operators.
+DBG_NONE = 0 # no debug information
+DBG_RQL = 1  # rql execution information
+DBG_SQL = 2  # executed sql
 DBG_REPO = 4 # repository events
 DBG_MORE = 8 # repository events
 
+# current debug mode
+DEBUG = 0
 
-# 2: + executed sql
-# 3: + additional debug information
-DEBUG = 0
 def set_debug(debugmode):
+    """change the repository debugging mode"""
     global DEBUG
     if not debugmode:
         DEBUG = 0
         return
     if isinstance(debugmode, basestring):
-        debugmode = globals()[debugmode]
-    DEBUG |= debugmode
+        for mode in get_csv(debugmode, sep='|'):
+            DEBUG |= globals()[mode]
+    else:
+        DEBUG |= debugmode
+
+
+class debugged(object):
+    """repository debugging context manager / decorator
+
+    Can be used either as a context manager:
+
+    >>> with debugged(server.DBG_RQL | server.DBG_REPO):
+    ...     # some code in which you want to debug repository activity,
+    ...     # seing information about RQL being executed an repository events.
+
+    or as a function decorator:
+
+    >>> @debugged(server.DBG_RQL | server.DBG_REPO)
+    ... def some_function():
+    ...     # some code in which you want to debug repository activity,
+    ...     # seing information about RQL being executed an repository events
 
-def debugged(func):
-    """decorator to activate debug mode"""
-    def wrapped(*args, **kwargs):
-        global DEBUG
-        DEBUG = True
-        try:
-            return func(*args, **kwargs)
-        finally:
-            DEBUG = False
-    return wrapped
+    debug mode will be reseted at its original value when leaving the "with"
+    block or the decorated function
+    """
+    def __init__(self, debugmode):
+        self.debugmode = debugmode
+        self._clevel = None
+
+    def __enter__(self):
+        """enter with block"""
+        self._clevel = DEBUG
+        set_debug(self.debugmode)
 
+    def __exit__(self, exctype, exc, traceback):
+        """leave with block"""
+        set_debug(self._clevel)
+        return traceback is None
+
+    def __call__(self, func):
+        """decorate function"""
+        def wrapped(*args, **kwargs):
+            _clevel = DEBUG
+            set_debug(self.debugmode)
+            try:
+                return func(*args, **kwargs)
+            finally:
+                set_debug(self._clevel)
+        return wrapped
 
 # database initialization ######################################################