You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 01:09:52 +08:00
Merge branch 'master' into python-2.4
This commit is contained in:
@@ -51,7 +51,6 @@ def test_grammar():
|
|||||||
else:
|
else:
|
||||||
expect_right_recursive.add((('l_stmts',
|
expect_right_recursive.add((('l_stmts',
|
||||||
('lastl_stmt', 'COME_FROM', 'l_stmts'))))
|
('lastl_stmt', 'COME_FROM', 'l_stmts'))))
|
||||||
# expect_lhs.add('kwargs1')
|
|
||||||
pass
|
pass
|
||||||
pass
|
pass
|
||||||
pass
|
pass
|
||||||
|
BIN
test/bytecode_3.4_run/04_call_function.pyc
Normal file
BIN
test/bytecode_3.4_run/04_call_function.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/bytecode_3.6_run/04_call_function.pyc
Normal file
BIN
test/bytecode_3.6_run/04_call_function.pyc
Normal file
Binary file not shown.
@@ -10,3 +10,14 @@ def tometadata(self, metadata, schema, Table, args, name=None):
|
|||||||
|
|
||||||
def _strptime_datetime(cls, args):
|
def _strptime_datetime(cls, args):
|
||||||
return cls(*args)
|
return cls(*args)
|
||||||
|
|
||||||
|
|
||||||
|
# From 3.5.5 imaplib
|
||||||
|
# Bug is in parsing *date_time[:6] parameter
|
||||||
|
from datetime import datetime, timezone, timedelta
|
||||||
|
import time
|
||||||
|
def Time2Internaldate(date_time):
|
||||||
|
delta = timedelta(seconds=0)
|
||||||
|
return datetime(*date_time[:6], tzinfo=timezone(delta))
|
||||||
|
|
||||||
|
assert Time2Internaldate(time.localtime())
|
||||||
|
@@ -31,3 +31,18 @@ def handle_read(self):
|
|||||||
return why
|
return why
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
# From 3.6 contextlib
|
||||||
|
# Bug is indentation of "return exc"
|
||||||
|
# Also there are extra statements to remove exec,
|
||||||
|
# which we hide (unless doing fragments).
|
||||||
|
# Note: The indentation bug may be a result of using improper
|
||||||
|
# grammar.
|
||||||
|
def __exit__(self, type, value, traceback):
|
||||||
|
try:
|
||||||
|
value()
|
||||||
|
except StopIteration as exc:
|
||||||
|
return exc
|
||||||
|
except RuntimeError as exc:
|
||||||
|
return exc
|
||||||
|
return
|
||||||
|
@@ -78,7 +78,8 @@ case $PYVERSION in
|
|||||||
[test_curses.py]=1 # Possibly fails on its own but not detected
|
[test_curses.py]=1 # Possibly fails on its own but not detected
|
||||||
[test_dis.py]=1 # We change line numbers - duh!
|
[test_dis.py]=1 # We change line numbers - duh!
|
||||||
[test_doctest.py]=1 # Fails on its own
|
[test_doctest.py]=1 # Fails on its own
|
||||||
[test_grammar.py]=1 # Too many stmts. Handle large stmts
|
[test_generators.py]=1 # control flow. uncompyle2 has problem here too
|
||||||
|
[test_grammar.py]=1 # Too many stmts. Handle large stmts
|
||||||
[test_io.py]=1 # Test takes too long to run
|
[test_io.py]=1 # Test takes too long to run
|
||||||
[test_ioctl.py]=1 # Test takes too long to run
|
[test_ioctl.py]=1 # Test takes too long to run
|
||||||
[test_itertools.py]=1 # Fix erroneous reduction to "conditional_true".
|
[test_itertools.py]=1 # Fix erroneous reduction to "conditional_true".
|
||||||
|
@@ -113,9 +113,9 @@ class Python3Parser(PythonParser):
|
|||||||
continues ::= continue
|
continues ::= continue
|
||||||
|
|
||||||
|
|
||||||
kwarg ::= LOAD_CONST expr
|
kwarg ::= LOAD_CONST expr
|
||||||
kwargs ::= kwarg*
|
kwargs ::= kwarg+
|
||||||
kwargs1 ::= kwarg+
|
|
||||||
|
|
||||||
classdef ::= build_class store
|
classdef ::= build_class store
|
||||||
|
|
||||||
@@ -393,9 +393,6 @@ class Python3Parser(PythonParser):
|
|||||||
'''
|
'''
|
||||||
load_genexpr ::= LOAD_GENEXPR
|
load_genexpr ::= LOAD_GENEXPR
|
||||||
load_genexpr ::= BUILD_TUPLE_1 LOAD_GENEXPR LOAD_CONST
|
load_genexpr ::= BUILD_TUPLE_1 LOAD_GENEXPR LOAD_CONST
|
||||||
|
|
||||||
# Is there something general going on here?
|
|
||||||
dict_comp ::= load_closure LOAD_DICTCOMP LOAD_CONST MAKE_CLOSURE_0 expr GET_ITER CALL_FUNCTION_1
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def p_expr3(self, args):
|
def p_expr3(self, args):
|
||||||
@@ -531,7 +528,7 @@ class Python3Parser(PythonParser):
|
|||||||
subclassing is, well, is pretty base. And we want it that way: lean and
|
subclassing is, well, is pretty base. And we want it that way: lean and
|
||||||
mean so that parsing will go faster.
|
mean so that parsing will go faster.
|
||||||
|
|
||||||
Here, we add additional grammra rules based on specific instructions
|
Here, we add additional grammar rules based on specific instructions
|
||||||
that are in the instruction/token stream. In classes that
|
that are in the instruction/token stream. In classes that
|
||||||
inherit from from here and other versions, grammar rules may
|
inherit from from here and other versions, grammar rules may
|
||||||
also be removed.
|
also be removed.
|
||||||
@@ -575,6 +572,10 @@ class Python3Parser(PythonParser):
|
|||||||
seen_LOAD_BUILD_CLASS = False
|
seen_LOAD_BUILD_CLASS = False
|
||||||
seen_GET_AWAITABLE_YIELD_FROM = False
|
seen_GET_AWAITABLE_YIELD_FROM = False
|
||||||
|
|
||||||
|
# This is used in parse36.py as well as here
|
||||||
|
self.seen_LOAD_DICTCOMP = False
|
||||||
|
|
||||||
|
|
||||||
# Loop over instructions adding custom grammar rules based on
|
# Loop over instructions adding custom grammar rules based on
|
||||||
# a specific instruction seen.
|
# a specific instruction seen.
|
||||||
|
|
||||||
@@ -656,9 +657,9 @@ class Python3Parser(PythonParser):
|
|||||||
('dict ' * token.attr) +
|
('dict ' * token.attr) +
|
||||||
'BUILD_MAP_UNPACK')
|
'BUILD_MAP_UNPACK')
|
||||||
else:
|
else:
|
||||||
rule = kvlist_n + ' ::= ' + 'expr ' * (token.attr*2)
|
rule = "%s ::= %s %s" % (kvlist_n, 'expr ' * (token.attr*2), opname)
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
rule = "dict ::= %s %s" % (kvlist_n, opname)
|
rule = "dict ::= %s" % kvlist_n
|
||||||
else:
|
else:
|
||||||
rule = kvlist_n + ' ::= ' + 'expr expr STORE_MAP ' * token.attr
|
rule = kvlist_n + ' ::= ' + 'expr expr STORE_MAP ' * token.attr
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
@@ -784,6 +785,7 @@ class Python3Parser(PythonParser):
|
|||||||
self.addRule("expr ::= LOAD_CLASSNAME", nop_func)
|
self.addRule("expr ::= LOAD_CLASSNAME", nop_func)
|
||||||
custom_ops_seen.add(opname)
|
custom_ops_seen.add(opname)
|
||||||
elif opname == 'LOAD_DICTCOMP':
|
elif opname == 'LOAD_DICTCOMP':
|
||||||
|
self.seen_LOAD_DICTCOMP = True
|
||||||
if has_get_iter_call_function1:
|
if has_get_iter_call_function1:
|
||||||
rule_pat = ("dict_comp ::= LOAD_DICTCOMP %sMAKE_FUNCTION_0 expr "
|
rule_pat = ("dict_comp ::= LOAD_DICTCOMP %sMAKE_FUNCTION_0 expr "
|
||||||
"GET_ITER CALL_FUNCTION_1")
|
"GET_ITER CALL_FUNCTION_1")
|
||||||
@@ -816,6 +818,17 @@ class Python3Parser(PythonParser):
|
|||||||
# DRY with MAKE_FUNCTION
|
# DRY with MAKE_FUNCTION
|
||||||
# Note: this probably doesn't handle kwargs proprerly
|
# Note: this probably doesn't handle kwargs proprerly
|
||||||
|
|
||||||
|
if opname == 'MAKE_CLOSURE_0' and self.seen_LOAD_DICTCOMP:
|
||||||
|
# Is there something general going on here?
|
||||||
|
# Note that 3.6+ doesn't do this, but we'll remove
|
||||||
|
# this rule in parse36.py
|
||||||
|
rule = """
|
||||||
|
dict_comp ::= load_closure LOAD_DICTCOMP LOAD_CONST
|
||||||
|
MAKE_CLOSURE_0 expr
|
||||||
|
GET_ITER CALL_FUNCTION_1
|
||||||
|
"""
|
||||||
|
self.addRule(rule, nop_func)
|
||||||
|
|
||||||
args_pos, args_kw, annotate_args = token.attr
|
args_pos, args_kw, annotate_args = token.attr
|
||||||
|
|
||||||
# FIXME: Fold test into add_make_function_rule
|
# FIXME: Fold test into add_make_function_rule
|
||||||
@@ -854,13 +867,13 @@ class Python3Parser(PythonParser):
|
|||||||
opname, token.attr, customize)
|
opname, token.attr, customize)
|
||||||
|
|
||||||
if args_kw > 0:
|
if args_kw > 0:
|
||||||
kwargs_str = 'kwargs1 '
|
kwargs_str = 'kwargs '
|
||||||
else:
|
else:
|
||||||
kwargs_str = ''
|
kwargs_str = ''
|
||||||
|
|
||||||
# Note order of kwargs and pos args changed between 3.3-3.4
|
# Note order of kwargs and pos args changed between 3.3-3.4
|
||||||
if self.version <= 3.2:
|
if self.version <= 3.2:
|
||||||
rule = ('mkfunc ::= %s%sload_closure LOAD_CONST kwargs %s'
|
rule = ('mkfunc ::= %s%sload_closure LOAD_CONST %s'
|
||||||
% (kwargs_str, 'expr ' * args_pos, opname))
|
% (kwargs_str, 'expr ' * args_pos, opname))
|
||||||
elif self.version == 3.3:
|
elif self.version == 3.3:
|
||||||
rule = ('mkfunc ::= %s%sload_closure LOAD_CONST LOAD_CONST %s'
|
rule = ('mkfunc ::= %s%sload_closure LOAD_CONST LOAD_CONST %s'
|
||||||
@@ -968,29 +981,39 @@ class Python3Parser(PythonParser):
|
|||||||
opname))
|
opname))
|
||||||
self.add_make_function_rule(rule_pat, opname, token.attr, customize)
|
self.add_make_function_rule(rule_pat, opname, token.attr, customize)
|
||||||
|
|
||||||
|
if args_kw == 0:
|
||||||
|
kwargs = 'no_kwargs'
|
||||||
|
self.add_unique_rule("no_kwargs ::=", opname, token.attr, customize)
|
||||||
|
else:
|
||||||
|
kwargs = 'kwargs'
|
||||||
|
|
||||||
if self.version < 3.3:
|
if self.version < 3.3:
|
||||||
# positional args after keyword args
|
# positional args after keyword args
|
||||||
rule = ('mkfunc ::= kwargs %s%s %s' %
|
rule = ('mkfunc ::= %s %s%s%s' %
|
||||||
|
(kwargs, 'pos_arg ' * args_pos, 'LOAD_CONST ',
|
||||||
|
opname))
|
||||||
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
|
rule = ('mkfunc ::= %s%s%s' %
|
||||||
('pos_arg ' * args_pos, 'LOAD_CONST ',
|
('pos_arg ' * args_pos, 'LOAD_CONST ',
|
||||||
opname))
|
opname))
|
||||||
elif self.version == 3.3:
|
elif self.version == 3.3:
|
||||||
# positional args after keyword args
|
# positional args after keyword args
|
||||||
rule = ('mkfunc ::= kwargs %s%s %s' %
|
rule = ('mkfunc ::= %s %s%s%s' %
|
||||||
('pos_arg ' * args_pos, 'LOAD_CONST '*2,
|
(kwargs, 'pos_arg ' * args_pos, 'LOAD_CONST '*2,
|
||||||
opname))
|
opname))
|
||||||
elif self.version > 3.5:
|
elif self.version > 3.5:
|
||||||
# positional args before keyword args
|
# positional args before keyword args
|
||||||
rule = ('mkfunc ::= %skwargs1 %s %s' %
|
rule = ('mkfunc ::= %s%s %s%s' %
|
||||||
('pos_arg ' * args_pos, 'LOAD_CONST '*2,
|
('pos_arg ' * args_pos, kwargs, 'LOAD_CONST '*2,
|
||||||
opname))
|
opname))
|
||||||
elif self.version > 3.3:
|
elif self.version > 3.3:
|
||||||
# positional args before keyword args
|
# positional args before keyword args
|
||||||
rule = ('mkfunc ::= %skwargs %s %s' %
|
rule = ('mkfunc ::= %s%s %s%s' %
|
||||||
('pos_arg ' * args_pos, 'LOAD_CONST '*2,
|
('pos_arg ' * args_pos, kwargs, 'LOAD_CONST '*2,
|
||||||
opname))
|
opname))
|
||||||
else:
|
else:
|
||||||
rule = ('mkfunc ::= kwargs %sexpr %s' %
|
rule = ('mkfunc ::= %s%sexpr %s' %
|
||||||
('pos_arg ' * args_pos, opname))
|
(kwargs, 'pos_arg ' * args_pos, opname))
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
if opname.startswith('MAKE_FUNCTION_A'):
|
if opname.startswith('MAKE_FUNCTION_A'):
|
||||||
if self.version >= 3.6:
|
if self.version >= 3.6:
|
||||||
|
@@ -35,9 +35,6 @@ class Python36Parser(Python35Parser):
|
|||||||
# 3.6 redoes how return_closure works. FIXME: Isolate to LOAD_CLOSURE
|
# 3.6 redoes how return_closure works. FIXME: Isolate to LOAD_CLOSURE
|
||||||
return_closure ::= LOAD_CLOSURE DUP_TOP STORE_NAME RETURN_VALUE RETURN_LAST
|
return_closure ::= LOAD_CLOSURE DUP_TOP STORE_NAME RETURN_VALUE RETURN_LAST
|
||||||
|
|
||||||
# Is there something general going on here? FIXME: Isolate to LOAD_DICTCOMP
|
|
||||||
dict_comp ::= load_closure LOAD_DICTCOMP LOAD_CONST MAKE_FUNCTION_8 expr GET_ITER CALL_FUNCTION_1
|
|
||||||
|
|
||||||
stmt ::= conditional_lambda
|
stmt ::= conditional_lambda
|
||||||
conditional_lambda ::= expr jmp_false expr return_if_lambda
|
conditional_lambda ::= expr jmp_false expr return_if_lambda
|
||||||
return_stmt_lambda LAMBDA_MARKER
|
return_stmt_lambda LAMBDA_MARKER
|
||||||
@@ -105,6 +102,14 @@ class Python36Parser(Python35Parser):
|
|||||||
fstring_single ::= expr FORMAT_VALUE
|
fstring_single ::= expr FORMAT_VALUE
|
||||||
"""
|
"""
|
||||||
self.add_unique_doc_rules(rules_str, customize)
|
self.add_unique_doc_rules(rules_str, customize)
|
||||||
|
elif opname == 'MAKE_FUNCTION_8' and self.seen_LOAD_DICTCOMP:
|
||||||
|
# Is there something general going on here?
|
||||||
|
rule = """
|
||||||
|
dict_comp ::= load_closure LOAD_DICTCOMP LOAD_CONST
|
||||||
|
MAKE_FUNCTION_8 expr
|
||||||
|
GET_ITER CALL_FUNCTION_1
|
||||||
|
"""
|
||||||
|
self.addRule(rule, nop_func)
|
||||||
elif opname == 'BEFORE_ASYNC_WITH':
|
elif opname == 'BEFORE_ASYNC_WITH':
|
||||||
rules_str = """
|
rules_str = """
|
||||||
stmt ::= async_with_stmt
|
stmt ::= async_with_stmt
|
||||||
|
@@ -288,7 +288,10 @@ TABLE_DIRECT = {
|
|||||||
'except': ( '%|except:\n%+%c%-', 3 ),
|
'except': ( '%|except:\n%+%c%-', 3 ),
|
||||||
'except_cond1': ( '%|except %c:\n', 1 ),
|
'except_cond1': ( '%|except %c:\n', 1 ),
|
||||||
'except_suite': ( '%+%c%-%C', 0, (1, maxint, '') ),
|
'except_suite': ( '%+%c%-%C', 0, (1, maxint, '') ),
|
||||||
|
|
||||||
|
# In Python 3.6, this is more complicated in the presence of "returns"
|
||||||
'except_suite_finalize': ( '%+%c%-%C', 1, (3, maxint, '') ),
|
'except_suite_finalize': ( '%+%c%-%C', 1, (3, maxint, '') ),
|
||||||
|
|
||||||
'pass': ( '%|pass\n', ),
|
'pass': ( '%|pass\n', ),
|
||||||
'STORE_FAST': ( '%{pattr}', ),
|
'STORE_FAST': ( '%{pattr}', ),
|
||||||
'kv': ( '%c: %c', 3, 1 ),
|
'kv': ( '%c: %c', 3, 1 ),
|
||||||
@@ -381,7 +384,6 @@ PRECEDENCE = {
|
|||||||
'ret_cond_not': 28,
|
'ret_cond_not': 28,
|
||||||
|
|
||||||
'_mklambda': 30,
|
'_mklambda': 30,
|
||||||
'call_kw': 100, # 100 seems to to be module/function precidence
|
|
||||||
'yield': 101,
|
'yield': 101,
|
||||||
'yield_from': 101
|
'yield_from': 101
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from uncompyle6.semantics.consts import (
|
from uncompyle6.semantics.consts import (
|
||||||
INDENT_PER_LEVEL, TABLE_R, TABLE_DIRECT)
|
PRECEDENCE, INDENT_PER_LEVEL, TABLE_R, TABLE_DIRECT)
|
||||||
|
|
||||||
from uncompyle6.semantics.make_function import (
|
from uncompyle6.semantics.make_function import (
|
||||||
make_function3_annotate,
|
make_function3_annotate,
|
||||||
@@ -239,6 +239,7 @@ def customize_for_version(self, is_pypy, version):
|
|||||||
TABLE_DIRECT.update({
|
TABLE_DIRECT.update({
|
||||||
'LOAD_CLASSDEREF': ( '%{pattr}', ),
|
'LOAD_CLASSDEREF': ( '%{pattr}', ),
|
||||||
})
|
})
|
||||||
|
|
||||||
########################
|
########################
|
||||||
# Python 3.5+ Additions
|
# Python 3.5+ Additions
|
||||||
#######################
|
#######################
|
||||||
@@ -312,7 +313,7 @@ def customize_for_version(self, is_pypy, version):
|
|||||||
template = ('*%P)', (0, len(args_node)-1, ', *', 100))
|
template = ('*%P)', (0, len(args_node)-1, ', *', 100))
|
||||||
self.template_engine(template, args_node)
|
self.template_engine(template, args_node)
|
||||||
else:
|
else:
|
||||||
template = ('*%c)', -2)
|
template = ('*%c, %C)', 1, (2, -1, ', '))
|
||||||
self.template_engine(template, node)
|
self.template_engine(template, node)
|
||||||
self.prune()
|
self.prune()
|
||||||
|
|
||||||
@@ -353,6 +354,10 @@ def customize_for_version(self, is_pypy, version):
|
|||||||
# Python 3.6+ Additions
|
# Python 3.6+ Additions
|
||||||
#######################
|
#######################
|
||||||
|
|
||||||
|
# Value 100 is important; it is exactly
|
||||||
|
# module/function precidence.
|
||||||
|
PRECEDENCE['call_kw'] = 100
|
||||||
|
|
||||||
TABLE_DIRECT.update({
|
TABLE_DIRECT.update({
|
||||||
'tryfinally36': ( '%|try:\n%+%c%-%|finally:\n%+%c%-\n\n',
|
'tryfinally36': ( '%|try:\n%+%c%-%|finally:\n%+%c%-\n\n',
|
||||||
(1, 'returns'), 3 ),
|
(1, 'returns'), 3 ),
|
||||||
@@ -484,7 +489,7 @@ def customize_for_version(self, is_pypy, version):
|
|||||||
self.n_call_ex_kw3 = call_ex_kw3
|
self.n_call_ex_kw3 = call_ex_kw3
|
||||||
|
|
||||||
def call_ex_kw4(node):
|
def call_ex_kw4(node):
|
||||||
"""Handle CALL_FUNCTION_EX 2 (have KW) but without
|
"""Handle CALL_FUNCTION_EX {1 or 2} (have KW) but without
|
||||||
BUILD_{MAP,TUPLE}_UNPACK_WITH_CALL"""
|
BUILD_{MAP,TUPLE}_UNPACK_WITH_CALL"""
|
||||||
self.preorder(node[0])
|
self.preorder(node[0])
|
||||||
self.write('(')
|
self.write('(')
|
||||||
@@ -503,8 +508,13 @@ def customize_for_version(self, is_pypy, version):
|
|||||||
kwargs = node[2]
|
kwargs = node[2]
|
||||||
if kwargs == 'expr':
|
if kwargs == 'expr':
|
||||||
kwargs = kwargs[0]
|
kwargs = kwargs[0]
|
||||||
self.write('**')
|
call_function_ex = node[-1]
|
||||||
self.preorder(kwargs)
|
assert call_function_ex == 'CALL_FUNCTION_EX_KW'
|
||||||
|
if call_function_ex.attr & 1 and not isinstance(kwargs, Token):
|
||||||
|
self.call36_dict(kwargs)
|
||||||
|
else:
|
||||||
|
self.write('**')
|
||||||
|
self.preorder(kwargs)
|
||||||
self.write(')')
|
self.write(')')
|
||||||
self.prune()
|
self.prune()
|
||||||
self.n_call_ex_kw4 = call_ex_kw4
|
self.n_call_ex_kw4 = call_ex_kw4
|
||||||
@@ -559,8 +569,16 @@ def customize_for_version(self, is_pypy, version):
|
|||||||
kv_node = node[0]
|
kv_node = node[0]
|
||||||
l = list(kv_node)
|
l = list(kv_node)
|
||||||
i = 0
|
i = 0
|
||||||
|
|
||||||
|
length = len(l)
|
||||||
|
# FIXME: Parser-speed improved grammars will have BUILD_MAP
|
||||||
|
# at the end. So in the future when everything is
|
||||||
|
# complete, we can do an "assert" instead of "if".
|
||||||
|
if kv_node[-1].kind.startswith("BUILD_MAP"):
|
||||||
|
length -= 1
|
||||||
|
|
||||||
# Respect line breaks from source
|
# Respect line breaks from source
|
||||||
while i < len(l):
|
while i < length:
|
||||||
self.write(sep)
|
self.write(sep)
|
||||||
name = self.traverse(l[i], indent='')
|
name = self.traverse(l[i], indent='')
|
||||||
# Strip off beginning and trailing quotes in name
|
# Strip off beginning and trailing quotes in name
|
||||||
@@ -605,6 +623,22 @@ def customize_for_version(self, is_pypy, version):
|
|||||||
|
|
||||||
FSTRING_CONVERSION_MAP = {1: '!s', 2: '!r', 3: '!a'}
|
FSTRING_CONVERSION_MAP = {1: '!s', 2: '!r', 3: '!a'}
|
||||||
|
|
||||||
|
def n_except_suite_finalize(node):
|
||||||
|
if node[1] == 'returns' and self.hide_internal:
|
||||||
|
# Process node[1] only.
|
||||||
|
# The code after "returns", e.g. node[3], is dead code.
|
||||||
|
# Adding it is wrong as it dedents and another
|
||||||
|
# exception handler "except_stmt" afterwards.
|
||||||
|
# Note it is also possible that the grammar is wrong here.
|
||||||
|
# and this should not be "except_stmt".
|
||||||
|
self.indent_more()
|
||||||
|
self.preorder(node[1])
|
||||||
|
self.indent_less()
|
||||||
|
else:
|
||||||
|
self.default(node)
|
||||||
|
self.prune()
|
||||||
|
self.n_except_suite_finalize = n_except_suite_finalize
|
||||||
|
|
||||||
def n_formatted_value(node):
|
def n_formatted_value(node):
|
||||||
if node[0] == 'LOAD_CONST':
|
if node[0] == 'LOAD_CONST':
|
||||||
self.write(node[0].attr)
|
self.write(node[0].attr)
|
||||||
|
@@ -428,10 +428,7 @@ def make_function2(self, node, is_lambda, nested=1, codeNode=None):
|
|||||||
code, self.version)
|
code, self.version)
|
||||||
|
|
||||||
# Python 2 doesn't support the "nonlocal" statement
|
# Python 2 doesn't support the "nonlocal" statement
|
||||||
try:
|
assert self.version >= 3.0 or not nonlocals
|
||||||
assert self.version >= 3.0 or not nonlocals
|
|
||||||
except:
|
|
||||||
from trepan.api import debug; debug()
|
|
||||||
|
|
||||||
for g in sorted((all_globals & self.mod_globs) | globals):
|
for g in sorted((all_globals & self.mod_globs) | globals):
|
||||||
self.println(self.indent, 'global ', g)
|
self.println(self.indent, 'global ', g)
|
||||||
@@ -512,15 +509,22 @@ def make_function3(self, node, is_lambda, nested=1, codeNode=None):
|
|||||||
if isinstance(args_node.attr, tuple):
|
if isinstance(args_node.attr, tuple):
|
||||||
pos_args, kw_args, annotate_argc = args_node.attr
|
pos_args, kw_args, annotate_argc = args_node.attr
|
||||||
# FIXME: there is probably a better way to classify this.
|
# FIXME: there is probably a better way to classify this.
|
||||||
|
have_kwargs = node[0].kind.startswith('kwarg') or node[0] == 'no_kwargs'
|
||||||
|
if len(node) >= 4:
|
||||||
|
lc_index = -4
|
||||||
|
else:
|
||||||
|
lc_index = -3
|
||||||
|
pass
|
||||||
|
|
||||||
if (self.version <= 3.3 and len(node) > 2 and
|
if (self.version <= 3.3 and len(node) > 2 and
|
||||||
node[lambda_index] != 'LOAD_LAMBDA' and
|
node[lambda_index] != 'LOAD_LAMBDA' and
|
||||||
(node[0].kind.startswith('kwarg') or node[-4].kind != 'load_closure')):
|
(have_kwargs or node[lc_index].kind != 'load_closure')):
|
||||||
# args are after kwargs; kwargs are bundled as one node
|
# args are after kwargs; kwargs are bundled as one node
|
||||||
defparams = node[1:args_node.attr[0]+1]
|
defparams = node[1:args_node.attr[0]+1]
|
||||||
else:
|
else:
|
||||||
# args are before kwargs; kwags as bundled as one node
|
# args are before kwargs; kwags as bundled as one node
|
||||||
defparams = node[:args_node.attr[0]]
|
defparams = node[:args_node.attr[0]]
|
||||||
pos_args, kw_args, annotate_argc = args_node.attr
|
pass
|
||||||
else:
|
else:
|
||||||
if self.version < 3.6:
|
if self.version < 3.6:
|
||||||
defparams = node[:args_node.attr]
|
defparams = node[:args_node.attr]
|
||||||
@@ -695,7 +699,7 @@ def make_function3(self, node, is_lambda, nested=1, codeNode=None):
|
|||||||
for n in node:
|
for n in node:
|
||||||
if n == 'pos_arg':
|
if n == 'pos_arg':
|
||||||
continue
|
continue
|
||||||
elif self.version >= 3.4 and not (n.kind in ('kwargs', 'kwargs1', 'kwarg')):
|
elif self.version >= 3.4 and not (n.kind in ('kwargs', 'no_kwargs', 'kwarg')):
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
self.preorder(n)
|
self.preorder(n)
|
||||||
|
@@ -404,7 +404,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
|
|
||||||
def n_mkfunc_annotate(node):
|
def n_mkfunc_annotate(node):
|
||||||
|
|
||||||
if self.version >= 3.3 or node[-2] == 'kwargs':
|
if self.version >= 3.3 or node[-2] in ('kwargs', 'no_kwargs'):
|
||||||
# LOAD_CONST code object ..
|
# LOAD_CONST code object ..
|
||||||
# LOAD_CONST 'x0' if >= 3.3
|
# LOAD_CONST 'x0' if >= 3.3
|
||||||
# EXTENDED_ARG
|
# EXTENDED_ARG
|
||||||
@@ -468,73 +468,6 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
def async_call(node):
|
|
||||||
self.f.write('async ')
|
|
||||||
node.kind == 'call'
|
|
||||||
p = self.prec
|
|
||||||
self.prec = 80
|
|
||||||
self.template_engine(('%c(%P)', 0,
|
|
||||||
(1, -4, ', ', 100)), node)
|
|
||||||
self.prec = p
|
|
||||||
node.kind == 'async_call'
|
|
||||||
self.prune()
|
|
||||||
self.n_async_call = async_call
|
|
||||||
self.n_build_list_unpack = self.n_list
|
|
||||||
|
|
||||||
if version == 3.5:
|
|
||||||
def n_call(node):
|
|
||||||
mapping = self._get_mapping(node)
|
|
||||||
table = mapping[0]
|
|
||||||
key = node
|
|
||||||
for i in mapping[1:]:
|
|
||||||
key = key[i]
|
|
||||||
pass
|
|
||||||
if key.kind.startswith('CALL_FUNCTION_VAR_KW'):
|
|
||||||
# Python 3.5 changes the stack position of *args. kwargs come
|
|
||||||
# after *args whereas in earlier Pythons, *args is at the end
|
|
||||||
# which simpilfiies things from our perspective.
|
|
||||||
# Python 3.6+ replaces CALL_FUNCTION_VAR_KW with CALL_FUNCTION_EX
|
|
||||||
# We will just swap the order to make it look like earlier Python 3.
|
|
||||||
entry = table[key.kind]
|
|
||||||
kwarg_pos = entry[2][1]
|
|
||||||
args_pos = kwarg_pos - 1
|
|
||||||
# Put last node[args_pos] after subsequent kwargs
|
|
||||||
while node[kwarg_pos] == 'kwarg' and kwarg_pos < len(node):
|
|
||||||
# swap node[args_pos] with node[kwargs_pos]
|
|
||||||
node[kwarg_pos], node[args_pos] = node[args_pos], node[kwarg_pos]
|
|
||||||
args_pos = kwarg_pos
|
|
||||||
kwarg_pos += 1
|
|
||||||
self.default(node)
|
|
||||||
self.n_call = n_call
|
|
||||||
|
|
||||||
def n_function_def(node):
|
|
||||||
if self.version == 3.6:
|
|
||||||
code_node = node[0][0]
|
|
||||||
else:
|
|
||||||
code_node = node[0][1]
|
|
||||||
|
|
||||||
is_code = hasattr(code_node, 'attr') and iscode(code_node.attr)
|
|
||||||
if (is_code and
|
|
||||||
(code_node.attr.co_flags & COMPILER_FLAG_BIT['COROUTINE'])):
|
|
||||||
self.template_engine(('\n\n%|async def %c\n',
|
|
||||||
-2), node)
|
|
||||||
else:
|
|
||||||
self.template_engine(('\n\n%|def %c\n', -2),
|
|
||||||
node)
|
|
||||||
self.prune()
|
|
||||||
self.n_function_def = n_function_def
|
|
||||||
|
|
||||||
def unmapexpr(node):
|
|
||||||
last_n = node[0][-1]
|
|
||||||
for n in node[0]:
|
|
||||||
self.preorder(n)
|
|
||||||
if n != last_n:
|
|
||||||
self.f.write(', **')
|
|
||||||
pass
|
|
||||||
pass
|
|
||||||
self.prune()
|
|
||||||
pass
|
|
||||||
self.n_unmapexpr = unmapexpr
|
|
||||||
|
|
||||||
pass # version >= 3.4
|
pass # version >= 3.4
|
||||||
pass # version >= 3.0
|
pass # version >= 3.0
|
||||||
@@ -1041,7 +974,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
|
|
||||||
def n_mkfunc(self, node):
|
def n_mkfunc(self, node):
|
||||||
|
|
||||||
if self.version >= 3.3 or node[-2] == 'kwargs':
|
if self.version >= 3.3 or node[-2] in ('kwargs', 'no_kwargs'):
|
||||||
# LOAD_CONST code object ..
|
# LOAD_CONST code object ..
|
||||||
# LOAD_CONST 'x0' if >= 3.3
|
# LOAD_CONST 'x0' if >= 3.3
|
||||||
# MAKE_FUNCTION ..
|
# MAKE_FUNCTION ..
|
||||||
@@ -1057,7 +990,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
self.write(func_name)
|
self.write(func_name)
|
||||||
|
|
||||||
self.indent_more()
|
self.indent_more()
|
||||||
self.make_function(node, is_lambda=False, codeNode=code_node)
|
self.make_function(node, is_lambda=False, code_node=code_node)
|
||||||
|
|
||||||
if len(self.param_stack) > 1:
|
if len(self.param_stack) > 1:
|
||||||
self.write('\n\n')
|
self.write('\n\n')
|
||||||
@@ -1067,14 +1000,14 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
self.prune() # stop recursing
|
self.prune() # stop recursing
|
||||||
|
|
||||||
def make_function(self, node, is_lambda, nested=1,
|
def make_function(self, node, is_lambda, nested=1,
|
||||||
codeNode=None, annotate=None):
|
code_node=None, annotate=None):
|
||||||
if self.version >= 3.0:
|
if self.version >= 3.0:
|
||||||
make_function3(self, node, is_lambda, nested, codeNode)
|
make_function3(self, node, is_lambda, nested, code_node)
|
||||||
else:
|
else:
|
||||||
make_function2(self, node, is_lambda, nested, codeNode)
|
make_function2(self, node, is_lambda, nested, code_node)
|
||||||
|
|
||||||
def n_mklambda(self, node):
|
def n_mklambda(self, node):
|
||||||
self.make_function(node, is_lambda=True, codeNode=node[-2])
|
self.make_function(node, is_lambda=True, code_node=node[-2])
|
||||||
self.prune() # stop recursing
|
self.prune() # stop recursing
|
||||||
|
|
||||||
def n_list_comp(self, node):
|
def n_list_comp(self, node):
|
||||||
@@ -1563,7 +1496,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
|
|
||||||
assert 'mkfunc' == build_class[1]
|
assert 'mkfunc' == build_class[1]
|
||||||
mkfunc = build_class[1]
|
mkfunc = build_class[1]
|
||||||
if mkfunc[0] == 'kwargs':
|
if mkfunc[0] in ('kwargs', 'no_kwargs'):
|
||||||
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):
|
||||||
@@ -1608,8 +1541,15 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
subclass_info = node
|
subclass_info = node
|
||||||
subclass_code = build_class[1][0].attr
|
subclass_code = build_class[1][0].attr
|
||||||
elif not subclass_info:
|
elif not subclass_info:
|
||||||
subclass_code = build_class[1][0].attr
|
if mkfunc[0] in ('no_kwargs', 'kwargs'):
|
||||||
subclass_info = node[0]
|
subclass_code = mkfunc[1].attr
|
||||||
|
else:
|
||||||
|
subclass_code = mkfunc[0].attr
|
||||||
|
if node == 'classdefdeco2':
|
||||||
|
subclass_info = node
|
||||||
|
else:
|
||||||
|
subclass_info = node[0]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if node == 'classdefdeco2':
|
if node == 'classdefdeco2':
|
||||||
build_class = node
|
build_class = node
|
||||||
@@ -1680,7 +1620,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
self.write(')')
|
self.write(')')
|
||||||
|
|
||||||
def print_super_classes3(self, node):
|
def print_super_classes3(self, node):
|
||||||
n = len(node)-1
|
n = len(node) - 1
|
||||||
if node.kind != 'expr':
|
if node.kind != 'expr':
|
||||||
assert node[n].kind.startswith('CALL_FUNCTION')
|
assert node[n].kind.startswith('CALL_FUNCTION')
|
||||||
|
|
||||||
@@ -1764,9 +1704,17 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
# Python 3.5+ style key/value list in dict
|
# Python 3.5+ style key/value list in dict
|
||||||
kv_node = node[0]
|
kv_node = node[0]
|
||||||
l = list(kv_node)
|
l = list(kv_node)
|
||||||
|
length = len(l)
|
||||||
|
|
||||||
|
# FIXME: Parser-speed improved grammars will have BUILD_MAP
|
||||||
|
# at the end. So in the future when everything is
|
||||||
|
# complete, we can do an "assert" instead of "if".
|
||||||
|
if kv_node[-1].kind.startswith("BUILD_MAP"):
|
||||||
|
length -= 1
|
||||||
i = 0
|
i = 0
|
||||||
|
|
||||||
# Respect line breaks from source
|
# Respect line breaks from source
|
||||||
while i < len(l):
|
while i < length:
|
||||||
self.write(sep)
|
self.write(sep)
|
||||||
name = self.traverse(l[i], indent='')
|
name = self.traverse(l[i], indent='')
|
||||||
if i > 0:
|
if i > 0:
|
||||||
@@ -2196,6 +2144,15 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
entry = ('%c(*%C, %c)', 0, p2, -2)
|
entry = ('%c(*%C, %c)', 0, p2, -2)
|
||||||
elif str == '%c(%C':
|
elif str == '%c(%C':
|
||||||
entry = ('%c(*%C)', 0, (1, 100, ''))
|
entry = ('%c(*%C)', 0, (1, 100, ''))
|
||||||
|
elif self.version == 3.4:
|
||||||
|
# CALL_FUNCTION_VAR's top element of the stack contains
|
||||||
|
# the variable argument list
|
||||||
|
if v == 0:
|
||||||
|
str = '%c(*%c)'
|
||||||
|
entry = (str, 0, -2)
|
||||||
|
else:
|
||||||
|
str = '%c(*%c, %C)'
|
||||||
|
entry = (str, 0, -2, p2)
|
||||||
else:
|
else:
|
||||||
str += '*%c)'
|
str += '*%c)'
|
||||||
entry = (str, 0, p2, -2)
|
entry = (str, 0, p2, -2)
|
||||||
|
Reference in New Issue
Block a user