diff --git a/ChangeLog b/ChangeLog index e1ee5ee0..26f9f2e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,105 @@ +2016-12-04 rocky + + * uncompyle6/version.py: Get ready for release 2.9.7 + +2016-11-28 rocky + + * uncompyle6/parsers/parse3.py, uncompyle6/parsers/parse36.py: + Shorten Python3 grammars with + and * + +2016-11-28 rocky + + * __pkginfo__.py, uncompyle6/parser.py, + uncompyle6/parsers/parse2.py: Try new spark 2.5.1 grammar syntax + shortcuts This package I now declare stable + +2016-11-28 R. Bernstein + + * README.rst: Update README.rst + +2016-11-27 rocky + + * README.rst: Limitations of decompiling control structures. + +2016-11-27 R. Bernstein + + * : Merge pull request #69 from rocky/ast-reduce-checks AST reduce checks + +2016-11-26 rocky + + * test/simple_source/bug26/03_elif_vs_continue.py, + uncompyle6/main.py, uncompyle6/parser.py, + uncompyle6/parsers/parse2.py, uncompyle6/scanners/scanner2.py, + uncompyle6/scanners/scanner26.py: Misc changes scanner26.py: make scanner2.py and scanner26.py more alike + scanner2.py: check that return stmt is last in list. (May change) + main.py: show filename on verify error test/*: add more + +2016-11-25 rocky + + * __pkginfo__.py, test/Makefile, uncompyle6/parser.py, + uncompyle6/parsers/parse2.py, uncompyle6/parsers/parse3.py: Start + grammar reduction checks + +2016-11-24 rocky + + * uncompyle6/parsers/parse27.py, uncompyle6/scanners/scanner2.py, + uncompyle6/semantics/helper.py, uncompyle6/semantics/pysource.py: + 2.7 grammar bug workaround. Fix docstring bug + +2016-11-24 rocky + + * uncompyle6/semantics/pysource.py: Better line number tracking Indent Python 2 list comprehensions, albeit badly. DRY code a + little via indent_if_source_nl + +2016-11-24 rocky + + * uncompyle6/parsers/parse3.py, uncompyle6/scanners/scanner2.py: + <2.7 "if" detection and dup Python 3 grammar rule + +2016-11-23 rocky + + * __pkginfo__.py, pytest/test_grammar.py, uncompyle6/parser.py, + uncompyle6/parsers/parse26.py: Python 2.6 grammary bug and.. __pkginfo.py__: Bump spark_parser version for parse_flags 'dups' + +2016-11-23 rocky + + * __pkginfo__.py: Note that we now work on 2.4 and 2.5 + +2016-11-23 rocky + + * : commit 6aa1531972de83ecab15b4c96b89c873ea5a7458 Author: rocky + Date: Wed Nov 23 00:48:38 2016 -0500 + +2016-11-22 rocky + + * uncompyle6/parsers/parse3.py, uncompyle6/parsers/parse32.py, + uncompyle6/parsers/parse33.py, uncompyle6/parsers/parse34.py, + uncompyle6/parsers/parse35.py: DRY Python3 grammar + +2016-11-22 rocky + + * uncompyle6/parsers/parse2.py, uncompyle6/parsers/parse27.py, + uncompyle6/scanners/scanner2.py: More detailed COME_FROMs For now we only add COME_FROM_FINALLY and COME_FROM_WITH and even + here only on 2.7 + +2016-11-22 rocky + + * circle.yml, pytest/test_grammar.py, tox.ini, + uncompyle6/parser.py, uncompyle6/parsers/parse2.py, + uncompyle6/parsers/parse27.py: Remove redundant 2.7 (and 2.x) + grammar rules + +2016-11-22 rocky + + * pytest/test_docstring.py, uncompyle6/linenumbers.py, + uncompyle6/semantics/fragments.py, uncompyle6/semantics/helper.py, + uncompyle6/semantics/make_function.py, + uncompyle6/semantics/pysource.py: Split out print_docstring move from pysource.py to new helper.py + 2016-11-20 rocky - * uncompyle6/version.py: Get ready for release 2.9.6 + * ChangeLog, NEWS, uncompyle6/version.py: Get ready for release + 2.9.6 2016-11-20 R. Bernstein diff --git a/NEWS b/NEWS index 17e3d784..38fd8760 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,11 @@ +uncompyle6 2.9.6 2016-12-04 + +- Shorten Python3 grammars with + and * + this requires spark parser 1.5.1 +- Add some AST reduction checks to improve + decompile accuracy. This too requires + spark parser 1.5.1 + uncompyle6 2.9.6 2016-11-20 - Correct MANIFEST.in diff --git a/uncompyle6/main.py b/uncompyle6/main.py index 256958a0..585166f1 100644 --- a/uncompyle6/main.py +++ b/uncompyle6/main.py @@ -49,7 +49,6 @@ def uncompyle( raise pysource.SourceWalkerError(str(e)) - def uncompyle_file(filename, outstream=None, showasm=None, showast=False, showgrammar=False): """ @@ -61,7 +60,6 @@ def uncompyle_file(filename, outstream=None, showasm=None, showast=False, (version, timestamp, magic_int, co, is_pypy, source_size) = load_module(filename, code_objects) - if type(co) == list: for con in co: uncompyle(version, con, outstream, showasm, showast, diff --git a/uncompyle6/parser.py b/uncompyle6/parser.py index 05b71188..0ddc7a83 100644 --- a/uncompyle6/parser.py +++ b/uncompyle6/parser.py @@ -136,9 +136,9 @@ class PythonParser(GenericASTBuilder): # print >> sys.stderr, 'resolve', str(list) return GenericASTBuilder.resolve(self, list) - ############################################## - ## Common Python 2 and Python 3 grammar rules - ############################################## + ############################################### + # Common Python 2 and Python 3 grammar rules # + ############################################### def p_start(self, args): ''' # The start or goal symbol diff --git a/uncompyle6/parsers/parse26.py b/uncompyle6/parsers/parse26.py index c485b00f..bb6cdffa 100644 --- a/uncompyle6/parsers/parse26.py +++ b/uncompyle6/parsers/parse26.py @@ -13,7 +13,6 @@ class Python26Parser(Python2Parser): super(Python26Parser, self).__init__(debug_parser) self.customized = {} - def p_try_except26(self, args): """ except_stmt ::= except_cond3 except_suite @@ -246,8 +245,8 @@ if __name__ == '__main__': """.split())) remain_tokens = set(tokens) - opcode_set import re - remain_tokens = set([re.sub('_\d+$','', t) for t in remain_tokens]) - remain_tokens = set([re.sub('_CONT$','', t) for t in remain_tokens]) + remain_tokens = set([re.sub('_\d+$', '', t) for t in remain_tokens]) + remain_tokens = set([re.sub('_CONT$', '', t) for t in remain_tokens]) remain_tokens = set(remain_tokens) - opcode_set print(remain_tokens) # print(sorted(p.rule2name.items())) diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index 5d58845c..ea1c3b7b 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -243,7 +243,6 @@ class Python3Parser(PythonParser): c_stmts_opt34 ::= JUMP_BACK JUMP_ABSOLUTE c_stmts_opt """ - def p_def_annotations3(self, args): """ # Annotated functions @@ -437,10 +436,10 @@ class Python3Parser(PythonParser): args_kw = (token.attr >> 8) & 0xff nak = ( len(opname)-len('CALL_FUNCTION') ) // 3 token.type = self.call_fn_name(token) - rule = ('call_function ::= expr ' - + ('pos_arg ' * args_pos) - + ('kwarg ' * args_kw) - + 'expr ' * nak + token.type) + rule = ('call_function ::= expr ' + + ('pos_arg ' * args_pos) + + ('kwarg ' * args_kw) + + 'expr ' * nak + token.type) self.add_unique_rule(rule, token.type, args_pos, customize) rule = ('classdefdeco2 ::= LOAD_BUILD_CLASS mkfunc %s%s_%d' % (('expr ' * (args_pos-1)), opname, args_pos)) @@ -632,10 +631,10 @@ class Python3Parser(PythonParser): # number of apply equiv arguments: nak = ( len(opname_base)-len('CALL_METHOD') ) // 3 - rule = ('call_function ::= expr ' - + ('pos_arg ' * args_pos) - + ('kwarg ' * args_kw) - + 'expr ' * nak + opname) + rule = ('call_function ::= expr ' + + ('pos_arg ' * args_pos) + + ('kwarg ' * args_kw) + + 'expr ' * nak + opname) self.add_unique_rule(rule, opname, token.attr, customize) elif opname.startswith('MAKE_CLOSURE'): # DRY with MAKE_FUNCTION diff --git a/uncompyle6/parsers/parse34.py b/uncompyle6/parsers/parse34.py index fa136f71..c3a93266 100644 --- a/uncompyle6/parsers/parse34.py +++ b/uncompyle6/parsers/parse34.py @@ -40,8 +40,8 @@ if __name__ == '__main__': """.split())) remain_tokens = set(tokens) - opcode_set import re - remain_tokens = set([re.sub('_\d+$','', t) for t in remain_tokens]) - remain_tokens = set([re.sub('_CONT$','', t) for t in remain_tokens]) + remain_tokens = set([re.sub('_\d+$', '', t) for t in remain_tokens]) + remain_tokens = set([re.sub('_CONT$', '', t) for t in remain_tokens]) remain_tokens = set(remain_tokens) - opcode_set print(remain_tokens) # print(sorted(p.rule2name.items())) diff --git a/uncompyle6/parsers/parse35.py b/uncompyle6/parsers/parse35.py index 032a7e18..c1852c82 100644 --- a/uncompyle6/parsers/parse35.py +++ b/uncompyle6/parsers/parse35.py @@ -66,8 +66,8 @@ if __name__ == '__main__': """.split())) remain_tokens = set(tokens) - opcode_set import re - remain_tokens = set([re.sub('_\d+$','', t) for t in remain_tokens]) - remain_tokens = set([re.sub('_CONT$','', t) for t in remain_tokens]) + remain_tokens = set([re.sub('_\d+$', '', t) for t in remain_tokens]) + remain_tokens = set([re.sub('_CONT$', '', t) for t in remain_tokens]) remain_tokens = set(remain_tokens) - opcode_set print(remain_tokens) # print(sorted(p.rule2name.items())) diff --git a/uncompyle6/scanner.py b/uncompyle6/scanner.py index 2d44490b..8f3c0a5d 100755 --- a/uncompyle6/scanner.py +++ b/uncompyle6/scanner.py @@ -27,7 +27,8 @@ if PYTHON3: intern = sys.intern L65536 = 65536 - def long(l): l + def long(l): + return l else: L65536 = long(65536) # NOQA diff --git a/uncompyle6/scanners/scanner2.py b/uncompyle6/scanners/scanner2.py index 1a6e9ec4..6ba44029 100644 --- a/uncompyle6/scanners/scanner2.py +++ b/uncompyle6/scanners/scanner2.py @@ -902,7 +902,6 @@ class Scanner2(scan.Scanner): pass pass - # FIXME: All the < 2.7 conditions are is horrible. We need a better way. if label is not None and label != -1: # In Python < 2.7, the POP_TOP in: diff --git a/uncompyle6/scanners/scanner23.py b/uncompyle6/scanners/scanner23.py index 116c0eb8..0d8de282 100644 --- a/uncompyle6/scanners/scanner23.py +++ b/uncompyle6/scanners/scanner23.py @@ -25,5 +25,5 @@ class Scanner23(scan.Scanner24): # These are the only differences in initialization between # 2.3-2.6 self.version = 2.3 - self.genexpr_name = ''; + self.genexpr_name = '' return diff --git a/uncompyle6/scanners/scanner24.py b/uncompyle6/scanners/scanner24.py index 9ee88378..9f550025 100755 --- a/uncompyle6/scanners/scanner24.py +++ b/uncompyle6/scanners/scanner24.py @@ -25,5 +25,5 @@ class Scanner24(scan.Scanner25): self.opc = opcode_24 self.opname = opcode_24.opname self.version = 2.4 - self.genexpr_name = ''; + self.genexpr_name = '' return diff --git a/uncompyle6/scanners/scanner3.py b/uncompyle6/scanners/scanner3.py index b6526cb8..12ced628 100644 --- a/uncompyle6/scanners/scanner3.py +++ b/uncompyle6/scanners/scanner3.py @@ -128,7 +128,6 @@ class Scanner3(Scanner): varargs_ops.add(self.opc.CALL_METHOD) self.varargs_ops = frozenset(varargs_ops) - def opName(self, offset): return self.opc.opname[self.code[offset]] diff --git a/uncompyle6/scanners/tok.py b/uncompyle6/scanners/tok.py index a260a24c..fb1690fc 100644 --- a/uncompyle6/scanners/tok.py +++ b/uncompyle6/scanners/tok.py @@ -29,7 +29,7 @@ class Token: self.pattr = pattr self.offset = offset self.linestart = linestart - if has_arg == False: + if has_arg is False: self.attr = None self.pattr = None self.opc = opc diff --git a/uncompyle6/semantics/make_function.py b/uncompyle6/semantics/make_function.py index 1b61e2d7..0a941af3 100644 --- a/uncompyle6/semantics/make_function.py +++ b/uncompyle6/semantics/make_function.py @@ -38,7 +38,7 @@ def find_globals(node, globs): def find_none(node): for n in node: if isinstance(n, AST): - if not n in ('return_stmt', 'return_if_stmt'): + if n not in ('return_stmt', 'return_if_stmt'): if find_none(n): return True elif n.type == 'LOAD_CONST' and n.pattr is None: diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index 4127c11c..256ce1b4 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -641,6 +641,7 @@ class SourceWalker(GenericASTTraversal, object): }) FSTRING_CONVERSION_MAP = {1: '!s', 2: '!r', 3: '!a'} + def f_conversion(node): node.conversion = FSTRING_CONVERSION_MAP.get(node.data[1].attr, '') @@ -897,7 +898,6 @@ class SourceWalker(GenericASTTraversal, object): pass self.write(')') - def n_LOAD_CONST(self, node): data = node.pattr; datatype = type(data) if isinstance(datatype, int) and data == minint: diff --git a/uncompyle6/verify.py b/uncompyle6/verify.py index 0063be7b..c65666d4 100755 --- a/uncompyle6/verify.py +++ b/uncompyle6/verify.py @@ -317,7 +317,7 @@ def cmp_code_objects(version, is_pypy, code_obj1, code_obj2, i2 += 2 continue elif tokens1[i1].type == 'LOAD_NAME' and tokens2[i2].type == 'LOAD_CONST' \ - and tokens1[i1].pattr == 'None' and tokens2[i2].pattr == None: + and tokens1[i1].pattr == 'None' and tokens2[i2].pattr is None: pass else: raise CmpErrorCode(name, tokens1[i1].offset, tokens1[i1], diff --git a/uncompyle6/version.py b/uncompyle6/version.py index e9ee1f29..5b5f9e44 100644 --- a/uncompyle6/version.py +++ b/uncompyle6/version.py @@ -1,3 +1,3 @@ # This file is suitable for sourcing inside bash as # well as importing into Python -VERSION='2.9.6' +VERSION='2.9.7'