Richard W.M. Jones
2019-Jun-28 10:05 UTC
[Libguestfs] [PATCH libnbd] python: Raise a custom exception containing error string and errno.
I spent a good few hours this morning trying to make this work and came up with the following patch. It's not quite right though. The exception I've created exists in the libnbdmod module (ie. the underlying C module that we use for the Python bindings). Ideally we'd define and throw an exception from the normal nbd module, but I couldn't work out how to do that. Probably someone who knows a bit more about Python might find this easy to do. Rich.
Richard W.M. Jones
2019-Jun-28 10:05 UTC
[Libguestfs] [PATCH libnbd] python: Raise a custom exception containing error string and errno.
Previously errors caused a RuntimeException to be raised. This commit defines a custom exception (libnbdmod.Error) which has two parameters, the required error string, and the optional errno (which may be 0 if unavailable). For example: $ ./run nbdsh -c 'h.pread(0, 0)' Traceback (most recent call last): File "/usr/lib64/python3.7/runpy.py", line 193, in _run_module_as_main "__main__", mod_spec) File "/usr/lib64/python3.7/runpy.py", line 85, in _run_code exec(code, run_globals) File "/home/rjones/d/libnbd/python/nbd.py", line 1133, in <module> nbdsh.shell() File "/home/rjones/d/libnbd/python/nbdsh.py", line 62, in shell exec (c) File "<string>", line 1, in <module> File "/home/rjones/d/libnbd/python/nbd.py", line 453, in pread return libnbdmod.pread (self._o, count, offset, flags) libnbdmod.Error: ('nbd_pread: invalid state: START: the handle must be connected and finished handshaking with the server: Transport endpoint is not connected', 107) --- generator/generator | 31 ++++++++++++++++++++++++++++++- python/t/610-exception.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/generator/generator b/generator/generator index 157a9cb..11ab8b8 100755 --- a/generator/generator +++ b/generator/generator @@ -3337,6 +3337,19 @@ get_handle (PyObject *obj) return (struct nbd_handle *) PyCapsule_GetPointer(obj, \"nbd_handle\"); } +/* nbd.Error exception. */ +extern PyObject *nbd_internal_py_Error; + +static inline void +raise_exception () +{ + PyObject *args = PyTuple_New (2); + + PyTuple_SetItem (args, 0, PyUnicode_FromString (nbd_get_error ())); + PyTuple_SetItem (args, 1, PyLong_FromLong (nbd_get_errno ())); + PyErr_SetObject (nbd_internal_py_Error, args); +} + "; List.iter ( @@ -3390,6 +3403,9 @@ static struct PyModuleDef moduledef = { NULL, /* m_free */ }; +/* nbd.Error exception. */ +PyObject *nbd_internal_py_Error; + extern PyMODINIT_FUNC PyInit_libnbdmod (void); PyMODINIT_FUNC @@ -3401,6 +3417,19 @@ PyInit_libnbdmod (void) if (mod == NULL) return NULL; + nbd_internal_py_Error = PyErr_NewExceptionWithDoc ( + \"libnbdmod.Error\", + \"Exception thrown when the underlying libnbd call fails. This\\n\" + \"exception carries a two element tuple. The first element is a\\n\" + \"printable string containing the error message. The second\\n\" + \"element is the optional errno (which may be 0 in some cases\\n\" + \"if the error does not correspond to a system call failure).\\n\", + NULL, NULL + ); + if (nbd_internal_py_Error == NULL) + return NULL; + PyModule_AddObject (mod, \"Error\", nbd_internal_py_Error); + return mod; } " @@ -3796,7 +3825,7 @@ let print_python_binding name { args; ret } | RBool | RErr | RFd | RInt | RInt64 -> pr " if (ret == -1) {\n"; | RConstString | RString -> pr " if (ret == NULL) {\n"; ); - pr " PyErr_SetString (PyExc_RuntimeError, nbd_get_error ());\n"; + pr " raise_exception ();\n"; pr " py_ret = NULL;\n"; pr " goto out;\n"; pr " }\n"; diff --git a/python/t/610-exception.py b/python/t/610-exception.py new file mode 100644 index 0000000..f27b57d --- /dev/null +++ b/python/t/610-exception.py @@ -0,0 +1,34 @@ +# libnbd Python bindings +# Copyright (C) 2010-2019 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +import nbd +import libnbdmod + +h = nbd.NBD () + +try: + # This will always throw an exception because the handle is not + # connected. + h.pread (0, 0) +except libnbdmod.Error as ex: + str = ex.args[0] + errno = ex.args[1] + print ("str = %s\nerr = %d\n" % (str, errno)) + exit (0) + +# If we reach here then we didn't catch the exception above. +exit (1) -- 2.22.0
Apparently Analagous Threads
- [PATCH libnbd v2] python: Raise a custom exception containing error string and errno.
- [PATCH libnbd v3] python: Raise a custom exception containing error string and errno.
- [PATCH libnbd v2] python: Raise a custom exception containing error string and errno.
- [PATCH libnbd v3] python: Raise a custom exception containing error string and errno.
- Re: [PATCH libnbd v3] python: Raise a custom exception containing error string and errno.