How to catch potentially undefined variables with pylint or mypy?

174 Views Asked by At
import time

if time.time() > 42:
    x = 1

print(x)

My IDE (PyCharm) warns me about x potentially being undefined:

enter image description here

But pylint and mypy do not say anything. Is there a way to make one of them complain about this situation too?

2

There are 2 best solutions below

0
dROOOze On BEST ANSWER

mypy has partial* support via the error code [possibly-undefined], which you can enable through one of the following:

  • The CLI when running mypy (mypy <...> --enable-error-code possibly-undefined);

  • A mypy configuration file setting which looks like

    [mypy]
    enable_error_code = possibly-undefined
    
  • The file-level configuration comment line

    # mypy: enable-error-code=possibly-undefined
    

See a demonstration of your example in the mypy Playground.


*Partial, because mypy treats annotated assignment statements as an implicit declaration of existence; it won't catch this example:

import time

x: int  # Annotated assignment statement with no value set
if time.time() > 42:
    x = 1

print(x)  # No errors caught here

Note that, for all intents and purposes, this is good enough as full support. It's not possible for a type-checker to determine whether all execution paths can be met for (e.g.) independent conditional blocks; any more inference of [possibly-undefined] would result in a copious amount of false positives.

0
Marcin Orlowski On

While mypy seems not to report the potentially undefined variable, but would yield

C0103: Constant name "x" doesn't conform to UPPER_CASE naming style (invalid-name)

While not necessary on point, still better than nothing. Also note mypy is not really a linter you are looking for, but type checker.

Next, was pylint but it stays silent, despite presence of potentially relevant checker E0602 (UnboundLocalError). I somehow failed to change that behavior on your code.

Digging deeper I found this old ticket on mypy's repo Not detecting UnboundLocalError which, despite the age is interesting read. I checked tools mentioned there and pyright raised the alarm:

test.py:6:7 - error: "x" is possibly unbound (reportPossiblyUnboundVariable)