- Get the fully qualified name of an object type;
call :c:func:`PyType_GetFullyQualifiedName`.
- * - ``T#``
+ * - ``#T``
- :c:expr:`PyObject*`
- Similar to ``T`` format, but use a colon (``:``) as separator between
the module name and the qualified name.
- Get the fully qualified name of a type;
call :c:func:`PyType_GetFullyQualifiedName`.
- * - ``N#``
+ * - ``#N``
- :c:expr:`PyTypeObject*`
- Similar to ``N`` format, but use a colon (``:``) as separator between
the module name and the qualified name.
copied as-is to the result string, and any extra arguments discarded.
.. versionchanged:: 3.13
- Support for ``%T``, ``%T#``, ``%N`` and ``%N#`` formats added.
+ Support for ``%T``, ``%#T``, ``%N`` and ``%#N`` formats added.
.. c:function:: PyObject* PyUnicode_FromFormatV(const char *format, va_list vargs)
Equivalent to getting the ``type.__module__`` attribute.
(Contributed by Eric Snow and Victor Stinner in :gh:`111696`.)
-* Add support for ``%T``, ``%T#``, ``%N`` and ``%N#`` formats to
+* Add support for ``%T``, ``%#T``, ``%N`` and ``%#N`` formats to
:c:func:`PyUnicode_FromFormat`: format the fully qualified name of an object
type and of a type: call :c:func:`PyType_GetModuleName`. See :pep:`737` for
more information.
check_format('\U0001f4bb+' if sizeof(c_wchar) > 2 else '\U0001f4bb',
b'%.2lV', None, c_wchar_p('\U0001f4bb+\U0001f40d'))
+ # test %T
+ check_format('type: str',
+ b'type: %T', py_object("abc"))
+ check_format(f'type: st',
+ b'type: %.2T', py_object("abc"))
+ check_format(f'type: str',
+ b'type: %10T', py_object("abc"))
+
+ class LocalType:
+ pass
+ obj = LocalType()
+ fullname = f'{__name__}.{LocalType.__qualname__}'
+ check_format(f'type: {fullname}',
+ b'type: %T', py_object(obj))
+ fullname_alt = f'{__name__}:{LocalType.__qualname__}'
+ check_format(f'type: {fullname_alt}',
+ b'type: %#T', py_object(obj))
+
+ # test %N
+ check_format('type: str',
+ b'type: %N', py_object(str))
+ check_format(f'type: st',
+ b'type: %.2N', py_object(str))
+ check_format(f'type: str',
+ b'type: %10N', py_object(str))
+
+ check_format(f'type: {fullname}',
+ b'type: %N', py_object(type(obj)))
+ check_format(f'type: {fullname_alt}',
+ b'type: %#N', py_object(type(obj)))
+ with self.assertRaisesRegex(TypeError, "%N argument must be a type"):
+ check_format('type: str',
+ b'type: %N', py_object("abc"))
+
# test variable width and precision
check_format(' abc', b'%*s', c_int(5), b'abc')
check_format('ab', b'%.*s', c_int(2), b'abc')
switch (*f++) {
case '-': flags |= F_LJUST; continue;
case '0': flags |= F_ZERO; continue;
+ case '#': flags |= F_ALT; continue;
}
f--;
break;
PyTypeObject *type = (PyTypeObject *)Py_NewRef(Py_TYPE(obj));
PyObject *type_name;
- if (f[1] == '#') {
+ if (flags & F_ALT) {
type_name = _PyType_GetFullyQualifiedName(type, ':');
- f++;
}
else {
type_name = PyType_GetFullyQualifiedName(type);
PyTypeObject *type = (PyTypeObject*)type_raw;
PyObject *type_name;
- if (f[1] == '#') {
+ if (flags & F_ALT) {
type_name = _PyType_GetFullyQualifiedName(type, ':');
- f++;
}
else {
type_name = PyType_GetFullyQualifiedName(type);