Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lifetime to PyAny etc #885

Closed
wants to merge 11 commits into from
30 changes: 15 additions & 15 deletions examples/rustapi_module/src/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ use pyo3::types::{
use pyo3::wrap_pyfunction;

#[pyfunction]
fn make_date<'p>(py: Python<'p>, year: i32, month: u8, day: u8) -> PyResult<&'p PyDate> {
fn make_date(py: Python, year: i32, month: u8, day: u8) -> PyResult<PyDate> {
PyDate::new(py, year, month, day)
}

#[pyfunction]
fn get_date_tuple<'p>(py: Python<'p>, d: &PyDate) -> &'p PyTuple {
fn get_date_tuple<'p>(py: Python<'p>, d: &PyDate) -> PyTuple<'p> {
PyTuple::new(
py,
&[d.get_year(), d.get_month() as i32, d.get_day() as i32],
)
}

#[pyfunction]
fn date_from_timestamp<'p>(py: Python<'p>, timestamp: i64) -> PyResult<&'p PyDate> {
fn date_from_timestamp(py: Python, timestamp: i64) -> PyResult<PyDate> {
PyDate::from_timestamp(py, timestamp)
}

Expand All @@ -31,7 +31,7 @@ fn make_time<'p>(
second: u8,
microsecond: u32,
tzinfo: Option<&PyTzInfo>,
) -> PyResult<&'p PyTime> {
) -> PyResult<PyTime<'p>> {
PyTime::new(
py,
hour,
Expand All @@ -52,7 +52,7 @@ fn time_with_fold<'p>(
microsecond: u32,
tzinfo: Option<&PyTzInfo>,
fold: bool,
) -> PyResult<&'p PyTime> {
) -> PyResult<PyTime<'p>> {
PyTime::new_with_fold(
py,
hour,
Expand All @@ -65,7 +65,7 @@ fn time_with_fold<'p>(
}

#[pyfunction]
fn get_time_tuple<'p>(py: Python<'p>, dt: &PyTime) -> &'p PyTuple {
fn get_time_tuple<'p>(py: Python<'p>, dt: &PyTime) -> PyTuple<'p> {
PyTuple::new(
py,
&[
Expand All @@ -79,7 +79,7 @@ fn get_time_tuple<'p>(py: Python<'p>, dt: &PyTime) -> &'p PyTuple {

#[cfg(Py_3_6)]
#[pyfunction]
fn get_time_tuple_fold<'p>(py: Python<'p>, dt: &PyTime) -> &'p PyTuple {
fn get_time_tuple_fold<'p>(py: Python<'p>, dt: &PyTime) -> PyTuple<'p> {
PyTuple::new(
py,
&[
Expand All @@ -103,7 +103,7 @@ fn make_delta<'p>(
}

#[pyfunction]
fn get_delta_tuple<'p>(py: Python<'p>, delta: &PyDelta) -> &'p PyTuple {
fn get_delta_tuple<'p>(py: Python<'p>, delta: &PyDelta) -> PyTuple<'p> {
PyTuple::new(
py,
&[
Expand All @@ -125,7 +125,7 @@ fn make_datetime<'p>(
second: u8,
microsecond: u32,
tzinfo: Option<&PyTzInfo>,
) -> PyResult<&'p PyDateTime> {
) -> PyResult<PyDateTime<'p>> {
PyDateTime::new(
py,
year,
Expand All @@ -140,7 +140,7 @@ fn make_datetime<'p>(
}

#[pyfunction]
fn get_datetime_tuple<'p>(py: Python<'p>, dt: &PyDateTime) -> &'p PyTuple {
fn get_datetime_tuple<'p>(py: Python<'p>, dt: &PyDateTime) -> PyTuple<'p> {
PyTuple::new(
py,
&[
Expand All @@ -157,7 +157,7 @@ fn get_datetime_tuple<'p>(py: Python<'p>, dt: &PyDateTime) -> &'p PyTuple {

#[cfg(Py_3_6)]
#[pyfunction]
fn get_datetime_tuple_fold<'p>(py: Python<'p>, dt: &PyDateTime) -> &'p PyTuple {
fn get_datetime_tuple_fold<'p>(py: Python<'p>, dt: &PyDateTime) -> PyTuple<'p> {
PyTuple::new(
py,
&[
Expand All @@ -178,7 +178,7 @@ fn datetime_from_timestamp<'p>(
py: Python<'p>,
ts: f64,
tz: Option<&PyTzInfo>,
) -> PyResult<&'p PyDateTime> {
) -> PyResult<PyDateTime<'p>> {
PyDateTime::from_timestamp(py, ts, tz)
}

Expand All @@ -199,15 +199,15 @@ impl TzClass {
TzClass {}
}

fn utcoffset<'p>(&self, py: Python<'p>, _dt: &PyDateTime) -> PyResult<&'p PyDelta> {
fn utcoffset<'p>(&self, py: Python<'p>, _dt: &PyDateTime) -> PyResult<PyDelta<'p>> {
PyDelta::new(py, 0, 3600, 0, true)
}

fn tzname(&self, _py: Python<'_>, _dt: &PyDateTime) -> PyResult<String> {
fn tzname(&self, _py: Python, _dt: &PyDateTime) -> PyResult<String> {
Ok(String::from("+01:00"))
}

fn dst(&self, _py: Python<'_>, _dt: &PyDateTime) -> PyResult<Option<&PyDelta>> {
fn dst<'p>(&self, _py: Python, _dt: &PyDateTime) -> PyResult<Option<PyDelta<'p>>> {
Ok(None)
}
}
Expand Down
1 change: 0 additions & 1 deletion guide/src/class.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ unsafe impl pyo3::PyTypeInfo for MyClass {
type BaseLayout = pyo3::pycell::PyCellBase<PyAny>;
type Layout = PyCell<Self>;
type Initializer = PyClassInitializer<Self>;
type AsRefTarget = PyCell<Self>;

const NAME: &'static str = "MyClass";
const MODULE: Option<&'static str> = None;
Expand Down
25 changes: 20 additions & 5 deletions pyo3-derive-backend/src/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,16 @@ pub(crate) fn impl_method_proto(
let mut slf_ty = get_arg_ty(sig, 0);

// update the type if no lifetime was given:
// PyRef<Self> --> PyRef<'p, Self>
// PyRef<Self> --> PyRef<'p, 'p, Self>
if let syn::Type::Path(ref mut path) = slf_ty {
if let syn::PathArguments::AngleBracketed(ref mut args) =
path.path.segments[0].arguments
{
if let syn::GenericArgument::Lifetime(_) = args.args[0] {
} else {
let lt = syn::parse_quote! {'p};
args.args.insert(0, lt);
// Insert two 'p lifetimes for PyRef / PyRefMut
args.args.insert(0, syn::parse_quote! {'p});
args.args.insert(0, syn::parse_quote! {'p});
}
}
}
Expand Down Expand Up @@ -452,8 +453,22 @@ fn get_arg_ty(sig: &syn::Signature, idx: usize) -> syn::Type {
_ => panic!("fn arg type is not supported"),
};

// Add a lifetime if there is none
if let syn::Type::Reference(ref mut r) = ty {

if let syn::Type::Reference(r) = &mut ty {
// HACK: For PyAny, add <'p>
match &mut *r.elem {
syn::Type::Path(ty) => {
let seg = ty.path.segments.last_mut().unwrap();
if seg.ident == "PyAny" {
if let syn::PathArguments::None = seg.arguments {
seg.arguments = syn::PathArguments::AngleBracketed(syn::parse_quote!(<'p>));
}
}
},
_ => {}
}

// Add a lifetime if there is none
r.lifetime.get_or_insert(syn::parse_quote! {'p});
}

Expand Down
55 changes: 34 additions & 21 deletions pyo3-derive-backend/src/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl Default for PyClassArgs {
// We need the 0 as value for the constant we're later building using quote for when there
// are no other flags
flags: vec![parse_quote! { 0 }],
base: parse_quote! { pyo3::PyAny },
base: parse_quote! { pyo3::type_marker::Any },
has_extends: false,
}
}
Expand Down Expand Up @@ -276,7 +276,7 @@ fn impl_class(
}
} else {
quote! {
impl pyo3::pyclass::PyClassAlloc for #cls {}
impl pyo3::pyclass::PyClassAlloc<'_> for #cls {}
}
}
};
Expand Down Expand Up @@ -312,14 +312,14 @@ fn impl_class(
let weakref = if has_weakref {
quote! { pyo3::pyclass_slots::PyClassWeakRefSlot }
} else if attr.has_extends {
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils>::WeakRef }
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils<'py>>::WeakRef }
} else {
quote! { pyo3::pyclass_slots::PyClassDummySlot }
};
let dict = if has_dict {
quote! { pyo3::pyclass_slots::PyClassDictSlot }
} else if attr.has_extends {
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils>::Dict }
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils<'py>>::Dict }
} else {
quote! { pyo3::pyclass_slots::PyClassDummySlot }
};
Expand Down Expand Up @@ -355,14 +355,14 @@ fn impl_class(
quote! { 0 }
};
let base_layout = if attr.has_extends {
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils>::LayoutAsBase }
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils<'py>>::LayoutAsBase }
} else {
quote! { pyo3::pycell::PyCellBase<pyo3::PyAny> }
quote! { pyo3::pycell::PyCellBase<'py, pyo3::type_marker::Any> }
};
let base_nativetype = if attr.has_extends {
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils>::BaseNativeType }
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils<'py>>::RootType }
} else {
quote! { pyo3::PyAny }
quote! { pyo3::type_marker::Any }
};

// If #cls is not extended type, we allow Self->PyObject conversion
Expand All @@ -379,18 +379,12 @@ fn impl_class(
};

Ok(quote! {
unsafe impl pyo3::type_object::PyTypeInfo for #cls {
unsafe impl<'py> pyo3::type_object::PyTypeInfo<'py> for #cls {
type Type = #cls;
type BaseType = #base;
type Layout = pyo3::PyCell<Self>;
type BaseLayout = #base_layout;
type Initializer = pyo3::pyclass_init::PyClassInitializer<Self>;
type AsRefTarget = pyo3::PyCell<Self>;

const NAME: &'static str = #cls_name;
const MODULE: Option<&'static str> = #module;
const DESCRIPTION: &'static str = #doc;
const FLAGS: usize = #(#flags)|* | #extended;

#[inline]
fn type_object() -> &'static pyo3::ffi::PyTypeObject {
Expand All @@ -400,20 +394,39 @@ fn impl_class(
}
}

impl pyo3::PyClass for #cls {
impl<'py> pyo3::PyClass<'py> for #cls {
type Dict = #dict;
type WeakRef = #weakref;
type BaseNativeType = #base_nativetype;
type RootType = #base_nativetype;
}

impl<'a> pyo3::derive_utils::ExtractExt<'a> for &'a #cls
impl<'a, 'py: 'a> pyo3::derive_utils::ExtractExt<'a, 'py> for &'a #cls
{
type Target = pyo3::PyRef<'a, #cls>;
type Target = pyo3::PyRef<'a, 'py, #cls>;
}

impl<'a> pyo3::derive_utils::ExtractExt<'a> for &'a mut #cls
impl<'a, 'py: 'a> pyo3::derive_utils::ExtractExt<'a, 'py> for &'a mut #cls
{
type Target = pyo3::PyRefMut<'a, #cls>;
type Target = pyo3::PyRefMut<'a, 'py, #cls>;
}

impl<'py> pyo3::type_marker::TypeMarker<'py> for #cls {
type NativeType = pyo3::PyCell<'py, #cls>;
type Layout = pyo3::pycell::PyCellLayout<'py, Self>;
type Initializer = pyo3::pyclass_init::PyClassInitializer<'py, Self>;

const FLAGS: usize = #(#flags)|* | #extended;

fn type_object() -> &'static pyo3::ffi::PyTypeObject {
<Self as pyo3::PyTypeInfo<'py>>::type_object()
}
}

impl<'py> pyo3::type_marker::TypeWithBase<'py> for #cls {
type BaseType = #base;
type BaseNativeType = <#base as pyo3::type_marker::TypeMarker<'py>>::NativeType;
type BaseLayout = #base_layout;
type BaseInitializer = <#base as pyo3::type_marker::TypeMarker<'py>>::Initializer;
}

#into_pyobject
Expand Down
8 changes: 4 additions & 4 deletions pyo3-derive-backend/src/pymethod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ fn impl_wrap_common(
let _py = _pool.python();
pyo3::run_callback(_py, || {
#slf
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _args = pyo3::PyAny::raw_borrowed(_py, &_args).downcast::<pyo3::types::PyTuple>()?;
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);

#body
Expand Down Expand Up @@ -451,8 +451,8 @@ fn impl_arg_params_(spec: &FnSpec<'_>, body: TokenStream, into_result: TokenStre
];

let mut output = [None; #num_normal_params];
let mut _args = _args;
let mut _kwargs = _kwargs;
let _args = _args;
let _kwargs = _kwargs;

let (_args, _kwargs) = pyo3::derive_utils::parse_fn_args(
Some(_LOCATION),
Expand Down Expand Up @@ -503,7 +503,7 @@ fn impl_arg_param(
};
} else if spec.is_kwargs(&name) {
return quote! {
let #arg_name = _kwargs;
let #arg_name = _kwargs.as_ref();
};
}
let arg_value = quote!(output[#option_pos]);
Expand Down
2 changes: 1 addition & 1 deletion src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ mod test {
.unwrap()
.call_method("array", ("f", (1.0, 1.5, 2.0, 2.5)), None)
.unwrap();
let buffer = PyBuffer::get(py, array).unwrap();
let buffer = PyBuffer::get(py, &array).unwrap();
assert_eq!(buffer.dimensions(), 1);
assert_eq!(buffer.item_count(), 4);
assert_eq!(buffer.format().to_str().unwrap(), "f");
Expand Down
14 changes: 7 additions & 7 deletions src/class/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub enum CompareOp {

/// Basic Python class customization
#[allow(unused_variables)]
pub trait PyObjectProtocol<'p>: PyClass {
pub trait PyObjectProtocol<'p>: PyClass<'p> {
fn __getattr__(&'p self, name: Self::Name) -> Self::Result
where
Self: PyObjectGetAttrProtocol<'p>,
Expand Down Expand Up @@ -102,17 +102,17 @@ pub trait PyObjectProtocol<'p>: PyClass {
}

pub trait PyObjectGetAttrProtocol<'p>: PyObjectProtocol<'p> {
type Name: FromPyObject<'p>;
type Name: FromPyObject<'p, 'p>;
type Success: IntoPy<PyObject>;
type Result: Into<PyResult<Self::Success>>;
}
pub trait PyObjectSetAttrProtocol<'p>: PyObjectProtocol<'p> {
type Name: FromPyObject<'p>;
type Value: FromPyObject<'p>;
type Name: FromPyObject<'p, 'p>;
type Value: FromPyObject<'p, 'p>;
type Result: Into<PyResult<()>>;
}
pub trait PyObjectDelAttrProtocol<'p>: PyObjectProtocol<'p> {
type Name: FromPyObject<'p>;
type Name: FromPyObject<'p, 'p>;
type Result: Into<PyResult<()>>;
}
pub trait PyObjectStrProtocol<'p>: PyObjectProtocol<'p> {
Expand All @@ -124,7 +124,7 @@ pub trait PyObjectReprProtocol<'p>: PyObjectProtocol<'p> {
type Result: Into<PyResult<Self::Success>>;
}
pub trait PyObjectFormatProtocol<'p>: PyObjectProtocol<'p> {
type Format: FromPyObject<'p>;
type Format: FromPyObject<'p, 'p>;
type Success: IntoPy<PyObject>;
type Result: Into<PyResult<Self::Success>>;
}
Expand All @@ -139,7 +139,7 @@ pub trait PyObjectBytesProtocol<'p>: PyObjectProtocol<'p> {
type Result: Into<PyResult<Self::Success>>;
}
pub trait PyObjectRichcmpProtocol<'p>: PyObjectProtocol<'p> {
type Other: FromPyObject<'p>;
type Other: FromPyObject<'p, 'p>;
type Success: IntoPy<PyObject>;
type Result: Into<PyResult<Self::Success>>;
}
Expand Down
Loading