Skip to content

Update traceback.tb_next to be writable. #4087

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Lib/unittest/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,8 @@ def _remove_unittest_tb_frames(self, tb):
while tb and not self._is_relevant_tb_level(tb):
prev = tb
tb = tb.tb_next
# TODO: RUSTPYTHON; traceback.tb_next is not writable yet #3857
# if prev is not None:
# prev.tb_next = None
if prev is not None:
prev.tb_next = None

def __repr__(self):
return ("<%s run=%i errors=%i failures=%i>" %
Expand Down
4 changes: 0 additions & 4 deletions Lib/unittest/test/test_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,6 @@ def test_1(self):
self.assertIs(test_case, test)
self.assertIsInstance(formatted_exc, str)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_addFailure_filter_traceback_frames(self):
class Foo(unittest.TestCase):
def test_1(self):
Expand All @@ -248,8 +246,6 @@ def get_exc_info():
self.assertEqual(len(dropped), 1)
self.assertIn("raise self.failureException(msg)", dropped[0])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_addFailure_filter_traceback_frames_context(self):
class Foo(unittest.TestCase):
def test_1(self):
Expand Down
15 changes: 11 additions & 4 deletions vm/src/builtins/traceback.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use rustpython_common::lock::PyMutex;

use super::PyType;
use crate::{class::PyClassImpl, frame::FrameRef, Context, Py, PyPayload, PyRef, VirtualMachine};

#[pyclass(module = false, name = "traceback")]
#[derive(Debug)]
pub struct PyTraceback {
pub next: Option<PyTracebackRef>, // TODO: Make mutable
pub next: PyMutex<Option<PyTracebackRef>>,
pub frame: FrameRef,
pub lasti: u32,
pub lineno: usize,
Expand All @@ -22,7 +24,7 @@ impl PyPayload for PyTraceback {
impl PyTraceback {
pub fn new(next: Option<PyRef<Self>>, frame: FrameRef, lasti: u32, lineno: usize) -> Self {
PyTraceback {
next,
next: PyMutex::new(next),
frame,
lasti,
lineno,
Expand All @@ -46,13 +48,18 @@ impl PyTraceback {

#[pyproperty]
fn tb_next(&self) -> Option<PyRef<Self>> {
self.next.as_ref().cloned()
self.next.lock().as_ref().cloned()
}

#[pyproperty(setter)]
fn set_tb_next(&self, value: Option<PyRef<Self>>) {
*self.next.lock() = value;
}
}

impl PyTracebackRef {
pub fn iter(&self) -> impl Iterator<Item = PyTracebackRef> {
std::iter::successors(Some(self.clone()), |tb| tb.next.clone())
std::iter::successors(Some(self.clone()), |tb| tb.next.lock().clone())
}
}

Expand Down
2 changes: 1 addition & 1 deletion vm/src/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ fn remove_importlib_frames_inner(
let file_name = traceback.frame.code.source_path.as_str();

let (inner_tb, mut now_in_importlib) =
remove_importlib_frames_inner(vm, traceback.next.clone(), always_trim);
remove_importlib_frames_inner(vm, traceback.next.lock().clone(), always_trim);
if file_name == "_frozen_importlib" || file_name == "_frozen_importlib_external" {
if traceback.frame.code.obj_name.as_str() == "_call_with_frames_removed" {
now_in_importlib = true;
Expand Down
2 changes: 1 addition & 1 deletion vm/src/suggestion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub fn offer_suggestions(exc: &PyBaseExceptionRef, vm: &VirtualMachine) -> Optio
} else if exc.class().is(vm.ctx.exceptions.name_error) {
let name = exc.as_object().to_owned().get_attr("name", vm).unwrap();
let mut tb = exc.traceback().unwrap();
while let Some(traceback) = tb.next.clone() {
for traceback in tb.iter() {
tb = traceback;
}

Expand Down