aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/py
diff options
context:
space:
mode:
Diffstat (limited to 'externals/grill/py')
-rw-r--r--externals/grill/py/pd/methods-1.pd22
-rw-r--r--externals/grill/py/readme.txt2
-rw-r--r--externals/grill/py/source/clmeth.cpp1
-rw-r--r--externals/grill/py/source/py.cpp21
-rw-r--r--externals/grill/py/source/pyargs.cpp121
-rw-r--r--externals/grill/py/source/pybase.cpp24
-rw-r--r--externals/grill/py/source/pybase.h21
-rw-r--r--externals/grill/py/source/pyext.cpp17
-rw-r--r--externals/grill/py/source/pyext.h2
-rw-r--r--externals/grill/py/source/pymeth.cpp18
10 files changed, 141 insertions, 108 deletions
diff --git a/externals/grill/py/pd/methods-1.pd b/externals/grill/py/pd/methods-1.pd
index 8d49f319..ab949c7e 100644
--- a/externals/grill/py/pd/methods-1.pd
+++ b/externals/grill/py/pd/methods-1.pd
@@ -1,24 +1,24 @@
-#N canvas 540 469 714 349 12;
+#N canvas 540 469 718 353 12;
#X obj 16 13 cnv 15 650 40 empty empty py/pyext 10 22 0 24 -260818
-1 0;
#X text 235 16 Python script objects \, (C)2003-2005 Thomas Grill;
#X text 235 32 http://grrrr.org/ext;
#X symbolatom 21 139 10 0 0 0 - - -;
#X symbolatom 25 298 10 0 0 0 - - -;
-#X obj 25 252 pym upper;
#X obj 22 179 py .str @xlate 0;
#X text 93 167 convert the symbol to a Python string;
#X text 35 216 pass it as a true Python object;
-#X text 105 251 use string.upper method;
-#X obj 363 252 py string.upper;
-#X symbolatom 364 288 10 0 0 0 - - -;
-#X text 495 254 use module function;
+#X symbolatom 364 295 10 0 0 0 - - -;
+#X text 462 269 use module function;
#X text 23 119 enter some text;
#X text 21 73 Py can act on Python objects in a object-oriented manner
;
#X text 93 184 using the built-in str function;
-#X connect 3 0 6 1;
-#X connect 5 0 4 0;
-#X connect 6 0 5 1;
-#X connect 6 0 10 1;
-#X connect 10 0 11 0;
+#X obj 25 252 pym swapcase;
+#X text 63 270 use swapcase method;
+#X obj 363 250 py string.swapcase;
+#X connect 3 0 5 1;
+#X connect 5 0 13 1;
+#X connect 5 0 15 1;
+#X connect 13 0 4 0;
+#X connect 15 0 8 0;
diff --git a/externals/grill/py/readme.txt b/externals/grill/py/readme.txt
index c36a081b..9213786d 100644
--- a/externals/grill/py/readme.txt
+++ b/externals/grill/py/readme.txt
@@ -96,6 +96,8 @@ Version history:
- ADD: py: enable Python built-in functions (like range, str etc.)
- ADD: sequence protocol for symbol type
- FIX: cleanup for outbound messages (e.g. symbol atoms instead of one-element general messages)
+- FIX: better exception handling (no longer leaves reference to function object) and cleared misleading error message
+- FIX: better definition of output values for atoms, lists and anythings
0.2.0:
- ADD: handling of Python threads
diff --git a/externals/grill/py/source/clmeth.cpp b/externals/grill/py/source/clmeth.cpp
index 3d740bcb..0dff50e9 100644
--- a/externals/grill/py/source/clmeth.cpp
+++ b/externals/grill/py/source/clmeth.cpp
@@ -167,7 +167,6 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args)
pyext *ext = GetThis(self);
PyObject *val;
- bool tp;
#if 0
if(sz == 3) {
val = PyTuple_GET_ITEM(args,2); // borrow reference
diff --git a/externals/grill/py/source/py.cpp b/externals/grill/py/source/py.cpp
index da9459fe..4b7c2bdc 100644
--- a/externals/grill/py/source/py.cpp
+++ b/externals/grill/py/source/py.cpp
@@ -54,7 +54,7 @@ protected:
private:
- virtual bool callpy(PyObject *fun,PyObject *args);
+ virtual void callpy(PyObject *fun,PyObject *args);
static void Setup(t_classid c);
@@ -343,19 +343,12 @@ void pyobj::Unload()
SetFunction(NULL);
}
-bool pyobj::callpy(PyObject *fun,PyObject *args)
+void pyobj::callpy(PyObject *fun,PyObject *args)
{
PyObject *ret = PyObject_CallObject(fun,args);
- if(ret == NULL) {
- // function not found resp. arguments not matching
- PyErr_Print();
- return false;
- }
- else {
- if(!OutObject(this,0,ret) && PyErr_Occurred())
- PyErr_Print();
+ if(ret) {
+ OutObject(this,0,ret); // exception might be raised here
Py_DECREF(ret);
- return true;
}
}
@@ -397,7 +390,8 @@ bool pyobj::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv)
// if n == 0, it's a pure bang
pargs = MakePyArgs(n?s:NULL,argc,argv);
- ret = gencall(function,pargs); // references are stolen
+ gencall(function,pargs); // references are stolen
+ ret = true;
}
else
PyErr_SetString(PyExc_RuntimeError,"No function set");
@@ -408,7 +402,8 @@ bool pyobj::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv)
PyObject *func = PyObject_GetAttrString(module,const_cast<char *>(GetString(s)));
if(func) {
PyObject *pargs = MakePyArgs(sym_list,argc,argv);
- ret = gencall(func,pargs);
+ gencall(func,pargs);
+ ret = true;
}
}
else
diff --git a/externals/grill/py/source/pyargs.cpp b/externals/grill/py/source/pyargs.cpp
index 2957801d..2cdfdade 100644
--- a/externals/grill/py/source/pyargs.cpp
+++ b/externals/grill/py/source/pyargs.cpp
@@ -126,6 +126,47 @@ PyObject *pybase::MakePyArg(const t_symbol *s,int argc,const t_atom *argv)
return ret;
}
+inline bool issym(PyObject *p)
+{
+ return PyString_Check(p) || pySymbol_Check(p);
+}
+
+inline bool isseq(PyObject *p)
+{
+ return PySequence_Check(p) && !issym(p);
+}
+
+const t_symbol *pybase::getone(t_atom &at,PyObject *arg)
+{
+ if(PyInt_Check(arg)) { flext::SetInt(at,PyInt_AsLong(arg)); return sym_fint; }
+ else if(PyLong_Check(arg)) { flext::SetInt(at,PyLong_AsLong(arg)); return sym_fint; }
+ else if(PyFloat_Check(arg)) { flext::SetFloat(at,(float)PyFloat_AsDouble(arg)); return flext::sym_float; }
+ else if(pySymbol_Check(arg)) { flext::SetSymbol(at,pySymbol_AS_SYMBOL(arg)); return flext::sym_symbol; }
+ else if(PyString_Check(arg)) { flext::SetString(at,PyString_AS_STRING(arg)); return flext::sym_symbol; }
+ else {
+ PyObject *tp = PyObject_Type(arg);
+ PyObject *stp = tp?PyObject_Str(tp):NULL;
+ char *tmp = "";
+ if(stp) tmp = PyString_AS_STRING(stp);
+ flext::post("py/pyext: Could not convert argument %s",tmp);
+ Py_XDECREF(stp);
+ Py_XDECREF(tp);
+
+ flext::SetSymbol(at,flext::sym__);
+ return sym_symbol;
+ }
+}
+
+const t_symbol *pybase::getlist(t_atom *lst,PyObject *seq,int cnt,int offs)
+{
+ for(int ix = 0; ix < cnt; ++ix) {
+ PyObject *arg = PySequence_GetItem(seq,ix+offs); // new reference
+ getone(lst[ix],arg);
+ Py_DECREF(arg);
+ }
+ return flext::sym_list;
+}
+
const t_symbol *pybase::GetPyArgs(AtomList &lst,PyObject *pValue,int offs)
{
if(pValue == NULL) return false;
@@ -134,66 +175,36 @@ const t_symbol *pybase::GetPyArgs(AtomList &lst,PyObject *pValue,int offs)
if(pValue == Py_None) return sym_bang;
// analyze return value or tuple
-
int rargc = 0;
- retval tp = nothing;
+ const t_symbol *sym = NULL;
- if(PyString_Check(pValue) || pySymbol_Check(pValue)) {
- rargc = 1;
- tp = atom;
- }
- else if(PySequence_Check(pValue)) {
- rargc = PySequence_Size(pValue);
- tp = sequ;
+ if(isseq(pValue)) {
+ int rargc = PySequence_Size(pValue);
+ if(rargc == 2) {
+ // check if syntax is symbol/string, list -> anything message
+ PyObject *s = PySequence_GetItem(pValue,0);
+ PyObject *l = PySequence_GetItem(pValue,1);
+
+ if(issym(s) && isseq(l)) {
+ // is anything message
+ rargc = PySequence_Size(l);
+ lst(offs+rargc);
+ getlist(lst.Atoms(),l,rargc);
+ sym = pyObject_AsSymbol(s);
+ }
+
+ Py_DECREF(s);
+ Py_DECREF(l);
+ }
+ else {
+ lst(offs+rargc);
+ sym = getlist(lst.Atoms(),pValue,rargc);
+ }
}
else {
- rargc = 1;
- tp = atom;
+ lst(offs+1);
+ sym = getone(lst[offs],pValue);
}
-// else
-// Py_DECREF(pValue);
-
- lst(offs+rargc);
-
- const t_symbol *sym = NULL;
-
- for(int ix = 0; ix < rargc; ++ix) {
- PyObject *arg;
- if(tp == sequ)
- arg = PySequence_GetItem(pValue,ix); // new reference
- else
- arg = pValue;
-
- t_atom &at = lst[offs+ix];
- if(PyInt_Check(arg)) { SetInt(at,PyInt_AsLong(arg)); sym = sym_fint; }
- else if(PyLong_Check(arg)) { SetInt(at,PyLong_AsLong(arg)); sym = sym_fint; }
- else if(PyFloat_Check(arg)) { SetFloat(at,(float)PyFloat_AsDouble(arg)); sym = sym_float; }
- else if(pySymbol_Check(arg)) { SetSymbol(at,pySymbol_AS_SYMBOL(arg)); sym = sym_symbol; }
- else if(PyString_Check(arg)) { SetString(at,PyString_AS_STRING(arg)); sym = sym_symbol; }
-/*
- else if(ix == 0 && self && PyInstance_Check(arg)) {
- // assumed to be self ... that should be checked _somehow_ !!!
- Py_INCREF(arg);
- *self = arg;
- }
-*/
- else {
- PyObject *tp = PyObject_Type(arg);
- PyObject *stp = tp?PyObject_Str(tp):NULL;
- char *tmp = "";
- if(stp) tmp = PyString_AS_STRING(stp);
- post("py/pyext: Could not convert argument %s",tmp);
- Py_XDECREF(stp);
- Py_XDECREF(tp);
-
- SetSymbol(at,sym__); sym = sym_symbol;
- }
-
- if(tp == sequ)
- Py_DECREF(arg);
- }
-
- if(sym && tp == sequ) sym = sym_list;
return sym;
}
diff --git a/externals/grill/py/source/pybase.cpp b/externals/grill/py/source/pybase.cpp
index 3bc589de..65c4369d 100644
--- a/externals/grill/py/source/pybase.cpp
+++ b/externals/grill/py/source/pybase.cpp
@@ -568,7 +568,7 @@ bool pybase::gencall(PyObject *pmeth,PyObject *pargs)
// Now call method
switch(detach) {
case 0:
- ret = callpy(pmeth,pargs);
+ ret = docall(pmeth,pargs);
Py_DECREF(pargs);
Py_DECREF(pmeth);
break;
@@ -591,6 +591,24 @@ bool pybase::gencall(PyObject *pmeth,PyObject *pargs)
return ret;
}
+void pybase::exchandle()
+{
+#if 0
+ // want to use that, but exception keeps a reference to the object
+ PyErr_Print();
+#else
+ // must use that instead... clear the exception
+ PyObject *type,*value,*traceback;
+ PyErr_Fetch(&type,&value,&traceback);
+ PyErr_NormalizeException(&type,&value,&traceback);
+ PyErr_Display(type,value,traceback);
+
+ Py_XDECREF(type);
+ Py_XDECREF(value);
+ Py_XDECREF(traceback);
+#endif
+}
+
void pybase::work_wrapper(void *data)
{
FLEXT_ASSERT(data);
@@ -603,7 +621,7 @@ void pybase::work_wrapper(void *data)
// call worker
work_data *w = (work_data *)data;
- callpy(w->fun,w->args);
+ docall(w->fun,w->args);
delete w;
PyUnlock(state);
@@ -634,7 +652,7 @@ void pybase::threadworker()
while(el = qufifo.Get()) {
++thrcount;
state = PyLock(my);
- callpy(el->fun,el->args);
+ docall(el->fun,el->args);
Py_XDECREF(el->fun);
Py_XDECREF(el->args);
PyUnlock(state);
diff --git a/externals/grill/py/source/pybase.h b/externals/grill/py/source/pybase.h
index 068aeb86..f7b6840b 100644
--- a/externals/grill/py/source/pybase.h
+++ b/externals/grill/py/source/pybase.h
@@ -89,7 +89,7 @@ protected:
static bool IsAnything(const t_symbol *s) { return s && s != sym_float && s != sym_int && s != sym_symbol && s != sym_list && s != sym_pointer; }
static bool IsAtom(const t_symbol *s) { return s == sym_float || s == sym_int || s == sym_symbol || s == sym_pointer; }
- enum retval { nothing,atom,sequ };
+// enum retval { nothing,atom,sequ };
// --- module stuff -----
@@ -136,8 +136,22 @@ protected:
bool xlate;
bool gencall(PyObject *fun,PyObject *args);
+
+ bool docall(PyObject *fun,PyObject *args)
+ {
+ callpy(fun,args);
+ if(PyErr_Occurred()) {
+ exchandle();
+ return false;
+ }
+ else
+ return true;
+ }
+
virtual bool thrcall(void *data) = 0;
- virtual bool callpy(PyObject *fun,PyObject *args) = 0;
+ virtual void callpy(PyObject *fun,PyObject *args) = 0;
+
+ void exchandle();
#if FLEXT_SYS == FLEXT_SYS_MAX
static short patcher_myvol(t_patcher *x);
@@ -164,6 +178,9 @@ protected:
static const t_symbol *sym_fint; // float or int symbol, depending on native number message type
+ static const t_symbol *getone(t_atom &at,PyObject *arg);
+ static const t_symbol *getlist(t_atom *lst,PyObject *seq,int cnt,int offs = 0);
+
public:
#ifdef FLEXT_THREADS
diff --git a/externals/grill/py/source/pyext.cpp b/externals/grill/py/source/pyext.cpp
index 593c8bd1..a48a45ed 100644
--- a/externals/grill/py/source/pyext.cpp
+++ b/externals/grill/py/source/pyext.cpp
@@ -506,18 +506,13 @@ void pyext::m_help()
post("");
}
-bool pyext::callpy(PyObject *fun,PyObject *args)
+void pyext::callpy(PyObject *fun,PyObject *args)
{
PyObject *ret = PyObject_CallObject(fun,args);
- if(ret == NULL) {
- // function not found resp. arguments not matching
- PyErr_Print();
- return false;
- }
- else {
+ if(ret) {
+ // function worked fine
if(!PyObject_Not(ret)) post("pyext - returned value is ignored");
Py_DECREF(ret);
- return true;
}
}
@@ -536,8 +531,10 @@ bool pyext::call(const char *meth,int inlet,const t_symbol *s,int argc,const t_a
PyErr_Print();
Py_DECREF(pmeth);
}
- else
- ret = gencall(pmeth,pargs);
+ else {
+ gencall(pmeth,pargs);
+ ret = true;
+ }
}
return ret;
}
diff --git a/externals/grill/py/source/pyext.h b/externals/grill/py/source/pyext.h
index 7fe0cc68..361eda5d 100644
--- a/externals/grill/py/source/pyext.h
+++ b/externals/grill/py/source/pyext.h
@@ -114,7 +114,7 @@ private:
bool call(const char *meth,int inlet,const t_symbol *s,int argc,const t_atom *argv);
virtual bool thrcall(void *data);
- virtual bool callpy(PyObject *fun,PyObject *args);
+ virtual void callpy(PyObject *fun,PyObject *args);
static bool stcallpy(PyObject *fun,PyObject *args);
PyThreadState *pythr;
diff --git a/externals/grill/py/source/pymeth.cpp b/externals/grill/py/source/pymeth.cpp
index 8c80bd43..e2278d1c 100644
--- a/externals/grill/py/source/pymeth.cpp
+++ b/externals/grill/py/source/pymeth.cpp
@@ -131,7 +131,7 @@ protected:
private:
- virtual bool callpy(PyObject *fun,PyObject *args);
+ virtual void callpy(PyObject *fun,PyObject *args);
static void Setup(t_classid c);
@@ -360,19 +360,12 @@ void pymeth::Unload()
SetFunction(NULL);
}
-bool pymeth::callpy(PyObject *fun,PyObject *args)
+void pymeth::callpy(PyObject *fun,PyObject *args)
{
PyObject *ret = PyObject_CallObject(fun,args);
- if(ret == NULL) {
- // function not found resp. arguments not matching
- PyErr_Print();
- return false;
- }
- else {
- if(ret != Py_None && !OutObject(this,0,ret) && PyErr_Occurred())
- PyErr_Print();
+ if(ret) {
+ OutObject(this,0,ret); // exception might be raised here
Py_DECREF(ret);
- return true;
}
}
@@ -421,7 +414,8 @@ bool pymeth::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv)
PyTuple_SET_ITEM(pargs,i-1,objects[i]);
}
- ret = gencall(function,pargs); // references are stolen
+ gencall(function,pargs); // references are stolen
+ ret = true;
}
else
PyErr_SetString(PyExc_RuntimeError,"No function set");