81 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			81 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
	
	
import py
 | 
						|
 | 
						|
class Code(object):
 | 
						|
    def __init__(self, rawcode):
 | 
						|
        rawcode = getattr(rawcode, 'im_func', rawcode)
 | 
						|
        rawcode = getattr(rawcode, 'func_code', rawcode)
 | 
						|
        self.raw = rawcode 
 | 
						|
        self.filename = rawcode.co_filename
 | 
						|
        try:
 | 
						|
            self.firstlineno = rawcode.co_firstlineno - 1
 | 
						|
        except AttributeError: 
 | 
						|
            raise TypeError("not a code object: %r" %(rawcode,))
 | 
						|
        self.name = rawcode.co_name
 | 
						|
        
 | 
						|
    def __eq__(self, other): 
 | 
						|
        return self.raw == other.raw 
 | 
						|
 | 
						|
    def new(self, rec=False, **kwargs): 
 | 
						|
        """ return new code object with modified attributes. 
 | 
						|
            if rec-cursive is true then dive into code 
 | 
						|
            objects contained in co_consts. 
 | 
						|
        """ 
 | 
						|
        names = [x for x in dir(self.raw) if x[:3] == 'co_']
 | 
						|
        for name in kwargs: 
 | 
						|
            if name not in names: 
 | 
						|
                raise TypeError("unknown code attribute: %r" %(name, ))
 | 
						|
        if rec: 
 | 
						|
            newconstlist = []
 | 
						|
            co = self.raw
 | 
						|
            cotype = type(co)
 | 
						|
            for c in co.co_consts:
 | 
						|
                if isinstance(c, cotype):
 | 
						|
                    c = self.__class__(c).new(rec=True, **kwargs) 
 | 
						|
                newconstlist.append(c)
 | 
						|
            return self.new(rec=False, co_consts=tuple(newconstlist), **kwargs) 
 | 
						|
        for name in names:
 | 
						|
            if name not in kwargs:
 | 
						|
                kwargs[name] = getattr(self.raw, name)
 | 
						|
        return py.std.new.code(
 | 
						|
                 kwargs['co_argcount'],
 | 
						|
                 kwargs['co_nlocals'],
 | 
						|
                 kwargs['co_stacksize'],
 | 
						|
                 kwargs['co_flags'],
 | 
						|
                 kwargs['co_code'],
 | 
						|
                 kwargs['co_consts'],
 | 
						|
                 kwargs['co_names'],
 | 
						|
                 kwargs['co_varnames'],
 | 
						|
                 kwargs['co_filename'],
 | 
						|
                 kwargs['co_name'],
 | 
						|
                 kwargs['co_firstlineno'],
 | 
						|
                 kwargs['co_lnotab'],
 | 
						|
                 kwargs['co_freevars'],
 | 
						|
                 kwargs['co_cellvars'],
 | 
						|
        )
 | 
						|
 | 
						|
    def path(self):
 | 
						|
        try:
 | 
						|
            return self.raw.co_filename.__path__
 | 
						|
        except AttributeError:
 | 
						|
            return py.path.local(self.raw.co_filename)
 | 
						|
    path = property(path, None, None, "path of this code object")
 | 
						|
 | 
						|
    def fullsource(self):
 | 
						|
        fn = self.raw.co_filename
 | 
						|
        try:
 | 
						|
            return fn.__source__
 | 
						|
        except AttributeError:
 | 
						|
            return py.code.Source(self.path.read(mode="rU"))
 | 
						|
    fullsource = property(fullsource, None, None,
 | 
						|
                          "full source containing this code object")
 | 
						|
    
 | 
						|
    def source(self):
 | 
						|
        # return source only for that part of code
 | 
						|
        import inspect
 | 
						|
        return py.code.Source(inspect.getsource(self.raw))
 | 
						|
 | 
						|
    def getargs(self):
 | 
						|
        # handfull shortcut for getting args
 | 
						|
        raw = self.raw
 | 
						|
        return raw.co_varnames[:raw.co_argcount]
 |