Skip to content

Incorrect typing when using asyncio.run #13262

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

Closed
Ben-Epstein opened this issue Dec 18, 2024 · 1 comment
Closed

Incorrect typing when using asyncio.run #13262

Ben-Epstein opened this issue Dec 18, 2024 · 1 comment

Comments

@Ben-Epstein
Copy link

Apologies if i'm in the wrong repo. I thought this was the right place because of #30

I have an example where mypy is complaining that my call is returning a type object when it should be returning Response[T] | Response[str]

import asyncio
import json
from typing import Generic, Type, TypeVar, overload

from pydantic import BaseModel, Field

T = TypeVar("T", bound=BaseModel)
U = TypeVar("U", bound=str | BaseModel) 


class Response(BaseModel, Generic[U]):
    text: str
    response_schema: Type[BaseModel] | None

    @property
    def out(self) -> U:
        if self.response_schema:
            return self.response_schema.model_validate_json(self.text)
        return self.text

    class Config:
        arbitrary_types_allowed = True


@overload
async def apredict(prompt: str, response_schema: Type[T]) -> Response[T]: ...
@overload
async def apredict(prompt: str, response_schema: None = ...) -> Response[str]: ...

async def apredict(prompt: str, response_schema: Type[T] | None = None) -> Response[str] | Response[T]:
    ... # irrelevant 
    
@overload
def predict(prompt: str, response_schema: Type[T]) -> Response[T]: ...
@overload
def predict(prompt: str, response_schema: None = ...) -> Response[str]: ...

def predict(prompt: str, response_schema: Type[T] | None = None) -> Response[str] | Response[T]:
    return asyncio.run(apredict(prompt, response_schema))

I get an error Incompatible return value type (got "object", expected "Response[str] | Response[T]") which I don't expect because it seems to be typed generically based on the signature of the function it is running.

thanks!

@Ben-Epstein Ben-Epstein changed the title Incorrect typing when using asyncio.gather Incorrect typing when using asyncio.run Dec 18, 2024
@srittau
Copy link
Collaborator

srittau commented Dec 18, 2024

This is due to the narrowing behavior of mypy. See this simplified example:

import asyncio
from typing import overload

@overload
async def apredict(x: int) -> int: ...
@overload
async def apredict(x: str) -> str: ...
async def apredict(x: int | str) -> int | str:
    return ""
    
x: int | str
y = asyncio.run(apredict(x))
reveal_type(y)  # object

Unfortunately, there's nothing we can do about this in typeshed, although I think there's talk about changing this behavior over at mypy.

@srittau srittau closed this as not planned Won't fix, can't repro, duplicate, stale Dec 18, 2024
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

No branches or pull requests

2 participants