Plugin hook to selectively silence error messages
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
For developing an Either-like monad that types correctly and also behaves nicely at runtime I currently use the following pattern to independently declare the types for mypy and the runtime implementation
from typing import Generic, TypeVar, TYPE_CHECKING
L = TypeVar('L')
R = TypeVar('R')
if TYPE_CHECKING: # type declarations
class Either(Generic[L, R]): pass
Left = Either[L, None]
Right = Either[None, R]
else: # runtime implementation
class Either(): pass
class Left(Either): pass
class Right(Either): pass
# type checking features
a: Left[int]
b: Either[int, None]
a = b # typechecks
b = a # typechecks
# runtime features
isinstance(Left(), Left) #works at runtime
isinstance(Left(), Either) #works at runtime
During static analysis it is important that Left and Right get treated as aliases for Either so that assignments get typechecked correctly (even though at runtime they are subclasses (and thus subtypes) of Either). Additionally I'd like to be able and use isinstance checks at runtime to determine whether a result is an instance of Left or Right (or more general if something is an instance of Either). This mostly works (assignments typecheck and runtime behavior is as excepted), however mypy (rightfully) complains about the isinstance checks that
Parameterized generics cannot be used with class or instance checks mypy(error)
In cases like these it would be useful if one could tell mypy that a generic class can be used with instance checks. This would also be somewhat similar to how one can declare protocol classes to support runtime instance checks with the @runtime_checkable decorator.
This would also allow user defined generics to behave similar to types from typing like List where
isinstance([1,2,3], List) # typechecks
isinstance([1,2,3], List[int]) # Parameterized generics cannot be ...
vs
isinstance(Left(1), Left) # should typecheck, currently doesn't
isinstance(Left(1), Left[int]) # Parameterized generics cannot be ...
I'd propose that @runtime_checkable marks an Generic accordingly so that in the example it would be
#...
if TYPE_CHECKING: # type declarations
@runtime_checkable
class Either(Generic[L, R]): pass
#...
Addendum
The issue is actually not with Either per se but rather with the type aliases Left and Right. For mypy
isinstance(Left(1), Left) #looks similar to 'isinstance([1,2,3], List)'
actually is
isinstance(Left(1), Either[L, None]) # looks similar to 'isinstance([1,2,3], List[int])'
I still think this would be a useful feature to be able and better support the dynamic nature of Python with the if TYPE_CHECKING pattern.
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
No implementation files or tests are named. Start by tracing mypy's handling of isinstance checks involving generic aliases and compare it with the existing List behavior described in the issue. Done means deciding and implementing the intended treatment of unparameterized and parameterized generic checks, with coverage for the Either, Left, and Right examples.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devtools
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100