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(a)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;
}