Description
Hey all,
I'm adding OS-specific typechecking to a large Python app, and we have a fair number of files and functions that mix OS versions. Currently, mypy only does limited analysis with platform/version/constants to figure out which lines it shouldn't check. With that limited analysis, it's possible to add OS-specific typechecking to the app, but it'll make the code a bit messier.
I'd like to get your feedback on two ideas that would make adding OS-specific typechecking easier.
- For
if
statements where the expression is a mypy-constant, short-circuit if there's areturn
statement one-level deep in the body of theif
. (Currently, the inner bodies of the if are conditionally checked, andreturn
doesn't short-circuit checking.)
E.g.
# flags: --always-false=IS_WINDOWS
if IS_WINDOWS:
import win_specific_import
def some_fun_broken() -> int:
if not IS_WINDOWS:
return 1 # checked
# The rest of this function is analyzed even though we returned above.
# Blows up since `win_specific_import` isn't defined
return win_specific_import.something()
def some_fun_fixed() -> int:
if not IS_WINDOWS:
return 1 # checked
else:
# Not analyzed because this is in the `else` part of the `if` statement
return win_specific_import.something() # Works
We use the if not IS_WINDOWS: return
pattern a fair amount in our codebase, and it would be nice if mypy supported that.
I'm not sure how we'd implement that in mypy, though. Maybe we can scan for a return
one-level deep in if
statement bodies which have a mypy-constant expression and mark the rest of the function as unreachable.
- Make mypy-constant asserts also ignore function bodies. This would be an extension of Idea: allow assert with platform or version check at top of file #5308. E.g.
# flags: --always-false=IS_WINDOWS
if IS_WINDOWS:
import win_specific_import
def invalid_win_specific_function() -> bool:
assert IS_WINDOWS
return win_specific_import.some_func() # This blows up
if IS_WINDOWS:
def valid_win_specific_function() -> bool:
return win_specific_import.some_func()
It would be convenient if we ignored the rest of the function body if the first statement in it is a mypy-constant assert. I don't think we'd want to look for asserts elsewhere in the function block, though, even though that would make it a magical special-case.
Any thoughts on the above ideas?