"raise" followed by a conditional expression (python)
I am trying to understand the python 2.5 code and I came across this pattern:
def __init__(self, matrix, top_buttons, side_buttons, config_button): raise isinstance(matrix, ButtonMatrixElement) or AssertionError raise matrix.width() == 8 and matrix.height() == 8 or AssertionError raise isinstance(top_buttons, tuple) or AssertionError raise len(top_buttons) == 8 or AssertionError raise isinstance(side_buttons, tuple) or AssertionError raise len(side_buttons) == 8 or AssertionError raise isinstance(config_button, ButtonElement) or AssertionError
I tried to test this in the shell with some simple conditional statements like:
'hello' > raise len(str) == 5 or AssertionError Traceback (most recent call last): File "<pyshell#6>", line 1, in <module> raise len(str) == 5 or AssertionError TypeError: exceptions must be classes, instances, or strings (deprecated), not bool> str =
So, judging from this test, at least the way I tried it, you cannot raise a boolean assertion. What does it mean to raise a conditional expression and why does it work in a function
but not in my test code?
source to share
The code is silly, a failed attempt at something that looks like a
statement that doesn't work as you discovered.
What they should have written:
assert isinstance(matrix, ButtonMatrixElement)
It looks like you discovered decompiled Ableton Live scripts , but the decompiled script caused the wrong Python code. The bytecode for
looks like this (Python 2.5 bytecode):
import dis dis.dis(compile('''assert isinstance(matrix, ButtonMatrixElement)''', '<stdin>', 'exec')) 1 0 LOAD_NAME 0 (isinstance) 3 LOAD_NAME 1 (matrix) 6 LOAD_NAME 2 (ButtonMatrixElement) 9 CALL_FUNCTION 2 12 JUMP_IF_TRUE 7 (to 22) 15 POP_TOP 16 LOAD_GLOBAL 3 (AssertionError) 19 RAISE_VARARGS 1 >> 22 POP_TOP 23 LOAD_CONST 0 (None) 26 RETURN_VALUE
and it looks like some kind of automatic process was used to decompile the bytecode translated into the code you see, rather than recognize it as
Note that if the call
, the branch instruction (index 12,
) jumps past the instruction
, but the rebuilt code does not. Compare this to the actual statement
raise ... or ...
, you will notice that the jump does not pass by
'raise foo or bar', '<stdin>', 'exec')) 1 0 LOAD_NAME 0 (foo) 3 JUMP_IF_TRUE 4 (to 10) 6 POP_TOP 7 LOAD_NAME 1 (bar) 10 RAISE_VARARGS 1 13 LOAD_CONST 0 (None) 16 RETURN_VALUE> dis.dis(compile(
Presumably the code generator was just not hard to handle; if you assume you are only
and not handling offsets as expected, you can see how the error was made.
source to share
As stated earlier, this is a bug in the decompiler that was used in the python-based bytecode reverse engineering process. If you want to decompile the files yourself, you can use the following version of the script:
The above error should be fixed. When you decompile
with this version, you get:
class MainSelectorComponent(ModeSelectorComponent): """ Class that reassigns the button on the launchpad to different functions """ def __init__(self, matrix, top_buttons, side_buttons, config_button): assert isinstance(matrix, ButtonMatrixElement) assert matrix.width() == 8 and matrix.height() == 8 assert isinstance(top_buttons, tuple) assert len(top_buttons) == 8 assert isinstance(side_buttons, tuple) assert len(side_buttons) == 8 assert isinstance(config_button, ButtonElement)
source to share