mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-29 03:04:38 +08:00
Do some more refactoring, but better
This commit is contained in:
4 files changed
+94
-52
No files matched your search
@@ -1,6 +1,7 @@
|
||||
use super::objcode::PyCodeRef;
|
||||
use super::objcoroinner::{Coro, Variant};
|
||||
use super::objtype::{self, PyClassRef};
|
||||
use crate::exceptions::PyBaseExceptionRef;
|
||||
use crate::frame::FrameRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
@@ -36,6 +37,12 @@ impl PyAsyncGen {
|
||||
.into_ref(vm)
|
||||
}
|
||||
|
||||
// TODO: fix function names situation
|
||||
#[pyproperty(magic)]
|
||||
fn name(&self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.get_none()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__aiter__")]
|
||||
fn aiter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
zelf
|
||||
@@ -297,7 +304,7 @@ impl PyAsyncGenAThrow {
|
||||
}
|
||||
if !vm.is_none(&val) {
|
||||
return Err(vm.new_runtime_error(
|
||||
"can't send non-None value to a just-started coroutine".to_owned(),
|
||||
"can't send non-None value to a just-started async generator".to_owned(),
|
||||
));
|
||||
}
|
||||
self.state.set(AwaitableState::Iter);
|
||||
@@ -306,18 +313,26 @@ impl PyAsyncGenAThrow {
|
||||
let (ty, val, tb) = self.value.clone();
|
||||
let ret = self.ag.inner.throw(ty, val, tb, vm);
|
||||
let ret = if self.aclose {
|
||||
self.check_no_ignore(&ret, vm)?;
|
||||
ret
|
||||
if self.ignored_close(&ret) {
|
||||
Err(self.yield_close(vm))
|
||||
} else {
|
||||
ret
|
||||
}
|
||||
} else {
|
||||
PyAsyncGenWrappedValue::unbox(&self.ag, ret, vm)
|
||||
};
|
||||
self.check_error(ret, vm)
|
||||
ret.map_err(|e| self.check_error(e, vm))
|
||||
}
|
||||
AwaitableState::Iter => {
|
||||
let ret = self.ag.inner.send(val, vm);
|
||||
if self.aclose {
|
||||
self.check_no_ignore(&ret, vm)?;
|
||||
self.check_error(ret, vm)
|
||||
match ret {
|
||||
Ok(v) if v.payload_is::<PyAsyncGenWrappedValue>() => {
|
||||
Err(self.yield_close(vm))
|
||||
}
|
||||
Ok(v) => Ok(v),
|
||||
Err(e) => Err(self.check_error(e, vm)),
|
||||
}
|
||||
} else {
|
||||
PyAsyncGenWrappedValue::unbox(&self.ag, ret, vm)
|
||||
}
|
||||
@@ -339,12 +354,16 @@ impl PyAsyncGenAThrow {
|
||||
exc_tb.unwrap_or_else(|| vm.get_none()),
|
||||
vm,
|
||||
);
|
||||
if self.aclose {
|
||||
self.check_no_ignore(&ret, vm)?;
|
||||
self.check_error(ret, vm)
|
||||
let res = if self.aclose {
|
||||
if self.ignored_close(&ret) {
|
||||
Err(self.yield_close(vm))
|
||||
} else {
|
||||
ret
|
||||
}
|
||||
} else {
|
||||
PyAsyncGenWrappedValue::unbox(&self.ag, ret, vm)
|
||||
}
|
||||
};
|
||||
res.map_err(|e| self.check_error(e, vm))
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -352,27 +371,26 @@ impl PyAsyncGenAThrow {
|
||||
self.state.set(AwaitableState::Closed);
|
||||
}
|
||||
|
||||
fn check_no_ignore(&self, res: &PyResult, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if let Ok(ref v) = res {
|
||||
if v.payload_is::<PyAsyncGenWrappedValue>() {
|
||||
return Err(
|
||||
vm.new_runtime_error("async generator ignored GeneratorExit".to_owned())
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
fn ignored_close(&self, res: &PyResult) -> bool {
|
||||
res.as_ref()
|
||||
.map_or(false, |v| v.payload_is::<PyAsyncGenWrappedValue>())
|
||||
}
|
||||
fn check_error(&self, res: PyResult, vm: &VirtualMachine) -> PyResult {
|
||||
if self.aclose {
|
||||
if let Err(ref e) = res {
|
||||
if objtype::isinstance(&e, &vm.ctx.exceptions.stop_async_iteration)
|
||||
|| objtype::isinstance(&e, &vm.ctx.exceptions.generator_exit)
|
||||
{
|
||||
return Err(vm.new_exception_empty(vm.ctx.exceptions.stop_iteration.clone()));
|
||||
}
|
||||
}
|
||||
fn yield_close(&self, vm: &VirtualMachine) -> PyBaseExceptionRef {
|
||||
self.ag.running_async.set(false);
|
||||
self.state.set(AwaitableState::Closed);
|
||||
vm.new_runtime_error("async generator ignored GeneratorExit".to_owned())
|
||||
}
|
||||
fn check_error(&self, exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyBaseExceptionRef {
|
||||
self.ag.running_async.set(false);
|
||||
self.state.set(AwaitableState::Closed);
|
||||
if self.aclose
|
||||
&& (objtype::isinstance(&exc, &vm.ctx.exceptions.stop_async_iteration)
|
||||
|| objtype::isinstance(&exc, &vm.ctx.exceptions.generator_exit))
|
||||
{
|
||||
vm.new_exception_empty(vm.ctx.exceptions.stop_iteration.clone())
|
||||
} else {
|
||||
exc
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+35
-23
@@ -1,4 +1,4 @@
|
||||
use super::{objiter, objtype};
|
||||
use super::objtype;
|
||||
use crate::exceptions::{self, PyBaseExceptionRef};
|
||||
use crate::frame::{ExecutionResult, FrameRef};
|
||||
use crate::pyobject::{PyObjectRef, PyResult};
|
||||
@@ -71,38 +71,47 @@ impl Coro {
|
||||
);
|
||||
self.running.set(false);
|
||||
self.started.set(true);
|
||||
if let Err(ref e) = result {
|
||||
if objtype::isinstance(e, &vm.ctx.exceptions.stop_iteration) {
|
||||
let err =
|
||||
vm.new_runtime_error(format!("{} raised StopIteration", self.variant.name()));
|
||||
err.set_cause(Some(e.clone()));
|
||||
return Err(err);
|
||||
}
|
||||
if self.variant == Variant::AsyncGen
|
||||
&& objtype::isinstance(e, &vm.ctx.exceptions.stop_async_iteration)
|
||||
{
|
||||
let err =
|
||||
vm.new_runtime_error("async generator raise StopAsyncIteration".to_owned());
|
||||
err.set_cause(Some(e.clone()));
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn send(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if self.closed.get() {
|
||||
return Err(objiter::new_stop_iteration(vm));
|
||||
let cls = if let Variant::AsyncGen = self.variant {
|
||||
vm.ctx.exceptions.stop_async_iteration.clone()
|
||||
} else {
|
||||
vm.ctx.exceptions.stop_iteration.clone()
|
||||
};
|
||||
return Err(vm.new_exception_empty(cls));
|
||||
}
|
||||
if !self.started.get() && !vm.is_none(&value) {
|
||||
return Err(vm.new_type_error(
|
||||
"can't send non-None value to a just-started coroutine".to_string(),
|
||||
));
|
||||
return Err(vm.new_type_error(format!(
|
||||
"can't send non-None value to a just-started {}",
|
||||
self.variant.name()
|
||||
)));
|
||||
}
|
||||
self.frame.push_value(value.clone());
|
||||
let result = self.run_with_context(|| vm.run_frame(self.frame.clone()), vm);
|
||||
self.maybe_close(&result);
|
||||
self.variant.exec_result(result?, vm)
|
||||
match result {
|
||||
Ok(exec_res) => self.variant.exec_result(exec_res, vm),
|
||||
Err(e) => {
|
||||
if objtype::isinstance(&e, &vm.ctx.exceptions.stop_iteration) {
|
||||
let err = vm
|
||||
.new_runtime_error(format!("{} raised StopIteration", self.variant.name()));
|
||||
err.set_cause(Some(e));
|
||||
Err(err)
|
||||
} else if self.variant == Variant::AsyncGen
|
||||
&& objtype::isinstance(&e, &vm.ctx.exceptions.stop_async_iteration)
|
||||
{
|
||||
let err = vm
|
||||
.new_runtime_error("async generator raised StopAsyncIteration".to_owned());
|
||||
err.set_cause(Some(e));
|
||||
Err(err)
|
||||
} else {
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn throw(
|
||||
&self,
|
||||
@@ -142,7 +151,7 @@ impl Coro {
|
||||
self.closed.set(true);
|
||||
match result {
|
||||
Ok(ExecutionResult::Yield(_)) => {
|
||||
Err(vm.new_runtime_error("generator ignored GeneratorExit".to_owned()))
|
||||
Err(vm.new_runtime_error(format!("{} ignored GeneratorExit", self.variant.name())))
|
||||
}
|
||||
Err(e) if !is_gen_exit(&e, vm) => Err(e),
|
||||
_ => Ok(()),
|
||||
@@ -161,6 +170,9 @@ impl Coro {
|
||||
pub fn frame(&self) -> FrameRef {
|
||||
self.frame.clone()
|
||||
}
|
||||
pub fn name(&self) -> String {
|
||||
self.frame.code.obj_name.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_gen_exit(exc: &PyBaseExceptionRef, vm: &VirtualMachine) -> bool {
|
||||
|
||||
@@ -34,6 +34,12 @@ impl PyCoroutine {
|
||||
.into_ref(vm)
|
||||
}
|
||||
|
||||
// TODO: fix function names situation
|
||||
#[pyproperty(magic)]
|
||||
fn name(&self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.get_none()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn send(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
self.inner.send(value, vm)
|
||||
|
||||
@@ -37,6 +37,12 @@ impl PyGenerator {
|
||||
.into_ref(vm)
|
||||
}
|
||||
|
||||
// TODO: fix function names situation
|
||||
#[pyproperty(magic)]
|
||||
fn name(&self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.get_none()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyGeneratorRef) -> PyGeneratorRef {
|
||||
zelf
|
||||
|
||||
Reference in new issue
Block a user