Static code analyzers for Python do not generate branches in the following case (one-liner if). Is this by design? Even coverage
gives 100% coverage even if only one case is tested.
x = 1 if q == 0 else 10
Can anyone please shed some light on this?
Advertisement
Answer
The first comment says “does not create a control structure.” I don’t know what that means. Whether it’s one line or many lines, the compiled byte code is nearly the same:
>>> import dis >>> def one_line(): ... x = 1 if q == 0 else 10 ... >>> dis.dis(one_line) 2 0 LOAD_GLOBAL 0 (q) 2 LOAD_CONST 1 (0) 4 COMPARE_OP 2 (==) 6 POP_JUMP_IF_FALSE 12 8 LOAD_CONST 2 (1) 10 JUMP_FORWARD 2 (to 14) >> 12 LOAD_CONST 3 (10) >> 14 STORE_FAST 0 (x) 16 LOAD_CONST 0 (None) 18 RETURN_VALUE >>> def multi_line(): ... if q == 0: ... x = 1 ... else: ... x = 10 ... >>> dis.dis(multi_line) 2 0 LOAD_GLOBAL 0 (q) 2 LOAD_CONST 1 (0) 4 COMPARE_OP 2 (==) 6 POP_JUMP_IF_FALSE 14 3 8 LOAD_CONST 2 (1) 10 STORE_FAST 0 (x) 12 JUMP_FORWARD 4 (to 18) 5 >> 14 LOAD_CONST 3 (10) 16 STORE_FAST 0 (x) >> 18 LOAD_CONST 0 (None) 20 RETURN_VALUE >>>
The reason coverage.py can’t tell you about the one-line case is because of the trace function that Python uses to tell coverage.py what is going on. The trace function is called for each line executed. The trace function doesn’t get events within a line.
A fuller discussion of possible ways to improve this is here: https://github.com/nedbat/coveragepy/issues/509