[pypy-svn] r68869 - in pypy/branch/logging2/pypy: rlib rlib/test rpython/lltypesystem translator/c translator/c/src translator/c/test

arigo at codespeak.net arigo at codespeak.net
Fri Oct 30 17:45:25 CET 2009


Author: arigo
Date: Fri Oct 30 17:45:24 2009
New Revision: 68869

Modified:
   pypy/branch/logging2/pypy/rlib/debug.py
   pypy/branch/logging2/pypy/rlib/test/test_debug.py
   pypy/branch/logging2/pypy/rpython/lltypesystem/lloperation.py
   pypy/branch/logging2/pypy/rpython/lltypesystem/opimpl.py
   pypy/branch/logging2/pypy/translator/c/funcgen.py
   pypy/branch/logging2/pypy/translator/c/src/debug.h
   pypy/branch/logging2/pypy/translator/c/test/test_standalone.py
Log:
Move all the code to support variants of logging to debug.h.
Implement a number of variants, documented at the start of debug.h.


Modified: pypy/branch/logging2/pypy/rlib/debug.py
==============================================================================
--- pypy/branch/logging2/pypy/rlib/debug.py	(original)
+++ pypy/branch/logging2/pypy/rlib/debug.py	Fri Oct 30 17:45:24 2009
@@ -61,35 +61,30 @@
             hop.genop(fn.__name__, vlist)
 
 
-def debug_level():
-    """Returns the current debug level.  It is:
-         0: all calls to debug_print/debug_start/debug_stop are ignored
-         1: profiling: debug_start/debug_stop handled, but debug_print ignored
-         2: all handled
-    The value returned depend on the runtime presence of the PYPYLOG env var,
-    unless debuglevel == 0 in the config.
-    """
-    return 2
+def have_debug_prints():
+    # returns True if the next calls to debug_print show up,
+    # and False if they would not have any effect.
+    return True
 
 class Entry(ExtRegistryEntry):
-    _about_ = debug_level
+    _about_ = have_debug_prints
 
     def compute_result_annotation(self):
         from pypy.annotation import model as annmodel
         t = self.bookkeeper.annotator.translator
         if t.config.translation.log:
-            return annmodel.SomeInteger()
+            return annmodel.s_Bool
         else:
-            return self.bookkeeper.immutablevalue(0)
+            return self.bookkeeper.immutablevalue(False)
 
     def specialize_call(self, hop):
         from pypy.rpython.lltypesystem import lltype
         t = hop.rtyper.annotator.translator
         hop.exception_cannot_occur()
         if t.config.translation.log:
-            return hop.genop('debug_level', [], resulttype=lltype.Signed)
+            return hop.genop('have_debug_prints', [], resulttype=lltype.Bool)
         else:
-            return hop.inputconst(lltype.Signed, 0)
+            return hop.inputconst(lltype.Bool, False)
 
 
 def llinterpcall(RESTYPE, pythonfunction, *args):

Modified: pypy/branch/logging2/pypy/rlib/test/test_debug.py
==============================================================================
--- pypy/branch/logging2/pypy/rlib/test/test_debug.py	(original)
+++ pypy/branch/logging2/pypy/rlib/test/test_debug.py	Fri Oct 30 17:45:24 2009
@@ -1,7 +1,8 @@
 
 import py
 from pypy.rlib.debug import check_annotation, make_sure_not_resized
-from pypy.rlib.debug import debug_print, debug_start, debug_stop, debug_level
+from pypy.rlib.debug import debug_print, debug_start, debug_stop
+from pypy.rlib.debug import have_debug_prints
 from pypy.rpython.test.test_llinterp import interpret
 
 def test_check_annotation():
@@ -50,13 +51,13 @@
             debug_start("mycat")
             debug_print("foo", 2, "bar", x)
             debug_stop("mycat")
-            return debug_level()
+            return have_debug_prints()
 
         olderr = sys.stderr
         try:
             sys.stderr = c = StringIO()
             res = f(3)
-            assert res == 2
+            assert res == True
         finally:
             sys.stderr = olderr
         assert 'mycat' in c.getvalue()
@@ -65,7 +66,7 @@
         try:
             sys.stderr = c = StringIO()
             res = self.interpret(f, [3])
-            assert res == 2
+            assert res == True
         finally:
             sys.stderr = olderr
         assert 'mycat' in c.getvalue()

Modified: pypy/branch/logging2/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/logging2/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/branch/logging2/pypy/rpython/lltypesystem/lloperation.py	Fri Oct 30 17:45:24 2009
@@ -525,7 +525,7 @@
     'debug_print':          LLOp(canrun=True),
     'debug_start':          LLOp(canrun=True),
     'debug_stop':           LLOp(canrun=True),
-    'debug_level':          LLOp(canrun=True),
+    'have_debug_prints':    LLOp(canrun=True),
     'debug_pdb':            LLOp(),
     'debug_assert':         LLOp(tryfold=True),
     'debug_fatalerror':     LLOp(),

Modified: pypy/branch/logging2/pypy/rpython/lltypesystem/opimpl.py
==============================================================================
--- pypy/branch/logging2/pypy/rpython/lltypesystem/opimpl.py	(original)
+++ pypy/branch/logging2/pypy/rpython/lltypesystem/opimpl.py	Fri Oct 30 17:45:24 2009
@@ -429,8 +429,8 @@
 def op_debug_stop(category):
     debug.debug_stop(_normalize(category))
 
-def op_debug_level():
-    return debug.debug_level()
+def op_have_debug_prints():
+    return debug.have_debug_prints()
 
 def op_gc_stack_bottom():
     pass       # marker for trackgcroot.py

Modified: pypy/branch/logging2/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/branch/logging2/pypy/translator/c/funcgen.py	(original)
+++ pypy/branch/logging2/pypy/translator/c/funcgen.py	Fri Oct 30 17:45:24 2009
@@ -744,8 +744,9 @@
                 raise Exception("don't know how to debug_print %r" % (T,))
             argv.append(self.expr(arg))
         argv.insert(0, c_string_constant(' '.join(format) + '\n'))
-        return ("if (PYPY_DEBUG_ENABLED) { fprintf(PYPY_DEBUG_FILE, %s); %s}"
-                % (', '.join(argv), free_line))
+        return (
+            "if (PYPY_HAVE_DEBUG_PRINTS) { fprintf(PYPY_DEBUG_FILE, %s); %s}"
+            % (', '.join(argv), free_line))
 
     def OP_DEBUG_START(self, op):
         arg = op.args[0]

Modified: pypy/branch/logging2/pypy/translator/c/src/debug.h
==============================================================================
--- pypy/branch/logging2/pypy/translator/c/src/debug.h	(original)
+++ pypy/branch/logging2/pypy/translator/c/src/debug.h	Fri Oct 30 17:45:24 2009
@@ -2,42 +2,41 @@
  /***  C header subsection: debug_print & related tools    ***/
 
 /* values of the PYPYLOG environment variable:
+   ("top-level" debug_prints means not between debug_start and debug_stop)
 
-   (empty)        logging is turned off
-   -              logging goes to stderr
-   filename       logging goes to the given file; overwritten at process start
-   prof:filename  logs only debug_start and debug_stop, not debug_print
+   (empty)        logging is turned off, apart from top-level debug_prints
+                     that go to stderr
+   fname          logging for profiling: includes all debug_start/debug_stop
+                     but not any nested debug_print
+   :fname         full logging
+   prefix:fname   conditional logging
+
+   Conditional logging means that it only includes the debug_start/debug_stop
+   sections whose name match 'prefix'.  Other sections are ignored, including
+   all debug_prints that occur while this section is running and all nested
+   subsections.
+
+   Note that 'fname' can be '-' to send the logging data to stderr.
 */
 
 
 /* macros used by the generated code */
-#define PYPY_DEBUG_ENABLED        \
-           (pypy_debug_level >= PYDEBUG_FULL && pypy_debug_is_ready_full())
-#define PYPY_DEBUG_FILE           \
-           pypy_debug_file
-#define PYPY_DEBUG_START(cat)     \
-           if (pypy_debug_level >= PYDEBUG_PROFILE) pypy_debug_start(cat)
-#define PYPY_DEBUG_STOP(cat)      \
-           if (pypy_debug_level >= PYDEBUG_PROFILE) pypy_debug_stop(cat)
-#define OP_DEBUG_LEVEL(r)         \
-           if (pypy_debug_level == PYDEBUG_UNINITIALIZED) pypy_debug_open(); \
-           r = pypy_debug_level
+#define PYPY_HAVE_DEBUG_PRINTS    (pypy_ignoring_nested_prints ? 0 : \
+                                   (pypy_debug_ensure_opened(), 1))
+#define PYPY_DEBUG_FILE           pypy_debug_file
+#define PYPY_DEBUG_START(cat)     pypy_debug_start(cat)
+#define PYPY_DEBUG_STOP(cat)      pypy_debug_stop(cat)
+#define OP_HAVE_DEBUG_PRINTS(r)   r = !pypy_ignoring_nested_prints
 
 
 /************************************************************/
 
-#define PYDEBUG_OFF             0
-#define PYDEBUG_PROFILE         1
-#define PYDEBUG_FULL            2
-#define PYDEBUG_UNINITIALIZED   3
-
 /* prototypes (internal use only) */
-void pypy_debug_open(void);
-bool_t pypy_debug_is_ready_full(void);
+void pypy_debug_ensure_opened(void);
 void pypy_debug_start(const char *category);
 void pypy_debug_stop(const char *category);
 
-extern int pypy_debug_level;
+extern int pypy_ignoring_nested_prints;
 extern FILE *pypy_debug_file;
 
 
@@ -45,40 +44,46 @@
 
 #ifndef PYPY_NOT_MAIN_FILE
 #include <sys/time.h>
+#include <string.h>
 
-int pypy_debug_level = PYDEBUG_UNINITIALIZED;
-FILE *pypy_debug_file;
+int pypy_ignoring_nested_prints = 0;
+FILE *pypy_debug_file = NULL;
+static bool_t debug_ready = 0;
+static bool_t debug_profile = 0;
+static char *debug_prefix = NULL;
 
-void pypy_debug_open(void)
+static void pypy_debug_open(void)
 {
   char *filename = getenv("PYPYLOG");
-  pypy_debug_level = PYDEBUG_FULL;
-  pypy_debug_file = NULL;
   if (filename && filename[0])
     {
-      if (filename[0] == 'p' &&
-          filename[1] == 'r' &&
-          filename[2] == 'o' &&
-          filename[3] == 'f' &&
-          filename[4] == ':')
+      char *colon = strchr(filename, ':');
+      if (!colon)
         {
-          pypy_debug_level = PYDEBUG_PROFILE;
-          filename += 5;
+          /* PYPYLOG=filename --- profiling version */
+          debug_profile = 1;
         }
-      if (filename[0] == '-' && filename[1] == 0)
-        pypy_debug_file = stderr;
       else
+        {
+          /* PYPYLOG=prefix:filename --- conditional logging */
+          int n = colon - filename;
+          debug_prefix = malloc(n + 1);
+          memcpy(debug_prefix, filename, n);
+          debug_prefix[n] = '\0';
+          filename = colon + 1;
+        }
+      if (strcmp(filename, "-") != 0)
         pypy_debug_file = fopen(filename, "w");
     }
-  if (pypy_debug_file == NULL)
-    pypy_debug_level = PYDEBUG_OFF;
+  if (!pypy_debug_file)
+    pypy_debug_file = stderr;
+  debug_ready = 1;
 }
 
-bool_t pypy_debug_is_ready_full(void)
+void pypy_debug_ensure_opened(void)
 {
-  if (pypy_debug_level == PYDEBUG_UNINITIALIZED)
+  if (!debug_ready)
     pypy_debug_open();
-  return pypy_debug_level == PYDEBUG_FULL;
 }
 
 
@@ -87,25 +92,58 @@
      __asm__ __volatile__("rdtsc" : "=A" (val))
 
 
-static void pypy_debug_category(const char *start, const char *category)
+static bool_t startswith(const char *str, const char *substr)
+{
+  while (*substr)
+    if (*str++ != *substr++)
+      return 0;
+  return 1;
+}
+
+static void display_startstop(const char *start, const char *category)
 {
   long long timestamp;
-  if (pypy_debug_level == PYDEBUG_UNINITIALIZED)
-    pypy_debug_open();
-  if (pypy_debug_level < PYDEBUG_PROFILE)
-    return;
   READ_TIMESTAMP(timestamp);
   fprintf(pypy_debug_file, "{%llx} -%s- %s\n", timestamp, start, category);
 }
 
 void pypy_debug_start(const char *category)
 {
-  pypy_debug_category("start", category);
+  if (debug_profile)
+    {
+      /* profiling version */
+      pypy_debug_ensure_opened();
+      pypy_ignoring_nested_prints++;    /* disable nested debug_print */
+    }
+  else
+    {
+      /* non-profiling version */
+      if (pypy_ignoring_nested_prints > 0)
+        {
+          /* already ignoring the parent section */
+          pypy_ignoring_nested_prints++;
+          return;
+        }
+      pypy_debug_ensure_opened();
+      if (!debug_prefix || !startswith(category, debug_prefix))
+        {
+          /* wrong section name, or no PYPYLOG at all, skip it */
+          pypy_ignoring_nested_prints = 1;
+          return;
+        }
+    }
+  display_startstop("start", category);
 }
 
 void pypy_debug_stop(const char *category)
 {
-  pypy_debug_category("stop", category);
+  if (pypy_ignoring_nested_prints > 0)
+    {
+      pypy_ignoring_nested_prints--;
+      if (!debug_profile)
+        return;
+    }
+  display_startstop("stop", category);
 }
 
 #endif /* PYPY_NOT_MAIN_FILE */

Modified: pypy/branch/logging2/pypy/translator/c/test/test_standalone.py
==============================================================================
--- pypy/branch/logging2/pypy/translator/c/test/test_standalone.py	(original)
+++ pypy/branch/logging2/pypy/translator/c/test/test_standalone.py	Fri Oct 30 17:45:24 2009
@@ -2,8 +2,8 @@
 import sys, os, re
 
 from pypy.rlib.rarithmetic import r_longlong
-from pypy.rlib.debug import ll_assert
-from pypy.rlib.debug import debug_print, debug_start, debug_stop, debug_level
+from pypy.rlib.debug import ll_assert, have_debug_prints
+from pypy.rlib.debug import debug_print, debug_start, debug_stop
 from pypy.translator.translator import TranslationContext
 from pypy.translator.backendopt import all
 from pypy.translator.c.genc import CStandaloneBuilder, ExternalCompilationInfo
@@ -258,42 +258,104 @@
 
     def test_debug_print_start_stop(self):
         def entry_point(argv):
-            os.write(1, str(debug_level()) + '\n')
-            debug_start("mycat")
-            debug_print("foo", 2, "bar", 3)
-            debug_stop("mycat")
+            x = "got:"
+            if have_debug_prints(): x += "a"
+            debug_print("toplevel")
+            debug_start  ("mycat")
+            if have_debug_prints(): x += "b"
+            debug_print    ("foo", 2, "bar", 3)
+            debug_start      ("cat2")
+            if have_debug_prints(): x += "c"
+            debug_print        ("baz")
+            debug_stop       ("cat2")
+            if have_debug_prints(): x += "d"
+            debug_print    ("bok")
+            debug_stop   ("mycat")
+            os.write(1, x + '.\n')
             return 0
         t, cbuilder = self.compile(entry_point)
         # check with PYPYLOG undefined
         out, err = cbuilder.cmdexec("", err=True, env={})
-        assert out.strip() == '0'
-        assert not err
+        assert out.strip() == 'got:a.'
+        assert 'toplevel' in err
+        assert 'mycat' not in err
+        assert 'foo 2 bar 3' not in err
+        assert 'cat2' not in err
+        assert 'baz' not in err
+        assert 'bok' not in err
         # check with PYPYLOG defined to an empty string (same as undefined)
         out, err = cbuilder.cmdexec("", err=True, env={'PYPYLOG': ''})
-        assert out.strip() == '0'
-        assert not err
-        # check with PYPYLOG=- (means print to stderr)
-        out, err = cbuilder.cmdexec("", err=True, env={'PYPYLOG': '-'})
-        assert out.strip() == '2'
+        assert out.strip() == 'got:a.'
+        assert 'toplevel' in err
+        assert 'mycat' not in err
+        assert 'foo 2 bar 3' not in err
+        assert 'cat2' not in err
+        assert 'baz' not in err
+        assert 'bok' not in err
+        # check with PYPYLOG=:- (means print to stderr)
+        out, err = cbuilder.cmdexec("", err=True, env={'PYPYLOG': ':-'})
+        assert out.strip() == 'got:abcd.'
+        assert 'toplevel' in err
         assert 'mycat' in err
         assert 'foo 2 bar 3' in err
-        # check with PYPYLOG=somefilename
+        assert 'cat2' in err
+        assert 'baz' in err
+        assert 'bok' in err
+        # check with PYPYLOG=:somefilename
         path = udir.join('test_debug_xxx.log')
+        out, err = cbuilder.cmdexec("", err=True,
+                                    env={'PYPYLOG': ':%s' % path})
+        assert out.strip() == 'got:abcd.'
+        assert not err
+        assert path.check(file=1)
+        data = path.read()
+        assert 'toplevel' in data
+        assert 'mycat' in data
+        assert 'foo 2 bar 3' in data
+        assert 'cat2' in data
+        assert 'baz' in data
+        assert 'bok' in data
+        # check with PYPYLOG=somefilename
+        path = udir.join('test_debug_xxx_prof.log')
         out, err = cbuilder.cmdexec("", err=True, env={'PYPYLOG': str(path)})
-        assert out.strip() == '2'
+        assert out.strip() == 'got:a.'
         assert not err
         assert path.check(file=1)
+        data = path.read()
+        assert 'toplevel' in data
+        assert 'mycat' in data
+        assert 'foo 2 bar 3' not in data
+        assert 'cat2' in data
+        assert 'baz' not in data
+        assert 'bok' not in data
+        # check with PYPYLOG=myc:somefilename   (includes mycat but not cat2)
+        path = udir.join('test_debug_xxx_myc.log')
+        out, err = cbuilder.cmdexec("", err=True,
+                                    env={'PYPYLOG': 'myc:%s' % path})
+        assert out.strip() == 'got:abd.'
+        assert not err
+        assert path.check(file=1)
+        data = path.read()
+        assert 'toplevel' in path.read()
         assert 'mycat' in path.read()
         assert 'foo 2 bar 3' in path.read()
-        # check with PYPYLOG=prof:somefilename   (only start/stop events)
-        path = udir.join('test_debug_xxx_prof.log')
+        assert 'cat2' not in data
+        assert 'baz' not in data
+        assert 'bok' in data
+        # check with PYPYLOG=cat:somefilename   (includes cat2 but not mycat)
+        path = udir.join('test_debug_xxx_cat.log')
         out, err = cbuilder.cmdexec("", err=True,
-                                    env={'PYPYLOG': 'prof:%s' % path})
-        assert out.strip() == '1'
+                                    env={'PYPYLOG': 'cat:%s' % path})
+        assert out.strip() == 'got:a.'
         assert not err
         assert path.check(file=1)
-        assert 'mycat' in path.read()
+        data = path.read()
+        assert 'toplevel' in path.read()
+        assert 'mycat' not in path.read()
         assert 'foo 2 bar 3' not in path.read()
+        assert 'cat2' not in data      # because it is nested
+        assert 'baz' not in data
+        assert 'bok' not in data
         #
         # finally, check compiling with logging disabled
         from pypy.config.pypyoption import get_pypy_config
@@ -302,8 +364,10 @@
         self.config = config
         t, cbuilder = self.compile(entry_point)
         path = udir.join('test_debug_does_not_show_up.log')
-        out = cbuilder.cmdexec("", env={'PYPYLOG': str(path)})
-        assert out.strip() == '0'
+        out, err = cbuilder.cmdexec("", err=True,
+                                    env={'PYPYLOG': ':%s' % path})
+        assert out.strip() == 'got:.'
+        assert not err
         assert path.check(file=0)
 
 



More information about the Pypy-commit mailing list