00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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
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
00096
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
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
00116 dict_ = PyDict_Copy(iOther.dict_);
00117 #endif
00118 return *this;
00119 }
00120
00121
00122
00123
00124
00125
00126
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
00144
00145 namespace impl
00146 {
00147
00148
00149
00150 void dealloc(PyObject* obj)
00151 {
00152 delete static_cast<PyObjectPlus*>(obj);
00153 };
00154
00155
00156
00157 PyObject* repr(PyObject* obj)
00158 {
00159 return pyBuildSimpleObject(static_cast<PyObjectPlus*>(obj)->doPyRepr());
00160 }
00161
00162
00163
00164 PyObject* str(PyObject* obj)
00165 {
00166 return pyBuildSimpleObject(static_cast<PyObjectPlus*>(obj)->doPyStr());
00167 }
00168
00169
00170
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
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
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
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
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
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
00426
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
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
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
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
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
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
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
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
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
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
00656
00657
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