Differed Protocol / runtime_checkable import inconsistently causes incompatible type error
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
Bug Report
An incompatible type error is raised for compatible types when Protocol & runtime_checkable are imported via a helper module (see # Option A: Via Helper), but not when they are imported within the module (see # Option B: Directly). Elsewhere in the codebase, importing via the helper module results in the expected behaviour.
Raises: error: Argument 1 to "handle" of "Interpreter" has incompatible type "ComposedAdapter"; expected "Adapter"
To Reproduce
# Option A: Via helper
from tickit.core.utils.compat.typing_compat import Protocol, runtime_checkable
# Option B: Directly
import sys
if sys.version_info >= (3, 8):
from typing import Protocol, runtime_checkable
else:
from typing_extensions import Protocol, runtime_checkable
@runtime_checkable
class Adapter(Protocol):
interrupt: bool
def __init__(self, device: Device) -> None:
...
async def run_forever(self) -> None:
...
class ComposedAdapter:
_interpreter: Interpreter
_server: Server
interrupt: bool = False
def __init__(self, device: Device) -> None:
assert isinstance(self._interpreter, Interpreter)
assert isinstance(self._server, Server)
self._device = device
async def run_forever(self) -> None:
async for interrupt in self._server.run_forever(
lambda message: self._interpreter.handle(self, message) # Error raised here
):
self.interrupt |= interrupt
Where tickit.utils.compat.typing_compat is implemented as:
import sys
if sys.version_info >= (3, 8):
from typing import Protocol, runtime_checkable
else:
from typing_extensions import Protocol, runtime_checkable
__all__ = ["Protocol", "runtime_checkable"]
Expected Behavior
No error is raised when importing via the helper module & behaviour is consistent across the codebase.
Actual Behavior
An error is raised when importing via the helper module.
Your Environment
- Mypy version used: 0.910
- Mypy command-line flags:
N/A - Mypy configuration options from
mypy.ini(and other config files):ignore_missing_imports = True - Python version used: 3.7.9, 3.9.5
- Operating system and version: Red Hat Enterprise Linux release 8.4 (Ootpa)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the incompatible type error using the helper import from tickit.core.utils.compat.typing_compat and compare it with the direct typing or typing_extensions imports shown in the report. Trace how mypy handles Protocol and runtime_checkable through the helper module, then verify that both import styles produce consistent type-checking behavior for the Adapter and ComposedAdapter example.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100