You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-02 16:44:46 +08:00
Token.format(), shows CONST values better...
We were not showing the proper value for None, or False. Start a unit test for Token(). I think this cleans the Token class up a little more. More work is needed for MAKE_FUNCTION... Note: Some debug stuff is commented out in make_funciton.py for upcoming work.
This commit is contained in:
20
pytest/test_token.py
Normal file
20
pytest/test_token.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from uncompyle6.scanners.tok import Token
|
||||
|
||||
def test_token():
|
||||
# Test token formatting of: LOAD_CONST None
|
||||
t = Token('LOAD_CONST', offset=0, attr=None, pattr=None, has_arg=True)
|
||||
expect = ' 0 LOAD_CONST None'
|
||||
# print(t.format())
|
||||
assert t
|
||||
assert t.format() == expect
|
||||
|
||||
# Make sure equality testing of tokens ignores offset
|
||||
t2 = Token('LOAD_CONST', offset=2, attr=None, pattr=None, has_arg=True)
|
||||
assert t2 == t
|
||||
|
||||
|
||||
# Make sure formatting of: LOAD_CONST False. We assume False is the 0th index
|
||||
# of co_consts.
|
||||
t = Token('LOAD_CONST', offset=1, attr=False, pattr=False, has_arg=True)
|
||||
expect = ' 1 LOAD_CONST 0 False'
|
||||
assert t.format() == expect
|
@@ -40,7 +40,7 @@ from collections import namedtuple
|
||||
from array import array
|
||||
|
||||
from xdis.code import iscode
|
||||
from xdis.bytecode import Bytecode, instruction_size
|
||||
from xdis.bytecode import Bytecode, instruction_size, _get_const_info
|
||||
|
||||
from uncompyle6.scanner import Token, parse_fn_counts
|
||||
import xdis
|
||||
@@ -340,6 +340,10 @@ class Scanner3(Scanner):
|
||||
# (id(const), const.co_filename, const.co_name)
|
||||
pattr = '<code_object ' + const.co_name + '>'
|
||||
else:
|
||||
argval, _ = _get_const_info(inst.arg, co.co_consts)
|
||||
# Why don't we use _ above for "pattr" rather than "const"?
|
||||
# This *is* a little hoaky, but we have to coordinate with
|
||||
# other parts like n_LOAD_CONST in pysource.py for example.
|
||||
pattr = const
|
||||
pass
|
||||
elif opname in ('MAKE_FUNCTION', 'MAKE_CLOSURE'):
|
||||
|
@@ -17,6 +17,7 @@
|
||||
|
||||
import re, sys
|
||||
from uncompyle6 import PYTHON3
|
||||
from xdis.bytecode import op_has_argument
|
||||
|
||||
if PYTHON3:
|
||||
intern = sys.intern
|
||||
@@ -35,7 +36,6 @@ class Token():
|
||||
def __init__(self, opname, attr=None, pattr=None, offset=-1,
|
||||
linestart=None, op=None, has_arg=None, opc=None):
|
||||
self.kind = intern(opname)
|
||||
self.op = op
|
||||
self.has_arg = has_arg
|
||||
self.attr = attr
|
||||
self.pattr = pattr
|
||||
@@ -44,7 +44,16 @@ class Token():
|
||||
if has_arg is False:
|
||||
self.attr = None
|
||||
self.pattr = None
|
||||
self.opc = opc
|
||||
|
||||
if opc is None:
|
||||
from xdis.std import _std_api
|
||||
self.opc = _std_api.opc
|
||||
else:
|
||||
self.opc = opc
|
||||
if op is None:
|
||||
self.op = self.opc.opmap.get(self.kind, None)
|
||||
else:
|
||||
self.op = op
|
||||
|
||||
def __eq__(self, o):
|
||||
""" '==' on kind and "pattr" attributes.
|
||||
@@ -78,7 +87,7 @@ class Token():
|
||||
if not self.has_arg:
|
||||
return "%s%s" % (prefix, offset_opname)
|
||||
argstr = "%6d " % self.attr if isinstance(self.attr, int) else (' '*7)
|
||||
if self.pattr:
|
||||
if op_has_argument(self.op, self.opc):
|
||||
pattr = self.pattr
|
||||
if self.opc:
|
||||
if self.op in self.opc.JREL_OPS:
|
||||
@@ -89,6 +98,11 @@ class Token():
|
||||
if not self.pattr.startswith('to '):
|
||||
pattr = "to " + str(self.pattr)
|
||||
pass
|
||||
elif self.op in self.opc.CONST_OPS:
|
||||
# Compare with pysource n_LOAD_CONST
|
||||
attr = self.attr
|
||||
if attr is None:
|
||||
pattr = None
|
||||
elif self.op in self.opc.hascompare:
|
||||
if isinstance(self.attr, int):
|
||||
pattr = self.opc.cmp_op[self.attr]
|
||||
|
@@ -642,9 +642,13 @@ def make_function3(self, node, is_lambda, nested=1, codeNode=None):
|
||||
if kw_dict == 'expr':
|
||||
kw_dict = kw_dict[0]
|
||||
|
||||
# FIXME: handle free_tup, annotatate_dict, and default_tup
|
||||
# FIXME: handle free_tup, annotate_dict, and default_tup
|
||||
if kw_dict:
|
||||
assert kw_dict == 'dict'
|
||||
# try:
|
||||
# assert kw_dict == 'dict'
|
||||
# except:
|
||||
# from trepan.api import debug; debug()
|
||||
defaults = [self.traverse(n, indent='') for n in kw_dict[:-2]]
|
||||
names = eval(self.traverse(kw_dict[-2]))
|
||||
assert len(defaults) == len(names)
|
||||
|
@@ -1079,6 +1079,7 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
self.write(')')
|
||||
|
||||
def n_LOAD_CONST(self, node):
|
||||
attr = node.attr
|
||||
data = node.pattr; datatype = type(data)
|
||||
if isinstance(data, float) and str(data) in frozenset(['nan', '-nan', 'inf', '-inf']):
|
||||
# float values 'nan' and 'inf' are not directly representable in Python at least
|
||||
@@ -1093,13 +1094,15 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
self.write( hex(data) )
|
||||
elif datatype is type(Ellipsis):
|
||||
self.write('...')
|
||||
elif data is None:
|
||||
elif attr is None:
|
||||
# LOAD_CONST 'None' only occurs, when None is
|
||||
# implicit eg. in 'return' w/o params
|
||||
# pass
|
||||
self.write('None')
|
||||
elif isinstance(data, tuple):
|
||||
self.pp_tuple(data)
|
||||
elif isinstance(attr, bool):
|
||||
self.write(repr(attr))
|
||||
elif self.FUTURE_UNICODE_LITERALS:
|
||||
# The FUTURE_UNICODE_LITERALS compiler flag
|
||||
# in 2.6 on change the way
|
||||
@@ -1290,8 +1293,8 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
|
||||
def n_import_from(self, node):
|
||||
relative_path_index = 0
|
||||
if self.version >= 2.5 and node[relative_path_index].pattr > 0:
|
||||
node[2].pattr = '.'*node[relative_path_index].pattr + node[2].pattr
|
||||
if self.version >= 2.5 and node[relative_path_index].attr > 0:
|
||||
node[2].pattr = '.'*node[relative_path_index].pattr + node[2].attr
|
||||
self.default(node)
|
||||
|
||||
n_import_from_star = n_import_from
|
||||
|
Reference in New Issue
Block a user