From 34f5f757b389e8fb3eab64f816e484c2cc434292 Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Tue, 28 Apr 2015 22:14:23 -0700 Subject: [PATCH] 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. --- gdb/ChangeLog | 6 ++ gdb/python/lib/gdb/printing.py | 12 ++- gdb/testsuite/ChangeLog | 7 ++ gdb/testsuite/gdb.python/py-pp-maint.py | 11 --- gdb/testsuite/gdb.python/py-pp-registration.c | 55 +++++++++++ gdb/testsuite/gdb.python/py-pp-registration.exp | 116 ++++++++++++++++++++++++ gdb/testsuite/gdb.python/py-pp-registration.py | 80 ++++++++++++++++ 7 files changed, 273 insertions(+), 14 deletions(-) create mode 100644 gdb/testsuite/gdb.python/py-pp-registration.c create mode 100644 gdb/testsuite/gdb.python/py-pp-registration.exp create mode 100644 gdb/testsuite/gdb.python/py-pp-registration.py diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3e11394..92d972e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,11 @@ 2015-04-28 Doug Evans + 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 + PR python/18089 * python/py-prettyprint.c (print_children): Verify result of children iterator. Provide better error message. diff --git a/gdb/python/lib/gdb/printing.py b/gdb/python/lib/gdb/printing.py index e384e41..ff20f71 100644 --- a/gdb/python/lib/gdb/printing.py +++ b/gdb/python/lib/gdb/printing.py @@ -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") diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index b686edb..639dae7 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,12 @@ 2015-04-28 Doug Evans + * 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 + * gdb.python/py-bad-printers.c: New file. * gdb.python/py-bad-printers.py: New file. * gdb.python/py-bad-printers.exp: New file. diff --git a/gdb/testsuite/gdb.python/py-pp-maint.py b/gdb/testsuite/gdb.python/py-pp-maint.py index 797f975..f4e5ecf 100644 --- a/gdb/testsuite/gdb.python/py-pp-maint.py +++ b/gdb/testsuite/gdb.python/py-pp-maint.py @@ -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 index 0000000..6891abf --- /dev/null +++ b/gdb/testsuite/gdb.python/py-pp-registration.c @@ -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 . */ + +#include + +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 index 0000000..2193407 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-pp-registration.exp @@ -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 . + +# 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 index 0000000..7cca270 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-pp-registration.py @@ -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 . + +# 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. -- 2.7.4