From 35a59e7dbce7f5cd6fb8c26e40fc66dfd8384cce Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Mon, 18 Jul 2005 18:03:12 +0000 Subject: python-like dotted module.function syntax cleaned up float vs. int pyext tags better definition of output values (atoms, lists, anythings) multiply inlets for py (hot and cold inlets) better exception handling and error message fixes for atomic pyext._outlet messages svn path=/trunk/; revision=3358 --- externals/grill/py/source/clmeth.cpp | 1 - externals/grill/py/source/py.cpp | 21 +++--- externals/grill/py/source/pyargs.cpp | 121 +++++++++++++++++++---------------- externals/grill/py/source/pybase.cpp | 24 ++++++- externals/grill/py/source/pybase.h | 21 +++++- externals/grill/py/source/pyext.cpp | 17 ++--- externals/grill/py/source/pyext.h | 2 +- externals/grill/py/source/pymeth.cpp | 18 ++---- 8 files changed, 128 insertions(+), 97 deletions(-) (limited to 'externals/grill/py/source') 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(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"); -- cgit v1.2.1