From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 839853858D1E for ; Tue, 24 Jan 2023 14:45:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 839853858D1E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1674571507; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=Q6UkfNm/KKcilnnQHTVZ/8eE/80wADcuH/n8ePMQ5iA=; b=hOBOzC5P1Ycfr8k6ElXDQEAyurbgkMzox/7K7cGxYQzzB74a9opJK78GSahozlkhHjmDri AEfBulS3d3hbu+4aaMWlg+Kyy7w01VStr2uHWiJz+9yn0+dmWm+LmdXBBxJSMmxuorEd/m ajP4pY0OXMjPHSd4YhqJ/SeoL+u6lcE= Received: from mail-qt1-f197.google.com (mail-qt1-f197.google.com [209.85.160.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-50-5h4nCa1gNxKEdBIxed83aw-1; Tue, 24 Jan 2023 09:45:05 -0500 X-MC-Unique: 5h4nCa1gNxKEdBIxed83aw-1 Received: by mail-qt1-f197.google.com with SMTP id bb10-20020a05622a1b0a00b003b68e868462so6008351qtb.15 for ; Tue, 24 Jan 2023 06:45:05 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=mime-version:message-id:date:references:in-reply-to:subject:cc:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Q6UkfNm/KKcilnnQHTVZ/8eE/80wADcuH/n8ePMQ5iA=; b=fXUAko1YxLyYE0ydID3Lk1lG3YlwvE5k6I4OA5L4+sjIq/z3uKICjE7cqvKcIzwTXp GGU7YyQby5SsRI3oBiLrM5iTo+wp6N+fmPZoNbGXQq8ZQfEvi52lB0qpesusLzzRz/Rk 64Q2CvNScJ7c3Iu/9bXn+6MIiUxI3ZK3xcAiuw80i1SxOU6V8I0M16B0LMmmL0kjozkE 6H0loQJh+7EL/Q8SZDVU4uPd+xINvZe/DITMcYQI8WYmau6VvIRo4KhHQ8q8/crrjH3i m2THz//IqbarGFywGti5PUSf7mQ2YXBmPz+qOLh3jHE2SMjY8bJLPXximmCpAJuJ0Qlr tNsw== X-Gm-Message-State: AFqh2ko7eG/03V4O3UTYAIWB8FnP+ueEqSd/7sLYU0nW7nRgvrFT48cl 1kt4oG6u/OvdwLm2zxyfPvm+oxmlnvOPaRqtieUoiQVz1GnLRA9+SfkbtVrYLqqmqRdlNiyfRk5 TLY03HnRM9el0zyBlCLjUeNjCK8v59NYuTdA2FWIFqMQiYfF4SmCv12fuA+ZCdkYKXiiVnu3hjQ == X-Received: by 2002:a05:622a:260a:b0:3ad:96d:98db with SMTP id ci10-20020a05622a260a00b003ad096d98dbmr44111988qtb.62.1674571504904; Tue, 24 Jan 2023 06:45:04 -0800 (PST) X-Google-Smtp-Source: AMrXdXtoSRyDERF8UBcFyM7zzbIAIQS3ysvIKfwq2X1MaG6DfxMRakg5mL/Kwy9zxl45L0rcSHax3A== X-Received: by 2002:a05:622a:260a:b0:3ad:96d:98db with SMTP id ci10-20020a05622a260a00b003ad096d98dbmr44111928qtb.62.1674571504358; Tue, 24 Jan 2023 06:45:04 -0800 (PST) Received: from localhost (95.72.115.87.dyn.plus.net. [87.115.72.95]) by smtp.gmail.com with ESMTPSA id x25-20020ac84d59000000b003b5bc7a4512sm1348189qtv.26.2023.01.24.06.45.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Jan 2023 06:45:03 -0800 (PST) From: Andrew Burgess To: Matheus Branco Borella via Gdb-patches , gdb-patches@sourceware.org Cc: Matheus Branco Borella Subject: Re: [PATCH] Add __repr__() implementation to a few Python types In-Reply-To: <20230120014336.377-1-dark.ryu.550@gmail.com> References: <87wn5jen5t.fsf@redhat.com> <20230120014336.377-1-dark.ryu.550@gmail.com> Date: Tue, 24 Jan 2023 14:45:01 +0000 Message-ID: <87y1psc7pu.fsf@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Matheus Branco Borella via Gdb-patches writes: > Only a few types in the Python API currently have __repr__() implementations. > This patch adds a few more of them. specifically: it adds __repr__() > implementations to gdb.Symbol, gdb.Architecture, gdb.Block, gdb.Breakpoint, > and gdb.Type. > > This makes it easier to play around the GDB Python API in the Python interpreter > session invoked with the 'pi' command in GDB, giving more easily accessible tipe > information to users. > > An example of how this would look like: > ``` > (gdb) pi >>> gdb.lookup_type("char") > >>> gdb.lookup_global_symbol("main") > > ``` > >> Sorry for being a little slow. What does this actually mean? When you >> say "makes use of u8 string literals" - does this mean you have string >> literals in this patch containing non ASCII characters? >> >> I've trying to understand why this is different to any other part of GDB >> that prints stuff via Python. > > I forgot to take that out of the commit message, my bad. Originally, I'd > intended for the string literals in the patch that get handed to Python to be > all u8 literals so that I could guarantee it wouldn't break in an environment > that doesn't output regular string literals in an ASCII-compatible encoding, > as Python expects all strings handed to it to be encoded in UTF-8. But seeing > as all of the rest of the Python interface code uses regular string literals, > I figured it wouldn't make much of difference having them in anyway. > >> I guess I was surprised that so many of the new tests included an >> explicit call to repr, given the premise of the change was that simply >> 'print(empty)' would now print something useful. >> >> I guess maybe it doesn't hurt to _also_ include some explicit repr >> calls, but I was expecting most tests to just be printing the object >> directly. > As blarsen@ also pointed out, `print`-ing an object directly that has an > implmentation of __str__() will print whatever its __str__() functions returns, > regardless of whether it implements __repr__() or not, which is not what we want > here. __repr__() is always preferred in the REPL, though, so it's understandable > it might not be clear at first why I'm calling `repr()` explicitly. > >> Over long line, please wrap a little. There's other long lines in your >> patch, I'll not point out each one. > > Should be all fixed now (hopefully I didn't miss any), with the exception of the > `repr_pattern` strings in `py-breakpoint.exp`, which I couldn't for the life of > me get to match properly with the output were they not on a single line. > > --- > gdb/python/py-arch.c | 18 +++++- > gdb/python/py-block.c | 27 ++++++++- > gdb/python/py-breakpoint.c | 68 +++++++++++++++++++++- > gdb/python/py-symbol.c | 16 ++++- > gdb/python/py-type.c | 30 +++++++++- > gdb/testsuite/gdb.python/py-arch.exp | 6 ++ > gdb/testsuite/gdb.python/py-block.exp | 4 +- > gdb/testsuite/gdb.python/py-breakpoint.exp | 24 ++++---- > gdb/testsuite/gdb.python/py-symbol.exp | 2 + > gdb/testsuite/gdb.python/py-type.exp | 4 ++ > 10 files changed, 181 insertions(+), 18 deletions(-) > > diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c > index cf0978560f9..5384a0d0d0c 100644 > --- a/gdb/python/py-arch.c > +++ b/gdb/python/py-arch.c > @@ -319,6 +319,22 @@ archpy_integer_type (PyObject *self, PyObject *args, PyObject *kw) > return type_to_type_object (type); > } > > +/* __repr__ implementation for gdb.Architecture. */ > + > +static PyObject * > +archpy_repr (PyObject *self) > +{ > + const auto gdbarch = arch_object_to_gdbarch (self); > + if (gdbarch == nullptr) > + return PyUnicode_FromFormat > + (""); Additionally, I think that instead of hard-coding gdb.Architecture, we should do: return PyUnicode_FromFormat ("<%s (invalid)>", Py_TYPE (self)->tp_name); The benefit being that if a user sub-classes gdb.Architecture, and doesn't override the __repr__ method, then the name printed will be the name of the sub-class, rather than the base-class. This obviously applies throughout this patch. Thanks, Andrew > + > + return PyUnicode_FromFormat > + ("", > + gdbarch_bfd_arch_info (gdbarch)->arch_name, > + gdbarch_bfd_arch_info (gdbarch)->printable_name); > +} > + > /* Implementation of gdb.architecture_names(). Return a list of all the > BFD architecture names that GDB understands. */ > > @@ -391,7 +407,7 @@ PyTypeObject arch_object_type = { > 0, /* tp_getattr */ > 0, /* tp_setattr */ > 0, /* tp_compare */ > - 0, /* tp_repr */ > + archpy_repr, /* tp_repr */ > 0, /* tp_as_number */ > 0, /* tp_as_sequence */ > 0, /* tp_as_mapping */ > diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c > index b9aea3aca69..b4c55add765 100644 > --- a/gdb/python/py-block.c > +++ b/gdb/python/py-block.c > @@ -424,6 +424,31 @@ blpy_iter_is_valid (PyObject *self, PyObject *args) > Py_RETURN_TRUE; > } > > +/* __repr__ implementation for gdb.Block. */ > + > +static PyObject * > +blpy_repr (PyObject *self) > +{ > + const auto block = block_object_to_block (self); > + if (block == nullptr) > + return PyUnicode_FromFormat (""); > + > + const auto name = block->function () ? > + block->function ()->print_name () : ""; > + > + block_iterator iter; > + block_iterator_first (block, &iter); > + > + std::string str; > + const struct symbol *symbol; > + while ((symbol = block_iterator_next (&iter)) != nullptr) > + str = (str + "\n") + symbol->print_name () + ","; > + if(!str.empty ()) > + str += "\n"; > + > + return PyUnicode_FromFormat ("", name, str.c_str ()); > +} > + > int > gdbpy_initialize_blocks (void) > { > @@ -486,7 +511,7 @@ PyTypeObject block_object_type = { > 0, /*tp_getattr*/ > 0, /*tp_setattr*/ > 0, /*tp_compare*/ > - 0, /*tp_repr*/ > + blpy_repr, /*tp_repr*/ > 0, /*tp_as_number*/ > 0, /*tp_as_sequence*/ > &block_object_as_mapping, /*tp_as_mapping*/ > diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c > index de7b9f4266b..d68a205330c 100644 > --- a/gdb/python/py-breakpoint.c > +++ b/gdb/python/py-breakpoint.c > @@ -33,6 +33,7 @@ > #include "location.h" > #include "py-event.h" > #include "linespec.h" > +#include "gdbsupport/common-utils.h" > > extern PyTypeObject breakpoint_location_object_type > CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("breakpoint_location_object"); > @@ -967,6 +968,31 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs) > return 0; > } > > +/* __repr__ implementation for gdb.Breakpoint. */ > + > +static PyObject * > +bppy_repr (PyObject *self) > +{ > + const auto bp = (struct gdbpy_breakpoint_object*) self; > + if (bp->bp == nullptr) > + return PyUnicode_FromFormat (""); > + > + std::string str = " "; > + if (bp->bp->thread != -1) > + str += string_printf ("thread=%d ", bp->bp->thread); > + if (bp->bp->task > 0) > + str += string_printf ("task=%d ", bp->bp->task); > + if (bp->bp->enable_count > 0) > + str += string_printf ("enable_count=%d ", bp->bp->enable_count); > + str.pop_back (); > + > + return PyUnicode_FromFormat > + ("", > + bp->bp->number, > + bp->bp->hit_count, > + str.c_str ()); > +} > + > /* Append to LIST the breakpoint Python object associated to B. > > Return true on success. Return false on failure, with the Python error > @@ -1389,7 +1415,7 @@ PyTypeObject breakpoint_object_type = > 0, /*tp_getattr*/ > 0, /*tp_setattr*/ > 0, /*tp_compare*/ > - 0, /*tp_repr*/ > + bppy_repr, /*tp_repr*/ > 0, /*tp_as_number*/ > 0, /*tp_as_sequence*/ > 0, /*tp_as_mapping*/ > @@ -1604,6 +1630,44 @@ bplocpy_dealloc (PyObject *py_self) > Py_TYPE (py_self)->tp_free (py_self); > } > > +/* __repr__ implementation for gdb.BreakpointLocation. */ > + > +static PyObject * > +bplocpy_repr (PyObject *py_self) > +{ > + const auto self = (gdbpy_breakpoint_location_object *) py_self; > + if (self->owner == nullptr || self->owner->bp == nullptr > + || self->owner->bp != self->bp_loc->owner) > + return PyUnicode_FromFormat (""); > + > + const auto enabled = self->bp_loc->enabled ? "enabled" : "disabled"; > + > + std::string str(enabled); > + > + str += " requested_address=0x"; > + str += string_printf ("%lx", self->bp_loc->requested_address); > + > + str += " address=0x"; > + str += string_printf ("%lx", self->bp_loc->address); > + > + if (self->bp_loc->symtab != nullptr) > + { > + str += " source="; > + str += self->bp_loc->symtab->filename; > + str += ":"; > + str += string_printf ("%d", self->bp_loc->line_number); > + } > + > + const auto fn_name = self->bp_loc->function_name.get (); > + if (fn_name != nullptr) > + { > + str += " in "; > + str += fn_name; > + } > + > + return PyUnicode_FromFormat ("", str.c_str ()); > +} > + > /* Attribute get/set Python definitions. */ > > static gdb_PyGetSetDef bp_location_object_getset[] = { > @@ -1635,7 +1699,7 @@ PyTypeObject breakpoint_location_object_type = > 0, /*tp_getattr*/ > 0, /*tp_setattr*/ > 0, /*tp_compare*/ > - 0, /*tp_repr*/ > + bplocpy_repr, /*tp_repr*/ > 0, /*tp_as_number*/ > 0, /*tp_as_sequence*/ > 0, /*tp_as_mapping*/ > diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c > index 93c86964f3e..5a8149bbe66 100644 > --- a/gdb/python/py-symbol.c > +++ b/gdb/python/py-symbol.c > @@ -375,6 +375,20 @@ sympy_dealloc (PyObject *obj) > Py_TYPE (obj)->tp_free (obj); > } > > +/* __repr__ implementation for gdb.Symbol. */ > + > +static PyObject * > +sympy_repr (PyObject *self) > +{ > + const auto symbol = symbol_object_to_symbol (self); > + if (symbol == nullptr) > + return PyUnicode_FromFormat (""); > + > + return PyUnicode_FromFormat > + ("", > + symbol->print_name ()); > +} > + > /* Implementation of > gdb.lookup_symbol (name [, block] [, domain]) -> (symbol, is_field_of_this) > A tuple with 2 elements is always returned. The first is the symbol > @@ -732,7 +746,7 @@ PyTypeObject symbol_object_type = { > 0, /*tp_getattr*/ > 0, /*tp_setattr*/ > 0, /*tp_compare*/ > - 0, /*tp_repr*/ > + sympy_repr, /*tp_repr*/ > 0, /*tp_as_number*/ > 0, /*tp_as_sequence*/ > 0, /*tp_as_mapping*/ > diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c > index 928efacfe8a..eb11ef029ca 100644 > --- a/gdb/python/py-type.c > +++ b/gdb/python/py-type.c > @@ -1026,6 +1026,34 @@ typy_template_argument (PyObject *self, PyObject *args) > return value_to_value_object (val); > } > > +/* __repr__ implementation for gdb.Type. */ > + > +static PyObject * > +typy_repr (PyObject *self) > +{ > + const auto type = type_object_to_type (self); > + if (type == nullptr) > + return PyUnicode_FromFormat (""); > + > + const char *code = pyty_codes[type->code ()].name; > + string_file type_name; > + try > + { > + current_language->print_type (type, "", > + &type_name, -1, 0, > + &type_print_raw_options); > + } > + catch (const gdb_exception &except) > + { > + GDB_PY_HANDLE_EXCEPTION (except); > + } > + auto py_typename = PyUnicode_Decode > + (type_name.c_str (), type_name.size (), > + host_charset (), NULL); > + > + return PyUnicode_FromFormat ("", code, py_typename); > +} > + > static PyObject * > typy_str (PyObject *self) > { > @@ -1612,7 +1640,7 @@ PyTypeObject type_object_type = > 0, /*tp_getattr*/ > 0, /*tp_setattr*/ > 0, /*tp_compare*/ > - 0, /*tp_repr*/ > + typy_repr, /*tp_repr*/ > &type_object_as_number, /*tp_as_number*/ > 0, /*tp_as_sequence*/ > &typy_mapping, /*tp_as_mapping*/ > diff --git a/gdb/testsuite/gdb.python/py-arch.exp b/gdb/testsuite/gdb.python/py-arch.exp > index 1fbbc47c872..d436c957e25 100644 > --- a/gdb/testsuite/gdb.python/py-arch.exp > +++ b/gdb/testsuite/gdb.python/py-arch.exp > @@ -29,6 +29,8 @@ if ![runto_main] { > # Test python/15461. Invalid architectures should not trigger an > # internal GDB assert. > gdb_py_test_silent_cmd "python empty = gdb.Architecture()" "get empty arch" 0 > +gdb_test "python print(repr (empty))" "" \ > + "Test empty achitecture __repr__ does not trigger an assert" > gdb_test "python print(empty.name())" ".*Architecture is invalid.*" \ > "Test empty architecture.name does not trigger an assert" > gdb_test "python print(empty.disassemble())" ".*Architecture is invalid.*" \ > @@ -46,6 +48,10 @@ gdb_py_test_silent_cmd "python insn_list3 = arch.disassemble(pc, count=1)" \ > gdb_py_test_silent_cmd "python insn_list4 = arch.disassemble(gdb.Value(pc))" \ > "disassemble no end no count" 0 > > +gdb_test "python print (repr (arch))" \ > + "" \ > + "test __repr__ for architecture" > + > gdb_test "python print (len(insn_list1))" "1" "test number of instructions 1" > gdb_test "python print (len(insn_list2))" "1" "test number of instructions 2" > gdb_test "python print (len(insn_list3))" "1" "test number of instructions 3" > diff --git a/gdb/testsuite/gdb.python/py-block.exp b/gdb/testsuite/gdb.python/py-block.exp > index 0a88aec56a0..5e3d1c72d5e 100644 > --- a/gdb/testsuite/gdb.python/py-block.exp > +++ b/gdb/testsuite/gdb.python/py-block.exp > @@ -39,7 +39,7 @@ gdb_continue_to_breakpoint "Block break here." > gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0 > gdb_py_test_silent_cmd "python block = frame.block()" \ > "Get block, initial innermost block" 0 > -gdb_test "python print (block)" "" "check block not None" > +gdb_test "python print (block)" "" "check block not None" > gdb_test "python print (block.function)" "None" "first anonymous block" > gdb_test "python print (block.start)" "${decimal}" "check start not None" > gdb_test "python print (block.end)" "${decimal}" "check end not None" > @@ -73,7 +73,7 @@ gdb_test "python print (block.function)" "block_func" \ > gdb_test "up" ".*" > gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame 2" 0 > gdb_py_test_silent_cmd "python block = frame.block()" "Get Frame 2's block" 0 > -gdb_test "python print (block)" "" \ > +gdb_test "python print (repr (block))" "" \ > "Check Frame 2's block not None" > gdb_test "python print (block.function)" "main" "main block" > > diff --git a/gdb/testsuite/gdb.python/py-breakpoint.exp b/gdb/testsuite/gdb.python/py-breakpoint.exp > index e36e87dc291..4da46431a3a 100644 > --- a/gdb/testsuite/gdb.python/py-breakpoint.exp > +++ b/gdb/testsuite/gdb.python/py-breakpoint.exp > @@ -50,11 +50,13 @@ proc_with_prefix test_bkpt_basic { } { > return 0 > } > > + set repr_pattern "" > + > # Now there should be one breakpoint: main. > gdb_py_test_silent_cmd "python blist = gdb.breakpoints()" \ > "Get Breakpoint List" 0 > - gdb_test "python print (blist\[0\])" \ > - "" "Check obj exists @main" > + gdb_test "python print (repr (blist\[0\]))" \ > + "$repr_pattern" "Check obj exists @main" > gdb_test "python print (blist\[0\].location)" \ > "main." "Check breakpoint location @main" > gdb_test "python print (blist\[0\].pending)" "False" \ > @@ -71,12 +73,12 @@ proc_with_prefix test_bkpt_basic { } { > "Get Breakpoint List" 0 > gdb_test "python print (len(blist))" \ > "2" "Check for two breakpoints" > - gdb_test "python print (blist\[0\])" \ > - "" "Check obj exists @main 2" > + gdb_test "python print (repr (blist\[0\]))" \ > + "$repr_pattern" "Check obj exists @main 2" > gdb_test "python print (blist\[0\].location)" \ > "main." "Check breakpoint location @main 2" > - gdb_test "python print (blist\[1\])" \ > - "" "Check obj exists @mult_line" > + gdb_test "python print (repr (blist\[1\]))" \ > + "$repr_pattern" "Check obj exists @mult_line" > > gdb_test "python print (blist\[1\].location)" \ > "py-breakpoint\.c:${mult_line}*" \ > @@ -224,14 +226,16 @@ proc_with_prefix test_bkpt_invisible { } { > return 0 > } > > + set repr_pattern "" > + > delete_breakpoints > set ibp_location [gdb_get_line_number "Break at multiply."] > gdb_py_test_silent_cmd "python ibp = gdb.Breakpoint(\"$ibp_location\", internal=False)" \ > "Set invisible breakpoint" 0 > gdb_py_test_silent_cmd "python ilist = gdb.breakpoints()" \ > "Get Breakpoint List" 0 > - gdb_test "python print (ilist\[0\])" \ > - "" "Check invisible bp obj exists 1" > + gdb_test "python print (repr (ilist\[0\]))" \ > + "$repr_pattern" "Check invisible bp obj exists 1" > gdb_test "python print (ilist\[0\].location)" \ > "py-breakpoint\.c:$ibp_location*" "Check breakpoint location 1" > gdb_test "python print (ilist\[0\].visible)" \ > @@ -243,8 +247,8 @@ proc_with_prefix test_bkpt_invisible { } { > "Set invisible breakpoint" 0 > gdb_py_test_silent_cmd "python ilist = gdb.breakpoints()" \ > "Get Breakpoint List" 0 > - gdb_test "python print (ilist\[0\])" \ > - "" "Check invisible bp obj exists 2" > + gdb_test "python print (repr (ilist\[0\]))" \ > + "$repr_pattern" "Check invisible bp obj exists 2" > gdb_test "python print (ilist\[0\].location)" \ > "py-breakpoint\.c:$ibp_location*" "Check breakpoint location 2" > gdb_test "python print (ilist\[0\].visible)" \ > diff --git a/gdb/testsuite/gdb.python/py-symbol.exp b/gdb/testsuite/gdb.python/py-symbol.exp > index ad06b07c2c6..979b7dfb8fb 100644 > --- a/gdb/testsuite/gdb.python/py-symbol.exp > +++ b/gdb/testsuite/gdb.python/py-symbol.exp > @@ -44,6 +44,8 @@ clean_restart ${binfile} > # point where we don't have a current frame, and we don't want to > # require one. > gdb_py_test_silent_cmd "python main_func = gdb.lookup_global_symbol(\"main\")" "Lookup main" 1 > +gdb_test "python print (repr (main_func))" "" \ > + "test main_func.__repr__" > gdb_test "python print (main_func.is_function)" "True" "test main_func.is_function" > gdb_test "python print (gdb.lookup_global_symbol(\"junk\"))" "None" "test lookup_global_symbol(\"junk\")" > > diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp > index 594c9749d8e..95cdfa54a6e 100644 > --- a/gdb/testsuite/gdb.python/py-type.exp > +++ b/gdb/testsuite/gdb.python/py-type.exp > @@ -393,3 +393,7 @@ if { [build_inferior "${binfile}-cxx" "c++"] == 0 } { > test_type_equality > } > } > + > +# Test __repr__() > +gdb_test "python print (repr (gdb.lookup_type ('char')))" \ > + "" "test __repr__()" > -- > 2.37.3.windows.1