[Python-Dev] bpo-34595: How to format a type name?

Walter Dörwald walter at livinglogic.de
Thu Sep 13 05:00:28 EDT 2018


On 13 Sep 2018, at 2:33, Victor Stinner wrote:

> Hi,
>
> For the type name, sometimes, we only get a type (not an instance),
> and we want to format its FQN. IMHO we need to provide ways to format
> the FQN of a type for *types* and for *instances*. Here is my
> proposal:
>
> * Add !t conversion to format string
> * Add ":T" format to type.__format__()
> * Add "%t" and "%T" formatters to PyUnicode_FromUnicodeV()

As far as I can remember, the distinction between lowercase and 
uppercase format letter for PyUnicode_FromUnicodeV() and friends was: 
lowercase letters are for formatting C types (like `char *` etc.) and 
uppercase formatting letters are for Python types (i.e. the C type is 
`PyObject *`). IMHO we should keep that distinction.

> * Add a read-only type.__fqn__ property

I like that.

> # Python: "!t" for instance
> raise TypeError(f"must be str, not {obj!t}")
>
> /* C: "%t" for instance */
> PyErr_Format(PyExc_TypeError, "must be str, not %t", obj);
>
>
> /* C: "%T" for type */
> PyErr_Format(PyExc_TypeError, "must be str, not %T", mytype);
>
> # Python: ":T" for type
> raise TypeError(f"must be str, not {mytype!T}")

We could solve the problem with instances and classes by adding two new 
! operators to str.format/f-strings and making them chainable. The !t 
operator would get the class of the argument and the !c operator would 
require a class argument and would convert it to its name (which is 
obj.__module__ + "." + obj.__qualname__ (or only obj.__qualname__ for 
builtin types)). So:

    >>> import pathlib
    >>> p = pathlib.Path("spam.py")
    >>> print(f"{pathlib.Path}")
     <class 'pathlib.Path'>
    >>> print(f"{pathlib.Path!c}")
     pathlib.Path
    >>> print(f"{pathlib.Path!c!r}")
     'pathlib.Path'
    >>> print(f"{p!t}")
     <class 'pathlib.Path'>
    >>> print(f"{p!t!c}")
     pathlib.Path
    >>> print(f"{p!c}")
     Traceback (most recent call last):
       File "<stdin>", line 1, in <module>
     TypeError: object is not a class

This would also give us:

    >>> print(f"{p!s!r}")
     'spam.py'

Which is different from:

    >>> print(f"{p}")
     spam.py
    >>> print(f"{p!r}")
     PosixPath('spam.py')

> Open question: Should we also add "%t" and "%T" formatters to the str
> % args operator at the Python level?
>
> I have a proof-of-concept implementation:
> https://github.com/python/cpython/pull/9251
>
> Victor

Servus,
    Walter


More information about the Python-Dev mailing list