python - Type hints for dict keys - Stack Overflow

I have code that calls into an API client.The specific API action that I need has a lot of optional a

I have code that calls into an API client. The specific API action that I need has a lot of optional arguments. On my side, there are two cases where I call it, each of which uses a different optional argument. The processing on my side is moderately involved but nearly identical between the two cases, so I combine them as follows (simplified):

def call_api(data: list[str]):
    keyword, value = ("spam", "foo") if condition(data) else ("eggs", "bar")
    kwargs = {keyword: [value]}
    api_client.method(**kwargs)
    something(other, stuff)

If I call it like this, I get a whole bunch of type checker errors from Pylance claiming that values of type list[str] are not valid for most of the other optional params to api_client.method; that's correct, since they expect str arguments. I could easily solve the problem by splitting the two cases into separate functions, each with the argument name hard-coded, but then I'd be duplicating a bunch of code. So to shut up that type checker, I annotate my code as follows:

def call_api(data: list[str]):
    keyword, value = ("spam", "foo") if condition(data) else ("eggs", "bar")
    kwargs: dict[typing.Literal["spam", "eggs"], list[str]] = {keyword: [value]}
    api_client.method(**kwargs)

Now that type checker knows that the argument name is either "spam" or "eggs", for which values of list[str] are valid, and it shuts up.

But now mypy complains:

 error: Dict entry 0 has incompatible type "str": "list[str]"; expected "Literal['spam', 'eggs']": "list[str]"

How can I give mypy enough information to recognize that my dict key is always "spam" or "eggs" while (hopefully) not taking away information that Pylance needs to do the same? I'm using Python 3.9, if that makes a difference.


Follow-up

Based on STerliakov@'s suggestion, I changed my code to the following:

def call_api(data: list[str]):
    keyword: typing.Literal["spam", "eggs"]
    value: str
    keyword, value = ("spam", "foo") if condition(data) else ("eggs", "bar")
    kwargs: dict[typing.Literal["spam", "eggs"], list[str]] = {keyword: [value]}
    api_client.method(**kwargs)

I seem to need the redundant type hint on kwargs to satisfy Pylance; apparently mypy only cares about the hints on the individual variables and Pylance only cares about the hint on the dict. However, I'm still not out of the woods: something in our build system (the debug spew suggests that it's mypy but I haven't been able to reproduce this using mypy outside of our big complicated wrapper) emits the following error:

Incompatible types in assignment (expression has type "str", variable has type
"Literal['spam', 'eggs']")  [assignment]
        key, value = ("spam", "foo") if condition(data) else ("eggs", "...
                     ^

However, this is accepted:

def call_api(data: list[str]):
    keyword: typing.Literal["spam", "eggs"]
    value: str
    if condition(data):
        keyword, value = "spam", "foo"
    else:
        keyword, value = "eggs", "bar"
    kwargs: dict[typing.Literal["spam", "eggs"], list[str]] = {keyword: [value]}
    api_client.method(**kwargs)

What's going on? Those two functions should be completely equivalent, shouldn't they? Or am I looking at a buggy type checker?

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744172645a4561609.html

相关推荐

  • python - Type hints for dict keys - Stack Overflow

    I have code that calls into an API client.The specific API action that I need has a lot of optional a

    9天前
    10

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信