Some files only work for certain platforms, but sometimes it's inconvenient to move the file to a location where it'll only be picked up for that platform. And yet the file doesn't type check cleanly on another platform (or ditto for Python versions).
We could enclose the entire file in if sys.platform == 'win32': but that seems overkill (and adding the indentation makes for an awkward diff). I propose an alternative that would have the same effect: assert sys.platform == 'win32'.
Another (minor) problem with the approach of enclosing the entire file in if ...: is that mypy won't flag imports of the file, only attempts to use names from it. In other words, if we're using the if ...: approach and I'm not on Windows, I would not get an error for import only_on_windows, but only for only_on_windows.some_function(). This could be confusing for users.
I think giving an error when mypy finds a reachable assert False is going to cause a lot of false positives. And detecting sequences of if-elif-elif-else where all tests are sys.platform checks seems complicated and not worth it.
Anyway, I just rechecked our original use case, and there we would actually want mypy to be silent if it finds a file containing assert sys.platform == 'win32' and the platform isn't 'win32'. The reason is that we statically compute a list of files to pass to mypy, and this file is always in it (the static computation is way too stupid to understand sys.platform checks). And on a non-win32 platform the contents of the file won't type-check at all (it imports other win32-specific modules, but since it is itself a win32-specific module, it doesn't wrap those in sys.platform checks). And the code that imports the module is inside a sys.platform check. And finally we don't want to edit the file to indent everything by an extra level and inserting a sys.platform check at the top, but we're fine adding a single assert at the top.
So really all I want is for mypy to silently ignore the rest of a file when it encounters a top-level assert with a sys.platform check in it.
lol.py:8: error: Revealed type is 'Any'
lol.py:8: error: Name 'f' is not defined
I don't mean giving an error on assert False, I mean suppressing the f not defined error (by not checking it).
This is prompted by a request from an internal user trying to run mypy on multiple platforms with some code that looks like what I had above.
But if supporting it directly is a pain we can easily require adding a toplevel assert, if we implement that.
Would it be really lame if I implemented this only if the assert occurs at the top level in a file, without any indentation (i.e. not inside e.g. if, and certainly not inside a function)?
Would it be really lame if I implemented this only if the assert occurs at the top level in a file, without any indentation
If that would be much easier implement than supporting this everywhere, I don' think that it would very lame. We'd just need to document it as a very specific feature -- ignoring the whole file (or anything after the assert) on some platform(s).
Activity
JelleZijlstra commented on Jul 3, 2018
I like it.
Another (minor) problem with the approach of enclosing the entire file in if ...: is that mypy won't flag imports of the file, only attempts to use names from it. In other words, if we're using the if ...: approach and I'm not on Windows, I would not get an error for import only_on_windows, but only for only_on_windows.some_function(). This could be confusing for users.
msullivan commented on Jul 5, 2018
I think this is a good idea.
We also probably want to support this related idiom:
if sys.platform == 'linux': # stuff elif sys.platform == 'darwin': # other stuff else: assert False, "unsupported"emmatyping commented on Jul 5, 2018
@msullivan We already support platform checks. So if I run this:
import sys if sys.platform == 'darwin': def f() -> str: return '' else: assert False, "unsupported" reveal_type(f)on Linux, I get f is Any, as the name is not defined on Linux/Windows. Are you suggesting that there be an error on the line with assert False?
gvanrossum commented on Jul 6, 2018
I think giving an error when mypy finds a reachable assert False is going to cause a lot of false positives. And detecting sequences of if-elif-elif-else where all tests are sys.platform checks seems complicated and not worth it.
Anyway, I just rechecked our original use case, and there we would actually want mypy to be silent if it finds a file containing assert sys.platform == 'win32' and the platform isn't 'win32'. The reason is that we statically compute a list of files to pass to mypy, and this file is always in it (the static computation is way too stupid to understand sys.platform checks). And on a non-win32 platform the contents of the file won't type-check at all (it imports other win32-specific modules, but since it is itself a win32-specific module, it doesn't wrap those in sys.platform checks). And the code that imports the module is inside a sys.platform check. And finally we don't want to edit the file to indent everything by an extra level and inserting a sys.platform check at the top, but we're fine adding a single assert at the top.
So really all I want is for mypy to silently ignore the rest of a file when it encounters a top-level assert with a sys.platform check in it.
msullivan commented on Jul 6, 2018
@ethanhs When I check that, I get:
I don't mean giving an error on assert False, I mean suppressing the f not defined error (by not checking it).
This is prompted by a request from an internal user trying to run mypy on multiple platforms with some code that looks like what I had above.
But if supporting it directly is a pain we can easily require adding a toplevel assert, if we implement that.
JukkaL commented on Jul 6, 2018
I like the top-level assert idea. It looks like this is something we should prioritize?
gvanrossum commented on Jul 6, 2018
ilevkivskyi commented on Nov 14, 2018
This keeps coming, so I am raising priority to high.
gvanrossum commented on Nov 14, 2018
To be clear, the implementation we're looking for is
gvanrossum commented on Nov 14, 2018
Would it be really lame if I implemented this only if the assert occurs at the top level in a file, without any indentation (i.e. not inside e.g. if, and certainly not inside a function)?
JukkaL commented on Nov 14, 2018
If that would be much easier implement than supporting this everywhere, I don' think that it would very lame. We'd just need to document it as a very specific feature -- ignoring the whole file (or anything after the assert) on some platform(s).
gvanrossum commented on Nov 14, 2018
I think it would be much easier. In semanal_pass1.py we can just truncate the list of defs when we encounter such an assert.
Skip rest of file upon top-level always-false assert
Skip rest of file upon top-level always-false assert (#5894)
ofek commented on May 1, 2025
What do we think about this? #19013