diff --git a/cuda_core/cuda/core/experimental/_stream.py b/cuda_core/cuda/core/experimental/_stream.py index 2baffb870..c50998db9 100644 --- a/cuda_core/cuda/core/experimental/_stream.py +++ b/cuda_core/cuda/core/experimental/_stream.py @@ -5,6 +5,7 @@ from __future__ import annotations import os +import warnings import weakref from dataclasses import dataclass from typing import TYPE_CHECKING, Optional, Tuple, Union @@ -87,9 +88,19 @@ def _init(obj=None, *, options: Optional[StreamOptions] = None): if obj is not None and options is not None: raise ValueError("obj and options cannot be both specified") if obj is not None: - if not hasattr(obj, "__cuda_stream__"): - raise ValueError - info = obj.__cuda_stream__ + try: + info = obj.__cuda_stream__() + except AttributeError as e: + raise TypeError(f"{type(obj)} object does not have a '__cuda_stream__' method") from e + except TypeError: + info = obj.__cuda_stream__ + warnings.simplefilter("once", DeprecationWarning) + warnings.warn( + "Implementing __cuda_stream__ as an attribute is deprecated; it must be implemented as a method", + stacklevel=3, + category=DeprecationWarning, + ) + assert info[0] == 0 self._mnff.handle = cuda.CUstream(info[1]) # TODO: check if obj is created under the current context/device @@ -132,7 +143,6 @@ def close(self): """ self._mnff.close() - @property def __cuda_stream__(self) -> Tuple[int, int]: """Return an instance of a __cuda_stream__ protocol.""" return (0, self.handle) @@ -279,7 +289,6 @@ def from_handle(handle: int) -> Stream: """ class _stream_holder: - @property def __cuda_stream__(self): return (0, handle) diff --git a/cuda_core/docs/source/interoperability.rst b/cuda_core/docs/source/interoperability.rst index 3bcdbe680..a3736b2bc 100644 --- a/cuda_core/docs/source/interoperability.rst +++ b/cuda_core/docs/source/interoperability.rst @@ -34,14 +34,13 @@ exposing their own stream types. To address this issue, we propose the ``__cuda_stream__`` protocol (currently version 0) as follows: For any Python objects that are meant to be interpreted as a stream, they -should add a ``__cuda_stream__`` attribute that returns a 2-tuple: The version number +should add a ``__cuda_stream__`` method that returns a 2-tuple: The version number (``0``) and the address of ``cudaStream_t`` (both as Python `int`): .. code-block:: python class MyStream: - @property def __cuda_stream__(self): return (0, self.ptr) diff --git a/cuda_core/docs/source/release.md b/cuda_core/docs/source/release.md index a9e16d6e8..b38d32609 100644 --- a/cuda_core/docs/source/release.md +++ b/cuda_core/docs/source/release.md @@ -5,6 +5,7 @@ maxdepth: 3 --- + 0.2.0 0.1.1 0.1.0 diff --git a/cuda_core/docs/source/release/0.2.0-notes.rst b/cuda_core/docs/source/release/0.2.0-notes.rst new file mode 100644 index 000000000..572567fd1 --- /dev/null +++ b/cuda_core/docs/source/release/0.2.0-notes.rst @@ -0,0 +1,7 @@ +``cuda.core`` v0.2.0 Release notes +================================== + +Breaking changes +---------------- + +- Change ``__cuda_stream__`` from attribute to method \ No newline at end of file diff --git a/cuda_core/examples/simple_multi_gpu_example.py b/cuda_core/examples/simple_multi_gpu_example.py index 89dd6cbea..7b83d844c 100644 --- a/cuda_core/examples/simple_multi_gpu_example.py +++ b/cuda_core/examples/simple_multi_gpu_example.py @@ -81,7 +81,6 @@ class StreamAdaptor: def __init__(self, obj): self.obj = obj - @property def __cuda_stream__(self): # Note: CuPy streams have a .ptr attribute return (0, self.obj.ptr)