GeezerVison is showing github.com — Fix qualname · RustPython/RustPython@455d3f6
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: Lib/test/test_asyncgen.py -4Lines changed: 0 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -375,8 +375,6 @@ async def async_gen_wrapper(): | 375 | 375 |
| 376 | 376 | self.compare_generators(sync_gen_wrapper(), async_gen_wrapper()) | 377 | 377 |
| 378 | | - # TODO: RUSTPYTHON | 379 | | - @unittest.expectedFailure | 380 | 378 | def test_async_gen_api_01(self): | 381 | 379 | async def gen(): | 382 | 380 | yield 123 | @@ -517,8 +515,6 @@ async def consume(): | 517 | 515 | res = self.loop.run_until_complete(consume()) | 518 | 516 | self.assertEqual(res, [1, 2]) | 519 | 517 |
| 520 | | - # TODO: RUSTPYTHON, NameError: name 'aiter' is not defined | 521 | | - @unittest.expectedFailure | 522 | 518 | def test_async_gen_aiter_class(self): | 523 | 519 | results = [] | 524 | 520 | class Gen: | |
Collapse file Copy file name to clipboardExpand all lines: crates/vm/src/builtins/asyncgenerator.rs +12-2Lines changed: 12 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -33,9 +33,9 @@ impl PyAsyncGen { | 33 | 33 | &self.inner | 34 | 34 | } | 35 | 35 |
| 36 | | - pub fn new(frame: FrameRef, name: PyStrRef) -> Self { | | 36 | + pub fn new(frame: FrameRef, name: PyStrRef, qualname: PyStrRef) -> Self { | 37 | 37 | Self { | 38 | | - inner: Coro::new(frame, name), | | 38 | + inner: Coro::new(frame, name, qualname), | 39 | 39 | running_async: AtomicCell::new(false), | 40 | 40 | } | 41 | 41 | } | @@ -50,6 +50,16 @@ impl PyAsyncGen { | 50 | 50 | self.inner.set_name(name) | 51 | 51 | } | 52 | 52 |
| | 53 | + #[pygetset] | | 54 | + fn __qualname__(&self) -> PyStrRef { | | 55 | + self.inner.qualname() | | 56 | + } | | 57 | + | | 58 | + #[pygetset(setter)] | | 59 | + fn set___qualname__(&self, qualname: PyStrRef) { | | 60 | + self.inner.set_qualname(qualname) | | 61 | + } | | 62 | + | 53 | 63 | #[pygetset] | 54 | 64 | fn ag_await(&self, _vm: &VirtualMachine) -> Option<PyObjectRef> { | 55 | 65 | self.inner.frame().yield_from_target() | |
Collapse file Copy file name to clipboardExpand all lines: crates/vm/src/builtins/coroutine.rs +12-2Lines changed: 12 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -29,9 +29,9 @@ impl PyCoroutine { | 29 | 29 | &self.inner | 30 | 30 | } | 31 | 31 |
| 32 | | - pub fn new(frame: FrameRef, name: PyStrRef) -> Self { | | 32 | + pub fn new(frame: FrameRef, name: PyStrRef, qualname: PyStrRef) -> Self { | 33 | 33 | Self { | 34 | | - inner: Coro::new(frame, name), | | 34 | + inner: Coro::new(frame, name, qualname), | 35 | 35 | } | 36 | 36 | } | 37 | 37 |
| @@ -45,6 +45,16 @@ impl PyCoroutine { | 45 | 45 | self.inner.set_name(name) | 46 | 46 | } | 47 | 47 |
| | 48 | + #[pygetset] | | 49 | + fn __qualname__(&self) -> PyStrRef { | | 50 | + self.inner.qualname() | | 51 | + } | | 52 | + | | 53 | + #[pygetset(setter)] | | 54 | + fn set___qualname__(&self, qualname: PyStrRef) { | | 55 | + self.inner.set_qualname(qualname) | | 56 | + } | | 57 | + | 48 | 58 | #[pymethod(name = "__await__")] | 49 | 59 | const fn r#await(zelf: PyRef<Self>) -> PyCoroutineWrapper { | 50 | 60 | PyCoroutineWrapper { coro: zelf } | |
Collapse file Copy file name to clipboardExpand all lines: crates/vm/src/builtins/function.rs +9-3Lines changed: 9 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -425,9 +425,15 @@ impl Py<PyFunction> { | 425 | 425 | let is_gen = code.flags.contains(bytecode::CodeFlags::IS_GENERATOR); | 426 | 426 | let is_coro = code.flags.contains(bytecode::CodeFlags::IS_COROUTINE); | 427 | 427 | match (is_gen, is_coro) { | 428 | | - (true, false) => Ok(PyGenerator::new(frame, self.__name__()).into_pyobject(vm)), | 429 | | - (false, true) => Ok(PyCoroutine::new(frame, self.__name__()).into_pyobject(vm)), | 430 | | - (true, true) => Ok(PyAsyncGen::new(frame, self.__name__()).into_pyobject(vm)), | | 428 | + (true, false) => { | | 429 | + Ok(PyGenerator::new(frame, self.__name__(), self.__qualname__()).into_pyobject(vm)) | | 430 | + } | | 431 | + (false, true) => { | | 432 | + Ok(PyCoroutine::new(frame, self.__name__(), self.__qualname__()).into_pyobject(vm)) | | 433 | + } | | 434 | + (true, true) => { | | 435 | + Ok(PyAsyncGen::new(frame, self.__name__(), self.__qualname__()).into_pyobject(vm)) | | 436 | + } | 431 | 437 | (false, false) => vm.run_frame(frame), | 432 | 438 | } | 433 | 439 | } | |
Collapse file Copy file name to clipboardExpand all lines: crates/vm/src/builtins/generator.rs +12-2Lines changed: 12 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -32,9 +32,9 @@ impl PyGenerator { | 32 | 32 | &self.inner | 33 | 33 | } | 34 | 34 |
| 35 | | - pub fn new(frame: FrameRef, name: PyStrRef) -> Self { | | 35 | + pub fn new(frame: FrameRef, name: PyStrRef, qualname: PyStrRef) -> Self { | 36 | 36 | Self { | 37 | | - inner: Coro::new(frame, name), | | 37 | + inner: Coro::new(frame, name, qualname), | 38 | 38 | } | 39 | 39 | } | 40 | 40 |
| @@ -48,6 +48,16 @@ impl PyGenerator { | 48 | 48 | self.inner.set_name(name) | 49 | 49 | } | 50 | 50 |
| | 51 | + #[pygetset] | | 52 | + fn __qualname__(&self) -> PyStrRef { | | 53 | + self.inner.qualname() | | 54 | + } | | 55 | + | | 56 | + #[pygetset(setter)] | | 57 | + fn set___qualname__(&self, qualname: PyStrRef) { | | 58 | + self.inner.set_qualname(qualname) | | 59 | + } | | 60 | + | 51 | 61 | #[pygetset] | 52 | 62 | fn gi_frame(&self, _vm: &VirtualMachine) -> FrameRef { | 53 | 63 | self.inner.frame() | |
Collapse file Copy file name to clipboardExpand all lines: crates/vm/src/coroutine.rs +11-2Lines changed: 11 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -32,7 +32,7 @@ pub struct Coro { | 32 | 32 | // code | 33 | 33 | // _weakreflist | 34 | 34 | name: PyMutex<PyStrRef>, | 35 | | - // qualname | | 35 | + qualname: PyMutex<PyStrRef>, | 36 | 36 | exception: PyMutex<Option<PyBaseExceptionRef>>, // exc_state | 37 | 37 | } | 38 | 38 |
| @@ -48,13 +48,14 @@ fn gen_name(jen: &PyObject, vm: &VirtualMachine) -> &'static str { | 48 | 48 | } | 49 | 49 |
| 50 | 50 | impl Coro { | 51 | | - pub fn new(frame: FrameRef, name: PyStrRef) -> Self { | | 51 | + pub fn new(frame: FrameRef, name: PyStrRef, qualname: PyStrRef) -> Self { | 52 | 52 | Self { | 53 | 53 | frame, | 54 | 54 | closed: AtomicCell::new(false), | 55 | 55 | running: AtomicCell::new(false), | 56 | 56 | exception: PyMutex::default(), | 57 | 57 | name: PyMutex::new(name), | | 58 | + qualname: PyMutex::new(qualname), | 58 | 59 | } | 59 | 60 | } | 60 | 61 |
| @@ -188,6 +189,14 @@ impl Coro { | 188 | 189 | *self.name.lock() = name; | 189 | 190 | } | 190 | 191 |
| | 192 | + pub fn qualname(&self) -> PyStrRef { | | 193 | + self.qualname.lock().clone() | | 194 | + } | | 195 | + | | 196 | + pub fn set_qualname(&self, qualname: PyStrRef) { | | 197 | + *self.qualname.lock() = qualname; | | 198 | + } | | 199 | + | 191 | 200 | pub fn repr(&self, jen: &PyObject, id: usize, vm: &VirtualMachine) -> String { | 192 | 201 | format!( | 193 | 202 | "<{} object {} at {:#x}>", | |
Collapse file Copy file name to clipboardExpand all lines: crates/vm/src/protocol/object.rs +32-6Lines changed: 32 additions & 6 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 4 | 4 | use crate::{ | 5 | 5 | AsObject, Py, PyObject, PyObjectRef, PyRef, PyResult, TryFromObject, VirtualMachine, | 6 | 6 | builtins::{ | 7 | | - PyAsyncGen, PyBytes, PyDict, PyDictRef, PyGenericAlias, PyInt, PyList, PyStr, PyTuple, | 8 | | - PyTupleRef, PyType, PyTypeRef, PyUtf8Str, pystr::AsPyStr, | | 7 | + PyBytes, PyDict, PyDictRef, PyGenericAlias, PyInt, PyList, PyStr, PyTuple, PyTupleRef, | | 8 | + PyType, PyTypeRef, PyUtf8Str, pystr::AsPyStr, | 9 | 9 | }, | 10 | 10 | common::{hash::PyHash, str::to_ascii}, | 11 | 11 | convert::{ToPyObject, ToPyResult}, | @@ -87,11 +87,37 @@ impl PyObject { | 87 | 87 |
| 88 | 88 | // PyObject *PyObject_GetAIter(PyObject *o) | 89 | 89 | pub fn get_aiter(&self, vm: &VirtualMachine) -> PyResult { | 90 | | - if self.downcastable::<PyAsyncGen>() { | 91 | | - vm.call_special_method(self, identifier!(vm, __aiter__), ()) | 92 | | - } else { | 93 | | - Err(vm.new_type_error("wrong argument type")) | | 90 | + use crate::builtins::PyCoroutine; | | 91 | + | | 92 | + // Check if object has __aiter__ method | | 93 | + let aiter_method = self.class().get_attr(identifier!(vm, __aiter__)); | | 94 | + let Some(_aiter_method) = aiter_method else { | | 95 | + return Err(vm.new_type_error(format!( | | 96 | + "'{}' object is not an async iterable", | | 97 | + self.class().name() | | 98 | + ))); | | 99 | + }; | | 100 | + | | 101 | + // Call __aiter__ | | 102 | + let iterator = vm.call_special_method(self, identifier!(vm, __aiter__), ())?; | | 103 | + | | 104 | + // Check that __aiter__ did not return a coroutine | | 105 | + if iterator.downcast_ref::<PyCoroutine>().is_some() { | | 106 | + return Err(vm.new_type_error( | | 107 | + "'async_iterator' object cannot be interpreted as an async iterable; \ | | 108 | + perhaps you forgot to call aiter()?", | | 109 | + )); | | 110 | + } | | 111 | + | | 112 | + // Check that the result is an async iterator (has __anext__) | | 113 | + if !iterator.class().has_attr(identifier!(vm, __anext__)) { | | 114 | + return Err(vm.new_type_error(format!( | | 115 | + "'{}' object is not an async iterator", | | 116 | + iterator.class().name() | | 117 | + ))); | 94 | 118 | } | | 119 | + | | 120 | + Ok(iterator) | 95 | 121 | } | 96 | 122 |
| 97 | 123 | pub fn has_attr<'a>(&self, attr_name: impl AsPyStr<'a>, vm: &VirtualMachine) -> PyResult<bool> { | |
|