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

pyright does not understand trio.open_memory_channel[int](0) #2873

Closed
Zac-HD opened this issue Nov 8, 2023 · 5 comments · Fixed by #2874
Closed

pyright does not understand trio.open_memory_channel[int](0) #2873

Zac-HD opened this issue Nov 8, 2023 · 5 comments · Fixed by #2874
Labels
typing Adding static types to trio's interface

Comments

@Zac-HD
Copy link
Member

Zac-HD commented Nov 8, 2023

# pyright: strict
import trio

send_chan, recv_chan = trio.open_memory_channel[int](1e999)

mypy --strict t.py succeeds, but pyright t.py fails with:

/Users/zac/t.py
  /Users/zac/t.py:4:49 - error: Expected no type arguments for class "open_memory_channel" (reportGeneralTypeIssues)
  /Users/zac/t.py:4:1 - error: Type of "send_chan" is partially unknown
    Type of "send_chan" is "MemorySendChannel[Unknown]" (reportUnknownVariableType)
  /Users/zac/t.py:4:12 - error: Type of "recv_chan" is partially unknown
    Type of "recv_chan" is "MemoryReceiveChannel[Unknown]" (reportUnknownVariableType)
3 errors, 0 warnings, 0 informations 

This is on Trio 0.23.1; if I install trio-typing I don't have any issues - but I'd prefer to drop the extra dependency.

See also: #2734

@Zac-HD Zac-HD added the typing Adding static types to trio's interface label Nov 8, 2023
@Zac-HD
Copy link
Member Author

Zac-HD commented Nov 8, 2023

I also saw a bizarre error: Argument missing for parameter "cancelled_caught" (reportGeneralTypeIssues) for trio.CancelScope(), implying a bug in handling of attrs classes since cancelled_caught is an init=False attribute... but couldn't get an isolated repro. I'm just going to ignore that for now, but noting it here in case someone else runs into it.

@A5rocks
Copy link
Contributor

A5rocks commented Nov 8, 2023

For the attrs thing that's very possible because pyright made a PEP based on dataclasses behavior and then applies it to attrs. mypy just has an attrs plugin builtin that does essentially the same transformations.

As for open_memory_channel it looks like we might be forgetting a Generic there? I find it surprising mypy doesn't warn; does mypy let us imply a generic class? nevermind that seems to pass pyright, hmm.

@A5rocks
Copy link
Contributor

A5rocks commented Nov 8, 2023

OK something's fishy here:

# pyright: strict
from trio._channel import MemorySendChannel, MemoryReceiveChannel, open_memory_channel
import typing

T = typing.TypeVar("T")

class omc(typing.Tuple[MemorySendChannel[T], MemoryReceiveChannel[T]]):
    def __new__(  # type: ignore[misc]  # "must return a subtype"
        cls, max_buffer_size: int | float
    ) -> tuple[MemorySendChannel[T], MemoryReceiveChannel[T]]:
        ...

    def __init__(self, max_buffer_size: int | float):
        ...

reveal_type(omc)
reveal_type(open_memory_channel)

Pyright says:

(.venv) PS C:\Users\A5rocks\Documents\trio\empty> pyright .\pyright-repro.py
C:\Users\A5rocks\Documents\trio\empty\pyright-repro.py
  C:\Users\A5rocks\Documents\trio\empty\pyright-repro.py:20:13 - information: Type of "omc" is "type[omc[Unknown]]"
  C:\Users\A5rocks\Documents\trio\empty\pyright-repro.py:21:13 - information: Type of "open_memory_channel" is "type[open_memory_channel]"
0 errors, 0 warnings, 2 informations

I'm not really feeling like digging deeper, this looks like a pyright bug.

@Zac-HD
Copy link
Member Author

Zac-HD commented Nov 8, 2023

Pyright is working correctly here, so I don't consider this a bug.

The problem is in the trio/_channel.py file. It declares a class called open_memory_channel. It derives from the type Tuple[MemorySendChannel[T], MemoryReceiveChannel[T]]. The problem is that MemorySendChannel and MemoryReceiveChannel are not defined at that point in the file, so they are evaluated as Unknown. The resulting class is therefore not considered generic. If you move the declaration of the open_memory_channel class later in the file (after MemorySendChannel and MemoryReceiveChannel have been defined, then it will work as you expect.

Looks like we can move some code around, check that solves it, and then ship 0.23.2 🙃

@A5rocks
Copy link
Contributor

A5rocks commented Nov 8, 2023

I believe we can just make open_memory_channel inherit from Tuple["MemorySendChannel[T], MemoryReceiveChannel[T]"]. But yeah, 0.23.2 material :/

(I do think that this should work because it's not gonna actually run at runtime and forward declaration stuff but... ugh gotta make sure it works with pyright :( )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
typing Adding static types to trio's interface
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants