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

Reply via email to