PR python/18299
authorDoug Evans <dje@google.com>
Wed, 29 Apr 2015 05:14:23 +0000 (22:14 -0700)
committerDoug Evans <dje@google.com>
Wed, 29 Apr 2015 05:14:23 +0000 (22:14 -0700)
gdb/ChangeLog:

PR python/18299
* python/lib/gdb/printing.py (register_pretty_printer): Handle
name or __name__ attributes.  Handle gdb module as first argument.

gdb/testsuite/ChangeLog:

* gdb.python/py-pp-maint.py: Move "replace" testing to ...
* gdb.python/py-pp-registration.exp: ... here.  New file.
* gdb.python/py-pp-registration.c: New file.
* gdb.python/py-pp-registration.py: New file.

gdb/ChangeLog
gdb/python/lib/gdb/printing.py
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.python/py-pp-maint.py
gdb/testsuite/gdb.python/py-pp-registration.c [new file with mode: 0644]
gdb/testsuite/gdb.python/py-pp-registration.exp [new file with mode: 0644]
gdb/testsuite/gdb.python/py-pp-registration.py [new file with mode: 0644]

index 3e11394..92d972e 100644 (file)
@@ -1,5 +1,11 @@
 2015-04-28  Doug Evans  <dje@google.com>
 
+       PR python/18299
+       * python/lib/gdb/printing.py (register_pretty_printer): Handle
+       name or __name__ attributes.  Handle gdb module as first argument.
+
+2015-04-28  Doug Evans  <dje@google.com>
+
        PR python/18089
        * python/py-prettyprint.c (print_children): Verify result of children
        iterator.  Provide better error message.
index e384e41..ff20f71 100644 (file)
@@ -114,15 +114,21 @@ def register_pretty_printer(obj, printer, replace=False):
     if not hasattr(printer, "__call__"):
         raise TypeError("printer missing attribute: __call__")
 
-    if obj is None:
+    if hasattr(printer, "name"):
+      name = printer.name
+    else:
+      name = printer.__name__
+    if obj is None or obj is gdb:
         if gdb.parameter("verbose"):
             gdb.write("Registering global %s pretty-printer ...\n" % name)
         obj = gdb
     else:
         if gdb.parameter("verbose"):
-            gdb.write("Registering %s pretty-printer for %s ...\n" %
-                      (printer.name, obj.filename))
+            gdb.write("Registering %s pretty-printer for %s ...\n" % (
+                name, obj.filename))
 
+    # Printers implemented as functions are old-style.  In order to not risk
+    # breaking anything we do not check __name__ here.
     if hasattr(printer, "name"):
         if not isinstance(printer.name, basestring):
             raise TypeError("printer name is not a string")
index b686edb..639dae7 100644 (file)
@@ -1,5 +1,12 @@
 2015-04-28  Doug Evans  <dje@google.com>
 
+       * gdb.python/py-pp-maint.py: Move "replace" testing to ...
+       * gdb.python/py-pp-registration.exp: ... here.  New file.
+       * gdb.python/py-pp-registration.c: New file.
+       * gdb.python/py-pp-registration.py: New file.
+
+2015-04-28  Doug Evans  <dje@google.com>
+
        * gdb.python/py-bad-printers.c: New file.
        * gdb.python/py-bad-printers.py: New file.
        * gdb.python/py-bad-printers.exp: New file.
index 797f975..f4e5ecf 100644 (file)
@@ -76,14 +76,3 @@ def build_pretty_printer():
 gdb.printing.register_pretty_printer(gdb, lookup_function_lookup_test)
 my_pretty_printer = build_pretty_printer()
 gdb.printing.register_pretty_printer(gdb, my_pretty_printer)
-
-# Exercise the "replace" argument to register pretty_printer.
-saw_runtime_error = False
-try:
-  gdb.printing.register_pretty_printer(gdb, my_pretty_printer, replace=False)
-except RuntimeError:
-  saw_runtime_error = True
-  pass
-if not saw_runtime_error:
-  raise RuntimeError("Missing RuntimeError from register_pretty_printer")
-gdb.printing.register_pretty_printer(gdb, my_pretty_printer, replace=True)
diff --git a/gdb/testsuite/gdb.python/py-pp-registration.c b/gdb/testsuite/gdb.python/py-pp-registration.c
new file mode 100644 (file)
index 0000000..6891abf
--- /dev/null
@@ -0,0 +1,55 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2010-2015 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+
+struct function_lookup_test
+{
+  int x,y;
+};
+
+void
+init_flt (struct function_lookup_test *p, int x, int y)
+{
+  p->x = x;
+  p->y = y;
+}
+
+struct s
+{
+  int a;
+  int *b;
+};
+
+void
+init_s (struct s *s, int a)
+{
+  s->a = a;
+  s->b = &s->a;
+}
+
+int
+main ()
+{
+  struct function_lookup_test flt;
+  struct s s;
+
+  init_flt (&flt, 42, 43);
+  init_s (&s, 1);
+  
+  return 0;      /* break to inspect */
+}
diff --git a/gdb/testsuite/gdb.python/py-pp-registration.exp b/gdb/testsuite/gdb.python/py-pp-registration.exp
new file mode 100644 (file)
index 0000000..2193407
--- /dev/null
@@ -0,0 +1,116 @@
+# Copyright (C) 2010-2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.  It tests python pretty
+# printer registration.
+
+load_lib gdb-python.exp
+
+standard_testfile
+
+if {[prepare_for_testing $testfile.exp $testfile $srcfile debug]} {
+    return -1
+}
+
+# Skip all tests if Python scripting is not enabled.
+if { [skip_python_tests] } { continue }
+
+set remote_python_file [gdb_remote_download host \
+                           ${srcdir}/${subdir}/${testfile}.py]
+
+if ![runto_main ] {
+    fail "Can't run to main"
+    return -1
+}
+
+proc prepare_test { } {
+    global testfile remote_python_file
+
+    # Start with a fresh gdb.
+    clean_restart ${testfile}
+
+    set run_to_here [gdb_get_line_number {break to inspect} ${testfile}.c ]
+    if ![runto ${testfile}.c:$run_to_here message] {
+       return 0
+    }
+
+    gdb_test_no_output "python exec (open ('${remote_python_file}').read ())"
+
+    gdb_test_no_output "py progspace = gdb.current_progspace()"
+    gdb_test_no_output "py my_pretty_printer1 = build_pretty_printer1()"
+    gdb_test_no_output "py my_pretty_printer2 = build_pretty_printer2()"
+
+    return 1
+}
+
+proc test_printers { s_prefix } {
+    global hex
+
+    gdb_test "print flt" " = x=<42> y=<43>" \
+       "print flt"
+    gdb_test "print s" " = ${s_prefix} a=<1> b=<$hex>" \
+       "print s"
+}
+
+# Test registration with verbose off.
+
+with_test_prefix "verbose off" {
+    if ![prepare_test] {
+       return -1
+    }
+
+    gdb_test_no_output "set verbose off"
+
+    gdb_test_no_output "py gdb.printing.register_pretty_printer(gdb, lookup_function_lookup_test)"
+    gdb_test_no_output "py gdb.printing.register_pretty_printer(progspace, my_pretty_printer1)"
+
+    test_printers "s1"
+}
+
+# Test registration with verbose on.
+
+with_test_prefix "verbose on" {
+    if ![prepare_test] {
+       return -1
+    }
+
+    gdb_test_no_output "set verbose on"
+
+    gdb_test "py gdb.printing.register_pretty_printer(gdb, lookup_function_lookup_test)" \
+       "Registering global lookup_function_lookup_test pretty-printer ..."
+    gdb_test "py gdb.printing.register_pretty_printer(progspace, my_pretty_printer1)" \
+       "Registering pp-test pretty-printer for .*/py-pp-registration ..."
+
+    test_printers "s1"
+}
+
+# Exercise the "replace" argument to register_pretty_printer.
+
+with_test_prefix "replace" {
+    if ![prepare_test] {
+       return -1
+    }
+
+    gdb_test_no_output "py gdb.printing.register_pretty_printer(gdb, lookup_function_lookup_test)"
+    gdb_test_no_output "py gdb.printing.register_pretty_printer(progspace, my_pretty_printer1)"
+    gdb_test "py gdb.printing.register_pretty_printer(progspace, my_pretty_printer2, replace=False)" \
+       "RuntimeError: pretty-printer already registered: pp-test\r\nError while executing Python code."
+
+    test_printers "s1"
+
+    gdb_test_no_output "py gdb.printing.register_pretty_printer(progspace, my_pretty_printer2, replace=True)"
+
+    test_printers "s2"
+}
diff --git a/gdb/testsuite/gdb.python/py-pp-registration.py b/gdb/testsuite/gdb.python/py-pp-registration.py
new file mode 100644 (file)
index 0000000..7cca270
--- /dev/null
@@ -0,0 +1,80 @@
+# Copyright (C) 2010-2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.  It tests python pretty
+# printer registration.
+
+import re
+import gdb.types
+import gdb.printing
+
+
+def lookup_function_lookup_test(val):
+    class PrintFunctionLookup(object):
+        def __init__(self, val):
+            self.val = val
+
+        def to_string(self):
+            return ("x=<" + str(self.val["x"]) +
+                    "> y=<" + str(self.val["y"]) + ">")
+
+    typename = gdb.types.get_basic_type(val.type).tag
+    # Note: typename could be None.
+    if typename == "function_lookup_test":
+        return PrintFunctionLookup(val)
+    return None
+
+
+class pp_s1 (object):
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        a = self.val["a"]
+        b = self.val["b"]
+        return "s1 a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">"
+
+
+class pp_s2 (object):
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        a = self.val["a"]
+        b = self.val["b"]
+        return "s2 a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">"
+
+
+def build_pretty_printer1():
+    pp = gdb.printing.RegexpCollectionPrettyPrinter("pp-test")
+
+    pp.add_printer('struct s', '^struct s$', pp_s1)
+    pp.add_printer('s', '^s$', pp_s1)
+
+    return pp
+
+
+def build_pretty_printer2():
+    # This intentionally has the same name as build_pretty_printer1.
+    # It is used to test the "replace" functionality of
+    # register_pretty_printer.
+    pp = gdb.printing.RegexpCollectionPrettyPrinter("pp-test")
+
+    pp.add_printer('struct s', '^struct s$', pp_s2)
+    pp.add_printer('s', '^s$', pp_s2)
+
+    return pp
+
+# Note: Registering the printers is done in the .exp file.