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

pyclass: switch from immutable to frozen #2448

Merged
merged 2 commits into from
Jun 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions guide/src/class.md
Original file line number Diff line number Diff line change
Expand Up @@ -951,7 +951,9 @@ unsafe impl ::pyo3::type_object::PyTypeInfo for MyClass {
}
}

impl ::pyo3::PyClass for MyClass { }
impl ::pyo3::PyClass for MyClass {
type Frozen = pyo3::pyclass::boolean_struct::False;
}

impl<'a> ::pyo3::derive_utils::ExtractExt<'a> for &'a mut MyClass {
type Target = ::pyo3::PyRefMut<'a, MyClass>;
Expand All @@ -974,7 +976,6 @@ impl pyo3::impl_::pyclass::PyClassImpl for MyClass {
type Layout = PyCell<MyClass>;
type BaseType = PyAny;
type ThreadChecker = pyo3::impl_::pyclass::ThreadCheckerStub<MyClass>;
type Mutability = pyo3::pycell::Mutable;
type PyClassMutability = pyo3::pycell::MutableClass;
type Dict = ::pyo3::impl_::pyclass::PyClassDummySlot;
type WeakRef = ::pyo3::impl_::pyclass::PyClassDummySlot;
Expand Down
2 changes: 1 addition & 1 deletion pyo3-macros-backend/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub mod kw {
syn::custom_keyword!(extends);
syn::custom_keyword!(freelist);
syn::custom_keyword!(from_py_with);
syn::custom_keyword!(frozen);
syn::custom_keyword!(gc);
syn::custom_keyword!(get);
syn::custom_keyword!(item);
Expand All @@ -29,7 +30,6 @@ pub mod kw {
syn::custom_keyword!(transparent);
syn::custom_keyword!(unsendable);
syn::custom_keyword!(weakref);
syn::custom_keyword!(immutable);
}

#[derive(Clone, Debug)]
Expand Down
29 changes: 10 additions & 19 deletions pyo3-macros-backend/src/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ pub struct PyClassPyO3Options {
pub dict: Option<kw::dict>,
pub extends: Option<ExtendsAttribute>,
pub freelist: Option<FreelistAttribute>,
pub immutable: Option<kw::immutable>,
pub frozen: Option<kw::frozen>,
pub mapping: Option<kw::mapping>,
pub module: Option<ModuleAttribute>,
pub name: Option<NameAttribute>,
Expand All @@ -78,7 +78,7 @@ enum PyClassPyO3Option {
Dict(kw::dict),
Extends(ExtendsAttribute),
Freelist(FreelistAttribute),
Immutable(kw::immutable),
Frozen(kw::frozen),
Mapping(kw::mapping),
Module(ModuleAttribute),
Name(NameAttribute),
Expand All @@ -101,8 +101,8 @@ impl Parse for PyClassPyO3Option {
input.parse().map(PyClassPyO3Option::Extends)
} else if lookahead.peek(attributes::kw::freelist) {
input.parse().map(PyClassPyO3Option::Freelist)
} else if lookahead.peek(attributes::kw::immutable) {
input.parse().map(PyClassPyO3Option::Immutable)
} else if lookahead.peek(attributes::kw::frozen) {
input.parse().map(PyClassPyO3Option::Frozen)
} else if lookahead.peek(attributes::kw::mapping) {
input.parse().map(PyClassPyO3Option::Mapping)
} else if lookahead.peek(attributes::kw::module) {
Expand Down Expand Up @@ -160,7 +160,7 @@ impl PyClassPyO3Options {
PyClassPyO3Option::Dict(dict) => set_option!(dict),
PyClassPyO3Option::Extends(extends) => set_option!(extends),
PyClassPyO3Option::Freelist(freelist) => set_option!(freelist),
PyClassPyO3Option::Immutable(immutable) => set_option!(immutable),
PyClassPyO3Option::Frozen(frozen) => set_option!(frozen),
PyClassPyO3Option::Mapping(mapping) => set_option!(mapping),
PyClassPyO3Option::Module(module) => set_option!(module),
PyClassPyO3Option::Name(name) => set_option!(name),
Expand Down Expand Up @@ -713,12 +713,14 @@ impl<'a> PyClassImplsBuilder<'a> {
let cls = self.cls;

quote! {
impl _pyo3::PyClass for #cls { }
impl _pyo3::PyClass for #cls {
type Frozen = <Self::PyClassMutability as _pyo3::pycell::PyClassMutability>::Frozen;
}
}
}
fn impl_extractext(&self) -> TokenStream {
let cls = self.cls;
if self.attr.options.immutable.is_some() {
if self.attr.options.frozen.is_some() {
quote! {
impl<'a> _pyo3::derive_utils::ExtractExt<'a> for &'a #cls
{
Expand Down Expand Up @@ -855,17 +857,7 @@ impl<'a> PyClassImplsBuilder<'a> {

let deprecations = &self.attr.deprecations;

let mutability = if self.attr.options.immutable.is_some() {
quote! {
_pyo3::pycell::Immutable
}
} else {
quote! {
_pyo3::pycell::Mutable
}
};

let class_mutability = if self.attr.options.immutable.is_some() {
let class_mutability = if self.attr.options.frozen.is_some() {
quote! {
ImmutableChild
}
Expand Down Expand Up @@ -907,7 +899,6 @@ impl<'a> PyClassImplsBuilder<'a> {
type BaseType = #base;
type ThreadChecker = #thread_checker;
#inventory
type Mutability = #mutability;
type PyClassMutability = <<#base as _pyo3::impl_::pyclass::PyClassBaseType>::PyClassMutability as _pyo3::pycell::PyClassMutability>::#class_mutability;
type Dict = #dict;
type WeakRef = #weakref;
Expand Down
13 changes: 6 additions & 7 deletions src/class/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@
//! [typeobj docs](https://docs.python.org/3/c-api/typeobj.html)

use crate::callback::{HashCallbackOutput, IntoPyCallbackOutput};
use crate::{
exceptions, ffi, pyclass::MutablePyClass, FromPyObject, PyAny, PyCell, PyClass, PyObject,
};
use crate::pyclass::boolean_struct::False;
use crate::{exceptions, ffi, FromPyObject, PyAny, PyCell, PyClass, PyObject};
use std::os::raw::c_int;

/// Basic Python class customization
Expand All @@ -28,14 +27,14 @@ pub trait PyObjectProtocol<'p>: PyClass {

fn __setattr__(&'p mut self, name: Self::Name, value: Self::Value) -> Self::Result
where
Self: PyObjectSetAttrProtocol<'p> + MutablePyClass,
Self: PyObjectSetAttrProtocol<'p> + PyClass<Frozen = False>,
{
unimplemented!()
}

fn __delattr__(&'p mut self, name: Self::Name) -> Self::Result
where
Self: PyObjectDelAttrProtocol<'p> + MutablePyClass,
Self: PyObjectDelAttrProtocol<'p> + PyClass<Frozen = False>,
{
unimplemented!()
}
Expand Down Expand Up @@ -79,12 +78,12 @@ pub trait PyObjectGetAttrProtocol<'p>: PyObjectProtocol<'p> {
type Name: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<PyObject>;
}
pub trait PyObjectSetAttrProtocol<'p>: PyObjectProtocol<'p> + MutablePyClass {
pub trait PyObjectSetAttrProtocol<'p>: PyObjectProtocol<'p> + PyClass<Frozen = False> {
type Name: FromPyObject<'p>;
type Value: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}
pub trait PyObjectDelAttrProtocol<'p>: PyObjectProtocol<'p> + MutablePyClass {
pub trait PyObjectDelAttrProtocol<'p>: PyObjectProtocol<'p> + PyClass<Frozen = False> {
type Name: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}
Expand Down
5 changes: 3 additions & 2 deletions src/class/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
//! For more information check [buffer protocol](https://docs.python.org/3/c-api/buffer.html)
//! c-api
use crate::callback::IntoPyCallbackOutput;
use crate::{ffi, pyclass::MutablePyClass, PyCell, PyRefMut};
use crate::pyclass::boolean_struct::False;
use crate::{ffi, PyCell, PyClass, PyRefMut};
use std::os::raw::c_int;

/// Buffer protocol interface
Expand All @@ -15,7 +16,7 @@ use std::os::raw::c_int;
/// c-api.
#[allow(unused_variables)]
#[deprecated(since = "0.16.0", note = "prefer `#[pymethods]` to `#[pyproto]`")]
pub trait PyBufferProtocol<'p>: MutablePyClass {
pub trait PyBufferProtocol<'p>: PyClass<Frozen = False> {
// No default implementations so that implementors of this trait provide both methods.

fn bf_getbuffer(
Expand Down
5 changes: 3 additions & 2 deletions src/class/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@

//! Python GC support

use crate::{ffi, pyclass::MutablePyClass, PyCell};
use crate::pyclass::boolean_struct::False;
use crate::{ffi, PyCell, PyClass};
use std::os::raw::{c_int, c_void};

pub use crate::impl_::pymethods::{PyTraverseError, PyVisit};

/// GC support
#[deprecated(since = "0.16.0", note = "prefer `#[pymethods]` to `#[pyproto]`")]
pub trait PyGCProtocol<'p>: MutablePyClass {
pub trait PyGCProtocol<'p>: PyClass<Frozen = False> {
fn __traverse__(&'p self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>;
fn __clear__(&'p mut self);
}
Expand Down
9 changes: 5 additions & 4 deletions src/class/mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
//! Trait and support implementation for implementing mapping support

use crate::callback::IntoPyCallbackOutput;
use crate::{pyclass::MutablePyClass, FromPyObject, PyClass, PyObject};
use crate::pyclass::boolean_struct::False;
use crate::{FromPyObject, PyClass, PyObject};

/// Mapping interface
#[allow(unused_variables)]
#[deprecated(since = "0.16.0", note = "prefer `#[pymethods]` to `#[pyproto]`")]
pub trait PyMappingProtocol<'p>: PyClass {
pub trait PyMappingProtocol<'p>: PyClass<Frozen = False> {
fn __len__(&'p self) -> Self::Result
where
Self: PyMappingLenProtocol<'p>,
Expand Down Expand Up @@ -52,13 +53,13 @@ pub trait PyMappingGetItemProtocol<'p>: PyMappingProtocol<'p> {
type Result: IntoPyCallbackOutput<PyObject>;
}

pub trait PyMappingSetItemProtocol<'p>: PyMappingProtocol<'p> + MutablePyClass {
pub trait PyMappingSetItemProtocol<'p>: PyMappingProtocol<'p> + PyClass<Frozen = False> {
type Key: FromPyObject<'p>;
type Value: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}

pub trait PyMappingDelItemProtocol<'p>: PyMappingProtocol<'p> + MutablePyClass {
pub trait PyMappingDelItemProtocol<'p>: PyMappingProtocol<'p> + PyClass<Frozen = False> {
type Key: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}
Expand Down
31 changes: 16 additions & 15 deletions src/class/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
//! Trait and support implementation for implementing number protocol
use crate::callback::IntoPyCallbackOutput;
use crate::err::PyErr;
use crate::{ffi, pyclass::MutablePyClass, FromPyObject, PyClass, PyObject};
use crate::pyclass::boolean_struct::False;
use crate::{ffi, FromPyObject, PyClass, PyObject};

/// Number interface
#[allow(unused_variables)]
Expand Down Expand Up @@ -461,76 +462,76 @@ pub trait PyNumberROrProtocol<'p>: PyNumberProtocol<'p> {
type Result: IntoPyCallbackOutput<PyObject>;
}

pub trait PyNumberIAddProtocol<'p>: PyNumberProtocol<'p> + MutablePyClass {
pub trait PyNumberIAddProtocol<'p>: PyNumberProtocol<'p> + PyClass<Frozen = False> {
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}

pub trait PyNumberISubProtocol<'p>: PyNumberProtocol<'p> + MutablePyClass {
pub trait PyNumberISubProtocol<'p>: PyNumberProtocol<'p> + PyClass<Frozen = False> {
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}

pub trait PyNumberIMulProtocol<'p>: PyNumberProtocol<'p> + MutablePyClass {
pub trait PyNumberIMulProtocol<'p>: PyNumberProtocol<'p> + PyClass<Frozen = False> {
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}

pub trait PyNumberIMatmulProtocol<'p>: PyNumberProtocol<'p> + MutablePyClass {
pub trait PyNumberIMatmulProtocol<'p>: PyNumberProtocol<'p> + PyClass<Frozen = False> {
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}

pub trait PyNumberITruedivProtocol<'p>: PyNumberProtocol<'p> + MutablePyClass {
pub trait PyNumberITruedivProtocol<'p>: PyNumberProtocol<'p> + PyClass<Frozen = False> {
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}

pub trait PyNumberIFloordivProtocol<'p>: PyNumberProtocol<'p> + MutablePyClass {
pub trait PyNumberIFloordivProtocol<'p>: PyNumberProtocol<'p> + PyClass<Frozen = False> {
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}

pub trait PyNumberIModProtocol<'p>: PyNumberProtocol<'p> + MutablePyClass {
pub trait PyNumberIModProtocol<'p>: PyNumberProtocol<'p> + PyClass<Frozen = False> {
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}

pub trait PyNumberIDivmodProtocol<'p>: PyNumberProtocol<'p> + MutablePyClass {
pub trait PyNumberIDivmodProtocol<'p>: PyNumberProtocol<'p> + PyClass<Frozen = False> {
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}

pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> + MutablePyClass {
pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> + PyClass<Frozen = False> {
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
// See https://bugs.python.org/issue36379
type Modulo: FromPyObject<'p>;
}

#[allow(clippy::upper_case_acronyms)]
pub trait PyNumberILShiftProtocol<'p>: PyNumberProtocol<'p> + MutablePyClass {
pub trait PyNumberILShiftProtocol<'p>: PyNumberProtocol<'p> + PyClass<Frozen = False> {
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}

#[allow(clippy::upper_case_acronyms)]
pub trait PyNumberIRShiftProtocol<'p>: PyNumberProtocol<'p> + MutablePyClass {
pub trait PyNumberIRShiftProtocol<'p>: PyNumberProtocol<'p> + PyClass<Frozen = False> {
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}

pub trait PyNumberIAndProtocol<'p>: PyNumberProtocol<'p> + MutablePyClass {
pub trait PyNumberIAndProtocol<'p>: PyNumberProtocol<'p> + PyClass<Frozen = False> {
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}

pub trait PyNumberIXorProtocol<'p>: PyNumberProtocol<'p> + MutablePyClass {
pub trait PyNumberIXorProtocol<'p>: PyNumberProtocol<'p> + PyClass<Frozen = False> {
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}

pub trait PyNumberIOrProtocol<'p>: PyNumberProtocol<'p> + MutablePyClass {
pub trait PyNumberIOrProtocol<'p>: PyNumberProtocol<'p> + PyClass<Frozen = False> {
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}
Expand Down
11 changes: 6 additions & 5 deletions src/class/sequence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
use crate::callback::IntoPyCallbackOutput;
use crate::conversion::{FromPyObject, IntoPy};
use crate::err::PyErr;
use crate::{exceptions, ffi, pyclass::MutablePyClass, PyAny, PyCell, PyClass, PyObject};
use crate::pyclass::boolean_struct::False;
use crate::{exceptions, ffi, PyAny, PyCell, PyClass, PyObject};
use std::os::raw::c_int;

/// Sequence interface
Expand Down Expand Up @@ -89,13 +90,13 @@ pub trait PySequenceGetItemProtocol<'p>: PySequenceProtocol<'p> {
type Result: IntoPyCallbackOutput<PyObject>;
}

pub trait PySequenceSetItemProtocol<'p>: PySequenceProtocol<'p> + MutablePyClass {
pub trait PySequenceSetItemProtocol<'p>: PySequenceProtocol<'p> + PyClass<Frozen = False> {
type Index: FromPyObject<'p> + From<isize>;
type Value: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<()>;
}

pub trait PySequenceDelItemProtocol<'p>: PySequenceProtocol<'p> + MutablePyClass {
pub trait PySequenceDelItemProtocol<'p>: PySequenceProtocol<'p> + PyClass<Frozen = False> {
type Index: FromPyObject<'p> + From<isize>;
type Result: IntoPyCallbackOutput<()>;
}
Expand All @@ -116,14 +117,14 @@ pub trait PySequenceRepeatProtocol<'p>: PySequenceProtocol<'p> {
}

pub trait PySequenceInplaceConcatProtocol<'p>:
PySequenceProtocol<'p> + IntoPy<PyObject> + MutablePyClass
PySequenceProtocol<'p> + IntoPy<PyObject> + PyClass<Frozen = False>
{
type Other: FromPyObject<'p>;
type Result: IntoPyCallbackOutput<Self>;
}

pub trait PySequenceInplaceRepeatProtocol<'p>:
PySequenceProtocol<'p> + IntoPy<PyObject> + MutablePyClass + 'p
PySequenceProtocol<'p> + IntoPy<PyObject> + PyClass<Frozen = False> + 'p
{
type Index: FromPyObject<'p> + From<isize>;
type Result: IntoPyCallbackOutput<Self>;
Expand Down
6 changes: 3 additions & 3 deletions src/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

//! Defines conversions between Rust and Python types.
use crate::err::{self, PyDowncastError, PyResult};
use crate::pyclass::boolean_struct::False;
use crate::type_object::PyTypeInfo;
use crate::types::PyTuple;
use crate::{
ffi, gil, pyclass::MutablePyClass, Py, PyAny, PyCell, PyClass, PyNativeType, PyObject, PyRef,
PyRefMut, Python,
ffi, gil, Py, PyAny, PyCell, PyClass, PyNativeType, PyObject, PyRef, PyRefMut, Python,
};
use std::ptr::NonNull;

Expand Down Expand Up @@ -375,7 +375,7 @@ where

impl<'a, T> FromPyObject<'a> for PyRefMut<'a, T>
where
T: MutablePyClass,
T: PyClass<Frozen = False>,
{
fn extract(obj: &'a PyAny) -> PyResult<Self> {
let cell: &PyCell<T> = PyTryFrom::try_from(obj)?;
Expand Down
Loading