python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.23k stars 2.79k forks source link

(🎁) Allow if expression / conditional base in class def #12445

Open KotlinIsland opened 2 years ago

KotlinIsland commented 2 years ago

I have some proxy objects and it's difficult to type them, I want to lie to mypy what the bases are

from typing import TYPE_CHECKING

class A: ...
class B: ...
class C(A if TYPE_CHECKING else B): ...  # error: Invalid base class  [misc]
hauntsaninja commented 2 years ago

Note that this works if you don't use ternary, e.g. I often do something like:

if TYPE_CHECKING:
    AnyBaseClass = Any
else:
    AnyBaseClass = object

class A(AnyBaseClass): ...
intgr commented 5 months ago

I want to make a type argument conditional on TYPE_CHECKING, because the upstream library used does not support a __class_getitem__ for this particular class -- only type stubs do.

@hauntsaninja's work-around doesn't work for this case. Is there another work-around for this pattern?

class NestedHyperlinkedRelatedField(HyperlinkedRelatedField[T_Model] if TYPE_CHECKING else HyperlinkedRelatedField):
    def get_foo(self) -> T_Model:
        ...
JelleZijlstra commented 5 months ago

It's not pretty but you can duplicate the whole class in the two branches of an if TYPE_CHECKING block.

JelleZijlstra commented 5 months ago

If someone is interested in fixing this, I imagine it's probably not too hard; it would likely require finding the code in or near semanal.py that handles ternaries and adding support for TYPE_CHECKING there.

hauntsaninja commented 5 months ago

The last example in https://mypy.readthedocs.io/en/stable/runtime_troubles.html#using-classes-that-are-generic-in-stubs-but-not-at-runtime could be useful. But a patch would be very welcome, feel free to tag me if you open a PR.