Changeset: 297602a0648d for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=297602a0648d Added Files: monetdb5/extras/pyapi/Tests/pyapi03.malC Modified Files: monetdb5/extras/pyapi/Tests/All monetdb5/extras/pyapi/Tests/pyapi01.malC monetdb5/extras/pyapi/Tests/pyapi02.malC monetdb5/extras/pyapi/pyapi.c Branch: pyapi Log Message:
Added boolean support. diffs (truncated from 462 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,3 +1,4 @@ HAVE_LIBPY?pyapi00 HAVE_LIBPY?pyapi01 HAVE_LIBPY?pyapi02 +HAVE_LIBPY?pyapi03 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,8 +1,23 @@ + + +#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); +io.print(rbool); + #strings testing bstr:= bat.new(:oid,:str); bat.append(bstr,"asdf":str); bat.append(bstr,"sd asd asd asd asd a":str); -bat.append(bstr,"":str); +bat.append(bstr,nil:str); bat.append(bstr,"test":str); rstr:bat[:oid,:str] := pyapi.eval(nil:ptr,"return(arg1)",bstr); io.print(rstr); 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 @@ -27,7 +27,7 @@ bat.append(bsht,82:sht); bat.append(bsht,0:sht); bat.append(bsht,240:sht); bat.append(bsht,nil:sht); -rsht:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"return([numpy.add(arg1.filled(0),1)])",bsht); +rsht:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"return([numpy.add(arg1,1)])",bsht); io.print(rsht); bint:= bat.new(:oid,:int); @@ -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); @@ -73,7 +73,7 @@ bat.append(bflt,846.930886:flt); bat.append(bflt,16.81692777:flt); bat.append(bflt,1714636.915:flt); bat.append(bflt,nil:flt); -rflt:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"return([numpy.add(arg1.filled(0),1)])",bflt); +rflt:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"return([numpy.add(arg1,1)])",bflt); io.print(rflt); bdbl:= bat.new(:oid,:dbl); @@ -82,19 +82,34 @@ 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 -#bstr:= bat.new(:oid,:str); -#bat.append(bstr,"asdf":str); -#bat.append(bstr,"sd asd asd asd asd a":str); -#bat.append(bstr,"":str); -#bat.append(bstr,"test":str); -#rstr:bat[:oid,:int] := pyapi.eval(nil:ptr,"print(arg1);\nreturn([arg1])",bstr); +bstr:= bat.new(:oid,:str); +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); +#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); +io.print(rbool); # output types testing diff --git a/monetdb5/extras/pyapi/Tests/pyapi03.malC b/monetdb5/extras/pyapi/Tests/pyapi03.malC new file mode 100644 --- /dev/null +++ b/monetdb5/extras/pyapi/Tests/pyapi03.malC @@ -0,0 +1,26 @@ +# input types testing + +# inty types + + +#single-value array gives segmentation fault +rstr:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"return [55]"); +io.print(rstr); + +bstr:= bat.new(:oid,:int); +bat.append(bstr,55:int); +bat.append(bstr,44:int); +bat.append(bstr,23:int); +bat.append(bstr,nil:int); +rstr:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"print numpy.mean(numpy.add(arg1, 50))\nreturn([[numpy.mean(numpy.add(arg1, 50))]])",bstr); +io.print(rstr); + + +bdbl:= bat.new(:oid,:dbl); +bat.append(bdbl,55:dbl); +bat.append(bdbl,44:dbl); +bat.append(bdbl,23.33:dbl); +bat.append(bdbl,nil:dbl); +io.print(bdbl); +rdbl:bat[:oid,:dbl] := pyapi.eval(nil:ptr,"print numpy.mean(numpy.add(arg1, 50))\nreturn([[numpy.mean(numpy.add(arg1, 50))]])",bdbl); +io.print(rdbl); 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 @@ -49,24 +49,42 @@ static int pyapiInitialized = FALSE; NPY_ARRAY_CARRAY || !NPY_ARRAY_WRITEABLE, NULL); #define NP_TO_BAT(bat, mtpe, nptpe) { \ - PyArrayObject* pCol = (PyArrayObject*) PyArray_FromAny(pColO, \ + pCol = (PyArrayObject*) PyArray_FromAny(pColO, \ PyArray_DescrFromType(nptpe), 1, 1, NPY_ARRAY_CARRAY | \ NPY_ARRAY_FORCECAST, NULL); \ - size_t cnt = 0; \ if (pCol == NULL) \ { \ pCol = (PyArrayObject*) PyArray_FromAny(pColO, NULL, 1, 1, NPY_ARRAY_CARRAY, NULL); \ msg = createException(MAL, "pyapi.eval", "Wrong return type in python function. Expected an array of type \"%s\" as return value, but the python function returned an array of type \"%s\".", #mtpe, NPYConstToString(PyArray_DTYPE(pCol)->type_num)); \ goto wrapup; \ } \ - cnt = PyArray_DIMS(pCol)[0], j; \ - bat = BATnew(TYPE_void, TYPE_##mtpe, cnt, TRANSIENT); \ + count = PyArray_DIMS(pCol)[0]; \ + bat = BATnew(TYPE_void, TYPE_##mtpe, count, TRANSIENT); \ + pMask = PyObject_GetAttrString(pColO, "mask"); \ + if (pMask != NULL) \ + { \ + pMaskArray = (PyArrayObject*) PyArray_FromAny(pMask, NPY_BOOL, 1, 1, NPY_ARRAY_CARRAY, NULL); \ + if (pMaskArray == NULL || PyArray_DIMS(pMaskArray)[0] != (int)count) \ + { \ + msg = createException(MAL, "pyapi.eval", "A masked array was returned, but the mask does not have the same length as the array."); \ + goto wrapup; \ + } \ + } \ + } +#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; \ - for (j =0; j < cnt; j++) { \ - ((mtpe*) Tloc(bat, BUNfirst(bat)))[j] = \ - *(mtpe*) PyArray_GETPTR1(pCol, j); } \ - BATsetcount(bat, cnt); } + for (j =0; j < count; j++) \ + { \ + ((mtpe*) Tloc(bat, BUNfirst(bat)))[j] = *(mtpe*) PyArray_GETPTR1(pCol, j); \ + if (pMaskArray != NULL && PyArray_GETITEM(pMaskArray, PyArray_GETPTR1(pMaskArray, j)) == Py_True) \ + { \ + bat->T->nil = 1; \ + ((mtpe*) Tloc(bat, BUNfirst(bat)))[j] = mtpe##_nil; \ + \ + } \ + } bat->T->nonil = 1 - bat->T->nil; \ + BATsetcount(bat, count); } //todo: NULL // TODO: also handle the case if someone returns a masked array @@ -226,9 +244,57 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st if (strlen(t) > maxsize) 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, @@ -251,7 +317,7 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st } break; case TYPE_hge: - vararray = BAT_TO_NP(b, hge, NPY_LONGLONG); + vararray = BAT_TO_NP(b, hge, NPY_LONGDOUBLE); break; // TODO: implement other types (boolean) @@ -413,6 +479,9 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st { //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) PyObject *list = PyList_New(1); PyList_SetItem(list, 0, pResult); pResult = list; @@ -431,67 +500,111 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st // collect the return values for (i = 0; i < pci->retc; i++) { PyArrayObject *pCol = NULL; + PyArrayObject *pMaskArray = NULL; _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list