Skip to content
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
47 changes: 30 additions & 17 deletions derive-impl/src/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1453,29 +1453,37 @@ fn extract_impl_attrs(attr: AttributeArgs, item: &Ident) -> Result<ExtractedImpl
}];
let mut payload = None;

let mut has_constructor = false;
for attr in attr {
match attr {
NestedMeta::Meta(Meta::List(syn::MetaList { path, nested, .. })) => {
if path.is_ident("with") {
for meta in nested {
let NestedMeta::Meta(Meta::Path(path)) = meta else {
bail_span!(meta, "#[pyclass(with(...))] arguments should be paths")
let NestedMeta::Meta(Meta::Path(path)) = &meta else {
bail_span!(meta, "#[pyclass(with(...))] arguments must be paths")
};
let (extend_class, method_defs, extend_slots) = if path.is_ident("PyRef")
|| path.is_ident("Py")
{
// special handling for PyRef
(
quote!(#path::<Self>::__extend_py_class),
quote!(#path::<Self>::__OWN_METHOD_DEFS),
quote!(#path::<Self>::__extend_slots),
)
} else {
if path.is_ident("DefaultConstructor") {
bail_span!(meta, "Try `#[pyclass(with(Constructor, ...))]` instead of `#[pyclass(with(DefaultConstructor, ...))]`. DefaultConstructor implicitly implements Constructor.")
}
if path.is_ident("Constructor") || path.is_ident("Unconstructible") {
has_constructor = true;
}
(
quote!(<Self as #path>::__extend_py_class),
quote!(<Self as #path>::__OWN_METHOD_DEFS),
quote!(<Self as #path>::__extend_slots),
)
};
let (extend_class, method_defs, extend_slots) =
if path.is_ident("PyRef") || path.is_ident("Py") {
// special handling for PyRef
(
quote!(#path::<Self>::__extend_py_class),
quote!(#path::<Self>::__OWN_METHOD_DEFS),
quote!(#path::<Self>::__extend_slots),
)
} else {
(
quote!(<Self as #path>::__extend_py_class),
quote!(<Self as #path>::__OWN_METHOD_DEFS),
quote!(<Self as #path>::__extend_slots),
)
};
let item_span = item.span().resolved_at(Span::call_site());
withs.push(quote_spanned! { path.span() =>
#extend_class(ctx, class);
Expand Down Expand Up @@ -1518,6 +1526,11 @@ fn extract_impl_attrs(attr: AttributeArgs, item: &Ident) -> Result<ExtractedImpl
attr => bail_span!(attr, "Unknown pyimpl attribute"),
}
}
// TODO: DISALLOW_INSTANTIATION check is required
let _ = has_constructor;
// if !withs.is_empty() && !has_constructor {
// bail_span!(item, "#[pyclass(with(...))] does not have a Constructor. Either #[pyclass(with(Constructor, ...))] or #[pyclass(with(Unconstructible, ...))] is mandatory. Consider to add `impl DefaultConstructor for T {{}}` or `impl Unconstructible for T {{}}`.")
// }

Ok(ExtractedImplAttrs {
payload,
Expand Down
4 changes: 2 additions & 2 deletions stdlib/src/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ mod _socket {
common::os::ErrorExt,
convert::{IntoPyException, ToPyObject, TryFromBorrowedObject, TryFromObject},
function::{ArgBytesLike, ArgMemoryBuffer, Either, FsPath, OptionalArg, OptionalOption},
types::{DefaultConstructor, Initializer, Representable},
types::{Constructor, DefaultConstructor, Initializer, Representable},
utils::ToCString,
AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
Expand Down Expand Up @@ -1062,7 +1062,7 @@ mod _socket {
}
}

#[pyclass(with(DefaultConstructor, Initializer, Representable), flags(BASETYPE))]
#[pyclass(with(Constructor, Initializer, Representable), flags(BASETYPE))]
impl PySocket {
fn _init(
zelf: PyRef<Self>,
Expand Down
4 changes: 2 additions & 2 deletions vm/src/builtins/asyncgenerator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
frame::FrameRef,
function::OptionalArg,
protocol::PyIterReturn,
types::{Constructor, IterNext, Iterable, Representable, SelfIter, Unconstructible},
types::{IterNext, Iterable, Representable, SelfIter, Unconstructible},
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};

Expand All @@ -26,7 +26,7 @@ impl PyPayload for PyAsyncGen {
}
}

#[pyclass(with(PyRef, Constructor, Representable))]
#[pyclass(with(PyRef, Unconstructible, Representable))]
impl PyAsyncGen {
pub fn as_coro(&self) -> &Coro {
&self.inner
Expand Down
9 changes: 6 additions & 3 deletions vm/src/builtins/builtin_func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
class::PyClassImpl,
convert::TryFromObject,
function::{FuncArgs, PyComparisonValue, PyMethodDef, PyMethodFlags, PyNativeFn},
types::{Callable, Comparable, Constructor, PyComparisonOp, Representable, Unconstructible},
types::{Callable, Comparable, PyComparisonOp, Representable, Unconstructible},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
use std::fmt;
Expand Down Expand Up @@ -65,7 +65,7 @@ impl Callable for PyNativeFunction {
}
}

#[pyclass(with(Callable, Constructor), flags(HAS_DICT))]
#[pyclass(with(Callable, Unconstructible), flags(HAS_DICT))]
impl PyNativeFunction {
#[pygetset(magic)]
fn module(zelf: NativeFunctionOrMethod) -> Option<&'static PyStrInterned> {
Expand Down Expand Up @@ -138,7 +138,10 @@ pub struct PyNativeMethod {
pub(crate) class: &'static Py<PyType>, // TODO: the actual life is &'self
}

#[pyclass(with(Callable, Comparable, Representable), flags(HAS_DICT))]
#[pyclass(
with(Unconstructible, Callable, Comparable, Representable),
flags(HAS_DICT)
)]
impl PyNativeMethod {
#[pygetset(magic)]
fn qualname(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
Expand Down
20 changes: 6 additions & 14 deletions vm/src/builtins/bytearray.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ use crate::{
},
convert::{ToPyObject, ToPyResult},
function::{
ArgBytesLike, ArgIterable, ArgSize, Either, FuncArgs, OptionalArg, OptionalOption,
PyComparisonValue,
ArgBytesLike, ArgIterable, ArgSize, Either, OptionalArg, OptionalOption, PyComparisonValue,
},
protocol::{
BufferDescriptor, BufferMethods, BufferResizeGuard, PyBuffer, PyIterReturn,
PyMappingMethods, PyNumberMethods, PySequenceMethods,
},
sliceable::{SequenceIndex, SliceableSequenceMutOp, SliceableSequenceOp},
types::{
AsBuffer, AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor, Initializer,
IterNext, Iterable, PyComparisonOp, Representable, SelfIter, Unconstructible,
AsBuffer, AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor,
DefaultConstructor, Initializer, IterNext, Iterable, PyComparisonOp, Representable,
SelfIter, Unconstructible,
},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
VirtualMachine,
Expand Down Expand Up @@ -696,15 +696,7 @@ impl PyRef<PyByteArray> {
}
}

impl Constructor for PyByteArray {
type Args = FuncArgs;

fn py_new(cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult {
PyByteArray::default()
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
impl DefaultConstructor for PyByteArray {}

impl Initializer for PyByteArray {
type Args = ByteInnerNewOptions;
Expand Down Expand Up @@ -891,7 +883,7 @@ impl PyPayload for PyByteArrayIterator {
}
}

#[pyclass(with(Constructor, IterNext, Iterable))]
#[pyclass(with(Unconstructible, IterNext, Iterable))]
impl PyByteArrayIterator {
#[pymethod(magic)]
fn length_hint(&self) -> usize {
Expand Down
2 changes: 1 addition & 1 deletion vm/src/builtins/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ impl PyPayload for PyBytesIterator {
}
}

#[pyclass(with(Constructor, IterNext, Iterable))]
#[pyclass(with(Unconstructible, IterNext, Iterable))]
impl PyBytesIterator {
#[pymethod(magic)]
fn length_hint(&self) -> usize {
Expand Down
4 changes: 2 additions & 2 deletions vm/src/builtins/coroutine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
frame::FrameRef,
function::OptionalArg,
protocol::PyIterReturn,
types::{Constructor, IterNext, Iterable, Representable, SelfIter, Unconstructible},
types::{IterNext, Iterable, Representable, SelfIter, Unconstructible},
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};

Expand All @@ -22,7 +22,7 @@ impl PyPayload for PyCoroutine {
}
}

#[pyclass(with(Constructor, IterNext, Representable))]
#[pyclass(with(Unconstructible, IterNext, Representable))]
impl PyCoroutine {
pub fn as_coro(&self) -> &Coro {
&self.inner
Expand Down
6 changes: 3 additions & 3 deletions vm/src/builtins/descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
builtins::{builtin_func::PyNativeMethod, type_},
class::PyClassImpl,
function::{FuncArgs, PyMethodDef, PyMethodFlags, PySetterValue},
types::{Callable, Constructor, GetDescriptor, Representable, Unconstructible},
types::{Callable, GetDescriptor, Representable, Unconstructible},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
use rustpython_common::lock::PyRwLock;
Expand Down Expand Up @@ -103,7 +103,7 @@ impl PyMethodDescriptor {
}

#[pyclass(
with(GetDescriptor, Callable, Constructor, Representable),
with(GetDescriptor, Callable, Unconstructible, Representable),
flags(METHOD_DESCRIPTOR)
)]
impl PyMethodDescriptor {
Expand Down Expand Up @@ -237,7 +237,7 @@ fn calculate_qualname(descr: &PyDescriptorOwned, vm: &VirtualMachine) -> PyResul
}
}

#[pyclass(with(GetDescriptor, Constructor, Representable), flags(BASETYPE))]
#[pyclass(with(GetDescriptor, Unconstructible, Representable), flags(BASETYPE))]
impl PyMemberDescriptor {
#[pygetset(magic)]
fn doc(&self) -> Option<String> {
Expand Down
28 changes: 9 additions & 19 deletions vm/src/builtins/dict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@ use crate::{
class::{PyClassDef, PyClassImpl},
common::ascii,
dictdatatype::{self, DictKey},
function::{
ArgIterable, FuncArgs, KwArgs, OptionalArg, PyArithmeticValue::*, PyComparisonValue,
},
function::{ArgIterable, KwArgs, OptionalArg, PyArithmeticValue::*, PyComparisonValue},
iter::PyExactSizeIterator,
protocol::{PyIterIter, PyIterReturn, PyMappingMethods, PyNumberMethods, PySequenceMethods},
recursion::ReprGuard,
types::{
AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor, Initializer, IterNext,
Iterable, PyComparisonOp, Representable, SelfIter, Unconstructible,
AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor, DefaultConstructor,
Initializer, IterNext, Iterable, PyComparisonOp, Representable, SelfIter, Unconstructible,
},
vm::VirtualMachine,
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult,
Expand Down Expand Up @@ -410,15 +408,7 @@ impl PyRef<PyDict> {
}
}

impl Constructor for PyDict {
type Args = FuncArgs;

fn py_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
PyDict::default()
.into_ref_with_type(vm, cls)
.map(Into::into)
}
}
impl DefaultConstructor for PyDict {}

impl Initializer for PyDict {
type Args = (OptionalArg<PyObjectRef>, KwArgs);
Expand Down Expand Up @@ -835,7 +825,7 @@ macro_rules! dict_view {
}
}

#[pyclass(with(Constructor, IterNext, Iterable))]
#[pyclass(with(Unconstructible, IterNext, Iterable))]
impl $iter_name {
fn new(dict: PyDictRef) -> Self {
$iter_name {
Expand Down Expand Up @@ -908,7 +898,7 @@ macro_rules! dict_view {
}
}

#[pyclass(with(Constructor, IterNext, Iterable))]
#[pyclass(with(Unconstructible, IterNext, Iterable))]
impl $reverse_iter_name {
fn new(dict: PyDictRef) -> Self {
let size = dict.size();
Expand Down Expand Up @@ -1114,7 +1104,7 @@ trait ViewSetOps: DictView {
impl ViewSetOps for PyDictKeys {}
#[pyclass(with(
DictView,
Constructor,
Unconstructible,
Comparable,
Iterable,
ViewSetOps,
Expand Down Expand Up @@ -1178,7 +1168,7 @@ impl AsNumber for PyDictKeys {
impl ViewSetOps for PyDictItems {}
#[pyclass(with(
DictView,
Constructor,
Unconstructible,
Comparable,
Iterable,
ViewSetOps,
Expand Down Expand Up @@ -1253,7 +1243,7 @@ impl AsNumber for PyDictItems {
}
}

#[pyclass(with(DictView, Constructor, Iterable, AsSequence, Representable))]
#[pyclass(with(DictView, Unconstructible, Iterable, AsSequence, Representable))]
impl PyDictValues {
#[pygetset]
fn mapping(zelf: PyRef<Self>) -> PyMappingProxy {
Expand Down
4 changes: 2 additions & 2 deletions vm/src/builtins/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
class::PyClassImpl,
frame::{Frame, FrameRef},
function::PySetterValue,
types::{Constructor, Representable, Unconstructible},
types::{Representable, Unconstructible},
AsObject, Context, Py, PyObjectRef, PyRef, PyResult, VirtualMachine,
};
use num_traits::Zero;
Expand All @@ -31,7 +31,7 @@ impl Representable for Frame {
}
}

#[pyclass(with(Constructor, Py))]
#[pyclass(with(Unconstructible, Py))]
impl Frame {
#[pymethod]
fn clear(&self) {
Expand Down
4 changes: 2 additions & 2 deletions vm/src/builtins/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
frame::FrameRef,
function::OptionalArg,
protocol::PyIterReturn,
types::{Constructor, IterNext, Iterable, Representable, SelfIter, Unconstructible},
types::{IterNext, Iterable, Representable, SelfIter, Unconstructible},
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};

Expand All @@ -25,7 +25,7 @@ impl PyPayload for PyGenerator {
}
}

#[pyclass(with(Py, Constructor, IterNext, Iterable))]
#[pyclass(with(Py, Unconstructible, IterNext, Iterable))]
impl PyGenerator {
pub fn as_coro(&self) -> &Coro {
&self.inner
Expand Down
4 changes: 2 additions & 2 deletions vm/src/builtins/getset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::PyType;
use crate::{
class::PyClassImpl,
function::{IntoPyGetterFunc, IntoPySetterFunc, PyGetterFunc, PySetterFunc, PySetterValue},
types::{Constructor, GetDescriptor, Unconstructible},
types::{GetDescriptor, Unconstructible},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine,
};

Expand Down Expand Up @@ -94,7 +94,7 @@ impl PyGetSet {
}
}

#[pyclass(with(GetDescriptor, Constructor))]
#[pyclass(with(GetDescriptor, Unconstructible))]
impl PyGetSet {
// Descriptor methods

Expand Down
4 changes: 2 additions & 2 deletions vm/src/builtins/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ impl PyPayload for PyListIterator {
}
}

#[pyclass(with(Constructor, IterNext, Iterable))]
#[pyclass(with(Unconstructible, IterNext, Iterable))]
impl PyListIterator {
#[pymethod(magic)]
fn length_hint(&self) -> usize {
Expand Down Expand Up @@ -583,7 +583,7 @@ impl PyPayload for PyListReverseIterator {
}
}

#[pyclass(with(Constructor, IterNext, Iterable))]
#[pyclass(with(Unconstructible, IterNext, Iterable))]
impl PyListReverseIterator {
#[pymethod(magic)]
fn length_hint(&self) -> usize {
Expand Down
2 changes: 1 addition & 1 deletion vm/src/builtins/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1137,7 +1137,7 @@ impl PyPayload for PyMemoryViewIterator {
}
}

#[pyclass(with(Constructor, IterNext, Iterable))]
#[pyclass(with(Unconstructible, IterNext, Iterable))]
impl PyMemoryViewIterator {
#[pymethod(magic)]
fn reduce(&self, vm: &VirtualMachine) -> PyTupleRef {
Expand Down
Loading