trio icon indicating copy to clipboard operation
trio copied to clipboard

attempt to add typing to _create

Open jakkdl opened this issue 8 months ago • 4 comments

context: https://github.com/python-trio/trio/pull/3256#discussion_r2067494288

@A5rocks

remaining errors:

src/trio/_core/_local.py:27: error: Argument 1 to "_create" of "NoPublicConstructor" has incompatible type "RunVar[T]"; expected "Never"  [arg-type]
src/trio/_channel.py:265: error: Argument 1 to "_create" of "NoPublicConstructor" has incompatible type "MemoryChannelState[SendType]"; expected "Never"  [arg-type]
src/trio/_channel.py:417: error: Argument 1 to "_create" of "NoPublicConstructor" has incompatible type "MemoryChannelState[ReceiveType]"; expected "Never"  [arg-type]

my hypothesis for these is that they all inherit from some other class which doesn't have this parameter, and _create sees the super class. idk how to fix that

src/trio/_core/_run.py:1907: error: Argument "coro" to "_create" of "NoPublicConstructor" has incompatible type "Coroutine[object, Never, object]"; expected "CoroutineType[Any, Outcome[object], Any]"  [arg-type]

idk who's in the wrong here

src/trio/_subprocess.py:430: error: Argument 1 to "_create" of "NoPublicConstructor" has incompatible type "Popen[str]"; expected "Popen[bytes]"  [arg-type]

this might be an actual bug? https://github.com/python/typeshed/blob/eec809d049d10a5ae9b88780eab15fe36a9768d7/stdlib/subprocess.pyi#L1464 for reference

jakkdl avatar May 01 '25 11:05 jakkdl

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Project coverage is 100.00000%. Comparing base (9c909fa) to head (b08cc92).

Additional details and impacted files
@@               Coverage Diff               @@
##                 main        #3260   +/-   ##
===============================================
  Coverage   100.00000%   100.00000%           
===============================================
  Files             124          124           
  Lines           19047        19047           
  Branches         1287         1287           
===============================================
  Hits            19047        19047           
Files with missing lines Coverage Δ
src/trio/_util.py 100.00000% <100.00000%> (ø)
src/trio/testing/_fake_net.py 100.00000% <100.00000%> (ø)
:rocket: New features to boost your workflow:
  • :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

codecov[bot] avatar May 01 '25 11:05 codecov[bot]

For the _create calls, I know Never often appears if mypy failed to solve the typevars, so could be an inference failure. Might be good to add reveal_type(TheClass._create) calls so we can see what mypy assumes it is.

reveal_type(cls._create) in class RunVarToken(Generic[T], metaclass=NoPublicConstructor)

src/trio/_core/_local.py:27: note: Revealed type is "def (*args: Never, **kwargs: Never) -> trio._core._local.RunVarToken[T`1]"

reveal_type(MemorySendChannel._create)

src/trio/_channel.py:265: note: Revealed type is "def (*args: Never, **kwargs: Never) -> Never"

jakkdl avatar May 02 '25 13:05 jakkdl

also if anybody wants to mess around with this PR you are very welcome, I'm not gonna put a lot of effort into it

jakkdl avatar May 02 '25 13:05 jakkdl

Looks like this approach doesn't handle type vars (I think that's what you're seeing):

import dataclasses
from typing import Protocol, TypeVar, ParamSpec, Generic, Callable

T = TypeVar("T", covariant=True)
P = ParamSpec("P")

class Meta(type):
    def __call__(cls, *args: object, **kwargs: object) -> None:
        raise TypeError(
            f"{cls.__module__}.{cls.__qualname__} has no public constructor",
        )

    def _create(cls: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> type[T]:
        return super().__call__(*args, **kwargs)  # type: ignore

@dataclasses.dataclass
class X(Generic[T], metaclass=Meta):
    x: T


reveal_type(X._create)  # N: Revealed type is "def (*args: Never, **kwargs: Never) -> type[Never]"

Surprisingly now that I see it minimized like that, I think I know exactly the bug: https://github.com/python/mypy/issues/18400. I haven't checked my solution PR to make sure it has the same cause though.

A5rocks avatar May 03 '25 03:05 A5rocks