Changeset: a81f559785ba for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=a81f559785ba Modified Files: monetdb5/extras/pyapi/Benchmarks/pyapi_test.sh monetdb5/extras/pyapi/formatinput.c monetdb5/extras/pyapi/formatinput.h monetdb5/extras/pyapi/pyapi.c Branch: pyapi Log Message:
Added better error reporting for problems while formatting Python code. diffs (190 lines): diff --git a/monetdb5/extras/pyapi/Benchmarks/pyapi_test.sh b/monetdb5/extras/pyapi/Benchmarks/pyapi_test.sh --- a/monetdb5/extras/pyapi/Benchmarks/pyapi_test.sh +++ b/monetdb5/extras/pyapi/Benchmarks/pyapi_test.sh @@ -1,7 +1,7 @@ # The base directory of testing, a new folder is created in this base directory [$PYAPI_TEST_DIR], and everything is done in that new folder -export PYAPI_BASE_DIR=$HOME +export PYAPI_BASE_DIR=/export/scratch1/raasveld # The terminal to start mserver with, examples are 'gnome-terminal', 'xterm', 'konsole' export TERMINAL=x-terminal-emulator # A command that tests if the mserver is still running (used to find out when the shutting down of mserver is completed) diff --git a/monetdb5/extras/pyapi/formatinput.c b/monetdb5/extras/pyapi/formatinput.c --- a/monetdb5/extras/pyapi/formatinput.c +++ b/monetdb5/extras/pyapi/formatinput.c @@ -8,10 +8,11 @@ #include "mal_linker.h" #include "gdk_utils.h" #include "gdk.h" +#include "mal_exception.h" //! Parse a PyCodeObject from a string, the string is expected to be in the format {@<encoded_function>};, where <encoded_function> is all the PyCodeObject properties in order -PyObject *PyCodeObject_ParseString(char *string); +PyObject *PyCodeObject_ParseString(char *string, char **msg); char* GetArg(char *string, char *storage, int index); char* GetArg(char *string, char *storage, int index) @@ -62,8 +63,8 @@ size_t ModifyCode(char *string, char *st return j; } -PyObject *GetConstantObject(char *string, char *storage); -PyObject *GetConstantObject(char *string, char *storage) +PyObject *GetConstantObject(char *string, char *storage, char **msg); +PyObject *GetConstantObject(char *string, char *storage, char **msg) { int numbers = 0, i = 0, j = 0, k = 0; int length = strlen(string); @@ -81,6 +82,7 @@ PyObject *GetConstantObject(char *string } if (brackets != 0) { //invalid number of brackets + *msg = createException(MAL, "pyapi.eval", "Invalid number of brackets in encoded Python code object string."); return NULL; } @@ -110,9 +112,9 @@ PyObject *GetConstantObject(char *string object = PyUnicode_FromString(storage); } else if (strcmp(type_str, "code") == 0) { //recursive call, we've got a function within this function, so we have to parse another code object - object = PyCodeObject_ParseString(storage); + object = PyCodeObject_ParseString(storage, msg); } else { - printf("ERROR: Unrecognized type %s!", type_str); + *msg = createException(MAL, "pyapi.eval", "Unrecognized constant type %s in encoded Python code object string.", type_str); return NULL; } PyTuple_SetItem(result, j, object); @@ -170,13 +172,17 @@ PyObject* GetStringTuple(char *string, c return result; } -PyObject *PyCodeObject_ParseString(char *string) +PyObject *PyCodeObject_ParseString(char *string, char **msg) { int argcount, nlocals, stacksize, flags, firstlineno; PyObject *code, *name, *filename, *lnotab; PyObject *consts, *names, *varnames, *freevars, *cellvars; char *temp_string = GDKmalloc(strlen(string)); char *temp_string2 = GDKmalloc(strlen(string)); + if (temp_string == NULL || temp_string2 == NULL) { + *msg = createException(MAL, "pyapi.eval", MAL_MALLOC_FAIL); + return NULL; + } size_t size; //argcount is a single int @@ -191,7 +197,7 @@ PyObject *PyCodeObject_ParseString(char size = ModifyCode(GetArg(string, temp_string, 4), temp_string2); code = PyString_FromStringAndSize(temp_string2, size); //now parse the constants, constants are a list of python objects in the form of (type:value) (ex: (int:20)(int:33)(str:hello)) - consts = GetConstantObject(GetArg(string, temp_string, 5), temp_string2); + consts = GetConstantObject(GetArg(string, temp_string, 5), temp_string2, msg); //now parse the names, this is a list of strings delimited by commas (ex: name,name2,) names = GetStringTuple(GetArg(string, temp_string, 6), temp_string2); //now parse the varnames, same as above @@ -214,7 +220,7 @@ PyObject *PyCodeObject_ParseString(char return (PyObject*)PyCode_New(argcount, nlocals, stacksize, flags, code, consts, names, varnames, freevars, cellvars, filename, name, firstlineno, lnotab); } -char* FormatCode(char* code, char **args, size_t argcount, size_t tabwidth, PyObject **code_object) +char* FormatCode(char* code, char **args, size_t argcount, size_t tabwidth, PyObject **code_object, char **msg) { // Format the python code by fixing the indentation levels // We do two passes, first we get the length of the resulting formatted code and then we actually create the resulting code @@ -247,15 +253,16 @@ char* FormatCode(char* code, char **args char base_start[] = "def pyfun("; char base_end[] = "):\n"; - + *msg = NULL; if (code[1] == '@') { - *code_object = PyCodeObject_ParseString(code); + *code_object = PyCodeObject_ParseString(code, msg); return NULL; } indentation_levels = (size_t*)GDKzalloc(max_indentation * sizeof(size_t)); statements_per_level = (size_t*)GDKzalloc(max_indentation * sizeof(size_t)); if (indentation_levels == NULL || statements_per_level == NULL) { + *msg = createException(MAL, "pyapi.eval", MAL_MALLOC_FAIL); goto finally; } @@ -343,9 +350,15 @@ char* FormatCode(char* code, char **args // This probably will never happen unless in really extreme code (or if max_indentation is set very low) size_t *new_indentation = GDKzalloc(2 * max_indentation * sizeof(size_t)); size_t *new_statements_per_level; - if (new_indentation == NULL) goto finally; + if (new_indentation == NULL) { + *msg = createException(MAL, "pyapi.eval", MAL_MALLOC_FAIL); + goto finally; + } new_statements_per_level = GDKzalloc(2 * max_indentation * sizeof(size_t)); - if (new_statements_per_level == NULL) goto finally; + if (new_statements_per_level == NULL) { + *msg = createException(MAL, "pyapi.eval", MAL_MALLOC_FAIL); + goto finally; + } for(i = 0; i < max_indentation; i++) { new_indentation[i] = indentation_levels[i]; @@ -402,7 +415,10 @@ char* FormatCode(char* code, char **args // Allocate space for the function newcode = GDKzalloc(size); - if (newcode == NULL) goto finally; + if (newcode == NULL) { + *msg = createException(MAL, "pyapi.eval", MAL_MALLOC_FAIL); + goto finally; + } initial_spaces = 0; seen_statement = false; @@ -467,7 +483,7 @@ char* FormatCode(char* code, char **args // This should never happen, because it means the initial spaces was not present in the array // When we just did exactly the same loop over the array, we should have encountered this statement // This means that something happened to either the indentation_levels array or something happened to the code - printf("WHAT HAPPENED\n"); + *msg = createException(MAL, "pyapi.eval", "If you see this error something went wrong in the code. Sorry."); goto finally; } for(j = 0; j < (level + 1) * spaces_per_level; j++) { @@ -490,7 +506,7 @@ char* FormatCode(char* code, char **args newcode[code_location] = '\0'; if (code_location >= size) { // Something went wrong with our size computation, this also should never happen - printf("WHAT HAPPENED\n"); + *msg = createException(MAL, "pyapi.eval", "If you see this error something went wrong in the code (size computation). Sorry."); goto finally; } finally: diff --git a/monetdb5/extras/pyapi/formatinput.h b/monetdb5/extras/pyapi/formatinput.h --- a/monetdb5/extras/pyapi/formatinput.h +++ b/monetdb5/extras/pyapi/formatinput.h @@ -21,6 +21,6 @@ #undef _POSIX_C_SOURCE #include <Python.h> -char* FormatCode(char* code, char **args, size_t argcount, size_t tabwidth, PyObject **code_object); +char* FormatCode(char* code, char **args, size_t argcount, size_t tabwidth, PyObject **code_object, char **return_message); #endif /* _PY_FORMAT_INPUT_LIB_ */ diff --git a/monetdb5/extras/pyapi/pyapi.c b/monetdb5/extras/pyapi/pyapi.c --- a/monetdb5/extras/pyapi/pyapi.c +++ b/monetdb5/extras/pyapi/pyapi.c @@ -696,9 +696,10 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st /*[PARSE_CODE]*/ VERBOSE_MESSAGE("Formatting python code.\n"); - pycall = FormatCode(exprStr, args, pci->argc, 4, &code_object); + pycall = FormatCode(exprStr, args, pci->argc, 4, &code_object, &msg); if (pycall == NULL && code_object == NULL) { - throw(MAL, "pyapi.eval", MAL_MALLOC_FAIL); + if (msg == NULL) { msg = createException(MAL, "pyapi.eval", "Error while parsing Python code."); } + goto wrapup; } /*[CONVERT_BAT]*/ _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list