module.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002   file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/trunk/modules/python/module.cpp $
00003   version : $LastChangedRevision: 732 $  $LastChangedBy: jdetaeye $
00004   date : $LastChangedDate: 2008-04-05 17:11:47 +0200 (Sat, 05 Apr 2008) $
00005  ***************************************************************************/
00006 
00007 /***************************************************************************
00008  *                                                                         *
00009  * Copyright (C) 2007 by Johan De Taeye                                    *
00010  *                                                                         *
00011  * This library is free software; you can redistribute it and/or modify it *
00012  * under the terms of the GNU Lesser General Public License as published   *
00013  * by the Free Software Foundation; either version 2.1 of the License, or  *
00014  * (at your option) any later version.                                     *
00015  *                                                                         *
00016  * This library is distributed in the hope that it will be useful,         *
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser *
00019  * General Public License for more details.                                *
00020  *                                                                         *
00021  * You should have received a copy of the GNU Lesser General Public        *
00022  * License along with this library; if not, write to the Free Software     *
00023  * Foundation Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA *
00024  *                                                                         *
00025  ***************************************************************************/
00026 
00027 #include "embeddedpython.h"
00028 
00029 namespace module_python
00030 {
00031 
00032 const MetaClass CommandPython::metadata;
00033 const MetaClass CommandPython::metadata2;
00034 PyThreadState *CommandPython::mainThreadState = NULL;
00035 
00036 PyObject* PythonLogicException = NULL;
00037 PyObject* PythonDataException = NULL;
00038 PyObject* PythonRuntimeException = NULL;
00039 
00040 
00041 // Define the methods to be exposed into Python
00042 PyMethodDef CommandPython::PythonAPI[] =
00043   {
00044     {"log", CommandPython::python_log, METH_VARARGS,
00045      "Prints a string to the frePPLe log file."
00046     },
00047     {"readXMLdata", CommandPython::python_readXMLdata, METH_VARARGS,
00048      "Processes an XML string passed as argument."},
00049     {"readXMLfile", CommandPython::python_readXMLfile, METH_VARARGS,
00050      "Read an XML-file."},
00051     {"saveXMLfile", CommandPython::python_saveXMLfile, METH_VARARGS,
00052      "Save the model to an XML-file."},
00053     {"saveXMLstring", CommandPython::python_saveXMLstring, METH_NOARGS,
00054      "Returns the model as an XML-formatted string."},
00055     {"buffers", PythonBufferIterator::create, METH_NOARGS,
00056      "Returns an iterator over the buffers."},
00057     {"locations", PythonLocationIterator::create, METH_NOARGS,
00058      "Returns an iterator over the locations."},
00059     {"customers", PythonCustomerIterator::create, METH_NOARGS,
00060      "Returns an iterator over the customer."},
00061     {"items", PythonItemIterator::create, METH_NOARGS,
00062      "Returns an iterator over the items."},
00063     {"calendars", PythonCalendarIterator::create, METH_NOARGS,
00064      "Returns an iterator over the calendars."},
00065     {"demands", PythonDemandIterator::create, METH_NOARGS,
00066      "Returns an iterator over the demands."},
00067     {"resources", PythonResourceIterator::create, METH_NOARGS,
00068      "Returns an iterator over the resources."},
00069     {"operations", PythonOperationIterator::create, METH_NOARGS,
00070      "Returns an iterator over the operations."},
00071     {"operationplans", PythonOperationPlanIterator::create, METH_NOARGS,
00072      "Returns an iterator over the operationplans."},
00073     {"problems", PythonProblemIterator::create, METH_NOARGS,
00074      "Returns an iterator over the problems."},
00075     {"solvers", PythonSolverIterator::create, METH_NOARGS,
00076      "Returns an iterator over the solvers."},
00077     {NULL, NULL, 0, NULL}
00078   };
00079 
00080 
00081 MODULE_EXPORT const char* initialize(const CommandLoadLibrary::ParameterList& z)
00082 {
00083   // Initialize only once
00084   static bool init = false;
00085   static const char* name = "python";
00086   if (init)
00087   {
00088     logger << "Warning: Initializing module python more than once." << endl;
00089     return name;
00090   }
00091   init = true;
00092 
00093   // Initialize the metadata.
00094   CommandPython::metadata.registerClass(
00095     "command",
00096     "command_python",
00097     Object::createDefault<CommandPython>);
00098 
00099   // Register python also as a processing instruction.
00100   CommandPython::metadata2.registerClass(
00101     "instruction",
00102     "python",
00103     Object::createDefault<CommandPython>);
00104 
00105   // Initialize the interpreter
00106   CommandPython::initialize();
00107 
00108   // Return the name of the module
00109   return name;
00110 }
00111 
00112 
00113 void CommandPython::initialize()
00114 {
00115   // Initialize the interpreter and the frepple module
00116   Py_InitializeEx(0);  // The arg 0 indicates that the interpreter doesn't
00117                        // implement its own signal handler
00118   PyEval_InitThreads();  // Initializes threads and captures global lock
00119   PyObject* m = Py_InitModule3
00120       ("frepple", CommandPython::PythonAPI, "Access to the frePPLe library");
00121   if (!m)
00122   {
00123     PyEval_ReleaseLock();
00124     throw frepple::RuntimeException("Can't initialize Python interpreter");
00125   }
00126 
00127   // Make the datetime types available
00128   PyDateTime_IMPORT;
00129 
00130   // Create python exception types
00131   int nok = 0;
00132   PythonLogicException = PyErr_NewException("frepple.LogicException", NULL, NULL);
00133   Py_IncRef(PythonLogicException);
00134   nok += PyModule_AddObject(m, "LogicException", PythonLogicException);
00135   PythonDataException = PyErr_NewException("frepple.DataException", NULL, NULL);
00136   Py_IncRef(PythonDataException);
00137   nok += PyModule_AddObject(m, "DataException", PythonDataException);
00138   PythonRuntimeException = PyErr_NewException("frepple.RuntimeException", NULL, NULL);
00139   Py_IncRef(PythonRuntimeException);
00140   nok += PyModule_AddObject(m, "RuntimeException", PythonRuntimeException);
00141 
00142   // Add a string constant for the version
00143   nok += PyModule_AddStringConstant(m, "version", PACKAGE_VERSION);
00144 
00145   // Capture the main trhead state, for use during threaded execution
00146   mainThreadState = PyThreadState_Get();
00147 
00148   // Register our new types
00149   nok += PythonPlan::initialize(m);
00150   nok += PythonBuffer::initialize(m);
00151   nok += PythonBufferDefault::initialize(m);
00152   nok += PythonBufferInfinite::initialize(m);
00153   nok += PythonBufferProcure::initialize(m);
00154   nok += PythonBufferIterator::initialize(m);
00155   nok += PythonCalendar::initialize(m);
00156   nok += PythonCalendarIterator::initialize(m);
00157   nok += PythonCalendarBucket::initialize(m);
00158   nok += PythonCalendarBucketIterator::initialize(m);
00159   nok += PythonCalendarBool::initialize(m);
00160   nok += PythonCalendarVoid::initialize(m);
00161   nok += PythonCalendarDouble::initialize(m);
00162   nok += PythonCustomer::initialize(m);
00163   nok += PythonCustomerDefault::initialize(m);
00164   nok += PythonCustomerIterator::initialize(m);
00165   nok += PythonDemand::initialize(m);
00166   nok += PythonDemandIterator::initialize(m);
00167   nok += PythonDemandDefault::initialize(m);
00168   nok += PythonDemandPlanIterator::initialize(m);
00169   nok += PythonPeggingIterator::initialize(m);
00170   nok += PythonFlow::initialize(m);
00171   nok += PythonFlowIterator::initialize(m);
00172   nok += PythonFlowPlan::initialize(m);
00173   nok += PythonFlowPlanIterator::initialize(m);
00174   nok += PythonItem::initialize(m);
00175   nok += PythonItemDefault::initialize(m);
00176   nok += PythonItemIterator::initialize(m);
00177   nok += PythonLoad::initialize(m);
00178   nok += PythonLoadIterator::initialize(m);
00179   nok += PythonLoadPlan::initialize(m);
00180   nok += PythonLoadPlanIterator::initialize(m);
00181   nok += PythonLocation::initialize(m);
00182   nok += PythonLocationDefault::initialize(m);
00183   nok += PythonLocationIterator::initialize(m);
00184   nok += PythonOperation::initialize(m);
00185   nok += PythonOperationAlternate::initialize(m);
00186   nok += PythonOperationFixedTime::initialize(m);
00187   nok += PythonOperationTimePer::initialize(m);
00188   nok += PythonOperationRouting::initialize(m);
00189   nok += PythonOperationIterator::initialize(m);
00190   nok += PythonOperationPlan::initialize(m);
00191   nok += PythonOperationPlanIterator::initialize(m);
00192   nok += PythonProblem::initialize(m);
00193   nok += PythonProblemIterator::initialize(m);
00194   nok += PythonResource::initialize(m);
00195   nok += PythonResourceDefault::initialize(m);
00196   nok += PythonResourceInfinite::initialize(m);
00197   nok += PythonResourceIterator::initialize(m);
00198   nok += PythonSolver::initialize(m);
00199   nok += PythonSolverIterator::initialize(m);
00200   nok += PythonSolverMRP::initialize(m);
00201 
00202   // Redirect the stderr and stdout streams of Python
00203   PyRun_SimpleString(
00204     "import frepple, sys\n"
00205     "class redirect:\n"
00206     "\tdef write(self,str):\n"
00207     "\t\tfrepple.log(str)\n"
00208     "sys.stdout = redirect()\n"
00209     "sys.stderr = redirect()"
00210   );
00211 
00212   // Search and execute the initialization file '$FREPPLE_HOME/init.py'
00213   string init = Environment::getHomeDirectory() + "init.py";
00214   struct stat stat_p;
00215   if (!nok && !stat(init.c_str(), &stat_p))
00216   {
00217     // Initialization file exists
00218     PyObject *m = PyImport_AddModule("__main__");
00219     if (!m)
00220     {
00221       PyEval_ReleaseLock();
00222       throw frepple::RuntimeException("Can't execute Python script 'init.py'");
00223     }
00224     PyObject *d = PyModule_GetDict(m);
00225     if (!d)
00226     {
00227       PyEval_ReleaseLock();
00228       throw frepple::RuntimeException("Can't execute Python script 'init.py'");
00229     }
00230     init = "execfile('" + init + "')\n";
00231     PyObject *v = PyRun_String(init.c_str(), Py_file_input, d, d);
00232     if (!v)
00233     {
00234       // Print the error message
00235       PyErr_Print();
00236       // Release the lock
00237       PyEval_ReleaseLock();
00238       throw frepple::RuntimeException("Error executing Python script 'init.py'");
00239     }
00240     Py_DECREF(v);
00241     if (Py_FlushLine()) PyErr_Clear();
00242   }
00243 
00244   // Release the lock
00245   PyEval_ReleaseLock();
00246 
00247   // A final check...
00248   if (nok || !mainThreadState)
00249     throw frepple::RuntimeException("Can't initialize Python interpreter");
00250 }
00251 
00252 
00253 } // End namespace

Documentation generated by  doxygen