typing_extensions icon indicating copy to clipboard operation
typing_extensions copied to clipboard

Backport `annotationlib.value_to_string`

Open JelleZijlstra opened this issue 9 months ago • 3 comments

In 3.14, I added a function to annotationlib to format type-like values, so you get e.g. int instead of <type 'int'>: https://docs.python.org/3.14/library/annotationlib.html#annotationlib.value_to_string

I think this would be useful in typing-extensions too, so let's backport it.

I don't like the name very much though, and it might look even more confusing outside of annotationlib. We can still change it in CPython too, suggestions welcome.

For reference this is what it does:

def value_to_string(value):

    if isinstance(value, type):
        if value.__module__ == "builtins":
            return value.__qualname__
        return f"{value.__module__}.{value.__qualname__}"
    if value is ...:
        return "..."
    if isinstance(value, (types.FunctionType, types.BuiltinFunctionType)):
        return value.__name__
    return repr(value)

JelleZijlstra avatar Mar 20 '25 18:03 JelleZijlstra

Some suggestions:

  • type_name
  • pretty_type_name
  • format_type_name
  • type_repr

srittau avatar Mar 20 '25 19:03 srittau

type_repr is the established name for this, so I'd go with that. I think I would avoid use of "value"? (It makes more sense in PEP 649 context, but this function will get used in all kinds of places)

hauntsaninja avatar Mar 21 '25 00:03 hauntsaninja

Been looking at this backporting issue and the name discussion. I agree that value_to_string isn't ideal – especially outside the original annotationlib context. Plus, I've run into naming collisions with similar helper functions in the past, so picking something more specific definitely makes sense.

type_repr seems like the best option to me too. It clearly conveys what the function does and as @hauntsaninja pointed out, it's already a somewhat established convention.

So, I'd suggest backporting the function with the name type_repr. Here’s a quick sketch of what the backported function could look like:

import types

def type_repr(value):
    if isinstance(value, type):
        if value.__module__ == "builtins":
            return value.__qualname__
        return f"{value.__module__}.{value.__qualname__}"
    if value is ...:
        return "..."
    if isinstance(value, (types.FunctionType, types.BuiltinFunctionType)):
        return value.__name__
    return repr(value)

Should be pretty straightforward to integrate. Let me know if anything comes up.

Mizokuiam avatar Mar 23 '25 01:03 Mizokuiam