rocky / python-uncompyle6

A cross-version Python bytecode decompiler
GNU General Public License v3.0
3.74k stars 408 forks source link

Incorrect decompilation of genexpr with `if isinstance` #479

Closed landaire closed 10 months ago

landaire commented 10 months ago

Description

Building a map using a generator that specifies if isintance(var, int) results in the if condition being present twice in decompiled output.

How to Reproduce

Download the testcase.zip and run:

$ uncompyle6 genexpr.pyc

This testcase was compiled from the following source code:

class Foo:
    FIELD = 0
    FIELD2 = 1

SOME_VALUE = {value: key for (key, value) in Foo.__dict__.iteritems() if isinstance(value, int)}

Using the following command:

$ python2.7 -m py_compile genexpr.py

Output Given

# uncompyle6 version 3.8.0
# Python bytecode 2.7 (62211)
# Decompiled from: Python 2.7.18 (default, Sep 28 2022, 20:52:16)
# [GCC Apple LLVM 14.0.0 (clang-1400.0.29.102)]
# Warning: this version of Python has problems handling the Python 3 byte type in constants properly.

# Embedded file name: genexpr.py
# Compiled at: 2023-11-11 16:00:43

class Foo:
    FIELD = 0
    FIELD2 = 1

SOME_VALUE = {value:key for key, value in Foo.__dict__.iteritems() if isinstance(value, int) if isinstance(value, int)}
# okay decompiling ./genexpr.pyc

Expected behavior

The output code should be:

# uncompyle6 version 3.8.0
# Python bytecode 2.7 (62211)
# Decompiled from: Python 2.7.18 (default, Sep 28 2022, 20:52:16)
# [GCC Apple LLVM 14.0.0 (clang-1400.0.29.102)]
# Warning: this version of Python has problems handling the Python 3 byte type in constants properly.

# Embedded file name: genexpr.py
# Compiled at: 2023-11-11 16:00:43

class Foo:
    FIELD = 0
    FIELD2 = 1

SOME_VALUE = {value:key for key, value in Foo.__dict__.iteritems() if isinstance(value, int)}
# okay decompiling ./genexpr.pyc
rocky commented 10 months ago

I get the correct output. Try using the master branch version in github.