diff options
Diffstat (limited to 'externals/grill/py')
-rw-r--r-- | externals/grill/py/pd/methods-1.pd | 22 | ||||
-rw-r--r-- | externals/grill/py/readme.txt | 2 | ||||
-rw-r--r-- | externals/grill/py/source/clmeth.cpp | 1 | ||||
-rw-r--r-- | externals/grill/py/source/py.cpp | 21 | ||||
-rw-r--r-- | externals/grill/py/source/pyargs.cpp | 121 | ||||
-rw-r--r-- | externals/grill/py/source/pybase.cpp | 24 | ||||
-rw-r--r-- | externals/grill/py/source/pybase.h | 21 | ||||
-rw-r--r-- | externals/grill/py/source/pyext.cpp | 17 | ||||
-rw-r--r-- | externals/grill/py/source/pyext.h | 2 | ||||
-rw-r--r-- | externals/grill/py/source/pymeth.cpp | 18 |
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");
|