1+ use crate :: ffi_ptr_ext:: FfiPtrExt ;
12use crate :: instance:: { Borrowed , Bound } ;
3+ use crate :: types:: any:: PyAnyMethods ;
24use crate :: { ffi, FromPyObject , IntoPy , Py , PyAny , PyNativeType , PyResult , Python , ToPyObject } ;
35use std:: borrow:: Cow ;
46use std:: ops:: Index ;
@@ -17,14 +19,45 @@ pub struct PyBytes(PyAny);
1719pyobject_native_type_core ! ( PyBytes , pyobject_native_static_type_object!( ffi:: PyBytes_Type ) , #checkfunction=ffi:: PyBytes_Check ) ;
1820
1921impl PyBytes {
22+ /// Deprecated form of [`PyBytes::new_bound`].
23+ #[ cfg_attr(
24+ not( feature = "gil-refs" ) ,
25+ deprecated(
26+ since = "0.21.0" ,
27+ note = "`PyBytes::new` will be replaced by `PyBytes::new_bound` in a future PyO3 version"
28+ )
29+ ) ]
30+ pub fn new < ' p > ( py : Python < ' p > , s : & [ u8 ] ) -> & ' p PyBytes {
31+ Self :: new_bound ( py, s) . into_gil_ref ( )
32+ }
33+
2034 /// Creates a new Python bytestring object.
2135 /// The bytestring is initialized by copying the data from the `&[u8]`.
2236 ///
2337 /// Panics if out of memory.
24- pub fn new < ' p > ( py : Python < ' p > , s : & [ u8 ] ) -> & ' p PyBytes {
38+ pub fn new_bound < ' p > ( py : Python < ' p > , s : & [ u8 ] ) -> Bound < ' p , PyBytes > {
2539 let ptr = s. as_ptr ( ) as * const c_char ;
2640 let len = s. len ( ) as ffi:: Py_ssize_t ;
27- unsafe { py. from_owned_ptr ( ffi:: PyBytes_FromStringAndSize ( ptr, len) ) }
41+ unsafe {
42+ ffi:: PyBytes_FromStringAndSize ( ptr, len)
43+ . assume_owned ( py)
44+ . downcast_into_unchecked ( )
45+ }
46+ }
47+
48+ /// Deprecated form of [`PyBytes::new_bound_with`].
49+ #[ cfg_attr(
50+ not( feature = "gil-refs" ) ,
51+ deprecated(
52+ since = "0.21.0" ,
53+ note = "`PyBytes::new_with` will be replaced by `PyBytes::new_bound_with` in a future PyO3 version"
54+ )
55+ ) ]
56+ pub fn new_with < F > ( py : Python < ' _ > , len : usize , init : F ) -> PyResult < & PyBytes >
57+ where
58+ F : FnOnce ( & mut [ u8 ] ) -> PyResult < ( ) > ,
59+ {
60+ Self :: new_bound_with ( py, len, init) . map ( Bound :: into_gil_ref)
2861 }
2962
3063 /// Creates a new Python `bytes` object with an `init` closure to write its contents.
@@ -41,31 +74,31 @@ impl PyBytes {
4174 ///
4275 /// # fn main() -> PyResult<()> {
4376 /// Python::with_gil(|py| -> PyResult<()> {
44- /// let py_bytes = PyBytes::new_with (py, 10, |bytes: &mut [u8]| {
77+ /// let py_bytes = PyBytes::new_bound_with (py, 10, |bytes: &mut [u8]| {
4578 /// bytes.copy_from_slice(b"Hello Rust");
4679 /// Ok(())
4780 /// })?;
48- /// let bytes: &[u8] = FromPyObject:: extract(py_bytes )?;
81+ /// let bytes: &[u8] = py_bytes. extract()?;
4982 /// assert_eq!(bytes, b"Hello Rust");
5083 /// Ok(())
5184 /// })
5285 /// # }
5386 /// ```
54- pub fn new_with < F > ( py : Python < ' _ > , len : usize , init : F ) -> PyResult < & PyBytes >
87+ pub fn new_bound_with < F > ( py : Python < ' _ > , len : usize , init : F ) -> PyResult < Bound < ' _ , PyBytes > >
5588 where
5689 F : FnOnce ( & mut [ u8 ] ) -> PyResult < ( ) > ,
5790 {
5891 unsafe {
5992 let pyptr = ffi:: PyBytes_FromStringAndSize ( std:: ptr:: null ( ) , len as ffi:: Py_ssize_t ) ;
6093 // Check for an allocation error and return it
61- let pypybytes : Py < PyBytes > = Py :: from_owned_ptr_or_err ( py, pyptr ) ? ;
94+ let pybytes = pyptr . assume_owned_or_err ( py) ? . downcast_into_unchecked ( ) ;
6295 let buffer: * mut u8 = ffi:: PyBytes_AsString ( pyptr) . cast ( ) ;
6396 debug_assert ! ( !buffer. is_null( ) ) ;
6497 // Zero-initialise the uninitialised bytestring
6598 std:: ptr:: write_bytes ( buffer, 0u8 , len) ;
6699 // (Further) Initialise the bytestring in init
67100 // If init returns an Err, pypybytearray will automatically deallocate the buffer
68- init ( std:: slice:: from_raw_parts_mut ( buffer, len) ) . map ( |_| pypybytes . into_ref ( py ) )
101+ init ( std:: slice:: from_raw_parts_mut ( buffer, len) ) . map ( |_| pybytes )
69102 }
70103 }
71104
@@ -80,10 +113,23 @@ impl PyBytes {
80113 /// `std::slice::from_raw_parts`, this is
81114 /// unsafe](https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html#safety).
82115 pub unsafe fn from_ptr ( py : Python < ' _ > , ptr : * const u8 , len : usize ) -> & PyBytes {
83- py. from_owned_ptr ( ffi:: PyBytes_FromStringAndSize (
84- ptr as * const _ ,
85- len as isize ,
86- ) )
116+ Self :: bound_from_ptr ( py, ptr, len) . into_gil_ref ( )
117+ }
118+
119+ /// Creates a new Python byte string object from a raw pointer and length.
120+ ///
121+ /// Panics if out of memory.
122+ ///
123+ /// # Safety
124+ ///
125+ /// This function dereferences the raw pointer `ptr` as the
126+ /// leading pointer of a slice of length `len`. [As with
127+ /// `std::slice::from_raw_parts`, this is
128+ /// unsafe](https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html#safety).
129+ pub unsafe fn bound_from_ptr ( py : Python < ' _ > , ptr : * const u8 , len : usize ) -> Bound < ' _ , PyBytes > {
130+ ffi:: PyBytes_FromStringAndSize ( ptr as * const _ , len as isize )
131+ . assume_owned ( py)
132+ . downcast_into_unchecked ( )
87133 }
88134
89135 /// Gets the Python string as a byte slice.
@@ -160,7 +206,7 @@ impl<'source> FromPyObject<'source> for Cow<'source, [u8]> {
160206
161207impl ToPyObject for Cow < ' _ , [ u8 ] > {
162208 fn to_object ( & self , py : Python < ' _ > ) -> Py < PyAny > {
163- PyBytes :: new ( py, self . as_ref ( ) ) . into ( )
209+ PyBytes :: new_bound ( py, self . as_ref ( ) ) . into ( )
164210 }
165211}
166212
@@ -171,6 +217,7 @@ impl IntoPy<Py<PyAny>> for Cow<'_, [u8]> {
171217}
172218
173219#[ cfg( test) ]
220+ #[ cfg_attr( not( feature = "gil-refs" ) , allow( deprecated) ) ]
174221mod tests {
175222 use super :: * ;
176223
0 commit comments