Author: juhliarik
Date: Tue Nov 13 15:13:53 2007
New Revision: 42021
URL: http://svn.opensuse.org/viewcvs/yast?rev=42021&view=rev
Log:
added functionality for calling python function in YCP via reference
Modified:
trunk/python-bindings/src/YCPDeclarations.cc
trunk/python-bindings/src/YCPDeclarations.h
trunk/python-bindings/src/YPython.cc
trunk/python-bindings/src/YPython.h
trunk/python-bindings/src/YPythonNamespace.cc
trunk/python-bindings/src/YPythonNamespace.h
Modified: trunk/python-bindings/src/YCPDeclarations.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/python-bindings/src/YCPDeclarations.cc?rev=42021&r1=42020&r2=42021&view=diff
==============================================================================
--- trunk/python-bindings/src/YCPDeclarations.cc (original)
+++ trunk/python-bindings/src/YCPDeclarations.cc Tue Nov 13 15:13:53 2007
@@ -2,21 +2,27 @@
#include <iostream>
using std::string;
using std::vector;
-#define DBG(str) \
- std::cerr << __FILE__ << ": " << __LINE__ << ": " << str << std::endl; \
- std::cerr.flush()
-//#define DBG(str)
+//#define DBG(str) \
+// std::cerr << __FILE__ << ": " << __LINE__ << ": " << str << std::endl; \
+// std::cerr.flush()
+#define DBG(str)
/********** STATIC MEMBERS **********/
+int YCPDeclarations::_initial = 0;
+
std::auto_ptr<YCPDeclarations> YCPDeclarations::_instance;
YCPDeclarations *YCPDeclarations::instance()
{
+
+ DBG("Called YCPDeclarations::instance()");
if (_instance.get() == 0){
_instance = std::auto_ptr<YCPDeclarations>(new YCPDeclarations());
}
return _instance.get();
}
+
+
/********** STATIC MEMBERS END **********/
@@ -164,6 +170,7 @@
YCPDeclarations::YCPDeclarations()
{
DBG("YCPDeclarations - constructor");
+ YCPDeclarations::_initial = 1;
_py_self = PyImport_ImportModule("YCPDeclarations");
if (_py_self == NULL){
DBG("YCPDeclarations::YCPDeclarations() - Failed to import YCPDeclarations module!");
@@ -174,19 +181,26 @@
{
DBG("YCPDeclarations - destructor");
-
- int cache_len = _cache.size();
- for (int i=0; i < cache_len; i++){
- delete _cache[i];
- }
-
- if (_py_self != NULL)
- Py_DECREF(_py_self);
-
- //_instance = std::auto_ptr<YCPDeclarations>(NULL);
+ if (Initialized()) {
+ int cache_len = _cache.size();
+ for (int i=0; i < cache_len; i++){
+ delete _cache[i];
+ }
+
+ if (_py_self != NULL)
+ Py_DECREF(_py_self);
+ }
+ YCPDeclarations::_initial = 0;
}
+bool YCPDeclarations::Initialized() {
+ if (YCPDeclarations::_initial == 1)
+ return true;
+ else
+ return false;
+}
+
int YCPDeclarations::numParams(PyFunctionObject *func)
{
Modified: trunk/python-bindings/src/YCPDeclarations.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/python-bindings/src/YCPDeclarations.h?rev=42021&r1=42020&r2=42021&view=diff
==============================================================================
--- trunk/python-bindings/src/YCPDeclarations.h (original)
+++ trunk/python-bindings/src/YCPDeclarations.h Tue Nov 13 15:13:53 2007
@@ -85,10 +85,22 @@
*/
const cache_function_t *_getCachedFunction(PyFunctionObject *func) const;
+
+ /**
+ * The value indicates if YCPDeclarations was initialized
+ * 1 - initialized 0 - non initialized
+ */
+ static int _initial;
+
public:
~YCPDeclarations();
/**
+ * Return true if YCPDeclarations was initialized.
+ */
+ bool Initialized();
+
+ /**
* Return number of parameters in declaration or -1 if function is not registered.
*/
int numParams(PyFunctionObject *pointer_to_function);
Modified: trunk/python-bindings/src/YPython.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/python-bindings/src/YPython.cc?rev=42021&r1=42020&r2=42021&view=diff
==============================================================================
--- trunk/python-bindings/src/YPython.cc (original)
+++ trunk/python-bindings/src/YPython.cc Tue Nov 13 15:13:53 2007
@@ -46,9 +46,11 @@
#include
#include
#include
+#include
#include "YCPTypes.h"
#include "YPythonNamespace.h"
+#include "YCPDeclarations.h"
#include <iostream>
#define DBG(str) \
@@ -134,7 +136,8 @@
if (!Py_IsInitialized()) {
setenv("PYTHONPATH", path.c_str(), 1);
Py_Initialize();
- YPython::_pMainDicts = PyDict_New();
+ if (!YPython::_pMainDicts)
+ YPython::_pMainDicts = PyDict_New();
}
if (!YPython::_pMainDicts)
@@ -610,11 +613,11 @@
* @return namespace of YCP
*/
-static Y2Namespace * getNs (const char * ns_name, const char * func_name) {
+static Y2Namespace * getNs (const char * ns_name) {
Import import(ns_name); // has a static cache
Y2Namespace *ns = import.nameSpace();
if (ns == NULL) {
- y2error ("... for a Python call of %s", func_name);
+ y2error ("... for a Python call of %s", ns_name);
} else {
ns->initialize ();
}
@@ -632,40 +635,115 @@
int YPython::findModuleFuncInDict(string module, string function) {
- PyObject* pMainDict = NULL; // dictionary of module
- PyObject* pFunc = NULL; // function from dictionary
+ PyObject * pModuleName = PyString_FromString(module.c_str());
+ if (_pMainDicts==NULL)
+ return -1;
+ if (PyDict_Contains(_pMainDicts, pModuleName)) {
- //obtain correct dictionary for module
- pMainDict = PyDict_GetItemString(YPython::yPython()->pMainDicts(),module.c_str());
+ PyObject * pMainDict = PyDict_GetItemString(_pMainDicts, module.c_str());
+ if (PyDict_Contains(pMainDict, PyString_FromString(function.c_str())))
+ return 1;
+ else
+ return 0;
+
+ } else {
- //obtain function from dictionary
- if (pMainDict)
- pFunc = PyDict_GetItemString(pMainDict, function.c_str());
- else
return -1;
-
- if (pFunc)
- return 1;
- else
- return 0;
+ }
+
}
+/**
+ * Adding module name and function into
+ * global dictionary
+ * (necessary for calling python function via reference)
+ **/
+bool YPython::addModuleAndFunction(string module, string fun_name, PyObject* function) {
+
+
+ PyObject * pModuleName = PyString_FromString(module.c_str());
+ //check if dictionary contain "dictionary" for module
+
+ if (_pMainDicts==NULL) {
+ _pMainDicts = PyDict_New();
+ }
+
+ if (PyDict_Contains(_pMainDicts, pModuleName)) {
+ PyObject * pMainDict = PyDict_GetItemString(_pMainDicts, module.c_str());
+
+ if (PyDict_Contains(pMainDict, PyString_FromString(fun_name.c_str()))) {
+ return true;
+
+ } else {
+ //PyObject * newDict = PyDict_New();
+ if (PyDict_SetItemString(pMainDict, fun_name.c_str(), function) < 0) {
+ y2error("Adding new function %s to local dictionary", fun_name.c_str());
+ return false;
+ }
+
+ if (PyDict_DelItemString(_pMainDicts, module.c_str()) <0) {
+ y2error("Deleting local dictionary %s from global dictionary failed", module.c_str());
+ return false;
+ }
+
+ if (PyDict_SetItemString(_pMainDicts, module.c_str(), pMainDict) <0) {
+ y2error("Adding new local dictionary %s to global dictionary", module.c_str());
+ return false;
+ }
+
+ return true;
+ }
+ } else {
+ PyObject * newDict = PyDict_New();
+
+ if (PyDict_SetItemString(newDict, fun_name.c_str(), function) < 0) {
+ y2error("Adding new function %s to local dictionary", fun_name.c_str());
+ return false;
+ }
+
+ if (PyDict_SetItemString(_pMainDicts, module.c_str(), newDict) <0) {
+ y2error("Adding new local dictionary %s to global dictionary", module.c_str());
+ return false;
+ }
+
+ return true;
+ }
+}
+
+YCPValue YPython::findSymbolEntry(Y2Namespace *ns, string module, string function) {
+
+ if (ns) {
+ TableEntry *sym_te = ns->table ()->find (function.c_str());
+
+ if (sym_te == NULL) {
+ y2error ("No such symbol %s::%s", module.c_str(), function.c_str());
+ return YCPNull();
+ }
+
+ SymbolEntryPtr sym_entry = sym_te->sentry();
+ //cout << "entry" << sym_entry->toString()<< endl;
+ return YCPReference(sym_entry);
+
+ } else {
+ y2error("Creating/Importing namespace for function %s failed", function.c_str());
+ return YCPNull();
+ }
+}
/**
* Convert Python Function to YCPCode.
*
* @param pointer to python function
- * @return YCPCode - Referecne
+ * @return YCPReference - Referecne
**/
YCPValue YPython::fromPythonFunToReference (PyObject* pyFun) {
-
PyObject *fun_code = PyFunction_GetCode(pyFun);
string fun_name = PyString_AsString(((PyCodeObject *) fun_code)->co_name);
string file_path = PyString_AsString(((PyCodeObject *) fun_code)->co_filename);
-
-
+ //int no_args = ((PyCodeObject *) fun_code)->co_argcount;
+
//found last "/" in path
size_t found = file_path.find_last_of("/");
//extract module name from path
@@ -674,25 +752,49 @@
module_name.erase(module_name.size()-3);
int find = findModuleFuncInDict(module_name, fun_name);
-
- if (find) {
- Y2Namespace *ns = getNs (module_name.c_str(),fun_name.c_str());
-
- if (ns) {
- TableEntry *sym_te = ns->table ()->find (fun_name.c_str());
- if (sym_te == NULL) {
- y2error ("No such symbol %s::%s", module_name.c_str(), fun_name.c_str());
- return YCPNull();
+
+ FunctionTypePtr sym_tp;
+ Y2Namespace *ns;
+
+ //namespace exist and includes function
+ if (find == 1) {
+ ns = getNs (module_name.c_str());
+
+ return findSymbolEntry(ns, module_name, fun_name);
+
+ //namespace exist but doesn't include function
+ } else if (find ==0) {
+ addModuleAndFunction(module_name, fun_name, pyFun);
+
+ ns = getNs (module_name.c_str());
+
+ if (ns) {
+
+ SymbolEntry *result = ((YPythonNamespace *)ns)->AddFunction(pyFun);
+ if (result)
+ return YCPReference(result);
+ else {
+ y2error("Adding function %s to namespace %s failed", fun_name.c_str(), module_name.c_str());
+ return YCPNull();
+ }
+
+ } else {
+ y2error("Importing namespace %s for function %s failed",
+ module_name.c_str(), fun_name.c_str());
+ return YCPNull();
}
- SymbolEntryPtr sym_entry = sym_te->sentry();
- //cout << "entry" << sym_entry->toString()<< endl;
- return YCPReference(sym_entry);
+ //namespace and function don't exist
} else {
- y2error("Creating namespace for function %s failed", fun_name.c_str());
- return YCPNull();
- }
+ addModuleAndFunction(module_name, fun_name, pyFun);
+ ns = new YPythonNamespace(module_name, pyFun);
+
+ //register new namespace
+ Import import(module_name, ns);
+
+ return findSymbolEntry(ns, module_name, fun_name);
+
}
return YCPNull();
@@ -707,9 +809,9 @@
YCPValue YPythonCode::evaluate(bool cse) {
- PyObject * pReturn;
+ PyObject * pReturn = NULL;
YCPValue result = YCPVoid();
- PyObject * pFunction;
+ PyObject * pFunction = NULL;
PyObject * pArgs = NULL;
int args_size;
Modified: trunk/python-bindings/src/YPython.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/python-bindings/src/YPython.h?rev=42021&r1=42020&r2=42021&view=diff
==============================================================================
--- trunk/python-bindings/src/YPython.h (original)
+++ trunk/python-bindings/src/YPython.h Tue Nov 13 15:13:53 2007
@@ -127,6 +127,14 @@
int findModuleFuncInDict(string module, string function);
+ /**
+ * Adding module name and function into
+ * global dictionary
+ * (necessary for calling python function via reference)
+ **/
+ bool addModuleAndFunction(string module, string fun_name, PyObject* function);
+
+
/**
* Convert a Python list to a YCPList.
**/
@@ -168,8 +176,17 @@
**/
PyObject* fromYCPTermToPythonTerm (YCPValue ycp_Term);
+ /**
+ * Prepare YCPReference for calling python function in YCP via reference
+ **/
YCPValue fromPythonFunToReference (PyObject* pyFun);
+
+ /**
+ * Function find in namespace function and return symbol entry
+ **/
+ YCPValue findSymbolEntry(Y2Namespace *ns, string module, string function);
+
protected:
/**
Modified: trunk/python-bindings/src/YPythonNamespace.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/python-bindings/src/YPythonNamespace.cc?rev=42021&r1=42020&r2=42021&view=diff
==============================================================================
--- trunk/python-bindings/src/YPythonNamespace.cc (original)
+++ trunk/python-bindings/src/YPythonNamespace.cc Tue Nov 13 15:13:53 2007
@@ -230,6 +230,111 @@
}
+
+YPythonNamespace::YPythonNamespace (string name, PyObject* function)
+ : m_name (name),
+ m_all_methods (true) {
+
+
+ PyObject * fun_code; //code of function
+
+ //Declarations (using YPCDelcarations python module)
+ YCPDeclarations *decl = YCPDeclarations::instance();
+ //YCPDeclarations *decl = new YCPDeclarations();
+
+ FunctionTypePtr sym_tp;
+ std::vector<constTypePtr> list_of_types;
+ int tmp;
+
+ int count = 0; // position. arbitrary numbering
+ long num = 0; //number of function arguments
+
+
+ fun_code = PyFunction_GetCode(function);
+ num = ((PyCodeObject *) fun_code)->co_argcount;
+ string fun_name = PyString_AsString(((PyCodeObject *) fun_code)->co_name);
+
+ if (decl->exists((PyFunctionObject *)function)
+ && decl->numParams((PyFunctionObject *)function) == num){
+
+ sym_tp = new FunctionType(decl->returnType((PyFunctionObject *)function));
+
+ list_of_types = decl->params((PyFunctionObject *)function);
+ tmp = list_of_types.size();
+ for (int i=0; i < tmp; i++){
+ sym_tp->concat(list_of_types[i]);
+ }
+ } else {
+ sym_tp = new FunctionType(Type::Any);
+ //y2milestone ("Number of parameters: %d", num);
+ //add types and number of arguments into SymbolEntry table
+ for (long j = 0; j < num; j++) {
+ sym_tp->concat(Type::Any);
+ }
+ }
+ //y2milestone ("Callable function %s", PyString_AsString(item));
+ // symbol entry for the function
+ SymbolEntry *fun_se = new SymbolEntry (
+ this,
+ count++, // position. arbitrary numbering. must stay consistent when?
+ fun_name.c_str(), // passed to Ustring, no need to strdup
+ SymbolEntry::c_function,
+ sym_tp);
+ fun_se->setGlobal (true);
+
+ // enter it to the symbol table
+ enterSymbol (fun_se, 0);
+
+
+ y2milestone ("(special) YPythonNamespace finish");
+
+}
+
+SymbolEntry * YPythonNamespace::AddFunction (PyObject* function) {
+
+ //Declarations (using YPCDelcarations python module)
+ YCPDeclarations *decl = YCPDeclarations::instance();
+ int tmp;
+ std::vector<constTypePtr> list_of_types;
+ FunctionTypePtr sym_tp;
+ PyObject *fun_code = PyFunction_GetCode(function);
+ int num = ((PyCodeObject *) fun_code)->co_argcount;
+ string fun_name = PyString_AsString(((PyCodeObject *) fun_code)->co_name);
+
+ if (decl->exists((PyFunctionObject *)function)
+ && decl->numParams((PyFunctionObject *)function) == num){
+
+ sym_tp = new FunctionType(decl->returnType((PyFunctionObject *)function));
+
+ list_of_types = decl->params((PyFunctionObject *)function);
+ tmp = list_of_types.size();
+ for (int i=0; i < tmp; i++){
+ sym_tp->concat(list_of_types[i]);
+ }
+ } else {
+ sym_tp = new FunctionType(Type::Any);
+ //y2milestone ("Number of parameters: %d", num);
+ //add types and number of arguments into SymbolEntry table
+ for (long j = 0; j < num; j++) {
+ sym_tp->concat(Type::Any);
+ }
+ }
+ // symbol entry for the function
+ SymbolEntry *fun_se = new SymbolEntry (
+ this,
+ 0, // position. arbitrary numbering. must stay consistent when?
+ fun_name.c_str(), // passed to Ustring, no need to strdup
+ SymbolEntry::c_function,
+ sym_tp);
+
+ fun_se->setGlobal (true);
+
+ enterSymbol (fun_se, 0);
+
+ return fun_se;
+}
+
+
YPythonNamespace::~YPythonNamespace ()
{
@@ -261,14 +366,18 @@
return YCPNull ();
}
+
// It seems that this is the standard implementation. why would we
// ever want it to be different?
Y2Function* YPythonNamespace::createFunctionCall (const string name, constFunctionTypePtr required_type)
{
y2debug ("Python creating function call for %s", name.c_str ());
- TableEntry *func_te = table ()->find (name.c_str (), SymbolEntry::c_function);
+ //TableEntry *func_te = table ()->find (name.c_str (), SymbolEntry::c_function);
+ TableEntry *func_te = table ()->find (name.c_str ());
+
if (func_te)
{
+ //cout << "namespace: " << m_name << " function: " << name << endl;
constTypePtr t = required_type ? required_type : (constFunctionTypePtr)func_te->sentry()->type ();
if (m_all_methods)
{
@@ -279,6 +388,8 @@
return new Y2PythonSubCall (m_name, name, t);
}
}
+
+ //cout << "namespace: " << m_name << " function: " << name << endl;
y2error ("No such function %s", name.c_str ());
return NULL;
}
Modified: trunk/python-bindings/src/YPythonNamespace.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/python-bindings/src/YPythonNamespace.h?rev=42021&r1=42020&r2=42021&view=diff
==============================================================================
--- trunk/python-bindings/src/YPythonNamespace.h (original)
+++ trunk/python-bindings/src/YPythonNamespace.h Tue Nov 13 15:13:53 2007
@@ -13,12 +13,29 @@
string m_name; //! this namespace's name, eg. XML::Writer
bool m_all_methods; //! add the class name to all calls
public:
+
/**
* Construct an interface. The module must be already loaded
* @param name eg "XML::Writer"
*/
YPythonNamespace (string name);
+ /**
+ * Construct an interface. The module must be already loaded
+ * special contruct for calling python function such as reference
+ * @param name eg "XML::Writer"
+ * @param function function defined in python
+ */
+ YPythonNamespace (string name, PyObject* function);
+
+ /**
+ * Add new function into namespace
+ * @param Y2Namespace pointer to namespace for adding function
+ * @param PyObject pointer to function
+ * @return SymbolEntry pointer to added symbol entry else NULL (if failed)
+ */
+ SymbolEntry * AddFunction (PyObject* function);
+
virtual ~YPythonNamespace ();
//! what namespace do we implement
--
To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org
For additional commands, e-mail: yast-commit+help@opensuse.org