pythonpython-typingpyright

Type hinting an object created by typing.Literal[]


I'm trying to create a function that goes through Unions and Literals and extracts their possible values. I'm trying to do that because I want to create a function that takes in a function and describes that passed-in function's parameters in the json-schema format (see https://platform.openai.com/docs/guides/function-calling).

The code I have right now for the function looks like this:

from typing import get_origin, get_args, Literal, Union

def traverse_union(union_type):
    origin = get_origin(union_type)
    
    if origin in {Union, Literal}:
        for argument in get_args(union_type):
            yield from traverse_union(argument)
        return
    
    yield union_type

print(list(traverse_union(int | float | Literal["Hello, world!"]))) 
# [<class 'int'>, <class 'str'>, 'Hello, world!']

I'm not quite sure how to add type annotations to it though. Ideally I want the function to take in some kind of type like union_type: UnionType | LiteralType and return a kind of type like -> Iterable[type | str | int | float | # and more literal types] but nothing I do seems to be right or even work for that matter.

I think my biggest roadblock is that LiteralType doesn't actually exist, and type[Literal] is invalid syntax (Expected type arguments for generic class "Literal"). From there, I think I can figure it out myself.

Could anybody help me?


Solution

  • After asking around a bit more (thanks @21305238/insync), I've found that what I actually want are TypeExprs.

    In the discussion for its PEP, TypeExprs are described as follows:

    They are similar to type[] class objects, but additionally allow matching TypedDicts, generic lists, unions, literals, and other complex types.

    When TypeExprs land, hopefully in Python 3.14, it'll be perfect for what I want to do, but unfortunately I haven't found a decent workaround for right now.