You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
LOAD_CONST->LOAD_STR for Python 3.x
This commit is contained in:
@@ -88,7 +88,7 @@ def test_grammar():
|
|||||||
COME_FROM_EXCEPT_CLAUSE
|
COME_FROM_EXCEPT_CLAUSE
|
||||||
COME_FROM_LOOP COME_FROM_WITH
|
COME_FROM_LOOP COME_FROM_WITH
|
||||||
COME_FROM_FINALLY ELSE
|
COME_FROM_FINALLY ELSE
|
||||||
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP
|
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP LOAD_STR
|
||||||
LAMBDA_MARKER
|
LAMBDA_MARKER
|
||||||
RETURN_END_IF RETURN_END_IF_LAMBDA RETURN_VALUE_LAMBDA RETURN_LAST
|
RETURN_END_IF RETURN_END_IF_LAMBDA RETURN_VALUE_LAMBDA RETURN_LAST
|
||||||
""".split())
|
""".split())
|
||||||
|
@@ -112,10 +112,9 @@ class Python3Parser(PythonParser):
|
|||||||
continues ::= continue
|
continues ::= continue
|
||||||
|
|
||||||
|
|
||||||
kwarg ::= LOAD_CONST expr
|
kwarg ::= LOAD_STR expr
|
||||||
kwargs ::= kwarg+
|
kwargs ::= kwarg+
|
||||||
|
|
||||||
|
|
||||||
classdef ::= build_class store
|
classdef ::= build_class store
|
||||||
|
|
||||||
# FIXME: we need to add these because don't detect this properly
|
# FIXME: we need to add these because don't detect this properly
|
||||||
@@ -394,11 +393,12 @@ class Python3Parser(PythonParser):
|
|||||||
def p_generator_exp3(self, args):
|
def p_generator_exp3(self, args):
|
||||||
'''
|
'''
|
||||||
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_STR
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def p_expr3(self, args):
|
def p_expr3(self, args):
|
||||||
"""
|
"""
|
||||||
|
expr ::= LOAD_STR
|
||||||
expr ::= conditionalnot
|
expr ::= conditionalnot
|
||||||
conditionalnot ::= expr jmp_true expr jump_forward_else expr COME_FROM
|
conditionalnot ::= expr jmp_true expr jump_forward_else expr COME_FROM
|
||||||
|
|
||||||
@@ -441,7 +441,7 @@ class Python3Parser(PythonParser):
|
|||||||
break
|
break
|
||||||
pass
|
pass
|
||||||
assert i < len(tokens), "build_class needs to find MAKE_FUNCTION or MAKE_CLOSURE"
|
assert i < len(tokens), "build_class needs to find MAKE_FUNCTION or MAKE_CLOSURE"
|
||||||
assert tokens[i+1].kind == 'LOAD_CONST', \
|
assert tokens[i+1].kind == 'LOAD_STR', \
|
||||||
"build_class expecting CONST after MAKE_FUNCTION/MAKE_CLOSURE"
|
"build_class expecting CONST after MAKE_FUNCTION/MAKE_CLOSURE"
|
||||||
call_fn_tok = None
|
call_fn_tok = None
|
||||||
for i in range(i, len(tokens)):
|
for i in range(i, len(tokens)):
|
||||||
@@ -515,13 +515,13 @@ class Python3Parser(PythonParser):
|
|||||||
self.add_unique_rule(rule, token.kind, uniq_param, customize)
|
self.add_unique_rule(rule, token.kind, uniq_param, customize)
|
||||||
|
|
||||||
def add_make_function_rule(self, rule, opname, attr, customize):
|
def add_make_function_rule(self, rule, opname, attr, customize):
|
||||||
"""Python 3.3 added a an addtional LOAD_CONST before MAKE_FUNCTION and
|
"""Python 3.3 added a an addtional LOAD_STR before MAKE_FUNCTION and
|
||||||
this has an effect on many rules.
|
this has an effect on many rules.
|
||||||
"""
|
"""
|
||||||
if self.version >= 3.3:
|
if self.version >= 3.3:
|
||||||
new_rule = rule % (('LOAD_CONST ') * 1)
|
new_rule = rule % (('LOAD_STR ') * 1)
|
||||||
else:
|
else:
|
||||||
new_rule = rule % (('LOAD_CONST ') * 0)
|
new_rule = rule % (('LOAD_STR ') * 0)
|
||||||
self.add_unique_rule(new_rule, opname, attr, customize)
|
self.add_unique_rule(new_rule, opname, attr, customize)
|
||||||
|
|
||||||
def customize_grammar_rules(self, tokens, customize):
|
def customize_grammar_rules(self, tokens, customize):
|
||||||
@@ -730,7 +730,7 @@ class Python3Parser(PythonParser):
|
|||||||
|
|
||||||
if opname == 'CALL_FUNCTION' and token.attr == 1:
|
if opname == 'CALL_FUNCTION' and token.attr == 1:
|
||||||
rule = """
|
rule = """
|
||||||
dict_comp ::= LOAD_DICTCOMP LOAD_CONST MAKE_FUNCTION_0 expr
|
dict_comp ::= LOAD_DICTCOMP LOAD_STR MAKE_FUNCTION_0 expr
|
||||||
GET_ITER CALL_FUNCTION_1
|
GET_ITER CALL_FUNCTION_1
|
||||||
classdefdeco1 ::= expr classdefdeco2 CALL_FUNCTION_1
|
classdefdeco1 ::= expr classdefdeco2 CALL_FUNCTION_1
|
||||||
"""
|
"""
|
||||||
@@ -849,7 +849,7 @@ class Python3Parser(PythonParser):
|
|||||||
# Note that 3.6+ doesn't do this, but we'll remove
|
# Note that 3.6+ doesn't do this, but we'll remove
|
||||||
# this rule in parse36.py
|
# this rule in parse36.py
|
||||||
rule = """
|
rule = """
|
||||||
dict_comp ::= load_closure LOAD_DICTCOMP LOAD_CONST
|
dict_comp ::= load_closure LOAD_DICTCOMP LOAD_STR
|
||||||
MAKE_CLOSURE_0 expr
|
MAKE_CLOSURE_0 expr
|
||||||
GET_ITER CALL_FUNCTION_1
|
GET_ITER CALL_FUNCTION_1
|
||||||
"""
|
"""
|
||||||
@@ -902,10 +902,10 @@ class Python3Parser(PythonParser):
|
|||||||
rule = ('mkfunc ::= %s%sload_closure LOAD_CONST %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_STR %s'
|
||||||
% (kwargs_str, 'expr ' * args_pos, opname))
|
% (kwargs_str, 'expr ' * args_pos, opname))
|
||||||
elif self.version >= 3.4:
|
elif self.version >= 3.4:
|
||||||
rule = ('mkfunc ::= %s%s load_closure LOAD_CONST LOAD_CONST %s'
|
rule = ('mkfunc ::= %s%s load_closure LOAD_CONST LOAD_STR %s'
|
||||||
% ('expr ' * args_pos, kwargs_str, opname))
|
% ('expr ' * args_pos, kwargs_str, opname))
|
||||||
|
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
@@ -933,17 +933,17 @@ class Python3Parser(PythonParser):
|
|||||||
rule = ('mklambda ::= %s%s%s%s' %
|
rule = ('mklambda ::= %s%s%s%s' %
|
||||||
('expr ' * stack_count,
|
('expr ' * stack_count,
|
||||||
'load_closure ' * closure,
|
'load_closure ' * closure,
|
||||||
'BUILD_TUPLE_1 LOAD_LAMBDA LOAD_CONST ',
|
'BUILD_TUPLE_1 LOAD_LAMBDA LOAD_STR ',
|
||||||
opname))
|
opname))
|
||||||
else:
|
else:
|
||||||
rule = ('mklambda ::= %s%s%s' %
|
rule = ('mklambda ::= %s%s%s' %
|
||||||
('load_closure ' * closure,
|
('load_closure ' * closure,
|
||||||
'LOAD_LAMBDA LOAD_CONST ',
|
'LOAD_LAMBDA LOAD_STR ',
|
||||||
opname))
|
opname))
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
rule = ('mklambda ::= %sLOAD_LAMBDA LOAD_CONST %s' %
|
rule = ('mklambda ::= %sLOAD_LAMBDA LOAD_STR %s' %
|
||||||
(('expr ' * stack_count), opname))
|
(('expr ' * stack_count), opname))
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
|
|
||||||
@@ -951,7 +951,7 @@ class Python3Parser(PythonParser):
|
|||||||
rule = ('mkfunc ::= %s%s%s%s' %
|
rule = ('mkfunc ::= %s%s%s%s' %
|
||||||
('expr ' * stack_count,
|
('expr ' * stack_count,
|
||||||
'load_closure ' * closure,
|
'load_closure ' * closure,
|
||||||
'LOAD_CONST ' * 2,
|
'LOAD_CONST LOAD_STR ',
|
||||||
opname))
|
opname))
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
|
|
||||||
@@ -1033,17 +1033,17 @@ class Python3Parser(PythonParser):
|
|||||||
elif self.version == 3.3:
|
elif self.version == 3.3:
|
||||||
# positional args after keyword args
|
# positional args after keyword args
|
||||||
rule = ('mkfunc ::= %s %s%s%s' %
|
rule = ('mkfunc ::= %s %s%s%s' %
|
||||||
(kwargs, 'pos_arg ' * args_pos, 'LOAD_CONST '*2,
|
(kwargs, 'pos_arg ' * args_pos, 'LOAD_CONST LOAD_STR ',
|
||||||
opname))
|
opname))
|
||||||
elif self.version > 3.5:
|
elif self.version > 3.5:
|
||||||
# positional args before keyword args
|
# positional args before keyword args
|
||||||
rule = ('mkfunc ::= %s%s %s%s' %
|
rule = ('mkfunc ::= %s%s %s%s' %
|
||||||
('pos_arg ' * args_pos, kwargs, 'LOAD_CONST '*2,
|
('pos_arg ' * args_pos, kwargs, 'LOAD_CONST LOAD_STR ',
|
||||||
opname))
|
opname))
|
||||||
elif self.version > 3.3:
|
elif self.version > 3.3:
|
||||||
# positional args before keyword args
|
# positional args before keyword args
|
||||||
rule = ('mkfunc ::= %s%s %s%s' %
|
rule = ('mkfunc ::= %s%s %s%s' %
|
||||||
('pos_arg ' * args_pos, kwargs, 'LOAD_CONST '*2,
|
('pos_arg ' * args_pos, kwargs, 'LOAD_CONST LOAD_STR ',
|
||||||
opname))
|
opname))
|
||||||
else:
|
else:
|
||||||
rule = ('mkfunc ::= %s%sexpr %s' %
|
rule = ('mkfunc ::= %s%sexpr %s' %
|
||||||
@@ -1052,22 +1052,22 @@ class Python3Parser(PythonParser):
|
|||||||
|
|
||||||
if opname.startswith('MAKE_FUNCTION_A'):
|
if opname.startswith('MAKE_FUNCTION_A'):
|
||||||
if self.version >= 3.6:
|
if self.version >= 3.6:
|
||||||
rule = ('mkfunc_annotate ::= %s%sannotate_tuple LOAD_CONST LOAD_CONST %s' %
|
rule = ('mkfunc_annotate ::= %s%sannotate_tuple LOAD_CONST LOAD_STR %s' %
|
||||||
(('pos_arg ' * (args_pos)),
|
(('pos_arg ' * (args_pos)),
|
||||||
('call ' * (annotate_args-1)), opname))
|
('call ' * (annotate_args-1)), opname))
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
rule = ('mkfunc_annotate ::= %s%sannotate_tuple LOAD_CONST LOAD_CONST %s' %
|
rule = ('mkfunc_annotate ::= %s%sannotate_tuple LOAD_CONST LOAD_STR %s' %
|
||||||
(('pos_arg ' * (args_pos)),
|
(('pos_arg ' * (args_pos)),
|
||||||
('annotate_arg ' * (annotate_args-1)), opname))
|
('annotate_arg ' * (annotate_args-1)), opname))
|
||||||
if self.version >= 3.3:
|
if self.version >= 3.3:
|
||||||
# Normally we remove EXTENDED_ARG from the opcodes, but in the case of
|
# Normally we remove EXTENDED_ARG from the opcodes, but in the case of
|
||||||
# annotated functions can use the EXTENDED_ARG tuple to signal we have an annotated function.
|
# annotated functions can use the EXTENDED_ARG tuple to signal we have an annotated function.
|
||||||
# Yes this is a little hacky
|
# Yes this is a little hacky
|
||||||
rule = ('mkfunc_annotate ::= %s%sannotate_tuple LOAD_CONST LOAD_CONST EXTENDED_ARG %s' %
|
rule = ('mkfunc_annotate ::= %s%sannotate_tuple LOAD_CONST LOAD_STR EXTENDED_ARG %s' %
|
||||||
(('pos_arg ' * (args_pos)),
|
(('pos_arg ' * (args_pos)),
|
||||||
('call ' * (annotate_args-1)), opname))
|
('call ' * (annotate_args-1)), opname))
|
||||||
self.add_unique_rule(rule, opname, token.attr, customize)
|
self.add_unique_rule(rule, opname, token.attr, customize)
|
||||||
rule = ('mkfunc_annotate ::= %s%sannotate_tuple LOAD_CONST LOAD_CONST EXTENDED_ARG %s' %
|
rule = ('mkfunc_annotate ::= %s%sannotate_tuple LOAD_CONST LOAD_STR EXTENDED_ARG %s' %
|
||||||
(('pos_arg ' * (args_pos)),
|
(('pos_arg ' * (args_pos)),
|
||||||
('annotate_arg ' * (annotate_args-1)), opname))
|
('annotate_arg ' * (annotate_args-1)), opname))
|
||||||
else:
|
else:
|
||||||
@@ -1143,7 +1143,8 @@ class Python3Parser(PythonParser):
|
|||||||
self.check_reduce['while1elsestmt'] = 'noAST'
|
self.check_reduce['while1elsestmt'] = 'noAST'
|
||||||
self.check_reduce['ifelsestmt'] = 'AST'
|
self.check_reduce['ifelsestmt'] = 'AST'
|
||||||
self.check_reduce['annotate_tuple'] = 'noAST'
|
self.check_reduce['annotate_tuple'] = 'noAST'
|
||||||
self.check_reduce['kwarg'] = 'noAST'
|
if not PYTHON3:
|
||||||
|
self.check_reduce['kwarg'] = 'noAST'
|
||||||
if self.version < 3.6:
|
if self.version < 3.6:
|
||||||
# 3.6+ can remove a JUMP_FORWARD which messes up our testing here
|
# 3.6+ can remove a JUMP_FORWARD which messes up our testing here
|
||||||
self.check_reduce['try_except'] = 'AST'
|
self.check_reduce['try_except'] = 'AST'
|
||||||
@@ -1160,10 +1161,7 @@ class Python3Parser(PythonParser):
|
|||||||
return not isinstance(tokens[first].attr, tuple)
|
return not isinstance(tokens[first].attr, tuple)
|
||||||
elif lhs == 'kwarg':
|
elif lhs == 'kwarg':
|
||||||
arg = tokens[first].attr
|
arg = tokens[first].attr
|
||||||
if PYTHON3:
|
return not (isinstance(arg, str) or isinstance(arg, unicode))
|
||||||
return not isinstance(arg, str)
|
|
||||||
else:
|
|
||||||
return not (isinstance(arg, str) or isinstance(arg, unicode))
|
|
||||||
elif lhs == 'while1elsestmt':
|
elif lhs == 'while1elsestmt':
|
||||||
|
|
||||||
n = len(tokens)
|
n = len(tokens)
|
||||||
|
@@ -202,14 +202,14 @@ class Python36Parser(Python35Parser):
|
|||||||
if 'LOAD_DICTCOMP' in self.seen_ops:
|
if 'LOAD_DICTCOMP' in self.seen_ops:
|
||||||
# Is there something general going on here?
|
# Is there something general going on here?
|
||||||
rule = """
|
rule = """
|
||||||
dict_comp ::= load_closure LOAD_DICTCOMP LOAD_CONST
|
dict_comp ::= load_closure LOAD_DICTCOMP LOAD_STR
|
||||||
MAKE_FUNCTION_8 expr
|
MAKE_FUNCTION_8 expr
|
||||||
GET_ITER CALL_FUNCTION_1
|
GET_ITER CALL_FUNCTION_1
|
||||||
"""
|
"""
|
||||||
self.addRule(rule, nop_func)
|
self.addRule(rule, nop_func)
|
||||||
elif 'LOAD_SETCOMP' in self.seen_ops:
|
elif 'LOAD_SETCOMP' in self.seen_ops:
|
||||||
rule = """
|
rule = """
|
||||||
set_comp ::= load_closure LOAD_SETCOMP LOAD_CONST
|
set_comp ::= load_closure LOAD_SETCOMP LOAD_STR
|
||||||
MAKE_FUNCTION_8 expr
|
MAKE_FUNCTION_8 expr
|
||||||
GET_ITER CALL_FUNCTION_1
|
GET_ITER CALL_FUNCTION_1
|
||||||
"""
|
"""
|
||||||
|
@@ -310,6 +310,8 @@ class Scanner3(Scanner):
|
|||||||
# pattr = 'code_object @ 0x%x %s->%s' %\
|
# pattr = 'code_object @ 0x%x %s->%s' %\
|
||||||
# (id(const), const.co_filename, const.co_name)
|
# (id(const), const.co_filename, const.co_name)
|
||||||
pattr = '<code_object ' + const.co_name + '>'
|
pattr = '<code_object ' + const.co_name + '>'
|
||||||
|
elif isinstance(const, str):
|
||||||
|
opname = 'LOAD_STR'
|
||||||
else:
|
else:
|
||||||
if isinstance(inst.arg, int) and inst.arg < len(co.co_consts):
|
if isinstance(inst.arg, int) and inst.arg < len(co.co_consts):
|
||||||
argval, _ = _get_const_info(inst.arg, co.co_consts)
|
argval, _ = _get_const_info(inst.arg, co.co_consts)
|
||||||
|
@@ -131,7 +131,7 @@ PASS = SyntaxTree('stmts',
|
|||||||
ASSIGN_DOC_STRING = lambda doc_string: \
|
ASSIGN_DOC_STRING = lambda doc_string: \
|
||||||
SyntaxTree('stmt',
|
SyntaxTree('stmt',
|
||||||
[ SyntaxTree('assign',
|
[ SyntaxTree('assign',
|
||||||
[ SyntaxTree('expr', [ Token('LOAD_CONST', pattr=doc_string) ]),
|
[ SyntaxTree('expr', [ Token('LOAD_STR', pattr=doc_string) ]),
|
||||||
SyntaxTree('store', [ Token('STORE_NAME', pattr='__doc__')])
|
SyntaxTree('store', [ Token('STORE_NAME', pattr='__doc__')])
|
||||||
])])
|
])])
|
||||||
|
|
||||||
@@ -221,8 +221,9 @@ TABLE_DIRECT = {
|
|||||||
'IMPORT_FROM': ( '%{pattr}', ),
|
'IMPORT_FROM': ( '%{pattr}', ),
|
||||||
'attribute': ( '%c.%[1]{pattr}',
|
'attribute': ( '%c.%[1]{pattr}',
|
||||||
(0, 'expr')),
|
(0, 'expr')),
|
||||||
'LOAD_FAST': ( '%{pattr}', ),
|
'LOAD_STR': ( '%{pattr}', ),
|
||||||
'LOAD_NAME': ( '%{pattr}', ),
|
'LOAD_FAST': ( '%{pattr}', ),
|
||||||
|
'LOAD_NAME': ( '%{pattr}', ),
|
||||||
'LOAD_CLASSNAME': ( '%{pattr}', ),
|
'LOAD_CLASSNAME': ( '%{pattr}', ),
|
||||||
'LOAD_GLOBAL': ( '%{pattr}', ),
|
'LOAD_GLOBAL': ( '%{pattr}', ),
|
||||||
'LOAD_DEREF': ( '%{pattr}', ),
|
'LOAD_DEREF': ( '%{pattr}', ),
|
||||||
@@ -317,7 +318,7 @@ TABLE_DIRECT = {
|
|||||||
'mkfuncdeco0': ( '%|def %c\n', 0),
|
'mkfuncdeco0': ( '%|def %c\n', 0),
|
||||||
'classdefdeco': ( '\n\n%c', 0),
|
'classdefdeco': ( '\n\n%c', 0),
|
||||||
'classdefdeco1': ( '%|@%c\n%c', 0, 1),
|
'classdefdeco1': ( '%|@%c\n%c', 0, 1),
|
||||||
'kwarg': ( '%[0]{pattr}=%c', 1),
|
'kwarg': ( '%[0]{attr}=%c', 1),
|
||||||
'kwargs': ( '%D', (0, maxint, ', ') ),
|
'kwargs': ( '%D', (0, maxint, ', ') ),
|
||||||
'kwargs1': ( '%D', (0, maxint, ', ') ),
|
'kwargs1': ( '%D', (0, maxint, ', ') ),
|
||||||
|
|
||||||
|
@@ -62,11 +62,11 @@ def customize_for_version3(self, version):
|
|||||||
subclass_info = None
|
subclass_info = None
|
||||||
if node == 'classdefdeco2':
|
if node == 'classdefdeco2':
|
||||||
if self.version >= 3.6:
|
if self.version >= 3.6:
|
||||||
class_name = node[1][1].pattr
|
class_name = node[1][1].attr
|
||||||
elif self.version <= 3.3:
|
elif self.version <= 3.3:
|
||||||
class_name = node[2][0].pattr
|
class_name = node[2][0].attr
|
||||||
else:
|
else:
|
||||||
class_name = node[1][2].pattr
|
class_name = node[1][2].attr
|
||||||
build_class = node
|
build_class = node
|
||||||
else:
|
else:
|
||||||
build_class = node[0]
|
build_class = node[0]
|
||||||
|
@@ -77,7 +77,7 @@ def customize_for_version36(self, version):
|
|||||||
self.call36_tuple(n)
|
self.call36_tuple(n)
|
||||||
first = 1
|
first = 1
|
||||||
sep = ', *'
|
sep = ', *'
|
||||||
elif n == 'LOAD_CONST':
|
elif n == 'LOAD_STR':
|
||||||
value = self.format_pos_args(n)
|
value = self.format_pos_args(n)
|
||||||
self.f.write(value)
|
self.f.write(value)
|
||||||
first = 1
|
first = 1
|
||||||
@@ -401,7 +401,7 @@ def customize_for_version36(self, version):
|
|||||||
self.n_except_suite_finalize = n_except_suite_finalize
|
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] in ('LOAD_STR', 'LOAD_CONST'):
|
||||||
value = node[0].attr
|
value = node[0].attr
|
||||||
if isinstance(value, tuple):
|
if isinstance(value, tuple):
|
||||||
self.write(node[0].attr)
|
self.write(node[0].attr)
|
||||||
@@ -415,7 +415,7 @@ def customize_for_version36(self, version):
|
|||||||
def n_formatted_value_attr(node):
|
def n_formatted_value_attr(node):
|
||||||
f_conversion(node)
|
f_conversion(node)
|
||||||
fmt_node = node.data[3]
|
fmt_node = node.data[3]
|
||||||
if fmt_node == 'expr' and fmt_node[0] == 'LOAD_CONST':
|
if fmt_node == 'expr' and fmt_node[0] == 'LOAD_STR':
|
||||||
node.string = escape_format(fmt_node[0].attr)
|
node.string = escape_format(fmt_node[0].attr)
|
||||||
else:
|
else:
|
||||||
node.string = fmt_node
|
node.string = fmt_node
|
||||||
@@ -424,7 +424,7 @@ def customize_for_version36(self, version):
|
|||||||
|
|
||||||
def f_conversion(node):
|
def f_conversion(node):
|
||||||
fmt_node = node.data[1]
|
fmt_node = node.data[1]
|
||||||
if fmt_node == 'expr' and fmt_node[0] == 'LOAD_CONST':
|
if fmt_node == 'expr' and fmt_node[0] == 'LOAD_STR':
|
||||||
data = fmt_node[0].attr
|
data = fmt_node[0].attr
|
||||||
else:
|
else:
|
||||||
data = fmt_node.attr
|
data = fmt_node.attr
|
||||||
@@ -482,11 +482,11 @@ def customize_for_version36(self, version):
|
|||||||
else:
|
else:
|
||||||
# {{ and }} in Python source-code format strings mean
|
# {{ and }} in Python source-code format strings mean
|
||||||
# { and } respectively. But only when *not* part of a
|
# { and } respectively. But only when *not* part of a
|
||||||
# formatted value. However in the LOAD_CONST
|
# formatted value. However in the LOAD_STR
|
||||||
# bytecode, the escaping of the braces has been
|
# bytecode, the escaping of the braces has been
|
||||||
# removed. So we need to put back the braces escaping in
|
# removed. So we need to put back the braces escaping in
|
||||||
# reconstructing the source.
|
# reconstructing the source.
|
||||||
assert expr[0] == 'LOAD_CONST'
|
assert expr[0] == 'LOAD_STR'
|
||||||
value = value.replace("{", "{{").replace("}", "}}")
|
value = value.replace("{", "{{").replace("}", "}}")
|
||||||
|
|
||||||
# Remove leading quotes
|
# Remove leading quotes
|
||||||
|
@@ -421,6 +421,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
pass
|
pass
|
||||||
self.set_pos_info(node, start, len(self.f.getvalue()))
|
self.set_pos_info(node, start, len(self.f.getvalue()))
|
||||||
self.prune()
|
self.prune()
|
||||||
|
n_LOAD_STR = n_LOAD_CONST
|
||||||
|
|
||||||
def n_exec_stmt(self, node):
|
def n_exec_stmt(self, node):
|
||||||
"""
|
"""
|
||||||
|
Reference in New Issue
Block a user