mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
flag: DISALLOW_INSTANTIATION (#6445)
* Set tp_new slot when build heap/static type * Improve type tp_call impl to check tp_new existence and error if not exist * Set DISALLOW_INSTANTIATION flag on several types according to cpython impl * Allow #[pyslot] for function pointer * Fix DISALLOW_INSTANTIATION --------- Signed-off-by: snowapril <sinjihng@gmail.com> Co-authored-by: snowapril <sinjihng@gmail.com>
This commit is contained in:
1
Lib/test/test_descr.py
vendored
1
Lib/test/test_descr.py
vendored
@@ -1788,7 +1788,6 @@ class ClassPropertiesAndMethods(unittest.TestCase, ExtraAssertions):
|
||||
self.assertEqual(b.foo, 3)
|
||||
self.assertEqual(b.__class__, D)
|
||||
|
||||
@unittest.expectedFailure
|
||||
def test_bad_new(self):
|
||||
self.assertRaises(TypeError, object.__new__)
|
||||
self.assertRaises(TypeError, object.__new__, '')
|
||||
|
||||
@@ -954,7 +954,10 @@ where
|
||||
} else if let Ok(f) = args.item.function_or_method() {
|
||||
(&f.sig().ident, f.span())
|
||||
} else {
|
||||
return Err(self.new_syn_error(args.item.span(), "can only be on a method"));
|
||||
return Err(self.new_syn_error(
|
||||
args.item.span(),
|
||||
"can only be on a method or const function pointer",
|
||||
));
|
||||
};
|
||||
|
||||
let item_attr = args.attrs.remove(self.index());
|
||||
@@ -1496,7 +1499,9 @@ impl SlotItemMeta {
|
||||
}
|
||||
} else {
|
||||
let ident_str = self.inner().item_name();
|
||||
let name = if let Some(stripped) = ident_str.strip_prefix("slot_") {
|
||||
// Convert to lowercase to handle both SLOT_NEW and slot_new
|
||||
let ident_lower = ident_str.to_lowercase();
|
||||
let name = if let Some(stripped) = ident_lower.strip_prefix("slot_") {
|
||||
proc_macro2::Ident::new(stripped, inner.item_ident.span())
|
||||
} else {
|
||||
inner.item_ident.clone()
|
||||
@@ -1609,7 +1614,6 @@ fn extract_impl_attrs(attr: PunctuatedNestedMeta, item: &Ident) -> Result<Extrac
|
||||
}];
|
||||
let mut payload = None;
|
||||
|
||||
let mut has_constructor = false;
|
||||
for attr in attr {
|
||||
match attr {
|
||||
NestedMeta::Meta(Meta::List(MetaList { path, nested, .. })) => {
|
||||
@@ -1634,9 +1638,6 @@ fn extract_impl_attrs(attr: PunctuatedNestedMeta, item: &Ident) -> Result<Extrac
|
||||
"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),
|
||||
@@ -1689,11 +1690,6 @@ fn extract_impl_attrs(attr: PunctuatedNestedMeta, item: &Ident) -> Result<Extrac
|
||||
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,
|
||||
|
||||
@@ -1399,7 +1399,7 @@ mod array {
|
||||
internal: PyMutex<PositionIterInternal<PyArrayRef>>,
|
||||
}
|
||||
|
||||
#[pyclass(with(IterNext, Iterable), flags(HAS_DICT))]
|
||||
#[pyclass(with(IterNext, Iterable), flags(HAS_DICT, DISALLOW_INSTANTIATION))]
|
||||
impl PyArrayIter {
|
||||
#[pymethod]
|
||||
fn __setstate__(&self, state: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
|
||||
@@ -908,7 +908,7 @@ mod _csv {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(IterNext, Iterable))]
|
||||
#[pyclass(with(IterNext, Iterable), flags(DISALLOW_INSTANTIATION))]
|
||||
impl Reader {
|
||||
#[pygetset]
|
||||
fn line_num(&self) -> u64 {
|
||||
@@ -1059,7 +1059,7 @@ mod _csv {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION))]
|
||||
impl Writer {
|
||||
#[pygetset(name = "dialect")]
|
||||
const fn get_dialect(&self, _vm: &VirtualMachine) -> PyDialect {
|
||||
|
||||
@@ -16,7 +16,7 @@ pub(crate) mod _struct {
|
||||
function::{ArgBytesLike, ArgMemoryBuffer, PosArgs},
|
||||
match_class,
|
||||
protocol::PyIterReturn,
|
||||
types::{Constructor, IterNext, Iterable, Representable, SelfIter, Unconstructible},
|
||||
types::{Constructor, IterNext, Iterable, Representable, SelfIter},
|
||||
};
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
|
||||
@@ -189,7 +189,7 @@ pub(crate) mod _struct {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Unconstructible, IterNext, Iterable))]
|
||||
#[pyclass(with(IterNext, Iterable), flags(DISALLOW_INSTANTIATION))]
|
||||
impl UnpackIterator {
|
||||
#[pymethod]
|
||||
fn __length_hint__(&self) -> usize {
|
||||
@@ -197,7 +197,7 @@ pub(crate) mod _struct {
|
||||
}
|
||||
}
|
||||
impl SelfIter for UnpackIterator {}
|
||||
impl Unconstructible for UnpackIterator {}
|
||||
|
||||
impl IterNext for UnpackIterator {
|
||||
fn next(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
|
||||
let size = zelf.format_spec.size;
|
||||
|
||||
@@ -75,7 +75,7 @@ mod _sqlite {
|
||||
sliceable::{SaturatedSliceIter, SliceableSequenceOp},
|
||||
types::{
|
||||
AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor, Hashable,
|
||||
Initializer, IterNext, Iterable, PyComparisonOp, SelfIter, Unconstructible,
|
||||
Initializer, IterNext, Iterable, PyComparisonOp, SelfIter,
|
||||
},
|
||||
utils::ToCString,
|
||||
};
|
||||
@@ -2197,8 +2197,6 @@ mod _sqlite {
|
||||
inner: PyMutex<Option<BlobInner>>,
|
||||
}
|
||||
|
||||
impl Unconstructible for Blob {}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct BlobInner {
|
||||
blob: SqliteBlob,
|
||||
@@ -2211,7 +2209,7 @@ mod _sqlite {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(AsMapping, Unconstructible, AsNumber, AsSequence))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(AsMapping, AsNumber, AsSequence))]
|
||||
impl Blob {
|
||||
#[pymethod]
|
||||
fn close(&self) {
|
||||
@@ -2592,9 +2590,7 @@ mod _sqlite {
|
||||
}
|
||||
}
|
||||
|
||||
impl Unconstructible for Statement {}
|
||||
|
||||
#[pyclass(with(Unconstructible))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION))]
|
||||
impl Statement {
|
||||
fn new(
|
||||
connection: &Connection,
|
||||
|
||||
@@ -105,7 +105,7 @@ mod unicodedata {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION))]
|
||||
impl Ucd {
|
||||
#[pymethod]
|
||||
fn category(&self, character: PyStrRef, vm: &VirtualMachine) -> PyResult<String> {
|
||||
|
||||
@@ -225,7 +225,7 @@ mod zlib {
|
||||
inner: PyMutex<PyDecompressInner>,
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION))]
|
||||
impl PyDecompress {
|
||||
#[pygetset]
|
||||
fn eof(&self) -> bool {
|
||||
@@ -383,7 +383,7 @@ mod zlib {
|
||||
inner: PyMutex<CompressState<CompressInner>>,
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION))]
|
||||
impl PyCompress {
|
||||
#[pymethod]
|
||||
fn compress(&self, data: ArgBytesLike, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
frame::FrameRef,
|
||||
function::OptionalArg,
|
||||
protocol::PyIterReturn,
|
||||
types::{IterNext, Iterable, Representable, SelfIter, Unconstructible},
|
||||
types::{IterNext, Iterable, Representable, SelfIter},
|
||||
};
|
||||
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
@@ -32,7 +32,7 @@ impl PyPayload for PyAsyncGen {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(PyRef, Unconstructible, Representable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(PyRef, Representable))]
|
||||
impl PyAsyncGen {
|
||||
pub const fn as_coro(&self) -> &Coro {
|
||||
&self.inner
|
||||
@@ -201,8 +201,6 @@ impl Representable for PyAsyncGen {
|
||||
}
|
||||
}
|
||||
|
||||
impl Unconstructible for PyAsyncGen {}
|
||||
|
||||
#[pyclass(module = false, name = "async_generator_wrapped_value")]
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct PyAsyncGenWrappedValue(pub PyObjectRef);
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::{
|
||||
common::wtf8::Wtf8,
|
||||
convert::TryFromObject,
|
||||
function::{FuncArgs, PyComparisonValue, PyMethodDef, PyMethodFlags, PyNativeFn},
|
||||
types::{Callable, Comparable, PyComparisonOp, Representable, Unconstructible},
|
||||
types::{Callable, Comparable, PyComparisonOp, Representable},
|
||||
};
|
||||
use std::fmt;
|
||||
|
||||
@@ -74,7 +74,7 @@ impl Callable for PyNativeFunction {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Callable, Unconstructible), flags(HAS_DICT))]
|
||||
#[pyclass(with(Callable), flags(HAS_DICT, DISALLOW_INSTANTIATION))]
|
||||
impl PyNativeFunction {
|
||||
#[pygetset]
|
||||
fn __module__(zelf: NativeFunctionOrMethod) -> Option<&'static PyStrInterned> {
|
||||
@@ -145,8 +145,6 @@ impl Representable for PyNativeFunction {
|
||||
}
|
||||
}
|
||||
|
||||
impl Unconstructible for PyNativeFunction {}
|
||||
|
||||
// `PyCMethodObject` in CPython
|
||||
#[pyclass(name = "builtin_method", module = false, base = PyNativeFunction, ctx = "builtin_method_type")]
|
||||
pub struct PyNativeMethod {
|
||||
@@ -155,8 +153,8 @@ pub struct PyNativeMethod {
|
||||
}
|
||||
|
||||
#[pyclass(
|
||||
with(Unconstructible, Callable, Comparable, Representable),
|
||||
flags(HAS_DICT)
|
||||
with(Callable, Comparable, Representable),
|
||||
flags(HAS_DICT, DISALLOW_INSTANTIATION)
|
||||
)]
|
||||
impl PyNativeMethod {
|
||||
#[pygetset]
|
||||
@@ -246,8 +244,6 @@ impl Representable for PyNativeMethod {
|
||||
}
|
||||
}
|
||||
|
||||
impl Unconstructible for PyNativeMethod {}
|
||||
|
||||
pub fn init(context: &Context) {
|
||||
PyNativeFunction::extend_class(context, context.types.builtin_function_or_method_type);
|
||||
PyNativeMethod::extend_class(context, context.types.builtin_method_type);
|
||||
|
||||
@@ -33,7 +33,7 @@ use crate::{
|
||||
types::{
|
||||
AsBuffer, AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor,
|
||||
DefaultConstructor, Initializer, IterNext, Iterable, PyComparisonOp, Representable,
|
||||
SelfIter, Unconstructible,
|
||||
SelfIter,
|
||||
},
|
||||
};
|
||||
use bstr::ByteSlice;
|
||||
@@ -865,7 +865,7 @@ impl PyPayload for PyByteArrayIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Unconstructible, IterNext, Iterable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
|
||||
impl PyByteArrayIterator {
|
||||
#[pymethod]
|
||||
fn __length_hint__(&self) -> usize {
|
||||
@@ -886,8 +886,6 @@ impl PyByteArrayIterator {
|
||||
}
|
||||
}
|
||||
|
||||
impl Unconstructible for PyByteArrayIterator {}
|
||||
|
||||
impl SelfIter for PyByteArrayIterator {}
|
||||
impl IterNext for PyByteArrayIterator {
|
||||
fn next(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
|
||||
|
||||
@@ -25,7 +25,7 @@ use crate::{
|
||||
sliceable::{SequenceIndex, SliceableSequenceOp},
|
||||
types::{
|
||||
AsBuffer, AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor, Hashable,
|
||||
IterNext, Iterable, PyComparisonOp, Representable, SelfIter, Unconstructible,
|
||||
IterNext, Iterable, PyComparisonOp, Representable, SelfIter,
|
||||
},
|
||||
};
|
||||
use bstr::ByteSlice;
|
||||
@@ -749,7 +749,7 @@ impl PyPayload for PyBytesIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Unconstructible, IterNext, Iterable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
|
||||
impl PyBytesIterator {
|
||||
#[pymethod]
|
||||
fn __length_hint__(&self) -> usize {
|
||||
@@ -770,7 +770,6 @@ impl PyBytesIterator {
|
||||
.set_state(state, |obj, pos| pos.min(obj.len()), vm)
|
||||
}
|
||||
}
|
||||
impl Unconstructible for PyBytesIterator {}
|
||||
|
||||
impl SelfIter for PyBytesIterator {}
|
||||
impl IterNext for PyBytesIterator {
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::{
|
||||
frame::FrameRef,
|
||||
function::OptionalArg,
|
||||
protocol::PyIterReturn,
|
||||
types::{IterNext, Iterable, Representable, SelfIter, Unconstructible},
|
||||
types::{IterNext, Iterable, Representable, SelfIter},
|
||||
};
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
|
||||
@@ -24,7 +24,7 @@ impl PyPayload for PyCoroutine {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Py, Unconstructible, IterNext, Representable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(Py, IterNext, Representable))]
|
||||
impl PyCoroutine {
|
||||
pub const fn as_coro(&self) -> &Coro {
|
||||
&self.inner
|
||||
@@ -123,8 +123,6 @@ impl Py<PyCoroutine> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Unconstructible for PyCoroutine {}
|
||||
|
||||
impl Representable for PyCoroutine {
|
||||
#[inline]
|
||||
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
builtins::{PyTypeRef, builtin_func::PyNativeMethod, type_},
|
||||
class::PyClassImpl,
|
||||
function::{FuncArgs, PyMethodDef, PyMethodFlags, PySetterValue},
|
||||
types::{Callable, GetDescriptor, Representable, Unconstructible},
|
||||
types::{Callable, GetDescriptor, Representable},
|
||||
};
|
||||
use rustpython_common::lock::PyRwLock;
|
||||
|
||||
@@ -105,8 +105,8 @@ impl PyMethodDescriptor {
|
||||
}
|
||||
|
||||
#[pyclass(
|
||||
with(GetDescriptor, Callable, Unconstructible, Representable),
|
||||
flags(METHOD_DESCRIPTOR)
|
||||
with(GetDescriptor, Callable, Representable),
|
||||
flags(METHOD_DESCRIPTOR, DISALLOW_INSTANTIATION)
|
||||
)]
|
||||
impl PyMethodDescriptor {
|
||||
#[pygetset]
|
||||
@@ -159,8 +159,6 @@ impl Representable for PyMethodDescriptor {
|
||||
}
|
||||
}
|
||||
|
||||
impl Unconstructible for PyMethodDescriptor {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MemberKind {
|
||||
Bool = 14,
|
||||
@@ -246,7 +244,10 @@ fn calculate_qualname(descr: &PyDescriptorOwned, vm: &VirtualMachine) -> PyResul
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(GetDescriptor, Unconstructible, Representable), flags(BASETYPE))]
|
||||
#[pyclass(
|
||||
with(GetDescriptor, Representable),
|
||||
flags(BASETYPE, DISALLOW_INSTANTIATION)
|
||||
)]
|
||||
impl PyMemberDescriptor {
|
||||
#[pygetset]
|
||||
fn __doc__(&self) -> Option<String> {
|
||||
@@ -339,8 +340,6 @@ fn set_slot_at_object(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Unconstructible for PyMemberDescriptor {}
|
||||
|
||||
impl Representable for PyMemberDescriptor {
|
||||
#[inline]
|
||||
fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
|
||||
|
||||
@@ -19,7 +19,7 @@ use crate::{
|
||||
recursion::ReprGuard,
|
||||
types::{
|
||||
AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor, DefaultConstructor,
|
||||
Initializer, IterNext, Iterable, PyComparisonOp, Representable, SelfIter, Unconstructible,
|
||||
Initializer, IterNext, Iterable, PyComparisonOp, Representable, SelfIter,
|
||||
},
|
||||
vm::VirtualMachine,
|
||||
};
|
||||
@@ -848,7 +848,7 @@ macro_rules! dict_view {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Unconstructible, IterNext, Iterable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
|
||||
impl $iter_name {
|
||||
fn new(dict: PyDictRef) -> Self {
|
||||
$iter_name {
|
||||
@@ -878,8 +878,6 @@ macro_rules! dict_view {
|
||||
}
|
||||
}
|
||||
|
||||
impl Unconstructible for $iter_name {}
|
||||
|
||||
impl SelfIter for $iter_name {}
|
||||
impl IterNext for $iter_name {
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
@@ -923,7 +921,7 @@ macro_rules! dict_view {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Unconstructible, IterNext, Iterable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
|
||||
impl $reverse_iter_name {
|
||||
fn new(dict: PyDictRef) -> Self {
|
||||
let size = dict.size();
|
||||
@@ -957,8 +955,6 @@ macro_rules! dict_view {
|
||||
.rev_length_hint(|_| self.size.entries_size)
|
||||
}
|
||||
}
|
||||
impl Unconstructible for $reverse_iter_name {}
|
||||
|
||||
impl SelfIter for $reverse_iter_name {}
|
||||
impl IterNext for $reverse_iter_name {
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
@@ -1126,16 +1122,18 @@ trait ViewSetOps: DictView {
|
||||
}
|
||||
|
||||
impl ViewSetOps for PyDictKeys {}
|
||||
#[pyclass(with(
|
||||
DictView,
|
||||
Unconstructible,
|
||||
Comparable,
|
||||
Iterable,
|
||||
ViewSetOps,
|
||||
AsSequence,
|
||||
AsNumber,
|
||||
Representable
|
||||
))]
|
||||
#[pyclass(
|
||||
flags(DISALLOW_INSTANTIATION),
|
||||
with(
|
||||
DictView,
|
||||
Comparable,
|
||||
Iterable,
|
||||
ViewSetOps,
|
||||
AsSequence,
|
||||
AsNumber,
|
||||
Representable
|
||||
)
|
||||
)]
|
||||
impl PyDictKeys {
|
||||
#[pymethod]
|
||||
fn __contains__(zelf: PyObjectRef, key: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
@@ -1147,7 +1145,6 @@ impl PyDictKeys {
|
||||
PyMappingProxy::from(zelf.dict().clone())
|
||||
}
|
||||
}
|
||||
impl Unconstructible for PyDictKeys {}
|
||||
|
||||
impl Comparable for PyDictKeys {
|
||||
fn cmp(
|
||||
@@ -1190,16 +1187,18 @@ impl AsNumber for PyDictKeys {
|
||||
}
|
||||
|
||||
impl ViewSetOps for PyDictItems {}
|
||||
#[pyclass(with(
|
||||
DictView,
|
||||
Unconstructible,
|
||||
Comparable,
|
||||
Iterable,
|
||||
ViewSetOps,
|
||||
AsSequence,
|
||||
AsNumber,
|
||||
Representable
|
||||
))]
|
||||
#[pyclass(
|
||||
flags(DISALLOW_INSTANTIATION),
|
||||
with(
|
||||
DictView,
|
||||
Comparable,
|
||||
Iterable,
|
||||
ViewSetOps,
|
||||
AsSequence,
|
||||
AsNumber,
|
||||
Representable
|
||||
)
|
||||
)]
|
||||
impl PyDictItems {
|
||||
#[pymethod]
|
||||
fn __contains__(zelf: PyObjectRef, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
@@ -1210,7 +1209,6 @@ impl PyDictItems {
|
||||
PyMappingProxy::from(zelf.dict().clone())
|
||||
}
|
||||
}
|
||||
impl Unconstructible for PyDictItems {}
|
||||
|
||||
impl Comparable for PyDictItems {
|
||||
fn cmp(
|
||||
@@ -1264,14 +1262,16 @@ impl AsNumber for PyDictItems {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(DictView, Unconstructible, Iterable, AsSequence, Representable))]
|
||||
#[pyclass(
|
||||
flags(DISALLOW_INSTANTIATION),
|
||||
with(DictView, Iterable, AsSequence, Representable)
|
||||
)]
|
||||
impl PyDictValues {
|
||||
#[pygetset]
|
||||
fn mapping(zelf: PyRef<Self>) -> PyMappingProxy {
|
||||
PyMappingProxy::from(zelf.dict().clone())
|
||||
}
|
||||
}
|
||||
impl Unconstructible for PyDictValues {}
|
||||
|
||||
impl AsSequence for PyDictValues {
|
||||
fn as_sequence() -> &'static PySequenceMethods {
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
class::PyClassImpl,
|
||||
frame::{Frame, FrameRef},
|
||||
function::PySetterValue,
|
||||
types::{Representable, Unconstructible},
|
||||
types::Representable,
|
||||
};
|
||||
use num_traits::Zero;
|
||||
|
||||
@@ -16,8 +16,6 @@ pub fn init(context: &Context) {
|
||||
Frame::extend_class(context, context.types.frame_type);
|
||||
}
|
||||
|
||||
impl Unconstructible for Frame {}
|
||||
|
||||
impl Representable for Frame {
|
||||
#[inline]
|
||||
fn repr(_zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
|
||||
@@ -31,7 +29,7 @@ impl Representable for Frame {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Unconstructible, Py))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(Py))]
|
||||
impl Frame {
|
||||
#[pymethod]
|
||||
const fn clear(&self) {
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
frame::FrameRef,
|
||||
function::OptionalArg,
|
||||
protocol::PyIterReturn,
|
||||
types::{IterNext, Iterable, Representable, SelfIter, Unconstructible},
|
||||
types::{IterNext, Iterable, Representable, SelfIter},
|
||||
};
|
||||
|
||||
#[pyclass(module = false, name = "generator")]
|
||||
@@ -26,7 +26,7 @@ impl PyPayload for PyGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Py, Unconstructible, IterNext, Iterable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(Py, IterNext, Iterable))]
|
||||
impl PyGenerator {
|
||||
pub const fn as_coro(&self) -> &Coro {
|
||||
&self.inner
|
||||
@@ -114,8 +114,6 @@ impl Py<PyGenerator> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Unconstructible for PyGenerator {}
|
||||
|
||||
impl Representable for PyGenerator {
|
||||
#[inline]
|
||||
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::{
|
||||
builtins::type_::PointerSlot,
|
||||
class::PyClassImpl,
|
||||
function::{IntoPyGetterFunc, IntoPySetterFunc, PyGetterFunc, PySetterFunc, PySetterValue},
|
||||
types::{GetDescriptor, Unconstructible},
|
||||
types::GetDescriptor,
|
||||
};
|
||||
|
||||
#[pyclass(module = false, name = "getset_descriptor")]
|
||||
@@ -96,7 +96,7 @@ impl PyGetSet {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(GetDescriptor, Unconstructible))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(GetDescriptor))]
|
||||
impl PyGetSet {
|
||||
// Descriptor methods
|
||||
|
||||
@@ -152,7 +152,6 @@ impl PyGetSet {
|
||||
Ok(unsafe { zelf.class.borrow_static() }.to_owned().into())
|
||||
}
|
||||
}
|
||||
impl Unconstructible for PyGetSet {}
|
||||
|
||||
pub(crate) fn init(context: &Context) {
|
||||
PyGetSet::extend_class(context, context.types.getset_type);
|
||||
|
||||
@@ -15,7 +15,7 @@ use crate::{
|
||||
sliceable::{SequenceIndex, SliceableSequenceMutOp, SliceableSequenceOp},
|
||||
types::{
|
||||
AsMapping, AsSequence, Comparable, Constructor, Initializer, IterNext, Iterable,
|
||||
PyComparisonOp, Representable, SelfIter, Unconstructible,
|
||||
PyComparisonOp, Representable, SelfIter,
|
||||
},
|
||||
utils::collection_repr,
|
||||
vm::VirtualMachine,
|
||||
@@ -544,7 +544,7 @@ impl PyPayload for PyListIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Unconstructible, IterNext, Iterable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
|
||||
impl PyListIterator {
|
||||
#[pymethod]
|
||||
fn __length_hint__(&self) -> usize {
|
||||
@@ -565,7 +565,6 @@ impl PyListIterator {
|
||||
.builtins_iter_reduce(|x| x.clone().into(), vm)
|
||||
}
|
||||
}
|
||||
impl Unconstructible for PyListIterator {}
|
||||
|
||||
impl SelfIter for PyListIterator {}
|
||||
impl IterNext for PyListIterator {
|
||||
@@ -590,7 +589,7 @@ impl PyPayload for PyListReverseIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Unconstructible, IterNext, Iterable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
|
||||
impl PyListReverseIterator {
|
||||
#[pymethod]
|
||||
fn __length_hint__(&self) -> usize {
|
||||
@@ -611,7 +610,6 @@ impl PyListReverseIterator {
|
||||
.builtins_reversed_reduce(|x| x.clone().into(), vm)
|
||||
}
|
||||
}
|
||||
impl Unconstructible for PyListReverseIterator {}
|
||||
|
||||
impl SelfIter for PyListReverseIterator {}
|
||||
impl IterNext for PyListReverseIterator {
|
||||
|
||||
@@ -23,7 +23,7 @@ use crate::{
|
||||
sliceable::SequenceIndexOp,
|
||||
types::{
|
||||
AsBuffer, AsMapping, AsSequence, Comparable, Constructor, Hashable, IterNext, Iterable,
|
||||
PyComparisonOp, Representable, SelfIter, Unconstructible,
|
||||
PyComparisonOp, Representable, SelfIter,
|
||||
},
|
||||
};
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
@@ -1132,7 +1132,7 @@ impl PyPayload for PyMemoryViewIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Unconstructible, IterNext, Iterable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
|
||||
impl PyMemoryViewIterator {
|
||||
#[pymethod]
|
||||
fn __reduce__(&self, vm: &VirtualMachine) -> PyTupleRef {
|
||||
@@ -1141,7 +1141,6 @@ impl PyMemoryViewIterator {
|
||||
.builtins_iter_reduce(|x| x.clone().into(), vm)
|
||||
}
|
||||
}
|
||||
impl Unconstructible for PyMemoryViewIterator {}
|
||||
|
||||
impl SelfIter for PyMemoryViewIterator {}
|
||||
impl IterNext for PyMemoryViewIterator {
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::{
|
||||
protocol::{PyIterReturn, PyMappingMethods, PySequenceMethods},
|
||||
types::{
|
||||
AsMapping, AsSequence, Comparable, Hashable, IterNext, Iterable, PyComparisonOp,
|
||||
Representable, SelfIter, Unconstructible,
|
||||
Representable, SelfIter,
|
||||
},
|
||||
};
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
@@ -548,7 +548,7 @@ impl PyPayload for PyLongRangeIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Unconstructible, IterNext, Iterable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
|
||||
impl PyLongRangeIterator {
|
||||
#[pymethod]
|
||||
fn __length_hint__(&self) -> BigInt {
|
||||
@@ -577,7 +577,6 @@ impl PyLongRangeIterator {
|
||||
)
|
||||
}
|
||||
}
|
||||
impl Unconstructible for PyLongRangeIterator {}
|
||||
|
||||
impl SelfIter for PyLongRangeIterator {}
|
||||
impl IterNext for PyLongRangeIterator {
|
||||
@@ -614,7 +613,7 @@ impl PyPayload for PyRangeIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Unconstructible, IterNext, Iterable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
|
||||
impl PyRangeIterator {
|
||||
#[pymethod]
|
||||
fn __length_hint__(&self) -> usize {
|
||||
@@ -640,7 +639,6 @@ impl PyRangeIterator {
|
||||
)
|
||||
}
|
||||
}
|
||||
impl Unconstructible for PyRangeIterator {}
|
||||
|
||||
impl SelfIter for PyRangeIterator {}
|
||||
impl IterNext for PyRangeIterator {
|
||||
|
||||
@@ -18,7 +18,7 @@ use crate::{
|
||||
types::AsNumber,
|
||||
types::{
|
||||
AsSequence, Comparable, Constructor, DefaultConstructor, Hashable, Initializer, IterNext,
|
||||
Iterable, PyComparisonOp, Representable, SelfIter, Unconstructible,
|
||||
Iterable, PyComparisonOp, Representable, SelfIter,
|
||||
},
|
||||
utils::collection_repr,
|
||||
vm::VirtualMachine,
|
||||
@@ -1304,7 +1304,7 @@ impl PyPayload for PySetIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Unconstructible, IterNext, Iterable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
|
||||
impl PySetIterator {
|
||||
#[pymethod]
|
||||
fn __length_hint__(&self) -> usize {
|
||||
@@ -1330,7 +1330,6 @@ impl PySetIterator {
|
||||
))
|
||||
}
|
||||
}
|
||||
impl Unconstructible for PySetIterator {}
|
||||
|
||||
impl SelfIter for PySetIterator {}
|
||||
impl IterNext for PySetIterator {
|
||||
|
||||
@@ -21,7 +21,7 @@ use crate::{
|
||||
sliceable::{SequenceIndex, SliceableSequenceOp},
|
||||
types::{
|
||||
AsMapping, AsNumber, AsSequence, Comparable, Constructor, Hashable, IterNext, Iterable,
|
||||
PyComparisonOp, Representable, SelfIter, Unconstructible,
|
||||
PyComparisonOp, Representable, SelfIter,
|
||||
},
|
||||
};
|
||||
use ascii::{AsciiChar, AsciiStr, AsciiString};
|
||||
@@ -282,7 +282,7 @@ impl PyPayload for PyStrIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Unconstructible, IterNext, Iterable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
|
||||
impl PyStrIterator {
|
||||
#[pymethod]
|
||||
fn __length_hint__(&self) -> usize {
|
||||
@@ -307,8 +307,6 @@ impl PyStrIterator {
|
||||
}
|
||||
}
|
||||
|
||||
impl Unconstructible for PyStrIterator {}
|
||||
|
||||
impl SelfIter for PyStrIterator {}
|
||||
|
||||
impl IterNext for PyStrIterator {
|
||||
|
||||
@@ -16,7 +16,7 @@ use crate::{
|
||||
sliceable::{SequenceIndex, SliceableSequenceOp},
|
||||
types::{
|
||||
AsMapping, AsSequence, Comparable, Constructor, Hashable, IterNext, Iterable,
|
||||
PyComparisonOp, Representable, SelfIter, Unconstructible,
|
||||
PyComparisonOp, Representable, SelfIter,
|
||||
},
|
||||
utils::collection_repr,
|
||||
vm::VirtualMachine,
|
||||
@@ -533,7 +533,7 @@ impl PyPayload for PyTupleIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(Unconstructible, IterNext, Iterable))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
|
||||
impl PyTupleIterator {
|
||||
#[pymethod]
|
||||
fn __length_hint__(&self) -> usize {
|
||||
@@ -554,7 +554,6 @@ impl PyTupleIterator {
|
||||
.builtins_iter_reduce(|x| x.clone().into(), vm)
|
||||
}
|
||||
}
|
||||
impl Unconstructible for PyTupleIterator {}
|
||||
|
||||
impl SelfIter for PyTupleIterator {}
|
||||
impl IterNext for PyTupleIterator {
|
||||
|
||||
@@ -191,13 +191,16 @@ impl PyType {
|
||||
name: &str,
|
||||
bases: Vec<PyRef<Self>>,
|
||||
attrs: PyAttributes,
|
||||
slots: PyTypeSlots,
|
||||
mut slots: PyTypeSlots,
|
||||
metaclass: PyRef<Self>,
|
||||
ctx: &Context,
|
||||
) -> Result<PyRef<Self>, String> {
|
||||
// TODO: ensure clean slot name
|
||||
// assert_eq!(slots.name.borrow(), "");
|
||||
|
||||
// Set HEAPTYPE flag for heap-allocated types
|
||||
slots.flags |= PyTypeFlags::HEAPTYPE;
|
||||
|
||||
let name = ctx.new_str(name);
|
||||
let heaptype_ext = HeapTypeExt {
|
||||
name: PyRwLock::new(name.clone()),
|
||||
@@ -401,6 +404,8 @@ impl PyType {
|
||||
None,
|
||||
);
|
||||
|
||||
Self::set_new(&new_type.slots, &new_type.base);
|
||||
|
||||
let weakref_type = super::PyWeak::static_type();
|
||||
for base in new_type.bases.read().iter() {
|
||||
base.subclasses.write().push(
|
||||
@@ -420,9 +425,6 @@ impl PyType {
|
||||
|
||||
for cls in self.mro.read().iter() {
|
||||
for &name in cls.attributes.read().keys() {
|
||||
if name == identifier!(ctx, __new__) {
|
||||
continue;
|
||||
}
|
||||
if name.as_bytes().starts_with(b"__") && name.as_bytes().ends_with(b"__") {
|
||||
slot_name_set.insert(name);
|
||||
}
|
||||
@@ -436,6 +438,20 @@ impl PyType {
|
||||
for attr_name in slot_name_set {
|
||||
self.update_slot::<true>(attr_name, ctx);
|
||||
}
|
||||
|
||||
Self::set_new(&self.slots, &self.base);
|
||||
}
|
||||
|
||||
fn set_new(slots: &PyTypeSlots, base: &Option<PyTypeRef>) {
|
||||
if slots.flags.contains(PyTypeFlags::DISALLOW_INSTANTIATION) {
|
||||
slots.new.store(None)
|
||||
} else if slots.new.load().is_none() {
|
||||
slots.new.store(
|
||||
base.as_ref()
|
||||
.map(|base| base.slots.new.load())
|
||||
.unwrap_or(None),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// This is used for class initialization where the vm is not yet available.
|
||||
@@ -1563,15 +1579,28 @@ impl Callable for PyType {
|
||||
type Args = FuncArgs;
|
||||
fn call(zelf: &Py<Self>, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
vm_trace!("type_call: {:?}", zelf);
|
||||
let obj = call_slot_new(zelf.to_owned(), zelf.to_owned(), args.clone(), vm)?;
|
||||
|
||||
if (zelf.is(vm.ctx.types.type_type) && args.kwargs.is_empty()) || !obj.fast_isinstance(zelf)
|
||||
{
|
||||
if zelf.is(vm.ctx.types.type_type) {
|
||||
let num_args = args.args.len();
|
||||
if num_args == 1 && args.kwargs.is_empty() {
|
||||
return Ok(args.args[0].obj_type());
|
||||
}
|
||||
if num_args != 3 {
|
||||
return Err(vm.new_type_error("type() takes 1 or 3 arguments".to_owned()));
|
||||
}
|
||||
}
|
||||
|
||||
let obj = if let Some(slot_new) = zelf.slots.new.load() {
|
||||
slot_new(zelf.to_owned(), args.clone(), vm)?
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!("cannot create '{}' instances", zelf.slots.name)));
|
||||
};
|
||||
|
||||
if !obj.class().fast_issubclass(zelf) {
|
||||
return Ok(obj);
|
||||
}
|
||||
|
||||
let init = obj.class().mro_find_map(|cls| cls.slots.init.load());
|
||||
if let Some(init_method) = init {
|
||||
if let Some(init_method) = obj.class().slots.init.load() {
|
||||
init_method(obj.clone(), args, vm)?;
|
||||
}
|
||||
Ok(obj)
|
||||
@@ -1700,6 +1729,40 @@ pub(crate) fn call_slot_new(
|
||||
args: FuncArgs,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
// Check DISALLOW_INSTANTIATION flag on subtype (the type being instantiated)
|
||||
if subtype
|
||||
.slots
|
||||
.flags
|
||||
.has_feature(PyTypeFlags::DISALLOW_INSTANTIATION)
|
||||
{
|
||||
return Err(vm.new_type_error(format!("cannot create '{}' instances", subtype.slot_name())));
|
||||
}
|
||||
|
||||
// "is not safe" check (tp_new_wrapper logic)
|
||||
// Check that the user doesn't do something silly and unsafe like
|
||||
// object.__new__(dict). To do this, we check that the most derived base
|
||||
// that's not a heap type is this type.
|
||||
let mut staticbase = subtype.clone();
|
||||
while staticbase.slots.flags.has_feature(PyTypeFlags::HEAPTYPE) {
|
||||
if let Some(base) = staticbase.base.as_ref() {
|
||||
staticbase = base.clone();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if staticbase's tp_new differs from typ's tp_new
|
||||
let typ_new = typ.slots.new.load();
|
||||
let staticbase_new = staticbase.slots.new.load();
|
||||
if typ_new.map(|f| f as usize) != staticbase_new.map(|f| f as usize) {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"{}.__new__({}) is not safe, use {}.__new__()",
|
||||
typ.slot_name(),
|
||||
subtype.slot_name(),
|
||||
staticbase.slot_name()
|
||||
)));
|
||||
}
|
||||
|
||||
let slot_new = typ
|
||||
.deref()
|
||||
.mro_find_map(|cls| cls.slots.new.load())
|
||||
|
||||
@@ -116,13 +116,23 @@ pub trait PyClassImpl: PyClassDef {
|
||||
);
|
||||
}
|
||||
|
||||
if class.slots.new.load().is_some() {
|
||||
let bound_new = Context::genesis().slot_new_wrapper.build_bound_method(
|
||||
ctx,
|
||||
class.to_owned().into(),
|
||||
class,
|
||||
);
|
||||
class.set_attr(identifier!(ctx, __new__), bound_new.into());
|
||||
// Don't add __new__ attribute if slot_new is inherited from object
|
||||
// (Python doesn't add __new__ to __dict__ for inherited slots)
|
||||
// Exception: object itself should have __new__ in its dict
|
||||
if let Some(slot_new) = class.slots.new.load() {
|
||||
let object_new = ctx.types.object_type.slots.new.load();
|
||||
let is_object_itself = std::ptr::eq(class, ctx.types.object_type);
|
||||
let is_inherited_from_object = !is_object_itself
|
||||
&& object_new.is_some_and(|obj_new| slot_new as usize == obj_new as usize);
|
||||
|
||||
if !is_inherited_from_object {
|
||||
let bound_new = Context::genesis().slot_new_wrapper.build_bound_method(
|
||||
ctx,
|
||||
class.to_owned().into(),
|
||||
class,
|
||||
);
|
||||
class.set_attr(identifier!(ctx, __new__), bound_new.into());
|
||||
}
|
||||
}
|
||||
|
||||
if class.slots.hash.load().map_or(0, |h| h as usize) == hash_not_implemented as usize {
|
||||
|
||||
@@ -9,7 +9,6 @@ use crate::{
|
||||
},
|
||||
object::PyObjectPayload,
|
||||
sliceable::SequenceIndexOp,
|
||||
types::Unconstructible,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use std::{borrow::Cow, fmt::Debug, ops::Range};
|
||||
@@ -402,7 +401,7 @@ pub struct VecBuffer {
|
||||
data: PyMutex<Vec<u8>>,
|
||||
}
|
||||
|
||||
#[pyclass(flags(BASETYPE), with(Unconstructible))]
|
||||
#[pyclass(flags(BASETYPE, DISALLOW_INSTANTIATION))]
|
||||
impl VecBuffer {
|
||||
pub fn take(&self) -> Vec<u8> {
|
||||
std::mem::take(&mut self.data.lock())
|
||||
@@ -417,8 +416,6 @@ impl From<Vec<u8>> for VecBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
impl Unconstructible for VecBuffer {}
|
||||
|
||||
impl PyRef<VecBuffer> {
|
||||
pub fn into_pybuffer(self, readonly: bool) -> PyBuffer {
|
||||
let len = self.data.lock().len();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::builtins::PyType;
|
||||
use crate::function::PySetterValue;
|
||||
use crate::types::{GetDescriptor, Representable, Unconstructible};
|
||||
use crate::types::{GetDescriptor, Representable};
|
||||
use crate::{AsObject, Py, PyObjectRef, PyResult, VirtualMachine};
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
@@ -85,8 +85,6 @@ impl Representable for PyCField {
|
||||
}
|
||||
}
|
||||
|
||||
impl Unconstructible for PyCField {}
|
||||
|
||||
impl GetDescriptor for PyCField {
|
||||
fn descr_get(
|
||||
zelf: PyObjectRef,
|
||||
@@ -184,7 +182,7 @@ impl PyCField {
|
||||
|
||||
#[pyclass(
|
||||
flags(DISALLOW_INSTANTIATION, IMMUTABLETYPE),
|
||||
with(Unconstructible, Representable, GetDescriptor)
|
||||
with(Representable, GetDescriptor)
|
||||
)]
|
||||
impl PyCField {
|
||||
#[pyslot]
|
||||
|
||||
@@ -167,7 +167,7 @@ pub(super) mod _os {
|
||||
ospath::{OsPath, OsPathOrFd, OutputMode},
|
||||
protocol::PyIterReturn,
|
||||
recursion::ReprGuard,
|
||||
types::{IterNext, Iterable, PyStructSequence, Representable, SelfIter, Unconstructible},
|
||||
types::{IterNext, Iterable, PyStructSequence, Representable, SelfIter},
|
||||
utils::ToCString,
|
||||
vm::VirtualMachine,
|
||||
};
|
||||
@@ -570,7 +570,7 @@ pub(super) mod _os {
|
||||
ino: AtomicCell<Option<u64>>,
|
||||
}
|
||||
|
||||
#[pyclass(with(Representable, Unconstructible))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(Representable))]
|
||||
impl DirEntry {
|
||||
#[pygetset]
|
||||
fn name(&self, vm: &VirtualMachine) -> PyResult {
|
||||
@@ -760,8 +760,6 @@ pub(super) mod _os {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Unconstructible for DirEntry {}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "ScandirIter")]
|
||||
#[derive(Debug, PyPayload)]
|
||||
@@ -770,7 +768,7 @@ pub(super) mod _os {
|
||||
mode: OutputMode,
|
||||
}
|
||||
|
||||
#[pyclass(with(IterNext, Iterable, Unconstructible))]
|
||||
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
|
||||
impl ScandirIterator {
|
||||
#[pymethod]
|
||||
fn close(&self) {
|
||||
@@ -788,7 +786,6 @@ pub(super) mod _os {
|
||||
zelf.close()
|
||||
}
|
||||
}
|
||||
impl Unconstructible for ScandirIterator {}
|
||||
impl SelfIter for ScandirIterator {}
|
||||
impl IterNext for ScandirIterator {
|
||||
fn next(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
|
||||
|
||||
@@ -922,15 +922,6 @@ pub trait DefaultConstructor: PyPayload + Default + std::fmt::Debug {
|
||||
}
|
||||
}
|
||||
|
||||
/// For types that cannot be instantiated through Python code.
|
||||
#[pyclass]
|
||||
pub trait Unconstructible: PyPayload {
|
||||
#[pyslot]
|
||||
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Err(vm.new_type_error(format!("cannot create '{}' instances", cls.slot_name())))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Constructor for T
|
||||
where
|
||||
T: DefaultConstructor,
|
||||
|
||||
Reference in New Issue
Block a user