Skip to content

Commit

Permalink
pyclass: switch from immutable to frozen
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Jun 12, 2022
1 parent 171b38a commit a758495
Show file tree
Hide file tree
Showing 24 changed files with 174 additions and 149 deletions.
2 changes: 1 addition & 1 deletion guide/src/class.md
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@ 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 Frozen = pyo3::boolean_traits::False;
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
26 changes: 8 additions & 18 deletions pyo3-macros-backend/src/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,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 @@ -77,7 +77,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 @@ -100,8 +100,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 @@ -159,7 +159,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 @@ -717,7 +717,7 @@ impl<'a> PyClassImplsBuilder<'a> {
}
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 @@ -844,17 +844,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 @@ -896,7 +886,7 @@ impl<'a> PyClassImplsBuilder<'a> {
type BaseType = #base;
type ThreadChecker = #thread_checker;
#inventory
type Mutability = #mutability;
type Frozen = <Self::PyClassMutability as _pyo3::pycell::PyClassMutability>::Frozen;
type PyClassMutability = <<#base as _pyo3::impl_::pyclass::PyClassBaseType>::PyClassMutability as _pyo3::pycell::PyClassMutability>::#class_mutability;
type Dict = #dict;
type WeakRef = #weakref;
Expand Down
23 changes: 23 additions & 0 deletions src/boolean_traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2022-present PyO3 Project and Contributors

//! A mechanism to have associated True / False values in the absence of
//! associated const equality.

pub(crate) mod private {
use super::*;

/// A way to "seal" the boolean traits.
pub trait Boolean {}

impl Boolean for True {}
impl Boolean for False {}
}

pub struct True(());
pub struct False(());

/// A trait which is used to describe whether a `#[pyclass]` is frozen.
pub trait Frozen: private::Boolean {}

impl Frozen for True {}
impl Frozen for False {}
13 changes: 6 additions & 7 deletions src/class/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@
//! Parts of the documentation are copied from the respective methods from the
//! [typeobj docs](https://docs.python.org/3/c-api/typeobj.html)

use crate::boolean_traits::False;
use crate::callback::{HashCallbackOutput, IntoPyCallbackOutput};
use crate::{
exceptions, ffi, pyclass::MutablePyClass, FromPyObject, PyAny, PyCell, PyClass, PyObject,
};
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 @@ -5,8 +5,9 @@
//!
//! For more information check [buffer protocol](https://docs.python.org/3/c-api/buffer.html)
//! c-api
use crate::boolean_traits::False;
use crate::callback::IntoPyCallbackOutput;
use crate::{ffi, pyclass::MutablePyClass, PyCell, PyRefMut};
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::boolean_traits::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 @@ -4,13 +4,14 @@
//! Python Mapping Interface
//! Trait and support implementation for implementing mapping support

use crate::boolean_traits::False;
use crate::callback::IntoPyCallbackOutput;
use crate::{pyclass::MutablePyClass, FromPyObject, PyClass, PyObject};
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 @@ -3,9 +3,10 @@

//! Python Number Interface
//! Trait and support implementation for implementing number protocol
use crate::boolean_traits::False;
use crate::callback::IntoPyCallbackOutput;
use crate::err::PyErr;
use crate::{ffi, pyclass::MutablePyClass, FromPyObject, PyClass, PyObject};
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 @@ -3,10 +3,11 @@
//! Python Sequence Interface
//! Trait and support implementation for implementing sequence

use crate::boolean_traits::False;
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::{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
Loading

0 comments on commit a758495

Please sign in to comment.