def to_code(self, from_function=False):
        """Assemble a Python code object from a Code object"""

        num_fastnames = sum(1 for op, arg in self.code if isopcode(op) and op in haslocal)
        is_function = self.newlocals or num_fastnames > 0 or len(self.args) > 0
        nested = is_function and from_function

        co_flags = {op[0] for op in self.code}

        is_generator = self.force_generator or (YIELD_VALUE in co_flags or YIELD_FROM in co_flags)
        no_free = (not self.freevars) and (not co_flags & hasfree)

        if version_info >= (3, 5):
            is_native_coroutine = bool(self.force_coroutine or (co_flags & coroutine_opcodes))
            assert not (is_native_coroutine and self.force_iterable_coroutine)

        co_flags =\
            (not(STORE_NAME in co_flags or LOAD_NAME in co_flags or DELETE_NAME in co_flags)) |\
            (self.newlocals and CO_NEWLOCALS) |\
            (self.varargs and CO_VARARGS) |\
            (self.varkwargs and CO_VARKEYWORDS) |\
            (is_generator and CO_GENERATOR) |\
            (no_free and CO_NOFREE) |\
            (nested and CO_NESTED)

        if version_info >= (3, 5):
            co_flags |= (is_native_coroutine and CO_COROUTINE) |\
                        (self.force_iterable_coroutine and CO_ITERABLE_COROUTINE) |\
                        (self.future_generator_stop and CO_FUTURE_GENERATOR_STOP)

        co_consts = [self.docstring]
        co_names = []
        co_varnames = list(self.args)
        co_freevars = tuple(self.freevars)

        # Find all cellvars beforehand for two reasons
        # Need the number of them to construct the numeric arg for ops in hasfree
        # Need to put args which are cells in the beginning of co_cellvars
        cellvars = {arg for op, arg in self.code
                    if isopcode(op) and op in hasfree
                    and arg not in co_freevars}
        co_cellvars = [jumps for jumps in self.args if jumps in cellvars]

        def index(seq, item, eq=True, can_append=True):
            for i, x in enumerate(seq):
                if x == item if eq else x is item:
                    return i
            if can_append:
                seq.append(item)
                return len(seq) - 1
            else:
                raise IndexError("Item not found")

        jumps = []
        label_pos = {}
        lastlineno = self.firstlineno
        lastlinepos = 0
        co_code = bytearray()
        co_lnotab = bytearray()

        for i, (op, arg) in enumerate(self.code):
            if isinstance(op, Label):
                label_pos[op] = len(co_code)
            elif op is SetLineno:
                incr_lineno = arg - lastlineno
                incr_pos = len(co_code) - lastlinepos
                lastlineno = arg
                lastlinepos += incr_pos
                if incr_lineno != 0 or incr_pos != 0:
                    while incr_pos > 255:
                        co_lnotab += b"\xFF\0"
                        incr_pos -= 255
                    while incr_lineno > 255:
                        co_lnotab += (0xFF00|incr_pos).to_bytes(2, "little")
                        incr_pos = 0
                        incr_lineno -= 255
                    if incr_pos or incr_lineno:
                        co_lnotab += bytes((incr_pos, incr_lineno))
            elif op == opcode.EXTENDED_ARG:
                self.code[i + 1][1] |= 1 << 32
            elif op not in hasarg:
                co_code.append(op)
            else:
                if op in hasconst:
                    if isinstance(arg, Code) and\
                            i + 2 < len(self.code) and self.code[i + 2][0] in hascode:
                        arg = arg.to_code(from_function=is_function)
                        assert arg is not None
                    arg = index(co_consts, arg, 0)
                elif op in hasname:
                    arg = index(co_names, arg)
                elif op in hasjump:
                    jumps.append((len(co_code), arg))
                    co_code += op.to_bytes(3, "little")
                    continue
                elif op in haslocal:
                    arg = index(co_varnames, arg)
                elif op in hascompare:
                    arg = index(cmp_op, arg, can_append=False)
                elif op in hasfree:
                    try:
                        arg = index(co_freevars, arg, can_append=False) + len(cellvars)
                    except IndexError:
                        arg = index(co_cellvars, arg)
                if arg > 0xFFFF:
                    co_code += (opcode.EXTENDED_ARG | ((arg & 0xFFFF0000) >> 8)).to_bytes(3, "little")
                co_code += (op | (arg << 8)).to_bytes(3, "little")

        for pos, label in jumps:
            jump = label_pos[label]
            if co_code[pos] in hasjrel:
                jump -= pos + 3
            if jump > 0xFFFF:
                raise NotImplementedError("Extended jumps not implemented")
            co_code[pos + 1] = jump & 0xFF
            co_code[pos + 2] = jump >> 8

        co_argcount = len(self.args) - self.varargs - self.varkwargs - self.kwonly
        co_stacksize = self._compute_stacksize()

        return CodeType(co_argcount, self.kwonly, len(co_varnames), co_stacksize, co_flags,
                        bytes(co_code), tuple(co_consts), tuple(co_names), tuple(co_varnames),
                        self.filename, self.name, self.firstlineno, bytes(co_lnotab), co_freevars,
                        tuple(co_cellvars))
def to_code ( self , from_function = False ) : num_fastnames = sum ( 1 for op , arg in self . code if isopcode ( op ) and op in haslocal ) is_function = self . newlocals or num_fastnames > 0 or len ( self . args ) > 0 nested = is_function and from_function co_flags = { op [ 0 ] for op in self . code } is_generator = self . force_generator or ( YIELD_VALUE in co_flags or YIELD_FROM in co_flags ) no_free = ( not self . freevars ) and ( not co_flags & hasfree ) if version_info >= ( 3 , 5 ) : is_native_coroutine = bool ( self . force_coroutine or ( co_flags & coroutine_opcodes ) ) assert not ( is_native_coroutine and self . force_iterable_coroutine ) co_flags = ( not ( STORE_NAME in co_flags or LOAD_NAME in co_flags or DELETE_NAME in co_flags ) ) | ( self . newlocals and CO_NEWLOCALS ) | ( self . varargs and CO_VARARGS ) | ( self . varkwargs and CO_VARKEYWORDS ) | ( is_generator and CO_GENERATOR ) | ( no_free and CO_NOFREE ) | ( nested and CO_NESTED ) if version_info >= ( 3 , 5 ) : co_flags |= ( is_native_coroutine and CO_COROUTINE ) | ( self . force_iterable_coroutine and CO_ITERABLE_COROUTINE ) | ( self . future_generator_stop and CO_FUTURE_GENERATOR_STOP ) co_consts = [ self . docstring ] co_names = [ ] co_varnames = list ( self . args ) co_freevars = tuple ( self . freevars ) cellvars = { arg for op , arg in self . code if isopcode ( op ) and op in hasfree and arg not in co_freevars } co_cellvars = [ jumps for jumps in self . args if jumps in cellvars ] def index ( seq , item , eq = True , can_append = True ) : for i , x in enumerate ( seq ) : if x == item if eq else x is item : return i if can_append : seq . append ( item ) return len ( seq ) - 1 else : raise IndexError ( "Item not found" ) jumps = [ ] label_pos = { } lastlineno = self . firstlineno lastlinepos = 0 co_code = bytearray ( ) co_lnotab = bytearray ( ) for i , ( op , arg ) in enumerate ( self . code ) : if isinstance ( op , Label ) : label_pos [ op ] = len ( co_code ) elif op is SetLineno : incr_lineno = arg - lastlineno incr_pos = len ( co_code ) - lastlinepos lastlineno = arg lastlinepos += incr_pos if incr_lineno != 0 or incr_pos != 0 : while incr_pos > 255 : co_lnotab += b"\xFF\0" incr_pos -= 255 while incr_lineno > 255 : co_lnotab += ( 0xFF00 | incr_pos ) . to_bytes ( 2 , "little" ) incr_pos = 0 incr_lineno -= 255 if incr_pos or incr_lineno : co_lnotab += bytes ( ( incr_pos , incr_lineno ) ) elif op == opcode . EXTENDED_ARG : self . code [ i + 1 ] [ 1 ] |= 1 << 32 elif op not in hasarg : co_code . append ( op ) else : if op in hasconst : if isinstance ( arg , Code ) and i + 2 < len ( self . code ) and self . code [ i + 2 ] [ 0 ] in hascode : arg = arg . to_code ( from_function = is_function ) assert arg is not None arg = index ( co_consts , arg , 0 ) elif op in hasname : arg = index ( co_names , arg ) elif op in hasjump : jumps . append ( ( len ( co_code ) , arg ) ) co_code += op . to_bytes ( 3 , "little" ) continue elif op in haslocal : arg = index ( co_varnames , arg ) elif op in hascompare : arg = index ( cmp_op , arg , can_append = False ) elif op in hasfree : try : arg = index ( co_freevars , arg , can_append = False ) + len ( cellvars ) except IndexError : arg = index ( co_cellvars , arg ) if arg > 0xFFFF : co_code += ( opcode . EXTENDED_ARG | ( ( arg & 0xFFFF0000 ) >> 8 ) ) . to_bytes ( 3 , "little" ) co_code += ( op | ( arg << 8 ) ) . to_bytes ( 3 , "little" ) for pos , label in jumps : jump = label_pos [ label ] if co_code [ pos ] in hasjrel : jump -= pos + 3 if jump > 0xFFFF : raise NotImplementedError ( "Extended jumps not implemented" ) co_code [ pos + 1 ] = jump & 0xFF co_code [ pos + 2 ] = jump >> 8 co_argcount = len ( self . args ) - self . varargs - self . varkwargs - self . kwonly co_stacksize = self . _compute_stacksize ( ) return CodeType ( co_argcount , self . kwonly , len ( co_varnames ) , co_stacksize , co_flags , bytes ( co_code ) , tuple ( co_consts ) , tuple ( co_names ) , tuple ( co_varnames ) , self . filename , self . name , self . firstlineno , bytes ( co_lnotab ) , co_freevars , tuple ( co_cellvars ) )
Assemble a Python code object from a Code object