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

Eric V. Smith eric at trueblade.com
Thu Sep 13 10:01:08 EDT 2018


On 9/12/2018 8:33 PM, 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

I'm strongly opposed to this. This !t conversion would not be widely 
applicable enough to be generally useful, and would need to be exposed 
in the f-string and str.format() documentation, even though 99% of 
programmers would never need or see it. The purpose of the conversions 
is not to save you from making a function call when you know the type of 
the arguments. The purpose was specifically to convert arguments to 
strings so that your format specifier could always use the string 
formatting mini-language. It was more useful in str.format(), where the 
format string might be written separately (as user input or a 
translation, say) and not know the types of the arguments. You can (and 
I have!) argued that the conversions are completely unneeded in f-strings.

raise TypeError(f"must be str, not {obj!t}")

Should be written as:
raise TypeError(f"must be str, not {type(obj)}")


> * Add ":T" format to type.__format__()
As you know (I've read the patch) this is just "T". I mention it here 
for future readers. They should understand that the ":" is a 
str.format() and f-string construct, and is unknown to __format__().

That said, I think this is a good idea. type.__format__() could also 
understand "#"  to specify qualname.

> * Add "%t" and "%T" formatters to PyUnicode_FromUnicodeV()
I think "T" is a good idea, but I think you're adding in obj vs 
type(obj) just because of the borrowed reference issue in Py_TYPE(). 
That issue is so much larger than string formatting the type of an 
object that it shouldn't be addressed here.

> * Add a read-only type.__fqn__ property
I'm not sure of the purpose of this. When in your examples is it used?
> # 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}")
>
>
> Open question: Should we also add "%t" and "%T" formatters to the str
> % args operator at the Python level?

No. Again, I think any formatting of type names should not be in a 
widely used interface, and should remain in our type-specific interface, 
__format__. %-formatting has no per-type extensibility, and I don't 
think we should start adding codes for every possible use case. Format 
codes for datetimes would be way more useful that %t, and I'd be opposed 
to adding them, too. (I realize my analogy is stretched, because every 
object has a type. But still.)

Eric

>
> I have a proof-of-concept implementation:
> https://github.com/python/cpython/pull/9251
>
> Victor
>
> Victor
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/eric%2Ba-python-dev%40trueblade.com



More information about the Python-Dev mailing list