code: def get_buffer_owner(data: Any) -> Optional[BufferOwner]:
      """Get the owner of `data`, if one exists
  
      Search through the stack of data owners in order to find an
      owner BufferOwner (incl. subclasses).
  
      Parameters
      ----------
      data
          The data object to search for a BufferOwner instance
  
      Return
      ------
      BufferOwner or None
          The owner of `data` if found otherwise None.
      """
  
      if isinstance(data, BufferOwner):
          return data
      if hasattr(data, "owner"):
          return get_buffer_owner(data.owner)
      return None
  
file_path: cudf/python/cudf/cudf/core/buffer/utils.py
imports: from __future__ import annotations
  import threading
  from contextlib import ContextDecorator
  from typing import Any, Dict, Optional, Tuple, Type, Union
  from cudf.core.buffer.buffer import Buffer, BufferOwner, cuda_array_interface_wrapper, get_ptr_and_size
  from cudf.core.buffer.exposure_tracked_buffer import ExposureTrackedBuffer
  from cudf.core.buffer.spill_manager import get_global_manager
  from cudf.core.buffer.spillable_buffer import SpillableBuffer, SpillableBufferOwner, SpillLock
  from cudf.options import get_option
label_desc: Use image node_id 1 for calling a global function with example usage: get_buffer_owner(data) and returns: None, data, get_buffer_owner