@@ -461,6 +461,88 @@ fn release_exported(exported: &mut ArrowDeviceArrayWithSchema) {
461461 release_device_array ( & mut exported. array ) ;
462462}
463463
464+ /// Return non-owning details from Arrow Device capsules for Python-side smoke consumers.
465+ #[ pyfunction]
466+ fn _debug_arrow_device_array_capsule_summary < ' py > (
467+ py : Python < ' py > ,
468+ schema : Bound < ' py , PyCapsule > ,
469+ device_array : Bound < ' py , PyCapsule > ,
470+ ) -> PyResult < Bound < ' py , PyDict > > {
471+ let schema = unsafe {
472+ schema
473+ . pointer_checked ( Some ( ARROW_SCHEMA_CAPSULE_NAME ) ) ?
474+ . cast :: < FFI_ArrowSchema > ( )
475+ . as_ref ( )
476+ } ;
477+ let device_array = unsafe {
478+ device_array
479+ . pointer_checked ( Some ( ARROW_DEVICE_ARRAY_CAPSULE_NAME ) ) ?
480+ . cast :: < ArrowDeviceArray > ( )
481+ . as_ref ( )
482+ } ;
483+
484+ let summary = PyDict :: new ( py) ;
485+ summary. set_item ( "schema_live" , schema. release . is_some ( ) ) ?;
486+ summary. set_item ( "array_live" , device_array. array . release . is_some ( ) ) ?;
487+ summary. set_item ( "is_cuda" , device_array. device_type == ARROW_DEVICE_CUDA ) ?;
488+ summary. set_item ( "device_type" , device_array. device_type ) ?;
489+ summary. set_item ( "device_id" , device_array. device_id ) ?;
490+ summary. set_item ( "length" , device_array. array . length ) ?;
491+ summary. set_item ( "null_count" , device_array. array . null_count ) ?;
492+ summary. set_item ( "n_buffers" , device_array. array . n_buffers ) ?;
493+ summary. set_item ( "n_children" , device_array. array . n_children ) ?;
494+ Ok ( summary)
495+ }
496+
497+ /// Simulate a Python Arrow Device consumer taking ownership from the returned capsules.
498+ #[ pyfunction]
499+ fn _debug_consume_arrow_device_array_capsules (
500+ schema : Bound < ' _ , PyCapsule > ,
501+ device_array : Bound < ' _ , PyCapsule > ,
502+ ) -> PyResult < ( bool , bool , bool , bool , bool , bool ) > {
503+ let mut schema_ptr = schema
504+ . pointer_checked ( Some ( ARROW_SCHEMA_CAPSULE_NAME ) ) ?
505+ . cast :: < FFI_ArrowSchema > ( ) ;
506+ let mut device_array_ptr = device_array
507+ . pointer_checked ( Some ( ARROW_DEVICE_ARRAY_CAPSULE_NAME ) ) ?
508+ . cast :: < ArrowDeviceArray > ( ) ;
509+
510+ let schema_ref = unsafe { schema_ptr. as_mut ( ) } ;
511+ let device_array_ref = unsafe { device_array_ptr. as_mut ( ) } ;
512+ let schema_had_release = schema_ref. release . is_some ( ) ;
513+ let array_had_release = device_array_ref. array . release . is_some ( ) ;
514+
515+ release_schema ( schema_ref) ;
516+ release_device_array ( device_array_ref) ;
517+
518+ let schema_release_cleared = schema_ref. release . is_none ( ) ;
519+ let array_release_cleared = device_array_ref. array . release . is_none ( ) ;
520+
521+ set_capsule_name ( & schema, USED_ARROW_SCHEMA_CAPSULE_NAME ) ?;
522+ set_capsule_name ( & device_array, USED_ARROW_DEVICE_ARRAY_CAPSULE_NAME ) ?;
523+
524+ Ok ( (
525+ schema_had_release,
526+ array_had_release,
527+ schema_release_cleared,
528+ array_release_cleared,
529+ capsule_is_valid ( & schema, USED_ARROW_SCHEMA_CAPSULE_NAME ) ,
530+ capsule_is_valid ( & device_array, USED_ARROW_DEVICE_ARRAY_CAPSULE_NAME ) ,
531+ ) )
532+ }
533+
534+ fn set_capsule_name ( capsule : & Bound < ' _ , PyCapsule > , name : & CStr ) -> PyResult < ( ) > {
535+ let result = unsafe { ffi:: PyCapsule_SetName ( capsule. as_ptr ( ) , name. as_ptr ( ) ) } ;
536+ if result != 0 {
537+ return Err ( PyErr :: fetch ( capsule. py ( ) ) ) ;
538+ }
539+ Ok ( ( ) )
540+ }
541+
542+ fn capsule_is_valid ( capsule : & Bound < ' _ , PyCapsule > , name : & CStr ) -> bool {
543+ unsafe { ffi:: PyCapsule_IsValid ( capsule. as_ptr ( ) , name. as_ptr ( ) ) == 1 }
544+ }
545+
464546fn schema_capsule < ' py > (
465547 py : Python < ' py > ,
466548 schema : FFI_ArrowSchema ,
@@ -573,6 +655,14 @@ fn _lib(m: &Bound<PyModule>) -> PyResult<()> {
573655 m. add_function ( wrap_pyfunction ! ( cuda_available, m) ?) ?;
574656 m. add_function ( wrap_pyfunction ! ( _debug_array_metadata_dtype, m) ?) ?;
575657 m. add_function ( wrap_pyfunction ! ( _debug_array_metadata_display_values, m) ?) ?;
658+ m. add_function ( wrap_pyfunction ! (
659+ _debug_arrow_device_array_capsule_summary,
660+ m
661+ ) ?) ?;
662+ m. add_function ( wrap_pyfunction ! (
663+ _debug_consume_arrow_device_array_capsules,
664+ m
665+ ) ?) ?;
576666 m. add_function ( wrap_pyfunction ! ( export_device_array, m) ?) ?;
577667 Ok ( ( ) )
578668}
0 commit comments