PR python/18299

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.
This commit is contained in:
Doug Evans 2015-04-28 22:14:23 -07:00
parent 69b4374a87
commit 34f5f757b3
7 changed files with 273 additions and 14 deletions

View File

@ -1,3 +1,9 @@
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

View 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")

View File

@ -1,3 +1,10 @@
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.

View 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)

View File

@ -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 */
}

View File

@ -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"
}

View File

@ -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.