Use xdis for code, magics, and marshal

This commit is contained in:
rocky
2016-05-27 18:21:32 -04:00
parent eebe8249a8
commit 4398b5b2e0
19 changed files with 16 additions and 648 deletions

View File

@@ -36,7 +36,8 @@ entry_points={
'pydisassemble=uncompyle6.bin.pydisassemble:main', 'pydisassemble=uncompyle6.bin.pydisassemble:main',
]} ]}
ftp_url = None ftp_url = None
install_requires = ['spark-parser >= 1.2.1'] install_requires = ['spark-parser >= 1.2.1',
'xdis >= 1.0.1']
license = 'MIT' license = 'MIT'
mailing_list = 'python-debugger@googlegroups.com' mailing_list = 'python-debugger@googlegroups.com'
modname = 'uncompyle6' modname = 'uncompyle6'

View File

@@ -18,7 +18,6 @@ def test_if_in_for():
scan.build_prev_op(n) scan.build_prev_op(n)
fjt = scan.find_jump_targets() fjt = scan.find_jump_targets()
assert {15: [3], 69: [66], 63: [18]} == fjt assert {15: [3], 69: [66], 63: [18]} == fjt
print(scan.structs)
assert scan.structs == \ assert scan.structs == \
[{'start': 0, 'end': 72, 'type': 'root'}, [{'start': 0, 'end': 72, 'type': 'root'},
{'start': 18, 'end': 66, 'type': 'if-then'}, {'start': 18, 'end': 66, 'type': 'if-then'},

View File

@@ -1,13 +0,0 @@
import os, sys
from uncompyle6.load import load_file, check_object_path, load_module
def test_load():
"""Basic test of load_file, check_object_path and load_module"""
co = load_file(__file__)
obj_path = check_object_path(__file__)
if os.path.exists(obj_path):
version, timestamp, magic_int, co2 = load_module(obj_path)
assert sys.version[0:3] == str(version)
assert co == co2
else:
assert True, "Skipped because we can't find %s" % obj_path

View File

@@ -1,28 +0,0 @@
#!/usr/bin/env python
import os.path
from uncompyle6.load import load_module
def get_srcdir():
filename = os.path.normcase(os.path.dirname(os.path.abspath(__file__)))
return os.path.realpath(filename)
srcdir = get_srcdir()
def test_load_module():
"""Tests uncompile6.load.load_module"""
# We deliberately pick a bytecode that we aren't likely to be running against
mod_file = os.path.join(get_srcdir(), '..', 'test', 'bytecode_2.5',
'02_complex.pyc')
version, timestamp, magic_int, co = load_module(mod_file)
assert version == 2.5, "Should have picked up Python version properly"
assert co.co_consts == (5j, None), "Code should have a complex constant"
mod_file = os.path.join(get_srcdir(), '..', 'test', 'bytecode_3.3',
'06_frozenset.pyc')
version, timestamp, magic_int, co = load_module(mod_file)
print(co.co_consts)
expect = (0, None, 'attlist', 'linktype', 'link', 'element', 'Yep',
frozenset({'linktype', 'attlist', 'element', 'link'}))
assert co.co_consts == expect, "Should handle frozenset"

View File

@@ -45,10 +45,8 @@ sys.setrecursionlimit(5000)
import uncompyle6.semantics.pysource import uncompyle6.semantics.pysource
import uncompyle6.semantics.fragments import uncompyle6.semantics.fragments
import uncompyle6.load
# Export some functions # Export some functions
from uncompyle6.load import load_module, load_file
from uncompyle6.main import uncompyle_file from uncompyle6.main import uncompyle_file
# Conventience functions so you can say: # Conventience functions so you can say:

View File

@@ -6,7 +6,6 @@
from __future__ import print_function from __future__ import print_function
import sys, os, getopt import sys, os, getopt
from uncompyle6 import check_python_version
from uncompyle6.disas import disassemble_file from uncompyle6.disas import disassemble_file
from uncompyle6.version import VERSION from uncompyle6.version import VERSION
@@ -35,8 +34,6 @@ def main():
Usage_short = """usage: %s FILE... Usage_short = """usage: %s FILE...
Type -h for for full help.""" % program Type -h for for full help.""" % program
check_python_version(program)
use_uncompyle6_format = False use_uncompyle6_format = False
if len(sys.argv) == 1: if len(sys.argv) == 1:

View File

@@ -1,53 +0,0 @@
import inspect
class Code3:
"""Class for a Python3 code object used when a Python interpreter less than 3 is
working on Python3 bytecode
"""
def __init__(self, co_argcount, co_kwonlyargcount,co_nlocals, co_stacksize, co_flags, co_code,
co_consts, co_names, co_varnames, co_filename, co_name,
co_firstlineno, co_lnotab, co_freevars, co_cellvars):
self.co_argcount = co_argcount
self.co_kwonlyargcount = co_kwonlyargcount
self.co_nlocals = co_nlocals
self.co_stacksize = co_stacksize
self.co_flags = co_flags
self.co_code = co_code
self.co_consts = co_consts
self.co_names = co_names
self.co_varnames = co_varnames
self.co_filename = co_filename
self.co_name = co_name
self.co_firstlineno = co_firstlineno
self.co_lnotab = co_lnotab
self.co_freevars = co_freevars
self.co_cellvars = co_cellvars
class Code2:
"""Class for a Python2 code object used when a Python interpreter less than 3 is
working on Python3 bytecode
"""
def __init__(self, co_argcount, co_kwonlyargcount,co_nlocals, co_stacksize, co_flags, co_code,
co_consts, co_names, co_varnames, co_filename, co_name,
co_firstlineno, co_lnotab, co_freevars, co_cellvars):
self.co_argcount = co_argcount
self.co_kwonlyargcount = co_kwonlyargcount
self.co_nlocals = co_nlocals
self.co_stacksize = co_stacksize
self.co_flags = co_flags
self.co_code = co_code
self.co_consts = co_consts
self.co_names = co_names
self.co_varnames = co_varnames
self.co_filename = co_filename
self.co_name = co_name
self.co_firstlineno = co_firstlineno
self.co_lnotab = co_lnotab
self.co_freevars = co_freevars
self.co_cellvars = co_cellvars
def iscode(obj):
"""A replacement for inspect.iscode() which we can't used because we may be
using a different version of Python than the version of Python used
in creating the byte-compiled objects. Here, he code types may mismatch.
"""
return inspect.iscode(obj) or isinstance(obj, Code3)

View File

@@ -22,8 +22,8 @@ import os, sys
from collections import deque from collections import deque
import uncompyle6 import uncompyle6
from uncompyle6.code import iscode from xdis.code import iscode
from uncompyle6.load import check_object_path, load_module from xdis.load import check_object_path, load_module
from uncompyle6.scanner import get_scanner from uncompyle6.scanner import get_scanner
def disco(version, co, out=None, use_uncompyle6_format=False): def disco(version, co, out=None, use_uncompyle6_format=False):
@@ -57,7 +57,7 @@ def disco_loop(disasm, queue, real_out, use_uncompyle6_format):
print('\n# %s line %d of %s' % print('\n# %s line %d of %s' %
(co.co_name, co.co_firstlineno, co.co_filename), (co.co_name, co.co_firstlineno, co.co_filename),
file=real_out) file=real_out)
tokens, customize = disasm(co, use_uncompyle6_format) tokens, customize = disasm(co)
for t in tokens: for t in tokens:
if iscode(t.pattr): if iscode(t.pattr):
queue.append(t.pattr) queue.append(t.pattr)

View File

@@ -1,117 +0,0 @@
# Copyright (c) 2015 by Rocky Bernstein
# Copyright (c) 2000 by hartmut Goebel <h.goebel@crazy-compilers.com>
from __future__ import print_function
import imp, marshal, os, py_compile, sys, tempfile
from struct import unpack
import uncompyle6.marsh
from uncompyle6 import PYTHON3
from uncompyle6 import magics
def check_object_path(path):
if path.endswith(".py"):
try:
import importlib
return importlib.util.cache_from_source(path,
optimization='')
except:
try:
import imp
imp.cache_from_source(path, debug_override=False)
except:
pass
pass
basename = os.path.basename(path)[0:-3]
spath = path if PYTHON3 else path.decode('utf-8')
path = tempfile.mkstemp(prefix=basename + '-',
suffix='.pyc', text=False)[1]
py_compile.compile(spath, cfile=path, doraise=True)
if not path.endswith(".pyc") and not path.endswith(".pyo"):
raise ValueError("path %s must point to a .py or .pyc file\n" %
path)
return path
def load_file(filename):
"""
load a Python source file and compile it to byte-code
_load_file(filename: string): code_object
filename: name of file containing Python source code
(normally a .py)
code_object: code_object compiled from this source code
This function does NOT write any file!
"""
with open(filename, 'rb') as fp:
source = fp.read().decode('utf-8') + '\n'
try:
co = compile(source, filename, 'exec', dont_inherit=True)
except SyntaxError:
print('>>Syntax error in %s\n' % filename, file= sys.stderr)
raise
pass
return co
def load_module(filename, code_objects={}):
"""
load a module without importing it.
load_module(filename: string): version, magic_int, code_object
filename: name of file containing Python byte-code object
(normally a .pyc)
code_object: code_object from this file
version: Python major/minor value e.g. 2.7. or 3.4
magic_int: more specific than version. The actual byte code version of the
code object
"""
with open(filename, 'rb') as fp:
magic = fp.read(4)
try:
version = float(magics.versions[magic])
except KeyError:
if len(magic) >= 2:
raise ImportError("Unknown magic number %s in %s" %
(ord(magic[0])+256*ord(magic[1]), filename))
else:
raise ImportError("Bad magic number: '%s'" % magic)
if not (2.5 <= version <= 2.7) and not (3.2 <= version <= 3.5):
raise ImportError("This is a Python %s file! Only "
"Python 2.5 to 2.7 and 3.2 to 3.5 files are supported."
% version)
# print version
ts = fp.read(4)
timestamp = unpack("I", ts)[0]
magic_int = magics.magic2int(magic)
my_magic_int = magics.magic2int(imp.get_magic())
# Note: a higher magic number doesn't necessarily mean a later
# release. At Python 3.0 the magic number decreased
# significantly. Hence the range below. Also note inclusion of
# the size info, occurred within a Python major/minor
# release. Hence the test on the magic value rather than
# PYTHON_VERSION, although PYTHON_VERSION would probably work.
if 3200 <= magic_int < 20121:
fp.read(4) # size mod 2**32
if my_magic_int == magic_int:
bytecode = fp.read()
co = marshal.loads(bytecode)
else:
co = uncompyle6.marsh.load_code(fp, magic_int, code_objects)
pass
return version, timestamp, magic_int, co
if __name__ == '__main__':
co = load_file(__file__)
obj_path = check_object_path(__file__)
version, timestamp, magic_int, co2 = load_module(obj_path)
print("version", version, "magic int", magic_int)
import datetime
print(datetime.datetime.fromtimestamp(timestamp))
if version < 3.5:
assert co == co2

View File

@@ -1,110 +0,0 @@
from __future__ import print_function
import imp, struct, sys
def __build_magic(magic):
if (sys.version_info >= (3, 0)):
return struct.pack('Hcc', magic, bytes('\r', 'utf-8'), bytes('\n', 'utf-8'))
else:
return struct.pack('Hcc', magic, '\r', '\n')
def magic2int(magic):
return struct.unpack('Hcc', magic)[0]
PYTHON_MAGIC_INT = magic2int(imp.get_magic())
by_magic = {}
by_version = {}
def __by_version(magics):
for m, v in list(magics.items()):
by_magic[m] = v
by_version[v] = m
return by_version
versions = {
# taken from from Python/import.c
# or importlib/_bootstrap.py
# magic, version
__build_magic(20121): '1.5', # 1.5, 1.5.1, 1.5.2
__build_magic(50428): '1.6', # 1.6
__build_magic(50823): '2.0', # 2.0, 2.0.1
__build_magic(60202): '2.1', # 2.1, 2.1.1, 2.1.2
__build_magic(60717): '2.2', # 2.2
__build_magic(62011): '2.3', # 2.3a0
__build_magic(62021): '2.3', # 2.3a0
__build_magic(62041): '2.4', # 2.4a0
__build_magic(62051): '2.4', # 2.4a3
__build_magic(62061): '2.4', # 2.4b1
__build_magic(62071): '2.5', # 2.5a0
__build_magic(62081): '2.5', # 2.5a0 (ast-branch)
__build_magic(62091): '2.5', # 2.5a0 (with)
__build_magic(62092): '2.5', # 2.5a0 (changed WITH_CLEANUP opcode)
__build_magic(62101): '2.5', # 2.5b3 (fix wrong code: for x, in ...)
__build_magic(62111): '2.5', # 2.5b3 (fix wrong code: x += yield)
__build_magic(62121): '2.5', # 2.5c1 (fix wrong lnotab with for loops and
# storing constants that should have been removed
__build_magic(62131): '2.5', # 2.5c2 (fix wrong code: for x, in ... in listcomp/genexp)
__build_magic(62151): '2.6', # 2.6a0 (peephole optimizations & STORE_MAP)
__build_magic(62161): '2.6', # 2.6a1 (WITH_CLEANUP optimization)
__build_magic(62171): '2.7', # 2.7a0 (optimize list comprehensions/change LIST_APPEND)
__build_magic(62181): '2.7', # 2.7a0 (optimize conditional branches:
# introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE)
__build_magic(62191): '2.7', # 2.7a0 (introduce SETUP_WITH)
__build_magic(62201): '2.7', # 2.7a0 (introduce BUILD_SET)
__build_magic(62211): '2.7', # 2.7a0 (introduce MAP_ADD and SET_ADD)
__build_magic(62218): '2.7', # 2.7 pypy?
__build_magic(3000): '3.0', # 3.000
__build_magic(3010): '3.0', # 3.000 (removed UNARY_CONVERT)
__build_magic(3020): '3.0', # 3.000 (added BUILD_SET)
__build_magic(3030): '3.0', # 3.000 (added keyword-only parameters)
__build_magic(3040): '3.0', # 3.000 (added signature annotations)
__build_magic(3050): '3.0', # 3.000 (print becomes a function)
__build_magic(3060): '3.0', # 3.000 (PEP 3115 metaclass syntax)
__build_magic(3061): '3.0', # 3.000 (string literals become unicode)
__build_magic(3071): '3.0', # 3.000 (PEP 3109 raise changes)
__build_magic(3081): '3.0', # 3.000 (PEP 3137 make __file__ and __name__ unicode)
__build_magic(3091): '3.0', # 3.000 (kill str8 interning)
__build_magic(3101): '3.0', # 3.000 (merge from 2.6a0, see 62151)
__build_magic(3103): '3.0', # 3.000 (__file__ points to source file)
__build_magic(3111): '3.0', # 3.0a4 (WITH_CLEANUP optimization).
__build_magic(3131): '3.0', # 3.0a5 (lexical exception stacking, including POP_EXCEPT)
__build_magic(3141): '3.1', # 3.1a0 (optimize list, set and dict comprehensions)
__build_magic(3151): '3.1', # 3.1a0 (optimize conditional branches)
__build_magic(3160): '3.2', # 3.2a0 (add SETUP_WITH)
__build_magic(3170): '3.2', # 3.2a1 (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR)
__build_magic(3180): '3.2', # 3.2a2 (add DELETE_DEREF)
__build_magic(3190): '3.3', # 3.3a0 3190 __class__ super closure changed
__build_magic(3100): '3.3', # 3.3a0 3200 (__qualname__ added)
__build_magic(3210): '3.3', # 3210 (added size modulo 2**32 to the pyc header)
__build_magic(3220): '3.3', # 3.3a1 3220 (changed PEP 380 implementation)
__build_magic(3230): '3.3', # 3.3a4 3230 (revert changes to implicit __class__ closure)
__build_magic(3250): '3.4', # 3.4a1 3250 (evaluate positional default arg
# keyword-only defaults)
__build_magic(3260): '3.4', # 3.4a1 3260 (add LOAD_CLASSDEREF;
# allow locals of class to override free vars)
__build_magic(3270): '3.4', # 3.4a1 3270 (various tweaks to the __class__ closure)
__build_magic(3280): '3.4', # 3.4a1 3280 (remove implicit class argument)
__build_magic(3290): '3.4', # 3.4a4 3290 (changes to __qualname__ computation)
__build_magic(3300): '3.4', # 3.4a4 3300 (more changes to __qualname__ computation)
__build_magic(3310): '3.4', # 3.4rc2 3310 (alter __qualname__ computation)
__build_magic(3350): '3.5', # 3.5.0
}
magics = __by_version(versions)
def __show(text, magic):
print(text, struct.unpack('BBBB', magic), struct.unpack('HBB', magic))
def test():
magic_20 = magics['2.0']
current = imp.get_magic()
magic_current = by_magic[ current ]
print(type(magic_20), len(magic_20), repr(magic_20))
print()
print('This Python interpreter has version', magic_current)
print('Magic code: ', PYTHON_MAGIC_INT)
print(type(magic_20), len(magic_20), repr(magic_20))
if __name__ == '__main__':
test()

View File

@@ -2,12 +2,12 @@ from __future__ import print_function
import datetime, os, sys import datetime, os, sys
from uncompyle6 import verify, PYTHON_VERSION from uncompyle6 import verify, PYTHON_VERSION
from uncompyle6.code import iscode from xdis.code import iscode
from uncompyle6.disas import check_object_path from uncompyle6.disas import check_object_path
from uncompyle6.semantics import pysource from uncompyle6.semantics import pysource
from uncompyle6.parser import ParserError from uncompyle6.parser import ParserError
from uncompyle6.load import load_module from xdis.load import load_module
def uncompyle(version, co, out=None, showasm=False, showast=False, def uncompyle(version, co, out=None, showasm=False, showast=False,
timestamp=None, showgrammar=False, code_objects={}): timestamp=None, showgrammar=False, code_objects={}):

View File

@@ -1,306 +0,0 @@
"""
CPython magic- and version- independent marshal routines
This is needed when the bytecode extracted is from
a different version than the currently-running Python.
When the two are the same, you can simply use Python's built-in marshal.loads()
to produce a code object
"""
# Copyright (c) 1999 John Aycock
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
# Copyright (c) 2015 by Rocky Bernstein
from __future__ import print_function
import sys, types
from struct import unpack
from uncompyle6.magics import PYTHON_MAGIC_INT
from uncompyle6.code import Code3
internStrings = []
internObjects = []
PYTHON3 = (sys.version_info >= (3, 0))
if PYTHON3:
def long(n): return n
def compat_str(s):
return s.decode('utf-8', errors='ignore') if PYTHON3 else str(s)
def load_code(fp, magic_int, code_objects={}):
"""
marshal.load() written in Python. When the Python bytecode magic loaded is the
same magic for the running Python interpreter, we can simply use the
Python-supplied mashal.load().
However we need to use this when versions are different since the internal
code structures are different. Sigh.
"""
global internStrings, internObjects
internStrings = []
internObjects = []
seek_pos = fp.tell()
# Do a sanity check. Is this a code type?
b = ord(fp.read(1))
if (b & 0x80):
b = b & 0x7f
c = chr(b)
if c != 'c':
raise TypeError("File %s doesn't smell like Python bytecode" % fp.name)
fp.seek(seek_pos)
return load_code_internal(fp, magic_int, code_objects=code_objects)
def load_code_type(fp, magic_int, bytes_for_s=False, code_objects={}):
# Python [1.3 .. 2.3)
# FIXME: find out what magics were for 1.3
v13_to_23 = magic_int in (20121, 50428, 50823, 60202, 60717)
# Python [1.5 .. 2.3)
v15_to_23 = magic_int in (20121, 50428, 50823, 60202, 60717)
if v13_to_23:
co_argcount = unpack('h', fp.read(2))[0]
else:
co_argcount = unpack('i', fp.read(4))[0]
if 3020 < magic_int < 20121:
kwonlyargcount = unpack('i', fp.read(4))[0]
else:
kwonlyargcount = 0
if v13_to_23:
co_nlocals = unpack('h', fp.read(2))[0]
else:
co_nlocals = unpack('i', fp.read(4))[0]
if v15_to_23:
co_stacksize = unpack('h', fp.read(2))[0]
else:
co_stacksize = unpack('i', fp.read(4))[0]
if v13_to_23:
co_flags = unpack('h', fp.read(2))[0]
else:
co_flags = unpack('i', fp.read(4))[0]
co_code = load_code_internal(fp, magic_int, bytes_for_s=True,
code_objects=code_objects)
co_consts = load_code_internal(fp, magic_int, code_objects=code_objects)
co_names = load_code_internal(fp, magic_int, code_objects=code_objects)
co_varnames = load_code_internal(fp, magic_int, code_objects=code_objects)
co_freevars = load_code_internal(fp, magic_int, code_objects=code_objects)
co_cellvars = load_code_internal(fp, magic_int, code_objects=code_objects)
co_filename = load_code_internal(fp, magic_int, code_objects=code_objects)
co_name = load_code_internal(fp, magic_int)
co_firstlineno = unpack('i', fp.read(4))[0]
co_lnotab = load_code_internal(fp, magic_int, code_objects=code_objects)
# The Python3 code object is different than Python2's which
# we are reading if we get here.
# Also various parameters which were strings are now
# bytes (which is probably more logical).
if PYTHON3:
Code = types.CodeType
if PYTHON_MAGIC_INT > 3020:
# In later Python3 magic_ints, there is a
# kwonlyargcount parameter which we set to 0.
code = Code(co_argcount, kwonlyargcount, co_nlocals, co_stacksize, co_flags,
co_code, co_consts, co_names, co_varnames, co_filename, co_name,
co_firstlineno, bytes(co_lnotab, encoding='utf-8'),
co_freevars, co_cellvars)
else:
code = Code(co_argcount, kwonlyargcount, co_nlocals, co_stacksize, co_flags,
co_code, co_consts, co_names, co_varnames, co_filename, co_name,
co_firstlineno, bytes(co_lnotab, encoding='utf-8'),
co_freevars, co_cellvars)
else:
if (3000 <= magic_int < 20121):
# Python 3 encodes some fields as Unicode while Python2
# requires the corresponding field to have string values
co_consts = tuple([str(s) if isinstance(s, unicode) else s for s in co_consts])
co_names = tuple([str(s) if isinstance(s, unicode) else s for s in co_names])
co_varnames = tuple([str(s) if isinstance(s, unicode) else s for s in co_varnames])
co_filename = str(co_filename)
co_name = str(co_name)
if 3020 < magic_int <= 20121:
code = Code3(co_argcount, kwonlyargcount,
co_nlocals, co_stacksize, co_flags, co_code,
co_consts, co_names, co_varnames, co_filename, co_name,
co_firstlineno, co_lnotab, co_freevars, co_cellvars)
else:
Code = types.CodeType
code = Code(co_argcount, co_nlocals, co_stacksize, co_flags, co_code,
co_consts, co_names, co_varnames, co_filename, co_name,
co_firstlineno, co_lnotab, co_freevars, co_cellvars)
pass
pass
code_objects[str(code)] = code
return code
def load_code_internal(fp, magic_int, bytes_for_s=False,
code_objects={}, marshalType=None):
global internStrings, internObjects
if marshalType is None:
b1 = ord(fp.read(1))
if b1 & 0x80:
b1 = b1 &0x7f
code = load_code_internal(fp, magic_int, bytes_for_s=False,
code_objects=code_objects,
marshalType=chr(b1))
internObjects.append(code)
return code
marshalType = chr(b1)
# print(marshalType) # debug
if marshalType == '0':
# Null
return None
elif marshalType == 'N':
return None
elif marshalType == 'F':
return False
elif marshalType == 'T':
return True
elif marshalType == 'S':
return StopIteration
elif marshalType == '.':
return Ellipsis
elif marshalType == 'i':
# int
return int(unpack('i', fp.read(4))[0])
elif marshalType == 'I':
# int64
return unpack('q', fp.read(8))[0]
elif marshalType == 'f':
# float
n = fp.read(1)
return float(unpack('d', fp.read(n))[0])
elif marshalType == 'g':
# binary float
return float(unpack('d', fp.read(8))[0])
elif marshalType == 'x':
# complex
raise KeyError(marshalType)
elif marshalType == 'y':
# binary complex
real = unpack('d', fp.read(8))[0]
imag = unpack('d', fp.read(8))[0]
return complex(real, imag)
elif marshalType == 'l':
# long
n = unpack('i', fp.read(4))[0]
if n == 0:
return long(0)
size = abs(n)
d = long(0)
for j in range(0, size):
md = int(unpack('h', fp.read(2))[0])
d += md << j*15
if n < 0:
return long(d*-1)
return d
elif marshalType == 's':
# string
# Note: could mean bytes in Python3 processing Python2 bytecode
strsize = unpack('i', fp.read(4))[0]
s = fp.read(strsize)
if not bytes_for_s:
s = compat_str(s)
return s
elif marshalType == 't':
# interned
strsize = unpack('i', fp.read(4))[0]
interned = compat_str(fp.read(strsize))
internStrings.append(interned)
return interned
elif marshalType == 'R':
# string reference
refnum = unpack('i', fp.read(4))[0]
return internStrings[refnum]
elif marshalType == 'r':
# object reference - new in Python3
refnum = unpack('i', fp.read(4))[0]
return internObjects[refnum-1]
elif marshalType == '(':
tuplesize = unpack('i', fp.read(4))[0]
ret = tuple()
while tuplesize > 0:
ret += load_code_internal(fp, magic_int, code_objects=code_objects),
tuplesize -= 1
return ret
elif marshalType == '[':
raise KeyError(marshalType)
elif marshalType == '{':
# dictionary
raise KeyError(marshalType)
elif marshalType == 'c':
return load_code_type(fp, magic_int, bytes_for_s=False,
code_objects=code_objects)
elif marshalType == 'C':
# code type used in Python 1.0 - 1.2
raise KeyError("C code is Python 1.0 - 1.2; can't handle yet")
elif marshalType == 'u':
strsize = unpack('i', fp.read(4))[0]
unicodestring = fp.read(strsize)
return unicodestring.decode('utf-8')
elif marshalType == '?':
# unknown
raise KeyError(marshalType)
elif marshalType in ['<', '>']:
# set and frozenset
setsize = unpack('i', fp.read(4))[0]
ret = tuple()
while setsize > 0:
ret += load_code_internal(fp, magic_int, code_objects=code_objects),
setsize -= 1
if marshalType == '>':
return frozenset(ret)
else:
return set(ret)
elif marshalType == 'a':
# ascii
# FIXME check
strsize = unpack('i', fp.read(4))[0]
s = fp.read(strsize)
s = compat_str(s)
return s
elif marshalType == 'A':
# ascii interned - since Python3
# FIXME: check
strsize = unpack('i', fp.read(4))[0]
interned = compat_str(fp.read(strsize))
internStrings.append(interned)
return interned
elif marshalType == ')':
# small tuple - since Python3
tuplesize = unpack('B', fp.read(1))[0]
ret = tuple()
while tuplesize > 0:
ret += load_code_internal(fp, magic_int, code_objects=code_objects),
tuplesize -= 1
return ret
elif marshalType == 'z':
# short ascii - since Python3
strsize = unpack('B', fp.read(1))[0]
return compat_str(fp.read(strsize))
elif marshalType == 'Z':
# short ascii interned - since Python3
# FIXME: check
strsize = unpack('B', fp.read(1))[0]
interned = compat_str(fp.read(strsize))
internStrings.append(interned)
return interned
else:
sys.stderr.write("Unknown type %i (hex %x) %c\n" %
(ord(marshalType), ord(marshalType), ord(marshalType)))
return

View File

@@ -10,7 +10,7 @@ from __future__ import print_function
import sys import sys
from uncompyle6.code import iscode from xdis.code import iscode
from spark_parser import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG from spark_parser import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
class ParserError(Exception): class ParserError(Exception):

View File

@@ -316,7 +316,7 @@ def get_scanner(version):
import uncompyle6.scanners.scanner35 as scan import uncompyle6.scanners.scanner35 as scan
scanner = scan.Scanner35() scanner = scan.Scanner35()
else: else:
raise RuntimeError("Unsupported Python version %d" % version) raise RuntimeError("Unsupported Python version %s" % version)
return scanner return scanner
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -17,7 +17,7 @@ import dis, inspect
from collections import namedtuple from collections import namedtuple
from array import array from array import array
from uncompyle6.code import iscode from xdis.code import iscode
from uncompyle6.opcodes.opcode_27 import * # NOQA from uncompyle6.opcodes.opcode_27 import * # NOQA
import uncompyle6.scanner as scan import uncompyle6.scanner as scan

View File

@@ -29,7 +29,7 @@ import uncompyle6.scanners.dis3 as dis3
from collections import namedtuple from collections import namedtuple
from array import array from array import array
from uncompyle6.code import iscode from xdis.code import iscode
from uncompyle6.scanner import Token from uncompyle6.scanner import Token
from uncompyle6 import PYTHON3 from uncompyle6 import PYTHON3

View File

@@ -29,7 +29,7 @@ from __future__ import print_function
import re, sys import re, sys
from uncompyle6 import PYTHON3 from uncompyle6 import PYTHON3
from uncompyle6.code import iscode from xdis.code import iscode
from uncompyle6.semantics import pysource from uncompyle6.semantics import pysource
from uncompyle6.parser import get_python_parser from uncompyle6.parser import get_python_parser
from uncompyle6 import parser from uncompyle6 import parser

View File

@@ -70,7 +70,7 @@ from __future__ import print_function
import sys, re import sys, re
from uncompyle6 import PYTHON3 from uncompyle6 import PYTHON3
from uncompyle6.code import iscode from xdis.code import iscode
from uncompyle6.parser import get_python_parser from uncompyle6.parser import get_python_parser
from uncompyle6.parsers.astnode import AST from uncompyle6.parsers.astnode import AST
from spark_parser import GenericASTTraversal, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG from spark_parser import GenericASTTraversal, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG

View File

@@ -13,9 +13,9 @@ import dis, operator
import uncompyle6 import uncompyle6
import uncompyle6.scanner as scanner import uncompyle6.scanner as scanner
from uncompyle6 import PYTHON3 from uncompyle6 import PYTHON3
from uncompyle6.code import iscode from xdis.code import iscode
from uncompyle6.magics import PYTHON_MAGIC_INT from xdis.magics import PYTHON_MAGIC_INT
from uncompyle6.load import load_file, load_module from xdis.load import load_file, load_module
# FIXME: DRY # FIXME: DRY
if PYTHON3: if PYTHON3: