def copy_tb(base_tb, tb_next): # TracebackType has no public constructor, so allocate one the hard way try: raise ValueError except ValueError as exc: new_tb = exc.__traceback__ c_new_tb = CTraceback.from_address(id(new_tb)) # At the C level, tb_next either pointer to the next traceback or is # NULL. c_void_p and the .tb_next accessor both convert NULL to None, # but we shouldn't DECREF None just because we assigned to a NULL # pointer! Here we know that our new traceback has only 1 frame in it, # so we can assume the tb_next field is NULL. assert c_new_tb.tb_next is None # If tb_next is None, then we want to set c_new_tb.tb_next to NULL, # which it already is, so we're done. Otherwise, we have to actually # do some work: if tb_next is not None: _ctypes.Py_INCREF(tb_next) c_new_tb.tb_next = id(tb_next) assert c_new_tb.tb_frame is not None _ctypes.Py_INCREF(base_tb.tb_frame) old_tb_frame = new_tb.tb_frame c_new_tb.tb_frame = id(base_tb.tb_frame) _ctypes.Py_DECREF(old_tb_frame) c_new_tb.tb_lasti = base_tb.tb_lasti c_new_tb.tb_lineno = base_tb.tb_lineno return new_tb
def set_aio_task_coro( task: "asyncio.Task[Any]", new_coro: Coroutine[Any, Any, Any] ) -> None: try: task._coro = new_coro # type: ignore return except AttributeError as ex: if sys.implementation.name != "cpython": # pragma: no cover raise if "is not writable" not in str(ex): # pragma: no cover raise # If using the C accelerator on CPython, the setter isn't # even present and we need to use ctypes to change the # coroutine field. global aio_task_coro_c_offset import ctypes old_coro = get_aio_task_coro(task) if aio_task_coro_c_offset is None: # Deduce the offset by scanning the task object representation # for id(task._coro) aio_task_coro_c_offset = _aligned_ptr_offset_in_object(task, old_coro) if aio_task_coro_c_offset is None: # pragma: no cover raise RuntimeError("Couldn't determine C offset of asyncio.Task._coro") # (Explanation copied from trio._core._multierror, applies equally well here.) # How to handle refcounting? I don't want to use ctypes.py_object because # I don't understand or trust it, and I don't want to use # ctypes.pythonapi.Py_{Inc,Dec}Ref because we might clash with user code # that also tries to use them but with different types. So private _ctypes # APIs it is! import _ctypes # type: ignore coro_field = ctypes.c_size_t.from_address(id(task) + aio_task_coro_c_offset) assert coro_field.value == id(old_coro) _ctypes.Py_INCREF(new_coro) coro_field.value = id(new_coro) _ctypes.Py_DECREF(old_coro)
def append(self, data): new_node = Node(data, None, None) _ctypes.Py_INCREF(new_node) print("Created new node with id ", id(new_node), " and value ", data, " and # refs: ", sys.getrefcount(new_node)) print("Referencing the new object: ", gc.get_referrers(new_node)) if self.head is None: self.head = self.tail = new_node else: new_node.nextprev = Node.xor(self.tail, None) # detected self reference, happens with first element. if (self.tail.nextprev == 0): tail_prev = id(None) else: tail_prev = id(None) ^ self.tail.nextprev tail_next = id(new_node) print("Linked node ref ", tail_prev, " to ", tail_next) self.tail.nextprev = tail_prev ^ tail_next self.tail = new_node