Skip to content

Commit

Permalink
Merge pull request #3686 from davidhewitt/bound
Browse files Browse the repository at this point in the history
make Bound and Borrowed types public API
  • Loading branch information
adamreichold committed Dec 21, 2023
2 parents 1fa47b0 + 4ac6a6b commit a115877
Show file tree
Hide file tree
Showing 21 changed files with 577 additions and 573 deletions.
1 change: 1 addition & 0 deletions newsfragments/3686.added.md
@@ -0,0 +1 @@
Add `Bound<T>` and `Borrowed<T>` smart pointers as a new API for accessing Python objects.
48 changes: 24 additions & 24 deletions src/err/mod.rs
@@ -1,4 +1,4 @@
use crate::instance::Py2;
use crate::instance::Bound;
use crate::panic::PanicException;
use crate::type_object::PyTypeInfo;
use crate::types::any::PyAnyMethods;
Expand Down Expand Up @@ -65,16 +65,16 @@ impl<'a> PyDowncastError<'a> {

/// Error that indicates a failure to convert a PyAny to a more specific Python type.
#[derive(Debug)]
pub(crate) struct PyDowncastError2<'a, 'py> {
from: &'a Py2<'py, PyAny>,
pub struct DowncastError<'a, 'py> {
from: &'a Bound<'py, PyAny>,
to: Cow<'static, str>,
}

impl<'a, 'py> PyDowncastError2<'a, 'py> {
impl<'a, 'py> DowncastError<'a, 'py> {
/// Create a new `PyDowncastError` representing a failure to convert the object
/// `from` into the type named in `to`.
pub fn new(from: &'a Py2<'py, PyAny>, to: impl Into<Cow<'static, str>>) -> Self {
PyDowncastError2 {
pub fn new(from: &'a Bound<'py, PyAny>, to: impl Into<Cow<'static, str>>) -> Self {
DowncastError {
from,
to: to.into(),
}
Expand All @@ -83,16 +83,16 @@ impl<'a, 'py> PyDowncastError2<'a, 'py> {

/// Error that indicates a failure to convert a PyAny to a more specific Python type.
#[derive(Debug)]
pub(crate) struct PyDowncastIntoError<'py> {
from: Py2<'py, PyAny>,
pub struct DowncastIntoError<'py> {
from: Bound<'py, PyAny>,
to: Cow<'static, str>,
}

impl<'py> PyDowncastIntoError<'py> {
/// Create a new `PyDowncastIntoError` representing a failure to convert the object
impl<'py> DowncastIntoError<'py> {
/// Create a new `DowncastIntoError` representing a failure to convert the object
/// `from` into the type named in `to`.
pub fn new(from: Py2<'py, PyAny>, to: impl Into<Cow<'static, str>>) -> Self {
PyDowncastIntoError {
pub fn new(from: Bound<'py, PyAny>, to: impl Into<Cow<'static, str>>) -> Self {
DowncastIntoError {
from,
to: to.into(),
}
Expand Down Expand Up @@ -811,13 +811,13 @@ impl<'a> std::error::Error for PyDowncastError<'a> {}

impl<'a> std::fmt::Display for PyDowncastError<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
display_downcast_error(f, Py2::borrowed_from_gil_ref(&self.from), &self.to)
display_downcast_error(f, Bound::borrowed_from_gil_ref(&self.from), &self.to)
}
}

/// Convert `PyDowncastError2` to Python `TypeError`.
impl std::convert::From<PyDowncastError2<'_, '_>> for PyErr {
fn from(err: PyDowncastError2<'_, '_>) -> PyErr {
/// Convert `DowncastError` to Python `TypeError`.
impl std::convert::From<DowncastError<'_, '_>> for PyErr {
fn from(err: DowncastError<'_, '_>) -> PyErr {
let args = PyDowncastErrorArguments {
from: err.from.get_type().into(),
to: err.to,
Expand All @@ -827,17 +827,17 @@ impl std::convert::From<PyDowncastError2<'_, '_>> for PyErr {
}
}

impl std::error::Error for PyDowncastError2<'_, '_> {}
impl std::error::Error for DowncastError<'_, '_> {}

impl std::fmt::Display for PyDowncastError2<'_, '_> {
impl std::fmt::Display for DowncastError<'_, '_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
display_downcast_error(f, self.from, &self.to)
}
}

/// Convert `PyDowncastIntoError` to Python `TypeError`.
impl std::convert::From<PyDowncastIntoError<'_>> for PyErr {
fn from(err: PyDowncastIntoError<'_>) -> PyErr {
/// Convert `DowncastIntoError` to Python `TypeError`.
impl std::convert::From<DowncastIntoError<'_>> for PyErr {
fn from(err: DowncastIntoError<'_>) -> PyErr {
let args = PyDowncastErrorArguments {
from: err.from.get_type().into(),
to: err.to,
Expand All @@ -847,17 +847,17 @@ impl std::convert::From<PyDowncastIntoError<'_>> for PyErr {
}
}

impl std::error::Error for PyDowncastIntoError<'_> {}
impl std::error::Error for DowncastIntoError<'_> {}

impl std::fmt::Display for PyDowncastIntoError<'_> {
impl std::fmt::Display for DowncastIntoError<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
display_downcast_error(f, &self.from, &self.to)
}
}

fn display_downcast_error(
f: &mut std::fmt::Formatter<'_>,
from: &Py2<'_, PyAny>,
from: &Bound<'_, PyAny>,
to: &str,
) -> std::fmt::Result {
write!(
Expand Down
48 changes: 20 additions & 28 deletions src/ffi_ptr_ext.rs
@@ -1,6 +1,6 @@
use crate::{
ffi,
instance::{Py2, Py2Borrowed},
instance::{Borrowed, Bound},
PyAny, PyResult, Python,
};

Expand All @@ -15,65 +15,57 @@ mod sealed {
use sealed::Sealed;

pub(crate) trait FfiPtrExt: Sealed {
unsafe fn assume_owned_or_err(self, py: Python<'_>) -> PyResult<Py2<'_, PyAny>>;
unsafe fn assume_owned(self, py: Python<'_>) -> Py2<'_, PyAny>;
unsafe fn assume_owned_or_err(self, py: Python<'_>) -> PyResult<Bound<'_, PyAny>>;
unsafe fn assume_owned(self, py: Python<'_>) -> Bound<'_, PyAny>;

/// Assumes this pointer is borrowed from a parent object.
///
/// Warning: the lifetime `'a` is not bounded by the function arguments; the caller is
/// responsible to ensure this is tied to some appropriate lifetime.
unsafe fn assume_borrowed_or_err<'a>(
self,
py: Python<'_>,
) -> PyResult<Py2Borrowed<'a, '_, PyAny>>;
unsafe fn assume_borrowed_or_err<'a>(self, py: Python<'_>)
-> PyResult<Borrowed<'a, '_, PyAny>>;

/// Same as `assume_borrowed_or_err`, but doesn't fetch an error on NULL.
unsafe fn assume_borrowed_or_opt<'a>(
self,
py: Python<'_>,
) -> Option<Py2Borrowed<'a, '_, PyAny>>;
unsafe fn assume_borrowed_or_opt<'a>(self, py: Python<'_>) -> Option<Borrowed<'a, '_, PyAny>>;

/// Same as `assume_borrowed_or_err`, but panics on NULL.
unsafe fn assume_borrowed<'a>(self, py: Python<'_>) -> Py2Borrowed<'a, '_, PyAny>;
unsafe fn assume_borrowed<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny>;

/// Same as `assume_borrowed_or_err`, but does not check for NULL.
unsafe fn assume_borrowed_unchecked<'a>(self, py: Python<'_>) -> Py2Borrowed<'a, '_, PyAny>;
unsafe fn assume_borrowed_unchecked<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny>;
}

impl FfiPtrExt for *mut ffi::PyObject {
#[inline]
unsafe fn assume_owned_or_err(self, py: Python<'_>) -> PyResult<Py2<'_, PyAny>> {
Py2::from_owned_ptr_or_err(py, self)
unsafe fn assume_owned_or_err(self, py: Python<'_>) -> PyResult<Bound<'_, PyAny>> {
Bound::from_owned_ptr_or_err(py, self)
}

#[inline]
unsafe fn assume_owned(self, py: Python<'_>) -> Py2<'_, PyAny> {
Py2::from_owned_ptr(py, self)
unsafe fn assume_owned(self, py: Python<'_>) -> Bound<'_, PyAny> {
Bound::from_owned_ptr(py, self)
}

#[inline]
unsafe fn assume_borrowed_or_err<'a>(
self,
py: Python<'_>,
) -> PyResult<Py2Borrowed<'a, '_, PyAny>> {
Py2Borrowed::from_ptr_or_err(py, self)
) -> PyResult<Borrowed<'a, '_, PyAny>> {
Borrowed::from_ptr_or_err(py, self)
}

#[inline]
unsafe fn assume_borrowed_or_opt<'a>(
self,
py: Python<'_>,
) -> Option<Py2Borrowed<'a, '_, PyAny>> {
Py2Borrowed::from_ptr_or_opt(py, self)
unsafe fn assume_borrowed_or_opt<'a>(self, py: Python<'_>) -> Option<Borrowed<'a, '_, PyAny>> {
Borrowed::from_ptr_or_opt(py, self)
}

#[inline]
unsafe fn assume_borrowed<'a>(self, py: Python<'_>) -> Py2Borrowed<'a, '_, PyAny> {
Py2Borrowed::from_ptr(py, self)
unsafe fn assume_borrowed<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny> {
Borrowed::from_ptr(py, self)
}

#[inline]
unsafe fn assume_borrowed_unchecked<'a>(self, py: Python<'_>) -> Py2Borrowed<'a, '_, PyAny> {
Py2Borrowed::from_ptr_unchecked(py, self)
unsafe fn assume_borrowed_unchecked<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny> {
Borrowed::from_ptr_unchecked(py, self)
}
}

0 comments on commit a115877

Please sign in to comment.