PEP 737: Remove Python changes (#3704)

This commit is contained in:
Victor Stinner 2024-03-14 12:30:23 +01:00 committed by GitHub
parent ec2ca2ec6c
commit b69e2daa81
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 163 additions and 151 deletions

View File

@ -1,5 +1,5 @@
PEP: 737 PEP: 737
Title: Unify type name formatting Title: C API to format a type fully qualified name
Author: Victor Stinner <vstinner@python.org> Author: Victor Stinner <vstinner@python.org>
Discussions-To: https://discuss.python.org/t/pep-737-unify-type-name-formatting/39872 Discussions-To: https://discuss.python.org/t/pep-737-unify-type-name-formatting/39872
Status: Draft Status: Draft
@ -12,17 +12,12 @@ Post-History: `29-Nov-2023 <https://discuss.python.org/t/pep-737-unify-type-name
Abstract Abstract
======== ========
Add new convenient APIs to format type names the same way in Python and Add new convenient C APIs to format a type fully qualified name. No longer
in C. No longer format type names differently depending on how types are format type names differently depending on how types are implemented.
implemented.
Recommend using the type fully qualified name in error messages and in Recommend using the type fully qualified name in error messages and in
``__repr__()`` methods in new code. Recommend not truncating type names ``__repr__()`` methods in new C code. Recommend not truncating type
in new code. names in new C code.
Add ``N`` and ``#N`` formats to ``type.__format__()`` to format a type
fully qualified name. For example, ``f"{type(obj):N}"`` formats the
fully qualified name of an object *obj*.
Add ``%T``, ``%#T``, ``%N`` and ``%#N`` formats to Add ``%T``, ``%#T``, ``%N`` and ``%#N`` formats to
``PyUnicode_FromFormat()`` to format the fully qualified, respectively, ``PyUnicode_FromFormat()`` to format the fully qualified, respectively,
@ -180,16 +175,149 @@ limit of 500 bytes is outdated
Specification Specification
============= =============
* Add ``type.__fully_qualified_name__`` attribute.
* Add ``type.__format__()`` method.
* Add formats to ``PyUnicode_FromFormat()``.
* Add ``PyType_GetModuleName()`` function.
* Add ``PyType_GetFullyQualifiedName()`` function. * Add ``PyType_GetFullyQualifiedName()`` function.
* Add ``PyType_GetModuleName()`` function.
* Add formats to ``PyUnicode_FromFormat()``.
* Recommend using the type fully qualified name in error messages and * Recommend using the type fully qualified name in error messages and
in ``__repr__()`` methods in new code. in ``__repr__()`` methods in new C code.
* Recommend not truncating type names in new code. * Recommend not truncating type names in new C code.
Add PyType_GetFullyQualifiedName() function
-------------------------------------------
Add the ``PyType_GetFullyQualifiedName()`` function to get the fully
qualified name of a type: similar to
``f"{type.__module__}.{type.__qualname__}"``, or ``type.__qualname__``
if ``type.__module__`` is not a string or is equal to ``"builtins"`` or
is equal to ``"__main__"``.
API:
.. code-block:: c
PyObject* PyType_GetFullyQualifiedName(PyTypeObject *type)
On success, return a new reference to the string. On error, raise an
exception and return ``NULL``.
Add PyType_GetModuleName() function
-----------------------------------
Add the ``PyType_GetModuleName()`` function to get the module name of a
type (``type.__module__`` string). API:
.. code-block:: c
PyObject* PyType_GetModuleName(PyTypeObject *type)
On success, return a new reference to the string. On error, raise an
exception and return ``NULL``.
Add formats to PyUnicode_FromFormat()
-------------------------------------
Add the following formats to ``PyUnicode_FromFormat()``:
* ``%N`` formats the **fully qualified name** of a **type**,
similar to ``PyType_GetFullyQualifiedName(type)``;
**N** stands for type **N**\ ame.
* ``%T`` formats the type **fully qualified name** of an **object**,
similar to ``PyType_GetFullyQualifiedName(Py_TYPE(obj))``;
**T** stands for object **T**\ ype.
* ``%#N`` and ``%#T``: the alternative form uses the **colon** separator
(``:``), instead of the dot separator (``.``), between the module name
and the qualified name.
For example, the existing code using *tp_name*:
.. code-block:: c
PyErr_Format(PyExc_TypeError,
"__format__ must return a str, not %.200s",
Py_TYPE(result)->tp_name);
can be replaced with the ``%T`` format:
.. code-block:: c
PyErr_Format(PyExc_TypeError,
"__format__ must return a str, not %T", result);
Advantages of the updated code:
* Safer C code: avoid ``Py_TYPE()`` which returns a borrowed reference.
* The ``PyTypeObject.tp_name`` member is no longer read explicitly: the
code becomes compatible with the limited C API.
* The formatted type name no longer depends on the type implementation.
* The type name is no longer truncated.
Note: The ``%T`` format is used by ``time.strftime()``, but not by
``printf()``.
Formats Summary
---------------
.. list-table::
:header-rows: 1
* - C object
- C type
- Format
* - ``%T``
- ``%N``
- Type **fully qualified** name.
* - ``%#T``
- ``%#N``
- Type **fully qualified** name, **colon** separator.
Recommend using the type fully qualified name
---------------------------------------------
The type fully qualified name is recommended in error messages and in
``__repr__()`` methods in new C code.
In non-trivial applications, it is likely to have two types with the
same short name defined in two different modules, especially with
generic names. Using the fully qualified name helps identifying the type
in an unambiguous way.
Recommend not truncating type names
-----------------------------------
Type names should not be truncated in new C code. For example, the
``%.100s`` format should be avoided: use the ``%s`` format instead (or
``%T`` format in C).
Implementation
==============
* Pull request: `Add type.__fully_qualified_name__ attribute <https://github.com/python/cpython/pull/112133>`_.
* Pull request: `Add %T format to PyUnicode_FromFormat() <https://github.com/python/cpython/pull/111703>`_.
Backwards Compatibility
=======================
Changes proposed in this PEP are backward compatible.
Adding new C APIs has no effect on the backward compatibility. Existing
C APIs are left unchanged. No Python API is changed.
Replacing the type short name with the type fully qualified name is only
recommended in new C code. No longer truncating type names is only
recommended in new C code. Existing code should be left unchanged and so
remains backward compatible. There is no recommendation for Python code.
Rejected Ideas
==============
Add type.__fully_qualified_name__ attribute Add type.__fully_qualified_name__ attribute
------------------------------------------- -------------------------------------------
@ -202,6 +330,22 @@ equal to ``"__main__"``.
The ``type.__repr__()`` is left unchanged, it only omits the module if The ``type.__repr__()`` is left unchanged, it only omits the module if
the module is equal to ``"builtins"``. the module is equal to ``"builtins"``.
This change was `rejected by the Steering Council
<https://discuss.python.org/t/pep-737-unify-type-name-formatting/39872/51>`__:
We can see the usefulness of the C API changes proposed by the PEP
and would likely accept those changes as is.
We see less justification for the Python level changes. We
especially question the need for ``__fully_qualified_name__``.
Thomas Wouters added:
If there really is a desire for formatting types the exact same way
the C API does it, a utility function would make more sense to me,
personally, than ``type.__format__``, but I think the SC could be
persuaded given some concrete use-cases.
Add type.__format__() method Add type.__format__() method
---------------------------- ----------------------------
@ -228,141 +372,9 @@ guesswork when you want to import the name, see
``pkgutil.resolve_name()``, ``python -m inspect`` command line ``pkgutil.resolve_name()``, ``python -m inspect`` command line
interface, and ``setuptools`` entry points. interface, and ``setuptools`` entry points.
This change was `rejected by the Steering Council
<https://discuss.python.org/t/pep-737-unify-type-name-formatting/39872/52>`__.
Add formats to PyUnicode_FromFormat()
-------------------------------------
Add the following formats to ``PyUnicode_FromFormat()``:
* ``%N`` formats the **fully qualified name** of a **type**
(``type.__fully_qualified_name__``); **N** stands for type **N**\ ame.
* ``%T`` formats the type **fully qualified name** of an **object**
(``type(obj).__fully_qualified_name__``); **T** stands for object
**T**\ ype.
* ``%#N`` and ``%#T``: the alternative form uses the **colon** separator
(``:``), instead of the dot separator (``.``), between the module name
and the qualified name.
For example, the existing code using *tp_name*:
.. code-block:: c
PyErr_Format(PyExc_TypeError,
"__format__ must return a str, not %.200s",
Py_TYPE(result)->tp_name);
can be replaced with the ``%T`` format:
.. code-block:: c
PyErr_Format(PyExc_TypeError,
"__format__ must return a str, not %T", result);
Advantages of the updated code:
* Safer C code: avoid ``Py_TYPE()`` which returns a borrowed reference.
* The ``PyTypeObject.tp_name`` member is no longer read explicitly: the
code becomes compatible with the limited C API.
* The ``PyTypeObject.tp_name`` bytes string no longer has to be decoded
from UTF-8 at each ``PyErr_Format()`` call, since
``type.__fully_qualified_name__`` is already a Unicode string.
* The formatted type name no longer depends on the type implementation.
* The type name is no longer truncated.
Note: The ``%T`` format is used by ``time.strftime()``, but not by
``printf()``.
Formats Summary
---------------
.. list-table::
:header-rows: 1
* - C object
- C type
- Python
- Format
* - ``%T``
- ``%N``
- ``:N``
- Type **fully qualified** name.
* - ``%#T``
- ``%#N``
- ``:#N``
- Type **fully qualified** name, **colon** separator.
Add PyType_GetModuleName() function
-----------------------------------
Add the ``PyType_GetModuleName()`` function to get the module name of a
type (``type.__module__``). API:
.. code-block:: c
PyObject* PyType_GetModuleName(PyTypeObject *type)
On success, return a new reference to the string. On error, raise an
exception and return ``NULL``.
Add PyType_GetFullyQualifiedName() function
-------------------------------------------
Add the ``PyType_GetFullyQualifiedName()`` function to get the fully
qualified name of a type (``type.__fully_qualified_name__``). API:
.. code-block:: c
PyObject* PyType_GetFullyQualifiedName(PyTypeObject *type)
On success, return a new reference to the string. On error, raise an
exception and return ``NULL``.
Recommend using the type fully qualified name
---------------------------------------------
The type fully qualified name is recommended in error messages and in
``__repr__()`` methods in new code.
In non-trivial applications, it is likely to have two types with the
same short name defined in two different modules, especially with
generic names. Using the fully qualified name helps identifying the type
in an unambiguous way.
Recommend not truncating type names
-----------------------------------
Type names should not be truncated in new code. For example, the
``%.100s`` format should be avoided: use the ``%s`` format instead (or
``%T`` format in C).
Implementation
==============
* Pull request: `Add type.__fully_qualified_name__ attribute <https://github.com/python/cpython/pull/112133>`_.
* Pull request: `Add %T format to PyUnicode_FromFormat() <https://github.com/python/cpython/pull/111703>`_.
Backwards Compatibility
=======================
Changes proposed in this PEP are backward compatible.
Adding new APIs has no effect on the backward compatibility. Existing
APIs are left unchanged.
Replacing the type short name with the type fully qualified name is only
recommended in new code. No longer truncating type names is only
recommended in new code. Existing code should be left unchanged and so
remains backward compatible.
Rejected Ideas
==============
Change str(type) Change str(type)
---------------- ----------------
@ -386,7 +398,7 @@ Add !t formatter to get an object type
Use ``f"{obj!t:T}"`` to format ``type(obj).__fully_qualified_name__``, Use ``f"{obj!t:T}"`` to format ``type(obj).__fully_qualified_name__``,
similar to ``f"{type(obj):T}"``. similar to ``f"{type(obj):T}"``.
When the ``!t`` formatter was proposed in 2018, `Eric Smith was stronly When the ``!t`` formatter was proposed in 2018, `Eric Smith was strongly
opposed to this opposed to this
<https://mail.python.org/archives/list/python-dev@python.org/message/BMIW3FEB77OS7OB3YYUUDUBITPWLRG3U/>`_; <https://mail.python.org/archives/list/python-dev@python.org/message/BMIW3FEB77OS7OB3YYUUDUBITPWLRG3U/>`_;
Eric is the author of the f-string :pep:`498` "Literal String Interpolation". Eric is the author of the f-string :pep:`498` "Literal String Interpolation".