I considered multiple approaches for this but settled on this one because I could make the lifetime management work in a reasonably easy way (others had issues with not being able to cast to a Python reference from a C++ constructor). We could stand to have more formatting helpers, but best to get the core mechanism in first.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
mlir/lib/Bindings/Python/IRModule.h | ||
---|---|---|
336 | When are the contextEnter and contextExit method called? |
mlir/lib/Bindings/Python/IRModule.h | ||
---|---|---|
336 | They are bound to __enter__ and __exit__ to enable use as a context manager. We do similar naming elsewhere in this module. |
I'd rather wait for @ftynse to have a look as well, I think I understand everything in this patch, but this in the realm of "I wouldn't be able to write this myself" ;)
mlir/lib/Bindings/Python/IRModule.h | ||
---|---|---|
336 | Right, I wasn't clear, I should have asked: "when is this class used as a context manager?" But I figured in the meantime by reading the test, so it's fine :) |
No problem at all getting another set of eyes... I've been needing/dreading this for the past year. A few more days makes no difference :)
re: "I wouldn't be able to write this myself" - I'm sure you could if sufficiently motivated.
For Alex, the primary alternative design I considered/tried was having the DiagnosticHandler be a free-standing class that auto attached on construction like:
with Context(), DiagnosticHandler(callback): # do stuff
Trying to make this work ran into all kinds of undocumented and surprising pybind behavior, since you need to get access to the py::object from within the scope of the py::init<> function (so that you can borrow against the python reference count). I couldn't come up with a way to make ownership transfer properly in that situation. I don't expect this is going to be one of those everyday things for people to be doing and opted for a simpler implementation. My hope is that we layer some kind of exception handler thing on top of this so that I can do something like:
with CaptureDiagnostics() as diag_cap: # run passes and do stuff # If we exit the with exceptionally, then raise a chained exception that includes any diagnostics. # If we exit successfully: print(diag_cap.diagnostics)
(or something like that -- need to fiddle with it, and this can be written in pure Python atop this basic facility)
LGTM! I agree that it's better to write nicer APIs directly in Python, debugging Pybind glue is hard.
mlir/lib/Bindings/Python/IRCore.cpp | ||
---|---|---|
515 | Nit: this could use a comment that the Python will free the newed object during its GC sweep because of ownership transfer below. | |
mlir/test/python/ir/diagnostic_handler.py | ||
75 | An optional kwargs notes? As in loc.emit_error("foo", notes=[loc.error_note("bar"), other_loc.error_note("qux")]) ? |
mlir/test/python/ir/diagnostic_handler.py | ||
---|---|---|
75 | Yes, something like that. Will need more C-APIs (and more Python), which was further than I wanted to go in this patch. |
Nit: this could use a comment that the Python will free the newed object during its GC sweep because of ownership transfer below.