You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-02 16:44:46 +08:00
Start using our replacement for inspect.iscode
This commit is contained in:
53
uncompyle6/code.py
Normal file
53
uncompyle6/code.py
Normal file
@@ -0,0 +1,53 @@
|
||||
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)
|
@@ -1,7 +1,7 @@
|
||||
# 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
|
||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||
# Copyright (c) 1999 John Aycock
|
||||
|
||||
"""
|
||||
CPython magic- and version- independent disassembly routines
|
||||
@@ -21,15 +21,16 @@ from __future__ import print_function
|
||||
import inspect, os, sys
|
||||
|
||||
import uncompyle6
|
||||
from uncompyle6.scanner import get_scanner
|
||||
from uncompyle6.code import iscode
|
||||
from uncompyle6.load import check_object_path, load_module
|
||||
from uncompyle6.scanner import get_scanner
|
||||
|
||||
def disco(version, co, out=None):
|
||||
"""
|
||||
diassembles and deparses a given code block 'co'
|
||||
"""
|
||||
|
||||
assert hasattr(co, 'co_name')
|
||||
assert iscode(co)
|
||||
|
||||
# store final output stream for case of error
|
||||
real_out = out or sys.stdout
|
||||
|
@@ -1,8 +1,9 @@
|
||||
from __future__ import print_function
|
||||
import datetime, inspect, os, sys
|
||||
|
||||
from uncompyle6.disas import check_object_path
|
||||
from uncompyle6 import verify, PYTHON_VERSION
|
||||
from uncompyle6.code import iscode
|
||||
from uncompyle6.disas import check_object_path
|
||||
from uncompyle6.semantics import pysource
|
||||
|
||||
from uncompyle6.load import load_module
|
||||
@@ -13,7 +14,7 @@ def uncompyle(version, co, out=None, showasm=False, showast=False,
|
||||
disassembles and deparses a given code block 'co'
|
||||
"""
|
||||
|
||||
assert hasattr(co, 'co_name')
|
||||
assert iscode(co)
|
||||
|
||||
# store final output stream for case of error
|
||||
real_out = out or sys.stdout
|
||||
|
@@ -20,6 +20,7 @@ from struct import unpack
|
||||
|
||||
import uncompyle6.scanners.scanner3 as scan3
|
||||
from uncompyle6.magics import PYTHON_MAGIC_INT
|
||||
from uncompyle6.code import Code3
|
||||
|
||||
internStrings = []
|
||||
internObjects = []
|
||||
@@ -132,10 +133,10 @@ def load_code_type(fp, magic_int, bytes_for_s=False, code_objects={}):
|
||||
co_filename = str(co_filename)
|
||||
co_name = str(co_name)
|
||||
if 3020 < magic_int <= 20121:
|
||||
code = scan3.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)
|
||||
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,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# Copyright (c) 2015 by Rocky Bernstein
|
||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||
# 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
|
||||
"""
|
||||
Python 2.7 bytecode scanner/deparser
|
||||
|
||||
@@ -17,6 +17,7 @@ import dis, inspect
|
||||
from collections import namedtuple
|
||||
from array import array
|
||||
|
||||
from uncompyle6.code import iscode
|
||||
from uncompyle6.opcodes.opcode_27 import * # NOQA
|
||||
import uncompyle6.scanner as scan
|
||||
|
||||
@@ -138,11 +139,7 @@ class Scanner27(scan.Scanner):
|
||||
continue
|
||||
if op in hasconst:
|
||||
const = co.co_consts[oparg]
|
||||
# We can't use inspect.iscode() because we may be
|
||||
# using a different version of Python than the
|
||||
# one that this was byte-compiled on. So the code
|
||||
# types may mismatch.
|
||||
if hasattr(const, 'co_name'):
|
||||
if iscode(const):
|
||||
oparg = const
|
||||
if const.co_name == '<lambda>':
|
||||
assert op_name == 'LOAD_CONST'
|
||||
|
@@ -13,6 +13,7 @@ import dis
|
||||
from collections import namedtuple
|
||||
from array import array
|
||||
|
||||
from uncompyle6.code import iscode
|
||||
from uncompyle6.scanner import Token
|
||||
from uncompyle6 import PYTHON_VERSION, PYTHON3
|
||||
|
||||
@@ -24,30 +25,6 @@ globals().update(op3.opmap)
|
||||
|
||||
import uncompyle6.scanner as scan
|
||||
|
||||
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 Scanner3(scan.Scanner):
|
||||
|
||||
def __init__(self):
|
||||
@@ -145,11 +122,7 @@ class Scanner3(scan.Scanner):
|
||||
if not PYTHON3 and isinstance(const, str):
|
||||
if const in code_objects:
|
||||
const = code_objects[const]
|
||||
# Not sure if'we can inspect.iscode() because we may be
|
||||
# using a different version of Python than the
|
||||
# one that this was byte-compiled on. Is probably okay,
|
||||
# but we'll use hasattr instead here.
|
||||
if hasattr(const, 'co_name'):
|
||||
if iscode(const):
|
||||
oparg = const
|
||||
if const.co_name == '<lambda>':
|
||||
assert op_name == 'LOAD_CONST'
|
||||
|
@@ -15,6 +15,7 @@ from array import array
|
||||
import uncompyle6.scanners.scanner3 as scan3
|
||||
|
||||
from uncompyle6 import PYTHON_VERSION
|
||||
from uncompyle6.code import iscode
|
||||
from uncompyle6.scanner import Token
|
||||
|
||||
# Get all the opcodes into globals
|
||||
@@ -92,13 +93,9 @@ class Scanner34(scan3.Scanner3):
|
||||
pattr = inst.argrepr
|
||||
opname = inst.opname
|
||||
|
||||
# For constants, the pattr is the same as attr. Using pattr adds
|
||||
# an extra level of quotes which messes other things up, like getting
|
||||
# keyword attribute names in a call. I suspect there will be things
|
||||
# other than LOAD_CONST, but we'll start out with just this for now.
|
||||
if opname in ['LOAD_CONST']:
|
||||
const = inst.argval
|
||||
if hasattr(const, 'co_name'):
|
||||
if iscode(const):
|
||||
if const.co_name == '<lambda>':
|
||||
opname = 'LOAD_LAMBDA'
|
||||
elif const.co_name == '<genexpr>':
|
||||
|
@@ -29,6 +29,7 @@ from __future__ import print_function
|
||||
import inspect, re, sys
|
||||
|
||||
from uncompyle6 import PYTHON3
|
||||
from uncompyle6.code import iscode
|
||||
from uncompyle6.semantics import pysource
|
||||
from uncompyle6.parser import get_python_parser
|
||||
from uncompyle6 import parser
|
||||
@@ -482,7 +483,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
||||
self.prec = 27
|
||||
code = node[-5].attr
|
||||
|
||||
assert hasattr(co, 'co_name')
|
||||
assert iscode(co)
|
||||
code = Code(code, self.scanner, self.currentclass)
|
||||
# assert isinstance(code, Code)
|
||||
|
||||
@@ -525,8 +526,8 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
||||
self.prec = 27
|
||||
code = node[code_index].attr
|
||||
|
||||
assert hasattr(code, 'co_name')
|
||||
## Or Code3
|
||||
assert iscode(code)
|
||||
# Or Code3
|
||||
code = Code(code, self.scanner, self.currentclass)
|
||||
# assert isinstance(code, Code)
|
||||
|
||||
@@ -1246,7 +1247,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
||||
def deparse_code(version, co, out=StringIO(), showasm=False, showast=False,
|
||||
showgrammar=False):
|
||||
|
||||
assert hasattr(co, 'co_name')
|
||||
assert iscode(co)
|
||||
# store final output stream for case of error
|
||||
scanner = get_scanner(version)
|
||||
|
||||
|
@@ -67,6 +67,7 @@ from __future__ import print_function
|
||||
import inspect, sys, re
|
||||
|
||||
from uncompyle6 import PYTHON3
|
||||
from uncompyle6.code import iscode
|
||||
from uncompyle6.parser import get_python_parser
|
||||
from uncompyle6.parsers.astnode import AST
|
||||
from uncompyle6.parsers.spark import GenericASTTraversal, DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||
@@ -980,7 +981,7 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
self.prec = 27
|
||||
code = node[code_index].attr
|
||||
|
||||
assert hasattr(code, 'co_name')
|
||||
assert iscode(code)
|
||||
code = Code(code, self.scanner, self.currentclass)
|
||||
ast = self.build_ast(code._tokens, code._customize)
|
||||
self.customize(code._customize)
|
||||
@@ -1025,7 +1026,7 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
self.prec = 27
|
||||
code = node[code_index].attr
|
||||
|
||||
assert hasattr(code, 'co_name')
|
||||
assert iscode(code)
|
||||
code = Code(code, self.scanner, self.currentclass)
|
||||
# assert isinstance(code, Code)
|
||||
|
||||
@@ -1448,7 +1449,7 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
defparams = node[:node[-1].attr]
|
||||
code = node[code_index].attr
|
||||
|
||||
assert hasattr(code, 'co_name')
|
||||
assert iscode(code)
|
||||
code = Code(code, self.scanner, self.currentclass)
|
||||
# assert isinstance(code, Code)
|
||||
|
||||
@@ -1515,7 +1516,7 @@ class SourceWalker(GenericASTTraversal, object):
|
||||
def build_class(self, code):
|
||||
"""Dump class definition, doc string and class body."""
|
||||
|
||||
assert hasattr(code, 'co_name')
|
||||
assert iscode(code)
|
||||
self.classes.append(self.currentclass)
|
||||
code = Code(code, self.scanner, self.currentclass)
|
||||
# assert isinstance(code, Code)
|
||||
@@ -1626,7 +1627,7 @@ def deparse_code(version, co, out=sys.stdout, showasm=False, showast=False,
|
||||
disassembles and deparses a given code block 'co'
|
||||
"""
|
||||
|
||||
assert hasattr(co, 'co_name')
|
||||
assert iscode(co)
|
||||
# store final output stream for case of error
|
||||
scanner = get_scanner(version)
|
||||
|
||||
|
@@ -13,6 +13,7 @@ import dis, inspect, 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
|
||||
|
||||
@@ -138,8 +139,8 @@ def cmp_code_objects(version, code_obj1, code_obj2, name=''):
|
||||
This is the main part of this module.
|
||||
"""
|
||||
# print code_obj1, type(code_obj2)
|
||||
assert code_obj1, hasattr('co_name')
|
||||
assert code_obj2, hasattr('co_name')
|
||||
assert iscode(code_obj1)
|
||||
assert iscode(code_obj2)
|
||||
# print dir(code_obj1)
|
||||
if isinstance(code_obj1, object):
|
||||
# new style classes (Python 2.2)
|
||||
|
Reference in New Issue
Block a user