New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support conditional Python version and platform checks #698

Closed
JukkaL opened this Issue May 31, 2015 · 11 comments

Comments

Projects
None yet
6 participants
@JukkaL
Collaborator

JukkaL commented May 31, 2015

Mypy should support some common kinds of Python version checks and platform checks (e.g. Windows vs. Posix). We should ignore code paths that won't be run on the targeted Python version or platform. This way mypy can more effectively type check code that supports Python 2 and 3 and multiplatform code.

We first need to decide which checks to support. These examples are from PEP 484 and should be supported:

import sys

if sys.version_info[0] >= 3:
    # Python 3 specific definitions
    ...
else:
    # Python 2 specific definitions
    ...

if sys.platform == 'win32':
    # Windows specific definitions
    ...
else:
    # Posix specific definitions
    ...

When type checking code as above, always only if or the else block would be analyzed, never both, since on any given program run only one them can be evaluated (we assume that nobody does anything crazy like modifying sys.platform at runtime). We'd detect the check expressions during semantic analysis and wouldn't semantically analyze (or type check) the skipped blocks, similar to how mypy currently deals with PY2/PY3 conditions in if statements.

We already have Python 2 and Python 3 modes, and we should also implement Windows and non-Windows (Posix) modes. Initially, we can just use the platform on which the type checker is being run, but more generally this should be configurable (e.g., mypy --platform win32 ...).

@JukkaL

This comment has been minimized.

Show comment
Hide comment
@JukkaL

JukkaL May 31, 2015

Collaborator

We should also support code that assigns the result of a check to a variable. Example:

import sys

PY3_OR_LATER = sys.version_info[0] >= 3

if PY3_OR_LATER:
    ...
else:
    ...
Collaborator

JukkaL commented May 31, 2015

We should also support code that assigns the result of a check to a variable. Example:

import sys

PY3_OR_LATER = sys.version_info[0] >= 3

if PY3_OR_LATER:
    ...
else:
    ...
@methane

This comment has been minimized.

Show comment
Hide comment
@methane

methane May 18, 2016

Member

How about type comment?

def quote(s):
    # if PY2:
    #     type: (AnyStr) -> AnyStr
    # else:
    #     type: (str) -> str
    return '"' + s + '"'

or

def quote(s):
    if PY2:
        # type: (AnyStr) -> AnyStr
        ...
    else:
        # type: (str) -> str
        ...
    return '"' + s + '"'
Member

methane commented May 18, 2016

How about type comment?

def quote(s):
    # if PY2:
    #     type: (AnyStr) -> AnyStr
    # else:
    #     type: (str) -> str
    return '"' + s + '"'

or

def quote(s):
    if PY2:
        # type: (AnyStr) -> AnyStr
        ...
    else:
        # type: (str) -> str
        ...
    return '"' + s + '"'
@gvanrossum

This comment has been minimized.

Show comment
Hide comment
@gvanrossum

gvanrossum May 18, 2016

Member

Please no new proposals.

Member

gvanrossum commented May 18, 2016

Please no new proposals.

@rwbarton

This comment has been minimized.

Show comment
Hide comment
@rwbarton

rwbarton May 18, 2016

Contributor

Cases like the one above could be handled already by defining a type variable or synonym MyStr conditionally on the python version and then declaring the type of quote to be (MyStr) -> MyStr.

Contributor

rwbarton commented May 18, 2016

Cases like the one above could be handled already by defining a type variable or synonym MyStr conditionally on the python version and then declaring the type of quote to be (MyStr) -> MyStr.

@methane

This comment has been minimized.

Show comment
Hide comment
@methane

methane May 18, 2016

Member

I'm sorry, and thanks for information.

Member

methane commented May 18, 2016

I'm sorry, and thanks for information.

@gvanrossum

This comment has been minimized.

Show comment
Hide comment
@gvanrossum

gvanrossum Jul 5, 2016

Member

Note that different versions may have different signatures for the same function. This should definitely be supported.

Member

gvanrossum commented Jul 5, 2016

Note that different versions may have different signatures for the same function. This should definitely be supported.

@gvanrossum

This comment has been minimized.

Show comment
Hide comment
@gvanrossum

gvanrossum Jul 26, 2016

Member

My plan:

  • implement straight checks for sys.version_info in a conditional expression
  • ditto for sys.platform, using the current platform
  • add a command-line flag to override the default platform
  • understand variables used as aliases for platform checks

I may need help with the last item, and maybe we should update PEP 484 to clarify what's allowed.

Member

gvanrossum commented Jul 26, 2016

My plan:

  • implement straight checks for sys.version_info in a conditional expression
  • ditto for sys.platform, using the current platform
  • add a command-line flag to override the default platform
  • understand variables used as aliases for platform checks

I may need help with the last item, and maybe we should update PEP 484 to clarify what's allowed.

@JukkaL

This comment has been minimized.

Show comment
Hide comment
@JukkaL

JukkaL Jul 26, 2016

Collaborator

Here are some thoughts:

  • Aliases can be a little tricky, as we currently don't process any aliases during the first semantic analysis pass -- and we'd probably want to process version checks during the first pass. A potential approach is to special case the detection of these aliases during the first pass, and ignore assignment statements that don't look like aliases that we are going to support.
  • As imports aren't fully processed during the first pass, you may want to just add some special cased imported values to the symbol table during the pass -- even having a special, temporary symbol table just for conditional definitions might not be terrible. For example, shallow process import sys and from sys import platform during the first pass without actually looking at the sys stub file, but skip other imports.
  • Importing conditional flags from other modules may also be a little tricky (for example, from myappconfig import PY3 or similar). Perhaps we don't need to support these initially.
  • Simple Python version checks without aliases are probably the most important use case (for python 2 and 3 compatible stubs), and focusing on this first seems reasonable.
Collaborator

JukkaL commented Jul 26, 2016

Here are some thoughts:

  • Aliases can be a little tricky, as we currently don't process any aliases during the first semantic analysis pass -- and we'd probably want to process version checks during the first pass. A potential approach is to special case the detection of these aliases during the first pass, and ignore assignment statements that don't look like aliases that we are going to support.
  • As imports aren't fully processed during the first pass, you may want to just add some special cased imported values to the symbol table during the pass -- even having a special, temporary symbol table just for conditional definitions might not be terrible. For example, shallow process import sys and from sys import platform during the first pass without actually looking at the sys stub file, but skip other imports.
  • Importing conditional flags from other modules may also be a little tricky (for example, from myappconfig import PY3 or similar). Perhaps we don't need to support these initially.
  • Simple Python version checks without aliases are probably the most important use case (for python 2 and 3 compatible stubs), and focusing on this first seems reasonable.
@gvanrossum

This comment has been minimized.

Show comment
Hide comment
@gvanrossum

gvanrossum Jul 26, 2016

Member
Member

gvanrossum commented Jul 26, 2016

@JukkaL

This comment has been minimized.

Show comment
Hide comment
@JukkaL

JukkaL Jul 26, 2016

Collaborator

There's visit_tuple_slice_helper in checkexpr.py which might be relevant.

Collaborator

JukkaL commented Jul 26, 2016

There's visit_tuple_slice_helper in checkexpr.py which might be relevant.

@gvanrossum

This comment has been minimized.

Show comment
Hide comment
@gvanrossum

gvanrossum Aug 5, 2016

Member

I did the first two bullets of my plan, and filed separate issues for the last two (the last one I think we may not actually need). So I'm closing this.

Member

gvanrossum commented Aug 5, 2016

I did the first two bullets of my plan, and filed separate issues for the last two (the last one I think we may not actually need). So I'm closing this.

@gvanrossum gvanrossum closed this Aug 5, 2016

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