Python gmxapi exception hierarchy
libgmxapi can throw exceptions derived from
gmxapi::Exception, defined in the gmxapi/exceptions.h installed header. These exceptions should have bindings in the gmxapi Python package (in the
_gmxapi C++ extension module) so that they are easily catchable from Python.
Should C++ exceptions defined in the
_gmxapi module should derive from
Is it a priority that users of the Python package should be able to use
gmxapi.exceptions.Error as a catch-all base exception, even for exceptions originating in the _gmxapi extension module or in the core GROMACS library?
Developer documentation should describe how exceptions propagate and how they are catchable in both directions between Python and C++, with explanations of caveats for exceptions originating in different binaries or Python packages.
Also reference prior discussion at https://github.com/kassonlab/gmxapi/issues/125
Map gmxapi C++ exceptions to Python exceptions.
Create a base exception and several derived exceptions in the
gmxapi._gmxapi C++ extension module for the Python package. In addition
to mapping the few existing exceptions from gmxapi/exceptions.h, we add
handlers for unmapped exceptions derived from gmxapi::Exception and for
unknown exceptions, such as exceptions originating in the core library
or uncaught stdlib exceptions. gmxapi._gmxapi.Exception derives from
#5 Updated by Eric Irrgang over 1 year ago
- Subject changed from Python bindings for gmxapi exceptions to Python gmxapi exception hierarchy
- Description updated (diff)
We may not want an actual inheritance relationship between the base exception in gmxapi._gmxapi and the base exception in gmxapi.exceptions because that would mean either we have a potentially troublesome circular dependency (if gmxapi._gmxapi depends on gmxapi.exceptions) or we can't raise gmxapi.exceptions.Error until gmxapi._gmxapi is imported successfully. Unfortunately, the exception matching in
try: ... except expressions doesn't seem to use the Python virtual inheritance hooks.
We could try to catch exceptions from gmxapi._gmxapi.Exception and wrap them in gmxapi.exception.X exceptions wherever possible in the Python package, but that would mean that all gmxapi._gmxapi objects would need to be wrapped in pure Python objects, and I don't think we want to do that.
We can also try minimizing the exceptions that can escape from gmxapi._gmxapi and instead develop the data model to embed the error reporting in return values, but we need to be cautious to be sure that errors can't go unnoticed and that failures occur as early as possible.
#6 Updated by Eric Irrgang about 1 year ago
- Description updated (diff)
The more I think about it, the more comfortable I am with letting the CPython gmxapi._gmxapi.Exception subclass the pure Python gmxapi.exceptions.Error. The gmxapi._gmxapi module is an implementation detail of the gmxapi Python package, and in the real world it is essentially inaccessible without explicitly or implicitly importing the pure Python package, which imports gmxapi.exceptions very early. If we want to be rigorously certain that we are subclassing the gmxapi.exceptions.Error class that has already been imported by the parent package, the import machinery should allow us to do that explicitly within the _gmxapi module initialization code, rather than trusting