library of assembled shared sources

http://lass.cocamware.com

pyobject_plus.cpp

Go to the documentation of this file.
00001 /** @file
00002  *  @author Bram de Greve (bramz@users.sourceforge.net)
00003  *  @author Tom De Muer (tomdemuer@users.sourceforge.net)
00004  *
00005  *  *** BEGIN LICENSE INFORMATION ***
00006  *  
00007  *  The contents of this file are subject to the Common Public Attribution License 
00008  *  Version 1.0 (the "License"); you may not use this file except in compliance with 
00009  *  the License. You may obtain a copy of the License at 
00010  *  http://lass.sourceforge.net/cpal-license. The License is based on the 
00011  *  Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover 
00012  *  use of software over a computer network and provide for limited attribution for 
00013  *  the Original Developer. In addition, Exhibit A has been modified to be consistent 
00014  *  with Exhibit B.
00015  *  
00016  *  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 
00017  *  WARRANTY OF ANY KIND, either express or implied. See the License for the specific 
00018  *  language governing rights and limitations under the License.
00019  *  
00020  *  The Original Code is LASS - Library of Assembled Shared Sources.
00021  *  
00022  *  The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
00023  *  The Original Developer is the Initial Developer.
00024  *  
00025  *  All portions of the code written by the Initial Developer are:
00026  *  Copyright (C) 2004-2007 the Initial Developer.
00027  *  All Rights Reserved.
00028  *  
00029  *  Contributor(s):
00030  *
00031  *  Alternatively, the contents of this file may be used under the terms of the 
00032  *  GNU General Public License Version 2 or later (the GPL), in which case the 
00033  *  provisions of GPL are applicable instead of those above.  If you wish to allow use
00034  *  of your version of this file only under the terms of the GPL and not to allow 
00035  *  others to use your version of this file under the CPAL, indicate your decision by 
00036  *  deleting the provisions above and replace them with the notice and other 
00037  *  provisions required by the GPL License. If you do not delete the provisions above,
00038  *  a recipient may use your version of this file under either the CPAL or the GPL.
00039  *  
00040  *  *** END LICENSE INFORMATION ***
00041  */
00042 
00043 
00044 
00045 #include "util_common.h"
00046 #include "pyobject_plus.h"
00047 #include "pyobject_macros.h"
00048 #include "py_stl.h"
00049 #include "py_tuple.h"
00050 
00051 #if LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_MSVC
00052 #   pragma warning(disable: 4996) // This function or variable may be unsafe ...
00053 #endif
00054 
00055 namespace lass
00056 {
00057 namespace python
00058 {
00059 
00060 PyTypeObject PyObjectPlus::_lassPyType = { PY_STATIC_FUNCTION_FORWARD( PyObjectPlus, "PyObjectPlus" ) };
00061 
00062 std::vector<PyMethodDef> initAbstractMethods()
00063 {
00064     std::vector<PyMethodDef> temp;
00065     temp.push_back( impl::createPyMethodDef( 0, 0, 0, 0 ) );
00066     return temp;
00067 
00068 }
00069 std::vector<PyMethodDef> PyObjectPlus::_lassPyMethods = initAbstractMethods();
00070 
00071 PyObjectPlus::PyObjectPlus()
00072 {
00073     // initializing the type to NULL, when the object is exported to python the type is fixed
00074     this->ob_type = NULL;
00075 #ifdef LASS_PYTHON_INHERITANCE_FROM_EMBEDDING
00076     dict_ = PyDict_New();
00077 #endif
00078     _Py_NewReference( this );
00079 };
00080 
00081 PyObjectPlus::~PyObjectPlus()
00082 {
00083     if (this->ob_refcnt>0)
00084     {
00085         if (this->ob_refcnt>1)
00086         {
00087             std::cerr << "[LASS RUN MSG] DANGLING REFERENCE to lass::python::PyObjectPlus" 
00088                 << std::endl;
00089         }
00090         --this->ob_refcnt;
00091         _Py_ForgetReference( this );
00092 
00093     }
00094 #ifdef LASS_PYTHON_INHERITANCE_FROM_EMBEDDING
00095     //if (dict_)
00096     //  Py_XDECREF(dict_);
00097 #endif
00098     LASS_ASSERT(this->ob_refcnt==0);
00099 };
00100 
00101 PyObjectPlus::PyObjectPlus(const PyObjectPlus& iOther)
00102 {
00103     this->ob_type = iOther.ob_type;
00104 #ifdef LASS_PYTHON_INHERITANCE_FROM_EMBEDDING
00105     // [TDM] or just copy the reference? 
00106     dict_ = PyDict_Copy(iOther.dict_);
00107 #endif
00108     _Py_NewReference( this );
00109 }
00110 
00111 PyObjectPlus& PyObjectPlus::operator =(const PyObjectPlus& iOther)
00112 {
00113     LASS_ASSERT(!this->ob_type || this->ob_type == iOther.ob_type);
00114 #ifdef LASS_PYTHON_INHERITANCE_FROM_EMBEDDING
00115     // [TDM] or just copy the reference? 
00116     dict_ = PyDict_Copy(iOther.dict_);
00117 #endif
00118     return *this;
00119 }
00120 
00121 /** @ingroup Python
00122  *  @brief retrieve pointer to PyObject by its name in the script.
00123  *  @return 
00124  *  new reference to PyObject @a iName or NULL if 
00125  *  @a iName does not exist (_without_ setting an exception!)
00126  *  @throw Never
00127  */
00128 TPyObjPtr getPyObjectByName(const std::string& iName)
00129 {
00130     PyObject* module = PyImport_AddModule("__main__");
00131     if (!module)
00132     {
00133         PyErr_Clear();
00134         return TPyObjPtr();
00135     }
00136     PyObject* dict = PyModule_GetDict(module);
00137     LASS_ASSERT(dict != 0);
00138     PyObject* object = PyDict_GetItemString(dict, const_cast<char*>(iName.c_str()));
00139     Py_XINCREF(object);
00140     return TPyObjPtr(object);
00141 }
00142 
00143 // --- impl ----------------------------------------------------------------------------------------
00144 
00145 namespace impl
00146 {
00147 
00148 /** @internal
00149  */
00150 void dealloc(PyObject* obj)
00151 {
00152     delete static_cast<PyObjectPlus*>(obj);
00153 };
00154 
00155 /** @internal
00156  */
00157 PyObject* repr(PyObject* obj)
00158 {
00159     return pyBuildSimpleObject(static_cast<PyObjectPlus*>(obj)->doPyRepr());
00160 }
00161 
00162 /** @internal
00163  */
00164 PyObject* str(PyObject* obj)
00165 {
00166     return pyBuildSimpleObject(static_cast<PyObjectPlus*>(obj)->doPyStr());
00167 }
00168 
00169 
00170 /** @internal
00171  */
00172 const std::string exceptionExtractMessage(const TPyObjPtr& type, const TPyObjPtr& value)
00173 {
00174     std::ostringstream buffer;
00175     const TPyObjPtr typeStr(PyObject_Str(type.get()));
00176     buffer << (typeStr ? PyString_AsString(typeStr.get()) : "unknown python exception");
00177     const TPyObjPtr valueStr(value.get() == Py_None ? 0 : PyObject_Str(value.get()));
00178     if (valueStr)
00179     {
00180         buffer << ": '" << PyString_AsString(valueStr.get()) << "'";
00181     }
00182     return buffer.str();
00183 }
00184 
00185 
00186 
00187 OverloadLink::OverloadLink()
00188 {
00189     setNull();
00190 }
00191 
00192 void OverloadLink::setNull()
00193 {
00194     pyCFunction_ = 0;
00195     unaryfunc_ = 0;
00196     binaryfunc_ = 0;
00197     ternaryfunc_ = 0;
00198 }
00199 
00200 void OverloadLink::setPyCFunction(PyCFunction iOverload)
00201 {
00202     setNull();
00203     pyCFunction_ = iOverload;
00204 }
00205 
00206 void OverloadLink::setUnaryfunc(unaryfunc iOverload)
00207 {
00208     setNull();
00209     unaryfunc_ = iOverload;
00210 }
00211 
00212 void OverloadLink::setBinaryfunc(binaryfunc iOverload)
00213 {
00214     setNull();
00215     binaryfunc_ = iOverload;
00216 }
00217 
00218 void OverloadLink::setTernaryfunc(ternaryfunc iOverload)
00219 {
00220     setNull();
00221     ternaryfunc_ = iOverload;
00222 }
00223 void OverloadLink::setSsizeArgfunc(ssizeargfunc iOverload)
00224 {
00225     setNull();
00226     ssizeargfunc_ = iOverload;
00227 }
00228 void OverloadLink::setSsizeSsizeArgfunc(ssizessizeargfunc iOverload)
00229 {
00230     setNull();
00231     ssizessizeargfunc_ = iOverload;
00232 }
00233 void OverloadLink::setLenfunc(lenfunc iOverload)
00234 {
00235     setNull();
00236     lenfunc_ = iOverload;
00237 }
00238 void OverloadLink::setSsizeObjArgProcfunc(ssizeobjargproc iOverload)
00239 {
00240     setNull();
00241     ssizeobjargproc_ = iOverload;
00242 }
00243 void OverloadLink::setSsizeSsizeObjArgProcfunc(ssizessizeobjargproc iOverload)
00244 {
00245     setNull();
00246     ssizessizeobjargproc_ = iOverload;
00247 }
00248 void OverloadLink::setObjObjProcfunc(objobjproc iOverload)
00249 {
00250     setNull();
00251     objobjproc_ = iOverload;
00252 }
00253 
00254 
00255 bool OverloadLink::operator ()(PyObject* iSelf, PyObject* iArgs, PyObject*& oResult) const
00256 {
00257     PyObject* temp = 0;
00258     if (pyCFunction_)
00259     {
00260         LASS_ASSERT(unaryfunc_ == 0 && binaryfunc_ == 0 && ternaryfunc_ == 0);
00261         temp = pyCFunction_(iSelf, iArgs);
00262     }
00263     else if (unaryfunc_)
00264     {
00265         LASS_ASSERT(binaryfunc_ == 0 && ternaryfunc_ == 0);
00266         if (decodeTuple(iArgs)  != 0)
00267         {
00268             return false;
00269         }
00270         temp = unaryfunc_(iSelf);
00271     }
00272     else if (binaryfunc_)
00273     {
00274         LASS_ASSERT(ternaryfunc_ == 0);
00275         TPyObjPtr arg;
00276         if (decodeTuple(iArgs, arg) != 0)
00277         {
00278             return false;
00279         }
00280         temp = binaryfunc_(iSelf, arg.get());
00281     }
00282     else if (ternaryfunc_)
00283     {
00284         temp = ternaryfunc_(iSelf, iArgs, 0);
00285     }
00286     else if (ssizeargfunc_)
00287     {
00288         Py_ssize_t size1;
00289         if (decodeTuple(iArgs, size1) != 0)
00290             return false;
00291         temp = ssizeargfunc_(iSelf, size1 );
00292     }
00293     else if (ssizessizeargfunc_)
00294     {
00295         Py_ssize_t size1;
00296         Py_ssize_t size2;
00297         if (decodeTuple(iArgs, size1, size2) != 0)
00298             return false;
00299         temp = ssizessizeargfunc_(iSelf, size1, size2 );
00300     }
00301     else if (lenfunc_)
00302     {
00303         temp = PyInt_FromSsize_t(lenfunc_(iSelf));
00304     }
00305     else if (ssizeobjargproc_)
00306     {
00307         Py_ssize_t size1;
00308         TPyObjPtr obj1;
00309         if (decodeTuple(iArgs, size1, obj1) != 0)
00310             return false;
00311         temp = PyInt_FromLong(ssizeobjargproc_(iSelf,size1,obj1.get()));
00312     }
00313     else if (ssizessizeobjargproc_)
00314     {
00315         Py_ssize_t size1;
00316         Py_ssize_t size2;
00317         TPyObjPtr obj1;
00318         if (decodeTuple(iArgs, size1, size2, obj1) != 0)
00319             return false;
00320         temp = PyInt_FromLong(ssizessizeobjargproc_(iSelf,size1,size2,obj1.get()));
00321     }
00322     else if (objobjproc_)
00323     {
00324         TPyObjPtr obj1;
00325         if (decodeTuple(iArgs, obj1) != 0)
00326             return false;
00327         temp = PyInt_FromLong(objobjproc_(iSelf,obj1.get()));       
00328     }
00329     else
00330     {
00331         return false;
00332     }
00333     if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_TypeError))
00334     {
00335         PyErr_Clear();
00336         Py_XDECREF(temp);
00337         return false;
00338     }
00339     oResult = temp;
00340     return true;
00341 }
00342 
00343 
00344 
00345 StaticMemberEqual::StaticMemberEqual(const char* iName):
00346     name_(iName)
00347 {
00348 }
00349 
00350 bool StaticMemberEqual::operator()(const StaticMember& iMember) const
00351 {
00352     return iMember.name && strcmp(iMember.name, name_) == 0;
00353 }
00354 
00355 PyMethodEqual::PyMethodEqual( const char* iName ):
00356     name_(iName)
00357 {
00358 }
00359 
00360 bool PyMethodEqual::operator()(const PyMethodDef& iMethod) const
00361 {
00362     return iMethod.ml_name && strcmp(iMethod.ml_name, name_) == 0;
00363 }
00364 
00365 /** @internal
00366  */
00367 StaticMember createStaticMember(
00368         const char* iName, const char* iDocumentation, const TStaticMemberHelperPtr& iMember, 
00369         PyTypeObject* iParentType, std::vector<PyMethodDef>* iMethods, 
00370         std::vector<PyGetSetDef>* iGetSetters, const TStaticMembers* iStatics)
00371 {
00372     StaticMember temp;
00373     temp.name = iName;
00374     temp.doc = iDocumentation;
00375     temp.member = iMember;
00376     temp.parentType = iParentType;
00377     temp.methods = iMethods;
00378     temp.getSetters = iGetSetters;
00379     temp.statics = iStatics;
00380     return temp;
00381 }
00382         
00383 /** @internal
00384 */
00385 PyMethodDef createPyMethodDef(const char *ml_name, PyCFunction ml_meth, int ml_flags, const char *ml_doc)
00386 {
00387     PyMethodDef temp;
00388     temp.ml_name = const_cast<char*>(ml_name);
00389     temp.ml_meth = ml_meth;
00390     temp.ml_flags = ml_flags;
00391     temp.ml_doc = const_cast<char*>(ml_doc);
00392     return temp;
00393 }
00394 
00395 /** @internal
00396 */
00397 PyGetSetDef createPyGetSetDef( const char* name, getter get, setter set, const char* doc, void* closure )
00398 {
00399     PyGetSetDef temp;
00400     temp.name = const_cast<char*>(name);
00401     temp.get = get;
00402     temp.set = set;
00403     temp.doc = const_cast<char*>(doc);
00404     temp.closure = closure;
00405     return temp;
00406 }
00407 
00408 /** @internal
00409 */
00410 void injectStaticMembers(PyTypeObject& iPyType, const TStaticMembers& iStatics)
00411 {
00412     for (TStaticMembers::const_iterator i = iStatics.begin(); i != iStatics.end(); ++i)
00413     {
00414         PyObject* member = i->member->build();
00415         if (PyType_Check(member))
00416         {
00417             // we have an innerclass
00418             finalizePyType(*reinterpret_cast<PyTypeObject*>(member), *i->parentType, 
00419                 *i->methods, *i->getSetters, *i->statics, iPyType.tp_name, i->doc);
00420         }
00421         PyDict_SetItemString(iPyType.tp_dict, const_cast<char*>(i->name), member);
00422     }
00423 }
00424 
00425 /** @internal
00426 *   The iFinal sets the flags for final classes from which no new types can be derived.  
00427 */
00428 void finalizePyType(PyTypeObject& iPyType, PyTypeObject& iPyParentType, 
00429     std::vector<PyMethodDef>& iMethods, std::vector<PyGetSetDef>& iGetSetters, 
00430     const TStaticMembers& iStatics, const char* iModuleName, const char* iDocumentation)
00431 {
00432     std::string fullName;
00433     if (iModuleName)
00434         fullName = std::string(iModuleName) + std::string(".") + std::string(iPyType.tp_name);
00435     else    // without module, aimed at utility objects, such as PySequence, PyMap
00436         fullName = std::string(iPyType.tp_name);
00437     char* fullNameCharPtr = new char[fullName.size()+1];
00438     strcpy(fullNameCharPtr,fullName.c_str());
00439 
00440     iPyType.tp_name = fullNameCharPtr;
00441     iPyType.tp_methods = &iMethods[0];
00442     iPyType.tp_getset = &iGetSetters[0];
00443     iPyType.tp_doc = const_cast<char*>(iDocumentation);
00444     iPyType.tp_base = &iPyParentType;
00445     // we take care of collecting garbage ourselves
00446     iPyType.tp_flags &= (~Py_TPFLAGS_HAVE_GC);
00447     Py_XINCREF( iPyType.tp_base );
00448     LASS_ENFORCE( PyType_Ready( &iPyType ) >= 0 );
00449     Py_INCREF( &iPyType ); 
00450     injectStaticMembers(iPyType, iStatics);
00451 }
00452 
00453 /** @internal
00454 */
00455 void addModuleFunction(std::vector<PyMethodDef>& ioModuleMethods, const char* iMethodName, 
00456     const char* iDocumentation, PyCFunction iMethodDispatcher, PyCFunction& oOverloadChain)
00457 {
00458     ::std::vector<PyMethodDef>::iterator i = ::std::find_if(
00459         ioModuleMethods.begin(), ioModuleMethods.end(), PyMethodEqual(iMethodName));
00460     if (i == ioModuleMethods.end())
00461     {
00462         ioModuleMethods.insert(ioModuleMethods.begin(), createPyMethodDef(
00463             iMethodName, iMethodDispatcher, METH_VARARGS , iDocumentation));
00464         oOverloadChain = 0;
00465     }
00466     else
00467     {
00468         oOverloadChain = i->ml_meth;
00469         i->ml_meth = iMethodDispatcher;
00470     };
00471 }
00472 
00473 
00474 
00475 #define LASS_PY_OPERATOR(s_name, i_protocol, t_protocol, i_hook, i_nary)\
00476     if (strcmp(methodName, s_name) == 0)\
00477     {\
00478         if (pyType.i_protocol == 0)\
00479         {\
00480             pyType.i_protocol = new t_protocol;\
00481             ::memset(pyType.i_protocol, 0, sizeof(t_protocol));\
00482         }\
00483         overloadChain.LASS_CONCATENATE_3(set, i_nary, func)(pyType.i_protocol->i_hook);\
00484         pyType.i_protocol->i_hook = LASS_CONCATENATE(dispatcher, i_nary);\
00485         return;\
00486     }\
00487     /**/
00488 
00489 
00490 
00491 #define LASS_PY_COMPARATOR(s_name, v_op)\
00492     if (strcmp(methodName, s_name) == 0)\
00493     {\
00494         compareFuncs.push_back(CompareFunc(dispatcher, v_op));\
00495     }\
00496         
00497 
00498 /** @internal
00499  */
00500 void addClassMethod(
00501         PyTypeObject& pyType, 
00502         std::vector<PyMethodDef>& classMethods, TCompareFuncs& compareFuncs,
00503         const char* methodName, const char* documentation, 
00504         PyCFunction dispatcher, unaryfunc dispatcherUnary, 
00505         binaryfunc dispatcherBinary, ternaryfunc dispatcherTernary, 
00506         ssizeargfunc dispatcherSsizeArg, ssizessizeargfunc dispatcherSsizeSsizeArg,
00507         lenfunc dispatcherLen, ssizeobjargproc dispatcherSsizeObjArgProc,
00508         ssizessizeobjargproc dispatcherSsizeSsizeObjArgProc, 
00509         objobjproc dispatcherObjObjProc,
00510         OverloadLink& overloadChain) 
00511 {
00512     const int n = static_cast<int>(strlen(methodName));
00513     LASS_ASSERT(n >= 0);
00514     if (n > 2 && methodName[0] == '_' && methodName[1] == '_')
00515     {
00516         if (strcmp(methodName, "__call__") == 0)
00517         {
00518             overloadChain.setTernaryfunc(pyType.tp_call);
00519             pyType.tp_call = dispatcherTernary;
00520             return;
00521         }
00522         // number protocol
00523         LASS_PY_OPERATOR("__add__", tp_as_number, PyNumberMethods, nb_add, Binary)
00524         LASS_PY_OPERATOR("__sub__", tp_as_number, PyNumberMethods, nb_subtract,Binary)
00525         LASS_PY_OPERATOR("__mul__", tp_as_number, PyNumberMethods, nb_multiply, Binary)
00526         LASS_PY_OPERATOR("__div__", tp_as_number, PyNumberMethods, nb_divide, Binary)
00527         LASS_PY_OPERATOR("__mod__", tp_as_number, PyNumberMethods, nb_remainder, Binary)
00528         LASS_PY_OPERATOR("__neg__", tp_as_number, PyNumberMethods, nb_negative, Unary)
00529         LASS_PY_OPERATOR("__pos__", tp_as_number, PyNumberMethods, nb_positive, Unary)
00530         LASS_PY_OPERATOR("__abs__", tp_as_number, PyNumberMethods, nb_absolute, Unary)
00531         LASS_PY_OPERATOR("__invert__", tp_as_number, PyNumberMethods, nb_invert, Unary)
00532         LASS_PY_OPERATOR("__lshift__", tp_as_number, PyNumberMethods, nb_lshift, Binary)
00533         LASS_PY_OPERATOR("__rshift__", tp_as_number, PyNumberMethods, nb_rshift, Binary)
00534         LASS_PY_OPERATOR("__and__", tp_as_number, PyNumberMethods, nb_and, Binary)
00535         LASS_PY_OPERATOR("__xor__", tp_as_number, PyNumberMethods, nb_xor, Binary)
00536         LASS_PY_OPERATOR("__or__", tp_as_number, PyNumberMethods, nb_or, Binary)
00537         LASS_PY_OPERATOR("__int__", tp_as_number, PyNumberMethods, nb_int, Unary)
00538         LASS_PY_OPERATOR("__long__", tp_as_number, PyNumberMethods, nb_long, Unary)
00539         LASS_PY_OPERATOR("__float__", tp_as_number, PyNumberMethods, nb_float, Unary)
00540         LASS_PY_OPERATOR("__oct__", tp_as_number, PyNumberMethods, nb_oct, Unary)
00541         LASS_PY_OPERATOR("__hex__", tp_as_number, PyNumberMethods, nb_hex, Unary)
00542         LASS_PY_OPERATOR("__iadd__", tp_as_number, PyNumberMethods, nb_inplace_add, Binary)
00543         LASS_PY_OPERATOR("__isub__", tp_as_number, PyNumberMethods, nb_inplace_subtract, Binary)
00544         LASS_PY_OPERATOR("__imul__", tp_as_number, PyNumberMethods, nb_inplace_multiply, Binary)
00545         LASS_PY_OPERATOR("__idiv__", tp_as_number, PyNumberMethods, nb_inplace_divide, Binary)
00546         LASS_PY_OPERATOR("__imod__", tp_as_number, PyNumberMethods, nb_inplace_remainder, Binary)
00547         LASS_PY_OPERATOR("__ilshift__", tp_as_number, PyNumberMethods, nb_inplace_lshift, Binary)
00548         LASS_PY_OPERATOR("__irshift__", tp_as_number, PyNumberMethods, nb_inplace_rshift, Binary)
00549         LASS_PY_OPERATOR("__iand__", tp_as_number, PyNumberMethods, nb_inplace_and, Binary)
00550         LASS_PY_OPERATOR("__ixor__", tp_as_number, PyNumberMethods, nb_inplace_xor, Binary)
00551         LASS_PY_OPERATOR("__ior__", tp_as_number, PyNumberMethods, nb_inplace_or, Binary)
00552         LASS_PY_COMPARATOR("__lt__", Py_LT)
00553         LASS_PY_COMPARATOR("__le__", Py_LE)
00554         LASS_PY_COMPARATOR("__eq__", Py_EQ)
00555         LASS_PY_COMPARATOR("__ne__", Py_NE)
00556         LASS_PY_COMPARATOR("__gt__", Py_GT)
00557         LASS_PY_COMPARATOR("__ge__", Py_GE)
00558     
00559         // sequence protocol
00560         LASS_PY_OPERATOR("__len__", tp_as_sequence, PySequenceMethods, sq_length, Len) 
00561         LASS_PY_OPERATOR("__concat__", tp_as_sequence, PySequenceMethods, sq_concat, Binary) 
00562         LASS_PY_OPERATOR("__repeat__", tp_as_sequence, PySequenceMethods, sq_repeat, SsizeArg) 
00563         LASS_PY_OPERATOR("__getitem__", tp_as_sequence, PySequenceMethods, sq_item, SsizeArg) 
00564         LASS_PY_OPERATOR("__getslice__", tp_as_sequence, PySequenceMethods, sq_slice, SsizeSsizeArg) 
00565         LASS_PY_OPERATOR("__setitem__", tp_as_sequence, PySequenceMethods, sq_ass_item, SsizeObjArgProc) 
00566         LASS_PY_OPERATOR("__setslice__", tp_as_sequence, PySequenceMethods, sq_ass_slice, SsizeSsizeObjArgProc) 
00567         LASS_PY_OPERATOR("__contains__", tp_as_sequence, PySequenceMethods, sq_contains, ObjObjProc) 
00568         LASS_PY_OPERATOR("__iconcat__", tp_as_sequence, PySequenceMethods, sq_inplace_concat, Binary) 
00569         LASS_PY_OPERATOR("__irepeat__", tp_as_sequence, PySequenceMethods, sq_inplace_repeat, SsizeArg) 
00570 
00571         if (strcmp(methodName, "__str__") == 0)
00572         {
00573             pyType.tp_str = dispatcherUnary;
00574             return;
00575         }
00576         if (strcmp(methodName, "__repr__") == 0)
00577         {
00578             pyType.tp_repr = dispatcherUnary;
00579             return;
00580         }
00581     }
00582 
00583     // normal method mechanism
00584 
00585     std::vector<PyMethodDef>::iterator i = std::find_if(
00586         classMethods.begin(), classMethods.end(), PyMethodEqual(methodName));
00587     if (i == classMethods.end())
00588     {
00589         classMethods.insert(classMethods.begin(), createPyMethodDef(
00590             methodName, dispatcher, METH_VARARGS , documentation));
00591         overloadChain.setNull();
00592     }
00593     else
00594     {
00595         LASS_ASSERT(i->ml_flags == METH_VARARGS);
00596         overloadChain.setPyCFunction(i->ml_meth);
00597         i->ml_meth = dispatcher;
00598         if (i->ml_doc == 0)
00599         {
00600             i->ml_doc = const_cast<char*>(documentation);
00601         }
00602     };
00603 }
00604 
00605 
00606 
00607 /** @internal
00608 */
00609 void addMessageHeader(const std::string& iHeader)
00610 {
00611     if (!PyErr_Occurred() || !PyErr_ExceptionMatches(PyExc_TypeError))
00612     {
00613         return;
00614     }
00615     PyObject *type, *value, *traceback;
00616     PyErr_Fetch(&type, &value, &traceback);
00617     try
00618     {
00619         if (PyString_Check(value))
00620         {
00621             std::ostringstream buffer;
00622             buffer << iHeader << ": " << PyString_AsString(value);
00623             PyObject* temp = PyString_FromString(buffer.str().c_str());
00624             std::swap(value, temp);
00625             Py_DECREF(temp);
00626         }
00627     }
00628     catch (const std::exception&)
00629     {
00630     }
00631     PyErr_Restore(type, value, traceback);
00632 }
00633 
00634 /** @internal
00635 */
00636 bool checkSequenceSize(PyObject* iValue, Py_ssize_t iExpectedSize)
00637 {
00638     if (!PySequence_Check(iValue))
00639     {
00640         PyErr_SetString(PyExc_TypeError, "not a python sequence (tuple, list, ...)");
00641         return false;
00642     }
00643     const Py_ssize_t size = PySequence_Size(iValue);
00644     if (size != iExpectedSize)
00645     {
00646         std::ostringstream buffer;
00647         buffer << "tuple/list is not of expected size " << iExpectedSize
00648             << " (size is " << size << ")";
00649         PyErr_SetString(PyExc_TypeError, buffer.str().c_str());
00650         return false;
00651     }
00652     return true;
00653 }
00654 
00655 /** @internal
00656  *  Check that @a iValue is a sequence and of expected size, and return it as a "FAST sequence"
00657  *  so that you can use PySequence_Fast_GET_ITEM to get its items with borrowed references.
00658  */
00659 TPyObjPtr checkedFastSequence(PyObject* iValue, Py_ssize_t iExpectedSize)
00660 {
00661     TPyObjPtr result(PySequence_Fast(iValue, "expected a sequence (tuple, list, ...)"));
00662     const Py_ssize_t size = PySequence_Fast_GET_SIZE(result.get());
00663     if (size != iExpectedSize)
00664     {
00665         std::ostringstream buffer;
00666         buffer << "expected a sequence of size " << iExpectedSize
00667             << " (your size is " << size << ")";
00668         PyErr_SetString(PyExc_TypeError, buffer.str().c_str());
00669         return TPyObjPtr();
00670     }
00671     return result;
00672 }
00673 
00674 }
00675 }
00676 }
00677 
00678 // EOF

Generated on Mon Nov 10 14:21:06 2008 for Library of Assembled Shared Sources by doxygen 1.5.7.1
SourceForge.net Logo