Changeset: 9a8852ef2aa2 for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=9a8852ef2aa2 Modified Files: monetdb5/extras/pyapi/Tests/All monetdb5/extras/pyapi/Tests/pyapi01.malC monetdb5/extras/pyapi/Tests/pyapi02.malC monetdb5/extras/pyapi/Tests/pyapi03.malC monetdb5/extras/pyapi/pyapi.c Branch: pyapi Log Message:
Fixed boolean types. diffs (truncated from 413 to 300 lines): diff --git a/monetdb5/extras/pyapi/Tests/All b/monetdb5/extras/pyapi/Tests/All --- a/monetdb5/extras/pyapi/Tests/All +++ b/monetdb5/extras/pyapi/Tests/All @@ -1,4 +1,1 @@ -HAVE_LIBPY?pyapi00 -HAVE_LIBPY?pyapi01 -HAVE_LIBPY?pyapi02 -HAVE_LIBPY?pyapi03 +HAVE_LIBPY?pyapi_types_string diff --git a/monetdb5/extras/pyapi/Tests/pyapi01.malC b/monetdb5/extras/pyapi/Tests/pyapi01.malC --- a/monetdb5/extras/pyapi/Tests/pyapi01.malC +++ b/monetdb5/extras/pyapi/Tests/pyapi01.malC @@ -1,16 +1,17 @@ +#testing basic string and boolean types #booleans -bool:= bat.new(:oid,:str); -bat.append(bool,"T":str); -bat.append(bool,"T":str); -bat.append(bool,"T":str); -bat.append(bool,"T":str); -bat.append(bool,"T":str); -bat.append(bool,"T":str); -bat.append(bool,"T":str); -bat.append(bool,nil:str); -rbool:bat[:oid,:str] := pyapi.eval(nil:ptr,"return([[True]])",bool); +bool:= bat.new(:oid,:bte); +bat.append(bool,1:bte); +bat.append(bool,1:bte); +bat.append(bool,1:bte); +bat.append(bool,1:bte); +bat.append(bool,1:bte); +bat.append(bool,1:bte); +bat.append(bool,1:bte); +bat.append(bool,nil:bte); +rbool:bat[:oid,:bte] := pyapi.eval(nil:ptr,"return(all(arg1))",bool); io.print(rbool); #strings testing diff --git a/monetdb5/extras/pyapi/Tests/pyapi02.malC b/monetdb5/extras/pyapi/Tests/pyapi02.malC --- a/monetdb5/extras/pyapi/Tests/pyapi02.malC +++ b/monetdb5/extras/pyapi/Tests/pyapi02.malC @@ -36,8 +36,8 @@ bat.append(bint,846930886:int); bat.append(bint,1681692777:int); bat.append(bint,1714636915:int); bat.append(bint,nil:int); -#rint:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"return([numpy.add(arg1.filled(0),1)])",bint); -#io.print(rint); +rint:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"return([numpy.add(arg1.filled(0),1)])",bint); +io.print(rint); bwrd:= bat.new(:oid,:wrd); bat.append(bwrd,1804289383:wrd); @@ -45,16 +45,16 @@ bat.append(bwrd,846930886:wrd); bat.append(bwrd,1681692777:wrd); bat.append(bwrd,1714636915:wrd); bat.append(bwrd,nil:wrd); -#rwrd:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"return([numpy.add(arg1.filled(0),1)])",bwrd); -#io.print(rwrd); +rwrd:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"return([numpy.add(arg1.filled(0),1)])",bwrd); +io.print(rwrd); blng:= bat.new(:oid,:lng); bat.append(blng,1804289383L); bat.append(blng,846930886L); bat.append(blng,1681692777L); bat.append(blng,1714636915L); -#rlng:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"return([numpy.add(arg1.filled(0),1)])",blng); -#io.print(rlng); +rlng:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"return([numpy.add(arg1.filled(0),1)])",blng); +io.print(rlng); # not sure what to with hge, numpy only supports 128 bits when sizeof(long)=16 # bhge:= bat.new(:oid,:hge); @@ -82,8 +82,8 @@ bat.append(bdbl,84.6930886:dbl); bat.append(bdbl,168169.2777:dbl); bat.append(bdbl,17146369.15:dbl); bat.append(bdbl,nil:dbl); -#rdbl:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"return([numpy.add(arg1.filled(0),1)])",bdbl); -#io.print(rdbl); +rdbl:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"return([numpy.add(arg1.filled(0),1)])",bdbl); +io.print(rdbl); # strings @@ -92,23 +92,21 @@ bat.append(bstr,"asdf":str); bat.append(bstr,"sd asd asd asd asd a":str); bat.append(bstr,nil:str); bat.append(bstr,"test":str); -#rstr:bat[:oid,:str] := pyapi.eval(nil:ptr,"print(arg1);\nreturn(arg1)",bstr); -#io.print(rstr); +rstr:bat[:oid,:str] := pyapi.eval(nil:ptr,"print(arg1);\nreturn(arg1)",bstr); +io.print(rstr); -#STRANGE BUG HERE WITH .filled() -#TODO: Investigate #booleans -bool:= bat.new(:oid,:str); -bat.append(bool,"T":str); -bat.append(bool,"T":str); -bat.append(bool,"T":str); -bat.append(bool,"T":str); -bat.append(bool,"T":str); -bat.append(bool,"T":str); -bat.append(bool,"T":str); -bat.append(bool,"T":str); -rbool:bat[:oid,:str] := pyapi.eval(nil:ptr,"print arg1\nreturn(arg1)",bool); +bool:= bat.new(:oid,:bte); +bat.append(bool,1:bte); +bat.append(bool,1:bte); +bat.append(bool,1:bte); +bat.append(bool,1:bte); +bat.append(bool,1:bte); +bat.append(bool,1:bte); +bat.append(bool,1:bte); +bat.append(bool,nil:bte); +rbool:bat[:oid,:bte] := pyapi.eval(nil:ptr,"print arg1\nreturn(arg1)",bool); io.print(rbool); diff --git a/monetdb5/extras/pyapi/Tests/pyapi03.malC b/monetdb5/extras/pyapi/Tests/pyapi03.malC --- a/monetdb5/extras/pyapi/Tests/pyapi03.malC +++ b/monetdb5/extras/pyapi/Tests/pyapi03.malC @@ -1,10 +1,9 @@ -# input types testing +# different functions testing # inty types -#single-value array gives segmentation fault -rstr:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"return [55]"); +rstr:bat[:oid,:str] := pyapi.eval(nil:ptr,"return 42"); io.print(rstr); bstr:= bat.new(:oid,:int); 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 @@ -28,7 +28,7 @@ const char* pyapi_enableflag = "embedded_py"; char *NPYConstToString(int); -bool IsPyArrayObject(PyObject *); +bool IsPyArrayObject(PyObject *, int); int PyAPIEnabled(void) { return (GDKgetenv_istrue(pyapi_enableflag) @@ -71,6 +71,7 @@ static int pyapiInitialized = FALSE; } \ } \ } + #define NP_MAKE_BAT(bat, mtpe, nptpe) { \ BATseqbase(bat, 0); bat->T->nil = 0; bat->T->nonil = 1; \ bat->tkey = 0; bat->tsorted = 0; bat->trevsorted = 0; \ @@ -246,55 +247,6 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st maxsize = length; } - if (maxsize == 1 || maxsize == strlen(str_nil)) - { - //BOOLEANS - bool isbool = true; - BATloop(b, p, q) - { - const char *t = (const char *) BUNtail(li, p); - if (t[0] != 'T' && t[0] !='F' && strcmp(t, str_nil) != 0) - { - isbool = false; - break; - } - } - if (isbool) - { - //create a NPY_BOOL array object - vararray = PyArray_New( - &PyArray_Type, - 1, - (npy_intp[1]) {count}, - NPY_BOOL, - NULL, - NULL, - 0, - NPY_ARRAY_CARRAY || NPY_ARRAY_WRITEABLE, - NULL); - - //fill the NPY_BOOL array object using the PyArray_SETITEM function - j = 0; - BATloop(b, p, q) - { - const char *t = (const char *) BUNtail(li, p); - PyObject *value; - if (t[0] == 'T') - { - Py_INCREF(Py_True); - value = Py_True; - } - else - { - Py_INCREF(Py_False); - value = Py_False; - } - PyArray_SETITEM((PyArrayObject*)vararray, PyArray_GETPTR1((PyArrayObject*)vararray, j), value); - j++; - } - break; - } - } //create a NPY_STRING array object vararray = PyArray_New( &PyArray_Type, @@ -319,8 +271,6 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st case TYPE_hge: vararray = BAT_TO_NP(b, hge, NPY_LONGDOUBLE); break; - - // TODO: implement other types (boolean) default: msg = createException(MAL, "pyapi.eval", "unknown argument type "); goto wrapup; @@ -472,31 +422,51 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st goto wrapup; // shudder } - if (!pResult || !PyList_Check(pResult) || PyList_Size(pResult) != pci->retc) + if (pResult) { - //the object is not a PyList, but maybe it is a single PyArrayObject, so we will check if it is - if (IsPyArrayObject(pResult)) + PyObject * pColO; + + if (!PyList_Check(pResult)) { - //a single array is returned rather than a list of arrays - //convert the single array to a list of size 1 - - //TODO: Accept a single object (not just a single array) and cast it to an array - //TODO: Accept a single array with a single object in it (this currently gives a Segmentation Fault) + if (pci->retc == 1) + { + //the object is not a PyList, turn it into a PyList! + PyObject *list = PyList_New(1); + PyList_SetItem(list, 0, pResult); + pResult = list; + } + else + { + //the result object is not a PyList, yet we expect more than one answer. We can only convert the result into a list with a single element, so the output is necessarily wrong. + msg = createException(MAL, "pyapi.eval", "Invalid result object. Need list of size %d containing numpy arrays", pci->retc); + goto wrapup; + } + } + //now check the first entry of the pResult + pColO = PyList_GetItem(pResult, 0); + if (!IsPyArrayObject(pColO, 1)) + { + //the first entry isn't a PyArrayObject! Then lets make it a double PyList! PyObject *list = PyList_New(1); PyList_SetItem(list, 0, pResult); pResult = list; } - else + + if (PyList_Size(pResult) != pci->retc) { - //it is neither a PyList nor a PyArrayObject, so throw an error + //wrong return size, we expect pci->retc arrays msg = createException(MAL, "pyapi.eval", "Invalid result object. Need list of size %d containing numpy arrays", pci->retc); goto wrapup; } } + else + { + msg = createException(MAL, "pyapi.eval", "Invalid result object. No result object could be generated."); + goto wrapup; + } // delete the function again PyRun_SimpleString("del pyfun"); } - // collect the return values for (i = 0; i < pci->retc; i++) { PyArrayObject *pCol = NULL; @@ -504,7 +474,6 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st PyObject *pMask = NULL; PyObject * pColO = PyList_GetItem(pResult, i); int bat_type = ATOMstorage(getColumnType(getArgType(mb,pci,i))); - bool isbool; // TODO null handling switch (bat_type) { @@ -534,77 +503,37 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st break; case TYPE_str: - pCol = (PyArrayObject*) PyArray_FromAny(pColO, \ - NULL, 1, 1, NPY_ARRAY_CARRAY | \ _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list