@@ -10,10 +10,10 @@ use pyo3::{
10
10
ffi:: { self , PyTuple_Size } ,
11
11
pyobject_native_type_extract, pyobject_native_type_named,
12
12
types:: { PyAnyMethods , PyDict , PyDictMethods , PyTuple , PyType } ,
13
- Borrowed , Bound , PyAny , PyObject , PyResult , PyTypeInfo , Python , ToPyObject ,
13
+ Borrowed , Bound , Py , PyAny , PyObject , PyResult , PyTypeInfo , Python , ToPyObject ,
14
14
} ;
15
15
#[ cfg( feature = "half" ) ]
16
- use pyo3:: { sync:: GILOnceCell , Py } ;
16
+ use pyo3:: { sync:: GILOnceCell } ;
17
17
#[ cfg( feature = "gil-refs" ) ]
18
18
use pyo3:: { AsPyPointer , PyNativeType } ;
19
19
@@ -644,56 +644,6 @@ impl<'py> PyArrayDescrMethods<'py> for Bound<'py, PyArrayDescr> {
644
644
645
645
impl Sealed for Bound < ' _ , PyArrayDescr > { }
646
646
647
- /// Weaker form of `Clone` for types that can be cloned while the GIL is held.
648
- ///
649
- /// Any type that implements `Clone` can trivially implement `PyClone` by forwarding
650
- /// to the `Clone::clone` method. However, some types (notably `PyObject`) can only
651
- /// be safely cloned while the GIL is held, and therefore cannot implement `Clone`.
652
- /// This trait provides a mechanism for performing a clone while the GIL is held, as
653
- /// represented by the [`Python`] token provided as an argument to the [`py_clone`]
654
- /// method. All API's in the `numpy` crate require the GIL to be held, so this weaker
655
- /// alternative to `Clone` is a sufficient prerequisite for implementing the
656
- /// [`Element`] trait.
657
- ///
658
- /// # Implementing `PyClone`
659
- /// Implementing this trait is trivial for most types, and simply requires defining
660
- /// the `py_clone` method. The `vec_from_slice` and `array_from_view` methods have
661
- /// default implementations that simply map the `py_clone` method to each item in
662
- /// the collection, but types may want to override these implementations if there
663
- /// is a more efficient way to perform the conversion. In particular, `Clone` types
664
- /// may instead defer to the `ToOwned::to_owned` and `ArrayBase::to_owned` methods
665
- /// for increased performance.
666
- ///
667
- /// [`py_clone`]: Self::py_clone
668
- pub trait PyClone : Sized {
669
- /// Create a clone of the value while the GIL is guaranteed to be held.
670
- fn py_clone ( & self , py : Python < ' _ > ) -> Self ;
671
-
672
- /// Create an owned copy of the slice while the GIL is guaranteed to be held.
673
- ///
674
- /// Some types may provide implementations of this method that are more efficient
675
- /// than simply mapping the `py_clone` method to each element in the slice.
676
- #[ inline]
677
- fn vec_from_slice ( py : Python < ' _ > , slc : & [ Self ] ) -> Vec < Self > {
678
- slc. iter ( ) . map ( |elem| elem. py_clone ( py) ) . collect ( )
679
- }
680
-
681
- /// Create an owned copy of the array while the GIL is guaranteed to be held.
682
- ///
683
- /// Some types may provide implementations of this method that are more efficient
684
- /// than simply mapping the `py_clone` method to each element in the view.
685
- #[ inline]
686
- fn array_from_view < D > (
687
- py : Python < ' _ > ,
688
- view : :: ndarray:: ArrayView < ' _ , Self , D > ,
689
- ) -> :: ndarray:: Array < Self , D >
690
- where
691
- D : :: ndarray:: Dimension ,
692
- {
693
- view. map ( |elem| elem. py_clone ( py) )
694
- }
695
- }
696
-
697
647
/// Represents that a type can be an element of `PyArray`.
698
648
///
699
649
/// Currently, only integer/float/complex/object types are supported. The [NumPy documentation][enumerated-types]
@@ -731,7 +681,7 @@ pub trait PyClone: Sized {
731
681
///
732
682
/// [enumerated-types]: https://numpy.org/doc/stable/reference/c-api/dtype.html#enumerated-types
733
683
/// [data-models]: https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models
734
- pub unsafe trait Element : PyClone + Send {
684
+ pub unsafe trait Element : Sized + Send {
735
685
/// Flag that indicates whether this type is trivially copyable.
736
686
///
737
687
/// It should be set to true for all trivially copyable types (like scalar types
@@ -749,6 +699,33 @@ pub unsafe trait Element: PyClone + Send {
749
699
750
700
/// Returns the associated type descriptor ("dtype") for the given element type.
751
701
fn get_dtype_bound ( py : Python < ' _ > ) -> Bound < ' _ , PyArrayDescr > ;
702
+
703
+ /// Create a clone of the value while the GIL is guaranteed to be held.
704
+ fn clone_ref ( & self , py : Python < ' _ > ) -> Self ;
705
+
706
+ /// Create an owned copy of the slice while the GIL is guaranteed to be held.
707
+ ///
708
+ /// Some types may provide implementations of this method that are more efficient
709
+ /// than simply mapping the `py_clone` method to each element in the slice.
710
+ #[ inline]
711
+ fn vec_from_slice ( py : Python < ' _ > , slc : & [ Self ] ) -> Vec < Self > {
712
+ slc. iter ( ) . map ( |elem| elem. clone_ref ( py) ) . collect ( )
713
+ }
714
+
715
+ /// Create an owned copy of the array while the GIL is guaranteed to be held.
716
+ ///
717
+ /// Some types may provide implementations of this method that are more efficient
718
+ /// than simply mapping the `py_clone` method to each element in the view.
719
+ #[ inline]
720
+ fn array_from_view < D > (
721
+ py : Python < ' _ > ,
722
+ view : :: ndarray:: ArrayView < ' _ , Self , D > ,
723
+ ) -> :: ndarray:: Array < Self , D >
724
+ where
725
+ D : :: ndarray:: Dimension ,
726
+ {
727
+ view. map ( |elem| elem. clone_ref ( py) )
728
+ }
752
729
}
753
730
754
731
fn npy_int_type_lookup < T , T0 , T1 , T2 > ( npy_types : [ NPY_TYPES ; 3 ] ) -> NPY_TYPES {
@@ -796,34 +773,33 @@ fn npy_int_type<T: Bounded + Zero + Sized + PartialEq>() -> NPY_TYPES {
796
773
}
797
774
}
798
775
799
- // Implements `PyClone` for a type that implements `Clone`
800
- macro_rules! impl_py_clone {
801
- ( $ty : ty $ ( ; [ $param : ident $ ( : $bound : ident ) ? ] ) ? ) => {
802
- impl <$ ( $param$ ( : $bound ) * ) ?> $crate :: dtype :: PyClone for $ty {
803
- #[ inline]
804
- fn py_clone ( & self , _py: :: pyo3:: Python <' _>) -> Self {
805
- self . clone( )
806
- }
776
+ // Invoke within the `Element` impl for a `Clone` type to provide an efficient
777
+ // implementation of the cloning methods
778
+ macro_rules! clone_methods_impl {
779
+ ( $Self : ty ) => {
780
+ #[ inline]
781
+ fn clone_ref ( & self , _py: :: pyo3:: Python <' _>) -> $ Self {
782
+ :: std :: clone:: Clone :: clone ( self )
783
+ }
807
784
808
- #[ inline]
809
- fn vec_from_slice( _py: :: pyo3:: Python <' _>, slc: & [ Self ] ) -> Vec <Self > {
810
- slc . to_owned( )
811
- }
785
+ #[ inline]
786
+ fn vec_from_slice( _py: :: pyo3:: Python <' _>, slc: & [ $ Self] ) -> Vec <$ Self> {
787
+ :: std :: borrow :: ToOwned :: to_owned( slc )
788
+ }
812
789
813
- #[ inline]
814
- fn array_from_view<D >(
815
- _py: :: pyo3:: Python <' _>,
816
- view: :: ndarray:: ArrayView <' _, Self , D >
817
- ) -> :: ndarray:: Array <Self , D >
818
- where
819
- D : :: ndarray:: Dimension
820
- {
821
- view. to_owned( )
822
- }
790
+ #[ inline]
791
+ fn array_from_view<D >(
792
+ _py: :: pyo3:: Python <' _>,
793
+ view: :: ndarray:: ArrayView <' _, $Self, D >
794
+ ) -> :: ndarray:: Array <$Self, D >
795
+ where
796
+ D : :: ndarray:: Dimension
797
+ {
798
+ :: ndarray:: ArrayView :: to_owned( & view)
823
799
}
824
800
}
825
801
}
826
- pub ( crate ) use impl_py_clone ;
802
+ pub ( crate ) use clone_methods_impl ;
827
803
828
804
macro_rules! impl_element_scalar {
829
805
( @impl : $ty: ty, $npy_type: expr $( , #[ $meta: meta] ) * ) => {
@@ -834,8 +810,9 @@ macro_rules! impl_element_scalar {
834
810
fn get_dtype_bound( py: Python <' _>) -> Bound <' _, PyArrayDescr > {
835
811
PyArrayDescr :: from_npy_type( py, $npy_type)
836
812
}
813
+
814
+ clone_methods_impl!( $ty) ;
837
815
}
838
- impl_py_clone!( $ty) ;
839
816
} ;
840
817
( $ty: ty => $npy_type: ident $( , #[ $meta: meta] ) * ) => {
841
818
impl_element_scalar!( @impl : $ty, NPY_TYPES :: $npy_type $( , #[ $meta] ) * ) ;
@@ -870,10 +847,9 @@ unsafe impl Element for bf16 {
870
847
. clone_ref ( py)
871
848
. into_bound ( py)
872
849
}
873
- }
874
850
875
- # [ cfg ( feature = "half" ) ]
876
- impl_py_clone ! ( bf16 ) ;
851
+ clone_methods_impl ! ( Self ) ;
852
+ }
877
853
878
854
impl_element_scalar ! ( Complex32 => NPY_CFLOAT ,
879
855
#[ doc = "Complex type with `f32` components which maps to `numpy.csingle` (`numpy.complex64`)." ] ) ;
@@ -883,19 +859,17 @@ impl_element_scalar!(Complex64 => NPY_CDOUBLE,
883
859
#[ cfg( any( target_pointer_width = "32" , target_pointer_width = "64" ) ) ]
884
860
impl_element_scalar ! ( usize , isize ) ;
885
861
886
- impl PyClone for PyObject {
887
- #[ inline]
888
- fn py_clone ( & self , py : Python < ' _ > ) -> Self {
889
- self . clone_ref ( py)
890
- }
891
- }
892
-
893
862
unsafe impl Element for PyObject {
894
863
const IS_COPY : bool = false ;
895
864
896
865
fn get_dtype_bound ( py : Python < ' _ > ) -> Bound < ' _ , PyArrayDescr > {
897
866
PyArrayDescr :: object_bound ( py)
898
867
}
868
+
869
+ #[ inline]
870
+ fn clone_ref ( & self , py : Python < ' _ > ) -> Self {
871
+ Py :: clone_ref ( self , py)
872
+ }
899
873
}
900
874
901
875
#[ cfg( test) ]
0 commit comments