-
Notifications
You must be signed in to change notification settings - Fork 899
add PyErr::set_traceback
#5349
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
base: main
Are you sure you want to change the base?
add PyErr::set_traceback
#5349
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -224,6 +224,7 @@ pub fn argument_extraction_error(py: Python<'_>, arg_name: &str, error: PyErr) - | |
| let remapped_error = | ||
| PyTypeError::new_err(format!("argument '{}': {}", arg_name, error.value(py))); | ||
| remapped_error.set_cause(py, error.cause(py)); | ||
| remapped_error.set_traceback(py, error.traceback(py)); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An alternative on Python 3.11+ could be to use call ... if so, it might even be good enough to just drop the "remapping" completely even on old Python versions, and just do nothing on old versions where the notes don't exist.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting, I did not know about Traceback (most recent call last):
File "G:\RustProjects\pyo3-workspace\pyo3-scratch\foo.py", line 7, in <module>
test(Foo())
~~~~^^^^^^^
File "G:\RustProjects\pyo3-workspace\pyo3-scratch\foo.py", line 4, in foo
raise TypeError("wrong type")
TypeError: wrong type
while processing `bar`or Traceback (most recent call last):
File "G:\RustProjects\pyo3-workspace\pyo3-scratch\foo.py", line 7, in <module>
test(Foo())
~~~~^^^^^^^
TypeError: 'str' object cannot be interpreted as an integer
while processing `bar`
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, we'd have to go via the Python call, but at least we could optimize that to be a "vectorcall". I think given this is already the error pathway it's not the end of the world if it's a little slower. What do you think of this option? I like the fact that it's applicable to all errors and simplifies, though I worry about possible silent breakage downstream.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm open to it. The ability to apply it to all exceptions is pretty appealing. Also there is also Depending on the wording the newline of Traceback (most recent call last):
File "G:\RustProjects\pyo3-workspace\pyo3-scratch\foo.py", line 7, in <module>
test(Foo())
~~~~^^^^^^^
TypeError: 'str' object cannot be interpreted as an integer
Note: This occurred while processing argument `bar`.
What kind of breakage do you have in mind here? Just someone relying on the exact error message? I think the type would be the same, right?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, dependency on the error message. I would argue that it's generally bad practice to depend on error message content (maybe aside from in tests), but you never know and hard to inform users of changes 😬 That said, I think I like it enough that we should move forward with the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just noticed that while these notes are shown on unhandled exceptions, they are not part final error message. So catching the exception and just from pyo3_scratch import test
class Foo:
def foo(self):
raise TypeError("wrong type")
try:
test(Foo())
except Exception as e:
print(e) # does not show the note
# wrong type
test(Foo())
# TypeError: wrong type
# Note: This occurred while processing argument 'bar'.For the same reason the notes are not shown in the I guess this is at least a good argument for taking a bit more time here and not land this in 0.26.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, that's a good (and unfortunate) point.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A related observation here: the current code may wrap Xref #5457 (comment) |
||
| remapped_error | ||
| } else { | ||
| error | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mild slight crazy idea I've wondered about in the past, I have wondered if there is a use case for a type which is something like
AtomicPy(maybe including theOption, not sure, would need it in this case I guess) which would allow for swapping the contained objects using atomics. Could avoid locking? 🤔There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually had the same idea that
AtomicPtrshould be possible here, but without a proper wrapper it's to hairy.An
AtomicPycould also be useful forfrozenpyclasses that want to swap out aPyfield. We would need to figure out whether it's possible to write a safe interface around it. I guess it would not be possible to borrow it, we would always have to work with "owned" pointers.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes I think
frozenclasses might be where I was wondering about this in the past too.I would definitely be open to exploring that further, I have no idea how it would feel in practice!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess so, but it's not completely stuck.
&AtomicPywould work, but the semantics would presumably be that someone else might swap the object that it points to until you.clone_ref(py)to get aBound, I guess.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I played a bit to find out how the interface could look like. I put that experiment in #5356