Skip to content

Idea: allow assert with platform or version check at top of file #5308

Description

@gvanrossum

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'.

Activity

  1. JelleZijlstra commented on Jul 3, 2018

    @JelleZijlstra
    Member

    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.

  2. msullivan commented on Jul 5, 2018

    @msullivan
    Collaborator

    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"
    
  3. emmatyping commented on Jul 5, 2018

    @emmatyping
    Member

    @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?

  4. gvanrossum commented on Jul 6, 2018

    @gvanrossum
    MemberAuthor

    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.

  5. msullivan commented on Jul 6, 2018

    @msullivan
    Collaborator

    @ethanhs When I check that, I get:

    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.

  6. JukkaL commented on Jul 6, 2018

    @JukkaL
    Collaborator

    I like the top-level assert idea. It looks like this is something we should prioritize?

  7. gvanrossum commented on Jul 6, 2018

    @gvanrossum
    MemberAuthor
  8. ilevkivskyi commented on Nov 14, 2018

    @ilevkivskyi
    Member

    This keeps coming, so I am raising priority to high.

  9. gvanrossum commented on Nov 14, 2018

    @gvanrossum
    MemberAuthor

    To be clear, the implementation we're looking for is

    for mypy to silently ignore the rest of a file when it encounters a top-level assert with a [non-matching] sys.platform check in it

  10. self-assigned this
    on Nov 14, 2018
  11. gvanrossum commented on Nov 14, 2018

    @gvanrossum
    MemberAuthor

    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)?

  12. JukkaL commented on Nov 14, 2018

    @JukkaL
    Collaborator

    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).

  13. gvanrossum commented on Nov 14, 2018

    @gvanrossum
    MemberAuthor

    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.

  14. added a commit that references this issue on Nov 14, 2018
    58546b7
  15. added a commit that references this issue on Nov 15, 2018
    79dc1f0
  16. ofek commented on May 1, 2025

    @ofek
    Sponsor

    What do we think about this? #19013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions