https://github.com/python/cpython/commit/24a2bd048115efae799b0a9c5dd9fbb7a0806978
commit: 24a2bd048115efae799b0a9c5dd9fbb7a0806978
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2024-04-08T16:27:25Z
summary:

gh-117642: Fix PEP 737 implementation (GH-117643)

* Fix implementation of %#T and %#N (they were implemented as %T# and
  %N#).
* Restore tests removed in gh-116417.

files:
A Misc/NEWS.d/next/C API/2024-04-08-18-53-33.gh-issue-117642._-tYH_.rst
M Doc/c-api/unicode.rst
M Doc/whatsnew/3.13.rst
M Lib/test/test_capi/test_unicode.py
M Objects/unicodeobject.c

diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst
index 78eec14e3a24d6..7320d035bab513 100644
--- a/Doc/c-api/unicode.rst
+++ b/Doc/c-api/unicode.rst
@@ -523,7 +523,7 @@ APIs:
         - 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.
@@ -533,7 +533,7 @@ APIs:
         - 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.
@@ -574,7 +574,7 @@ APIs:
       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)
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 0fe2dafbfd6f02..72b3a4c951eda6 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -1775,7 +1775,7 @@ New Features
   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.
diff --git a/Lib/test/test_capi/test_unicode.py 
b/Lib/test/test_capi/test_unicode.py
index a64c75c415c3fe..a69f817c515ba7 100644
--- a/Lib/test/test_capi/test_unicode.py
+++ b/Lib/test/test_capi/test_unicode.py
@@ -650,6 +650,40 @@ def check_format(expected, format, *args):
         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')
diff --git a/Misc/NEWS.d/next/C 
API/2024-04-08-18-53-33.gh-issue-117642._-tYH_.rst b/Misc/NEWS.d/next/C 
API/2024-04-08-18-53-33.gh-issue-117642._-tYH_.rst
new file mode 100644
index 00000000000000..edef2777717014
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2024-04-08-18-53-33.gh-issue-117642._-tYH_.rst     
@@ -0,0 +1 @@
+Fix :pep:`737` implementation for ``%#T`` and ``%#N``.
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 59b350f0a609a6..5f15071d7d54ef 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -2468,6 +2468,7 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer,
         switch (*f++) {
         case '-': flags |= F_LJUST; continue;
         case '0': flags |= F_ZERO; continue;
+        case '#': flags |= F_ALT; continue;
         }
         f--;
         break;
@@ -2797,9 +2798,8 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer,
         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);
@@ -2830,9 +2830,8 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer,
         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);

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to