Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

str counts as a Callable[..., str], but not as a Callable[..., TypeVar] #16867

Closed
rish-shadra opened this issue Feb 3, 2024 · 1 comment
Closed
Labels
bug mypy got something wrong

Comments

@rish-shadra
Copy link

rish-shadra commented Feb 3, 2024

Bug Report

Hey folks!

I ran into what I think is a bug while trying to write a config retrieval library for a Flask server. I'd like to pass a return_type argument into my get_config function. When the argument is provided, I'd like the function to return a value as that type.

To Reproduce

Here's a pared-down version of my function that still causes MyPy to error out. Pyright seems to think this code is valid.

from typing import Callable, TypeVar
ValueType = TypeVar("ValueType")

def get_config(return_type: Callable[..., ValueType] = str) -> ValueType:
    return return_type(42)

# mypy get_config_typed.py
# error: Incompatible default for argument "return_type" (default has type "type[str]", argument has type "Callable[..., ValueType]")  [assignment]

The same code works fine when ValueType is replaced with str:

from typing import Callable

def get_config(return_type: Callable[..., str] = str) -> str:
    return return_type(42)

# mypy get_config_typed.py
# Success: no issues found in 1 source file

Actual Behavior

error: Incompatible default for argument "return_type" (default has type "type[str]", argument has type "Callable[..., ValueType]") [assignment]

Your Environment

% mypy --version
mypy 1.8.0 (compiled: yes)
% python --version
Python 3.9.17
% uname -a
Darwin <...> 23.2.0 Darwin Kernel Version 23.2.0: Wed Nov 15 21:54:51 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T6030 arm64
  • Mypy version used: 1.8.0
  • Mypy command-line flags: N/A
  • Mypy configuration options from mypy.ini (and other config files): N/A
  • Python version used: 3.9.17
@rish-shadra rish-shadra added the bug mypy got something wrong label Feb 3, 2024
@picnixz
Copy link
Member

picnixz commented Feb 4, 2024

One workaround is to use overloads.

from typing import Any, Callable, TypeVar, overload

T_co = TypeVar('T_co', covariant=True)

@overload
def get_config() -> str: ...
@overload
def get_config(return_type: Callable[..., T_co]) -> T_co: ...
def get_config(return_type: Callable[..., Any] = str) -> Any:
    return return_type(42)

def foo(x: Any) -> dict[str, Any]: 
    return {}

reveal_type(get_config())     # builtins.str
reveal_type(get_config(int))  # builtins.int
reveal_type(get_config(foo))  # builtins.dict[builtins.str, Any]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

3 participants