You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
Use xdis for code, magics, and marshal
This commit is contained in:
@@ -36,7 +36,8 @@ entry_points={
|
||||
'pydisassemble=uncompyle6.bin.pydisassemble:main',
|
||||
]}
|
||||
ftp_url = None
|
||||
install_requires = ['spark-parser >= 1.2.1']
|
||||
install_requires = ['spark-parser >= 1.2.1',
|
||||
'xdis >= 1.0.1']
|
||||
license = 'MIT'
|
||||
mailing_list = 'python-debugger@googlegroups.com'
|
||||
modname = 'uncompyle6'
|
||||
|
@@ -18,7 +18,6 @@ def test_if_in_for():
|
||||
scan.build_prev_op(n)
|
||||
fjt = scan.find_jump_targets()
|
||||
assert {15: [3], 69: [66], 63: [18]} == fjt
|
||||
print(scan.structs)
|
||||
assert scan.structs == \
|
||||
[{'start': 0, 'end': 72, 'type': 'root'},
|
||||
{'start': 18, 'end': 66, 'type': 'if-then'},
|
||||
|
@@ -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
|
@@ -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"
|
@@ -45,10 +45,8 @@ sys.setrecursionlimit(5000)
|
||||
|
||||
import uncompyle6.semantics.pysource
|
||||
import uncompyle6.semantics.fragments
|
||||
import uncompyle6.load
|
||||
|
||||
# Export some functions
|
||||
from uncompyle6.load import load_module, load_file
|
||||
from uncompyle6.main import uncompyle_file
|
||||
|
||||
# Conventience functions so you can say:
|
||||
|
@@ -6,7 +6,6 @@
|
||||
from __future__ import print_function
|
||||
import sys, os, getopt
|
||||
|
||||
from uncompyle6 import check_python_version
|
||||
from uncompyle6.disas import disassemble_file
|
||||
from uncompyle6.version import VERSION
|
||||
|
||||
@@ -35,8 +34,6 @@ def main():
|
||||
Usage_short = """usage: %s FILE...
|
||||
Type -h for for full help.""" % program
|
||||
|
||||
check_python_version(program)
|
||||
|
||||
use_uncompyle6_format = False
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
|
@@ -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)
|
@@ -22,8 +22,8 @@ import os, sys
|
||||
from collections import deque
|
||||
|
||||
import uncompyle6
|
||||
from uncompyle6.code import iscode
|
||||
from uncompyle6.load import check_object_path, load_module
|
||||
from xdis.code import iscode
|
||||
from xdis.load import check_object_path, load_module
|
||||
from uncompyle6.scanner import get_scanner
|
||||
|
||||
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' %
|
||||
(co.co_name, co.co_firstlineno, co.co_filename),
|
||||
file=real_out)
|
||||
tokens, customize = disasm(co, use_uncompyle6_format)
|
||||
tokens, customize = disasm(co)
|
||||
for t in tokens:
|
||||
if iscode(t.pattr):
|
||||
queue.append(t.pattr)
|
||||
|
@@ -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
|
@@ -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()
|
@@ -2,12 +2,12 @@ from __future__ import print_function
|
||||
import datetime, os, sys
|
||||
|
||||
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.semantics import pysource
|
||||
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,
|
||||
timestamp=None, showgrammar=False, code_objects={}):
|
||||
|
@@ -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
|
@@ -10,7 +10,7 @@ from __future__ import print_function
|
||||
|
||||
import sys
|
||||
|
||||
from uncompyle6.code import iscode
|
||||
from xdis.code import iscode
|
||||
from spark_parser import GenericASTBuilder, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||
|
||||
class ParserError(Exception):
|
||||
|
@@ -316,7 +316,7 @@ def get_scanner(version):
|
||||
import uncompyle6.scanners.scanner35 as scan
|
||||
scanner = scan.Scanner35()
|
||||
else:
|
||||
raise RuntimeError("Unsupported Python version %d" % version)
|
||||
raise RuntimeError("Unsupported Python version %s" % version)
|
||||
return scanner
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@@ -17,7 +17,7 @@ import dis, inspect
|
||||
from collections import namedtuple
|
||||
from array import array
|
||||
|
||||
from uncompyle6.code import iscode
|
||||
from xdis.code import iscode
|
||||
from uncompyle6.opcodes.opcode_27 import * # NOQA
|
||||
import uncompyle6.scanner as scan
|
||||
|
||||
|
@@ -29,7 +29,7 @@ import uncompyle6.scanners.dis3 as dis3
|
||||
from collections import namedtuple
|
||||
from array import array
|
||||
|
||||
from uncompyle6.code import iscode
|
||||
from xdis.code import iscode
|
||||
from uncompyle6.scanner import Token
|
||||
from uncompyle6 import PYTHON3
|
||||
|
||||
|
@@ -29,7 +29,7 @@ from __future__ import print_function
|
||||
import re, sys
|
||||
|
||||
from uncompyle6 import PYTHON3
|
||||
from uncompyle6.code import iscode
|
||||
from xdis.code import iscode
|
||||
from uncompyle6.semantics import pysource
|
||||
from uncompyle6.parser import get_python_parser
|
||||
from uncompyle6 import parser
|
||||
|
@@ -70,7 +70,7 @@ from __future__ import print_function
|
||||
import sys, re
|
||||
|
||||
from uncompyle6 import PYTHON3
|
||||
from uncompyle6.code import iscode
|
||||
from xdis.code import iscode
|
||||
from uncompyle6.parser import get_python_parser
|
||||
from uncompyle6.parsers.astnode import AST
|
||||
from spark_parser import GenericASTTraversal, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||
|
@@ -13,9 +13,9 @@ import dis, operator
|
||||
import uncompyle6
|
||||
import uncompyle6.scanner as scanner
|
||||
from uncompyle6 import PYTHON3
|
||||
from uncompyle6.code import iscode
|
||||
from uncompyle6.magics import PYTHON_MAGIC_INT
|
||||
from uncompyle6.load import load_file, load_module
|
||||
from xdis.code import iscode
|
||||
from xdis.magics import PYTHON_MAGIC_INT
|
||||
from xdis.load import load_file, load_module
|
||||
|
||||
# FIXME: DRY
|
||||
if PYTHON3:
|
||||
|
Reference in New Issue
Block a user