diff --git a/bindings/python/dlite-python.i b/bindings/python/dlite-python.i index eeab41e10..7752c9897 100644 --- a/bindings/python/dlite-python.i +++ b/bindings/python/dlite-python.i @@ -25,9 +25,11 @@ count. */ PyObject *dlite_swig_exception = NULL; - /* forward declarations */ + /* Global DLite exceptions - they will be initialised in %init */ static PyObject *DLiteError = NULL; static PyObject *DLiteVerifyError = NULL; + + /* forward declarations */ char *strndup(const char *s, size_t n); %} diff --git a/bindings/python/tests/test_entity.py b/bindings/python/tests/test_entity.py index 4ed493f6c..a6d0322e6 100755 --- a/bindings/python/tests/test_entity.py +++ b/bindings/python/tests/test_entity.py @@ -153,7 +153,7 @@ entity = dlite.Instance.from_json(json_repr) except dlite.DLiteError as exc: assert str(exc) == ( - "Error 1: metadata does not confirm to schema, please check " + "DLiteOtherError: metadata does not confirm to schema, please check " "dimensions, properties and/or relations: " "http://onto-ns.com/ex/0.1/test" ) diff --git a/src/dlite-errors.c b/src/dlite-errors.c index 4a71bdd9b..121cd4567 100644 --- a/src/dlite-errors.c +++ b/src/dlite-errors.c @@ -7,35 +7,35 @@ const char *dlite_errname(DLiteErrors code) { switch (code) { - case dliteSuccess: return "Sussess"; - case dliteUnknownError: return "UnknownError"; - case dliteIOError: return "IOError"; - case dliteRuntimeError: return "RuntimeError"; - case dliteIndexError: return "IndexError"; - case dliteTypeError: return "TypeError"; - case dliteDivisionByZero: return "DivisionByZero"; - case dliteOverflowError: return "OverflowError"; - case dliteSyntaxError: return "SyntaxError"; - case dliteValueError: return "ValueError"; - case dliteSystemError: return "SystemError"; - case dliteAttributeError: return "AttributeError"; - case dliteMemoryError: return "MemoryError"; - case dliteNullReferenceError: return "NullReferenceError"; + case dliteSuccess: return "DLiteSussess"; + case dliteUnknownError: return "DLiteUnknown"; + case dliteIOError: return "DLiteIO"; + case dliteRuntimeError: return "DLiteRuntime"; + case dliteIndexError: return "DLiteIndex"; + case dliteTypeError: return "DLiteType"; + case dliteDivisionByZero: return "DLiteDivisionByZero"; + case dliteOverflowError: return "DLiteOverflow"; + case dliteSyntaxError: return "DLiteSyntax"; + case dliteValueError: return "DLiteValue"; + case dliteSystemError: return "DLiteSystem"; + case dliteAttributeError: return "DLiteAttribute"; + case dliteMemoryError: return "DLiteMemory"; + case dliteNullReferenceError: return "DLiteNullReference"; - case dliteKeyError: return "KeyError"; - case dliteParseError: return "ParseError"; - case dlitePrintError: return "PrintError"; - case dliteUnsupportedError: return "UnsupportedError"; - case dliteInconsistentDataError: return "InconsistentDataError"; - case dliteStorageOpenError: return "StorageOpenError"; - case dliteStorageLoadError: return "StorageLoadError"; - case dliteStorageSaveError: return "StorageSaveError"; - case dliteMissingInstanceError: return "MissingInstanceError"; - case dliteMissingMetadataError: return "MissingMetadataError"; - case dliteMetadataExistError: return "MetadataExistError"; + case dliteKeyError: return "DLiteKey"; + case dliteParseError: return "DLiteParse"; + case dlitePrintError: return "DLitePrint"; + case dliteUnsupportedError: return "DLiteUnsupported"; + case dliteInconsistentDataError: return "DLiteInconsistentData"; + case dliteStorageOpenError: return "DLiteStorageOpen"; + case dliteStorageLoadError: return "DLiteStorageLoad"; + case dliteStorageSaveError: return "DLiteStorageSave"; + case dliteMissingInstanceError: return "DLiteMissingInstance"; + case dliteMissingMetadataError: return "DLiteMissingMetadata"; + case dliteMetadataExistError: return "DLiteMetadataExist"; - case dliteLastError: return "LastError"; + case dliteLastError: return "DLiteLast"; } - if (code < 0) return "UndefinedError"; - return "Successful"; + if (code < 0) return "DLiteUndefined"; + return "DLiteOther"; } diff --git a/src/dlite-misc.c b/src/dlite-misc.c index 1f34b7a61..e1d1f286c 100644 --- a/src/dlite-misc.c +++ b/src/dlite-misc.c @@ -519,6 +519,15 @@ void dlite_globals_set(DLiteGlobals *globals_handler) err_set_state(g); } + +/* Error handler for DLite. */ +static void dlite_err_handler(const ErrRecord *record) +{ + FILE *stream = err_get_stream(); + if (stream) fprintf(stream, "** %s\n", record->msg); +} + + /* Initialises dlite. This function may be called several times. */ @@ -532,8 +541,11 @@ void dlite_init(void) /* Set up global state for utils/err.c */ if (!dlite_globals_get_state(ERR_STATE_ID)) dlite_globals_add_state(ERR_STATE_ID, err_get_state(), NULL); - } + /* Set up error handling */ + err_set_handler(dlite_err_handler); + err_set_nameconv(dlite_errname); + } } diff --git a/src/pyembed/dlite-pyembed.c b/src/pyembed/dlite-pyembed.c index a474eeea3..b7a482f43 100644 --- a/src/pyembed/dlite-pyembed.c +++ b/src/pyembed/dlite-pyembed.c @@ -9,6 +9,8 @@ #include "dlite-python-singletons.h" #include "config-paths.h" +#define GLOBALS_ID "dlite-pyembed-globals" + /* Get rid of MSVS warnings */ #if defined WIN32 || defined _WIN32 || defined __WIN32__ # pragma warning(disable: 4273 4996) @@ -17,6 +19,67 @@ static int python_initialized = 0; + +/* Struct correlating Python exceptions with DLite errors */ +typedef struct { + PyObject *exc; /* Python exception */ + DLiteErrors errcode; /* DLite error */ +} ErrorCorrelation; + +/* Global state for this module */ +typedef struct { + ErrorCorrelation *errcorr; /* NULL-terminated array */ +} PyembedGlobals; + + +/* Free global state for this module */ +static void free_globals(void *globals) +{ + PyembedGlobals *g = (PyembedGlobals *)globals;; + if (g->errcorr) free(g->errcorr); + free(g); +} + +/* Return a pointer to global state for this module */ +static PyembedGlobals *get_globals(void) +{ + PyembedGlobals *g = dlite_globals_get_state(GLOBALS_ID); + if (!g) { + if (!(g = calloc(1, sizeof(PyembedGlobals)))) + return dlite_err(dliteMemoryError, "allocation failure"), NULL; + dlite_globals_add_state(GLOBALS_ID, g, free_globals); + } + return g; +} + +/* Help function returning a constant pointer to a NULL-terminated + array of ErrorCorrelation records. */ +static const ErrorCorrelation *error_correlations(void) +{ + PyembedGlobals *g = get_globals(); + if (!g->errcorr) { + ErrorCorrelation corr[] = { + {PyExc_KeyError, dliteKeyError}, + {PyExc_MemoryError, dliteMemoryError}, + {PyExc_AttributeError, dliteAttributeError}, + {PyExc_SystemError, dliteSystemError}, + {PyExc_ValueError, dliteValueError}, + {PyExc_SyntaxError, dliteSyntaxError}, + {PyExc_OverflowError, dliteOverflowError}, + {PyExc_ZeroDivisionError, dliteDivisionByZero}, + {PyExc_TypeError, dliteTypeError}, + {PyExc_IndexError, dliteIndexError}, + {PyExc_RuntimeError, dliteRuntimeError}, + {PyExc_IOError, dliteIOError}, + {NULL, 0} + }; + if (!(g->errcorr = malloc(sizeof(corr)))) + return dlite_err(dliteMemoryError, "allocation failure"), NULL; + memcpy(g->errcorr, corr, sizeof(corr)); + } + return g->errcorr; +} + /* Initialises the embedded Python environment. */ void dlite_pyembed_initialise(void) { @@ -112,7 +175,6 @@ int dlite_pyembed_finalise(void) return status; } - /* Returns a static pointer to the class name of python object cls or NULL on error. @@ -130,6 +192,37 @@ const char *dlite_pyembed_classname(PyObject *cls) } +/* + Return DLite error code given Python exception type. + */ +DLiteErrors dlite_pyembed_errcode(PyObject *type) +{ + const ErrorCorrelation *corr = error_correlations(); + if (!type) return dliteSuccess; + while (corr->exc) { + if (PyErr_GivenExceptionMatches(type, corr->exc)) + return corr->errcode; + corr++; + } + return dliteUnknownError; +} + +/* + Return Python exception class corresponding to given DLite error code. + Returns NULL if `code` is zero. + */ +PyObject *dlite_pyembed_exception(DLiteErrors code) +{ + const ErrorCorrelation *corr = error_correlations(); + if (!code) return NULL; + while (corr->exc) { + if (code == corr->errcode) return corr->exc; + corr++; + } + return PyExc_Exception; +} + + /* Writes Python error message to `errmsg` (of length `len`) if an Python error has occured. @@ -267,9 +360,14 @@ int dlite_pyembed_err_check(const char *msg, ...) */ int dlite_pyembed_verr_check(const char *msg, va_list ap) { - /* TODO: can we correlate the return value to Python error type? */ - if (PyErr_Occurred()) - return dlite_pyembed_verr(1, msg, ap); + PyObject *err; + //PyGILState_STATE state = PyGILState_STATE(); + err = PyErr_Occurred(); + //PyGILState_Release(state); + if (err) { + int eval = dlite_pyembed_errcode(err); + return dlite_pyembed_verr(eval, msg, ap); + } return 0; } diff --git a/src/pyembed/dlite-pyembed.h b/src/pyembed/dlite-pyembed.h index 4e27fcd5d..d456411b3 100644 --- a/src/pyembed/dlite-pyembed.h +++ b/src/pyembed/dlite-pyembed.h @@ -18,6 +18,11 @@ #include "utils/plugin.h" #include "dlite.h" +/* Remove __attribute__ when we are not compiling with gcc */ +#ifndef __GNUC__ +# define __attribute__(x) +#endif + /** Initialises the embedded Python environment. @@ -35,6 +40,16 @@ int dlite_pyembed_finalise(void); */ const char *dlite_pyembed_classname(PyObject *cls); +/** + Return DLite error code given Python exception type. + */ +DLiteErrors dlite_pyembed_errcode(PyObject *type); + +/** + Return Python exception class corresponding to given DLite error code. + Returns NULL if `code` is zero. + */ +PyObject *dlite_pyembed_exception(DLiteErrors code); /** Writes Python error message to `errmsg` (of length `len`) if an @@ -56,24 +71,28 @@ int dlite_pyembed_errmsg(char *errmsg, size_t errlen); Returns `eval`. */ -int dlite_pyembed_err(int eval, const char *msg, ...); +int dlite_pyembed_err(int eval, const char *msg, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); /** Like dlite_pyembed_err() but takes a `va_list` as input. */ -int dlite_pyembed_verr(int eval, const char *msg, va_list ap); +int dlite_pyembed_verr(int eval, const char *msg, va_list ap) + __attribute__ ((__format__ (__printf__, 2, 0))); /** Checks if an Python error has occured. Returns zero if no error has occured. Otherwise dlite_pyembed_err() is called and non-zero is returned. */ -int dlite_pyembed_err_check(const char *msg, ...); +int dlite_pyembed_err_check(const char *msg, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); /** Like dlite_pyembed_err_check() but takes a `va_list` as input. */ -int dlite_pyembed_verr_check(const char *msg, va_list ap); +int dlite_pyembed_verr_check(const char *msg, va_list ap) + __attribute__ ((__format__ (__printf__, 1, 0))); /** diff --git a/src/pyembed/dlite-python-singletons.c b/src/pyembed/dlite-python-singletons.c index 05461109c..05e64234c 100644 --- a/src/pyembed/dlite-python-singletons.c +++ b/src/pyembed/dlite-python-singletons.c @@ -67,3 +67,9 @@ PyObject *dlite_python_mapping_base(void) { return dlite_python_mainclass("DLiteMappingBase"); } + + +//PyObject *dlite_python_error(void) +//{ +// +//} diff --git a/src/utils/err.c b/src/utils/err.c index 4301e3dc5..2b5750cf8 100644 --- a/src/utils/err.c +++ b/src/utils/err.c @@ -48,6 +48,7 @@ typedef struct { //!< application. Typically the program name. FILE *err_stream; //!< Stream for error printing. Set to NULL to silent ErrHandler err_handler; //!< Error handler + ErrNameConv err_nameconv;//!< Error name converter function int err_stream_opened; //!< Whether err_stream has been opened int err_stream_atexit_called; //!< Whether atexit() has been installed } Globals; @@ -83,7 +84,8 @@ typedef struct { } ThreadLocals; /* Global state */ -static Globals _globals = {"", err_default_stream, err_default_handler, 0, 0}; +static Globals _globals = {"", err_default_stream, err_default_handler, + NULL, 0, 0}; /* Thread local state */ static thread_local ThreadLocals _tls; @@ -99,6 +101,7 @@ static void reset_tls(void) _globals.err_prefix = ""; _globals.err_stream = err_default_stream; _globals.err_handler = err_default_handler; + _globals.err_nameconv = NULL; _globals.err_stream_opened = 0; _globals.err_stream_atexit_called = 0; @@ -150,7 +153,7 @@ void err_set_state(void *state) static char *err_append_sep = "\n - "; /* Error names */ -static char *error_names[] = { +static char *errlevel_names[] = { "Success", "Warning", "Error", @@ -173,7 +176,7 @@ int _err_vformat(ErrLevel errlevel, int eval, int errnum, const char *file, { ThreadLocals *tls = get_tls(); int n=0; - char *errname = error_names[errlevel]; + const char *errlevel_name = err_getlevelname(errlevel); char *errmsg = tls->err_record->msg; size_t errsize = sizeof(tls->err_record->msg); FILE *stream = err_get_stream(); @@ -183,6 +186,7 @@ int _err_vformat(ErrLevel errlevel, int eval, int errnum, const char *file, ErrOverrideMode override = err_get_override_mode(); int ignore_new_error = 0; ErrHandler handler = err_get_handler(); + ErrNameConv nameconv = err_get_nameconv(); int call_handler = handler && !tls->err_record->prev; /* Check warning mode */ @@ -194,7 +198,7 @@ int _err_vformat(ErrLevel errlevel, int eval, int errnum, const char *file, return 0; case errWarnError: errlevel = errLevelError; - errname = error_names[errlevel]; + errlevel_name = errlevel_names[errlevel]; break; default: // should never be reached assert(0); @@ -245,10 +249,16 @@ int _err_vformat(ErrLevel errlevel, int eval, int errnum, const char *file, n += snprintf(errmsg + n, errsize - n, "in %s(): ", func); if (eval) { - n += snprintf(errmsg + n, errsize - n, "%s %d: ", - (errname && *errname) ? errname : "Errval", eval); - } else if (errname && *errname) { - n += snprintf(errmsg + n, errsize - n, "%s: ", errname); + if (nameconv) + n += snprintf(errmsg + n, errsize - n, "%s%s: ", nameconv(eval), + (errlevel_name && *errlevel_name) ? + errlevel_name : ""); + else + n += snprintf(errmsg + n, errsize - n, "%s %d: ", + (errlevel_name && *errlevel_name) ? + errlevel_name : "Errval", eval); + } else if (errlevel_name && *errlevel_name) { + n += snprintf(errmsg + n, errsize - n, "%s: ", errlevel_name); } if (msg && *msg) n += vsnprintf(errmsg + n, errsize - n, msg, ap); @@ -398,6 +408,12 @@ int verr_generic(int errlevel, int eval, int errnum, const char *msg, va_list ap /* Associated functions */ +int err_getlevel(void) +{ + ThreadLocals *tls = get_tls(); + return tls->err_record->level; +} + int err_geteval(void) { ThreadLocals *tls = get_tls(); @@ -446,12 +462,6 @@ const char *err_get_prefix(void) return g->err_prefix; } -/* whether the error stream has been opened with fopen() */ -//static int err_stream_opened = 0; - -/* whether `atexit(err_close_stream)` has been called */ -//static int err_stream_atexit_called = 0; - static void err_close_stream(void) { ThreadLocals *tls = get_tls(); @@ -612,9 +622,8 @@ ErrOverrideMode err_get_override_mode() /* Default error handler. */ static void _err_default_handler(const ErrRecord *record) { - ThreadLocals *tls = get_tls(); - Globals *g = tls->globals; - if (g->err_stream) fprintf(g->err_stream, "** %s\n", record->msg); + FILE *stream = err_get_stream(); + if (stream) fprintf(stream, "** %s\n", record->msg); } ErrHandler err_set_handler(ErrHandler handler) @@ -635,6 +644,37 @@ ErrHandler err_get_handler(void) return g->err_handler; } +ErrNameConv err_set_nameconv(ErrNameConv nameconv) +{ + ThreadLocals *tls = get_tls(); + Globals *g = tls->globals; + ErrNameConv prev = g->err_nameconv; + g->err_nameconv = nameconv; + return prev; +} + +ErrNameConv err_get_nameconv(void) +{ + ThreadLocals *tls = get_tls(); + Globals *g = tls->globals; + return g->err_nameconv; +} + +const char *err_getname(int eval) +{ + ThreadLocals *tls = get_tls(); + Globals *g = tls->globals; + if (g->err_nameconv) return g->err_nameconv(eval); + return NULL; +} + +const char *err_getlevelname(int errlevel) +{ + int n = sizeof(errlevel_names) / sizeof(char *); + if (0 <= errlevel && errlevel < n) return errlevel_names[errlevel]; + return NULL; +} + /* Returns a pointer to the error record */ ErrRecord *_err_get_record() diff --git a/src/utils/err.h b/src/utils/err.h index 8cb17cd1d..c05e82d48 100644 --- a/src/utils/err.h +++ b/src/utils/err.h @@ -327,7 +327,7 @@ int verr_generic(int errlevel, int eval, int errnum, const char *msg, va_list ap /** - * Return a pointer to (thread local) state for this module + * Return a pointer to (thread local) state for this module. */ void *err_get_state(void); @@ -337,6 +337,11 @@ void *err_get_state(void); */ void err_set_state(void *state); +/** + * @brief Returns the error level of the last error. + */ +int err_getlevel(void); + /** * @brief Returns the error value of the last error. */ @@ -369,7 +374,7 @@ void err_clear(void); * @brief Set prefix to prepend to all errors in this application. * Typically this is the program name. * - * Returns the current prefix. + * Returns the current prefix. */ const char *err_set_prefix(const char *prefix); @@ -516,6 +521,42 @@ ErrHandler err_set_handler(ErrHandler handler); */ ErrHandler err_get_handler(void); +/** + * @brief Prototype for function that converts error codes to names. + * + * It should return a static pointer to the name corresponding to + * error level `errlevel` and error code `eval`. May return NULL, if + * the error code is unknown. + */ +typedef const char *(*ErrNameConv)(int eval); + +/** + * @brief Register a function that converts error code to name. + * + * Returns the current error name function. By default it is NULL. + */ +ErrNameConv err_set_nameconv(ErrNameConv nameconv); + +/** + * @brief Returns the current error name converter. + */ +ErrNameConv err_get_nameconv(void); + +/** + * @brief Return const pointer to name corresponding to error code `eval`. + * + * Returns NULL if no error name converter has been registered or if the + * error code is unknown. + */ +const char *err_getname(int eval); + +/** + * @brief Return const pointer to name corresponding to error level `errlevel`. + * + * Returns NULL if `errlevel` does not correspond to a valid error level. + */ +const char *err_getlevelname(int errlevel); + /** @} */ diff --git a/storages/python/dlite-plugins-python.c b/storages/python/dlite-plugins-python.c index 6d8e4e39c..5487f54c3 100644 --- a/storages/python/dlite-plugins-python.c +++ b/storages/python/dlite-plugins-python.c @@ -26,7 +26,6 @@ typedef struct { } DLitePythonStorage; - /* Opens `location` and returns a newly created storage for it. @@ -48,14 +47,16 @@ opener(const DLiteStoragePlugin *api, const char *location, PyErr_Clear(); if (!(classname = dlite_pyembed_classname(cls))) - dlite_warnx("cannot get class name for storage plugin %s", api->name); + dlite_warnx("cannot get class name for storage plugin '%s'", api->name); /* Call method: open() */ if (!(obj = PyObject_CallObject(cls, NULL))) - FAILCODE1(dliteStorageOpenError, "error instantiating %s", classname); + FAILCODE1(dliteStorageOpenError, "error instantiating Python plugin '%s'", + classname); v = PyObject_CallMethod(obj, "open", "ss", location, options); - if (dlite_pyembed_err_check("error calling %s.open()", classname)) goto fail; + if (dlite_pyembed_err_check("calling open() in Python plugin '%s'", classname)) + goto fail; /* Check if the open() method has set attribute `writable` */ if (PyObject_HasAttrString(obj, "readable")) @@ -115,13 +116,14 @@ int closer(DLiteStorage *s) dlite_errclr(); if (!(classname = dlite_pyembed_classname(class))) - dlite_warnx("cannot get class name for storage plugin %s", s->api->name); + dlite_warnx("cannot get class name for storage plugin '%s'", s->api->name); /* Return if close() is not defined */ if (!PyObject_HasAttrString(sp->obj, "close")) return retval; v = PyObject_CallMethod(sp->obj, "close", ""); - if (dlite_pyembed_err_check("error calling %s.close()", classname)) + if (dlite_pyembed_err_check("calling close() in Python plugin '%s'", + classname)) retval = 1; Py_XDECREF(v); Py_DECREF(sp->obj); @@ -142,13 +144,14 @@ int flusher(DLiteStorage *s) dlite_errclr(); if (!(classname = dlite_pyembed_classname(class))) - dlite_warnx("cannot get class name for storage plugin %s", s->api->name); + dlite_warnx("cannot get class name for storage plugin '%s'", s->api->name); /* Return if flush() is not defined */ if (!PyObject_HasAttrString(sp->obj, "flush")) return retval; v = PyObject_CallMethod(sp->obj, "flush", ""); - if (dlite_pyembed_err_check("error calling %s.flush()", classname)) + if (dlite_pyembed_err_check("calling flush() in Python plugin '%s'", + classname)) retval = 1; Py_XDECREF(v); return retval; @@ -171,7 +174,7 @@ char *helper(DLiteStorage *s) dlite_errclr(); if (!(classname = dlite_pyembed_classname(class))) - dlite_warnx("cannot get class name for storage plugin %s", s->api->name); + dlite_warnx("cannot get class name for storage plugin '%s'", s->api->name); if (PyObject_HasAttrString(class, "__doc__")) { if (!(pyclassdoc = PyObject_GetAttrString(class, "__doc__"))) @@ -239,14 +242,14 @@ DLiteInstance *loader(const DLiteStorage *s, const char *id) } dlite_errclr(); if (!(classname = dlite_pyembed_classname(class))) - dlite_warnx("cannot get class name for storage plugin %s", s->api->name); + dlite_warnx("cannot get class name for storage plugin '%s'", s->api->name); PyObject *v = PyObject_CallMethod(sp->obj, "load", "O", pyuuid); Py_DECREF(pyuuid); if (v) { inst = dlite_pyembed_get_instance(v); Py_DECREF(v); } else - dlite_pyembed_err(1, "error calling %s.load()", classname); + dlite_pyembed_err(1, "calling load() in Python plugin '%s'", classname); return inst; } @@ -265,9 +268,11 @@ int saver(DLiteStorage *s, const DLiteInstance *inst) const char *classname; dlite_errclr(); if (!(classname = dlite_pyembed_classname(class))) - dlite_warnx("cannot get class name for storage plugin %s", s->api->name); + dlite_warnx("cannot get class name for storage plugin '%s'", s->api->name); v = PyObject_CallMethod(sp->obj, "save", "O", pyinst); - if (dlite_pyembed_err_check("error calling %s.save()", classname)) goto fail; + if (dlite_pyembed_err_check("calling save() in Python plugin '%s'", + classname)) + goto fail; retval = 0; fail: Py_XDECREF(pyinst); @@ -290,9 +295,10 @@ int deleter(DLiteStorage *s, const char *id) dlite_errclr(); if (dlite_get_uuid(uuid, id) < 0) goto fail; if (!(classname = dlite_pyembed_classname(class))) - dlite_warnx("cannot get class name for storage plugin %s", s->api->name); + dlite_warnx("cannot get class name for storage plugin '%s'", s->api->name); v = PyObject_CallMethod(sp->obj, "delete", "s", uuid); - if (dlite_pyembed_err_check("error calling %s.delete()", classname)) + if (dlite_pyembed_err_check("calling delete() in Python plugin '%s'", + classname)) goto fail; retval = 0; fail: @@ -313,10 +319,11 @@ DLiteInstance *memloader(const DLiteStoragePlugin *api, const char *classname; PyErr_Clear(); if (!(classname = dlite_pyembed_classname(class))) - dlite_warnx("cannot get class name for storage plugin %s", api->name); + dlite_warnx("cannot get class name for storage plugin '%s'", api->name); v = PyObject_CallMethod(class, "from_bytes", "y#s", (const char *)buf, (Py_ssize_t) size, id); - if (dlite_pyembed_err_check("error calling %s.from_bytes()", classname)) { + if (dlite_pyembed_err_check("calling from_bytes() in Python plugin '%s'", + classname)) { Py_XDECREF(v); return NULL; } @@ -324,7 +331,8 @@ DLiteInstance *memloader(const DLiteStoragePlugin *api, inst = dlite_pyembed_get_instance(v); Py_DECREF(v); } else - dlite_pyembed_err(1, "error calling %s.from_bytes()", classname); + dlite_pyembed_err(1, "calling from_bytes() in Python plugin '%s'", + classname); return inst; } @@ -344,9 +352,10 @@ int memsaver(const DLiteStoragePlugin *api, unsigned char *buf, size_t size, dlite_errclr(); if (!pyinst) goto fail; if (!(classname = dlite_pyembed_classname(class))) - dlite_warnx("cannot get class name for storage plugin %s", api->name); + dlite_warnx("cannot get class name for storage plugin '%s'", api->name); v = PyObject_CallMethod(class, "to_bytes", "O", pyinst); - if (dlite_pyembed_err_check("error calling %s.to_bytes()", classname)) + if (dlite_pyembed_err_check("calling to_bytes() in Python plugin '%s'", + classname)) goto fail; if (PyBytes_Check(v)) { if (PyBytes_AsStringAndSize(v, &buffer, &length)) goto fail; @@ -412,13 +421,15 @@ void *iterCreate(const DLiteStorage *s, const char *pattern) const char *classname; dlite_errclr(); if (!(classname = dlite_pyembed_classname(class))) - dlite_warnx("cannot get class name for storage plugin %s", s->api->name); + dlite_warnx("cannot get class name for storage plugin '%s'", s->api->name); if (!(iter = calloc(1, sizeof(Iter)))) FAILCODE(dliteMemoryError, "allocation failure"); iter->v = PyObject_CallMethod(sp->obj, "queue", "s", pattern); - if (dlite_pyembed_err_check("error calling %s.queue()", classname)) goto fail; + if (dlite_pyembed_err_check("calling queue() in Python plugin '%s'", + classname)) + goto fail; if (!PyIter_Check(iter->v)) FAIL1("method %s.queue() does not return a iterator object", classname); @@ -491,7 +502,7 @@ get_dlite_storage_plugin_api(void *state, int *iter) /* get classname for error messages */ if (!(classname = dlite_pyembed_classname(cls))) - dlite_warnx("cannot get class name for storage plugin: %s", api->name); + dlite_warnx("cannot get class name for storage plugin: '%s'", api->name); /* get attributes to fill into the api */ if (PyObject_HasAttrString(cls, "name")) diff --git a/storages/python/python-storage-plugins/blob.json b/storages/python/python-storage-plugins/blob.json index fdf529c34..682c96452 100644 --- a/storages/python/python-storage-plugins/blob.json +++ b/storages/python/python-storage-plugins/blob.json @@ -2,11 +2,11 @@ "name": "Blob", "version": "0.1", "namespace": "http://onto-ns.com/meta", - "description": "Entity representing a single binary blob.", + "description": "Entity representing a single binary blob as a sequence of bytes.", "dimensions": [ { "name": "n", - "description": "Size of blob." + "description": "Size of blob(i.e. number of bytes)." } ], "properties": [ diff --git a/storages/python/python-storage-plugins/yaml.py b/storages/python/python-storage-plugins/yaml.py index 519a721d1..5c9761c27 100644 --- a/storages/python/python-storage-plugins/yaml.py +++ b/storages/python/python-storage-plugins/yaml.py @@ -39,7 +39,6 @@ def open(self, uri: str, options=None): self.uri = uri self.flushed = False # whether buffered data has been written to file self._data = {} # data buffer - if self.options.mode in ("r", "a", "append"): with open(uri, "r") as f: data = pyyaml.safe_load(f) @@ -62,6 +61,7 @@ def flush(self): sort_keys=False, ) self.flushed = True + raise TypeError("abc") def load(self, id: str): """Loads `uuid` from current storage and return it as a new instance.