From d8598f61e4b27b26b2e76ca3f0438250f0d5506e Mon Sep 17 00:00:00 2001 From: rocky Date: Sat, 13 Aug 2016 07:08:48 -0400 Subject: [PATCH] Start handling Python 2.2 bytecode and... Fix some bugs in Python 2.3-2.5 bytecode handling --- README.rst | 4 ++-- test/bytecode_2.2/00_assign.pyc | Bin 0 -> 195 bytes test/bytecode_2.2/00_import.pyc | Bin 0 -> 213 bytes test/bytecode_2.2/00_pass.pyc | Bin 0 -> 106 bytes test/bytecode_2.2/03_class_method.pyc | Bin 0 -> 570 bytes test/bytecode_2.3/00_import.pyc | Bin 191 -> 211 bytes uncompyle6/parser.py | 11 ++++++---- uncompyle6/parsers/parse22.py | 30 ++++++++++++++++++++++++++ uncompyle6/scanner.py | 2 +- uncompyle6/scanners/scanner22.py | 27 +++++++++++++++++++++++ uncompyle6/scanners/scanner23.py | 6 ++++-- uncompyle6/scanners/scanner24.py | 2 ++ uncompyle6/scanners/scanner25.py | 2 ++ uncompyle6/semantics/pysource.py | 8 +++---- 14 files changed, 79 insertions(+), 13 deletions(-) create mode 100644 test/bytecode_2.2/00_assign.pyc create mode 100644 test/bytecode_2.2/00_import.pyc create mode 100644 test/bytecode_2.2/00_pass.pyc create mode 100644 test/bytecode_2.2/03_class_method.pyc create mode 100644 uncompyle6/parsers/parse22.py create mode 100644 uncompyle6/scanners/scanner22.py diff --git a/README.rst b/README.rst index b0a6f19a..502e9a0e 100644 --- a/README.rst +++ b/README.rst @@ -11,7 +11,7 @@ Introduction ------------ *uncompyle6* translates Python bytecode back into equivalent Python -source code. It accepts bytecodes from Python version 2.3 to 3.6 or +source code. It accepts bytecodes from Python version 2.2 to 3.6 or so, including PyPy bytecode. Why this? @@ -45,7 +45,7 @@ Requirements This project requires Python 2.6 or later, PyPy 3-2.4, or PyPy-5.0.1. The bytecode files it can read has been tested on Python bytecodes from -versions 2.3-2.7, and 3.2-3.6 and the above-mentioned PyPy versions. +versions 2.2-2.7, and 3.2-3.6 and the above-mentioned PyPy versions. Installation ------------ diff --git a/test/bytecode_2.2/00_assign.pyc b/test/bytecode_2.2/00_assign.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd63a6ead9d5788c2b5eeb04ab874f3ea1fe37e9 GIT binary patch literal 195 zcmdOW%gZHXSrL}Z00fLcT&x5n>Vb%bA%%e<3dmq(NM&S*Vq&OgV@Lrqm>E)-7=ksJ zL26lmgkOGMYNieokf8zM7K02)gv)@rNnkP=q6Z=mB4NTnCW8iuC{_RwnYjfysqw}6 mrA5i9`o$%=CB^y%2Jwl-#hK}OdIgnWv+P+Qmh&)jG6DdXTp?Ki literal 0 HcmV?d00001 diff --git a/test/bytecode_2.2/00_import.pyc b/test/bytecode_2.2/00_import.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bccadb0c52a93059100cf0313b85455f4f53274b GIT binary patch literal 213 zcmdOW%ga>~+ZdkA00c}xT&xQu>Vb%vA%%e9N zVFK|(fJ%Zjn1MR{G#EjeS%5@AVo3&s2NKc(OBaLG6jv4(gRICeMyLZ@36q5D1}b9E z01?FsAR;rjASX4xIKQ+gIaR;7B)6nk-@qUqD4JhXqE}E^46?_b8Dcv>qW~iShAk#) literal 0 HcmV?d00001 diff --git a/test/bytecode_2.2/00_pass.pyc b/test/bytecode_2.2/00_pass.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3df2c5a738d65bd368f98aac77c4f3e0cce6b55c GIT binary patch literal 106 zcmdOW%geQ$wK^=B0SFj@xR?t_)B_PSLka^!um(uXPXkCWpb^D#K(XS?+=86c_~QK1 hqU2Ql;*#8wVtoUH_=3dZV!eXOVvuHgW`<&rb^x*z6UhJo literal 0 HcmV?d00001 diff --git a/test/bytecode_2.2/03_class_method.pyc b/test/bytecode_2.2/03_class_method.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0304456719ac94b4c94fb26af0e994e7952a63b9 GIT binary patch literal 570 zcmb7B!AiqG5PiFCOj}dXlPAH0NG@8@5Afi@UhKgf#9o$?-C!hXijyh@AqV{zZ~mFT zAkJ(G7QARk9y9aa?3>vfe+~!lUmv$A`04OR`wR`g0W6RKR^bhJ1@5MtXe6aZOd(s=A2Br#4xbB^5+$6DPZjx%2X*Qyek4=QtNNgRu1Ilw77O|?_Y-+N zxguNFm_;l=hXQ%ID4d~c`Ix$qb=m0j+@!LzDP4VE*^|YJ#JtTy(14SU+EJ0(RgrG5 zs>d~B=Cjfn;|0c)m0j||W~14={=nb;H~vHblC}GK((buI{VuTZzpKjSU9gF?ego2- BagYE2 literal 0 HcmV?d00001 diff --git a/test/bytecode_2.3/00_import.pyc b/test/bytecode_2.3/00_import.pyc index 2915366342b9cd724a4e8157c08bef84a3aecc49..80b58aba80afcb114e4254cab2383195ee709dd8 100644 GIT binary patch delta 89 zcmdnbc$rb!`V%i#No-?yG6NJa0ci&yE>@fAJ$jb--xoizN delta 54 zcmcc2xSvtl`V%i#CR=q_G6NJa0ci&yE|!`oEyc>f5Ujy8(NTC}d=48(hLaHhAu + +from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG +from uncompyle6.parser import PythonParserSingle +from uncompyle6.parsers.parse23 import Python23Parser + +class Python22Parser(Python23Parser): + + def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG): + super(Python23Parser, self).__init__(debug_parser) + self.customized = {} + + def p_misc22(self, args): + ''' + stmt ::= SET_LINENO + _for ::= LOAD_CONST FOR_LOOP + ''' + +class Python22ParserSingle(Python23Parser, PythonParserSingle): + pass + +if __name__ == '__main__': + # Check grammar + p = Python22Parser() + p.checkGrammar() + p.dumpGrammar() + +# local variables: +# tab-width: 4 diff --git a/uncompyle6/scanner.py b/uncompyle6/scanner.py index 1a0d8758..3bec4eb2 100755 --- a/uncompyle6/scanner.py +++ b/uncompyle6/scanner.py @@ -22,7 +22,7 @@ from uncompyle6 import PYTHON3, IS_PYPY from uncompyle6.scanners.tok import Token # The byte code versions we support -PYTHON_VERSIONS = (2.3, 2.4, 2.5, 2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6) +PYTHON_VERSIONS = (2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6) # FIXME: DRY if PYTHON3: diff --git a/uncompyle6/scanners/scanner22.py b/uncompyle6/scanners/scanner22.py new file mode 100644 index 00000000..8c773036 --- /dev/null +++ b/uncompyle6/scanners/scanner22.py @@ -0,0 +1,27 @@ +# Copyright (c) 2016 by Rocky Bernstein +""" +Python 2.2 bytecode scanner/deparser + +This overlaps Python's 2.2's dis module, but it can be run from +Python 3 and other versions of Python. Also, we save token +information for later use in deparsing. +""" + +import uncompyle6.scanners.scanner23 as scan + +# bytecode verification, verify(), uses JUMP_OPs from here +from xdis.opcodes import opcode_22 +JUMP_OPs = opcode_22.JUMP_OPs + +# We base this off of 2.3 instead of the other way around +# because we cleaned things up this way. +# The history is that 2.7 support is the cleanest, +# then from that we got 2.6 and so on. +class Scanner22(scan.Scanner23): + def __init__(self, show_asm=False): + scan.Scanner23.__init__(self, show_asm) + self.opc = opcode_22 + self.opname = opcode_22.opname + self.version = 2.2 + self.genexpr_name = ''; + return diff --git a/uncompyle6/scanners/scanner23.py b/uncompyle6/scanners/scanner23.py index 0c59b29d..116c0eb8 100644 --- a/uncompyle6/scanners/scanner23.py +++ b/uncompyle6/scanners/scanner23.py @@ -1,8 +1,8 @@ # Copyright (c) 2016 by Rocky Bernstein """ -Python 2.4 bytecode scanner/deparser +Python 2.3 bytecode scanner/deparser -This overlaps Python's 2.4's dis module, but it can be run from +This overlaps Python's 2.3's dis module, but it can be run from Python 3 and other versions of Python. Also, we save token information for later use in deparsing. """ @@ -20,6 +20,8 @@ JUMP_OPs = opcode_23.JUMP_OPs class Scanner23(scan.Scanner24): def __init__(self, show_asm): scan.Scanner24.__init__(self, show_asm) + self.opc = opcode_23 + self.opname = opcode_23.opname # These are the only differences in initialization between # 2.3-2.6 self.version = 2.3 diff --git a/uncompyle6/scanners/scanner24.py b/uncompyle6/scanners/scanner24.py index f2e86420..9ee88378 100755 --- a/uncompyle6/scanners/scanner24.py +++ b/uncompyle6/scanners/scanner24.py @@ -22,6 +22,8 @@ class Scanner24(scan.Scanner25): scan.Scanner25.__init__(self, show_asm) # These are the only differences in initialization between # 2.4, 2.5 and 2.6 + self.opc = opcode_24 + self.opname = opcode_24.opname self.version = 2.4 self.genexpr_name = ''; return diff --git a/uncompyle6/scanners/scanner25.py b/uncompyle6/scanners/scanner25.py index a11015a2..446f5091 100755 --- a/uncompyle6/scanners/scanner25.py +++ b/uncompyle6/scanners/scanner25.py @@ -21,6 +21,8 @@ class Scanner25(scan.Scanner26): def __init__(self, show_asm): # There are no differences in initialization between # 2.5 and 2.6 + self.opc = opcode_25 + self.opname = opcode_25.opname scan.Scanner26.__init__(self, show_asm) self.version = 2.5 return diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index 9a1c4731..d22e176c 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -329,7 +329,9 @@ TABLE_DIRECT = { 'kv': ( '%c: %c', 3, 1 ), 'kv2': ( '%c: %c', 1, 2 ), 'mapexpr': ( '{%[1]C}', (0, maxint, ', ') ), - + 'importstmt': ( '%|import %c\n', 2), + 'importfrom': ( '%|from %[2]{pattr} import %c\n', 3 ), + 'importstar': ( '%|from %[2]{pattr} import *\n', ), } @@ -560,14 +562,12 @@ class SourceWalker(GenericASTTraversal, object): 'importfrom20': ( '%|from %[1]{pattr} import %c\n', 2 ), 'importlist20': ( '%C', (0, maxint, ', ') ), }) + elif version >= 2.5: ######################## # Import style for 2.5+ ######################## TABLE_DIRECT.update({ - 'importstmt': ( '%|import %c\n', 2), - 'importstar': ( '%|from %[2]{pattr} import *\n', ), - 'importfrom': ( '%|from %[2]{pattr} import %c\n', 3 ), 'importmultiple': ( '%|import %c%c\n', 2, 3 ), 'import_cont' : ( ', %c', 2 ), })