@@ -1060,37 +1060,90 @@ def test_dlpack_export_non_native_endian_rejected():
10601060 bad_view .__dlpack__ ()
10611061
10621062
1063- @pytest .mark .parametrize (
1064- "dtype" ,
1065- [
1066- np .uint8 ,
1067- np .uint16 ,
1068- np .uint32 ,
1069- np .uint64 ,
1070- np .int8 ,
1071- np .int16 ,
1072- np .int32 ,
1073- np .int64 ,
1074- np .float16 ,
1075- np .float32 ,
1076- np .float64 ,
1077- np .complex64 ,
1078- np .complex128 ,
1079- np .bool_ ,
1080- ],
1081- )
1082- def test_strided_memory_view_dtype_roundtrip_all (dtype ):
1083- """Exercise dtype_dlpack_to_numpy for every NumPy-native DLPack dtype.
1084-
1085- bfloat16 (kDLBfloat) is excluded -- NumPy's __dlpack__ doesn't reliably
1086- export ml_dtypes-extended dtypes; cover separately via jax/torch if needed.
1063+ def test_strided_memory_view_proxy_cai_only_has_dlpack_false ():
1064+ """``_StridedMemoryViewProxy`` records ``has_dlpack=False`` for an object
1065+ that exposes only ``__cuda_array_interface__`` (check_has_dlpack CAI branch)."""
1066+ from cuda .core ._memoryview import _StridedMemoryViewProxy
1067+
1068+ obj = _make_cuda_array_interface_obj (shape = (2 ,), strides = None )
1069+ proxy = _StridedMemoryViewProxy (obj )
1070+ assert proxy .has_dlpack is False
1071+ assert proxy .obj is obj
1072+
1073+
1074+ def test_view_as_cai_device_pointer_and_stream_ordering (init_cuda ):
1075+ """``view_as_cai`` on a real device pointer resolves the device ordinal via
1076+ ``cuPointerGetAttribute`` and takes the cross-stream branch when the CAI
1077+ ``stream`` differs from the consumer stream.
1078+
1079+ This only exercises the code path and checks *device* correctness (ptr,
1080+ device_id, shape); it does NOT verify stream-order correctness. Uses a
1081+ synthetic CAI object backed by a genuine device allocation, so the
1082+ cupy/numba-only device branch is exercised without those optional deps.
10871083 """
1088- src = np .zeros (3 , dtype = dtype )
1089- # Probe NumPy first: if it can't export this dtype, skip as env limit.
1090- # Any failure AFTER the probe is OUR consumer regression and must fail.
1091- try :
1092- src .__dlpack__ ()
1093- except (BufferError , TypeError ) as e :
1094- pytest .skip (f"NumPy does not export { np .dtype (dtype )} via DLPack: { e } " )
1095- view = StridedMemoryView .from_dlpack (src , stream_ptr = - 1 )
1096- assert view .dtype == np .dtype (dtype ) # .dtype triggers dtype_dlpack_to_numpy
1084+ dev = init_cuda
1085+ buffer = dev .memory_resource .allocate (64 , stream = dev .default_stream )
1086+ producer = dev .create_stream ()
1087+ consumer = dev .create_stream ()
1088+ obj = _make_cuda_array_interface_obj (
1089+ shape = (8 ,),
1090+ strides = None ,
1091+ typestr = "<f4" ,
1092+ data = (int (buffer .handle ), False ),
1093+ )
1094+ obj .__cuda_array_interface__ ["stream" ] = int (producer .handle )
1095+
1096+ view = StridedMemoryView .from_cuda_array_interface (obj , stream_ptr = consumer .handle )
1097+
1098+ assert view .is_device_accessible is True
1099+ assert view .ptr == int (buffer .handle )
1100+ assert view .device_id == dev .device_id
1101+ assert view .shape == (8 ,)
1102+ dev .default_stream .sync ()
1103+
1104+
1105+ def test_strided_memory_view_init_cai_path_deprecated (init_cuda ):
1106+ """The deprecated ``StridedMemoryView(obj)`` constructor routes a CAI-only
1107+ object through the CAI branch (warn + ``view_as_cai``), not the DLPack one."""
1108+ obj = _make_cuda_array_interface_obj (shape = (4 ,), strides = None , typestr = "<f4" , data = (0 , False ))
1109+ with pytest .deprecated_call (match = "CUDA-array-interface-supporting object is deprecated" ):
1110+ view = StridedMemoryView (obj , stream_ptr = - 1 )
1111+ assert view .is_device_accessible is True
1112+ assert view .shape == (4 ,)
1113+ assert view .device_id == init_cuda .device_id
1114+
1115+
1116+ def test_dlpack_export_device_accessible_cai_view (init_cuda ):
1117+ """Exporting a device-accessible CAI-backed view (no dl_tensor) drives the
1118+ ``_smv_get_dl_device`` branch that calls ``get_buffer``/``classify_dl_device``
1119+ and reports a CUDA device via ``__dlpack_device__``."""
1120+ dev = init_cuda
1121+ buffer = dev .memory_resource .allocate (64 , stream = dev .default_stream )
1122+ obj = _make_cuda_array_interface_obj (
1123+ shape = (8 ,),
1124+ strides = None ,
1125+ typestr = "<f4" ,
1126+ data = (int (buffer .handle ), False ),
1127+ )
1128+ view = StridedMemoryView .from_cuda_array_interface (obj , stream_ptr = - 1 )
1129+
1130+ device_type , device_id = view .__dlpack_device__ ()
1131+ assert device_type == int (DLDeviceType .kDLCUDA )
1132+ assert device_id == dev .device_id
1133+
1134+ capsule = view .__dlpack__ ()
1135+ assert _PyCapsule_IsValid (capsule , b"dltensor" ) == 1
1136+ del capsule # unconsumed -> deleter frees the managed tensor
1137+ dev .default_stream .sync ()
1138+
1139+
1140+ def test_strided_memory_view_repr_with_none_dtype (init_cuda ):
1141+ """``__repr__`` of a view whose dtype is None renders the dtype via
1142+ ``get_simple_repr`` taking the builtins branch (NoneType)."""
1143+ dev = init_cuda
1144+ buffer = dev .memory_resource .allocate (16 , stream = dev .default_stream )
1145+ view = StridedMemoryView .from_buffer (buffer , shape = (16 ,), itemsize = 1 , dtype = None )
1146+ assert view .dtype is None
1147+ r = repr (view )
1148+ assert r .startswith ("StridedMemoryView(ptr=" )
1149+ assert "dtype=NoneType" in r
0 commit comments