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
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list