I like the principle of making the if TYPE_CHECKING:
pattern cleaner, but I wonder if type checking could be one case of a more general pattern? It’s often recommended to use a multi-valued option rather than a boolean, so that the situations an option covers can be expanded over time.
If we had something like __mode__
, we could use it to check for other modes of operation in addition to type checking. For example, I often think it would be nice to be able to include unit tests alongside the functions they cover, rather than in a separate module. I could imagine doing that with some kind of __mode__
enabled when pytest is running:
def plural(singular_word: str, plural_word: str | None = None, *, count: int) -> str:
"""Get a plural or singular version of a word to describe `count`."""
return singular_word if count == 1 else (plural_word or f"{singular_word}s")
if "pytest" in __mode__:
def test_plural() -> None:
assert plural("example", count=1) == "example"
assert plural("example", count=2) == "examples"
assert plural("sheep", "sheep", count=2) == "sheep"
assert plural("affix", "affixes", count=2) == "affixes"
If the interpreter was able to cheaply throw out the test block (or perhaps even strip it out at package-install time?) I wouldn’t feel bad about bloating a runtime module.
This is similar to the if __name__ == "main":
pattern, but I’m imagining multiple modes could be enabled at once.
And for type checking, this could be something like:
if "typechecking" in __mode__:
from typing_extensions import assert_type as assert_type
else:
def assert_type(val: _T, typ: Any, /) -> _T:
return val
What else could a mode be used for? Perhaps other expensive things done at runtime, like @dataclass()
or enum definition as @steve.dower mentions above? e.g. if a module could handle pre-processing a __mode__
conditional block before runtime (e.g. at install or build time?), it could substitute a regular class definition for a dataclass or enum.