Now the python interpreter is loaded in Initialization plugin and accessible for any expression evaluation even if no parameters were created.
-
INCLUDE(Common)
+INCLUDE(FindPython)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events
${PROJECT_SOURCE_DIR}/src/Config
${PROJECT_SOURCE_DIR}/src/ModelAPI
${PROJECT_SOURCE_DIR}/src/GeomAPI
+ ${PROJECT_SOURCE_DIR}/src/GeomDataAPI
+ ${PROJECT_SOURCE_DIR}/src/ParametersPlugin
+ ${SUIT_INCLUDE}
+ ${PYTHON_INCLUDE_DIR}
)
SET(PROJECT_HEADERS
InitializationPlugin.h
InitializationPlugin_Plugin.h
- #InitializationPlugin_OriginPlanesFeature.h
+ InitializationPlugin_EvalListener.h
+ InitializationPlugin_PyInterp.h
)
SET(PROJECT_SOURCES
InitializationPlugin_Plugin.cpp
- #InitializationPlugin_OriginPlanesFeature.cpp
+ InitializationPlugin_EvalListener.cpp
+ InitializationPlugin_PyInterp.cpp
)
-#SET(XML_RESOURCES
-#)
+MESSAGE(STATUS "PYTHON_LIBRARIES (ParametersPlugin): ${PYTHON_LIBRARIES}")
SET(PROJECT_LIBRARIES
Events
Config
ModelAPI
+ ${PyInterp}
+ ${PYTHON_LIBRARIES}
)
-ADD_DEFINITIONS(-DINITIALIZATIONPLUGIN_EXPORTS)
+ADD_DEFINITIONS(-DINITIALIZATIONPLUGIN_EXPORTS -DHAVE_DEBUG_PYTHON)
ADD_LIBRARY(InitializationPlugin MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES})
TARGET_LINK_LIBRARIES(InitializationPlugin ${PROJECT_LIBRARIES})
INSTALL(TARGETS InitializationPlugin DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
#INSTALL(FILES ${XML_RESOURCES} DESTINATION plugins)
+
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+/*
+ * InitializationPlugin_EvalListener.cpp
+ *
+ * Created on: Apr 28, 2015
+ * Author: sbh
+ */
+
+#include <pyconfig.h>
+
+#include <InitializationPlugin_EvalListener.h>
+#include <ParametersPlugin_Parameter.h>
+#include <InitializationPlugin_PyInterp.h>
+
+#include <Events_InfoMessage.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeValidator.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Events.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Tools.h>
+
+#include <GeomDataAPI_Point.h>
+#include <GeomDataAPI_Point2D.h>
+
+#include <string>
+#include <set>
+#include <sstream>
+
+//------------------------------------------------------------------------------
+// Tools
+
+std::string toStdString(double theValue)
+{
+ std::ostringstream sstream;
+ sstream << theValue;
+ size_t aPos = sstream.str().find(".");
+ std::string aPnt = "";
+ if (aPos == std::string::npos)
+ aPnt = ".";
+ return sstream.str() + aPnt;
+}
+
+std::set<std::string> toSet(const std::list<std::string>& theContainer)
+{
+ return std::set<std::string>(theContainer.begin(), theContainer.end());
+}
+
+//------------------------------------------------------------------------------
+
+InitializationPlugin_EvalListener::InitializationPlugin_EvalListener()
+{
+ Events_Loop* aLoop = Events_Loop::loop();
+
+ aLoop->registerListener(this, ModelAPI_AttributeEvalMessage::eventId(), NULL, true);
+ aLoop->registerListener(this, ModelAPI_ParameterEvalMessage::eventId(), NULL, true);
+ aLoop->registerListener(this, ModelAPI_ComputePositionsMessage::eventId(), NULL, true);
+
+ myInterp = std::shared_ptr<InitializationPlugin_PyInterp>(new InitializationPlugin_PyInterp());
+ myInterp->initialize();
+}
+
+InitializationPlugin_EvalListener::~InitializationPlugin_EvalListener()
+{
+}
+
+void InitializationPlugin_EvalListener::processEvent(
+ const std::shared_ptr<Events_Message>& theMessage)
+{
+ if (!theMessage.get())
+ return;
+
+ if (theMessage->eventID() == ModelAPI_AttributeEvalMessage::eventId()) {
+ processEvaluationEvent(theMessage);
+ } else if (theMessage->eventID() == ModelAPI_ParameterEvalMessage::eventId()) {
+ std::shared_ptr<ModelAPI_ParameterEvalMessage> aMsg =
+ std::dynamic_pointer_cast<ModelAPI_ParameterEvalMessage>(theMessage);
+ FeaturePtr aParam = aMsg->parameter();
+ std::string anExp = aParam->string(ParametersPlugin_Parameter::EXPRESSION_ID())->value();
+ std::string anError;
+ std::list<std::shared_ptr<ModelAPI_ResultParameter> > aParamsList;
+ double aResult = evaluate(aParam, anExp, anError, aParamsList, true);
+ aMsg->setResults(aParamsList, aResult, anError);
+ } else if (theMessage->eventID() == ModelAPI_ComputePositionsMessage::eventId()) {
+ std::shared_ptr<ModelAPI_ComputePositionsMessage> aMsg =
+ std::dynamic_pointer_cast<ModelAPI_ComputePositionsMessage>(theMessage);
+ aMsg->setPositions(myInterp->positions(aMsg->expression(), aMsg->parameter()));
+ }
+}
+
+double InitializationPlugin_EvalListener::evaluate(FeaturePtr theParameter,
+ const std::string& theExpression, std::string& theError,
+ std::list<std::shared_ptr<ModelAPI_ResultParameter> >& theParamsList,
+ const bool theIsParameter)
+{
+ std::list<std::string> anExprParams = myInterp->compile(theExpression);
+ // find expression's params in the model
+ std::list<std::string> aContext;
+ std::list<std::string>::iterator it = anExprParams.begin();
+ for ( ; it != anExprParams.end(); it++) {
+ double aValue;
+ ResultParameterPtr aParamRes;
+ // If variable does not exist python interpreter will generate an error. It is OK.
+ // But due to the issue 1479 it should not check the history position of parameters relatively
+ // to feature that contains expression
+ if (!ModelAPI_Tools::findVariable(theIsParameter ? theParameter : FeaturePtr(),
+ *it, aValue, aParamRes, theParameter->document()))
+ continue;
+
+ if (theIsParameter)
+ theParamsList.push_back(aParamRes);
+ aContext.push_back(*it + "=" + toStdString(aValue));
+ }
+ myInterp->extendLocalContext(aContext);
+ double result = myInterp->evaluate(theExpression, theError);
+ myInterp->clearLocalContext();
+ return result;
+}
+
+void InitializationPlugin_EvalListener::processEvaluationEvent(
+ const std::shared_ptr<Events_Message>& theMessage)
+{
+ std::shared_ptr<ModelAPI_AttributeEvalMessage> aMessage =
+ std::dynamic_pointer_cast<ModelAPI_AttributeEvalMessage>(theMessage);
+
+ std::list<std::shared_ptr<ModelAPI_ResultParameter> > aParamsList;
+ FeaturePtr aParamFeature =
+ std::dynamic_pointer_cast<ModelAPI_Feature>(aMessage->attribute()->owner());
+ if (aMessage->attribute()->attributeType() == ModelAPI_AttributeInteger::typeId()) {
+ AttributeIntegerPtr anAttribute =
+ std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(aMessage->attribute());
+ std::string anError;
+ int aValue = (int)evaluate(aParamFeature, anAttribute->text(), anError, aParamsList);
+ bool isValid = anError.empty();
+ if (isValid)
+ anAttribute->setCalculatedValue(aValue);
+ anAttribute->setUsedParameters(isValid ?
+ toSet(myInterp->compile(anAttribute->text())) : std::set<std::string>());
+ anAttribute->setExpressionInvalid(!isValid);
+ anAttribute->setExpressionError(anAttribute->text().empty() ? "" : anError);
+ } else
+ if (aMessage->attribute()->attributeType() == ModelAPI_AttributeDouble::typeId()) {
+ AttributeDoublePtr anAttribute =
+ std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aMessage->attribute());
+ std::string anError;
+ double aValue = evaluate(aParamFeature, anAttribute->text(), anError, aParamsList);
+ bool isValid = anError.empty();
+ if (isValid)
+ anAttribute->setCalculatedValue(aValue);
+ anAttribute->setUsedParameters(isValid ?
+ toSet(myInterp->compile(anAttribute->text())) : std::set<std::string>());
+ anAttribute->setExpressionInvalid(!isValid);
+ anAttribute->setExpressionError(anAttribute->text().empty() ? "" : anError);
+ } else
+ if (aMessage->attribute()->attributeType() == GeomDataAPI_Point::typeId()) {
+ AttributePointPtr anAttribute =
+ std::dynamic_pointer_cast<GeomDataAPI_Point>(aMessage->attribute());
+ std::string aText[] = {
+ anAttribute->textX(),
+ anAttribute->textY(),
+ anAttribute->textZ()
+ };
+ double aCalculatedValue[] = {
+ anAttribute->x(),
+ anAttribute->y(),
+ anAttribute->z()
+ };
+ for (int i = 0; i < 3; ++i) {
+ std::string anError;
+ double aValue = evaluate(aParamFeature, aText[i], anError, aParamsList);
+ bool isValid = anError.empty();
+ if (isValid) aCalculatedValue[i] = aValue;
+ anAttribute->setUsedParameters(i,
+ isValid ? toSet(myInterp->compile(aText[i])) : std::set<std::string>());
+ anAttribute->setExpressionInvalid(i, !isValid);
+ anAttribute->setExpressionError(i, aText[i].empty() ? "" : anError);
+ }
+ anAttribute->setCalculatedValue(aCalculatedValue[0],
+ aCalculatedValue[1],
+ aCalculatedValue[2]);
+ } else
+ if (aMessage->attribute()->attributeType() == GeomDataAPI_Point2D::typeId()) {
+ AttributePoint2DPtr anAttribute =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aMessage->attribute());
+ std::string aText[] = {
+ anAttribute->textX(),
+ anAttribute->textY()
+ };
+ double aCalculatedValue[] = {
+ anAttribute->x(),
+ anAttribute->y()
+ };
+ for (int i = 0; i < 2; ++i) {
+ std::string anError;
+ double aValue = evaluate(aParamFeature, aText[i], anError, aParamsList);
+ bool isValid = anError.empty();
+ if (isValid) aCalculatedValue[i] = aValue;
+ anAttribute->setUsedParameters(i,
+ isValid ? toSet(myInterp->compile(aText[i])) : std::set<std::string>());
+ anAttribute->setExpressionInvalid(i, !isValid);
+ anAttribute->setExpressionError(i, aText[i].empty() ? "" : anError);
+ }
+ anAttribute->setCalculatedValue(aCalculatedValue[0],
+ aCalculatedValue[1]);
+ }
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+/*
+ * InitializationPlugin_EvalListener.h
+ *
+ * Created on: Apr 28, 2015
+ * Author: sbh
+ */
+
+#ifndef SRC_INITIALIZATIONPLUGIN_EVALLISTENER_H_
+#define SRC_INITIALIZATIONPLUGIN_EVALLISTENER_H_
+
+#include <InitializationPlugin.h>
+#include <Events_Loop.h>
+
+class ModelAPI_Attribute;
+class ModelAPI_Document;
+class ModelAPI_Feature;
+class ModelAPI_ResultParameter;
+class InitializationPlugin_Parameter;
+class InitializationPlugin_PyInterp;
+
+/**
+ * \class InitializationPlugin_EvalListener
+ * \ingroup Plugins
+ * \brief Class which process the events from the event loop.
+ */
+class InitializationPlugin_EvalListener : public Events_Listener
+{
+ public:
+ INITIALIZATIONPLUGIN_EXPORT InitializationPlugin_EvalListener();
+ INITIALIZATIONPLUGIN_EXPORT virtual ~InitializationPlugin_EvalListener();
+
+ /// Reimplemented from Events_Listener::processEvent().
+ INITIALIZATIONPLUGIN_EXPORT
+ virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+ protected:
+ /// Evaluates theExpression and returns its value.
+ double evaluate(std::shared_ptr<ModelAPI_Feature> theParameter,
+ const std::string& theExpression, std::string& theError,
+ std::list<std::shared_ptr<ModelAPI_ResultParameter> >& theParamsList,
+ const bool theIsParameter = false);
+
+ /// Processes Evaluation event.
+ void processEvaluationEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+ private:
+ std::shared_ptr<InitializationPlugin_PyInterp> myInterp;
+};
+
+#endif /* SRC_INITIALIZATIONPLUGIN_INITIALIZATIONPLUGIN_EVALLISTENER_H_ */
#include <InitializationPlugin_Plugin.h>
+#include <InitializationPlugin_EvalListener.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Document.h>
#include <ModelAPI_AttributeBoolean.h>
Events_Loop* aLoop = Events_Loop::loop();
const Events_ID kDocCreatedEvent = ModelAPI_DocumentCreatedMessage::eventId();
aLoop->registerListener(this, kDocCreatedEvent, NULL, true);
+
+ myEvalListener =
+ std::shared_ptr<InitializationPlugin_EvalListener>(new InitializationPlugin_EvalListener());
}
void InitializationPlugin_Plugin::processEvent(const std::shared_ptr<Events_Message>& theMessage)
#define INITIALIZATIONPLUGIN_PLUGIN_H_
#include <InitializationPlugin.h>
-
#include <ModelAPI_Feature.h>
#include <Events_Loop.h>
+class InitializationPlugin_EvalListener;
+
/**\class InitializationPlugin_Plugin
* \ingroup Plugins
* This class is represents a plugin.
/// \param theZ - Z of direction point
FeaturePtr createAxis(DocumentPtr theDoc, FeaturePtr theOrigin,
double theX, double theY, double theZ);
+
+ private:
+ std::shared_ptr<InitializationPlugin_EvalListener> myEvalListener;
};
#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+/*
+ * InitializationPlugin_PyInterp.cpp
+ *
+ * Created on: Apr 2, 2015
+ * Author: sbh
+ */
+
+#include <InitializationPlugin_PyInterp.h>
+
+#include <string>
+#include <stdexcept>
+
+InitializationPlugin_PyInterp::InitializationPlugin_PyInterp()
+: PyInterp_Interp()
+{
+}
+
+InitializationPlugin_PyInterp::~InitializationPlugin_PyInterp()
+{
+}
+
+const char* aSearchCode =
+ "import ast\n"
+ "class FindName(ast.NodeVisitor):\n"
+ " def __init__(self, name):\n"
+ " self.name = name\n"
+ " def visit_Name(self, node):\n"
+ " if node.id == self.name:\n"
+ " positions.append((node.lineno, node.col_offset))\n"
+ "FindName(name).visit(ast.parse(expression))";
+
+std::list<std::pair<int, int> >
+InitializationPlugin_PyInterp::positions(const std::string& theExpression,
+ const std::string& theName)
+{
+ PyLockWrapper lck; // Acquire GIL until the end of the method
+
+ std::list<std::pair<int, int> > aResult;
+
+ // prepare a context
+ PyObject* aContext = PyDict_New();
+ PyObject* aBuiltinModule = PyImport_AddModule("__builtin__");
+ PyDict_SetItemString(aContext, "__builtins__", aBuiltinModule);
+
+ // extend aContext with variables
+ PyDict_SetItemString(aContext, "expression", PyString_FromString(theExpression.c_str()));
+ PyDict_SetItemString(aContext, "name", PyString_FromString(theName.c_str()));
+ PyDict_SetItemString(aContext, "positions", Py_BuildValue("[]"));
+
+ // run the search code
+ PyObject* aExecResult = PyRun_String(aSearchCode, Py_file_input, aContext, aContext);
+ Py_XDECREF(aExecResult);
+
+ // receive results from context
+ PyObject* aPositions = PyDict_GetItemString(aContext, "positions");
+ for (int anIndex = 0; anIndex < PyList_Size(aPositions); ++anIndex) {
+ PyObject* aPosition = PyList_GetItem(aPositions, anIndex);
+ PyObject* aLineNo = PyTuple_GetItem(aPosition, 0);
+ PyObject* aColOffset = PyTuple_GetItem(aPosition, 1);
+
+ aResult.push_back(
+ std::pair<int, int>((int)PyInt_AsLong(aLineNo),
+ (int)PyInt_AsLong(aColOffset)));
+ }
+
+ // TODO(spo): after this refCount of the variable is not 0. Is there memory leak?
+ Py_DECREF(aContext);
+
+ return aResult;
+}
+
+
+std::list<std::string> InitializationPlugin_PyInterp::compile(const std::string& theExpression)
+{
+ PyLockWrapper lck; // Acquire GIL until the end of the method
+ std::list<std::string> aResult;
+ PyObject *aCodeopModule = PyImport_AddModule("codeop");
+ if(!aCodeopModule) { // Fatal error. No way to go on.
+ PyErr_Print();
+ return aResult;
+ }
+
+ PyObject *aCodePyObj =
+ PyObject_CallMethod(aCodeopModule, (char*)"compile_command", (char*)"(s)",
+ theExpression.c_str());
+
+ if(!aCodePyObj || aCodePyObj == Py_None || !PyCode_Check(aCodePyObj)) {
+ Py_XDECREF(aCodePyObj);
+ return aResult;
+ }
+
+ PyCodeObject* aCodeObj = (PyCodeObject*) aCodePyObj;
+ std::string aCodeName(PyString_AsString(aCodeObj->co_code));
+ // co_names should be tuple, but can be changed in modern versions of python (>2.7.3)
+ if(!PyTuple_Check(aCodeObj->co_names))
+ return aResult;
+
+ size_t params_size = PyTuple_Size(aCodeObj->co_names);
+ if (params_size > 0) {
+ for (size_t i = 0; i < params_size; i++) {
+ PyObject* aParamObj = PyTuple_GetItem(aCodeObj->co_names, i);
+ PyObject* aParamObjStr = PyObject_Str(aParamObj);
+ std::string aParamName(PyString_AsString(aParamObjStr));
+ aResult.push_back(aParamName);
+ Py_XDECREF(aParamObjStr);
+ }
+ }
+ Py_XDECREF(aCodeObj);
+ return aResult;
+}
+
+void InitializationPlugin_PyInterp::extendLocalContext(const std::list<std::string>& theParameters)
+{
+ PyLockWrapper lck; // Acquire GIL until the end of the method
+ if (theParameters.empty())
+ return;
+ std::list<std::string>::const_iterator it = theParameters.begin();
+ for ( ; it != theParameters.cend(); it++) {
+ std::string aParamValue = *it;
+ simpleRun(aParamValue.c_str(), false);
+ }
+}
+
+void InitializationPlugin_PyInterp::clearLocalContext()
+{
+ PyLockWrapper lck;
+ PyDict_Clear(_local_context);
+}
+
+double InitializationPlugin_PyInterp::evaluate(const std::string& theExpression, std::string& theError)
+{
+ PyLockWrapper lck; // Acquire GIL until the end of the method
+ PyCompilerFlags aFlags = {CO_FUTURE_DIVISION};
+ aFlags.cf_flags = CO_FUTURE_DIVISION;
+ PyCodeObject* anExprCode = (PyCodeObject *) Py_CompileStringFlags(theExpression.c_str(),
+ "<string>", Py_eval_input, &aFlags);
+ if(!anExprCode) {
+ theError = errorMessage();
+ Py_XDECREF(anExprCode);
+ return 0.;
+ }
+
+ PyObject* anEvalResult = PyEval_EvalCode(anExprCode, _global_context, _local_context);
+ if(!anEvalResult) {
+ theError = errorMessage();
+ Py_XDECREF(anExprCode);
+ Py_XDECREF(anEvalResult);
+ return 0.;
+ }
+
+ PyObject* anEvalStrObj = PyObject_Str(anEvalResult);
+ std::string anEvalStr(PyString_AsString(anEvalStrObj));
+ Py_XDECREF(anExprCode);
+ Py_XDECREF(anEvalResult);
+ Py_XDECREF(anEvalStrObj);
+ double result = 0.;
+ try {
+ result = std::stod(anEvalStr);
+ } catch (const std::invalid_argument&) {
+ theError = "Unable to eval " + anEvalStr;
+ }
+
+ return result;
+}
+
+std::string InitializationPlugin_PyInterp::errorMessage()
+{
+ std::string aPyError;
+ if (PyErr_Occurred()) {
+ PyObject *pstr, *ptype, *pvalue, *ptraceback;
+ PyErr_Fetch(&ptype, &pvalue, &ptraceback);
+ PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
+ pstr = PyObject_Str(pvalue);
+ aPyError = std::string(PyString_AsString(pstr));
+ Py_XDECREF(pstr);
+ Py_XDECREF(ptype);
+ Py_XDECREF(pvalue);
+ Py_XDECREF(ptraceback);
+ }
+ return aPyError;
+}
+
+bool InitializationPlugin_PyInterp::initContext()
+{
+ PyObject *m = PyImport_AddModule("__main__"); // interpreter main module (module context)
+ if(!m){
+ PyErr_Print();
+ return false;
+ }
+ _global_context = PyModule_GetDict(m); // get interpreter global variable context
+ Py_INCREF(_global_context);
+ _local_context = PyDict_New();
+ Py_INCREF(_local_context);
+
+ return PyRun_SimpleString("from math import *") == 0;
+}
+
+void InitializationPlugin_PyInterp::closeContext()
+{
+ Py_XDECREF(_local_context);
+ PyInterp_Interp::closeContext();
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+/*
+ * InitializationPlugin_PyInterp.h
+ *
+ * Created on: Apr 2, 2015
+ * Author: sbh
+ */
+
+#ifndef INITIALIZATIONPLUGIN_PYINTERP_H_
+#define INITIALIZATIONPLUGIN_PYINTERP_H_
+
+#include <PyInterp_Interp.h>
+#include <InitializationPlugin.h>
+
+#include <list>
+#include <string>
+#include <utility>
+
+/**
+ * \class InitializationPlugin_PyInterp
+ * \ingroup Plugins
+ * \brief Helper class for using Python interpreter.
+ */
+class INITIALIZATIONPLUGIN_EXPORT InitializationPlugin_PyInterp : public PyInterp_Interp
+{
+ public:
+ InitializationPlugin_PyInterp();
+ virtual ~InitializationPlugin_PyInterp();
+
+ /// Returns a list of positions for theName in theExpression.
+ std::list<std::pair<int, int> > positions(const std::string& theExpression,
+ const std::string& theName);
+ /// Compiles theExpression and returns a list of parameters used in theExpression.
+ std::list<std::string> compile(const std::string& theExpression);
+ /// Extends local context with the list of parameters.
+ void extendLocalContext(const std::list<std::string>& theParameters);
+ /// Clears local context.
+ void clearLocalContext();
+ /// Evaluates theExpression and returns its value.
+ double evaluate(const std::string& theExpression, std::string& theError);
+
+ protected:
+ /// Returns error message.
+ std::string errorMessage();
+ /// Overrides PyInterp_Interp.
+ virtual bool initContext();
+ /// Reimplemented from PyInterp_Interp::closeContext().
+ virtual void closeContext();
+};
+
+#endif /* INITIALIZATIONPLUGIN_PYINTERP_H_ */
}
-ModelAPI_DocumentCreatedMessage::ModelAPI_DocumentCreatedMessage(const Events_ID theID,
- const void* theSender)
+ModelAPI_DocumentCreatedMessage::ModelAPI_DocumentCreatedMessage(
+ const Events_ID theID, const void* theSender)
: Events_Message(theID, theSender)
-{
-
-}
+{}
ModelAPI_DocumentCreatedMessage::~ModelAPI_DocumentCreatedMessage()
-{
-
-}
+{}
DocumentPtr ModelAPI_DocumentCreatedMessage::document() const
{
myDocument = theDocument;
}
-ModelAPI_AttributeEvalMessage::ModelAPI_AttributeEvalMessage(const Events_ID theID,
- const void* theSender)
+ModelAPI_AttributeEvalMessage::ModelAPI_AttributeEvalMessage(
+ const Events_ID theID, const void* theSender)
: Events_Message(theID, theSender)
+{}
+
+ModelAPI_AttributeEvalMessage::~ModelAPI_AttributeEvalMessage()
+{}
+
+AttributePtr ModelAPI_AttributeEvalMessage::attribute() const
+{
+ return myAttribute;
+}
+
+void ModelAPI_AttributeEvalMessage::setAttribute(AttributePtr theAttribute)
{
+ myAttribute = theAttribute;
+}
+ModelAPI_ParameterEvalMessage::ModelAPI_ParameterEvalMessage(
+ const Events_ID theID, const void* theSender)
+ : Events_Message(theID, theSender), myIsProcessed(false)
+{}
+
+ModelAPI_ParameterEvalMessage::~ModelAPI_ParameterEvalMessage()
+{}
+
+FeaturePtr ModelAPI_ParameterEvalMessage::parameter() const
+{
+ return myParam;
}
-ModelAPI_AttributeEvalMessage::~ModelAPI_AttributeEvalMessage()
+void ModelAPI_ParameterEvalMessage::setParameter(FeaturePtr theParam)
{
+ myParam = theParam;
+}
+void ModelAPI_ParameterEvalMessage::setResults(
+ const std::list<std::shared_ptr<ModelAPI_ResultParameter> >& theParamsList,
+ const double theResult, const std::string& theError)
+{
+ myParamsList = theParamsList;
+ myResult = theResult;
+ myError = theError;
+ myIsProcessed = true;
}
-AttributePtr ModelAPI_AttributeEvalMessage::attribute() const
+bool ModelAPI_ParameterEvalMessage::isProcessed()
{
- return myAttribute;
+ return myIsProcessed;
}
-void ModelAPI_AttributeEvalMessage::setAttribute(AttributePtr theDocument)
+const std::list<std::shared_ptr<ModelAPI_ResultParameter> >&
+ ModelAPI_ParameterEvalMessage::params() const
{
- myAttribute = theDocument;
+ return myParamsList;
}
+const double& ModelAPI_ParameterEvalMessage::result() const
+{
+ return myResult;
+}
+
+const std::string& ModelAPI_ParameterEvalMessage::error() const
+{
+ return myError;
+}
+
+ModelAPI_ComputePositionsMessage::ModelAPI_ComputePositionsMessage(
+ const Events_ID theID, const void* theSender)
+ : Events_Message(theID, theSender)
+{}
+
+ModelAPI_ComputePositionsMessage::~ModelAPI_ComputePositionsMessage()
+{}
+
+const std::string& ModelAPI_ComputePositionsMessage::expression() const
+{
+ return myExpression;
+}
+
+const std::string& ModelAPI_ComputePositionsMessage::parameter() const
+{
+ return myParamName;
+}
+
+void ModelAPI_ComputePositionsMessage::set(
+ const std::string& theExpression, const std::string& theParameter)
+{
+ myExpression = theExpression;
+ myParamName = theParameter;
+}
+
+void ModelAPI_ComputePositionsMessage::setPositions(
+ const std::list<std::pair<int, int> >& thePositions)
+{
+ myPositions = thePositions;
+}
+
+const std::list<std::pair<int, int> >& ModelAPI_ComputePositionsMessage::positions() const
+{
+ return myPositions;
+}
+
+
ModelAPI_ObjectRenamedMessage::ModelAPI_ObjectRenamedMessage(const Events_ID theID,
const void* theSender)
: Events_Message(theID, theSender)
class ModelAPI_Document;
+class ModelAPI_ResultParameter;
/// Event ID that feature is created (comes with ModelAPI_ObjectUpdatedMessage)
static const char * EVENT_OBJECT_CREATED = "ObjectCreated";
MODELAPI_EXPORT void setAttribute(AttributePtr theAttribute);
};
+/// Message that parameter feature expression should be evaluated: value and error producing
+class ModelAPI_ParameterEvalMessage : public Events_Message
+{
+ FeaturePtr myParam; ///< parameters that should be evaluated
+ bool myIsProcessed; ///< true if results were set
+ /// result of processing, list of parameters in expression found
+ std::list<std::shared_ptr<ModelAPI_ResultParameter> > myParamsList;
+ double myResult; ///< result of processing, the computed value of the expression
+ std::string myError; ///< error of processing, empty if there is no error
+
+ public:
+ /// Static. Returns EventID of the message.
+ MODELAPI_EXPORT static Events_ID& eventId()
+ {
+ static const char * MY_PARAMETER_EVALUATION_EVENT_ID("ParameterEvaluationRequest");
+ static Events_ID anId = Events_Loop::eventByName(MY_PARAMETER_EVALUATION_EVENT_ID);
+ return anId;
+ }
+
+ /// Useful method that creates and sends the event.
+ /// Returns the message, processed, with the resulting fields filled.
+ MODELAPI_EXPORT static std::shared_ptr<ModelAPI_ParameterEvalMessage>
+ send(FeaturePtr theParameter, const void* theSender)
+ {
+ std::shared_ptr<ModelAPI_ParameterEvalMessage> aMessage =
+ std::shared_ptr<ModelAPI_ParameterEvalMessage>(
+ new ModelAPI_ParameterEvalMessage(eventId(), theSender));
+ aMessage->setParameter(theParameter);
+ Events_Loop::loop()->send(aMessage);
+ return aMessage;
+ }
+
+ /// Creates an empty message
+ MODELAPI_EXPORT ModelAPI_ParameterEvalMessage(const Events_ID theID, const void* theSender = 0);
+ /// The virtual destructor
+ MODELAPI_EXPORT virtual ~ModelAPI_ParameterEvalMessage();
+
+ /// Returns a parameter stored in the message
+ MODELAPI_EXPORT FeaturePtr parameter() const;
+ /// Sets a parameter to the message
+ MODELAPI_EXPORT void setParameter(FeaturePtr theParam);
+ /// Sets the results of processing
+ MODELAPI_EXPORT void setResults(
+ const std::list<std::shared_ptr<ModelAPI_ResultParameter> >& theParamsList,
+ const double theResult, const std::string& theError);
+ /// Returns true if the expression is processed
+ MODELAPI_EXPORT bool isProcessed();
+ /// Returns the results of processing: list of parameters found in the expression
+ MODELAPI_EXPORT const std::list<std::shared_ptr<ModelAPI_ResultParameter> >& params() const;
+ /// Returns the expression result
+ MODELAPI_EXPORT const double& result() const;
+ /// Returns the interpreter error (empty if no error)
+ MODELAPI_EXPORT const std::string& error() const;
+};
+
+
+/// Message to ask compute the positions of parameters in the expression
+class ModelAPI_ComputePositionsMessage : public Events_Message
+{
+ std::string myExpression; ///< the expression string
+ std::string myParamName; ///< name of the parameter to be searched
+ std::list<std::pair<int, int> > myPositions; ///< computation result: start-end position indices
+
+public:
+ /// Static. Returns EventID of the message.
+ MODELAPI_EXPORT static Events_ID& eventId()
+ {
+ static const char * MY_COMPUTE_POSITIOND_EVENT_ID("ComputePositionsRequest");
+ static Events_ID anId = Events_Loop::eventByName(MY_COMPUTE_POSITIOND_EVENT_ID);
+ return anId;
+ }
+
+ /// Useful method that creates and sends the AttributeEvalMessage event
+ /// Returns the message, processed, with the resulting fields filled
+ MODELAPI_EXPORT static std::shared_ptr<ModelAPI_ComputePositionsMessage>
+ send(const std::string& theExpression, const std::string& theParameter, const void* theSender)
+ {
+ std::shared_ptr<ModelAPI_ComputePositionsMessage> aMessage =
+ std::shared_ptr<ModelAPI_ComputePositionsMessage>(
+ new ModelAPI_ComputePositionsMessage(eventId(), theSender));
+ aMessage->set(theExpression, theParameter);
+ Events_Loop::loop()->send(aMessage);
+ return aMessage;
+ }
+
+ /// Creates an empty message
+ MODELAPI_EXPORT ModelAPI_ComputePositionsMessage(
+ const Events_ID theID, const void* theSender = 0);
+ /// The virtual destructor
+ MODELAPI_EXPORT virtual ~ModelAPI_ComputePositionsMessage();
+
+ /// Returns an expression stored in the message
+ MODELAPI_EXPORT const std::string& expression() const;
+ /// Returns a parameter name stored in the message
+ MODELAPI_EXPORT const std::string& parameter() const;
+ /// Sets an expression and parameter needed for computation
+ MODELAPI_EXPORT void set(const std::string& theExpression, const std::string& theParameter);
+ /// Sets the results of processing
+ MODELAPI_EXPORT void setPositions(const std::list<std::pair<int, int> >& thePositions);
+ /// Returns the results of processing: position start and end indices
+ MODELAPI_EXPORT const std::list<std::pair<int, int> >& positions() const;
+};
+
/// Message that the object is renamed
class ModelAPI_ObjectRenamedMessage : public Events_Message
{
INCLUDE(Common)
-INCLUDE(FindPython)
INCLUDE(UnitTest)
SET(CMAKE_AUTOMOC ON)
ParametersPlugin.h
ParametersPlugin_Plugin.h
ParametersPlugin_Parameter.h
- ParametersPlugin_PyInterp.h
+ ParametersPlugin_EvalListener.h
ParametersPlugin_Validators.h
- ParametersPlugin_EvalListener.h
ParametersPlugin_WidgetCreator.h
ParametersPlugin_ParametersMgr.h
ParametersPlugin_WidgetParamsMgr.h
SET(PROJECT_SOURCES
ParametersPlugin_Plugin.cpp
ParametersPlugin_Parameter.cpp
- ParametersPlugin_PyInterp.cpp
+ ParametersPlugin_EvalListener.cpp
ParametersPlugin_Validators.cpp
- ParametersPlugin_EvalListener.cpp
ParametersPlugin_WidgetCreator.cpp
ParametersPlugin_ParametersMgr.cpp
ParametersPlugin_WidgetParamsMgr.cpp
${PROJECT_SOURCE_DIR}/src/GeomAPI
${PROJECT_SOURCE_DIR}/src/GeomDataAPI
${PROJECT_SOURCE_DIR}/src/ModuleBase
- ${SUIT_INCLUDE}
- ${PYTHON_INCLUDE_DIR}
${CAS_INCLUDE_DIRS}
)
-MESSAGE(STATUS "PYTHON_LIBRARIES (ParametersPlugin): ${PYTHON_LIBRARIES}")
-
SET(PROJECT_LIBRARIES
Events
Config
ModelAPI
ModuleBase
- ${PyInterp}
- ${PYTHON_LIBRARIES}
${QT_LIBRARIES}
)
-ADD_DEFINITIONS(-DPARAMETERSPLUGIN_EXPORTS -DHAVE_DEBUG_PYTHON ${CAS_DEFINITIONS})
+ADD_DEFINITIONS(-DPARAMETERSPLUGIN_EXPORTS ${CAS_DEFINITIONS})
SET(TEXT_RESOURCES
ParametersPlugin_msg_ru.ts
#include <ParametersPlugin_EvalListener.h>
#include <ParametersPlugin_Parameter.h>
-#include <ParametersPlugin_PyInterp.h>
#include <Events_InfoMessage.h>
Events_Loop* aLoop = Events_Loop::loop();
Events_ID anEvents_IDs[] = {
- ModelAPI_AttributeEvalMessage::eventId(),
ModelAPI_ObjectRenamedMessage::eventId(),
ModelAPI_ReplaceParameterMessage::eventId()
};
for (int i = 0; i < sizeof(anEvents_IDs)/sizeof(anEvents_IDs[0]); ++i)
aLoop->registerListener(this, anEvents_IDs[i], NULL, true);
-
- myInterp = std::shared_ptr<ParametersPlugin_PyInterp>(new ParametersPlugin_PyInterp());
- myInterp->initialize();
}
ParametersPlugin_EvalListener::~ParametersPlugin_EvalListener()
if (!theMessage.get())
return;
- const Events_ID kEvaluationEvent = ModelAPI_AttributeEvalMessage::eventId();
const Events_ID kObjectRenamedEvent = ModelAPI_ObjectRenamedMessage::eventId();
const Events_ID kReplaceParameterEvent = ModelAPI_ReplaceParameterMessage::eventId();
- if (theMessage->eventID() == kEvaluationEvent) {
- processEvaluationEvent(theMessage);
- } else if (theMessage->eventID() == kObjectRenamedEvent) {
+ if (theMessage->eventID() == kObjectRenamedEvent) {
processObjectRenamedEvent(theMessage);
} else if (theMessage->eventID() == kReplaceParameterEvent) {
processReplaceParameterEvent(theMessage);
- } else {
- Events_InfoMessage("ParametersPlugin_EvalListener",
- "ParametersPlugin python interpreter, unhandled message caught: ")
- .arg(theMessage->eventID().eventText()).send();
- }
-}
-
-double ParametersPlugin_EvalListener::evaluate(FeaturePtr theParameter,
- const std::string& theExpression, std::string& theError)
-{
- std::list<std::string> anExprParams = myInterp->compile(theExpression);
- // find expression's params in the model
- std::list<std::string> aContext;
- std::list<std::string>::iterator it = anExprParams.begin();
- for ( ; it != anExprParams.end(); it++) {
- double aValue;
- ResultParameterPtr aParamRes;
- // If variable does not exist python interpreter will generate an error. It is OK.
- // But due to the issue 1479 it should not check the history position of parameters relatively
- // to feature that contains expression
- if (!ModelAPI_Tools::findVariable(/*theParameter*/ FeaturePtr(),
- *it, aValue, aParamRes, theParameter->document()))
- continue;
-
- aContext.push_back(*it + "=" + toStdString(aValue));
- }
- myInterp->extendLocalContext(aContext);
- double result = myInterp->evaluate(theExpression, theError);
- myInterp->clearLocalContext();
- return result;
-}
-
-void ParametersPlugin_EvalListener::processEvaluationEvent(
- const std::shared_ptr<Events_Message>& theMessage)
-{
- std::shared_ptr<ModelAPI_AttributeEvalMessage> aMessage =
- std::dynamic_pointer_cast<ModelAPI_AttributeEvalMessage>(theMessage);
-
- FeaturePtr aParamFeature =
- std::dynamic_pointer_cast<ModelAPI_Feature>(aMessage->attribute()->owner());
- if (aMessage->attribute()->attributeType() == ModelAPI_AttributeInteger::typeId()) {
- AttributeIntegerPtr anAttribute =
- std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(aMessage->attribute());
- std::string anError;
- int aValue = (int)evaluate(aParamFeature, anAttribute->text(), anError);
- bool isValid = anError.empty();
- if (isValid)
- anAttribute->setCalculatedValue(aValue);
- anAttribute->setUsedParameters(isValid ?
- toSet(myInterp->compile(anAttribute->text())) : std::set<std::string>());
- anAttribute->setExpressionInvalid(!isValid);
- anAttribute->setExpressionError(anAttribute->text().empty() ? "" : anError);
- } else
- if (aMessage->attribute()->attributeType() == ModelAPI_AttributeDouble::typeId()) {
- AttributeDoublePtr anAttribute =
- std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aMessage->attribute());
- std::string anError;
- double aValue = evaluate(aParamFeature, anAttribute->text(), anError);
- bool isValid = anError.empty();
- if (isValid)
- anAttribute->setCalculatedValue(aValue);
- anAttribute->setUsedParameters(isValid ?
- toSet(myInterp->compile(anAttribute->text())) : std::set<std::string>());
- anAttribute->setExpressionInvalid(!isValid);
- anAttribute->setExpressionError(anAttribute->text().empty() ? "" : anError);
- } else
- if (aMessage->attribute()->attributeType() == GeomDataAPI_Point::typeId()) {
- AttributePointPtr anAttribute =
- std::dynamic_pointer_cast<GeomDataAPI_Point>(aMessage->attribute());
- std::string aText[] = {
- anAttribute->textX(),
- anAttribute->textY(),
- anAttribute->textZ()
- };
- double aCalculatedValue[] = {
- anAttribute->x(),
- anAttribute->y(),
- anAttribute->z()
- };
- for (int i = 0; i < 3; ++i) {
- std::string anError;
- double aValue = evaluate(aParamFeature, aText[i], anError);
- bool isValid = anError.empty();
- if (isValid) aCalculatedValue[i] = aValue;
- anAttribute->setUsedParameters(i,
- isValid ? toSet(myInterp->compile(aText[i])) : std::set<std::string>());
- anAttribute->setExpressionInvalid(i, !isValid);
- anAttribute->setExpressionError(i, aText[i].empty() ? "" : anError);
- }
- anAttribute->setCalculatedValue(aCalculatedValue[0],
- aCalculatedValue[1],
- aCalculatedValue[2]);
- } else
- if (aMessage->attribute()->attributeType() == GeomDataAPI_Point2D::typeId()) {
- AttributePoint2DPtr anAttribute =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aMessage->attribute());
- std::string aText[] = {
- anAttribute->textX(),
- anAttribute->textY()
- };
- double aCalculatedValue[] = {
- anAttribute->x(),
- anAttribute->y()
- };
- for (int i = 0; i < 2; ++i) {
- std::string anError;
- double aValue = evaluate(aParamFeature, aText[i], anError);
- bool isValid = anError.empty();
- if (isValid) aCalculatedValue[i] = aValue;
- anAttribute->setUsedParameters(i,
- isValid ? toSet(myInterp->compile(aText[i])) : std::set<std::string>());
- anAttribute->setExpressionInvalid(i, !isValid);
- anAttribute->setExpressionError(i, aText[i].empty() ? "" : anError);
- }
- anAttribute->setCalculatedValue(aCalculatedValue[0],
- aCalculatedValue[1]);
}
}
{
std::string anExpressionString = theExpression;
- std::list<std::pair<int, int> > aPositions =
- myInterp->positions(anExpressionString, theOldName);
+ // ask interpreter to compute the positions in the expression
+ std::shared_ptr<ModelAPI_ComputePositionsMessage> aMsg =
+ ModelAPI_ComputePositionsMessage::send(theExpression, theOldName, this);
+ const std::list<std::pair<int, int> >& aPositions = aMsg->positions();
if (aPositions.empty())
return anExpressionString;
class ModelAPI_Feature;
class ModelAPI_ResultParameter;
class ParametersPlugin_Parameter;
-class ParametersPlugin_PyInterp;
/**
* \class ParametersPlugin_EvalListener
virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
protected:
- /// Evaluates theExpression and returns its value.
- double evaluate(std::shared_ptr<ModelAPI_Feature> theParameter,
- const std::string& theExpression, std::string& theError);
-
- /// Processes Evaluation event.
- void processEvaluationEvent(const std::shared_ptr<Events_Message>& theMessage);
/// Processes ObjectRenamed event.
void processObjectRenamedEvent(const std::shared_ptr<Events_Message>& theMessage);
/// Processes ReplaceParameter event.
void renameInDependents(std::shared_ptr<ModelAPI_ResultParameter> theResultParameter,
const std::string& theOldName,
const std::string& theNewName);
-
- private:
- std::shared_ptr<ParametersPlugin_PyInterp> myInterp;
};
#endif /* SRC_PARAMETERSPLUGIN_PARAMETERSPLUGIN_EVALLISTENER_H_ */
#include <pyconfig.h>
#include "ParametersPlugin_Parameter.h"
-#include <ParametersPlugin_PyInterp.h>
#include <ModelAPI_AttributeString.h>
#include <ModelAPI_ResultParameter.h>
#include <ModelAPI_Tools.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
+#include <ModelAPI_Events.h>
#include <string>
#include <sstream>
ParametersPlugin_Parameter::ParametersPlugin_Parameter()
{
- myInterp = std::shared_ptr<ParametersPlugin_PyInterp>(new ParametersPlugin_PyInterp());
- myInterp->initialize();
}
ParametersPlugin_Parameter::~ParametersPlugin_Parameter()
double ParametersPlugin_Parameter::evaluate(const std::string& theExpression, std::string& theError)
{
- std::list<std::string> anExprParams = myInterp->compile(theExpression);
- // find expression's params in the model
- std::list<std::string> aContext;
- std::list<std::string>::iterator it = anExprParams.begin();
- std::list<ResultParameterPtr> aParamsList;
- for ( ; it != anExprParams.end(); it++) {
- std::string& aVariableName = *it;
-
- // Parameter with the same name should be searched in the parent document.
- // For the PartSet assume that the parameter is absent.
- // Currently there is no way to get parent document, so we get PartSet for all.
- DocumentPtr aDocument = document();
- if (data()->name() == aVariableName) {
- if (aDocument == ModelAPI_Session::get()->moduleDocument())
- continue;
- aDocument = ModelAPI_Session::get()->moduleDocument();
+ FeaturePtr aMyPtr = std::dynamic_pointer_cast<ModelAPI_Feature>(data()->owner());
+ std::shared_ptr<ModelAPI_ParameterEvalMessage> aProcessMessage =
+ ModelAPI_ParameterEvalMessage::send(aMyPtr, this);
+
+ double aResult = 0;
+ if (aProcessMessage->isProcessed()) {
+ const std::list<ResultParameterPtr>& aParamsList = aProcessMessage->params();
+ aResult = aProcessMessage->result();
+ theError = aProcessMessage->error();
+ // compare the list of parameters to store if changed
+ AttributeRefListPtr aParams = reflist(ARGUMENTS_ID());
+ bool aDifferent = aParams->size() != aParamsList.size();
+ if (!aDifferent) {
+ std::list<ResultParameterPtr>::const_iterator aNewIter = aParamsList.begin();
+ std::list<ObjectPtr> anOldList = aParams->list();
+ std::list<ObjectPtr>::const_iterator anOldIter = anOldList.begin();
+ for(; !aDifferent && aNewIter != aParamsList.end(); aNewIter++, anOldIter++) {
+ if (*aNewIter != *anOldIter)
+ aDifferent = true;
+ }
}
-
- double aValue;
- ResultParameterPtr aParamRes;
- if (!ModelAPI_Tools::findVariable(std::dynamic_pointer_cast<ModelAPI_Feature>(data()->owner()),
- aVariableName, aValue, aParamRes, aDocument)) continue;
- aParamsList.push_back(aParamRes);
-
- std::ostringstream sstream;
- sstream << aValue;
- std::string aParamValue = sstream.str();
- size_t aPos = aParamValue.find(".");
- std::string aPnt = "";
- if (aPos == std::string::npos)
- aPnt = ".";
- aContext.push_back(*it + "=" + aParamValue + aPnt);
- }
- // compare the list of parameters to store if changed
- AttributeRefListPtr aParams = reflist(ARGUMENTS_ID());
- bool aDifferent = aParams->size() != aParamsList.size();
- if (!aDifferent) {
- std::list<ResultParameterPtr>::iterator aNewIter = aParamsList.begin();
- std::list<ObjectPtr> anOldList = aParams->list();
- std::list<ObjectPtr>::iterator anOldIter = anOldList.begin();
- for(; !aDifferent && aNewIter != aParamsList.end(); aNewIter++, anOldIter++) {
- if (*aNewIter != *anOldIter)
- aDifferent = true;
+ if (aDifferent) {
+ aParams->clear();
+ std::list<ResultParameterPtr>::const_iterator aNewIter = aParamsList.begin();
+ for(; aNewIter != aParamsList.end(); aNewIter++) {
+ aParams->append(*aNewIter);
+ }
}
+ } else { // error: python interpreter is not active
+ theError = "Python interpreter is not available";
}
- if (aDifferent) {
- aParams->clear();
- std::list<ResultParameterPtr>::iterator aNewIter = aParamsList.begin();
- for(; aNewIter != aParamsList.end(); aNewIter++) {
- aParams->append(*aNewIter);
- }
- }
-
- myInterp->extendLocalContext(aContext);
- double result = myInterp->evaluate(theExpression, theError);
- myInterp->clearLocalContext();
- return result;
+ return aResult;
}
bool ParametersPlugin_Parameter::isPreviewNeeded() const
#include <memory>
-class ParametersPlugin_PyInterp;
-
/**
* \class ParametersPlugin_Parameter
* \ingroup Plugins
void updateName();
/// Updates expression of the parameter
bool updateExpression();
-
- private:
- std::shared_ptr<ParametersPlugin_PyInterp> myInterp;
};
#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-/*
- * ParametersPlugin_PyInterp.cpp
- *
- * Created on: Apr 2, 2015
- * Author: sbh
- */
-
-#include <ParametersPlugin_PyInterp.h>
-
-#include <string>
-#include <stdexcept>
-
-ParametersPlugin_PyInterp::ParametersPlugin_PyInterp()
-: PyInterp_Interp()
-{
-}
-
-ParametersPlugin_PyInterp::~ParametersPlugin_PyInterp()
-{
-}
-
-const char* aSearchCode =
- "import ast\n"
- "class FindName(ast.NodeVisitor):\n"
- " def __init__(self, name):\n"
- " self.name = name\n"
- " def visit_Name(self, node):\n"
- " if node.id == self.name:\n"
- " positions.append((node.lineno, node.col_offset))\n"
- "FindName(name).visit(ast.parse(expression))";
-
-std::list<std::pair<int, int> >
-ParametersPlugin_PyInterp::positions(const std::string& theExpression,
- const std::string& theName)
-{
- PyLockWrapper lck; // Acquire GIL until the end of the method
-
- std::list<std::pair<int, int> > aResult;
-
- // prepare a context
- PyObject* aContext = PyDict_New();
- PyObject* aBuiltinModule = PyImport_AddModule("__builtin__");
- PyDict_SetItemString(aContext, "__builtins__", aBuiltinModule);
-
- // extend aContext with variables
- PyDict_SetItemString(aContext, "expression", PyString_FromString(theExpression.c_str()));
- PyDict_SetItemString(aContext, "name", PyString_FromString(theName.c_str()));
- PyDict_SetItemString(aContext, "positions", Py_BuildValue("[]"));
-
- // run the search code
- PyObject* aExecResult = PyRun_String(aSearchCode, Py_file_input, aContext, aContext);
- Py_XDECREF(aExecResult);
-
- // receive results from context
- PyObject* aPositions = PyDict_GetItemString(aContext, "positions");
- for (int anIndex = 0; anIndex < PyList_Size(aPositions); ++anIndex) {
- PyObject* aPosition = PyList_GetItem(aPositions, anIndex);
- PyObject* aLineNo = PyTuple_GetItem(aPosition, 0);
- PyObject* aColOffset = PyTuple_GetItem(aPosition, 1);
-
- aResult.push_back(
- std::pair<int, int>((int)PyInt_AsLong(aLineNo),
- (int)PyInt_AsLong(aColOffset)));
- }
-
- // TODO(spo): after this refCount of the variable is not 0. Is there memory leak?
- Py_DECREF(aContext);
-
- return aResult;
-}
-
-
-std::list<std::string> ParametersPlugin_PyInterp::compile(const std::string& theExpression)
-{
- PyLockWrapper lck; // Acquire GIL until the end of the method
- std::list<std::string> aResult;
- PyObject *aCodeopModule = PyImport_AddModule("codeop");
- if(!aCodeopModule) { // Fatal error. No way to go on.
- PyErr_Print();
- return aResult;
- }
-
- PyObject *aCodePyObj =
- PyObject_CallMethod(aCodeopModule, (char*)"compile_command", (char*)"(s)",
- theExpression.c_str());
-
- if(!aCodePyObj || aCodePyObj == Py_None || !PyCode_Check(aCodePyObj)) {
- Py_XDECREF(aCodePyObj);
- return aResult;
- }
-
- PyCodeObject* aCodeObj = (PyCodeObject*) aCodePyObj;
- std::string aCodeName(PyString_AsString(aCodeObj->co_code));
- // co_names should be tuple, but can be changed in modern versions of python (>2.7.3)
- if(!PyTuple_Check(aCodeObj->co_names))
- return aResult;
-
- size_t params_size = PyTuple_Size(aCodeObj->co_names);
- if (params_size > 0) {
- for (size_t i = 0; i < params_size; i++) {
- PyObject* aParamObj = PyTuple_GetItem(aCodeObj->co_names, i);
- PyObject* aParamObjStr = PyObject_Str(aParamObj);
- std::string aParamName(PyString_AsString(aParamObjStr));
- aResult.push_back(aParamName);
- Py_XDECREF(aParamObjStr);
- }
- }
- Py_XDECREF(aCodeObj);
- return aResult;
-}
-
-void ParametersPlugin_PyInterp::extendLocalContext(const std::list<std::string>& theParameters)
-{
- PyLockWrapper lck; // Acquire GIL until the end of the method
- if (theParameters.empty())
- return;
- std::list<std::string>::const_iterator it = theParameters.begin();
- for ( ; it != theParameters.cend(); it++) {
- std::string aParamValue = *it;
- simpleRun(aParamValue.c_str(), false);
- }
-}
-
-void ParametersPlugin_PyInterp::clearLocalContext()
-{
- PyLockWrapper lck;
- PyDict_Clear(_local_context);
-}
-
-double ParametersPlugin_PyInterp::evaluate(const std::string& theExpression, std::string& theError)
-{
- PyLockWrapper lck; // Acquire GIL until the end of the method
- PyCompilerFlags aFlags = {CO_FUTURE_DIVISION};
- aFlags.cf_flags = CO_FUTURE_DIVISION;
- PyCodeObject* anExprCode = (PyCodeObject *) Py_CompileStringFlags(theExpression.c_str(),
- "<string>", Py_eval_input, &aFlags);
- if(!anExprCode) {
- theError = errorMessage();
- Py_XDECREF(anExprCode);
- return 0.;
- }
-
- PyObject* anEvalResult = PyEval_EvalCode(anExprCode, _global_context, _local_context);
- if(!anEvalResult) {
- theError = errorMessage();
- Py_XDECREF(anExprCode);
- Py_XDECREF(anEvalResult);
- return 0.;
- }
-
- PyObject* anEvalStrObj = PyObject_Str(anEvalResult);
- std::string anEvalStr(PyString_AsString(anEvalStrObj));
- Py_XDECREF(anExprCode);
- Py_XDECREF(anEvalResult);
- Py_XDECREF(anEvalStrObj);
- double result = 0.;
- try {
- result = std::stod(anEvalStr);
- } catch (const std::invalid_argument&) {
- theError = "Unable to eval " + anEvalStr;
- }
-
- return result;
-}
-
-std::string ParametersPlugin_PyInterp::errorMessage()
-{
- std::string aPyError;
- if (PyErr_Occurred()) {
- PyObject *pstr, *ptype, *pvalue, *ptraceback;
- PyErr_Fetch(&ptype, &pvalue, &ptraceback);
- PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
- pstr = PyObject_Str(pvalue);
- aPyError = std::string(PyString_AsString(pstr));
- Py_XDECREF(pstr);
- Py_XDECREF(ptype);
- Py_XDECREF(pvalue);
- Py_XDECREF(ptraceback);
- }
- return aPyError;
-}
-
-bool ParametersPlugin_PyInterp::initContext()
-{
- PyObject *m = PyImport_AddModule("__main__"); // interpreter main module (module context)
- if(!m){
- PyErr_Print();
- return false;
- }
- _global_context = PyModule_GetDict(m); // get interpreter global variable context
- Py_INCREF(_global_context);
- _local_context = PyDict_New();
- Py_INCREF(_local_context);
-
- return PyRun_SimpleString("from math import *") == 0;
-}
-
-void ParametersPlugin_PyInterp::closeContext()
-{
- Py_XDECREF(_local_context);
- PyInterp_Interp::closeContext();
-}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
-/*
- * ParametersPlugin_PyInterp.h
- *
- * Created on: Apr 2, 2015
- * Author: sbh
- */
-
-#ifndef PARAMETERSPLUGIN_PYINTERP_H_
-#define PARAMETERSPLUGIN_PYINTERP_H_
-
-#include <PyInterp_Interp.h>
-#include <ParametersPlugin.h>
-
-#include <list>
-#include <string>
-#include <utility>
-
-/**
- * \class ParametersPlugin_PyInterp
- * \ingroup Plugins
- * \brief Helper class for using Python interpreter.
- */
-class PARAMETERSPLUGIN_EXPORT ParametersPlugin_PyInterp : public PyInterp_Interp
-{
- public:
- ParametersPlugin_PyInterp();
- virtual ~ParametersPlugin_PyInterp();
-
- /// Returns a list of positions for theName in theExpression.
- std::list<std::pair<int, int> > positions(const std::string& theExpression,
- const std::string& theName);
- /// Compiles theExpression and returns a list of parameters used in theExpression.
- std::list<std::string> compile(const std::string& theExpression);
- /// Extends local context with the list of parameters.
- void extendLocalContext(const std::list<std::string>& theParameters);
- /// Clears local context.
- void clearLocalContext();
- /// Evaluates theExpression and returns its value.
- double evaluate(const std::string& theExpression, std::string& theError);
-
- protected:
- /// Returns error message.
- std::string errorMessage();
- /// Overrides PyInterp_Interp.
- virtual bool initContext();
- /// Reimplemented from PyInterp_Interp::closeContext().
- virtual void closeContext();
-};
-
-#endif /* PARAMETERSPLUGIN_PYINTERP_H_ */