![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /******************************************************************************* 00002 * This file is part of openWNS (open Wireless Network Simulator) 00003 * _____________________________________________________________________________ 00004 * 00005 * Copyright (C) 2004-2007 00006 * Chair of Communication Networks (ComNets) 00007 * Kopernikusstr. 16, D-52074 Aachen, Germany 00008 * phone: ++49-241-80-27910, 00009 * fax: ++49-241-80-22242 00010 * email: info@openwns.org 00011 * www: http://www.openwns.org 00012 * _____________________________________________________________________________ 00013 * 00014 * openWNS is free software; you can redistribute it and/or modify it under the 00015 * terms of the GNU Lesser General Public License version 2 as published by the 00016 * Free Software Foundation; 00017 * 00018 * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY 00019 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00020 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00021 * details. 00022 * 00023 * You should have received a copy of the GNU Lesser General Public License 00024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00025 * 00026 ******************************************************************************/ 00027 00028 // Since Python may define some pre-processor definitions which affect the 00029 // standard headers on some systems, you must include Python.h before any 00030 // standard headers are included. 00031 #include <WNS/Python.hpp> 00032 00033 #include <WNS/pyconfig/View.hpp> 00034 #include <WNS/Exception.hpp> 00035 #include <WNS/Assure.hpp> 00036 00037 #include <sstream> 00038 #include <iostream> 00039 #include <csignal> 00040 00041 using namespace wns::pyconfig; 00042 00043 View::View() : 00044 dict(NULL), 00045 viewExpression() 00046 { 00047 ++View::getCount(); 00048 this->initializePython(); 00049 } 00050 00051 View::View(const View& other, const std::string &newViewExpression) : 00052 dict(NULL), 00053 viewExpression("") 00054 { 00055 ++View::getCount(); 00056 this->initializePython(); 00057 00058 assure(!PyErr_Occurred(), "Dirty python context!"); 00059 00060 Object pyObject = other.getObject(newViewExpression); 00061 if(pyObject.isNull()) 00062 { 00063 other.couldntRetrieve(newViewExpression); 00064 this->showdown("Couldn't resolve viewExpression."); 00065 } 00066 00067 // not needed any longer 00068 pyObject.decref(); 00069 00070 std::stringstream ss; 00071 // the following python code snippet creates the context 00072 // for the new view. 00073 // View is a subclass of dict. you can find View in the 00074 // pyconfig::Parser module of the wns package. 00075 ss << "__import__('openwns.pyconfig').pyconfig.View(" << newViewExpression << ")"; 00076 00077 this->dict = Object(PyRun_String(ss.str().c_str(), 00078 Py_eval_input, 00079 other.dict.obj_, 00080 other.dict.obj_)); 00081 if(this->dict.isNull()) 00082 { 00083 other.couldntRetrieve(newViewExpression); 00084 showdown("Couldn't resolve viewExpression."); 00085 } 00086 assert(!this->dict.isNull()); 00087 00088 this->viewExpression = other.viewExpression + "::" + newViewExpression; 00089 } // View 00090 00091 00092 View::View(const View& other, const std::string &newViewExpression, int at) : 00093 dict(NULL), 00094 viewExpression("") 00095 { 00096 ++View::getCount(); 00097 this->initializePython(); 00098 assure(!PyErr_Occurred(), "Dirty python context!"); 00099 00100 std::stringstream subscription; 00101 subscription << newViewExpression << "[" << at << "]"; 00102 00103 Object pyObject = other.getObject(subscription.str()); 00104 if(pyObject.isNull()) 00105 { 00106 other.couldntRetrieve(newViewExpression); 00107 showdown("Couldn't resolve viewExpression."); 00108 } 00109 00110 // Not needed any longer 00111 pyObject.decref(); 00112 00113 { 00114 std::stringstream ss; 00115 ss << "__import__('openwns.pyconfig').pyconfig.View(" 00116 << newViewExpression 00117 << "[" << at << "]" 00118 << ")"; 00119 00120 dict = Object(PyRun_String(ss.str().c_str(), 00121 Py_eval_input, 00122 other.dict.obj_, 00123 other.dict.obj_)); 00124 assert(!dict.isNull()); 00125 } 00126 00127 { 00128 std::stringstream ss; 00129 00130 ss << other.viewExpression 00131 << "::" << newViewExpression << "[" << at << "]"; 00132 viewExpression = ss.str(); 00133 } 00134 } // View 00135 00136 00137 View::View(const Sequence& seq, int at) : 00138 dict(NULL), 00139 viewExpression("") 00140 { 00141 ++View::getCount(); 00142 this->initializePython(); 00143 assure(!PyErr_Occurred(), "Dirty python context!"); 00144 00145 assure(!seq.isSequenceAt(at), "Trying to create pyconfig::View from nested sequence!"); 00146 00147 Object pyDict(PyDict_New()); 00148 assure(!pyDict.isNull(), "Creation of Python Dict Failed"); 00149 00150 int result = PyDict_SetItemString(pyDict.obj_, "dummy", seq.sequence.obj_); 00151 assure(result==0, "Inserting of element into Dict failed!"); 00152 00153 result = PyDict_SetItemString(pyDict.obj_, "__builtins__", PyImport_ImportModule("__builtin__")); 00154 assure(result==0, "Initializing __builtins__ failed!"); 00155 00156 { 00157 std::stringstream ss; 00158 ss << "__import__('openwns.pyconfig').pyconfig.View(" 00159 << "dummy[" << at << "]" 00160 << ")"; 00161 00162 dict = Object(PyRun_String(ss.str().c_str(), 00163 Py_eval_input, 00164 pyDict.obj_, 00165 pyDict.obj_)); 00166 if (dict.isNull()) 00167 showdown("couldn't create View from sequence item!", true); 00168 } 00169 pyDict.decref(); 00170 00171 { 00172 std::stringstream ss; 00173 00174 ss << seq.pathName << "[" << at << "]"; 00175 viewExpression = ss.str(); 00176 } 00177 } 00178 00179 View::~View() 00180 { 00181 // can happen that dict is NULL if View() has been called but not object 00182 // has not been used. 00183 if(!dict.isNull()) 00184 { 00185 dict.decref(); 00186 } 00187 00188 --View::getCount(); 00189 this->finalizePython(); 00190 } //~View 00191 00192 wns::pyconfig::View 00193 View::getView(const std::string& newViewExpression) const 00194 { 00195 return View(*this, newViewExpression); 00196 } // getView 00197 00198 wns::pyconfig::Sequence 00199 View::getSequence(const std::string& sequenceExpression) const 00200 { 00201 if (!this->isSequence(sequenceExpression)) 00202 { 00203 Exception e; 00204 e << "Cannot retrieve sequence named '" << sequenceExpression 00205 << "' from this view.\n\n" 00206 << "Context: " << this->context() << "\n\n" 00207 << "Content: " << this->asString() << "\n\n"; 00208 throw e; 00209 } 00210 return pyconfig::Sequence(getObject(sequenceExpression), 00211 this->viewExpression+"::"+sequenceExpression); 00212 } // getSequence 00213 00214 wns::pyconfig::View 00215 View::getView(const std::string& newViewExpression, int at) const 00216 { 00217 return View(*this, newViewExpression, at); 00218 } // getView 00219 00220 Object 00221 View::getObject(const std::string& optionExpression) const 00222 { 00223 assure(!PyErr_Occurred(), "Dirty python context!"); 00224 00225 return Object(PyRun_String(optionExpression.c_str(), 00226 Py_eval_input, 00227 dict.obj_, 00228 dict.obj_)); 00229 } // getObject 00230 00231 00232 Object 00233 View::getObject(const std::string& optionExpression, int at) const 00234 { 00235 Object seq = getObject(optionExpression); 00236 if(seq.isNull()) 00237 { 00238 return Object(); 00239 } 00240 00241 if(!PySequence_Check(seq.obj_)) 00242 { 00243 seq.decref(); 00244 return Object(); 00245 } 00246 00247 Object o(PySequence_GetItem(seq.obj_, at)); 00248 seq.decref(); 00249 00250 return o; 00251 } // getObject 00252 00253 00254 bool 00255 View::len(int& result, const std::string& optionExpression) const 00256 { 00257 assure(!PyErr_Occurred(), "Dirty python context!"); 00258 00259 Object o = getObject(optionExpression); 00260 if(o.isNull()) 00261 { 00262 PyErr_Clear(); 00263 return false; 00264 } 00265 00266 if(!PySequence_Check(o.obj_)) 00267 { 00268 o.decref(); 00269 return false; 00270 } 00271 00272 result = PySequence_Length(o.obj_); 00273 o.decref(); 00274 return true; 00275 } // len 00276 00277 00278 int 00279 View::len(const std::string& optionExpression) const 00280 { 00281 assure(!PyErr_Occurred(), "Dirty python context!"); 00282 00283 int result; 00284 00285 if(!len(result, optionExpression)) 00286 { 00287 couldntRetrieve(optionExpression); 00288 00289 showdown("Unknown thang in View::len."); 00290 } 00291 00292 return result; 00293 } // len 00294 00295 bool 00296 View::knows(const std::string& optionExpression) const 00297 { 00298 assure(!PyErr_Occurred(), "Dirty python context!"); 00299 00300 Object o = getObject(optionExpression); 00301 if(o.isNull()) 00302 { 00303 PyErr_Clear(); 00304 return false; 00305 } 00306 00307 o.decref(); 00308 return true; 00309 } // knows 00310 00311 long long int 00312 View::getId() const 00313 { 00314 // id(object) returns long long since python2.5 00315 // Using PY_LONG_LONG here yields a compile error 00316 // if PY_LONG_LONG cannot be converted to long long int, 00317 // which moves the problem from runtime to compile time 00318 // fixes bug lp:174730 00319 return get<PY_LONG_LONG>("__id__"); 00320 } // getId 00321 00322 std::string 00323 View::context() const 00324 { 00325 return viewExpression; 00326 } // context 00327 00328 00329 void 00330 View::patch(const std::string& expression) 00331 { 00332 assure(!PyErr_Occurred(), "Dirty python context!"); 00333 00334 Object o(PyRun_String(expression.c_str(), Py_file_input, dict.obj_, dict.obj_)); 00335 if(o.isNull()) 00336 { 00337 showdown("couldn't patch View.", true); 00338 } 00339 00340 o.decref(); 00341 } // patch 00342 00343 bool 00344 View::isNone(const std::string& expression) const 00345 { 00346 Object o = this->getObject(expression); 00347 bool isNone = o.isNone(); 00348 o.decref(); 00349 return isNone; 00350 } // isNone 00351 00352 bool 00353 View::isSequence(const std::string& expression) const 00354 { 00355 Object o = this->getObject(expression); 00356 00357 if(o.isNull()) 00358 { 00359 this->couldntRetrieve(expression); 00360 this->showdown("Couldn't resolve viewExpression."); 00361 } 00362 00363 if (PySequence_Check(o.obj_) == 1) 00364 { 00365 o.decref(); 00366 return true; 00367 } 00368 else 00369 { 00370 o.decref(); 00371 return false; 00372 } 00373 } 00374 00375 View::View(const View& other) 00376 { 00377 ++View::getCount(); 00378 this->initializePython(); 00379 viewExpression = other.viewExpression; 00380 dict = other.dict; 00381 dict.incref(); 00382 } // copy constructor 00383 00384 00385 View& 00386 View::operator=(const View& other) 00387 { 00388 viewExpression = other.viewExpression; 00389 dict = other.dict; 00390 dict.incref(); 00391 00392 return *this; 00393 } // assignment operator 00394 00395 00396 bool 00397 View::operator==(const View& other) const 00398 { 00399 return getId() == other.getId(); 00400 } // equality operator 00401 00402 bool 00403 View::operator!=(const View& other) const 00404 { 00405 return !(*this == other); 00406 } // inequality operator 00407 00408 bool 00409 View::operator<(const View& other) const 00410 { 00411 return getId() < other.getId(); 00412 } // less than operator 00413 00414 bool 00415 View::doConvert(bool& value, Object o) const 00416 { 00417 switch(PyObject_IsTrue(o.obj_)) 00418 { 00419 case 1: 00420 value = true; 00421 break; 00422 case 0: 00423 value = false; 00424 break; 00425 default: 00426 return false; 00427 } 00428 00429 return true; 00430 } // convert 00431 00432 bool 00433 View::doConvert(std::string& value, Object o) const 00434 { 00435 if(!o.isConvertibleToString()) 00436 { 00437 return false; 00438 } 00439 00440 value = o.toString(); 00441 00442 return true; 00443 } // convert 00444 00445 void 00446 View::couldntRetrieve(const std::string& optionExpression) const 00447 { 00448 std::cerr << "PyConfig says:\n" 00449 << "The configuration entry " 00450 << "'" << optionExpression << "' " 00451 << "could not be retrieved from:\n " 00452 << context() << "\n" 00453 << "Following configuration entries are available:\n"; 00454 { 00455 PyObject *ptype, *pvalue, *ptraceback; 00456 PyErr_Fetch(&ptype, &pvalue, &ptraceback); 00457 00458 PyRun_String( 00459 "__import__('sys').stderr.write( __visible__ + '\\n')\n", 00460 Py_file_input, 00461 dict.obj_, 00462 dict.obj_); 00463 00464 PyErr_Restore(ptype, pvalue, ptraceback); 00465 } 00466 } // couldntRetrieve 00467 00468 00469 void 00470 View::showdown(const std::string& reason, bool raise) const 00471 { 00472 std::cerr << "PyConfig says:\n"; 00473 PyErr_Print(); 00474 std::cerr << "\n"; 00475 00476 PyErr_Clear(); 00477 00478 if(raise) 00479 throw Exception(reason); 00480 } // showdown 00481 00482 std::string 00483 View::asString() const 00484 { 00485 return this->get<std::string>("__stringRepresentation__"); 00486 } // asString 00487 00488 void 00489 View::initializePython() 00490 { 00491 if(View::getCount() == 1) 00492 { 00493 assure(Py_IsInitialized() == false, "called initializePython() although interpreter is already initialized!"); 00494 void (*handler)(int); 00495 handler = std::signal(2, SIG_DFL); 00496 Py_Initialize(); 00497 std::signal(2, handler); 00498 } 00499 } 00500 00501 void 00502 View::finalizePython() 00503 { 00504 if(View::getCount() == 0) 00505 { 00506 assure(Py_IsInitialized() == true, "called finalizePython although interpreter has not been initialized!"); 00507 void (*handler)(int); 00508 handler = std::signal(2, SIG_DFL); 00509 Py_Finalize(); 00510 std::signal(2, handler); 00511 } 00512 } 00513 00514 int& 00515 View::getCount() 00516 { 00517 static int count = 0; 00518 assure(count >=0, "Internal reference counting is broken!"); 00519 return count; 00520 } 00521 00522 00523
1.5.5