2

https://github.com/asottile/pyupgrade/blob/fecacc91e57c224a0bd2564579ef01238650126c/pyupgrade.py#L53

if False:  # pragma: no cover (mypy)
    from typing import Type
    if sys.version_info >= (3,):
        AsyncFunctionDef = ast.AsyncFunctionDef
    else:
        AsyncFunctionDef = ast.stmt

The commit is not revealing: https://github.com/asottile/pyupgrade/commit/fecacc91e57c224a0bd2564579ef01238650126c#diff-8213eba6a28bcc759225cd8cf49b2fd1

False can be truthy in Python 2 (where it can be re-defined) but not in Python 3. It might be a joke, or work in progress, or way of commenting out the code, but this is quite a mature tool- am I missing something?

anthony sottile
  • 61,815
  • 15
  • 148
  • 207
Chris_Rands
  • 38,994
  • 14
  • 83
  • 119

2 Answers2

5

The value of AsyncFunctionDef is never needed at runtime, only by mypy in two Python-2-compatible type hints (at lines 1298 and 1318). The if False prevents the assignments from occurring at run-time, but lets mypy see the correct underlying type to use during type-checking. (It also prevents an ImportError from being raised at the attempt to import the typing module under Python 2.)

It would be clearer to use typing.TYPE_CHECKING (whose value is False at run-time, but True when mypy runs) here, except typing.TYPE_CHECKING is also unavailable in Python 2.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • Thanks! I'm not very familar with `mypy`, I can see they recommend using `MYPY = False` where `TYPE_CHECKING` is not available https://mypy.readthedocs.io/en/latest/common_issues.html so `mypy` considers `False` to be truthy when type checking? – Chris_Rands Jan 06 '20 at 16:05
  • `MYPY = False` ensures that when the code is actually executed, you'll skip things guarded by `if MYPY:...`. When `mypy` runs, it *interprets* certain conditionals without actually *evaluating* the Python code. The name `MYPY` is special-cased to be *assumed* `True`, regardless of its actual value. – chepner Jan 06 '20 at 16:10
  • Sorry, are you saying that the `MYPY` variable has a special meaning to `mypy`? If yes, why is `if False:` type checked? Or are you saying that `mypy` type checks every line regardless of whether it's executed at runtime – Chris_Rands Jan 06 '20 at 16:16
  • Yes, `mypy` type-checks all code; it doesn't make any assumptions about run-time semantics like "will this condition be true", precisely *because* it needs to follow imports that may or may not be reached at run-time. – chepner Jan 06 '20 at 16:22
5

if False is used over if typing.TYPE_CHECKING because python3.5.0-3.5.2 is supported by pyupgrade and does not have typing.TYPE_CHECKING -- you can find more information in flake8-typing-imports (I'm also the author of this flake8 plugin)

in 3.5.3+ and the typing backport (available in anything <3.5) TYPE_CHECKING is available

disclaimer: I'm the author of pyupgrade

anthony sottile
  • 61,815
  • 15
  • 148
  • 207