From 29416a643b9c3d19a60b91b37a263d300c11486b Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Sat, 9 Jul 2005 13:03:34 +0000 Subject: 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 svn path=/trunk/; revision=3310 --- externals/grill/py/source/py.cpp | 137 ++++++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 59 deletions(-) (limited to 'externals/grill/py/source/py.cpp') diff --git a/externals/grill/py/source/py.cpp b/externals/grill/py/source/py.cpp index d007f0c3..7cb7fa97 100644 --- a/externals/grill/py/source/py.cpp +++ b/externals/grill/py/source/py.cpp @@ -44,7 +44,7 @@ protected: virtual void Load(); virtual void Unload(); - bool SetFunction(const char *func); + bool SetFunction(const t_symbol *func); bool ResetFunction(); virtual bool thrcall(void *data); @@ -122,11 +122,15 @@ pyobj::pyobj(int argc,const t_atom *argv) PyThreadState *state = PyLockSys(); - int inlets = -1; // -1 signals non-explicit definition + 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) { objects = new PyObject *[inlets]; @@ -136,7 +140,7 @@ pyobj::pyobj(int argc,const t_atom *argv) AddInAnything(1+(inlets < 0?1:inlets)); AddOutAnything(); - const char *funnm = NULL; + const t_symbol *funnm = NULL; // init script module if(argc) { @@ -151,15 +155,24 @@ pyobj::pyobj(int argc,const t_atom *argv) char *pt = strrchr(modnm,'.'); // search for last dot if(pt && *pt) { - funnm = pt+1; + funnm = MakeSymbol(pt+1); *pt = 0; - } - char dir[1024]; - GetModulePath(modnm,dir,sizeof(dir)); - AddToPath(dir); +#if 0 + if(!*modnm) + // if module name is empty set it to __builtin__ + strcpy(modnm,"__builtin__"); +#endif + } - ImportModule(modnm); + if(*modnm) { + char dir[1024]; + GetModulePath(modnm,dir,sizeof(dir)); + AddToPath(dir); + ImportModule(modnm); + } + else + ImportModule(NULL); } else PyErr_SetString(PyExc_ValueError,"Invalid module name"); @@ -169,7 +182,7 @@ pyobj::pyobj(int argc,const t_atom *argv) if(funnm || argc) { if(!funnm) { - funnm = GetAString(*argv); + funnm = GetASymbol(*argv); argv++,argc--; } @@ -225,7 +238,7 @@ void pyobj::m_set(int argc,const t_atom *argv) } if(argc) { - const char *fn = GetAString(*argv); + const t_symbol *fn = GetASymbol(*argv); if(fn) SetFunction(fn); else @@ -269,18 +282,24 @@ void pyobj::m_help() bool pyobj::ResetFunction() { + // function was borrowed from dict! function = NULL; - if(!module || !dict) - post("%s - No module loaded",thisName()); + 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(!PyFunction_Check(function)) { + else if(!PyCallable_Check(function)) { function = NULL; - PyErr_SetString(PyExc_TypeError,"Attribute is not a function"); + PyErr_SetString(PyExc_TypeError,"Attribute is not callable"); } } } @@ -289,10 +308,10 @@ bool pyobj::ResetFunction() return function != NULL; } -bool pyobj::SetFunction(const char *func) +bool pyobj::SetFunction(const t_symbol *func) { if(func) { - funname = MakeSymbol(func); + funname = func; withfunction = ResetFunction(); } else { @@ -307,7 +326,7 @@ bool pyobj::SetFunction(const char *func) void pyobj::LoadModule() { - SetFunction(funname?GetString(funname):NULL); + SetFunction(funname); } void pyobj::UnloadModule() @@ -342,68 +361,68 @@ bool pyobj::callpy(PyObject *fun,PyObject *args) 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(n == 0 && s != sym_bang) goto end; - if(objects && 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 - goto end; - } + if(n > 1) ret = true; // just store, don't trigger } - 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]); + 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 - pargs = MakePyArgs(s,argc,argv); + 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 + ret = gencall(function,pargs); // references are stolen + } + else + PyErr_SetString(PyExc_RuntimeError,"No function set"); } - 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(GetString(s))); - if(func) { - PyObject *pargs = MakePyArgs(sym_list,argc,argv); - ret = gencall(func,pargs); + else if(module) { + // no function defined as creation argument -> use message tag + if(s) { + PyObject *func = PyObject_GetAttrString(module,const_cast(GetString(s))); + if(func) { + PyObject *pargs = MakePyArgs(sym_list,argc,argv); + ret = gencall(func,pargs); + } } + else + PyErr_SetString(PyExc_RuntimeError,"No function set"); } - else - PyErr_SetString(PyExc_RuntimeError,"No function set"); - } - Report(); + Report(); + } PyUnlock(state); Respond(ret); -end: - return ret || flext_base::CbMethodResort(n,s,argc,argv); + return ret; } void pyobj::CbClick() { pybase::OpenEditor(); } -- cgit v1.2.1