def code_object_replace(code: types.CodeType, **kwargs) -> types.CodeType: """ Return a copy of the code object with new values for the specified fields. """ try: kwargs["co_consts"] = tuple(kwargs["co_consts"]) except ValueError: pass # Python 3.8+ if hasattr(code, "replace"): return code.replace(**kwargs) params = [ kwargs.get("co_argcount", code.co_argcount), kwargs.get("co_kwonlyargcount", code.co_kwonlyargcount), kwargs.get("co_nlocals", code.co_nlocals), kwargs.get("co_stacksize", code.co_stacksize), kwargs.get("co_flags", code.co_flags), kwargs.get("co_code", code.co_code), kwargs.get("co_consts", code.co_consts), kwargs.get("co_names", code.co_names), kwargs.get("co_varnames", code.co_varnames), kwargs.get("co_filename", code.co_filename), kwargs.get("co_name", code.co_name), kwargs.get("co_firstlineno", code.co_firstlineno), kwargs.get("co_lnotab", code.co_lnotab), kwargs.get("co_freevars", code.co_freevars), kwargs.get("co_cellvars", code.co_cellvars), ] return types.CodeType(*params)
def replace_paths_in_code(self, co: types.CodeType) -> types.CodeType: new_filename = original_filename = os.path.normpath(co.co_filename) for f, r in self.replace_paths: if original_filename.startswith(f): new_filename = r + original_filename[len(f):] break if self.debug and original_filename not in self.processed_paths: if new_filename != original_filename: self.msgout( 2, "co_filename %r changed to %r" % ( original_filename, new_filename, ), ) else: self.msgout( 2, "co_filename %r remains unchanged" % (original_filename, )) self.processed_paths.append(original_filename) consts = list(co.co_consts) for i in range(len(consts)): # pylint: disable=consider-using-enumerate if isinstance(consts[i], type(co)): consts[i] = self.replace_paths_in_code(consts[i]) return co.replace(co_consts=tuple(consts), co_filename=new_filename)
def _instrument_inner_code_objects(self, code: CodeType, parent_code_object_id: int) -> CodeType: """Apply the instrumentation to all constants of the given code object. :param code: the Code Object that should be instrumented. :param parent_code_object_id: the id of the parent code object, if any. :return: the code object whose constants were instrumented. """ new_consts = [] for const in code.co_consts: if isinstance(const, CodeType): # The const is an inner code object new_consts.append( self._instrument_code_recursive( const, parent_code_object_id=parent_code_object_id)) else: new_consts.append(const) return code.replace(co_consts=tuple(new_consts))
def _instrument_inner_code_objects(self, code: CodeType) -> CodeType: """Apply the instrumentation to all constants of the given code object. Args: code: the Code Object that should be instrumented. Returns: the code object whose constants were instrumented. """ new_consts = [] for const in code.co_consts: if isinstance(const, CodeType): # The const is an inner code object new_consts.append(self._instrument_code_recursive(const)) else: new_consts.append(const) return code.replace(co_consts=tuple(new_consts))
def _instrument_inner_code_objects(self, code: CodeType, parent_code_object_id: int) -> CodeType: """Apply the instrumentation to all constants of the given code object. :param code: The code object to be instrumented. :param parent_code_object_id: Internal id of the code object to which this code object belongs (can be None if `code` is the highest node, i.e. the module node). :return: The code object whose constants were instrumented. """ new_consts = [] for const in code.co_consts: if isinstance(const, CodeType): # The const is an inner code object new_consts.append( self.instrument_code_recursive( const, parent_code_object_id=parent_code_object_id)) else: new_consts.append(const) return code.replace(co_consts=tuple(new_consts))