gdb: add new helpers for retrieving a type's fully qualified name
Py_TYPE (self)->tp_name is the traditional idiomatic way to get a Python
type's fully qualified name. However, in the context of the Python
limited API, PyTypeObject is opaque, so the 'tp_name' attribute is no
longer accessible. Additionally, retrieving the type of a Python object
requires Py_TYPE, which is only available as part of the stable API
starting with Python 3.14.
This patch increases minimal Python limited API version from 3.11 to 3.14.
It also introduces two new helpers to retrieve a type's fully qualified
name: gdb_py_tp_name() and gdbpy_py_obj_tp_name(), which extract the fully
qualified name from a PyTypeObject and a PyObject, respectively. Ifdefery
allows these wrappers to select the appropriate API depending on the Python
version and whether the Python limited API is enabled. For any Python
version less than 3.13, gdb_py_tp_name() fallbacks using __qualname__
instead. However, the result may differ slightly in some cases, e.g. the
module name may be missing.
Finally, this patch adapts the existing code to use these wrappers, and
adjusts some test expectations to use the fully qualified name (or
__qualname__ for versions <= 3.13) where it was not previously used.
Note that the corner case where the module name would be missing does not
appear in the testsuite.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-01-28 13:09:51 +00:00
|
|
|
/* Helpers related to Python object type
|
|
|
|
|
|
|
|
|
|
Copyright (C) 2026 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
|
|
This file is part of GDB.
|
|
|
|
|
|
|
|
|
|
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 "python-internal.h"
|
|
|
|
|
#include "py-obj-type.h"
|
|
|
|
|
|
|
|
|
|
/* Return the type's fully qualified name from a PyTypeObject. */
|
2026-05-26 11:46:29 +01:00
|
|
|
std::string
|
gdb: add new helpers for retrieving a type's fully qualified name
Py_TYPE (self)->tp_name is the traditional idiomatic way to get a Python
type's fully qualified name. However, in the context of the Python
limited API, PyTypeObject is opaque, so the 'tp_name' attribute is no
longer accessible. Additionally, retrieving the type of a Python object
requires Py_TYPE, which is only available as part of the stable API
starting with Python 3.14.
This patch increases minimal Python limited API version from 3.11 to 3.14.
It also introduces two new helpers to retrieve a type's fully qualified
name: gdb_py_tp_name() and gdbpy_py_obj_tp_name(), which extract the fully
qualified name from a PyTypeObject and a PyObject, respectively. Ifdefery
allows these wrappers to select the appropriate API depending on the Python
version and whether the Python limited API is enabled. For any Python
version less than 3.13, gdb_py_tp_name() fallbacks using __qualname__
instead. However, the result may differ slightly in some cases, e.g. the
module name may be missing.
Finally, this patch adapts the existing code to use these wrappers, and
adjusts some test expectations to use the fully qualified name (or
__qualname__ for versions <= 3.13) where it was not previously used.
Note that the corner case where the module name would be missing does not
appear in the testsuite.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-01-28 13:09:51 +00:00
|
|
|
gdb_py_tp_name (PyTypeObject *py_type) noexcept
|
|
|
|
|
{
|
2026-05-26 11:46:29 +01:00
|
|
|
static const std::string NO_TYPE_NAME = "<type name unavailable>";
|
|
|
|
|
|
|
|
|
|
/* This helper should be used for cases when the called CPython function
|
|
|
|
|
informs the caller that an error occurred, and a Python error was set. */
|
|
|
|
|
auto handle_err = [&]() -> std::string
|
|
|
|
|
{
|
|
|
|
|
gdbpy_print_stack ();
|
|
|
|
|
return NO_TYPE_NAME;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Convert a PyObject to a UTF-8 encoded string. */
|
|
|
|
|
auto pyobj_to_str = [&](PyObject *name) -> std::string
|
|
|
|
|
{
|
|
|
|
|
const char *s = PyUnicode_AsUTF8AndSize (name, nullptr);
|
|
|
|
|
if (s == nullptr)
|
|
|
|
|
return handle_err ();
|
|
|
|
|
return s;
|
|
|
|
|
};
|
|
|
|
|
|
gdb: add new helpers for retrieving a type's fully qualified name
Py_TYPE (self)->tp_name is the traditional idiomatic way to get a Python
type's fully qualified name. However, in the context of the Python
limited API, PyTypeObject is opaque, so the 'tp_name' attribute is no
longer accessible. Additionally, retrieving the type of a Python object
requires Py_TYPE, which is only available as part of the stable API
starting with Python 3.14.
This patch increases minimal Python limited API version from 3.11 to 3.14.
It also introduces two new helpers to retrieve a type's fully qualified
name: gdb_py_tp_name() and gdbpy_py_obj_tp_name(), which extract the fully
qualified name from a PyTypeObject and a PyObject, respectively. Ifdefery
allows these wrappers to select the appropriate API depending on the Python
version and whether the Python limited API is enabled. For any Python
version less than 3.13, gdb_py_tp_name() fallbacks using __qualname__
instead. However, the result may differ slightly in some cases, e.g. the
module name may be missing.
Finally, this patch adapts the existing code to use these wrappers, and
adjusts some test expectations to use the fully qualified name (or
__qualname__ for versions <= 3.13) where it was not previously used.
Note that the corner case where the module name would be missing does not
appear in the testsuite.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-01-28 13:09:51 +00:00
|
|
|
#if PY_VERSION_HEX >= 0x030d0000
|
2026-05-26 11:46:29 +01:00
|
|
|
/* Notes:
|
|
|
|
|
1. PyType_GetFullyQualifiedName() was added in version 3.13, and is
|
|
|
|
|
part of the stable ABI since version 3.13.
|
|
|
|
|
2. If an error occurs when looking up the module name (for instance,
|
|
|
|
|
during the destruction of the object), PyType_GetFullyQualifiedName()
|
|
|
|
|
returns NULL, and a Python error is set. */
|
|
|
|
|
gdbpy_ref<> fully_qualified_name (PyType_GetFullyQualifiedName (py_type));
|
gdb: add new helpers for retrieving a type's fully qualified name
Py_TYPE (self)->tp_name is the traditional idiomatic way to get a Python
type's fully qualified name. However, in the context of the Python
limited API, PyTypeObject is opaque, so the 'tp_name' attribute is no
longer accessible. Additionally, retrieving the type of a Python object
requires Py_TYPE, which is only available as part of the stable API
starting with Python 3.14.
This patch increases minimal Python limited API version from 3.11 to 3.14.
It also introduces two new helpers to retrieve a type's fully qualified
name: gdb_py_tp_name() and gdbpy_py_obj_tp_name(), which extract the fully
qualified name from a PyTypeObject and a PyObject, respectively. Ifdefery
allows these wrappers to select the appropriate API depending on the Python
version and whether the Python limited API is enabled. For any Python
version less than 3.13, gdb_py_tp_name() fallbacks using __qualname__
instead. However, the result may differ slightly in some cases, e.g. the
module name may be missing.
Finally, this patch adapts the existing code to use these wrappers, and
adjusts some test expectations to use the fully qualified name (or
__qualname__ for versions <= 3.13) where it was not previously used.
Note that the corner case where the module name would be missing does not
appear in the testsuite.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-01-28 13:09:51 +00:00
|
|
|
if (fully_qualified_name == nullptr)
|
2026-05-26 11:46:29 +01:00
|
|
|
return handle_err ();
|
|
|
|
|
return pyobj_to_str (fully_qualified_name.get ());
|
gdb: add new helpers for retrieving a type's fully qualified name
Py_TYPE (self)->tp_name is the traditional idiomatic way to get a Python
type's fully qualified name. However, in the context of the Python
limited API, PyTypeObject is opaque, so the 'tp_name' attribute is no
longer accessible. Additionally, retrieving the type of a Python object
requires Py_TYPE, which is only available as part of the stable API
starting with Python 3.14.
This patch increases minimal Python limited API version from 3.11 to 3.14.
It also introduces two new helpers to retrieve a type's fully qualified
name: gdb_py_tp_name() and gdbpy_py_obj_tp_name(), which extract the fully
qualified name from a PyTypeObject and a PyObject, respectively. Ifdefery
allows these wrappers to select the appropriate API depending on the Python
version and whether the Python limited API is enabled. For any Python
version less than 3.13, gdb_py_tp_name() fallbacks using __qualname__
instead. However, the result may differ slightly in some cases, e.g. the
module name may be missing.
Finally, this patch adapts the existing code to use these wrappers, and
adjusts some test expectations to use the fully qualified name (or
__qualname__ for versions <= 3.13) where it was not previously used.
Note that the corner case where the module name would be missing does not
appear in the testsuite.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-01-28 13:09:51 +00:00
|
|
|
|
|
|
|
|
#else /* PY_VERSION_HEX < 0x030d0000 && ! defined (Py_LIMITED_API) */
|
2026-05-26 11:46:29 +01:00
|
|
|
/* For non-heap types, the fully qualified name corresponds to tp_name,
|
|
|
|
|
which can never be NULL. */
|
gdb: add new helpers for retrieving a type's fully qualified name
Py_TYPE (self)->tp_name is the traditional idiomatic way to get a Python
type's fully qualified name. However, in the context of the Python
limited API, PyTypeObject is opaque, so the 'tp_name' attribute is no
longer accessible. Additionally, retrieving the type of a Python object
requires Py_TYPE, which is only available as part of the stable API
starting with Python 3.14.
This patch increases minimal Python limited API version from 3.11 to 3.14.
It also introduces two new helpers to retrieve a type's fully qualified
name: gdb_py_tp_name() and gdbpy_py_obj_tp_name(), which extract the fully
qualified name from a PyTypeObject and a PyObject, respectively. Ifdefery
allows these wrappers to select the appropriate API depending on the Python
version and whether the Python limited API is enabled. For any Python
version less than 3.13, gdb_py_tp_name() fallbacks using __qualname__
instead. However, the result may differ slightly in some cases, e.g. the
module name may be missing.
Finally, this patch adapts the existing code to use these wrappers, and
adjusts some test expectations to use the fully qualified name (or
__qualname__ for versions <= 3.13) where it was not previously used.
Note that the corner case where the module name would be missing does not
appear in the testsuite.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-01-28 13:09:51 +00:00
|
|
|
if (! (PyType_GetFlags (py_type) & Py_TPFLAGS_HEAPTYPE))
|
|
|
|
|
return py_type->tp_name;
|
|
|
|
|
|
|
|
|
|
/* In the absence of PyType_GetFullyQualifiedName(), we fallback using
|
|
|
|
|
__qualname__ instead. However, the result may differ slightly in some
|
|
|
|
|
cases, e.g. the module name may be missing. */
|
|
|
|
|
|
|
|
|
|
# if PY_VERSION_HEX >= 0x030b0000
|
2026-05-26 11:46:29 +01:00
|
|
|
/* Notes:
|
|
|
|
|
1. PyType_GetQualName() was added in version 3.11.
|
|
|
|
|
2. On one hand, PyType_GetQualName() relies internally on ht_qualname
|
|
|
|
|
which is supposed to never be NULL, therefore, does not set any Python
|
|
|
|
|
error. On the other hand, PyType_GetQualName() calls internally
|
|
|
|
|
PyUnicode_AsUTF8AndSize(), which when erroring, sets a Python error
|
|
|
|
|
and returns NULL. */
|
|
|
|
|
gdbpy_ref<> qualname (PyType_GetQualName (py_type));
|
gdb: add new helpers for retrieving a type's fully qualified name
Py_TYPE (self)->tp_name is the traditional idiomatic way to get a Python
type's fully qualified name. However, in the context of the Python
limited API, PyTypeObject is opaque, so the 'tp_name' attribute is no
longer accessible. Additionally, retrieving the type of a Python object
requires Py_TYPE, which is only available as part of the stable API
starting with Python 3.14.
This patch increases minimal Python limited API version from 3.11 to 3.14.
It also introduces two new helpers to retrieve a type's fully qualified
name: gdb_py_tp_name() and gdbpy_py_obj_tp_name(), which extract the fully
qualified name from a PyTypeObject and a PyObject, respectively. Ifdefery
allows these wrappers to select the appropriate API depending on the Python
version and whether the Python limited API is enabled. For any Python
version less than 3.13, gdb_py_tp_name() fallbacks using __qualname__
instead. However, the result may differ slightly in some cases, e.g. the
module name may be missing.
Finally, this patch adapts the existing code to use these wrappers, and
adjusts some test expectations to use the fully qualified name (or
__qualname__ for versions <= 3.13) where it was not previously used.
Note that the corner case where the module name would be missing does not
appear in the testsuite.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-01-28 13:09:51 +00:00
|
|
|
if (qualname == nullptr)
|
2026-05-26 11:46:29 +01:00
|
|
|
return handle_err ();
|
|
|
|
|
return pyobj_to_str (qualname.get ());
|
gdb: add new helpers for retrieving a type's fully qualified name
Py_TYPE (self)->tp_name is the traditional idiomatic way to get a Python
type's fully qualified name. However, in the context of the Python
limited API, PyTypeObject is opaque, so the 'tp_name' attribute is no
longer accessible. Additionally, retrieving the type of a Python object
requires Py_TYPE, which is only available as part of the stable API
starting with Python 3.14.
This patch increases minimal Python limited API version from 3.11 to 3.14.
It also introduces two new helpers to retrieve a type's fully qualified
name: gdb_py_tp_name() and gdbpy_py_obj_tp_name(), which extract the fully
qualified name from a PyTypeObject and a PyObject, respectively. Ifdefery
allows these wrappers to select the appropriate API depending on the Python
version and whether the Python limited API is enabled. For any Python
version less than 3.13, gdb_py_tp_name() fallbacks using __qualname__
instead. However, the result may differ slightly in some cases, e.g. the
module name may be missing.
Finally, this patch adapts the existing code to use these wrappers, and
adjusts some test expectations to use the fully qualified name (or
__qualname__ for versions <= 3.13) where it was not previously used.
Note that the corner case where the module name would be missing does not
appear in the testsuite.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-01-28 13:09:51 +00:00
|
|
|
|
|
|
|
|
# else
|
|
|
|
|
/* In the absence of PyType_GetQualName(), fallback on using PyHeapTypeObject
|
|
|
|
|
which is not part of the public API.
|
|
|
|
|
Tested on 3.10 which is the oldest supported version at the time of this
|
|
|
|
|
writing, i.e. February 2026. Hopefully, this workaround should go away
|
|
|
|
|
when the minimum supported Python version is increased above 3.10. */
|
|
|
|
|
PyHeapTypeObject *ht = (PyHeapTypeObject *) py_type;
|
|
|
|
|
if (ht->ht_qualname == nullptr)
|
2026-05-26 11:46:29 +01:00
|
|
|
return NO_TYPE_NAME;
|
|
|
|
|
return pyobj_to_str (ht->ht_qualname);
|
gdb: add new helpers for retrieving a type's fully qualified name
Py_TYPE (self)->tp_name is the traditional idiomatic way to get a Python
type's fully qualified name. However, in the context of the Python
limited API, PyTypeObject is opaque, so the 'tp_name' attribute is no
longer accessible. Additionally, retrieving the type of a Python object
requires Py_TYPE, which is only available as part of the stable API
starting with Python 3.14.
This patch increases minimal Python limited API version from 3.11 to 3.14.
It also introduces two new helpers to retrieve a type's fully qualified
name: gdb_py_tp_name() and gdbpy_py_obj_tp_name(), which extract the fully
qualified name from a PyTypeObject and a PyObject, respectively. Ifdefery
allows these wrappers to select the appropriate API depending on the Python
version and whether the Python limited API is enabled. For any Python
version less than 3.13, gdb_py_tp_name() fallbacks using __qualname__
instead. However, the result may differ slightly in some cases, e.g. the
module name may be missing.
Finally, this patch adapts the existing code to use these wrappers, and
adjusts some test expectations to use the fully qualified name (or
__qualname__ for versions <= 3.13) where it was not previously used.
Note that the corner case where the module name would be missing does not
appear in the testsuite.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-01-28 13:09:51 +00:00
|
|
|
# endif
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return the type's fully qualified name from a PyObject. */
|
2026-05-26 11:46:29 +01:00
|
|
|
std::string
|
gdb: add new helpers for retrieving a type's fully qualified name
Py_TYPE (self)->tp_name is the traditional idiomatic way to get a Python
type's fully qualified name. However, in the context of the Python
limited API, PyTypeObject is opaque, so the 'tp_name' attribute is no
longer accessible. Additionally, retrieving the type of a Python object
requires Py_TYPE, which is only available as part of the stable API
starting with Python 3.14.
This patch increases minimal Python limited API version from 3.11 to 3.14.
It also introduces two new helpers to retrieve a type's fully qualified
name: gdb_py_tp_name() and gdbpy_py_obj_tp_name(), which extract the fully
qualified name from a PyTypeObject and a PyObject, respectively. Ifdefery
allows these wrappers to select the appropriate API depending on the Python
version and whether the Python limited API is enabled. For any Python
version less than 3.13, gdb_py_tp_name() fallbacks using __qualname__
instead. However, the result may differ slightly in some cases, e.g. the
module name may be missing.
Finally, this patch adapts the existing code to use these wrappers, and
adjusts some test expectations to use the fully qualified name (or
__qualname__ for versions <= 3.13) where it was not previously used.
Note that the corner case where the module name would be missing does not
appear in the testsuite.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-01-28 13:09:51 +00:00
|
|
|
gdbpy_py_obj_tp_name (PyObject *self) noexcept
|
|
|
|
|
{
|
|
|
|
|
/* Note: Py_TYPE () is part of the stable ABI since version 3.14. */
|
|
|
|
|
return gdb_py_tp_name (Py_TYPE (self));
|
|
|
|
|
}
|