It's difficult not to emit false positives in the general case. Imagine this code:
if list_empty or x in my_list:
this is perfectly valid to any human because list_empty
is probably a boolean. Now with:
if number1 or number2 in my_list:
A (woken up :)) human sees the error immediately (because the names are similar, and usually identify numbers not conditions, same for strings with if name1 or name2 in my_list:
), but that would require the static analyser to know the type for sure.
And even in those "trivial" cases, who knows if the programmer didn't want to test if number1
is zero or name1
is empty to proceed to the next test?
Type annotations may help, I didn't test all tools out there to give you a positive answer but the dynamic nature of python makes it very difficult to be sure of the intent of the programmer, and what's worth an analyser program with emits a ton of false positives?
For string & integer/float literals this construct is probably a mistake, so I wrote a lousy static analyzer with regexes. Cheap and if it yells, you're very likely with a faulty line (standalone example here which self-analyses itself):
dt=[]
if 'char' or 'CHAR' in dt:
foo = 'ch'
if 12.0 and 45 in dt:
foo = 'ch'
import re
infamous_bug = re.compile("if\s+(['\"].*?['\"]|[\d\.]+)\s+(or|and)")
with open(__file__) as f:
for line in f:
if infamous_bug.search(line):
print("GOTCHA {}".format(line.rstrip()))
outputs:
GOTCHA if 'char' or 'CHAR' in dt:
GOTCHA if 12.0 and 45 in dt: