Submit a pull request to mypy implementing support for PEP 613. This PEP is intended to give users a way of directly resolving this ambiguity by letting them directly indicate whether something is supposed to be a type alias or not.
This PEP has been accepted; the only reason why mypy doesn't support it is because nobody has gotten around to implementing it yet.
Ask the Cython maintainers if they'd be ok with shipping stub files for cython by turning their package into a PEP 561 compliant package -- a package that comes bundled with type hints.
It seems Cython is already bundling some type hints in a limited way, and making them available for external use may theoretically be as simple as testing to make sure they're still up-to-date and adding a py.typed
file to the Cython package.
More context about type hints in Cython can be found here and here.
Mypy is also planning on overhauling how imports are handled so you can optionally use any bundled type hints even if the package isn't PEP 561 compliant during the next few months -- you could also wait for that to happen.
Create your own stubs package for cython. This package can be incomplete and define only int
and a few other things you need. For example, you could create a "stubs/cython.pyi" file that looks like this:
from typing import Any
def __getattr__(name: str) -> Any: ...
def __setattr__(name: str, value: Any) -> None: ...
class _int:
Then, point mypy at this stub file in addition to your usual code. Mypy will then understand that it should use this stub file to serve as type hints for the cython
module. This means that when you do cython.int
, mypy will see that it's the class you defined up above and so will have enough information to know that Flags = cython.int
is likely a type alias.
Redefine what Flags
is assigned when performing type checking only. You can do this via the typing.TYPE_CHECKING
variable:
from typing import TYPE_CHECKING
import cython
if TYPE_CHECKING:
Flags = int
else:
Flags = cython.int
def difference(f1: Flags, f2: Flags):
return bin(f1 ^ f2).count("1")
One caveat to this approach is that I'm not sure to what degree Cython supports these sorts of PEP 484 tricks and whether it'll recognize that Flags
is meant to be a type alias if it's wrapped in an if statement like this.
Instead of making Flags
a type alias for cython.int
, make it a subclass:
import cython
class Flags(cython.int): pass
def foo(a: Flags, b: Flags) -> Flags:
return a ^ b
Now, you're using cython.int
back in a context where it's reasonable to assume it's a type, and mypy ends up not reporting an error.
Granted, this does change the semantics of your program and may also make Cython unhappy -- I'm not really familiar with how Cython works, but I suspect you're not really meant to subclass cython.int
.