You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 09:22:40 +08:00
Bang on 3.6 MAKE_FUNCTION a bit more
parse3.py, parse36.py: adding return_closure rule tags what's going on with this rule pysource.py: start changing semantic rules to support code changed by new make_function semantics README.rst: typo
This commit is contained in:
@@ -168,7 +168,7 @@ See Also
|
|||||||
--------
|
--------
|
||||||
|
|
||||||
* https://github.com/zrax/pycdc : supports all versions of Python and is written in C++. Support for later Python 3 versions is a bit lacking though.
|
* https://github.com/zrax/pycdc : supports all versions of Python and is written in C++. Support for later Python 3 versions is a bit lacking though.
|
||||||
* https://code.google.com/archive/p/unpyc3/ : supports Python 3.2 only. The above projects use a different decompiling technique what is used here.
|
* https://code.google.com/archive/p/unpyc3/ : supports Python 3.2 only. The above projects use a different decompiling technique than what is used here.
|
||||||
* https://github.com/figment/unpyc3/ : fork of above, but supports Python 3.3 only. Include some fixes like supporting function annotations
|
* https://github.com/figment/unpyc3/ : fork of above, but supports Python 3.3 only. Include some fixes like supporting function annotations
|
||||||
* The HISTORY_ file.
|
* The HISTORY_ file.
|
||||||
|
|
||||||
|
@@ -334,7 +334,9 @@ class Python3Parser(PythonParser):
|
|||||||
|
|
||||||
def p_stmt3(self, args):
|
def p_stmt3(self, args):
|
||||||
"""
|
"""
|
||||||
stmt ::= LOAD_CLOSURE RETURN_VALUE RETURN_LAST
|
stmt ::= return_closure
|
||||||
|
return_closure ::= LOAD_CLOSURE RETURN_VALUE RETURN_LAST
|
||||||
|
|
||||||
stmt ::= whileTruestmt
|
stmt ::= whileTruestmt
|
||||||
ifelsestmt ::= testexpr c_stmts_opt JUMP_FORWARD else_suite _come_from
|
ifelsestmt ::= testexpr c_stmts_opt JUMP_FORWARD else_suite _come_from
|
||||||
"""
|
"""
|
||||||
|
@@ -16,6 +16,8 @@ class Python36Parser(Python35Parser):
|
|||||||
|
|
||||||
def p_36misc(self, args):
|
def p_36misc(self, args):
|
||||||
"""
|
"""
|
||||||
|
return_closure ::= LOAD_CLOSURE DUP_TOP STORE_NAME RETURN_VALUE RETURN_LAST
|
||||||
|
|
||||||
expr ::= LOAD_NAME EXTENDED_ARG
|
expr ::= LOAD_NAME EXTENDED_ARG
|
||||||
|
|
||||||
fstring_multi ::= fstring_expr_or_strs BUILD_STRING
|
fstring_multi ::= fstring_expr_or_strs BUILD_STRING
|
||||||
|
@@ -424,7 +424,17 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
if i < num_kwargs:
|
if i < num_kwargs:
|
||||||
self.write(',')
|
self.write(',')
|
||||||
self.prune()
|
self.prune()
|
||||||
|
return
|
||||||
self.n_kwargs_only_36 = n_kwargs_only_36
|
self.n_kwargs_only_36 = n_kwargs_only_36
|
||||||
|
|
||||||
|
def n_return_closure(node):
|
||||||
|
# Nothing should be output here
|
||||||
|
self.prune()
|
||||||
|
return
|
||||||
|
self.n_return_closure = n_return_closure
|
||||||
|
pass # version > 3.6
|
||||||
|
pass # version > 3.4
|
||||||
|
pass # version > 3.0
|
||||||
return
|
return
|
||||||
|
|
||||||
f = property(lambda s: s.params['f'],
|
f = property(lambda s: s.params['f'],
|
||||||
@@ -1288,11 +1298,18 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
|
|
||||||
if self.version > 3.0:
|
if self.version > 3.0:
|
||||||
if node == 'classdefdeco2':
|
if node == 'classdefdeco2':
|
||||||
currentclass = node[1][2].pattr
|
if self.version >= 3.6:
|
||||||
|
class_code = node[1][1].pattr
|
||||||
|
else:
|
||||||
|
class_code = node[1][2].pattr
|
||||||
buildclass = node
|
buildclass = node
|
||||||
else:
|
else:
|
||||||
currentclass = node[1][0].pattr
|
if self.version >= 3.6:
|
||||||
buildclass = node[0]
|
class_code = node[0][1][0].pattr
|
||||||
|
buildclass = node[0]
|
||||||
|
else:
|
||||||
|
class_code = node[1][0].pattr
|
||||||
|
buildclass = node[0]
|
||||||
|
|
||||||
assert 'mkfunc' == buildclass[1]
|
assert 'mkfunc' == buildclass[1]
|
||||||
mkfunc = buildclass[1]
|
mkfunc = buildclass[1]
|
||||||
@@ -1300,16 +1317,16 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
if 3.0 <= self.version <= 3.2:
|
if 3.0 <= self.version <= 3.2:
|
||||||
for n in mkfunc:
|
for n in mkfunc:
|
||||||
if hasattr(n, 'attr') and iscode(n.attr):
|
if hasattr(n, 'attr') and iscode(n.attr):
|
||||||
subclass = n.attr
|
subclass_code = n.attr
|
||||||
break
|
break
|
||||||
elif n == 'expr':
|
elif n == 'expr':
|
||||||
subclass = n[0].attr
|
subclass_code = n[0].attr
|
||||||
pass
|
pass
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
for n in mkfunc:
|
for n in mkfunc:
|
||||||
if hasattr(n, 'attr') and iscode(n.attr):
|
if hasattr(n, 'attr') and iscode(n.attr):
|
||||||
subclass = n.attr
|
subclass_code = n.attr
|
||||||
break
|
break
|
||||||
pass
|
pass
|
||||||
pass
|
pass
|
||||||
@@ -1321,10 +1338,10 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
# Python 3.3 classes with closures work like this.
|
# Python 3.3 classes with closures work like this.
|
||||||
# Note have to test before 3.2 case because
|
# Note have to test before 3.2 case because
|
||||||
# index -2 also has an attr.
|
# index -2 also has an attr.
|
||||||
subclass = load_closure[-3].attr
|
subclass_code = load_closure[-3].attr
|
||||||
elif hasattr(load_closure[-2], 'attr'):
|
elif hasattr(load_closure[-2], 'attr'):
|
||||||
# Python 3.2 works like this
|
# Python 3.2 works like this
|
||||||
subclass = load_closure[-2].attr
|
subclass_code = load_closure[-2].attr
|
||||||
else:
|
else:
|
||||||
raise 'Internal Error n_classdef: cannot find class body'
|
raise 'Internal Error n_classdef: cannot find class body'
|
||||||
if hasattr(buildclass[3], '__len__'):
|
if hasattr(buildclass[3], '__len__'):
|
||||||
@@ -1333,18 +1350,21 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
subclass_info = buildclass[2]
|
subclass_info = buildclass[2]
|
||||||
else:
|
else:
|
||||||
raise 'Internal Error n_classdef: cannot superclass name'
|
raise 'Internal Error n_classdef: cannot superclass name'
|
||||||
|
elif self.version >= 3.6 and node == 'classdefdeco2':
|
||||||
|
subclass_info = node
|
||||||
|
subclass_code = buildclass[1][0].attr
|
||||||
else:
|
else:
|
||||||
subclass = buildclass[1][0].attr
|
subclass_code = buildclass[1][0].attr
|
||||||
subclass_info = node[0]
|
subclass_info = node[0]
|
||||||
else:
|
else:
|
||||||
buildclass = node if (node == 'classdefdeco2') else node[0]
|
buildclass = node if (node == 'classdefdeco2') else node[0]
|
||||||
build_list = buildclass[1][0]
|
build_list = buildclass[1][0]
|
||||||
if hasattr(buildclass[-3][0], 'attr'):
|
if hasattr(buildclass[-3][0], 'attr'):
|
||||||
subclass = buildclass[-3][0].attr
|
subclass_code = buildclass[-3][0].attr
|
||||||
currentclass = buildclass[0].pattr
|
class_code = buildclass[0].pattr
|
||||||
elif hasattr(node[0][0], 'pattr'):
|
elif hasattr(node[0][0], 'pattr'):
|
||||||
subclass = buildclass[-3][1].attr
|
subclass_code = buildclass[-3][1].attr
|
||||||
currentclass = node[0][0].pattr
|
class_code = node[0][0].pattr
|
||||||
else:
|
else:
|
||||||
raise 'Internal Error n_classdef: cannot find class name'
|
raise 'Internal Error n_classdef: cannot find class name'
|
||||||
|
|
||||||
@@ -1353,7 +1373,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
else:
|
else:
|
||||||
self.write('\n\n')
|
self.write('\n\n')
|
||||||
|
|
||||||
self.currentclass = str(currentclass)
|
self.currentclass = str(class_code)
|
||||||
self.write(self.indent, 'class ', self.currentclass)
|
self.write(self.indent, 'class ', self.currentclass)
|
||||||
|
|
||||||
if self.version > 3.0:
|
if self.version > 3.0:
|
||||||
@@ -1364,7 +1384,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
|
|
||||||
# class body
|
# class body
|
||||||
self.indentMore()
|
self.indentMore()
|
||||||
self.build_class(subclass)
|
self.build_class(subclass_code)
|
||||||
self.indentLess()
|
self.indentLess()
|
||||||
|
|
||||||
self.currentclass = cclass
|
self.currentclass = cclass
|
||||||
|
Reference in New Issue
Block a user