Merge pull request #3291 from DimitrisJim/unconstructible

Add Unconstructible trait
This commit is contained in:
Jeong YunWon
2021-10-14 13:28:23 +09:00
committed by GitHub
10 changed files with 67 additions and 26 deletions

View File

@@ -0,0 +1,18 @@
from typing import Type
from testutils import assert_raises
def check_forbidden_instantiation(typ, reverse=False):
f = reversed if reverse else iter
with assert_raises(TypeError):
type(f(typ()))()
dict_values, dict_items = lambda: {}.values(), lambda: {}.items()
# types with custom forward iterators
iter_types = [list, set, str, bytearray, bytes, dict, tuple, lambda: range(0), dict_items, dict_values]
# types with custom backwards iterators
reviter_types = [list, dict, lambda: range(0), dict_values, dict_items]
for typ in iter_types:
check_forbidden_instantiation(typ)
for typ in reviter_types:
check_forbidden_instantiation(typ, reverse=True)

View File

@@ -24,7 +24,7 @@ use crate::{
sliceable::{PySliceableSequence, PySliceableSequenceMut, SequenceIndex},
slots::{
AsBuffer, AsMapping, Callable, Comparable, Hashable, Iterable, IteratorIterable,
PyComparisonOp, SlotIterator, Unhashable,
PyComparisonOp, SlotConstructor, SlotIterator, Unconstructible, Unhashable,
},
utils::Either,
IdProtocol, PyClassDef, PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef,
@@ -816,7 +816,7 @@ impl PyValue for PyByteArrayIterator {
}
}
#[pyimpl(with(SlotIterator))]
#[pyimpl(with(SlotConstructor, SlotIterator))]
impl PyByteArrayIterator {
#[pymethod(magic)]
fn length_hint(&self) -> usize {
@@ -836,6 +836,8 @@ impl PyByteArrayIterator {
.set_state(state, |obj, pos| pos.min(obj.len()), vm)
}
}
impl Unconstructible for PyByteArrayIterator {}
impl IteratorIterable for PyByteArrayIterator {}
impl SlotIterator for PyByteArrayIterator {
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {

View File

@@ -12,7 +12,7 @@ use crate::{
protocol::{BufferInternal, BufferOptions, PyBuffer, PyIterReturn, PyMappingMethods},
slots::{
AsBuffer, AsMapping, Callable, Comparable, Hashable, Iterable, IteratorIterable,
PyComparisonOp, SlotConstructor, SlotIterator,
PyComparisonOp, SlotConstructor, SlotIterator, Unconstructible,
},
utils::Either,
IdProtocol, PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue,
@@ -649,7 +649,7 @@ impl PyValue for PyBytesIterator {
}
}
#[pyimpl(with(SlotIterator))]
#[pyimpl(with(SlotConstructor, SlotIterator))]
impl PyBytesIterator {
#[pymethod(magic)]
fn length_hint(&self) -> usize {
@@ -670,6 +670,8 @@ impl PyBytesIterator {
.set_state(state, |obj, pos| pos.min(obj.len()), vm)
}
}
impl Unconstructible for PyBytesIterator {}
impl IteratorIterable for PyBytesIterator {}
impl SlotIterator for PyBytesIterator {
fn next(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {

View File

@@ -9,8 +9,8 @@ use crate::{
function::{ArgIterable, FuncArgs, IntoPyObject, KwArgs, OptionalArg},
protocol::{PyIterIter, PyIterReturn, PyMappingMethods},
slots::{
AsMapping, Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp, SlotIterator,
Unhashable,
AsMapping, Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp,
SlotConstructor, SlotIterator, Unconstructible, Unhashable,
},
vm::{ReprGuard, VirtualMachine},
IdProtocol, ItemProtocol,
@@ -762,7 +762,7 @@ macro_rules! dict_view {
}
}
#[pyimpl(with(SlotIterator))]
#[pyimpl(with(SlotConstructor, SlotIterator))]
impl $iter_name {
fn new(dict: PyDictRef) -> Self {
$iter_name {
@@ -776,6 +776,7 @@ macro_rules! dict_view {
self.internal.lock().length_hint(|_| self.size.entries_size)
}
}
impl Unconstructible for $iter_name {}
impl IteratorIterable for $iter_name {}
impl SlotIterator for $iter_name {
@@ -818,7 +819,7 @@ macro_rules! dict_view {
}
}
#[pyimpl(with(SlotIterator))]
#[pyimpl(with(SlotConstructor, SlotIterator))]
impl $reverse_iter_name {
fn new(dict: PyDictRef) -> Self {
let size = dict.size();
@@ -836,6 +837,7 @@ macro_rules! dict_view {
.rev_length_hint(|_| self.size.entries_size)
}
}
impl Unconstructible for $reverse_iter_name {}
impl IteratorIterable for $reverse_iter_name {}
impl SlotIterator for $reverse_iter_name {

View File

@@ -8,8 +8,8 @@ use crate::{
sequence::{self, SimpleSeq},
sliceable::{PySliceableSequence, PySliceableSequenceMut, SequenceIndex},
slots::{
AsMapping, Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp, SlotIterator,
Unhashable,
AsMapping, Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp,
SlotConstructor, SlotIterator, Unconstructible, Unhashable,
},
stdlib::sys,
utils::Either,
@@ -517,7 +517,7 @@ impl PyValue for PyListIterator {
}
}
#[pyimpl(with(SlotIterator))]
#[pyimpl(with(SlotConstructor, SlotIterator))]
impl PyListIterator {
#[pymethod(magic)]
fn length_hint(&self) -> usize {
@@ -538,6 +538,7 @@ impl PyListIterator {
.builtins_iter_reduce(|x| x.clone().into(), vm)
}
}
impl Unconstructible for PyListIterator {}
impl IteratorIterable for PyListIterator {}
impl SlotIterator for PyListIterator {
@@ -564,7 +565,7 @@ impl PyValue for PyListReverseIterator {
}
}
#[pyimpl(with(SlotIterator))]
#[pyimpl(with(SlotConstructor, SlotIterator))]
impl PyListReverseIterator {
#[pymethod(magic)]
fn length_hint(&self) -> usize {
@@ -585,6 +586,7 @@ impl PyListReverseIterator {
.builtins_reversed_reduce(|x| x.clone().into(), vm)
}
}
impl Unconstructible for PyListReverseIterator {}
impl IteratorIterable for PyListReverseIterator {}
impl SlotIterator for PyListReverseIterator {

View File

@@ -11,7 +11,7 @@ use crate::{
sliceable::PySliceableSequence,
slots::{
Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp, SlotConstructor,
SlotIterator,
SlotIterator, Unconstructible,
},
stdlib::sys,
utils::Either,
@@ -220,7 +220,7 @@ impl PyValue for PyStrIterator {
}
}
#[pyimpl(with(SlotIterator))]
#[pyimpl(with(SlotConstructor, SlotIterator))]
impl PyStrIterator {
#[pymethod(magic)]
fn length_hint(&self) -> usize {
@@ -244,6 +244,7 @@ impl PyStrIterator {
.builtins_iter_reduce(|x| x.clone().into(), vm)
}
}
impl Unconstructible for PyStrIterator {}
impl IteratorIterable for PyStrIterator {}
impl SlotIterator for PyStrIterator {

View File

@@ -5,7 +5,8 @@ use crate::{
function::{FuncArgs, OptionalArg},
protocol::{PyIterReturn, PyMappingMethods},
slots::{
AsMapping, Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp, SlotIterator,
AsMapping, Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp,
SlotConstructor, SlotIterator, Unconstructible,
},
IdProtocol, IntoPyRef, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue,
TryFromObject, TypeProtocol, VirtualMachine,
@@ -511,7 +512,7 @@ impl PyValue for PyLongRangeIterator {
}
}
#[pyimpl(with(SlotIterator))]
#[pyimpl(with(SlotConstructor, SlotIterator))]
impl PyLongRangeIterator {
#[pyslot]
fn slot_new(_cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
@@ -545,6 +546,7 @@ impl PyLongRangeIterator {
)
}
}
impl Unconstructible for PyLongRangeIterator {}
impl IteratorIterable for PyLongRangeIterator {}
impl SlotIterator for PyLongRangeIterator {
@@ -580,13 +582,8 @@ impl PyValue for PyRangeIterator {
}
}
#[pyimpl(with(SlotIterator))]
#[pyimpl(with(SlotConstructor, SlotIterator))]
impl PyRangeIterator {
#[pyslot]
fn slot_new(_cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
Err(vm.new_type_error("cannot create 'range_iterator' instances".to_owned()))
}
#[pymethod(magic)]
fn length_hint(&self) -> usize {
let index = self.index.load();
@@ -615,6 +612,7 @@ impl PyRangeIterator {
)
}
}
impl Unconstructible for PyRangeIterator {}
impl IteratorIterable for PyRangeIterator {}
impl SlotIterator for PyRangeIterator {

View File

@@ -9,7 +9,7 @@ use crate::{
protocol::PyIterReturn,
slots::{
Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp, SlotConstructor,
SlotIterator, Unhashable,
SlotIterator, Unconstructible, Unhashable,
},
vm::{ReprGuard, VirtualMachine},
IdProtocol, PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue,
@@ -884,7 +884,7 @@ impl PyValue for PySetIterator {
}
}
#[pyimpl(with(SlotIterator))]
#[pyimpl(with(SlotConstructor, SlotIterator))]
impl PySetIterator {
#[pymethod(magic)]
fn length_hint(&self) -> usize {
@@ -907,6 +907,7 @@ impl PySetIterator {
))
}
}
impl Unconstructible for PySetIterator {}
impl IteratorIterable for PySetIterator {}
impl SlotIterator for PySetIterator {

View File

@@ -7,7 +7,7 @@ use crate::{
sliceable::PySliceableSequence,
slots::{
AsMapping, Comparable, Hashable, Iterable, IteratorIterable, PyComparisonOp,
SlotConstructor, SlotIterator,
SlotConstructor, SlotIterator, Unconstructible,
},
stdlib::sys,
utils::Either,
@@ -379,7 +379,7 @@ impl PyValue for PyTupleIterator {
}
}
#[pyimpl(with(SlotIterator))]
#[pyimpl(with(SlotConstructor, SlotIterator))]
impl PyTupleIterator {
#[pymethod(magic)]
fn length_hint(&self) -> usize {
@@ -400,6 +400,7 @@ impl PyTupleIterator {
.builtins_iter_reduce(|x| x.clone().into(), vm)
}
}
impl Unconstructible for PyTupleIterator {}
impl IteratorIterable for PyTupleIterator {}
impl SlotIterator for PyTupleIterator {

View File

@@ -157,6 +157,20 @@ pub trait SlotConstructor: PyValue {
fn py_new(cls: PyTypeRef, args: Self::Args, vm: &VirtualMachine) -> PyResult;
}
/// For types that cannot be instantiated through Python code.
pub trait Unconstructible: PyValue {}
impl<T> SlotConstructor for T
where
T: Unconstructible,
{
type Args = FuncArgs;
fn py_new(cls: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult {
Err(vm.new_type_error(format!("cannot create {} instances", cls.slot_name())))
}
}
#[pyimpl]
pub trait SlotDestructor: PyValue {
#[inline] // for __del__