mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									1a6594f661
								
							
						
					
					
						commit
						24a2bd0481
					
				
					 5 changed files with 42 additions and 8 deletions
				
			
		|  | @ -523,7 +523,7 @@ APIs: | ||||||
|         - Get the fully qualified name of an object type; |         - Get the fully qualified name of an object type; | ||||||
|           call :c:func:`PyType_GetFullyQualifiedName`. |           call :c:func:`PyType_GetFullyQualifiedName`. | ||||||
| 
 | 
 | ||||||
|       * - ``T#`` |       * - ``#T`` | ||||||
|         - :c:expr:`PyObject*` |         - :c:expr:`PyObject*` | ||||||
|         - Similar to ``T`` format, but use a colon (``:``) as separator between |         - Similar to ``T`` format, but use a colon (``:``) as separator between | ||||||
|           the module name and the qualified name. |           the module name and the qualified name. | ||||||
|  | @ -533,7 +533,7 @@ APIs: | ||||||
|         - Get the fully qualified name of a type; |         - Get the fully qualified name of a type; | ||||||
|           call :c:func:`PyType_GetFullyQualifiedName`. |           call :c:func:`PyType_GetFullyQualifiedName`. | ||||||
| 
 | 
 | ||||||
|       * - ``N#`` |       * - ``#N`` | ||||||
|         - :c:expr:`PyTypeObject*` |         - :c:expr:`PyTypeObject*` | ||||||
|         - Similar to ``N`` format, but use a colon (``:``) as separator between |         - Similar to ``N`` format, but use a colon (``:``) as separator between | ||||||
|           the module name and the qualified name. |           the module name and the qualified name. | ||||||
|  | @ -574,7 +574,7 @@ APIs: | ||||||
|       copied as-is to the result string, and any extra arguments discarded. |       copied as-is to the result string, and any extra arguments discarded. | ||||||
| 
 | 
 | ||||||
|    .. versionchanged:: 3.13 |    .. 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) | .. c:function:: PyObject* PyUnicode_FromFormatV(const char *format, va_list vargs) | ||||||
|  |  | ||||||
|  | @ -1775,7 +1775,7 @@ New Features | ||||||
|   Equivalent to getting the ``type.__module__`` attribute. |   Equivalent to getting the ``type.__module__`` attribute. | ||||||
|   (Contributed by Eric Snow and Victor Stinner in :gh:`111696`.) |   (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 |   :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 |   type and of a type: call :c:func:`PyType_GetModuleName`. See :pep:`737` for | ||||||
|   more information. |   more information. | ||||||
|  |  | ||||||
|  | @ -650,6 +650,40 @@ def check_format(expected, format, *args): | ||||||
|         check_format('\U0001f4bb+' if sizeof(c_wchar) > 2 else '\U0001f4bb', |         check_format('\U0001f4bb+' if sizeof(c_wchar) > 2 else '\U0001f4bb', | ||||||
|                      b'%.2lV', None, c_wchar_p('\U0001f4bb+\U0001f40d')) |                      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 |         # test variable width and precision | ||||||
|         check_format('  abc', b'%*s', c_int(5), b'abc') |         check_format('  abc', b'%*s', c_int(5), b'abc') | ||||||
|         check_format('ab', b'%.*s', c_int(2), b'abc') |         check_format('ab', b'%.*s', c_int(2), b'abc') | ||||||
|  |  | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | Fix :pep:`737` implementation for ``%#T`` and ``%#N``. | ||||||
|  | @ -2468,6 +2468,7 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer, | ||||||
|         switch (*f++) { |         switch (*f++) { | ||||||
|         case '-': flags |= F_LJUST; continue; |         case '-': flags |= F_LJUST; continue; | ||||||
|         case '0': flags |= F_ZERO; continue; |         case '0': flags |= F_ZERO; continue; | ||||||
|  |         case '#': flags |= F_ALT; continue; | ||||||
|         } |         } | ||||||
|         f--; |         f--; | ||||||
|         break; |         break; | ||||||
|  | @ -2797,9 +2798,8 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer, | ||||||
|         PyTypeObject *type = (PyTypeObject *)Py_NewRef(Py_TYPE(obj)); |         PyTypeObject *type = (PyTypeObject *)Py_NewRef(Py_TYPE(obj)); | ||||||
| 
 | 
 | ||||||
|         PyObject *type_name; |         PyObject *type_name; | ||||||
|         if (f[1] == '#') { |         if (flags & F_ALT) { | ||||||
|             type_name = _PyType_GetFullyQualifiedName(type, ':'); |             type_name = _PyType_GetFullyQualifiedName(type, ':'); | ||||||
|             f++; |  | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             type_name = PyType_GetFullyQualifiedName(type); |             type_name = PyType_GetFullyQualifiedName(type); | ||||||
|  | @ -2830,9 +2830,8 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer, | ||||||
|         PyTypeObject *type = (PyTypeObject*)type_raw; |         PyTypeObject *type = (PyTypeObject*)type_raw; | ||||||
| 
 | 
 | ||||||
|         PyObject *type_name; |         PyObject *type_name; | ||||||
|         if (f[1] == '#') { |         if (flags & F_ALT) { | ||||||
|             type_name = _PyType_GetFullyQualifiedName(type, ':'); |             type_name = _PyType_GetFullyQualifiedName(type, ':'); | ||||||
|             f++; |  | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             type_name = PyType_GetFullyQualifiedName(type); |             type_name = PyType_GetFullyQualifiedName(type); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Serhiy Storchaka
						Serhiy Storchaka