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:
rocky
2018-02-28 22:05:12 -05:00
parent 1fe432585e
commit 413df51dfa
5 changed files with 53 additions and 8 deletions

20
pytest/test_token.py Normal file
View 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

View File

@@ -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'):

View File

@@ -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]

View File

@@ -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)

View File

@@ -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