GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Align builtin iterator controls and callback lifetimes (#9699) · RustPython/RustPython@1f6c4dc

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • crates/vm/src
    • builtins
      • bytearray.rs
      • bytes.rs
      • enumerate.rs
      • filter.rs
      • iter.rs
      • map.rs
      • weakproxy.rs
      • zip.rs
    • stdlib
      • builtins.rs
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎crates/vm/src/builtins/bytearray.rs‎

Copy file name to clipboardExpand all lines: crates/vm/src/builtins/bytearray.rs
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1504,7 +1504,7 @@ impl AsSequence for PyByteArray {
15041504
PyByteArray::sequence_downcast(seq)
15051505
.borrow_buf()
15061506
.getitem_by_index(vm, i)
1507-
.map(|x| vm.ctx.new_bytes(vec![x]).into())
1507+
.map(|x| vm.ctx.new_int(x).into())
15081508
}),
15091509
ass_item: atomic_func!(|seq, i, value, vm| {
15101510
let zelf = PyByteArray::sequence_downcast(seq);
Collapse file

‎crates/vm/src/builtins/bytes.rs‎

Copy file name to clipboardExpand all lines: crates/vm/src/builtins/bytes.rs
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ impl AsSequence for PyBytes {
698698
PyBytes::sequence_downcast(seq)
699699
.as_bytes()
700700
.getitem_by_index(vm, i)
701-
.map(|x| vm.ctx.new_bytes(vec![x]).into())
701+
.map(|x| vm.ctx.new_int(x).into())
702702
}),
703703
contains: atomic_func!(|seq, other, vm| {
704704
PyBytes::sequence_downcast(seq).__contains__(other.to_owned(), vm)
Collapse file

‎crates/vm/src/builtins/enumerate.rs‎

Copy file name to clipboardExpand all lines: crates/vm/src/builtins/enumerate.rs
+99-28Lines changed: 99 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
use super::{
2-
IterStatus, PositionIterInternal, PyGenericAlias, PyTupleRef, PyType, PyTypeRef,
3-
iter::builtins_reversed, locked_rev_next,
2+
PyGenericAlias, PyTupleRef, PyType, PyTypeRef,
3+
iter::{SequenceIter, SequenceIterDirection},
44
};
5-
use crate::common::lock::{PyMutex, PyRwLock};
5+
use crate::common::lock::PyRwLock;
66
use crate::{
77
AsObject, Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
88
class::PyClassImpl,
9-
function::ArgIndex,
9+
function::{ArgIndex, FuncArgs},
1010
protocol::{PyIter, PyIterReturn},
1111
raise_if_stop,
12-
types::{Constructor, IterNext, Iterable, SelfIter},
12+
types::{Constructor, IterNext, Iterable, SelfIter, drop_kwargs_if_init_overridden},
1313
};
1414
use malachite_bigint::BigInt;
1515
use num_traits::ToPrimitive;
@@ -139,7 +139,7 @@ impl IterNext for PyEnumerate {
139139
#[pyclass(module = false, name = "reversed", traverse)]
140140
#[derive(Debug)]
141141
pub(crate) struct PyReverseSequenceIterator {
142-
internal: PyMutex<PositionIterInternal<PyObjectRef>>,
142+
internal: SequenceIter,
143143
}
144144

145145
impl PyPayload for PyReverseSequenceIterator {
@@ -150,50 +150,121 @@ impl PyPayload for PyReverseSequenceIterator {
150150
}
151151

152152
impl PyReverseSequenceIterator {
153+
pub(crate) fn from_object(
154+
cls: PyTypeRef,
155+
sequence: &PyObjectRef,
156+
vm: &VirtualMachine,
157+
) -> PyResult {
158+
// Keep the original sequence alive while binding, calling, and releasing
159+
// the special method, including when it does not retain its receiver.
160+
if let Some(method) = vm.get_method(sequence.clone(), identifier!(vm, __reversed__)) {
161+
let method = method?;
162+
if vm.is_none(&method) {
163+
return Err(Self::not_reversible(sequence, vm));
164+
}
165+
let result = method.call((), vm);
166+
drop(method);
167+
return result;
168+
}
169+
170+
Self::py_new(
171+
&cls,
172+
ReversedArgs {
173+
object: sequence.clone(),
174+
},
175+
vm,
176+
)?
177+
.into_ref_with_type(vm, cls)
178+
.map(Into::into)
179+
}
180+
181+
fn not_reversible(
182+
sequence: &PyObjectRef,
183+
vm: &VirtualMachine,
184+
) -> crate::builtins::PyBaseExceptionRef {
185+
vm.new_type_error(format!(
186+
"'{}' object is not reversible",
187+
sequence.class().slot_name()
188+
))
189+
}
190+
153191
pub(crate) const fn new(obj: PyObjectRef, len: usize) -> Self {
154-
let position = len.saturating_sub(1);
192+
let position = len as isize - 1;
155193
Self {
156-
internal: PyMutex::new(PositionIterInternal::new(obj, position)),
194+
internal: SequenceIter::new(obj, position, SequenceIterDirection::Reverse),
157195
}
158196
}
159197
}
160198

161-
#[pyclass(with(IterNext, Iterable))]
199+
#[derive(FromArgs)]
200+
pub(crate) struct ReversedArgs {
201+
#[pyarg(positional)]
202+
object: PyObjectRef,
203+
}
204+
205+
impl Constructor for PyReverseSequenceIterator {
206+
type Args = ReversedArgs;
207+
208+
fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
209+
// A subtype's custom initializer may consume keywords, but the exact
210+
// type and subtypes inheriting its initializer reject them first.
211+
// Retain the original arguments through callbacks even if keywords
212+
// are removed from the constructor's view of the call.
213+
let constructor_args =
214+
drop_kwargs_if_init_overridden(&cls, vm.ctx.types.reverse_iter_type, args.clone());
215+
if !constructor_args.kwargs.is_empty() {
216+
return Err(vm.new_type_error("reversed() takes no keyword arguments"));
217+
}
218+
let ReversedArgs { object } = constructor_args.bind_for(vm, "reversed")?;
219+
let result = Self::from_object(cls, &object, vm);
220+
drop(object);
221+
drop(args);
222+
result
223+
}
224+
225+
fn py_new(
226+
_cls: &Py<PyType>,
227+
Self::Args { object }: Self::Args,
228+
vm: &VirtualMachine,
229+
) -> PyResult<Self> {
230+
// The slot handles arbitrary __reversed__ results before constructing
231+
// a payload. Checking sequence support must not bind __getitem__.
232+
let protocol = object.sequence_unchecked();
233+
if !protocol.check() {
234+
return Err(Self::not_reversible(&object, vm));
235+
}
236+
let len = protocol.length(vm)?;
237+
Ok(Self::new(object, len))
238+
}
239+
}
240+
241+
#[pyclass(with(IterNext, Iterable, Constructor), flags(BASETYPE))]
162242
impl Py<PyReverseSequenceIterator> {
163243
#[pymethod]
164244
fn __length_hint__(&self, vm: &VirtualMachine) -> PyResult<usize> {
165-
let internal = self.internal.lock();
166-
if let IterStatus::Active(obj) = &internal.status
167-
&& internal.position <= obj.length(vm)?
168-
{
169-
return Ok(internal.position + 1);
170-
}
171-
Ok(0)
245+
vm.with_recursion(" in __length_hint__", || {
246+
self.internal
247+
.length_hint(vm)
248+
.map(|length| length.unwrap_or(0))
249+
})
172250
}
173251

174252
#[pymethod]
175253
fn __setstate__(&self, state: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
176-
self.internal.lock().set_state(&state, |_, pos| pos, vm)
254+
self.internal.set_state(&state, vm)
177255
}
178256

179257
#[pymethod]
180-
fn __reduce__(&self, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
181-
let func = builtins_reversed(vm)?;
182-
Ok(self.internal.lock().reduce(
183-
func,
184-
|x| x.clone(),
185-
|vm| vm.ctx.empty_tuple.clone().into(),
186-
vm,
187-
))
258+
fn __reduce__(&self, vm: &VirtualMachine) -> PyTupleRef {
259+
let func = self.class().to_owned().into();
260+
self.internal.reduce(func, vm)
188261
}
189262
}
190263

191264
impl SelfIter for PyReverseSequenceIterator {}
192265
impl IterNext for PyReverseSequenceIterator {
193266
fn next(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
194-
locked_rev_next(&zelf.internal, |obj, pos| {
195-
PyIterReturn::from_getitem_result(obj.get_item(&pos, vm), vm)
196-
})
267+
zelf.internal.next(vm)
197268
}
198269
}
199270

Collapse file

‎crates/vm/src/builtins/filter.rs‎

Copy file name to clipboardExpand all lines: crates/vm/src/builtins/filter.rs
+18-17Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::{PyType, PyTypeRef};
22
use crate::{
3-
Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
3+
AsObject, Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
44
class::PyClassImpl,
55
protocol::{PyIter, PyIterReturn},
66
raise_if_stop,
@@ -26,7 +26,7 @@ pub struct FilterArgs {
2626
#[pyarg(positional)]
2727
function: PyObjectRef,
2828
#[pyarg(positional)]
29-
iterable: PyIter,
29+
iterable: PyObjectRef,
3030
}
3131

3232
impl Constructor for PyFilter {
@@ -35,25 +35,25 @@ impl Constructor for PyFilter {
3535

3636
fn py_new(
3737
_cls: &Py<PyType>,
38-
Self::Args {
39-
function,
40-
iterable: iterator,
41-
}: Self::Args,
42-
_vm: &VirtualMachine,
38+
Self::Args { function, iterable }: Self::Args,
39+
vm: &VirtualMachine,
4340
) -> PyResult<Self> {
44-
Ok(Self {
45-
predicate: function,
41+
let result = iterable.get_iter(vm).map(|iterator| Self {
42+
predicate: function.clone(),
4643
iterator,
47-
})
44+
});
45+
drop(iterable);
46+
drop(function);
47+
result
4848
}
4949
}
5050

5151
#[pyclass(with(IterNext, Iterable, Constructor), flags(BASETYPE))]
5252
impl Py<PyFilter> {
5353
#[pymethod]
54-
fn __reduce__(&self, vm: &VirtualMachine) -> (PyTypeRef, (PyObjectRef, PyIter)) {
54+
fn __reduce__(&self) -> (PyTypeRef, (PyObjectRef, PyIter)) {
5555
(
56-
vm.ctx.types.filter_type.to_owned(),
56+
self.class().to_owned(),
5757
(self.predicate.clone(), self.iterator.clone()),
5858
)
5959
}
@@ -66,17 +66,18 @@ impl IterNext for PyFilter {
6666
let predicate = &zelf.predicate;
6767
loop {
6868
let next_obj = raise_if_stop!(zelf.iterator.next(vm)?);
69-
let predicate_value = if vm.is_none(predicate) {
70-
next_obj.clone()
69+
let is_true = if vm.is_none(predicate) || predicate.is(vm.ctx.types.bool_type) {
70+
next_obj.try_to_bool(vm)?
7171
} else {
7272
// the predicate itself can raise StopIteration which does stop the filter iteration
73-
raise_if_stop!(PyIterReturn::from_pyresult(
73+
let predicate_value = raise_if_stop!(PyIterReturn::from_pyresult(
7474
predicate.call((next_obj.clone(),), vm),
7575
vm
76-
)?)
76+
)?);
77+
predicate_value.try_to_bool(vm)?
7778
};
7879

79-
if predicate_value.try_to_bool(vm)? {
80+
if is_true {
8081
return Ok(PyIterReturn::Return(next_obj));
8182
}
8283
}

0 commit comments

Comments
0 (0)
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.