Skip to content
R. Bernstein edited this page Aug 22, 2019 · 5 revisions

See https://github.com/rocky/python-uncompyle6/issues/283

Step 1: Create test case and reproduce the problem

The first step is to create a little test case.

Ths was one in the issue:

G = ( c for c in "spam, Spam, SPAM!" if c > 'A' and c < 'S')

I used pyenv to get me to Python 2.6.9. And produced a byte compiled file:

$ pyenv local 2.6.9
$ ./test/stdlib/compile-file.py  /tmp/bug.py
compiling /tmp/bug.py to /tmp/bug-2.6.pyc

Now run:

$ ./bin/ucompyle /tmp/bug-2.6.pyc
...
Parse error at or near `None' instruction at offset -1
$ 

Ok I can reproduce the problem The offset -1 means that basically there is no code before we hit an error. When this happens, sometimes could can add a valid statement before it and that will often produce an offset that is more easily tracked. However here the error is inside the generator: ( c for c in "spam, Spam, SPAM!" if c > 'A' and c < 'S') so this can't easily be done.

Step 2: See if there if a neighboring version that doesn't have the problem

It so happens that this bug doesn't appear in Python 2.7:

$ pyenv local 2.7.16
$ ./test/stdlib/compile-file.py  /tmp/bug.py
compiling /tmp/bug.py to /tmp/bug-2.7.pyc
$ ./bin/ucompyle /tmp/bug-2.7.pyc
...
G = (c for c in 'spam, Spam, SPAM!' if c > 'A' and c < 'S')
# okay decompiling /tmp/bug-2.7.pyc

Great! We now have a way to hone in on the parser error.

Step 3: Compare working and non-working with debug output

Now that we have two examples one that works in uncompyle6 and one that doesn't we can get debug output and see where things go awry. The options I often use are -agT:

$ ./bin/uncompyle6  -agT /tmp/bug-2.7.pyc > /tmp/bug-good.log
$ ./bin/uncompyle6  -agT /tmp/bug-2.6.pyc > /tmp/bug-bad.log 2>&1
Clone this wiki locally