aboutsummaryrefslogtreecommitdiff
path: root/externals
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2005-04-18 15:11:43 +0000
committerThomas Grill <xovo@users.sourceforge.net>2005-04-18 15:11:43 +0000
commit14719fd1f8cc2384398168788357930e29bde5c4 (patch)
tree8e7abc2070a13d6a40abd9a1d46b5c4688329249 /externals
parentf61347eda1d8f25fa6eb6542bd7eea32d894b6b2 (diff)
check for PD version
better reload handling, but still far fom perfect fixed minor other issues fixed buglet fixing strange gcc behavior updates for DSP processing better argument checking svn path=/trunk/; revision=2781
Diffstat (limited to 'externals')
-rw-r--r--externals/grill/py/pd/simple-1.pd4
-rw-r--r--externals/grill/py/readme.txt1
-rw-r--r--externals/grill/py/source/bound.cpp5
-rw-r--r--externals/grill/py/source/clmeth.cpp37
-rw-r--r--externals/grill/py/source/main.cpp81
-rw-r--r--externals/grill/py/source/main.h35
-rw-r--r--externals/grill/py/source/py.cpp48
-rw-r--r--externals/grill/py/source/pydsp.cpp2
-rw-r--r--externals/grill/py/source/pyext.cpp62
-rw-r--r--externals/grill/py/source/pyext.h12
-rw-r--r--externals/grill/py/source/register.cpp70
11 files changed, 260 insertions, 97 deletions
diff --git a/externals/grill/py/pd/simple-1.pd b/externals/grill/py/pd/simple-1.pd
index d34d43b5..e3ef6754 100644
--- a/externals/grill/py/pd/simple-1.pd
+++ b/externals/grill/py/pd/simple-1.pd
@@ -1,4 +1,4 @@
-#N canvas 156 192 670 397 12;
+#N canvas 156 192 674 401 12;
#X obj 53 123 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X floatatom 52 155 5 0 0 0 - - -;
@@ -25,6 +25,7 @@ file.;
-1 0;
#X text 213 32 http://grrrr.org/ext;
#X text 213 16 Python script objects \, (C)2003-2005 Thomas Grill;
+#X msg 41 246 reload;
#X connect 0 0 9 1;
#X connect 1 0 9 1;
#X connect 3 0 9 1;
@@ -41,3 +42,4 @@ file.;
#X connect 15 0 9 0;
#X connect 18 0 9 0;
#X connect 19 0 9 0;
+#X connect 23 0 9 0;
diff --git a/externals/grill/py/readme.txt b/externals/grill/py/readme.txt
index 45248f34..526b3299 100644
--- a/externals/grill/py/readme.txt
+++ b/externals/grill/py/readme.txt
@@ -100,6 +100,7 @@ Version history:
- FIX: solved py->py messaging problem with lock count instead of message queuing
- ADD: buffer handling with optional numarray support (if present)
- ADD: new objects for dsp processing: pyext~,pyx~,pyext.~,pyx.~
+- FIX: correctly report Python errors while contructing the object
0.1.4:
- ADD: better (and independent) handling of inlet and outlet count (as class variables or dynamically initialized in __init__)
diff --git a/externals/grill/py/source/bound.cpp b/externals/grill/py/source/bound.cpp
index 1d10c2d3..a5ace4ee 100644
--- a/externals/grill/py/source/bound.cpp
+++ b/externals/grill/py/source/bound.cpp
@@ -174,13 +174,14 @@ void pyext::ClearBinding()
// in case the object couldn't be constructed...
if(!pyobj) return;
- FLEXT_ASSERT(GetThis(pyobj));
+ pyext *th = GetThis(pyobj);
+ FLEXT_ASSERT(th);
void *data = NULL;
const t_symbol *sym = NULL;
// unbind all
- while(GetThis(pyobj)->UnbindMethod(sym,NULL,&data)) {
+ while(th->UnbindMethod(sym,NULL,&data)) {
bounddata *bdt = (bounddata *)data;
if(bdt) {
for(FuncSet::iterator it = bdt->funcs.begin(); it != bdt->funcs.end(); ++it)
diff --git a/externals/grill/py/source/clmeth.cpp b/externals/grill/py/source/clmeth.cpp
index 3f856f57..a8e1ceb7 100644
--- a/externals/grill/py/source/clmeth.cpp
+++ b/externals/grill/py/source/clmeth.cpp
@@ -124,6 +124,10 @@ PyObject* pyext::pyext_getattr(PyObject *,PyObject *args)
pyext *ext = GetThis(self);
if(ext)
ret = PyLong_FromLong(ext->shouldexit?1:0);
+ else {
+ Py_INCREF(Py_True);
+ ret = Py_True;
+ }
}
// post("pyext::getattr %s",sname);
}
@@ -188,23 +192,20 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args)
ext->ToOutList(o-1,lst);
else
ext->ToOutAtom(o-1,*lst.Atoms());
+ ok = true;
}
else
- post("pyext: outlet index out of range");
-
- ok = true;
+ PyErr_SetString(PyExc_ValueError,"pyext - _outlet: index out of range");
}
else
- post("py/pyext - No data to send");
+ PyErr_SetString(PyExc_ValueError,"pyext - _outlet: invalid arguments");
if(!tp) Py_DECREF(val);
}
-
- if(!ok) {
+ else
PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _outlet(self,outlet,args...)");
- return NULL;
- }
+ if(!ok) return NULL;
Py_INCREF(Py_None);
return Py_None;
}
@@ -219,12 +220,16 @@ PyObject *pyext::pyext_detach(PyObject *,PyObject *args)
int val;
if(!PyArg_ParseTuple(args, "Oi:pyext_detach",&self,&val)) {
// handle error
- PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _detach(self,[0/1])");
+ PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _detach(self,[0/1/2])");
+ return NULL;
+ }
+ else if(val < 0 || val > 2) {
+ PyErr_SetString(PyExc_ValueError,"pyext - _detach must be in the range 0..2");
return NULL;
}
else {
pyext *ext = GetThis(self);
- ext->detach = val != 0;
+ ext->detach = val;
}
Py_INCREF(Py_None);
@@ -241,6 +246,10 @@ PyObject *pyext::pyext_stop(PyObject *,PyObject *args)
PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _stop(self,{wait time})");
return NULL;
}
+ else if(val < 0) {
+ PyErr_SetString(PyExc_ValueError,"pyext - _stop time must be >= 0");
+ return NULL;
+ }
else {
pyext *ext = GetThis(self);
int cnt;
@@ -332,6 +341,10 @@ PyObject *pyext::pyext_invec(PyObject *,PyObject *args)
PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _invec(self,inlet)");
return NULL;
}
+ else if(val < 0) {
+ PyErr_SetString(PyExc_ValueError,"pyext - _invec: index out of range");
+ return NULL;
+ }
else {
pyext *ext = GetThis(self);
PyObject *b = ext->GetSig(val,true);
@@ -351,6 +364,10 @@ PyObject *pyext::pyext_outvec(PyObject *,PyObject *args)
PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _outvec(self,inlet)");
return NULL;
}
+ else if(val < 0) {
+ PyErr_SetString(PyExc_ValueError,"pyext - _outvec: index out of range");
+ return NULL;
+ }
else {
pyext *ext = GetThis(self);
PyObject *b = ext->GetSig(val,false);
diff --git a/externals/grill/py/source/main.cpp b/externals/grill/py/source/main.cpp
index fadb0173..fa5169b7 100644
--- a/externals/grill/py/source/main.cpp
+++ b/externals/grill/py/source/main.cpp
@@ -288,12 +288,9 @@ void pybase::SetArgs()
bool pybase::ImportModule(const char *name)
{
if(!name) return false;
-
- SetArgs();
- module = PyImport_ImportModule((char *)name); // increases module_obj ref count by one
- dict = module?PyModule_GetDict(module):NULL;
-
- return module != NULL;
+ if(modname == name) return true;
+ modname = name;
+ return ReloadModule();
}
void pybase::UnimportModule()
@@ -315,22 +312,22 @@ void pybase::UnimportModule()
bool pybase::ReloadModule()
{
bool ok = false;
- if(module) {
- SetArgs();
- PyObject *newmod = PyImport_ReloadModule(module);
- if(!newmod) {
- // old module still exists?!
-// dict = NULL;
- }
- else {
- Py_XDECREF(module);
- module = newmod;
- dict = PyModule_GetDict(module); // borrowed
- ok = true;
- }
+
+ SetArgs();
+ PyObject *newmod = module
+ ?PyImport_ReloadModule(module)
+ :PyImport_ImportModule((char *)modname.c_str());
+
+ if(!newmod) {
+ // unload faulty module
+ if(module) UnimportModule();
+ }
+ else {
+ Py_XDECREF(module);
+ module = newmod;
+ dict = PyModule_GetDict(module); // borrowed
+ ok = true;
}
- else
- post("py/pyext - No module to reload");
return ok;
}
@@ -402,6 +399,48 @@ void pybase::Respond(bool b)
}
}
+void pybase::Reload()
+{
+ PyThreadState *state = PyLockSys();
+
+ PyObject *reg = GetRegistry(REGNAME);
+
+ if(reg) {
+ PyObject *key;
+ int pos = 0;
+ while(PyDict_Next(reg,&pos,&key,NULL)) {
+ pybase *th = (pybase *)PyLong_AsLong(key);
+ FLEXT_ASSERT(th);
+ th->Unload();
+ }
+
+ UnloadModule();
+ }
+
+ bool ok = ReloadModule();
+
+ if(ok) {
+ LoadModule();
+
+ if(reg) {
+ SetRegistry(REGNAME,reg);
+
+ PyObject *key;
+ int pos = 0;
+ while(PyDict_Next(reg,&pos,&key,NULL)) {
+ pybase *th = (pybase *)PyLong_AsLong(key);
+ FLEXT_ASSERT(th);
+ th->Load();
+ }
+ }
+ else
+ Load();
+ }
+
+ Report();
+ PyUnlock(state);
+}
+
static PyObject *output = NULL;
diff --git a/externals/grill/py/source/main.h b/externals/grill/py/source/main.h
index b828f47b..23a9ccb0 100644
--- a/externals/grill/py/source/main.h
+++ b/externals/grill/py/source/main.h
@@ -15,17 +15,24 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#include "pysymbol.h"
#include "pybuffer.h"
#include <flcontainers.h>
+#include <string>
#if FLEXT_OS == FLEXT_LINUX || FLEXT_OS == FLEXT_IRIX
#include <unistd.h>
#endif
+#if FLEXT_SYS == FLEXT_SYS_PD && (!defined (PD_MINOR_VERSION) || PD_MINOR_VERSION < 37)
+#error PD version >= 0.37 required, please upgrade!
+#endif
+
#define PY__VERSION "0.2.0pre"
#define PYEXT_MODULE "pyext" // name for module
#define PYEXT_CLASS "_class" // name for base class
+#define REGNAME "_registry"
+
#define PY_STOP_WAIT 100 // ms
#define PY_STOP_TICK 1 // ms
@@ -67,7 +74,8 @@ protected:
void mg_dir(AtomList &lst) { m__dir(module); }
void m_doc() { m__doc(dict); }
- PyObject *module,*dict; // inherited user class module and associated dictionary
+ std::string modname; // module name
+ PyObject *module,*dict; // object module and associated dictionary
static const char *py_doc;
@@ -78,14 +86,29 @@ protected:
void GetModulePath(const char *mod,char *dir,int len);
void AddToPath(const char *dir);
void SetArgs();
+
+ // reload module and all connected objects
+ void Reload();
+
bool ImportModule(const char *name);
void UnimportModule();
bool ReloadModule();
- void Register(const char *reg);
- void Unregister(const char *reg);
- void Reregister(const char *reg);
- virtual bool Reload() = 0;
+ // Get module registry
+ PyObject *GetRegistry(const char *regname);
+ // Set module registry
+ void SetRegistry(const char *regname,PyObject *reg);
+
+ // Register object
+ void Register(PyObject *reg);
+ // Unregister object
+ void Unregister(PyObject *reg);
+
+ virtual void LoadModule() = 0;
+ virtual void UnloadModule() = 0;
+
+ virtual void Load() = 0;
+ virtual void Unload() = 0;
void OpenEditor();
void Respond(bool b);
@@ -199,7 +222,7 @@ public:
inline void Lock() {}
inline void Unlock() {}
- inline PyThreadState *PyLock(PyThreadState *) { return NULL; }
+ inline PyThreadState *PyLock(PyThreadState * = NULL) { return NULL; }
inline PyThreadState *PyLockSys() { return NULL; }
inline void PyUnlock(PyThreadState *st) {}
#endif
diff --git a/externals/grill/py/source/py.cpp b/externals/grill/py/source/py.cpp
index 93309b37..f91d13b6 100644
--- a/externals/grill/py/source/py.cpp
+++ b/externals/grill/py/source/py.cpp
@@ -29,8 +29,8 @@ protected:
void m_help();
- void m_reload();
- void m_reload_(int argc,const t_atom *argv) { args(argc,argv); m_reload(); }
+ 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); }
@@ -48,7 +48,11 @@ protected:
PyObject *function;
bool withfunction;
- virtual bool Reload();
+ virtual void LoadModule();
+ virtual void UnloadModule();
+
+ virtual void Load();
+ virtual void Unload();
bool SetFunction(const char *func);
bool ResetFunction();
@@ -165,7 +169,7 @@ pyobj::pyobj(int argc,const t_atom *argv):
PyErr_SetString(PyExc_ValueError,"Invalid module name");
}
- Register("_py");
+ Register(GetRegistry(REGNAME));
if(argc >= 2) {
const char *fn = GetAString(argv[1]);
@@ -183,7 +187,7 @@ pyobj::pyobj(int argc,const t_atom *argv):
pyobj::~pyobj()
{
PyThreadState *state = PyLockSys();
- Unregister("_py");
+ Unregister(GetRegistry(REGNAME));
Report();
PyUnlock(state);
}
@@ -201,21 +205,6 @@ bool pyobj::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv)
return false;
}
-void pyobj::m_reload()
-{
- PyThreadState *state = PyLockSys();
-
- Unregister("_py");
-
- ReloadModule();
- Reregister("_py");
- Register("_py");
- SetFunction(funname?GetString(funname):NULL);
-
- Report();
- PyUnlock(state);
-}
-
void pyobj::m_set(int argc,const t_atom *argv)
{
PyThreadState *state = PyLockSys();
@@ -228,7 +217,7 @@ void pyobj::m_set(int argc,const t_atom *argv)
if(sn) {
if(!module || !strcmp(sn,PyModule_GetName(module))) {
ImportModule(sn);
- Register("_py");
+ Register(GetRegistry(REGNAME));
}
}
else
@@ -316,10 +305,23 @@ bool pyobj::SetFunction(const char *func)
}
-bool pyobj::Reload()
+void pyobj::LoadModule()
+{
+ SetFunction(funname?GetString(funname):NULL);
+}
+
+void pyobj::UnloadModule()
+{
+}
+
+void pyobj::Load()
{
ResetFunction();
- return true;
+}
+
+void pyobj::Unload()
+{
+ SetFunction(NULL);
}
bool pyobj::callpy(PyObject *fun,PyObject *args)
diff --git a/externals/grill/py/source/pydsp.cpp b/externals/grill/py/source/pydsp.cpp
index cecefbe2..b7459a59 100644
--- a/externals/grill/py/source/pydsp.cpp
+++ b/externals/grill/py/source/pydsp.cpp
@@ -124,7 +124,7 @@ bool pydsp::CbDsp()
if(dspfun) {
PyObject *ret = PyObject_CallObject(dspfun,NULL);
if(ret) {
- dodsp = PyObject_IsTrue(ret);
+ dodsp = PyObject_IsTrue(ret) != 0;
Py_DECREF(ret);
}
else {
diff --git a/externals/grill/py/source/pyext.cpp b/externals/grill/py/source/pyext.cpp
index eb58d1a0..e500e264 100644
--- a/externals/grill/py/source/pyext.cpp
+++ b/externals/grill/py/source/pyext.cpp
@@ -11,6 +11,7 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#include "pyext.h"
#include <flinternal.h>
+
FLEXT_LIB_V("pyext pyext. pyx pyx.",pyext)
@@ -100,6 +101,11 @@ void pyext::SetThis()
/*int ret =*/ PyObject_SetAttrString(pyobj,"_this",th); // ref is taken
}
+void pyext::ClearThis()
+{
+ int ret = PyObject_DelAttrString(pyobj,"_this");
+ FLEXT_ASSERT(ret != -1);
+}
PyObject *pyext::class_obj = NULL;
PyObject *pyext::class_dict = NULL;
@@ -169,7 +175,7 @@ pyext::pyext(int argc,const t_atom *argv,bool sig):
if(strrchr(thisName(),'.')) clname = scr;
}
- Register("_pyext");
+ Register(GetRegistry(REGNAME));
if(argc > apre || clname) {
if(!clname) clname = GetASymbol(argv[apre++]);
@@ -208,6 +214,7 @@ bool pyext::Init()
AddOutAnything(outlets);
}
+ Report();
PyUnlock(state);
return pyobj && flext_dsp::Init();
@@ -219,9 +226,11 @@ void pyext::Exit()
PyThreadState *state = PyLockSys();
DoExit();
- Unregister("_pyext");
+
+ Unregister(GetRegistry(REGNAME));
UnimportModule();
+ Report();
PyUnlock(state);
flext_dsp::Exit();
@@ -229,19 +238,20 @@ void pyext::Exit()
bool pyext::DoInit()
{
- SetThis();
-
// call init now, after _this has been set, which is
// important for eventual callbacks from __init__ to c
PyObject *pargs = MakePyArgs(NULL,initargs.Count(),initargs.Atoms(),-1,true);
if(pargs) {
bool ok = true;
+ SetThis();
+
PyObject *init = PyObject_GetAttrString(pyobj,"__init__"); // get ref
if(init) {
if(PyMethod_Check(init)) {
PyObject *res = PyObject_CallObject(init,pargs);
- if(!res)
+ if(!res)
+ // exception is set
ok = false;
else
Py_DECREF(res);
@@ -278,6 +288,8 @@ void pyext::DoExit()
// _del has not been found - don't care
PyErr_Clear();
+ ClearThis();
+
gcrun = pyobj->ob_refcnt > 1;
Py_DECREF(pyobj); // opposite of SetClssMeth
}
@@ -368,16 +380,19 @@ bool pyext::MakeInstance()
return false;
}
-bool pyext::Reload()
+void pyext::LoadModule()
{
- DoExit();
+}
- // by here, the Python class destructor should have been called!
+void pyext::UnloadModule()
+{
+}
-// SetArgs(0,NULL);
- bool ok = ReloadModule();
-
- if(ok) ok = MakeInstance();
+void pyext::Load()
+{
+ FLEXT_ASSERT(!pyobj);
+
+ bool ok = MakeInstance();
if(ok) {
int inl = -1,outl = -1;
@@ -387,26 +402,13 @@ bool pyext::Reload()
post("%s - Inlet and outlet count can't be changed by reload",thisName());
}
- return ok;
+// return ok;
}
-
-void pyext::m_reload()
-{
- PyThreadState *state = PyLockSys();
-
- Unregister("_pyext"); // self
-
- Reload();
-
- Reregister("_pyext"); // the others
- Register("_pyext"); // self
-
- SetThis();
-
- Report();
-
- PyUnlock(state);
+void pyext::Unload()
+{
+ DoExit();
+ pyobj = NULL;
}
void pyext::m_get(const t_symbol *s)
diff --git a/externals/grill/py/source/pyext.h b/externals/grill/py/source/pyext.h
index c0b5909a..cab0c6a2 100644
--- a/externals/grill/py/source/pyext.h
+++ b/externals/grill/py/source/pyext.h
@@ -61,8 +61,8 @@ protected:
void m_help();
- void m_reload();
- void m_reload_(int argc,const t_atom *argv) { initargs(argc,argv); m_reload(); }
+ void m_reload() { Reload(); }
+ void m_reload_(int argc,const t_atom *argv) { initargs(argc,argv); Reload(); }
void ms_initargs(const AtomList &a) { m_reload_(a.Count(),a.Atoms()); }
void m_dir_() { m__dir(pyobj); }
void mg_dir_(AtomList &lst) { GetDir(pyobj,lst); }
@@ -78,7 +78,12 @@ protected:
flext::AtomListStatic<16> initargs;
- virtual bool Reload();
+ virtual void LoadModule();
+ virtual void UnloadModule();
+
+ virtual void Load();
+ virtual void Unload();
+
virtual bool DoInit();
virtual void DoExit();
@@ -90,6 +95,7 @@ private:
static void Setup(t_classid);
void SetThis();
+ void ClearThis();
void ClearBinding();
bool MakeInstance();
diff --git a/externals/grill/py/source/register.cpp b/externals/grill/py/source/register.cpp
index bc2563ae..d26d5504 100644
--- a/externals/grill/py/source/register.cpp
+++ b/externals/grill/py/source/register.cpp
@@ -10,6 +10,74 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#include "main.h"
+#if 1
+
+PyObject *pybase::GetRegistry(const char *regnm)
+{
+ if(module) {
+ FLEXT_ASSERT(dict); // module must have a valid dict
+
+ // add this to module registry
+ PyObject *reg = PyDict_GetItemString(dict,(char *)regnm); // borrowed!!!
+ if(reg)
+ FLEXT_ASSERT(PyDict_Check(reg));
+ else {
+ // make a new empty registry
+ reg = PyDict_New();
+ PyDict_SetItemString(dict,(char *)regnm,reg);
+ }
+ return reg;
+ }
+ else
+ return NULL;
+}
+
+void pybase::SetRegistry(const char *regnm,PyObject *reg)
+{
+ if(module) {
+ FLEXT_ASSERT(dict); // module must have a valid dict
+ FLEXT_ASSERT(reg && PyDict_Check(reg));
+ PyDict_SetItemString(dict,(char *)regnm,reg);
+ }
+}
+
+void pybase::Register(PyObject *reg)
+{
+ if(!module) return;
+ FLEXT_ASSERT(reg && PyDict_Check(reg));
+
+ // add this to module registry
+ Py_INCREF(Py_None);
+ PyObject *key = PyLong_FromUnsignedLong((size_t)this);
+ PyDict_SetItem(reg,key,Py_None);
+}
+
+void pybase::Unregister(PyObject *reg)
+{
+ if(!module) return;
+ FLEXT_ASSERT(reg && PyDict_Check(reg));
+
+ // remove this from module registry
+ PyObject *key = PyLong_FromUnsignedLong((size_t)this);
+ PyObject *item = PyDict_GetItem(reg,key);
+ if(!item)
+ post("py/pyext - Internal error: object not found in registry");
+ else
+ PyDict_DelItem(reg,key);
+}
+
+/*
+void pybase::RegLoad(PyObject *reg)
+{
+
+}
+
+void pybase::RegUnload(PyObject *reg)
+{
+}
+*/
+
+#else
void pybase::Register(const char *regnm)
{
@@ -79,3 +147,5 @@ void pybase::Reregister(const char *regnm)
}
}
}
+
+#endif