Add `Py::bind`, `Py::into_bound`, and `Py::bind_borrowed`
This commit is contained in:
parent
0f242c399d
commit
e8e6fb93d7
|
@ -832,17 +832,18 @@ where
|
||||||
|
|
||||||
impl<T> Py<T> {
|
impl<T> Py<T> {
|
||||||
/// Attaches this `Py` to the given Python context, allowing access to further Python APIs.
|
/// Attaches this `Py` to the given Python context, allowing access to further Python APIs.
|
||||||
pub(crate) fn attach<'py>(&self, _py: Python<'py>) -> &Bound<'py, T> {
|
pub fn bind<'py>(&self, _py: Python<'py>) -> &Bound<'py, T> {
|
||||||
// Safety: `Bound` has the same layout as `Py`
|
// Safety: `Bound` has the same layout as `Py`
|
||||||
unsafe { &*(self as *const Py<T>).cast() }
|
unsafe { &*(self as *const Py<T>).cast() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as `attach` but takes ownership of `self`.
|
/// Same as `bind` but takes ownership of `self`.
|
||||||
pub(crate) fn attach_into(self, py: Python<'_>) -> Bound<'_, T> {
|
pub fn into_bound(self, py: Python<'_>) -> Bound<'_, T> {
|
||||||
Bound(py, ManuallyDrop::new(self))
|
Bound(py, ManuallyDrop::new(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn attach_borrow<'a, 'py>(&'a self, py: Python<'py>) -> Borrowed<'a, 'py, T> {
|
/// Same as `bind` but produces a `Borrowed<T>` instead of a `Bound<T>`.
|
||||||
|
pub fn bind_borrowed<'a, 'py>(&'a self, py: Python<'py>) -> Borrowed<'a, 'py, T> {
|
||||||
Borrowed(self.0, PhantomData, py)
|
Borrowed(self.0, PhantomData, py)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -957,7 +958,7 @@ impl<T> Py<T> {
|
||||||
where
|
where
|
||||||
N: IntoPy<Py<PyString>>,
|
N: IntoPy<Py<PyString>>,
|
||||||
{
|
{
|
||||||
self.attach(py).as_any().getattr(attr_name).map(Into::into)
|
self.bind(py).as_any().getattr(attr_name).map(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets an attribute value.
|
/// Sets an attribute value.
|
||||||
|
@ -987,9 +988,9 @@ impl<T> Py<T> {
|
||||||
N: IntoPy<Py<PyString>>,
|
N: IntoPy<Py<PyString>>,
|
||||||
V: IntoPy<Py<PyAny>>,
|
V: IntoPy<Py<PyAny>>,
|
||||||
{
|
{
|
||||||
self.attach(py)
|
self.bind(py)
|
||||||
.as_any()
|
.as_any()
|
||||||
.setattr(attr_name, value.into_py(py).attach_into(py))
|
.setattr(attr_name, value.into_py(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls the object.
|
/// Calls the object.
|
||||||
|
@ -1001,21 +1002,21 @@ impl<T> Py<T> {
|
||||||
args: impl IntoPy<Py<PyTuple>>,
|
args: impl IntoPy<Py<PyTuple>>,
|
||||||
kwargs: Option<&PyDict>,
|
kwargs: Option<&PyDict>,
|
||||||
) -> PyResult<PyObject> {
|
) -> PyResult<PyObject> {
|
||||||
self.attach(py).as_any().call(args, kwargs).map(Into::into)
|
self.bind(py).as_any().call(args, kwargs).map(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls the object with only positional arguments.
|
/// Calls the object with only positional arguments.
|
||||||
///
|
///
|
||||||
/// This is equivalent to the Python expression `self(*args)`.
|
/// This is equivalent to the Python expression `self(*args)`.
|
||||||
pub fn call1(&self, py: Python<'_>, args: impl IntoPy<Py<PyTuple>>) -> PyResult<PyObject> {
|
pub fn call1(&self, py: Python<'_>, args: impl IntoPy<Py<PyTuple>>) -> PyResult<PyObject> {
|
||||||
self.attach(py).as_any().call1(args).map(Into::into)
|
self.bind(py).as_any().call1(args).map(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls the object without arguments.
|
/// Calls the object without arguments.
|
||||||
///
|
///
|
||||||
/// This is equivalent to the Python expression `self()`.
|
/// This is equivalent to the Python expression `self()`.
|
||||||
pub fn call0(&self, py: Python<'_>) -> PyResult<PyObject> {
|
pub fn call0(&self, py: Python<'_>) -> PyResult<PyObject> {
|
||||||
self.attach(py).as_any().call0().map(Into::into)
|
self.bind(py).as_any().call0().map(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls a method on the object.
|
/// Calls a method on the object.
|
||||||
|
@ -1035,7 +1036,7 @@ impl<T> Py<T> {
|
||||||
N: IntoPy<Py<PyString>>,
|
N: IntoPy<Py<PyString>>,
|
||||||
A: IntoPy<Py<PyTuple>>,
|
A: IntoPy<Py<PyTuple>>,
|
||||||
{
|
{
|
||||||
self.attach(py)
|
self.bind(py)
|
||||||
.as_any()
|
.as_any()
|
||||||
.call_method(name, args, kwargs)
|
.call_method(name, args, kwargs)
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
|
@ -1052,7 +1053,7 @@ impl<T> Py<T> {
|
||||||
N: IntoPy<Py<PyString>>,
|
N: IntoPy<Py<PyString>>,
|
||||||
A: IntoPy<Py<PyTuple>>,
|
A: IntoPy<Py<PyTuple>>,
|
||||||
{
|
{
|
||||||
self.attach(py)
|
self.bind(py)
|
||||||
.as_any()
|
.as_any()
|
||||||
.call_method1(name, args)
|
.call_method1(name, args)
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
|
@ -1068,7 +1069,7 @@ impl<T> Py<T> {
|
||||||
where
|
where
|
||||||
N: IntoPy<Py<PyString>>,
|
N: IntoPy<Py<PyString>>,
|
||||||
{
|
{
|
||||||
self.attach(py).as_any().call_method0(name).map(Into::into)
|
self.bind(py).as_any().call_method0(name).map(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `Py<T>` instance by taking ownership of the given FFI pointer.
|
/// Create a `Py<T>` instance by taking ownership of the given FFI pointer.
|
||||||
|
@ -1624,7 +1625,7 @@ a = A()
|
||||||
#[test]
|
#[test]
|
||||||
fn test_debug_fmt() {
|
fn test_debug_fmt() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let obj = "hello world".to_object(py).attach_into(py);
|
let obj = "hello world".to_object(py).into_bound(py);
|
||||||
assert_eq!(format!("{:?}", obj), "'hello world'");
|
assert_eq!(format!("{:?}", obj), "'hello world'");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1632,7 +1633,7 @@ a = A()
|
||||||
#[test]
|
#[test]
|
||||||
fn test_display_fmt() {
|
fn test_display_fmt() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let obj = "hello world".to_object(py).attach_into(py);
|
let obj = "hello world".to_object(py).into_bound(py);
|
||||||
assert_eq!(format!("{}", obj), "hello world");
|
assert_eq!(format!("{}", obj), "hello world");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1728,7 +1728,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, attr_name.into_py(self.py()).attach_into(py))
|
inner(self, attr_name.into_py(self.py()).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()>
|
fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()>
|
||||||
|
@ -1749,8 +1749,8 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(
|
inner(
|
||||||
self,
|
self,
|
||||||
attr_name.into_py(py).attach_into(py),
|
attr_name.into_py(py).into_bound(py),
|
||||||
value.to_object(py).attach_into(py),
|
value.to_object(py).into_bound(py),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1765,7 +1765,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, attr_name.into_py(py).attach_into(py))
|
inner(self, attr_name.into_py(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compare<O>(&self, other: O) -> PyResult<Ordering>
|
fn compare<O>(&self, other: O) -> PyResult<Ordering>
|
||||||
|
@ -1795,7 +1795,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, other.to_object(py).attach_into(py))
|
inner(self, other.to_object(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rich_compare<O>(&self, other: O, compare_op: CompareOp) -> PyResult<Bound<'py, PyAny>>
|
fn rich_compare<O>(&self, other: O, compare_op: CompareOp) -> PyResult<Bound<'py, PyAny>>
|
||||||
|
@ -1814,7 +1814,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, other.to_object(py).attach_into(py), compare_op)
|
inner(self, other.to_object(py).into_bound(py), compare_op)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lt<O>(&self, other: O) -> PyResult<bool>
|
fn lt<O>(&self, other: O) -> PyResult<bool>
|
||||||
|
@ -1890,7 +1890,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, args.into_py(py).attach_into(py), kwargs)
|
inner(self, args.into_py(py).into_bound(py), kwargs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call0(&self) -> PyResult<Bound<'py, PyAny>> {
|
fn call0(&self) -> PyResult<Bound<'py, PyAny>> {
|
||||||
|
@ -1937,7 +1937,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
|
||||||
|
|
||||||
// Optimized path on python 3.9+
|
// Optimized path on python 3.9+
|
||||||
unsafe {
|
unsafe {
|
||||||
let name = name.into_py(py).attach_into(py);
|
let name = name.into_py(py).into_bound(py);
|
||||||
ffi::PyObject_CallMethodNoArgs(self.as_ptr(), name.as_ptr()).assume_owned_or_err(py)
|
ffi::PyObject_CallMethodNoArgs(self.as_ptr(), name.as_ptr()).assume_owned_or_err(py)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1987,7 +1987,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, key.to_object(py).attach_into(py))
|
inner(self, key.to_object(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
|
fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
|
||||||
|
@ -2008,8 +2008,8 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(
|
inner(
|
||||||
self,
|
self,
|
||||||
key.to_object(py).attach_into(py),
|
key.to_object(py).into_bound(py),
|
||||||
value.to_object(py).attach_into(py),
|
value.to_object(py).into_bound(py),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2024,7 +2024,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, key.to_object(py).attach_into(py))
|
inner(self, key.to_object(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter(&self) -> PyResult<Bound<'py, PyIterator>> {
|
fn iter(&self) -> PyResult<Bound<'py, PyIterator>> {
|
||||||
|
@ -2184,7 +2184,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, value.to_object(py).attach_into(py))
|
inner(self, value.to_object(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(PyPy))]
|
#[cfg(not(PyPy))]
|
||||||
|
|
|
@ -129,7 +129,7 @@ impl Py<PyBytes> {
|
||||||
/// immutable, the result may be used for as long as the reference to
|
/// immutable, the result may be used for as long as the reference to
|
||||||
/// `self` is held, including when the GIL is released.
|
/// `self` is held, including when the GIL is released.
|
||||||
pub fn as_bytes<'a>(&'a self, py: Python<'_>) -> &'a [u8] {
|
pub fn as_bytes<'a>(&'a self, py: Python<'_>) -> &'a [u8] {
|
||||||
self.attach_borrow(py).as_bytes()
|
self.bind_borrowed(py).as_bytes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -391,7 +391,7 @@ impl<'py> PyDictMethods<'py> for Bound<'py, PyDict> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, key.to_object(py).attach_into(py))
|
inner(self, key.to_object(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_item<K>(&self, key: K) -> PyResult<Option<Bound<'py, PyAny>>>
|
fn get_item<K>(&self, key: K) -> PyResult<Option<Bound<'py, PyAny>>>
|
||||||
|
@ -414,7 +414,7 @@ impl<'py> PyDictMethods<'py> for Bound<'py, PyDict> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, key.to_object(py).attach_into(py))
|
inner(self, key.to_object(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
|
fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
|
||||||
|
@ -435,8 +435,8 @@ impl<'py> PyDictMethods<'py> for Bound<'py, PyDict> {
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(
|
inner(
|
||||||
self,
|
self,
|
||||||
key.to_object(py).attach_into(py),
|
key.to_object(py).into_bound(py),
|
||||||
value.to_object(py).attach_into(py),
|
value.to_object(py).into_bound(py),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,7 +451,7 @@ impl<'py> PyDictMethods<'py> for Bound<'py, PyDict> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, key.to_object(py).attach_into(py))
|
inner(self, key.to_object(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keys(&self) -> Bound<'py, PyList> {
|
fn keys(&self) -> Bound<'py, PyList> {
|
||||||
|
|
|
@ -437,7 +437,7 @@ impl<'py> PyListMethods<'py> for Bound<'py, PyList> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, index, item.to_object(py).attach_into(py))
|
inner(self, index, item.to_object(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes the `index`th element of self.
|
/// Deletes the `index`th element of self.
|
||||||
|
@ -483,7 +483,7 @@ impl<'py> PyListMethods<'py> for Bound<'py, PyList> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, item.to_object(py).attach_into(py))
|
inner(self, item.to_object(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inserts an item at the specified index.
|
/// Inserts an item at the specified index.
|
||||||
|
@ -500,7 +500,7 @@ impl<'py> PyListMethods<'py> for Bound<'py, PyList> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, index, item.to_object(py).attach_into(py))
|
inner(self, index, item.to_object(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines if self contains `value`.
|
/// Determines if self contains `value`.
|
||||||
|
|
|
@ -375,7 +375,7 @@ impl<'py> PySequenceMethods<'py> for Bound<'py, PySequence> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, i, item.to_object(py).attach_into(py))
|
inner(self, i, item.to_object(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -417,7 +417,7 @@ impl<'py> PySequenceMethods<'py> for Bound<'py, PySequence> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, value.to_object(py).attach_into(py))
|
inner(self, value.to_object(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -435,7 +435,7 @@ impl<'py> PySequenceMethods<'py> for Bound<'py, PySequence> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, value.to_object(py).attach_into(py))
|
inner(self, value.to_object(py).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -450,7 +450,7 @@ impl<'py> PySequenceMethods<'py> for Bound<'py, PySequence> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let py = self.py();
|
let py = self.py();
|
||||||
inner(self, value.to_object(self.py()).attach_into(py))
|
inner(self, value.to_object(self.py()).into_bound(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -407,7 +407,7 @@ impl Py<PyString> {
|
||||||
/// the GIL lifetime.
|
/// the GIL lifetime.
|
||||||
#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]
|
#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]
|
||||||
pub fn to_str<'a>(&'a self, py: Python<'_>) -> PyResult<&'a str> {
|
pub fn to_str<'a>(&'a self, py: Python<'_>) -> PyResult<&'a str> {
|
||||||
self.attach_borrow(py).to_str()
|
self.bind_borrowed(py).to_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the `PyString` into a Rust string, avoiding copying when possible.
|
/// Converts the `PyString` into a Rust string, avoiding copying when possible.
|
||||||
|
@ -418,7 +418,7 @@ impl Py<PyString> {
|
||||||
/// Because `str` objects are immutable, the returned slice is independent of
|
/// Because `str` objects are immutable, the returned slice is independent of
|
||||||
/// the GIL lifetime.
|
/// the GIL lifetime.
|
||||||
pub fn to_cow<'a>(&'a self, py: Python<'_>) -> PyResult<Cow<'a, str>> {
|
pub fn to_cow<'a>(&'a self, py: Python<'_>) -> PyResult<Cow<'a, str>> {
|
||||||
self.attach_borrow(py).to_cow()
|
self.bind_borrowed(py).to_cow()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the `PyString` into a Rust string.
|
/// Converts the `PyString` into a Rust string.
|
||||||
|
@ -429,7 +429,7 @@ impl Py<PyString> {
|
||||||
/// Because `str` objects are immutable, the returned slice is independent of
|
/// Because `str` objects are immutable, the returned slice is independent of
|
||||||
/// the GIL lifetime.
|
/// the GIL lifetime.
|
||||||
pub fn to_string_lossy<'a>(&'a self, py: Python<'_>) -> Cow<'a, str> {
|
pub fn to_string_lossy<'a>(&'a self, py: Python<'_>) -> Cow<'a, str> {
|
||||||
self.attach_borrow(py).to_string_lossy()
|
self.bind_borrowed(py).to_string_lossy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue