Skip to content

Conversation

@cuu508
Copy link
Contributor

@cuu508 cuu508 commented Oct 27, 2025

@github-actions

This comment has been minimized.

@srittau
Copy link
Collaborator

srittau commented Oct 30, 2025

As the primer output shows, this is problematic, as the user needs to add an instance check, even though the return type is usually statically known.

A better approach would be to add overloads for the various info options that can be supplied to these functions with the appropriate return types.

@cuu508
Copy link
Contributor Author

cuu508 commented Oct 31, 2025

getinfo takes a single integer argument and the return values have different types depending on the argument's value.

Is it possible to use @overload to match specific constant values of a function's argument?

@cuu508
Copy link
Contributor Author

cuu508 commented Oct 31, 2025

Ah, looks like something this might work:

from typing import Literal, overload


@overload
def foo(x: Literal[1]) -> int:
    ...


@overload
def foo(x: Literal[2]) -> str:
    ...


def foo(x: int):
    if x == 1:
        return 1
    if x == 2:
        return "world"


print(1 + foo(1))
print("hello " + foo(2))

I'll see if can use something similar in the PR.

@cuu508
Copy link
Contributor Author

cuu508 commented Oct 31, 2025

The only way I've found to work so far is quite messy. In pycurl.pyi:

class Curl:
    [...]
    @overload
    def getinfo(self, info: Literal[1048577]) -> str: ...
    @overload
    def getinfo(self, info: Literal[2097154]) -> int: ...
    @overload
    def getinfo(self, info: Literal[4194338]) -> list[Sequence[tuple[str, str]]]: ...
    @overload
    def getinfo(self, info: int): ...
    [...]

In client code:

import pycurl

c = pycurl.Curl()
reveal_type(c.getinfo(pycurl.EFFECTIVE_URL))  # mypy reveals: builtins.str
reveal_type(c.getinfo(pycurl.RESPONSE_CODE))  # mypy reveals: builtins.int
reveal_type(c.getinfo(pycurl.INFO_CERTINFO))  # mypy reveals: builtins.list[typing.Sequence[tuple[builtins.str, builtins.str]]]

The messy part is that I cannot use the existing pycurl constants (pycurl.EFFECTIVE_URL, pycurl.RESPONSE_CODE etc.) in the type annotations, I must duplicate the constant values.

I tried a few different things like:

@overload
def getinfo(self, info: Literal[pycurl.EFFECTIVE_URL]) -> str: ...

and:

EFFECTIVE_URL: Literal[1048577] = 1048577
@overload
def getinfo(self, info: EFFECTIVE_URL) -> str: ...

but neither worked with mypy.

@srittau
Copy link
Collaborator

srittau commented Oct 31, 2025

I didn't realize the constants were this messy. In that case, I don't think we should overloads like I suggested, but instead we should use Any as return type with a comment that the exact type depends on the requested mode. Unfortunately that's the only reasonable way to prevent unnecessary isinstance checks.

@github-actions
Copy link
Contributor

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

Copy link
Collaborator

@srittau srittau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@srittau srittau merged commit e389c7b into python:main Oct 31, 2025
48 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants