diff options
Diffstat (limited to 'externals/grill')
-rw-r--r-- | externals/grill/py/package.txt | 2 | ||||
-rw-r--r-- | externals/grill/py/pd/builtins-1.pd | 47 | ||||
-rw-r--r-- | externals/grill/py/pd/methods-1.pd | 24 | ||||
-rw-r--r-- | externals/grill/py/pd/methods-2.pd | 28 | ||||
-rw-r--r-- | externals/grill/py/pd/script-1.pd | 26 | ||||
-rw-r--r-- | externals/grill/py/pd/simple-2.pd | 8 | ||||
-rw-r--r-- | externals/grill/py/py.vcproj | 7 | ||||
-rw-r--r-- | externals/grill/py/readme.txt | 5 | ||||
-rw-r--r-- | externals/grill/py/source/clmeth.cpp | 7 | ||||
-rw-r--r-- | externals/grill/py/source/modmeth.cpp | 10 | ||||
-rw-r--r-- | externals/grill/py/source/py.cpp | 137 | ||||
-rw-r--r-- | externals/grill/py/source/pyargs.cpp | 40 | ||||
-rw-r--r-- | externals/grill/py/source/pybase.cpp | 52 | ||||
-rw-r--r-- | externals/grill/py/source/pybase.h | 7 | ||||
-rw-r--r-- | externals/grill/py/source/pyext.cpp | 9 | ||||
-rw-r--r-- | externals/grill/py/source/pymeth.cpp | 449 | ||||
-rw-r--r-- | externals/grill/py/source/pysymbol.cpp | 87 |
17 files changed, 819 insertions, 126 deletions
diff --git a/externals/grill/py/package.txt b/externals/grill/py/package.txt index 31637831..5204b0a8 100644 --- a/externals/grill/py/package.txt +++ b/externals/grill/py/package.txt @@ -11,6 +11,6 @@ SRCS= \ py.cpp pyext.cpp modmeth.cpp clmeth.cpp \
register.cpp bound.cpp pyargs.cpp \
pysymbol.cpp pybuffer.cpp pydsp.cpp \
- pyatom.cpp pybase.cpp
+ pyatom.cpp pybase.cpp pymeth.cpp
HDRS= pyprefix.h main.h pyext.h pysymbol.h pybuffer.h pyatom.h pybase.h
diff --git a/externals/grill/py/pd/builtins-1.pd b/externals/grill/py/pd/builtins-1.pd new file mode 100644 index 00000000..095e7690 --- /dev/null +++ b/externals/grill/py/pd/builtins-1.pd @@ -0,0 +1,47 @@ +#N canvas 327 349 706 421 12;
+#X obj 36 241 py .range @xlate 0;
+#X floatatom 35 356 5 0 0 0 - - -;
+#X obj 35 323 py .sum;
+#X obj 16 13 cnv 15 650 40 empty empty py/pyext 10 22 0 24 -260818
+-1 0;
+#X text 235 16 Python script objects \, (C)2003-2005 Thomas Grill;
+#X text 235 32 http://grrrr.org/ext;
+#X obj 36 159 nbx 5 14 -1e+037 1e+037 0 1 empty empty min 0 -6 0 10
+-262131 -1 -1 38 256;
+#X obj 95 159 nbx 5 14 -1e+037 1e+037 0 1 empty empty max 0 -6 0 10
+-262131 -1 -1 100 256;
+#X obj 154 159 nbx 5 14 1 100000 1 1 empty empty step 0 -6 0 10 -262131
+-1 -1 1 256;
+#N canvas 0 0 462 312 pak3 0;
+#X obj 34 26 inlet;
+#X obj 81 28 inlet;
+#X obj 129 28 inlet;
+#X obj 36 158 outlet;
+#X obj 36 123 pack 0 0 0;
+#X obj 61 78 t b f;
+#X obj 108 80 t b f;
+#X obj 208 46 loadbang;
+#X obj 208 73 1;
+#X connect 0 0 4 0;
+#X connect 1 0 5 0;
+#X connect 2 0 6 0;
+#X connect 4 0 3 0;
+#X connect 5 0 4 0;
+#X connect 5 1 4 1;
+#X connect 6 0 4 0;
+#X connect 6 1 4 2;
+#X connect 7 0 8 0;
+#X connect 8 0 4 2;
+#X restore 36 195 pd pak3;
+#X text 115 240 construct a Python list;
+#X text 78 282 Python object pointer is propagated to next object;
+#X text 106 320 calculate sum over list elements;
+#X text 21 73 Py can use built-in Python functions;
+#X text 21 97 A . preceding the function name searches for the function
+in either the pyext module or in __builtins__;
+#X connect 0 0 2 1;
+#X connect 2 0 1 0;
+#X connect 6 0 9 0;
+#X connect 7 0 9 1;
+#X connect 8 0 9 2;
+#X connect 9 0 0 1;
diff --git a/externals/grill/py/pd/methods-1.pd b/externals/grill/py/pd/methods-1.pd new file mode 100644 index 00000000..8d49f319 --- /dev/null +++ b/externals/grill/py/pd/methods-1.pd @@ -0,0 +1,24 @@ +#N canvas 540 469 714 349 12;
+#X obj 16 13 cnv 15 650 40 empty empty py/pyext 10 22 0 24 -260818
+-1 0;
+#X text 235 16 Python script objects \, (C)2003-2005 Thomas Grill;
+#X text 235 32 http://grrrr.org/ext;
+#X symbolatom 21 139 10 0 0 0 - - -;
+#X symbolatom 25 298 10 0 0 0 - - -;
+#X obj 25 252 pym upper;
+#X obj 22 179 py .str @xlate 0;
+#X text 93 167 convert the symbol to a Python string;
+#X text 35 216 pass it as a true Python object;
+#X text 105 251 use string.upper method;
+#X obj 363 252 py string.upper;
+#X symbolatom 364 288 10 0 0 0 - - -;
+#X text 495 254 use module function;
+#X text 23 119 enter some text;
+#X text 21 73 Py can act on Python objects in a object-oriented manner
+;
+#X text 93 184 using the built-in str function;
+#X connect 3 0 6 1;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 0 10 1;
+#X connect 10 0 11 0;
diff --git a/externals/grill/py/pd/methods-2.pd b/externals/grill/py/pd/methods-2.pd new file mode 100644 index 00000000..b10e183c --- /dev/null +++ b/externals/grill/py/pd/methods-2.pd @@ -0,0 +1,28 @@ +#N canvas 540 469 734 339 12;
+#X obj 16 13 cnv 15 650 40 empty empty py/pyext 10 22 0 24 -260818
+-1 0;
+#X text 235 16 Python script objects \, (C)2003-2005 Thomas Grill;
+#X text 235 32 http://grrrr.org/ext;
+#X symbolatom 21 139 10 0 0 0 - #0-t -;
+#X text 23 119 enter some text;
+#X text 21 73 Py can act on Python objects in a object-oriented manner
+;
+#X obj 25 252 pym 2 *;
+#X obj 213 169 t b f;
+#X text 105 251 repeat text;
+#X text 215 117 multiply it!;
+#X symbolatom 25 283 80 0 0 0 - - -;
+#X obj 214 139 nbx 5 14 1 100 0 1 empty empty empty 0 -6 0 10 -262131
+-1 -1 34 256;
+#N canvas 0 0 458 308 init 0;
+#X obj 61 116 s \$0-t;
+#X obj 64 44 loadbang;
+#X obj 64 81 symbol a;
+#X connect 1 0 2 0;
+#X connect 2 0 0 0;
+#X restore 606 127 pd init;
+#X connect 3 0 6 1;
+#X connect 6 0 10 0;
+#X connect 7 0 6 0;
+#X connect 7 1 6 2;
+#X connect 11 0 7 0;
diff --git a/externals/grill/py/pd/script-1.pd b/externals/grill/py/pd/script-1.pd index 328b096d..98fee527 100644 --- a/externals/grill/py/pd/script-1.pd +++ b/externals/grill/py/pd/script-1.pd @@ -1,4 +1,4 @@ -#N canvas 297 17 696 538 12;
+#N canvas 297 17 700 542 12;
#X obj 39 278 print;
#X obj 345 251 print;
#X msg 499 149 freakhole;
@@ -26,7 +26,6 @@ file.; #X obj 39 241 py script strcat;
#X obj 43 424 py script addall;
#X obj 350 420 py script;
-#X obj 516 419 py script ret3;
#X obj 346 204 py script strlen;
#X msg 21 159 dir;
#X obj 146 279 print A;
@@ -39,26 +38,27 @@ file.; #X text 556 181 too many args;
#X text 505 372 just trigger without arguments;
#X msg 386 371 set ret4;
-#X connect 2 0 25 1;
+#X obj 516 419 py script ret3;
+#X connect 2 0 24 1;
#X connect 3 0 21 1;
#X connect 4 0 21 1;
#X connect 6 0 22 1;
#X connect 7 0 22 1;
#X connect 9 0 23 0;
-#X connect 11 0 24 0;
+#X connect 11 0 35 0;
#X connect 12 0 21 1;
-#X connect 13 0 25 0;
+#X connect 13 0 24 0;
#X connect 14 0 23 0;
#X connect 15 0 23 0;
-#X connect 17 0 25 1;
+#X connect 17 0 24 1;
#X connect 19 0 21 0;
#X connect 21 0 0 0;
-#X connect 21 1 27 0;
+#X connect 21 1 26 0;
#X connect 22 0 5 0;
#X connect 23 0 8 0;
-#X connect 24 0 10 0;
-#X connect 25 0 1 0;
-#X connect 26 0 21 0;
-#X connect 28 0 21 0;
-#X connect 32 0 25 1;
-#X connect 35 0 23 0;
+#X connect 24 0 1 0;
+#X connect 25 0 21 0;
+#X connect 27 0 21 0;
+#X connect 31 0 24 1;
+#X connect 34 0 23 0;
+#X connect 35 0 10 0;
diff --git a/externals/grill/py/pd/simple-2.pd b/externals/grill/py/pd/simple-2.pd index 1845b032..4c857d49 100644 --- a/externals/grill/py/pd/simple-2.pd +++ b/externals/grill/py/pd/simple-2.pd @@ -1,4 +1,4 @@ -#N canvas 95 223 654 394 12;
+#N canvas 570 275 788 398 12;
#X floatatom 202 113 5 0 0 0 - - -;
#X text 338 286 watch the console output!;
#X msg 20 115 help;
@@ -16,13 +16,11 @@ file.; #X msg 120 174 hello;
#X msg 193 180 hello;
#X msg 266 179 msg;
-#X msg 325 154 hello 3;
-#X text 338 189 special case: 'hello' handler doesn't like args \,
-so _anything_ is called!;
#X obj 16 13 cnv 15 600 40 empty empty py/pyext 10 22 0 24 -260818
-1 0;
#X text 213 16 Python script objects \, (C)2003-2005 Thomas Grill;
#X text 213 32 http://grrrr.org/ext;
+#X msg 333 186 whoopie a b c;
#X connect 0 0 8 1;
#X connect 2 0 8 0;
#X connect 4 0 8 0;
@@ -36,4 +34,4 @@ so _anything_ is called!; #X connect 13 0 8 1;
#X connect 14 0 8 3;
#X connect 15 0 8 2;
-#X connect 16 0 8 3;
+#X connect 19 0 8 3;
diff --git a/externals/grill/py/py.vcproj b/externals/grill/py/py.vcproj index a103c872..31e24d3c 100644 --- a/externals/grill/py/py.vcproj +++ b/externals/grill/py/py.vcproj @@ -1244,6 +1244,13 @@ </FileConfiguration> </File> </Filter> + <Filter + Name="meth" + Filter=""> + <File + RelativePath=".\source\pymeth.cpp"> + </File> + </Filter> <File RelativePath="source\main.cpp"> <FileConfiguration diff --git a/externals/grill/py/readme.txt b/externals/grill/py/readme.txt index 309e99d5..c36a081b 100644 --- a/externals/grill/py/readme.txt +++ b/externals/grill/py/readme.txt @@ -91,6 +91,11 @@ Version history: - ADD: py can have multiple inlets for multiple function arguments (right inlets are non-triggering) - ADD: allow module.function syntax for py and pyext - FIX: pyext: cleanup up float vs. int ... first decision is made by tag, afterwards a conversion is tried +- ADD: pym: object-oriented object... Python methods for any object type +- ADD: py: allow all callables (also object constructors and builtins) +- ADD: py: enable Python built-in functions (like range, str etc.) +- ADD: sequence protocol for symbol type +- FIX: cleanup for outbound messages (e.g. symbol atoms instead of one-element general messages) 0.2.0: - ADD: handling of Python threads diff --git a/externals/grill/py/source/clmeth.cpp b/externals/grill/py/source/clmeth.cpp index 303b5888..37ba257e 100644 --- a/externals/grill/py/source/clmeth.cpp +++ b/externals/grill/py/source/clmeth.cpp @@ -182,7 +182,7 @@ PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) // offset outlet by signal outlets o += ext->sigoutlets; - if(ext->OutObject(ext,o,val)) + if(ext->OutObject(ext,o-1,val)) ok = true; else PyErr_SetString(PyExc_ValueError,"pyext - _outlet: invalid arguments"); @@ -295,11 +295,12 @@ PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) val = PyTuple_GetSlice(args,1,sz); // new ref flext::AtomListStatic<16> lst; - if(GetPyArgs(lst,val)) { + 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()); + pd_forwardmess(cl,lst.Count(),lst.Atoms()); #ifdef FLEXT_DEBUG else post("pyext - no parent canvas?!"); diff --git a/externals/grill/py/source/modmeth.cpp b/externals/grill/py/source/modmeth.cpp index d56441ac..44299b0c 100644 --- a/externals/grill/py/source/modmeth.cpp +++ b/externals/grill/py/source/modmeth.cpp @@ -128,13 +128,9 @@ PyObject *pybase::py_send(PyObject *,PyObject *args) val = PySequence_GetSlice(args,1,sz); // new ref 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); - + const t_symbol *sym = GetPyArgs(lst,val); + if(sym) { + bool ok = Forward(recv,sym,lst.Count(),lst.Atoms()); #ifdef FLEXT_DEBUG if(!ok) post("py/pyext - Receiver doesn't exist"); 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<char *>(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<char *>(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(); } diff --git a/externals/grill/py/source/pyargs.cpp b/externals/grill/py/source/pyargs.cpp index f08369a7..5c903f17 100644 --- a/externals/grill/py/source/pyargs.cpp +++ b/externals/grill/py/source/pyargs.cpp @@ -17,19 +17,19 @@ static PyObject *MakePyAtom(const t_atom &at) { 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! int ival = flext::GetAInt(at); double fval = flext::GetAFloat(at); 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; } @@ -99,7 +99,8 @@ PyObject *pybase::MakePyArg(const t_symbol *s,int argc,const t_atom *argv) if(s == symatom && (ret = MakePyAtom(argc,argv)) != NULL) { // ok! } - else if(argc == 1 && IsAtom(s)) + else if(argc == 1 && !IsAnything(s)) + // convert atoms and one-element lists ret = MakePyAtom(*argv); else { bool any = s != sym_list; @@ -125,14 +126,13 @@ PyObject *pybase::MakePyArg(const t_symbol *s,int argc,const t_atom *argv) return ret; } -bool pybase::GetPyArgs(AtomList &lst,PyObject *pValue,int offs) +const t_symbol *pybase::GetPyArgs(AtomList &lst,PyObject *pValue,int offs) { if(pValue == NULL) return false; // analyze return value or tuple int rargc = 0; - bool ok = true; retval tp = nothing; if(PyString_Check(pValue)) { @@ -152,6 +152,8 @@ bool pybase::GetPyArgs(AtomList &lst,PyObject *pValue,int offs) lst(offs+rargc); + const t_symbol *sym = NULL; + for(int ix = 0; ix < rargc; ++ix) { PyObject *arg; if(tp == sequ) @@ -160,11 +162,11 @@ bool pybase::GetPyArgs(AtomList &lst,PyObject *pValue,int offs) arg = pValue; 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)); + 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)) { // assumed to be self ... that should be checked _somehow_ !!! @@ -180,25 +182,27 @@ bool pybase::GetPyArgs(AtomList &lst,PyObject *pValue,int offs) post("py/pyext: Could not convert argument %s",tmp); Py_XDECREF(stp); Py_XDECREF(tp); - ok = false; + + SetSymbol(at,sym__); sym = sym_symbol; } if(tp == sequ) Py_DECREF(arg); } - return ok; + if(sym && tp == sequ) sym = sym_list; + + return sym; } -bool pybase::GetPyAtom(AtomList &lst,PyObject *obj) +const t_symbol *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); + lst(szat); for(size_t i = 0; i < szat; ++i,atom >>= 16) - flext::SetInt(lst[i+1],(int)(atom&((1<<16)-1))); - return true; + flext::SetInt(lst[i],(int)(atom&((1<<16)-1))); + return symatom; } diff --git a/externals/grill/py/source/pybase.cpp b/externals/grill/py/source/pybase.cpp index cc51a59e..3bc589de 100644 --- a/externals/grill/py/source/pybase.cpp +++ b/externals/grill/py/source/pybase.cpp @@ -62,6 +62,10 @@ void pybase::FreeThreadState() PyObject *pybase::module_obj = NULL;
PyObject *pybase::module_dict = NULL;
+PyObject *pybase::builtins_obj = NULL;
+PyObject *pybase::builtins_dict = NULL;
+
+const t_symbol *pybase::sym_fint = NULL;
// -----------------------------------------------------------------------------------------------------------
@@ -128,6 +132,9 @@ void pybase::lib_setup() Py_DECREF(gcobj);
}
+ builtins_obj = PyImport_ImportModule("__builtin__");
+ builtins_dict = PyModule_GetDict(builtins_obj); // borrowed reference
+
// add symbol type
initsymbol();
PyModule_AddObject(module_obj,"Symbol",(PyObject *)&pySymbol_Type);
@@ -144,9 +151,16 @@ void pybase::lib_setup() initsamplebuffer();
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);
@@ -213,8 +227,11 @@ void pybase::GetDir(PyObject *obj,AtomList &lst) if(!pvar)
PyErr_Print(); // no method found
else {
- if(!GetPyArgs(lst,pvar))
+ 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);
}
@@ -294,9 +311,12 @@ void pybase::SetArgs() bool pybase::ImportModule(const char *name)
{
- if(!name) return false;
- if(modname == name) return true;
- modname = name;
+ if(name) {
+ if(modname == name) return true;
+ modname = name;
+ }
+ else
+ modname.clear();
return ReloadModule();
}
@@ -321,9 +341,17 @@ bool pybase::ReloadModule() bool ok = false;
SetArgs();
- PyObject *newmod = module
- ?PyImport_ReloadModule(module)
- :PyImport_ImportModule((char *)modname.c_str());
+ 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) {
// unload faulty module
@@ -415,15 +443,11 @@ void pybase::AddCurrentPath(t_canvas *cnv) bool pybase::OutObject(flext_base *ext,int o,PyObject *obj)
{
flext::AtomListStatic<16> lst;
- if(xlate?GetPyArgs(lst,obj):GetPyAtom(lst,obj)) {
+ 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
- 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]);
+ ext->ToOutAnything(o,sym,lst.Count(),lst.Atoms());
return true;
}
else
diff --git a/externals/grill/py/source/pybase.h b/externals/grill/py/source/pybase.h index ea5f6b49..068aeb86 100644 --- a/externals/grill/py/source/pybase.h +++ b/externals/grill/py/source/pybase.h @@ -26,8 +26,8 @@ public: 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 const t_symbol *GetPyArgs(AtomList &lst,PyObject *pValue,int offs = 0);
+ static const t_symbol *GetPyAtom(AtomList &lst,PyObject *pValue);
static void lib_setup();
@@ -94,6 +94,7 @@ protected: // --- module stuff -----
static PyObject *module_obj,*module_dict;
+ static PyObject *builtins_obj,*builtins_dict;
static PyMethodDef func_tbl[];
static PyObject *py__doc__(PyObject *,PyObject *args);
@@ -161,6 +162,8 @@ protected: static PyThreadState *FindThreadState() { return NULL; }
#endif
+ static const t_symbol *sym_fint; // float or int symbol, depending on native number message type
+
public:
#ifdef FLEXT_THREADS
diff --git a/externals/grill/py/source/pyext.cpp b/externals/grill/py/source/pyext.cpp index 88b5de0c..593c8bd1 100644 --- a/externals/grill/py/source/pyext.cpp +++ b/externals/grill/py/source/pyext.cpp @@ -420,7 +420,9 @@ void pyext::m_get(const t_symbol *s) PyObject *pvar = PyObject_GetAttrString(pyobj,const_cast<char *>(GetString(s))); /* fetch bound method */ if(pvar) { flext::AtomListStatic<16> lst; - if(GetPyArgs(lst,pvar,1)) { + const t_symbol *sym = GetPyArgs(lst,pvar,1); + if(sym) { + FLEXT_ASSERT(!IsAnything(sym)); // dump value to attribute outlet SetSymbol(lst[0],s); ToOutAnything(GetOutAttr(),sym_get,lst.Count(),lst.Atoms()); @@ -469,7 +471,10 @@ void pyext::m_set(int argc,const t_atom *argv) 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); + if(!n) + return flext_dsp::CbMethodResort(n,s,argc,argv); + + return pyobj && work(n,s,argc,argv); } diff --git a/externals/grill/py/source/pymeth.cpp b/externals/grill/py/source/pymeth.cpp new file mode 100644 index 00000000..8c80bd43 --- /dev/null +++ b/externals/grill/py/source/pymeth.cpp @@ -0,0 +1,449 @@ +/*
+
+py/pyext - python script object for PD and Max/MSP
+
+Copyright (c)2002-2005 Thomas Grill (gr@grrrr.org)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+#include "pybase.h"
+#include <map>
+
+struct xlt { const t_symbol *from,*to; };
+
+static const xlt xtdefs[] = {
+ { flext::MakeSymbol("+"),flext::MakeSymbol("__add__") },
+ { flext::MakeSymbol("+="),flext::MakeSymbol("__iadd__") },
+ { flext::MakeSymbol("!+"),flext::MakeSymbol("__radd__") },
+ { flext::MakeSymbol("-"),flext::MakeSymbol("__sub__") },
+ { flext::MakeSymbol("-="),flext::MakeSymbol("__isub__") },
+ { flext::MakeSymbol("!-"),flext::MakeSymbol("__rsub__") },
+ { flext::MakeSymbol("*"),flext::MakeSymbol("__mul__") },
+ { flext::MakeSymbol("*="),flext::MakeSymbol("__imul__") },
+ { flext::MakeSymbol("!*"),flext::MakeSymbol("__rmul__") },
+ { flext::MakeSymbol("/"),flext::MakeSymbol("__div__") },
+ { flext::MakeSymbol("/="),flext::MakeSymbol("__idiv__") },
+ { flext::MakeSymbol("!/"),flext::MakeSymbol("__rdiv__") },
+ { flext::MakeSymbol("//"),flext::MakeSymbol("__floordiv__") },
+ { flext::MakeSymbol("//="),flext::MakeSymbol("__ifloordiv__") },
+ { flext::MakeSymbol("!//"),flext::MakeSymbol("__rfloordiv__") },
+ { flext::MakeSymbol("%"),flext::MakeSymbol("__mod__") },
+ { flext::MakeSymbol("%="),flext::MakeSymbol("__imod__") },
+ { flext::MakeSymbol("!%"),flext::MakeSymbol("__rmod__") },
+ { flext::MakeSymbol("**"),flext::MakeSymbol("__pow__") },
+ { flext::MakeSymbol("**="),flext::MakeSymbol("__ipow__") },
+ { flext::MakeSymbol("!**"),flext::MakeSymbol("__rpow__") },
+ { flext::MakeSymbol("&"),flext::MakeSymbol("__and__") },
+ { flext::MakeSymbol("&="),flext::MakeSymbol("__iand__") },
+ { flext::MakeSymbol("!&"),flext::MakeSymbol("__rand__") },
+ { flext::MakeSymbol("|"),flext::MakeSymbol("__or__") },
+ { flext::MakeSymbol("|="),flext::MakeSymbol("__ior__") },
+ { flext::MakeSymbol("!|"),flext::MakeSymbol("__ror__") },
+ { flext::MakeSymbol("^"),flext::MakeSymbol("__xor__") },
+ { flext::MakeSymbol("^="),flext::MakeSymbol("__ixor__") },
+ { flext::MakeSymbol("!^"),flext::MakeSymbol("__rxor__") },
+ { flext::MakeSymbol("<<"),flext::MakeSymbol("__lshift__") },
+ { flext::MakeSymbol("<<="),flext::MakeSymbol("__ilshift__") },
+ { flext::MakeSymbol("!<<"),flext::MakeSymbol("__rlshift__") },
+ { flext::MakeSymbol(">>"),flext::MakeSymbol("__rshift__") },
+ { flext::MakeSymbol(">>="),flext::MakeSymbol("__irshift__") },
+ { flext::MakeSymbol("!>>"),flext::MakeSymbol("__rrshift__") },
+ { flext::MakeSymbol("=="),flext::MakeSymbol("__eq__") },
+ { flext::MakeSymbol("!="),flext::MakeSymbol("__ne__") },
+ { flext::MakeSymbol("<"),flext::MakeSymbol("__lt__") },
+ { flext::MakeSymbol(">"),flext::MakeSymbol("__gt__") },
+ { flext::MakeSymbol("<="),flext::MakeSymbol("__le__") },
+ { flext::MakeSymbol(">="),flext::MakeSymbol("__ge__") },
+ { flext::MakeSymbol("!"),flext::MakeSymbol("__nonzero__") },
+ { flext::MakeSymbol("~"),flext::MakeSymbol("__invert__") },
+ { flext::MakeSymbol("[]"),flext::MakeSymbol("__getitem__") },
+ { flext::MakeSymbol("[]="),flext::MakeSymbol("__setitem__") },
+ { flext::MakeSymbol("[:]"),flext::MakeSymbol("__getslice__") },
+ { flext::MakeSymbol("[:]="),flext::MakeSymbol("__setslice__") },
+
+ { flext::MakeSymbol(".abs"),flext::MakeSymbol("__abs__") },
+ { flext::MakeSymbol(".neg"),flext::MakeSymbol("__neg__") },
+ { flext::MakeSymbol(".pos"),flext::MakeSymbol("__pos__") },
+ { flext::MakeSymbol(".divmod"),flext::MakeSymbol("__divmod__") },
+
+ { flext::MakeSymbol(".int"),flext::MakeSymbol("__int__") },
+ { flext::MakeSymbol(".long"),flext::MakeSymbol("__long__") },
+ { flext::MakeSymbol(".float"),flext::MakeSymbol("__float__") },
+ { flext::MakeSymbol(".complex"),flext::MakeSymbol("__complex__") },
+ { flext::MakeSymbol(".str"),flext::MakeSymbol("__str__") },
+ { flext::MakeSymbol(".coerce"),flext::MakeSymbol("__coerce__") },
+
+ { flext::MakeSymbol(".doc"),flext::MakeSymbol("__doc__") },
+ { flext::MakeSymbol(".repr"),flext::MakeSymbol("__repr__") },
+
+ { flext::MakeSymbol(".len"),flext::MakeSymbol("__len__") },
+ { flext::MakeSymbol(".in"),flext::MakeSymbol("__contains") },
+
+ { NULL,NULL } // sentinel
+};
+
+typedef std::map<const t_symbol *,const t_symbol *> XTable;
+static XTable xtable;
+
+
+class pymeth
+ : public pybase
+ , public flext_base
+{
+ FLEXT_HEADER_S(pymeth,flext_base,Setup)
+
+public:
+ pymeth(int argc,const t_atom *argv);
+ ~pymeth();
+
+protected:
+ virtual void Exit();
+
+ virtual bool CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv);
+ virtual void CbClick();
+
+ void m_help();
+
+ void m_reload() { Reload(); }
+ void m_reload_(int argc,const t_atom *argv) { args(argc,argv); Reload(); }
+ void m_set(int argc,const t_atom *argv);
+ void m_dir_() { m__dir(function); }
+ void m_doc_() { m__doc(function); }
+
+ const t_symbol *funname;
+ PyObject *function;
+
+ virtual void LoadModule();
+ virtual void UnloadModule();
+
+ virtual void Load();
+ virtual void Unload();
+
+ void SetFunction(const t_symbol *func);
+ void ResetFunction();
+
+ virtual bool thrcall(void *data);
+ virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv);
+
+ PyObject **objects;
+
+private:
+
+ virtual bool callpy(PyObject *fun,PyObject *args);
+
+ static void Setup(t_classid c);
+
+ FLEXT_CALLBACK(m_help)
+ FLEXT_CALLBACK(m_reload)
+ FLEXT_CALLBACK_V(m_reload_)
+ FLEXT_CALLBACK_V(m_set)
+ FLEXT_CALLBACK(m_dir_)
+ FLEXT_CALLBACK(m_doc_)
+
+ // callbacks
+ FLEXT_ATTRVAR_I(detach)
+ FLEXT_ATTRVAR_B(xlate)
+ FLEXT_ATTRVAR_B(respond)
+
+ FLEXT_CALLBACK_V(m_stop)
+ FLEXT_CALLBACK(m_dir)
+ FLEXT_CALLGET_V(mg_dir)
+ FLEXT_CALLBACK(m_doc)
+
+#ifdef FLEXT_THREADS
+ FLEXT_CALLBACK_T(tick)
+ FLEXT_THREAD(threadworker)
+ FLEXT_THREAD_X(work_wrapper)
+#else
+ FLEXT_CALLBACK_X(work_wrapper)
+#endif
+};
+
+FLEXT_LIB_V("pym",pymeth)
+
+
+void pymeth::Setup(t_classid c)
+{
+ FLEXT_CADDMETHOD_(c,0,"doc",m_doc);
+ FLEXT_CADDMETHOD_(c,0,"dir",m_dir);
+#ifdef FLEXT_THREADS
+ FLEXT_CADDATTR_VAR1(c,"detach",detach);
+ FLEXT_CADDMETHOD_(c,0,"stop",m_stop);
+#endif
+
+ FLEXT_CADDMETHOD_(c,0,"help",m_help);
+ FLEXT_CADDMETHOD_(c,0,"reload",m_reload_);
+ FLEXT_CADDMETHOD_(c,0,"reload.",m_reload);
+ FLEXT_CADDMETHOD_(c,0,"doc+",m_doc_);
+ FLEXT_CADDMETHOD_(c,0,"dir+",m_dir_);
+
+ FLEXT_CADDMETHOD_(c,0,"set",m_set);
+
+ FLEXT_CADDATTR_VAR1(c,"xlate",xlate);
+ FLEXT_CADDATTR_VAR1(c,"respond",respond);
+
+ // init translation map
+ for(const xlt *xi = xtdefs; xi->from; ++xi) xtable[xi->from] = xi->to;
+}
+
+pymeth::pymeth(int argc,const t_atom *argv)
+ : funname(NULL)
+ , function(NULL)
+ , objects(NULL)
+{
+#ifdef FLEXT_THREADS
+ FLEXT_ADDTIMER(stoptmr,tick);
+ // launch thread worker
+ FLEXT_CALLMETHOD(threadworker);
+#endif
+
+ PyThreadState *state = PyLockSys();
+
+ int inlets;
+ if(argc && CanbeInt(*argv)) {
+ inlets = GetAInt(*argv);
+ if(inlets < 1) inlets = 1;
+ argv++,argc--;
+ }
+ else inlets = 1;
+
+ objects = new PyObject *[inlets];
+ for(int i = 0; i < inlets; ++i) { objects[i] = Py_None; Py_INCREF(Py_None); }
+
+ if(inlets <= 0) InitProblem();
+
+ AddInAnything(1+(inlets < 0?1:inlets));
+ AddOutAnything();
+
+ Register(GetRegistry(REGNAME));
+
+ if(argc) {
+ const t_symbol *funnm = GetASymbol(*argv);
+ argv++,argc--;
+
+ if(funnm)
+ SetFunction(funnm);
+ else
+ PyErr_SetString(PyExc_ValueError,"Invalid function name");
+ }
+
+ if(argc) args(argc,argv);
+
+ Report();
+
+ PyUnlock(state);
+}
+
+pymeth::~pymeth()
+{
+ if(objects) {
+ for(int i = 0; i < CntIn()-1; ++i) Py_DECREF(objects[i]);
+ delete[] objects;
+ }
+
+ PyThreadState *state = PyLockSys();
+ Unregister(GetRegistry(REGNAME));
+ Report();
+ PyUnlock(state);
+}
+
+void pymeth::Exit()
+{
+ pybase::Exit();
+ flext_base::Exit();
+}
+
+void pymeth::m_set(int argc,const t_atom *argv)
+{
+ PyThreadState *state = PyLockSys();
+
+ // function name has precedence
+ if(argc >= 2) {
+ const char *sn = GetAString(*argv);
+ ++argv,--argc;
+
+ if(sn) {
+ if(!module || !strcmp(sn,PyModule_GetName(module))) {
+ ImportModule(sn);
+ Register(GetRegistry(REGNAME));
+ }
+ }
+ else
+ PyErr_SetString(PyExc_ValueError,"Invalid module name");
+ }
+
+ if(argc) {
+ const t_symbol *fn = GetASymbol(*argv);
+ if(fn)
+ SetFunction(fn);
+ else
+ PyErr_SetString(PyExc_ValueError,"Invalid function name");
+ }
+
+ Report();
+
+ PyUnlock(state);
+}
+
+void pymeth::m_help()
+{
+ post("");
+ post("%s %s - python method object, (C)2002-2005 Thomas Grill",thisName(),PY__VERSION);
+#ifdef FLEXT_DEBUG
+ post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__);
+#endif
+
+ post("Arguments: %s [method name] {args...}",thisName());
+
+ post("Inlet 1:messages to control the py object");
+ post(" 2:call python function with message as argument(s)");
+ post("Outlet: 1:return values from python function");
+ post("Methods:");
+ post("\thelp: shows this help");
+ post("\tbang: call script without arguments");
+ post("\tset [script name] [function name]: set (script and) function name");
+ post("\treload {args...}: reload python script");
+ post("\treload. : reload with former arguments");
+ post("\tdoc: display module doc string");
+ post("\tdoc+: display function doc string");
+ post("\tdir: dump module dictionary");
+ post("\tdir+: dump function dictionary");
+#ifdef FLEXT_THREADS
+ post("\tdetach 0/1/2: detach threads");
+ post("\tstop {wait time (ms)}: stop threads");
+#endif
+ post("");
+}
+
+void pymeth::ResetFunction()
+{
+ Py_XDECREF(function);
+ function = NULL;
+
+ if(funname && objects[0] != Py_None) {
+ function = PyObject_GetAttrString(objects[0],(char *)GetString(funname)); // new reference
+ if(!function)
+ PyErr_SetString(PyExc_AttributeError,"Method not found");
+ }
+
+ // exception could be set here
+}
+
+void pymeth::SetFunction(const t_symbol *func)
+{
+ // look for method name in translation table
+ XTable::iterator it = xtable.find(func);
+ funname = it == xtable.end()?func:it->second;
+
+ ResetFunction();
+}
+
+
+void pymeth::LoadModule()
+{
+ SetFunction(funname);
+}
+
+void pymeth::UnloadModule()
+{
+}
+
+void pymeth::Load()
+{
+ ResetFunction();
+}
+
+void pymeth::Unload()
+{
+ SetFunction(NULL);
+}
+
+bool pymeth::callpy(PyObject *fun,PyObject *args)
+{
+ PyObject *ret = PyObject_CallObject(fun,args);
+ if(ret == NULL) {
+ // function not found resp. arguments not matching
+ PyErr_Print();
+ return false;
+ }
+ else {
+ if(ret != Py_None && !OutObject(this,0,ret) && PyErr_Occurred())
+ PyErr_Print();
+ Py_DECREF(ret);
+ return true;
+ }
+}
+
+bool pymeth::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv)
+{
+ if(n == 0 && s != sym_bang)
+ return flext_base::CbMethodResort(n,s,argc,argv);
+
+ PyThreadState *state = PyLock();
+
+ bool ret = false;
+
+ if(n >= 1) {
+ // store args
+ PyObject *&obj = objects[n-1];
+ Py_DECREF(obj);
+ obj = MakePyArg(s,argc,argv); // steal reference
+
+ if(n > 1) ret = true; // just store, don't trigger
+ }
+
+ if(!ret) {
+ if(function) {
+ PyObject *self = PyMethod_Self(function);
+ PyErr_Clear();
+ if(!self || self->ob_type != objects[0]->ob_type)
+ // type has changed, search for new method
+ ResetFunction();
+ else if(self != objects[0]) {
+ // type hasn't changed, but object has
+ PyObject *f = function;
+ function = PyMethod_New(PyMethod_GET_FUNCTION(f),objects[0],PyMethod_GET_CLASS(f));
+ Py_DECREF(f);
+ }
+ }
+ else
+ ResetFunction();
+
+ if(function) {
+ Py_INCREF(function);
+
+ int inlets = CntIn()-1;
+ PyObject *pargs = PyTuple_New(inlets-1);
+ for(int i = 1; i < inlets; ++i) {
+ Py_INCREF(objects[i]);
+ PyTuple_SET_ITEM(pargs,i-1,objects[i]);
+ }
+
+ ret = gencall(function,pargs); // references are stolen
+ }
+ else
+ PyErr_SetString(PyExc_RuntimeError,"No function set");
+
+ Report();
+ }
+
+ PyUnlock(state);
+
+ Respond(ret);
+
+ return ret;
+}
+
+void pymeth::CbClick() { pybase::OpenEditor(); }
+
+void pymeth::DumpOut(const t_symbol *sym,int argc,const t_atom *argv)
+{
+ ToOutAnything(GetOutAttr(),sym?sym:thisTag(),argc,argv);
+}
+
+bool pymeth::thrcall(void *data)
+{
+ return FLEXT_CALLMETHOD_X(work_wrapper,data);
+}
diff --git a/externals/grill/py/source/pysymbol.cpp b/externals/grill/py/source/pysymbol.cpp index 189d6a6f..be7d3139 100644 --- a/externals/grill/py/source/pysymbol.cpp +++ b/externals/grill/py/source/pysymbol.cpp @@ -81,6 +81,89 @@ static long symbol_hash(PyObject *self) return (long)pySymbol_AS_SYMBOL(self);
}
+
+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)
0, /*ob_size*/
@@ -94,7 +177,7 @@ PyTypeObject pySymbol_Type = { 0, /*tp_compare*/
symbol_repr, /*tp_repr*/
0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
+ &symbol_as_seq, /*tp_as_sequence*/
0, /*tp_as_mapping*/
symbol_hash, /*tp_hash */
0, /*tp_call*/
@@ -108,7 +191,7 @@ PyTypeObject pySymbol_Type = { 0, /* tp_clear */
symbol_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
- 0, /* tp_iter */
+ symbol_iter, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
|