Update of /cvsroot/pure-data/externals/grill/py/source In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4239/source
Modified Files: clmeth.cpp modmeth.cpp py.cpp pyargs.cpp pybase.cpp pybase.h pyext.cpp pysymbol.cpp Added Files: pymeth.cpp Log Message: python-like dotted module.function syntax reworked outbound message generation (now with symbols instead of one-element anythings) multiply inlets for py (hot and cold inlets) cleaned up float vs. int pyext tags pymeth object for object methods enable built-in functions sequence protocol for symbol type enabled built-in functions py: allow all callables
Index: pysymbol.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pysymbol.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** pysymbol.cpp 19 Jan 2005 04:58:36 -0000 1.2 --- pysymbol.cpp 9 Jul 2005 13:03:34 -0000 1.3 *************** *** 82,85 **** --- 82,168 ---- }
+ + static int symbol_length(pySymbol *self) + { + return strlen(flext::GetString(self->sym)); + } + + static PyObject *symbol_item(pySymbol *self, int i) + { + const char *str = flext::GetString(self->sym); + int len = strlen(str); + if(i < 0) i += len; + + if(i >= 0 && i < len) + return PyString_FromStringAndSize(str+i,1); + else { + Py_INCREF(Py_None); + return Py_None; + } + } + + static PyObject *symbol_slice(pySymbol *self,int ilow = 0,int ihigh = 1<<(sizeof(int)*8-2)) + { + const char *str = flext::GetString(self->sym); + int len = strlen(str); + if(ilow < 0) { + ilow += len; + if(ilow < 0) ilow = 0; + } + if(ihigh < 0) ihigh += len; + if(ihigh >= len) ihigh = len-1; + + return PyString_FromStringAndSize(str+ilow,ilow <= ihigh?ihigh-ilow+1:0); + } + + static PyObject *symbol_concat(pySymbol *self,PyObject *op) + { + PyObject *nobj = symbol_slice(self); // take all + if(nobj) { + PyObject *ret = PySequence_Concat(nobj,op); + Py_DECREF(nobj); + return ret; + } + else + return NULL; + } + + static PyObject *symbol_repeat(pySymbol *self,int rep) + { + PyObject *nobj = symbol_slice(self); // take all + if(nobj) { + PyObject *ret = PySequence_Repeat(nobj,rep); + Py_DECREF(nobj); + return ret; + } + else + return NULL; + } + + static PySequenceMethods symbol_as_seq = { + (inquiry)symbol_length, /* inquiry sq_length; __len__ */ + (binaryfunc)symbol_concat, /* __add__ */ + (intargfunc)symbol_repeat, /* __mul__ */ + (intargfunc)symbol_item, /* intargfunc sq_item; __getitem__ */ + (intintargfunc)symbol_slice, /* intintargfunc sq_slice; __getslice__ */ + NULL, /* intobjargproc sq_ass_item; __setitem__ */ + NULL, /* intintobjargproc sq_ass_slice; __setslice__ */ + }; + + static PyObject *symbol_iter(PyObject *obj) + { + pySymbol *self = (pySymbol *)obj; + PyObject *nobj = symbol_slice(self); + if(nobj) { + PyObject *it = PyObject_GetIter(nobj); + Py_DECREF(nobj); + return it; + } + else + return NULL; + } + + + PyTypeObject pySymbol_Type = { PyObject_HEAD_INIT(NULL) *************** *** 95,99 **** symbol_repr, /*tp_repr*/ 0, /*tp_as_number*/ ! 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ symbol_hash, /*tp_hash */ --- 178,182 ---- symbol_repr, /*tp_repr*/ 0, /*tp_as_number*/ ! &symbol_as_seq, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ symbol_hash, /*tp_hash */ *************** *** 109,113 **** symbol_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ ! 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ --- 192,196 ---- symbol_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ ! symbol_iter, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */
Index: pyargs.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pyargs.cpp,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** pyargs.cpp 8 Jul 2005 14:30:31 -0000 1.16 --- pyargs.cpp 9 Jul 2005 13:03:34 -0000 1.17 *************** *** 18,22 **** if(flext::IsSymbol(at)) return pySymbol_FromSymbol(flext::GetSymbol(at)); ! /* else if(flext::CanbeInt(at) || flext::CanbeFloat(at)) { // if a number can be an integer... let it be an integer! --- 18,22 ---- if(flext::IsSymbol(at)) return pySymbol_FromSymbol(flext::GetSymbol(at)); ! #if 1 else if(flext::CanbeInt(at) || flext::CanbeFloat(at)) { // if a number can be an integer... let it be an integer! *************** *** 25,34 **** return (double)ival == fval?PyInt_FromLong(ival):PyFloat_FromDouble(fval); } ! */ else if(flext::IsFloat(at)) return PyFloat_FromDouble(flext::GetFloat(at)); else if(flext::IsInt(at)) return PyInt_FromLong(flext::GetInt(at)); ! return NULL; } --- 25,34 ---- return (double)ival == fval?PyInt_FromLong(ival):PyFloat_FromDouble(fval); } ! #else else if(flext::IsFloat(at)) return PyFloat_FromDouble(flext::GetFloat(at)); else if(flext::IsInt(at)) return PyInt_FromLong(flext::GetInt(at)); ! #endif return NULL; } *************** *** 100,104 **** // ok! } ! else if(argc == 1 && IsAtom(s)) ret = MakePyAtom(*argv); else { --- 100,105 ---- // ok! } ! else if(argc == 1 && !IsAnything(s)) ! // convert atoms and one-element lists ret = MakePyAtom(*argv); else { *************** *** 126,130 **** }
! bool pybase::GetPyArgs(AtomList &lst,PyObject *pValue,int offs) { if(pValue == NULL) return false; --- 127,131 ---- }
! const t_symbol *pybase::GetPyArgs(AtomList &lst,PyObject *pValue,int offs) { if(pValue == NULL) return false; *************** *** 133,137 ****
int rargc = 0; - bool ok = true; retval tp = nothing;
--- 134,137 ---- *************** *** 153,156 **** --- 153,158 ---- lst(offs+rargc);
+ const t_symbol *sym = NULL; + for(int ix = 0; ix < rargc; ++ix) { PyObject *arg; *************** *** 161,169 ****
t_atom &at = lst[offs+ix]; ! if(PyInt_Check(arg)) SetInt(at,PyInt_AsLong(arg)); ! else if(PyLong_Check(arg)) SetInt(at,PyLong_AsLong(arg)); ! else if(PyFloat_Check(arg)) SetFloat(at,(float)PyFloat_AsDouble(arg)); ! else if(pySymbol_Check(arg)) SetSymbol(at,pySymbol_AS_SYMBOL(arg)); ! else if(PyString_Check(arg)) SetString(at,PyString_AS_STRING(arg)); /* else if(ix == 0 && self && PyInstance_Check(arg)) { --- 163,171 ----
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)) { *************** *** 181,185 **** Py_XDECREF(stp); Py_XDECREF(tp); ! ok = false; }
--- 183,188 ---- Py_XDECREF(stp); Py_XDECREF(tp); ! ! SetSymbol(at,sym__); sym = sym_symbol; }
*************** *** 188,204 **** }
! return ok; }
! bool pybase::GetPyAtom(AtomList &lst,PyObject *obj) { size_t atom = PyAtom::Register(obj); size_t szat = sizeof(atom)/2;
! lst(1+szat); ! SetSymbol(lst[0],symatom); for(size_t i = 0; i < szat; ++i,atom >>= 16) ! flext::SetInt(lst[i+1],(int)(atom&((1<<16)-1))); ! return true; } --- 191,208 ---- }
! if(sym && tp == sequ) sym = sym_list; ! ! return sym; }
! const t_symbol *pybase::GetPyAtom(AtomList &lst,PyObject *obj) { size_t atom = PyAtom::Register(obj); size_t szat = sizeof(atom)/2;
! lst(szat); for(size_t i = 0; i < szat; ++i,atom >>= 16) ! flext::SetInt(lst[i],(int)(atom&((1<<16)-1))); ! return symatom; }
--- NEW FILE: pymeth.cpp --- /*
py/pyext - python script object for PD and Max/MSP
Copyright (c)2002-2005 Thomas Grill (gr@grrrr.org) For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "license.txt," in this distribution.
*/
#include "pybase.h" #include <map>
struct xlt { const t_symbol *from,*to; };
static const xlt xtdefs[] = { { flext::MakeSymbol("+"),flext::MakeSymbol("__add__") }, { flext::MakeSymbol("+="),flext::MakeSymbol("__iadd__") }, { flext::MakeSymbol("!+"),flext::MakeSymbol("__radd__") }, { flext::MakeSymbol("-"),flext::MakeSymbol("__sub__") }, { flext::MakeSymbol("-="),flext::MakeSymbol("__isub__") }, { flext::MakeSymbol("!-"),flext::MakeSymbol("__rsub__") }, { flext::MakeSymbol("*"),flext::MakeSymbol("__mul__") }, { flext::MakeSymbol("*="),flext::MakeSymbol("__imul__") }, { flext::MakeSymbol("!*"),flext::MakeSymbol("__rmul__") }, { flext::MakeSymbol("/"),flext::MakeSymbol("__div__") }, { flext::MakeSymbol("/="),flext::MakeSymbol("__idiv__") }, { flext::MakeSymbol("!/"),flext::MakeSymbol("__rdiv__") }, { flext::MakeSymbol("//"),flext::MakeSymbol("__floordiv__") }, { flext::MakeSymbol("//="),flext::MakeSymbol("__ifloordiv__") }, { flext::MakeSymbol("!//"),flext::MakeSymbol("__rfloordiv__") }, { flext::MakeSymbol("%"),flext::MakeSymbol("__mod__") }, { flext::MakeSymbol("%="),flext::MakeSymbol("__imod__") }, { flext::MakeSymbol("!%"),flext::MakeSymbol("__rmod__") }, { flext::MakeSymbol("**"),flext::MakeSymbol("__pow__") }, { flext::MakeSymbol("**="),flext::MakeSymbol("__ipow__") }, { flext::MakeSymbol("!**"),flext::MakeSymbol("__rpow__") }, { flext::MakeSymbol("&"),flext::MakeSymbol("__and__") }, { flext::MakeSymbol("&="),flext::MakeSymbol("__iand__") }, { flext::MakeSymbol("!&"),flext::MakeSymbol("__rand__") }, { flext::MakeSymbol("|"),flext::MakeSymbol("__or__") }, { flext::MakeSymbol("|="),flext::MakeSymbol("__ior__") }, { flext::MakeSymbol("!|"),flext::MakeSymbol("__ror__") }, { flext::MakeSymbol("^"),flext::MakeSymbol("__xor__") }, { flext::MakeSymbol("^="),flext::MakeSymbol("__ixor__") }, { flext::MakeSymbol("!^"),flext::MakeSymbol("__rxor__") }, { flext::MakeSymbol("<<"),flext::MakeSymbol("__lshift__") }, { flext::MakeSymbol("<<="),flext::MakeSymbol("__ilshift__") }, { flext::MakeSymbol("!<<"),flext::MakeSymbol("__rlshift__") }, { flext::MakeSymbol(">>"),flext::MakeSymbol("__rshift__") }, { flext::MakeSymbol(">>="),flext::MakeSymbol("__irshift__") }, { flext::MakeSymbol("!>>"),flext::MakeSymbol("__rrshift__") }, { flext::MakeSymbol("=="),flext::MakeSymbol("__eq__") }, { flext::MakeSymbol("!="),flext::MakeSymbol("__ne__") }, { flext::MakeSymbol("<"),flext::MakeSymbol("__lt__") }, { flext::MakeSymbol(">"),flext::MakeSymbol("__gt__") }, { flext::MakeSymbol("<="),flext::MakeSymbol("__le__") }, { flext::MakeSymbol(">="),flext::MakeSymbol("__ge__") }, { flext::MakeSymbol("!"),flext::MakeSymbol("__nonzero__") }, { flext::MakeSymbol("~"),flext::MakeSymbol("__invert__") }, { flext::MakeSymbol("[]"),flext::MakeSymbol("__getitem__") }, { flext::MakeSymbol("[]="),flext::MakeSymbol("__setitem__") }, { flext::MakeSymbol("[:]"),flext::MakeSymbol("__getslice__") }, { flext::MakeSymbol("[:]="),flext::MakeSymbol("__setslice__") },
{ flext::MakeSymbol(".abs"),flext::MakeSymbol("__abs__") }, { flext::MakeSymbol(".neg"),flext::MakeSymbol("__neg__") }, { flext::MakeSymbol(".pos"),flext::MakeSymbol("__pos__") }, { flext::MakeSymbol(".divmod"),flext::MakeSymbol("__divmod__") },
{ flext::MakeSymbol(".int"),flext::MakeSymbol("__int__") }, { flext::MakeSymbol(".long"),flext::MakeSymbol("__long__") }, { flext::MakeSymbol(".float"),flext::MakeSymbol("__float__") }, { flext::MakeSymbol(".complex"),flext::MakeSymbol("__complex__") }, { flext::MakeSymbol(".str"),flext::MakeSymbol("__str__") }, { flext::MakeSymbol(".coerce"),flext::MakeSymbol("__coerce__") },
{ flext::MakeSymbol(".doc"),flext::MakeSymbol("__doc__") }, { flext::MakeSymbol(".repr"),flext::MakeSymbol("__repr__") },
{ flext::MakeSymbol(".len"),flext::MakeSymbol("__len__") }, { flext::MakeSymbol(".in"),flext::MakeSymbol("__contains") },
{ NULL,NULL } // sentinel };
typedef std::map<const t_symbol *,const t_symbol *> XTable; static XTable xtable;
class pymeth : public pybase , public flext_base { FLEXT_HEADER_S(pymeth,flext_base,Setup)
public: pymeth(int argc,const t_atom *argv); ~pymeth();
protected: virtual void Exit();
virtual bool CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv); virtual void CbClick();
void m_help();
void m_reload() { Reload(); } void m_reload_(int argc,const t_atom *argv) { args(argc,argv); Reload(); } void m_set(int argc,const t_atom *argv); void m_dir_() { m__dir(function); } void m_doc_() { m__doc(function); }
const t_symbol *funname; PyObject *function;
virtual void LoadModule(); virtual void UnloadModule();
virtual void Load(); virtual void Unload();
void SetFunction(const t_symbol *func); void ResetFunction();
virtual bool thrcall(void *data); virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv);
PyObject **objects;
private:
virtual bool callpy(PyObject *fun,PyObject *args);
static void Setup(t_classid c);
FLEXT_CALLBACK(m_help) FLEXT_CALLBACK(m_reload) FLEXT_CALLBACK_V(m_reload_) FLEXT_CALLBACK_V(m_set) FLEXT_CALLBACK(m_dir_) FLEXT_CALLBACK(m_doc_)
// callbacks FLEXT_ATTRVAR_I(detach) FLEXT_ATTRVAR_B(xlate) FLEXT_ATTRVAR_B(respond)
FLEXT_CALLBACK_V(m_stop) FLEXT_CALLBACK(m_dir) FLEXT_CALLGET_V(mg_dir) FLEXT_CALLBACK(m_doc)
#ifdef FLEXT_THREADS FLEXT_CALLBACK_T(tick) FLEXT_THREAD(threadworker) FLEXT_THREAD_X(work_wrapper) #else FLEXT_CALLBACK_X(work_wrapper) #endif };
FLEXT_LIB_V("pym",pymeth)
void pymeth::Setup(t_classid c) { FLEXT_CADDMETHOD_(c,0,"doc",m_doc); FLEXT_CADDMETHOD_(c,0,"dir",m_dir); #ifdef FLEXT_THREADS FLEXT_CADDATTR_VAR1(c,"detach",detach); FLEXT_CADDMETHOD_(c,0,"stop",m_stop); #endif
FLEXT_CADDMETHOD_(c,0,"help",m_help); FLEXT_CADDMETHOD_(c,0,"reload",m_reload_); FLEXT_CADDMETHOD_(c,0,"reload.",m_reload); FLEXT_CADDMETHOD_(c,0,"doc+",m_doc_); FLEXT_CADDMETHOD_(c,0,"dir+",m_dir_);
FLEXT_CADDMETHOD_(c,0,"set",m_set);
FLEXT_CADDATTR_VAR1(c,"xlate",xlate); FLEXT_CADDATTR_VAR1(c,"respond",respond);
// init translation map for(const xlt *xi = xtdefs; xi->from; ++xi) xtable[xi->from] = xi->to; }
pymeth::pymeth(int argc,const t_atom *argv) : funname(NULL) , function(NULL) , objects(NULL) { #ifdef FLEXT_THREADS FLEXT_ADDTIMER(stoptmr,tick); // launch thread worker FLEXT_CALLMETHOD(threadworker); #endif
PyThreadState *state = PyLockSys();
int inlets; if(argc && CanbeInt(*argv)) { inlets = GetAInt(*argv); if(inlets < 1) inlets = 1; argv++,argc--; } else inlets = 1;
objects = new PyObject *[inlets]; for(int i = 0; i < inlets; ++i) { objects[i] = Py_None; Py_INCREF(Py_None); }
if(inlets <= 0) InitProblem();
AddInAnything(1+(inlets < 0?1:inlets)); AddOutAnything();
Register(GetRegistry(REGNAME));
if(argc) { const t_symbol *funnm = GetASymbol(*argv); argv++,argc--;
if(funnm) SetFunction(funnm); else PyErr_SetString(PyExc_ValueError,"Invalid function name"); }
if(argc) args(argc,argv);
Report();
PyUnlock(state); }
pymeth::~pymeth() { if(objects) { for(int i = 0; i < CntIn()-1; ++i) Py_DECREF(objects[i]); delete[] objects; }
PyThreadState *state = PyLockSys(); Unregister(GetRegistry(REGNAME)); Report(); PyUnlock(state); }
void pymeth::Exit() { pybase::Exit(); flext_base::Exit(); }
void pymeth::m_set(int argc,const t_atom *argv) { PyThreadState *state = PyLockSys();
// function name has precedence if(argc >= 2) { const char *sn = GetAString(*argv); ++argv,--argc;
if(sn) { if(!module || !strcmp(sn,PyModule_GetName(module))) { ImportModule(sn); Register(GetRegistry(REGNAME)); } } else PyErr_SetString(PyExc_ValueError,"Invalid module name"); }
if(argc) { const t_symbol *fn = GetASymbol(*argv); if(fn) SetFunction(fn); else PyErr_SetString(PyExc_ValueError,"Invalid function name"); }
Report();
PyUnlock(state); }
void pymeth::m_help() { post(""); post("%s %s - python method object, (C)2002-2005 Thomas Grill",thisName(),PY__VERSION); #ifdef FLEXT_DEBUG post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__); #endif
post("Arguments: %s [method name] {args...}",thisName());
post("Inlet 1:messages to control the py object"); post(" 2:call python function with message as argument(s)"); post("Outlet: 1:return values from python function"); post("Methods:"); post("\thelp: shows this help"); post("\tbang: call script without arguments"); post("\tset [script name] [function name]: set (script and) function name"); post("\treload {args...}: reload python script"); post("\treload. : reload with former arguments"); post("\tdoc: display module doc string"); post("\tdoc+: display function doc string"); post("\tdir: dump module dictionary"); post("\tdir+: dump function dictionary"); #ifdef FLEXT_THREADS post("\tdetach 0/1/2: detach threads"); post("\tstop {wait time (ms)}: stop threads"); #endif post(""); }
void pymeth::ResetFunction() { Py_XDECREF(function); function = NULL;
if(funname && objects[0] != Py_None) { function = PyObject_GetAttrString(objects[0],(char *)GetString(funname)); // new reference if(!function) PyErr_SetString(PyExc_AttributeError,"Method not found"); }
// exception could be set here }
void pymeth::SetFunction(const t_symbol *func) { // look for method name in translation table XTable::iterator it = xtable.find(func); funname = it == xtable.end()?func:it->second;
ResetFunction(); }
void pymeth::LoadModule() { SetFunction(funname); }
void pymeth::UnloadModule() { }
void pymeth::Load() { ResetFunction(); }
void pymeth::Unload() { SetFunction(NULL); }
bool 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(); Py_DECREF(ret); return true; } }
bool pymeth::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv) { if(n == 0 && s != sym_bang) return flext_base::CbMethodResort(n,s,argc,argv);
PyThreadState *state = PyLock();
bool ret = false;
if(n >= 1) { // store args PyObject *&obj = objects[n-1]; Py_DECREF(obj); obj = MakePyArg(s,argc,argv); // steal reference
if(n > 1) ret = true; // just store, don't trigger }
if(!ret) { if(function) { PyObject *self = PyMethod_Self(function); PyErr_Clear(); if(!self || self->ob_type != objects[0]->ob_type) // type has changed, search for new method ResetFunction(); else if(self != objects[0]) { // type hasn't changed, but object has PyObject *f = function; function = PyMethod_New(PyMethod_GET_FUNCTION(f),objects[0],PyMethod_GET_CLASS(f)); Py_DECREF(f); } } else ResetFunction();
if(function) { Py_INCREF(function);
int inlets = CntIn()-1; PyObject *pargs = PyTuple_New(inlets-1); for(int i = 1; i < inlets; ++i) { Py_INCREF(objects[i]); PyTuple_SET_ITEM(pargs,i-1,objects[i]); }
ret = gencall(function,pargs); // references are stolen } else PyErr_SetString(PyExc_RuntimeError,"No function set");
Report(); }
PyUnlock(state);
Respond(ret);
return ret; }
void pymeth::CbClick() { pybase::OpenEditor(); }
void pymeth::DumpOut(const t_symbol *sym,int argc,const t_atom *argv) { ToOutAnything(GetOutAttr(),sym?sym:thisTag(),argc,argv); }
bool pymeth::thrcall(void *data) { return FLEXT_CALLMETHOD_X(work_wrapper,data); }
Index: modmeth.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/modmeth.cpp,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -d -r1.20 -r1.21 *** modmeth.cpp 8 Jul 2005 14:30:31 -0000 1.20 --- modmeth.cpp 9 Jul 2005 13:03:34 -0000 1.21 *************** *** 129,139 ****
AtomListStatic<16> lst; ! if(GetPyArgs(lst,val)) { ! bool ok; ! if(lst.Count() && IsSymbol(lst[0])) ! ok = Forward(recv,GetSymbol(lst[0]),lst.Count()-1,lst.Atoms()+1); ! else ! ok = Forward(recv,lst); ! #ifdef FLEXT_DEBUG if(!ok) --- 129,135 ----
AtomListStatic<16> lst; ! const t_symbol *sym = GetPyArgs(lst,val); ! if(sym) { ! bool ok = Forward(recv,sym,lst.Count(),lst.Atoms()); #ifdef FLEXT_DEBUG if(!ok)
Index: clmeth.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/clmeth.cpp,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** clmeth.cpp 8 Jul 2005 14:30:30 -0000 1.21 --- clmeth.cpp 9 Jul 2005 13:03:34 -0000 1.22 *************** *** 183,187 **** o += ext->sigoutlets;
! if(ext->OutObject(ext,o,val)) ok = true; else --- 183,187 ---- o += ext->sigoutlets;
! if(ext->OutObject(ext,o-1,val)) ok = true; else *************** *** 296,304 ****
flext::AtomListStatic<16> lst; ! if(GetPyArgs(lst,val)) { t_glist *gl = ext->thisCanvas(); //canvas_getcurrent(); t_class **cl = (t_pd *)gl; if(cl) ! pd_forwardmess(cl,lst.Count(),lst.Atoms()); #ifdef FLEXT_DEBUG else --- 296,305 ----
flext::AtomListStatic<16> lst; ! const t_symbol *sym = GetPyArgs(lst,val); ! if(sym) { t_glist *gl = ext->thisCanvas(); //canvas_getcurrent(); t_class **cl = (t_pd *)gl; if(cl) ! pd_forwardmess(cl,lst.Count(),lst.Atoms()); #ifdef FLEXT_DEBUG else
Index: pybase.h =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pybase.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pybase.h 8 Jul 2005 14:30:31 -0000 1.1 --- pybase.h 9 Jul 2005 13:03:34 -0000 1.2 *************** *** 27,32 **** static PyObject *MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet = -1); static PyObject *MakePyArg(const t_symbol *s,int argc,const t_atom *argv); ! static bool GetPyArgs(AtomList &lst,PyObject *pValue,int offs = 0); ! static bool GetPyAtom(AtomList &lst,PyObject *pValue);
static void lib_setup(); --- 27,32 ---- static PyObject *MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet = -1); static PyObject *MakePyArg(const t_symbol *s,int argc,const t_atom *argv); ! static const t_symbol *GetPyArgs(AtomList &lst,PyObject *pValue,int offs = 0); ! static const t_symbol *GetPyAtom(AtomList &lst,PyObject *pValue);
static void lib_setup(); *************** *** 95,98 **** --- 95,99 ----
static PyObject *module_obj,*module_dict; + static PyObject *builtins_obj,*builtins_dict; static PyMethodDef func_tbl[];
*************** *** 162,165 **** --- 163,168 ---- #endif
+ static const t_symbol *sym_fint; // float or int symbol, depending on native number message type + public:
Index: pybase.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pybase.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pybase.cpp 8 Jul 2005 14:30:31 -0000 1.1 --- pybase.cpp 9 Jul 2005 13:03:34 -0000 1.2 *************** *** 63,66 **** --- 63,70 ---- PyObject *pybase::module_dict = NULL;
+ PyObject *pybase::builtins_obj = NULL; + PyObject *pybase::builtins_dict = NULL; + + const t_symbol *pybase::sym_fint = NULL;
// ----------------------------------------------------------------------------------------------------------- *************** *** 129,132 **** --- 133,139 ---- }
+ builtins_obj = PyImport_ImportModule("__builtin__"); + builtins_dict = PyModule_GetDict(builtins_obj); // borrowed reference + // add symbol type initsymbol(); *************** *** 145,151 **** --- 152,165 ---- PyModule_AddObject(module_obj,"Buffer",(PyObject *)&pySamplebuffer_Type);
+ #if FLEXT_SYS == FLEXT_SYS_PD + sym_fint = sym_float; + #else + sym_fint = sym_int; + #endif + // -------------------------------------------------------------
FLEXT_SETUP(pyobj); + FLEXT_SETUP(pymeth); FLEXT_SETUP(pyext); FLEXT_DSP_SETUP(pydsp); *************** *** 214,219 **** PyErr_Print(); // no method found else { ! if(!GetPyArgs(lst,pvar)) post("py/pyext - Argument list could not be created"); Py_DECREF(pvar); } --- 228,236 ---- PyErr_Print(); // no method found else { ! const t_symbol *sym = GetPyArgs(lst,pvar); ! if(!sym) post("py/pyext - Argument list could not be created"); + else + FLEXT_ASSERT(sym == sym_list); Py_DECREF(pvar); } *************** *** 295,301 **** bool pybase::ImportModule(const char *name) { ! if(!name) return false; ! if(modname == name) return true; ! modname = name; return ReloadModule(); } --- 312,321 ---- bool pybase::ImportModule(const char *name) { ! if(name) { ! if(modname == name) return true; ! modname = name; ! } ! else ! modname.clear(); return ReloadModule(); } *************** *** 322,328 ****
SetArgs(); ! PyObject *newmod = module ! ?PyImport_ReloadModule(module) ! :PyImport_ImportModule((char *)modname.c_str());
if(!newmod) { --- 342,356 ----
SetArgs(); ! PyObject *newmod; ! ! if(modname.length()) ! newmod = module ! ?PyImport_ReloadModule(module) ! :PyImport_ImportModule((char *)modname.c_str()); ! else { ! // if no module name given, take py module ! newmod = module_obj; ! Py_INCREF(newmod); ! }
if(!newmod) { *************** *** 416,428 **** { flext::AtomListStatic<16> lst; ! if(xlate?GetPyArgs(lst,obj):GetPyAtom(lst,obj)) { // call to outlet _outside_ the Mutex lock! // otherwise (if not detached) deadlock will occur ! if(lst.Count() && IsSymbol(lst[0])) ! ext->ToOutAnything(o,GetSymbol(lst[0]),lst.Count()-1,lst.Atoms()+1); ! else if(lst.Count() > 1) ! ext->ToOutList(o,lst); ! else ! ext->ToOutAtom(o,lst[0]); return true; } --- 444,452 ---- { flext::AtomListStatic<16> lst; ! const t_symbol *sym = xlate?GetPyArgs(lst,obj):GetPyAtom(lst,obj); ! if(sym) { // call to outlet _outside_ the Mutex lock! // otherwise (if not detached) deadlock will occur ! ext->ToOutAnything(o,sym,lst.Count(),lst.Atoms()); return true; }
Index: pyext.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pyext.cpp,v retrieving revision 1.35 retrieving revision 1.36 diff -C2 -d -r1.35 -r1.36 *** pyext.cpp 8 Jul 2005 14:30:31 -0000 1.35 --- pyext.cpp 9 Jul 2005 13:03:34 -0000 1.36 *************** *** 421,425 **** if(pvar) { flext::AtomListStatic<16> lst; ! if(GetPyArgs(lst,pvar,1)) { // dump value to attribute outlet SetSymbol(lst[0],s); --- 421,427 ---- if(pvar) { flext::AtomListStatic<16> lst; ! const t_symbol *sym = GetPyArgs(lst,pvar,1); ! if(sym) { ! FLEXT_ASSERT(!IsAnything(sym)); // dump value to attribute outlet SetSymbol(lst[0],s); *************** *** 470,474 **** bool pyext::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv) { ! return (pyobj && n >= 1 && work(n,s,argc,argv)) || flext_dsp::CbMethodResort(n,s,argc,argv); }
--- 472,479 ---- bool pyext::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv) { ! if(!n) ! return flext_dsp::CbMethodResort(n,s,argc,argv); ! ! return pyobj && work(n,s,argc,argv); }
Index: py.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/py.cpp,v retrieving revision 1.26 retrieving revision 1.27 diff -C2 -d -r1.26 -r1.27 *** py.cpp 8 Jul 2005 14:30:31 -0000 1.26 --- py.cpp 9 Jul 2005 13:03:34 -0000 1.27 *************** *** 45,49 **** virtual void Unload();
! bool SetFunction(const char *func); bool ResetFunction();
--- 45,49 ---- virtual void Unload();
! bool SetFunction(const t_symbol *func); bool ResetFunction();
*************** *** 123,131 **** PyThreadState *state = PyLockSys();
! int inlets = -1; // -1 signals non-explicit definition if(argc && CanbeInt(*argv)) { inlets = GetAInt(*argv); argv++,argc--; }
if(inlets >= 1) { --- 123,135 ---- PyThreadState *state = PyLockSys();
! int inlets; if(argc && CanbeInt(*argv)) { inlets = GetAInt(*argv); + if(inlets < 1) inlets = 1; argv++,argc--; } + else + // -1 signals non-explicit definition + inlets = -1;
if(inlets >= 1) { *************** *** 137,141 **** AddOutAnything();
! const char *funnm = NULL;
// init script module --- 141,145 ---- AddOutAnything();
! const t_symbol *funnm = NULL;
// init script module *************** *** 152,164 **** char *pt = strrchr(modnm,'.'); // search for last dot if(pt && *pt) { ! funnm = pt+1; *pt = 0; - }
! char dir[1024]; ! GetModulePath(modnm,dir,sizeof(dir)); ! AddToPath(dir);
! ImportModule(modnm); } else --- 156,177 ---- char *pt = strrchr(modnm,'.'); // search for last dot if(pt && *pt) { ! funnm = MakeSymbol(pt+1); *pt = 0;
! #if 0 ! if(!*modnm) ! // if module name is empty set it to __builtin__ ! strcpy(modnm,"__builtin__"); ! #endif ! }
! if(*modnm) { ! char dir[1024]; ! GetModulePath(modnm,dir,sizeof(dir)); ! AddToPath(dir); ! ImportModule(modnm); ! } ! else ! ImportModule(NULL); } else *************** *** 170,174 **** if(funnm || argc) { if(!funnm) { ! funnm = GetAString(*argv); argv++,argc--; } --- 183,187 ---- if(funnm || argc) { if(!funnm) { ! funnm = GetASymbol(*argv); argv++,argc--; } *************** *** 226,230 ****
if(argc) { ! const char *fn = GetAString(*argv); if(fn) SetFunction(fn); --- 239,243 ----
if(argc) { ! const t_symbol *fn = GetASymbol(*argv); if(fn) SetFunction(fn); *************** *** 270,285 **** bool pyobj::ResetFunction() { function = NULL;
! if(!module || !dict) ! post("%s - No module loaded",thisName()); else { if(funname) { function = PyDict_GetItemString(dict,(char *)GetString(funname)); // borrowed!!! if(!function) PyErr_SetString(PyExc_AttributeError,"Function not found"); ! else if(!PyFunction_Check(function)) { function = NULL; ! PyErr_SetString(PyExc_TypeError,"Attribute is not a function"); } } --- 283,304 ---- bool pyobj::ResetFunction() { + // function was borrowed from dict! function = NULL;
! if(!dict) ! post("%s - No namespace available",thisName()); else { if(funname) { function = PyDict_GetItemString(dict,(char *)GetString(funname)); // borrowed!!! + + if(!function && dict == module_dict) + // search also in __builtins__ + function = PyDict_GetItemString(builtins_dict,(char *)GetString(funname)); // borrowed!!! + if(!function) PyErr_SetString(PyExc_AttributeError,"Function not found"); ! else if(!PyCallable_Check(function)) { function = NULL; ! PyErr_SetString(PyExc_TypeError,"Attribute is not callable"); } } *************** *** 290,297 **** }
! bool pyobj::SetFunction(const char *func) { if(func) { ! funname = MakeSymbol(func); withfunction = ResetFunction(); } --- 309,316 ---- }
! bool pyobj::SetFunction(const t_symbol *func) { if(func) { ! funname = func; withfunction = ResetFunction(); } *************** *** 308,312 **** void pyobj::LoadModule() { ! SetFunction(funname?GetString(funname):NULL); }
--- 327,331 ---- void pyobj::LoadModule() { ! SetFunction(funname); }
*************** *** 343,350 **** bool pyobj::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv) { bool ret = false;
- if(n == 0 && s != sym_bang) goto end; - if(objects && n >= 1) { // store args --- 362,372 ---- bool pyobj::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv) { + if(n == 0 && s != sym_bang) + return flext_base::CbMethodResort(n,s,argc,argv); + + PyThreadState *state = PyLock(); + bool ret = false;
if(objects && n >= 1) { // store args *************** *** 353,401 **** obj = MakePyArg(s,argc,argv); // steal reference
! if(n > 1) { ! ret = true; // just store, don't trigger ! goto end; ! } }
! PyThreadState *state = PyLock(); ! ! if(withfunction) { ! if(function) { ! Py_INCREF(function);
! PyObject *pargs; ! ! if(objects) { ! int inlets = CntIn()-1; ! pargs = PyTuple_New(inlets); ! for(int i = 0; i < inlets; ++i) { ! Py_INCREF(objects[i]); ! PyTuple_SET_ITEM(pargs,i,objects[i]); } ! } ! else ! // construct tuple from args ! pargs = MakePyArgs(s,argc,argv);
! ret = gencall(function,pargs); // references are stolen } ! else ! PyErr_SetString(PyExc_RuntimeError,"No function set"); ! } ! else if(module) { ! // no function defined as creation argument -> use message tag ! if(s) { ! PyObject *func = PyObject_GetAttrString(module,const_cast<char *>(GetString(s))); ! if(func) { ! PyObject *pargs = MakePyArgs(sym_list,argc,argv); ! ret = gencall(func,pargs); } } - else - PyErr_SetString(PyExc_RuntimeError,"No function set"); - }
! Report();
PyUnlock(state); --- 375,421 ---- obj = MakePyArg(s,argc,argv); // steal reference
! if(n > 1) ret = true; // just store, don't trigger }
! if(!ret) { ! if(withfunction) { ! if(function) { ! Py_INCREF(function);
! PyObject *pargs; ! ! if(objects) { ! int inlets = CntIn()-1; ! pargs = PyTuple_New(inlets); ! for(int i = 0; i < inlets; ++i) { ! Py_INCREF(objects[i]); ! PyTuple_SET_ITEM(pargs,i,objects[i]); ! } } ! else ! // construct tuple from args ! // if n == 0, it's a pure bang ! pargs = MakePyArgs(n?s:NULL,argc,argv);
! ret = gencall(function,pargs); // references are stolen ! } ! else ! PyErr_SetString(PyExc_RuntimeError,"No function set"); } ! else if(module) { ! // no function defined as creation argument -> use message tag ! if(s) { ! PyObject *func = PyObject_GetAttrString(module,const_cast<char *>(GetString(s))); ! if(func) { ! PyObject *pargs = MakePyArgs(sym_list,argc,argv); ! ret = gencall(func,pargs); ! } } + else + PyErr_SetString(PyExc_RuntimeError,"No function set"); }
! Report(); ! }
PyUnlock(state); *************** *** 403,408 **** Respond(ret);
! end: ! return ret || flext_base::CbMethodResort(n,s,argc,argv); }
--- 423,427 ---- Respond(ret);
! return ret; }