[PD-cvs] externals/grill/py/source pymeth.cpp, NONE, 1.1 clmeth.cpp, 1.21, 1.22 modmeth.cpp, 1.20, 1.21 py.cpp, 1.26, 1.27 pyargs.cpp, 1.16, 1.17 pybase.cpp, 1.1, 1.2 pybase.h, 1.1, 1.2 pyext.cpp, 1.35, 1.36 pysymbol.cpp, 1.2, 1.3

Thomas Grill xovo at users.sourceforge.net
Sat Jul 9 15:03:36 CEST 2005


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 at 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;
  }
  





More information about the Pd-cvs mailing list