"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:

>>> str = '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

      

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 __init__

but not in my test code?

+3


source to share


2 answers


The code is silly, a failed attempt at something that looks like a assert

statement
that doesn't work as you discovered.

What they should have written:

assert isinstance(matrix, ButtonMatrixElement)

      

etc.

It looks like you discovered decompiled Ableton Live scripts , but the decompiled script caused the wrong Python code. The bytecode for assert

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 assert

.

Note that if the call isinstance()

returns True

, the branch instruction (index 12, JUMP_IF_TRUE

) jumps past the instruction RAISE_VARARGS

, 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

:

>>> dis.dis(compile('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        

      

Presumably the code generator was just not hard to handle; if you assume you are only or

generating JUMP_IF_TRUE

and not handling offsets as expected, you can see how the error was made.

+8


source


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:

https://github.com/frankebersoll/uncompyle2



The above error should be fixed. When you decompile MainSelectorComponent.pyc

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)

      

+2


source







All Articles