source: trunk/zoo-project/zoo-kernel/service_internal_python.c @ 928

Last change on this file since 928 was 928, checked in by djay, 5 years ago

Fix typo

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 24.1 KB
RevLine 
[579]1/*
[1]2 * Author : Gérald FENOY
3 *
[453]4 * Copyright (c) 2009-2014 GeoLabs SARL
[1]5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#include "service_internal_python.h"
26
[579]27/**
28 * The state for the zoo Python module
29 */
[392]30struct module_state {
[579]31   PyObject *error;
[392]32};
33
34#if PY_MAJOR_VERSION >= 3
35#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
[453]36#define PyInt_FromLong PyLong_FromLong
37#define PyInt_AsLong PyLong_AsLong
38#define PyString_FromString PyUnicode_FromString
39#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
40#define PyString_Check PyUnicode_Check
41#define PyString_AsString _PyUnicode_AsString
42#define PyString_Size PyUnicode_GetSize
[392]43#else
44#define GETSTATE(m) (&_state)
45static struct module_state _state;
46#endif
47
[579]48/**
49 * The exception for the zoo Python module
50 */
[368]51static PyObject* ZooError;
52
[579]53/**
54 * Function definitions for the zoo Python Module
55 *
56 * Define the following functions available from a service loaded and running
57 * from the ZOO-Kernel Python environment:
58 *  - "_" corresponding to the PythonTranslate function
[917]59 *  - "update_status" corresponding to the PythonUpdateStatus function
[579]60 * @see PythonTranslate, PythonUpdateStatus
61 */
[368]62PyMethodDef zooMethods[] = {
[376]63  {"_", PythonTranslate, METH_VARARGS, "Translate a string using the zoo-services textdomain."},
[368]64  {"update_status", PythonUpdateStatus, METH_VARARGS, "Update status percentage of a running process."},
65  {NULL, NULL, 0, NULL} /* tempt not the blade, all fear the sentinel */
66};
67
[392]68#if PY_MAJOR_VERSION >= 3
69
70static int myextension_traverse(PyObject *m, visitproc visit, void *arg) {
71  Py_VISIT(GETSTATE(m)->error);
72  return 0;
73}
74
75static int myextension_clear(PyObject *m) {
76  Py_CLEAR(GETSTATE(m)->error);
77  return 0;
78}
79
80static struct PyModuleDef moduledef = {
81  PyModuleDef_HEAD_INIT,
82  "zoo",
83  NULL,
84  sizeof(struct module_state),
85  zooMethods,
86  NULL,
87  myextension_traverse,
88  myextension_clear,
89  NULL
90};
91#endif
92
[579]93/**
94 * Function to create and initialize the zoo Python module
95 *
96 * @return the Python module (for Python versions < 3, nothing for version >=3)
97 */
[368]98PyMODINIT_FUNC init_zoo(){
99  PyObject *tmp,*d;
[392]100  PyObject *module = 
101#if PY_MAJOR_VERSION >= 3
102    PyModule_Create(&moduledef);
103#else
104    Py_InitModule("zoo", zooMethods);
105#endif
106  if (module == NULL){
107#if PY_MAJOR_VERSION >= 3
108    return NULL;
109#else
[368]110    return;
[392]111#endif
112  }
113
114  struct module_state *st = GETSTATE(module);
115
[368]116  d = PyModule_GetDict(module);
117  tmp = PyInt_FromLong(3);
118  PyDict_SetItemString(d, "SERVICE_SUCCEEDED", tmp);
119  Py_DECREF(tmp);
120
121  tmp = PyInt_FromLong(4);
122  PyDict_SetItemString(d, "SERVICE_FAILED", tmp);
123  Py_DECREF(tmp);
124
[465]125  tmp = PyString_FromString(ZOO_VERSION);
126  PyDict_SetItemString(d, "VERSION", tmp);
127  Py_DECREF(tmp);
128
[490]129  ZooError = PyErr_NewException((char*)"zoo.error", NULL, NULL);
[368]130  Py_INCREF(ZooError);
131  PyModule_AddObject(module, "error", ZooError);
[392]132#if PY_MAJOR_VERSION >= 3
133  return module;
134#endif
[368]135}
136
[579]137/**
[580]138 * Load a Python module then run the function corresponding to the service
[579]139 * by passing the conf, inputs and outputs parameters by reference.
140 *
141 * @param main_conf the conf maps containing the main.cfg settings
142 * @param request the map containing the HTTP request
143 * @param s the service structure
144 * @param real_inputs the maps containing the inputs
145 * @param real_outputs the maps containing the outputs
146 */
[1]147int zoo_python_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
[917]148
[451]149  char *pythonpath;
150  char *python_path;
[917]151
152#ifdef WIN32
[921]153  const char* os_pathsep = ";";
[917]154#else
[921]155  const char* os_pathsep = ":";
[917]156#endif
157
[1]158  maps* m=*main_conf;
159  maps* inputs=*real_inputs;
160  maps* outputs=*real_outputs;
[392]161  map* tmp0=getMapFromMaps(*main_conf,"lenv","cwd");
[917]162  char *ntmp=tmp0->value; 
[1]163  map* tmp=NULL;
[451]164  int hasToClean=0;
[917]165  tmp=getMapFromMaps(*main_conf,"env","PYTHONPATH"); 
166
167  map* kvp = NULL;
168  char* libPath = NULL;
169  if (hasvalue(*main_conf, "main", "libPath", &kvp)) {
170          libPath = kvp->value;
171  }
172  else {
173          libPath = "";
174  }
175
[63]176#ifdef DEBUG
[9]177  fprintf(stderr,"PYTHON SUPPORT \n");
[63]178#endif
[1]179  if(tmp!=NULL){
[63]180#ifdef DEBUG
[9]181    fprintf(stderr,"PYTHON SUPPORT (%i)\n",strlen(tmp->value));
[63]182#endif
[917]183    python_path=(char*)malloc((strlen(tmp->value)+1)*sizeof(char));
[9]184    sprintf(python_path,"%s",tmp->value);
[451]185    hasToClean=1;
[1]186  }
187  else{
[784]188    map* cwdMap=getMapFromMaps(*main_conf,"main","servicePath");
189    if(cwdMap!=NULL)
190      python_path=cwdMap->value;
191    else
[917]192      python_path=(char*)".";   
[1]193  }
194  tmp=NULL;
195  tmp=getMap(request,"metapath");
[392]196  if(tmp!=NULL && strcmp(tmp->value,"")!=0){
[917]197    //pythonpath=(char*)malloc((4+strlen(python_path)+strlen(ntmp)+strlen(tmp->value))*sizeof(char));
198          pythonpath = (char*)malloc((5 + strlen(python_path) + strlen(ntmp) + strlen(tmp->value) + strlen(libPath)) * sizeof(char));
[1]199#ifdef WIN32
[917]200  //sprintf(pythonpath,"%s/%s/;%s",ntmp,tmp->value,python_path);
201        sprintf(pythonpath, "%s/%s/;%s;%s", ntmp, tmp->value, python_path, libPath);
[1]202#else
[917]203  //sprintf(pythonpath,"%s/%s/:%s",ntmp,tmp->value,python_path);
204  sprintf(pythonpath, "%s/%s/:%s:%s", ntmp, tmp->value, python_path, libPath); 
[1]205#endif
[392]206  }
207  else{
[917]208    //pythonpath=(char*)malloc((2+strlen(python_path)+strlen(ntmp))*sizeof(char));
209          pythonpath = (char*)malloc((3 + strlen(python_path) + strlen(ntmp) + strlen(libPath)) * sizeof(char));
[1]210#ifdef WIN32
[917]211    //sprintf(pythonpath,"%s;%s",ntmp,python_path);
212        sprintf(pythonpath, "%s;%s;%s", ntmp, python_path, libPath);
[1]213#else
[917]214    //sprintf(pythonpath,"%s:%s",ntmp,python_path);
215        sprintf(pythonpath, "%s:%s:%s", ntmp, python_path, libPath);
216#endif 
[392]217  }
[67]218#ifdef DEBUG
[9]219    fprintf(stderr,"PYTHONPATH=%s\n",pythonpath);
[67]220#endif
[917]221        map* home = NULL;
222// knut: also set PYTHONHOME environment variable so that Python can load standard modules
223#ifndef WIN32   
224  setenv("PYTHONPATH",pythonpath,1); 
225  //= getMapFromMaps(*main_conf, "env", "PYTHONHOME");
226  if (hasvalue(*main_conf, "env", "PYTHONHOME", &home)) {
227          setenv("PYTHONHOME", home->value, 1); // overwrite
228  }
229#else   
[1]230  SetEnvironmentVariable("PYTHONPATH",pythonpath);
[364]231  char* toto=(char*)malloc((strlen(pythonpath)+12)*sizeof(char));
232  sprintf(toto,"PYTHONPATH=%s",pythonpath);
[917]233  _putenv(toto);
[451]234  free(toto);
[917]235  if (hasvalue(*main_conf, "env", "PYTHONHOME", &home)) { 
236          SetEnvironmentVariable("PYTHONHOME", home->value);
237  }
238  char buffer[128];       
239#endif 
[451]240  if(hasToClean>0)
241    free(python_path);
[1]242  free(pythonpath);
[9]243
[295]244  PyThreadState *mainstate;
[917]245#if PY_MAJOR_VERSION >= 3 
246  PyImport_AppendInittab("zoo", init_zoo); 
[392]247#else
[295]248  PyEval_InitThreads();
[917]249#endif 
250  Py_Initialize(); 
251#if PY_MAJOR_VERSION >= 3 
[392]252  PyEval_InitThreads();
[917]253  PyImport_ImportModule("zoo"); 
[392]254#else
[368]255  init_zoo();
[917]256#endif 
[295]257  mainstate = PyThreadState_Swap(NULL);
258  PyEval_ReleaseLock();
259  PyGILState_STATE gstate;
260  gstate = PyGILState_Ensure();
[1]261  PyObject *pName, *pModule, *pFunc;
262  tmp=getMap(s->content,"serviceProvider");
[505]263  map* mp=getMap(request,"metapath");
264  if(tmp!=NULL){
265    if(mp!=NULL && strlen(mp->value)>0){
266      char *mps=zStrdup(mp->value);
267      int i,len=strlen(mps);
268      int j=0;
269      for(i=0;i<len;i++){
270        if(mps[i]=='/'){
271          mps[i]='.';
272        }
273      }
274      char *mn=(char*)malloc((strlen(mps)+strlen(tmp->value)+2)*sizeof(char));
275      sprintf(mn,"%s.%s",mps,tmp->value);
[917]276      pName = PyString_FromString(mn);   
[505]277      free(mn);
278      free(mps);
279    }
280    else{
281      pName = PyString_FromString(tmp->value);
282    }
283  }
[9]284  else{
[576]285    errorException (m, "Unable to parse serviceProvider please check your zcfg file.", "NoApplicableCode", NULL);
[9]286    exit(-1);
[917]287  } 
288  pModule = PyImport_Import(pName);   
[1]289  int res=SERVICE_FAILED;
290  if (pModule != NULL) {
291    pFunc=PyObject_GetAttrString(pModule,s->name);
292    if (pFunc && PyCallable_Check(pFunc)){
[114]293      PyObject *pValue;
[1]294      PyDictObject* arg1=PyDict_FromMaps(m);
295      PyDictObject* arg2=PyDict_FromMaps(inputs);
296      PyDictObject* arg3=PyDict_FromMaps(outputs);
297      PyObject *pArgs=PyTuple_New(3);
[114]298      if (!pArgs)
299        return -1;
[1]300      PyTuple_SetItem(pArgs, 0, (PyObject *)arg1);
301      PyTuple_SetItem(pArgs, 1, (PyObject *)arg2);
302      PyTuple_SetItem(pArgs, 2, (PyObject *)arg3);
[917]303      pValue = PyObject_CallObject(pFunc, pArgs);         
[1]304      if (pValue != NULL) {
305        res=PyInt_AsLong(pValue);
[9]306        freeMaps(real_outputs);
307        free(*real_outputs);
[59]308        freeMaps(main_conf);
309        free(*main_conf);
[57]310        *main_conf=mapsFromPyDict(arg1);
[917]311        *real_outputs=mapsFromPyDict(arg3);     
[1]312#ifdef DEBUG
313        fprintf(stderr,"Result of call: %i\n", PyInt_AsLong(pValue));
314        dumpMaps(inputs);
[364]315        dumpMaps(*real_outputs);
[1]316#endif
[917]317      }else{
[576]318        PythonZooReport(m,tmp->value,0);
[295]319        res=-1;
[1]320      }
321    }
322    else{
323      char tmpS[1024];
[295]324      sprintf(tmpS, "Cannot find the %s function in the %s file.\n", s->name, tmp->value);
[576]325      errorException(m,tmpS,"NoApplicableCode",NULL);
[295]326      res=-1;
[1]327    }
328  } else{
[576]329    PythonZooReport(m,tmp->value,1);
[295]330    res=-1;
[1]331  } 
[392]332#if PY_MAJOR_VERSION < 3
[295]333  PyGILState_Release(gstate);
[478]334  PyEval_AcquireLock();
[392]335#endif
[295]336  PyThreadState_Swap(mainstate);
[917]337  Py_Finalize(); 
[1]338  return res;
339}
340
[579]341/**
[580]342 * Report Python error which may occur on loading the Python module or at
[579]343 * runtime.
344 *
345 * @param m the conf maps containing the main.cfg settings
346 * @param module the service name
347 * @param load 1 if the Python module was not loaded yet
348 */
[576]349void PythonZooReport(maps* m,const char* module,int load){
350  PyObject *pName, *pModule, *pFunc;
351  PyObject *ptype, *pvalue, *ptraceback,*pValue,*pArgs;
352  PyErr_Fetch(&ptype, &pvalue, &ptraceback);
[927]353#if PY_MAJOR_VERSION >= 3 
354  const
355#endif
356    char *pStrErrorMessage = PyString_AsString(pvalue);
[576]357  char *tmp0=_("Python module %s cannot be loaded. Message: %s\n");
358 
359  PyObject *trace=PyObject_Str(pvalue);
360  char *pbt=NULL;
361  if(PyString_Check(trace)){
[917]362    pbt=(char*)malloc((8+strlen(PyString_AsString(trace)))*sizeof(char));
[576]363    sprintf(pbt,"TRACE: %s",PyString_AsString(trace));
364  }
365  else
366    fprintf(stderr,"EMPTY TRACE ?");
[917]367
[576]368  trace=NULL;
369 
370  trace=PyObject_Str(ptype);
371  if(PyString_Check(trace)){
372    char *tpbt=zStrdup(pbt);
373    if(pbt!=NULL)
374      free(pbt);
375    pbt=(char*)malloc((1+strlen(tpbt)+strlen(PyString_AsString(trace))+1)*sizeof(char));
376    sprintf(pbt,"%s\n%s",tpbt,PyString_AsString(trace));
377    free(tpbt);
378  }
379  else
380    fprintf(stderr,"EMPTY TRACE ?");
381 
382  if(ptraceback!=NULL){
383    char *tpbt=zStrdup(pbt);
384    pName = PyString_FromString("traceback");
385    pModule = PyImport_Import(pName);
386    pArgs = PyTuple_New(1);
387    PyTuple_SetItem(pArgs, 0, ptraceback);
388    pFunc = PyObject_GetAttrString(pModule,"format_tb");
389    pValue = PyObject_CallObject(pFunc, pArgs);
390    trace=NULL;
391    trace=PyObject_Str(pValue);
392    if(PyString_Check(trace)){
393      if(pbt!=NULL)
394        free(pbt);
[790]395      char* format=_("%s\nUnable to run your python process properly. Please check the following messages : %s");
396      pbt=(char*)malloc((strlen(format)+strlen(tpbt)+strlen(PyString_AsString(trace))+1)*sizeof(char));
397      sprintf(pbt,format,tpbt,PyString_AsString(trace));
[576]398    }
399    else{
400      if(pbt!=NULL)
401        free(pbt);
[790]402      char* format=_("%s \n Unable to run your python process properly. Unable to provide any further information.");
403      pbt=(char*)malloc((strlen(format)+strlen(tpbt)+strlen(PyString_AsString(trace))+1)*sizeof(char));
404      sprintf(pbt,format,tpbt);
[576]405    }
406    free(tpbt);
407  }
408  if(load>0){
409    char *tmpS=(char*)malloc((strlen(tmp0)+strlen(module)+strlen(pbt)+1)*sizeof(char));
410    sprintf(tmpS,tmp0,module,pbt);
411    errorException(m,tmpS,"NoApplicableCode",NULL);
412    free(tmpS);
413  }else
414    errorException(m,pbt,"NoApplicableCode",NULL);
415  free(pbt);
416}
417
[579]418/**
419 * Convert a maps to a Python dictionary
420 *
421 * @param t the maps to convert
422 * @return a new PyDictObject containing the converted maps
423 * @see PyDict_FromMap
[781]424 * @warning make sure to free resources returned by this function
[579]425 */
[1]426PyDictObject* PyDict_FromMaps(maps* t){
427  PyObject* res=PyDict_New( );
428  maps* tmp=t;
429  while(tmp!=NULL){
[295]430    PyObject* value=(PyObject*)PyDict_FromMap(tmp->content);
[790]431    if(tmp->child!=NULL){
432      PyObject* cname=PyString_FromString("child");
433      PyObject* childs=(PyObject*)PyDict_FromMaps(tmp->child);
434      if(PyDict_SetItem(value,cname,childs)<0){
435        fprintf(stderr,"Unable to set map value ...");
436        return NULL;
437      } 
438      Py_DECREF(cname);
439    }
[453]440    PyObject* name=PyString_FromString(tmp->name);
[295]441    if(PyDict_SetItem(res,name,value)<0){
442      fprintf(stderr,"Unable to set map value ...");
443      return NULL;
[1]444    }
[295]445    Py_DECREF(name);
[1]446    tmp=tmp->next;
447  } 
448  return (PyDictObject*) res;
449}
450
[579]451/**
452 * Convert a map to a Python dictionary
453 *
454 * @param t the map to convert
455 * @return a new PyDictObject containing the converted maps
[781]456 * @warning make sure to free resources returned by this function
[579]457 */
[1]458PyDictObject* PyDict_FromMap(map* t){
459  PyObject* res=PyDict_New( );
460  map* tmp=t;
[360]461  int hasSize=0;
462  map* isArray=getMap(tmp,"isArray");
[58]463  map* size=getMap(tmp,"size");
[917]464  map* useFile=getMap(tmp,"use_file");
465  map* cacheFile=getMap(tmp,"cache_file");
[360]466  map* tmap=getMapType(tmp);
[1]467  while(tmp!=NULL){
[453]468    PyObject* name=PyString_FromString(tmp->name);
[360]469    if(strcasecmp(tmp->name,"value")==0) {
470      if(isArray!=NULL){
471        map* len=getMap(tmp,"length");
472        int cnt=atoi(len->value);
473        PyObject* value=PyList_New(cnt);
474        PyObject* mvalue=PyList_New(cnt);
475        PyObject* svalue=PyList_New(cnt);
[917]476        PyObject* cvalue=PyList_New(cnt);
[360]477
478        for(int i=0;i<cnt;i++){
479         
[917]480          map* vMap=getMapArray(t,"value",i);
481          map* uMap=getMapArray(t,"use_file",i);
482          map* sMap=getMapArray(t,"size",i);
483          map* cMap=getMapArray(t,"cache_file",i);
[360]484
485          if(vMap!=NULL){
486           
487            PyObject* lvalue;
488            PyObject* lsvalue;
[917]489            PyObject* lcvalue;
490            if(sMap==NULL || uMap!=NULL){
[360]491              lvalue=PyString_FromString(vMap->value);
492            }
[453]493            else{   
[360]494              lvalue=PyString_FromStringAndSize(vMap->value,atoi(sMap->value));
[917]495            }
496            if(sMap!=NULL){
[360]497              lsvalue=PyString_FromString(sMap->value);
498              hasSize=1;
499            }
[917]500            else
501              lsvalue=Py_None;
502            if(uMap!=NULL){
503              lcvalue=PyString_FromString(cMap->value);;
504            }else
505              lcvalue=Py_None;
[360]506
507            if(PyList_SetItem(value,i,lvalue)<0){
508              fprintf(stderr,"Unable to set key value pair...");
509              return NULL;
510            } 
511            if(PyList_SetItem(svalue,i,lsvalue)<0){
512              fprintf(stderr,"Unable to set key value pair...");
513              return NULL;
514            } 
[917]515            if(PyList_SetItem(cvalue,i,lcvalue)<0){
516              fprintf(stderr,"Unable to set key value pair...");
517              return NULL;
518            }
[360]519          }
520         
[917]521          PyObject* lmvalue;
[360]522          map* mMap=getMapArray(tmp,tmap->name,i);
523          if(mMap!=NULL){
524            lmvalue=PyString_FromString(mMap->value);
525          }else
526            lmvalue=Py_None;
527         
528          if(PyList_SetItem(mvalue,i,lmvalue)<0){
529              fprintf(stderr,"Unable to set key value pair...");
530              return NULL;
531          } 
532         
533        }
534
535        if(PyDict_SetItem(res,name,value)<0){
536          fprintf(stderr,"Unable to set key value pair...");
537          return NULL;
538        }
539        if(PyDict_SetItem(res,PyString_FromString(tmap->name),mvalue)<0){
540          fprintf(stderr,"Unable to set key value pair...");
541          return NULL;
542        }
[917]543        if(PyDict_SetItem(res,PyString_FromString("cache_file"),cvalue)<0){
544          fprintf(stderr,"Unable to set key value pair...");
545          return NULL;
546        }
[360]547        if(hasSize>0)
548          if(PyDict_SetItem(res,PyString_FromString("size"),svalue)<0){
549            fprintf(stderr,"Unable to set key value pair...");
550            return NULL;
551          }
552      }
[917]553      else if(size!=NULL && useFile==NULL){
[453]554        PyObject* value=PyString_FromStringAndSize(tmp->value,atoi(size->value));
[59]555        if(PyDict_SetItem(res,name,value)<0){
[471]556          Py_DECREF(value);
[295]557          fprintf(stderr,"Unable to set key value pair...");
558          return NULL;
[43]559        }
[471]560        Py_DECREF(value);
[58]561      }
[59]562      else{
[453]563        PyObject* value=PyString_FromString(tmp->value);
[59]564        if(PyDict_SetItem(res,name,value)<0){
[471]565          Py_DECREF(value);
[295]566          fprintf(stderr,"Unable to set key value pair...");
567          return NULL;
[43]568        }
[471]569        Py_DECREF(value);
[59]570      }
571    }
572    else{
[360]573      if(PyDict_GetItem(res,name)==NULL){
[453]574        PyObject* value=PyString_FromString(tmp->value);
[360]575        if(PyDict_SetItem(res,name,value)<0){
[471]576          Py_DECREF(value);
[360]577          fprintf(stderr,"Unable to set key value pair...");
578          return NULL;
579        }
[471]580        Py_DECREF(value);
[43]581      }
[59]582    }
583    Py_DECREF(name);
[1]584    tmp=tmp->next;
585  }
586  return (PyDictObject*) res;
587}
588
[579]589/**
590 * Convert a Python dictionary to a maps
591 *
592 * @param t the PyDictObject to convert
593 * @return a new maps containing the converted PyDictObject
[781]594 * @warning make sure to free resources returned by this function
[579]595 */
[1]596maps* mapsFromPyDict(PyDictObject* t){
597  maps* res=NULL;
[682]598  maps* cursor=NULL;
[1]599  PyObject* list=PyDict_Keys((PyObject*)t);
600  int nb=PyList_Size(list);
601  int i;
[682]602  PyObject* key;
603  PyObject* value;
[1]604  for(i=0;i<nb;i++){
605#ifdef DEBUG
606    fprintf(stderr,">> parsing maps %d\n",i);
607#endif
[682]608    key=PyList_GetItem(list,i);
609    value=PyDict_GetItem((PyObject*)t,key);
[1]610#ifdef DEBUG
611    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
612            PyString_AsString(key),PyString_AsString(value));
613#endif
[790]614    cursor=createMaps(PyString_AsString(key));
[295]615    cursor->content=mapFromPyDict((PyDictObject*)value);
[790]616    PyObject* cname=PyString_FromString("child");
617    PyObject* childs=PyDict_GetItem((PyObject*)value,cname);
618    if(childs!=NULL)
619      cursor->child=mapsFromPyDict((PyDictObject*)childs);
620    Py_DECREF(cname);
[1]621#ifdef DEBUG
[295]622    dumpMap(cursor->content);
[1]623#endif
624    cursor->next=NULL;
625    if(res==NULL)
[59]626      res=dupMaps(&cursor);
[1]627    else
628      addMapsToMaps(&res,cursor);
[59]629    freeMap(&cursor->content);
630    free(cursor->content);
631    free(cursor);
[1]632#ifdef DEBUG
633    dumpMaps(res);
634    fprintf(stderr,">> parsed maps %d\n",i);
635#endif
636  }
[505]637  Py_DECREF(list);
[1]638  return res;
639}
640
[579]641/**
[738]642 * Convert a Python dictionary to a maps
643 *
644 * @param t the PyDictObject to convert
645 * @return a new maps containing the converted PyDictObject
646 * @warning make sure to free resources returned by this function
647 */
648maps* _mapsFromPyDict(PyDictObject* t){
649       
650        PyObject* list = PyDict_Keys((PyObject*)t); // new ref 
651        int nb = PyList_Size(list);     
652       
653        if (nb < 1) {
654                Py_DECREF(list);
655                return NULL;
656        }
657
658        maps* ptr = (maps*) malloc(MAPS_SIZE);
659        maps* res = ptr;       
660       
661        PyObject* key;
662        PyObject* value;
663       
664        for(int i = 0; i < nb; i++) {
665               
666                key = PyList_GetItem(list,i); // borrowed ref
667                value = PyDict_GetItem((PyObject*) t, key); // borrowed ref
668               
669                ptr->name = zStrdup(PyString_AsString(key));
670                ptr->content = mapFromPyDict((PyDictObject*) value);
671               
672                ptr->next = i < nb - 1 ? (maps*) malloc(MAPS_SIZE) : NULL;
673                ptr = ptr->next;
674        }
675        Py_DECREF(list);
676
677        return res;
678} // mapsFromPyDict
679
680/**
[579]681 * Convert a Python dictionary to a map
682 *
683 * @param t the PyDictObject to convert
684 * @return a new map containing the converted PyDictObject
[781]685 * @warning make sure to free resources returned by this function
[579]686 */
[1]687map* mapFromPyDict(PyDictObject* t){
688  map* res=NULL;
689  PyObject* list=PyDict_Keys((PyObject*)t);
690  int nb=PyList_Size(list);
691  int i;
[682]692  PyObject* key;
693  PyObject* value;
[1]694  for(i=0;i<nb;i++){
[682]695    key=PyList_GetItem(list,i);
696    value=PyDict_GetItem((PyObject*)t,key);
[1]697#ifdef DEBUG
698    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
699            PyString_AsString(key),PyString_AsString(value));
700#endif
[790]701    if(strncmp(PyString_AsString(key),"child",5)!=0){
702      if(strncmp(PyString_AsString(key),"value",5)==0){
[927]703#if PY_MAJOR_VERSION >= 3 
704        const
705#endif
706          char *buffer=NULL;
[790]707        Py_ssize_t size;
[392]708#if PY_MAJOR_VERSION >= 3
[790]709        if(PyBytes_Check(value)){
710          size=PyBytes_Size(value);
711          buffer=PyBytes_AsString(value);
[682]712        }
[790]713        else
714          if(PyUnicode_Check(value) && PyUnicode_READY(value) == 0){
715            buffer=PyUnicode_AsUTF8AndSize(value,&size);
716          }
717          else{
[738]718#ifdef DEBUG
[790]719            fprintf(stderr,"Unsupported return value.");
[738]720#endif
[790]721            return NULL;
722          }
[392]723#else
[790]724        PyString_AsStringAndSize(value,&buffer,&size);
[738]725#endif     
[790]726        res = addToMapWithSize(res,PyString_AsString(key),buffer,size);
727      }else{
[927]728#if PY_MAJOR_VERSION >= 3 
729        const
730#endif
731          char* lkey=PyString_AsString(key);
732#if PY_MAJOR_VERSION >= 3 
733        const
734#endif
735          char* lvalue=PyString_AsString(value);
[790]736        if(res!=NULL){
737          if(PyString_Size(value)>0)
738            addToMap(res,lkey,lvalue);
739        }
740        else{
741          if(PyString_Size(value)>0)
742            res=createMap(lkey,lvalue);
743        }
[392]744      }
[67]745    }
[1]746  }
[505]747  Py_DECREF(list);
[1]748  return res;
749}
[368]750
[579]751/**
[738]752 * Convert a Python dictionary to a map
753 *
754 * @param t the PyDictObject to convert
755 * @return a new map containing the converted PyDictObject
756 * @warning make sure to free resources returned by this function
757 */
758map* _mapFromPyDict(PyDictObject* t) {
759       
[928]760  PyObject* list = PyDict_Keys((PyObject*) t); // new ref
761  int nb = PyList_Size(list);
[738]762       
[928]763  if (nb < 1) {
764    Py_DECREF(list);
765    return NULL;
766  }     
[738]767       
[928]768  map* ptr = (map*) malloc(MAP_SIZE);
769  map* res = ptr;
[738]770       
[928]771  PyObject* key;
772  PyObject* value;
773#if PY_MAJOR_VERSION >= 3 
774  const
775#endif
776    char *buffer = NULL;
777  Py_ssize_t size;
778  for(int i = 0; i < nb; i++) {
[738]779               
[928]780    key = PyList_GetItem(list, i); // borrowed ref
781    value = PyDict_GetItem((PyObject*) t, key); // borrowed ref         
[738]782                               
[928]783    ptr->name = zStrdup(PyString_AsString(key));               
784    map* msize = NULL;
[738]785               
[928]786#if PY_MAJOR_VERSION >= 3
787    if (PyBytes_Check(value)) {
788      // value is byte array
789      size = PyBytes_Size(value);                               
790      buffer = PyBytes_AsString(value); // pointer to internal buffer
791      char sz[32];
792      sprintf(sz, "%d", (int) size);   
793      msize = createMap("size", sz);                   
794    }
795    else if (PyUnicode_Check(value) && PyUnicode_READY(value) == 0) {
796      // value is string object         
797      buffer = PyUnicode_AsUTF8AndSize(value, &size);
798      size++;
799    }
800    else {
801      printf("Type not recognized\n");
802      // error handling
803      // ...
804    }
805#else   
806    PyString_AsStringAndSize(value, &buffer, &size);
807    size++;
808    // to do: handle byte arrays
809#endif
[738]810               
[928]811    ptr->value = (char*) malloc(size); // check for NULL pointer
812    memmove(ptr->value, buffer, size);
[738]813                       
[928]814    if (msize != NULL) {
815      ptr->next = msize;
816      ptr = ptr->next;
817    }                                           
[738]818               
[928]819    ptr->next = i < nb - 1 ? (map*) malloc(MAP_SIZE) : NULL;
820    ptr = ptr->next;
821  }     
822  Py_DECREF(list);
[738]823                       
[928]824  return res;
[738]825} // mapFromPyDict
826
827/**
[580]828 * Use the ZOO-Services messages translation function from the Python
[579]829 * environment
830 *
831 * @param self the Python object on which we can run the method
832 * @param args the Python arguments given from the Python environment
[581]833 * @return a new Python string containing the translated value
[579]834 * @see _ss
835 */
[368]836PyObject*
[376]837PythonTranslate(PyObject* self, PyObject* args)
838{
839  char *str;
840  if (!PyArg_ParseTuple(args, "s", &str)){
841#ifdef DEBUG
842    fprintf(stderr,"Incorrect arguments to update status function");
843#endif
844    return NULL;
845  }
846  return PyString_FromString(_ss(str));
847}
848
[579]849/**
850 * Update the ongoing status of a running service from the Python environment
851 *
852 * @param self the Python object on which we can run the method
853 * @param args the Python arguments given from the Python environment
854 * @return None to the Python environment
855 * @see _updateStatus
856 */
[376]857PyObject*
[368]858PythonUpdateStatus(PyObject* self, PyObject* args)
859{
860  maps* conf;
861  PyObject* confdict;
862  int istatus;
[624]863  char* status=NULL;
[368]864  if (!PyArg_ParseTuple(args, "O!i", &PyDict_Type, &confdict, &istatus)){
865#ifdef DEBUG
866    fprintf(stderr,"Incorrect arguments to update status function");
867#endif
[624]868    Py_RETURN_NONE;
[368]869  }
870  if (istatus < 0 || istatus > 100){
871     PyErr_SetString(ZooError, "Status must be a percentage.");
[624]872     Py_RETURN_NONE;
[368]873  }else{
874     char tmpStatus[4];
875     snprintf(tmpStatus, 4, "%i", istatus);
[453]876     status = zStrdup(tmpStatus);
[368]877  }
[624]878  // create a local copy and update the lenv map
[368]879  conf = mapsFromPyDict((PyDictObject*)confdict);
[624]880  if(status!=NULL){
881    setMapInMaps(conf,"lenv","status",status);
882    free(status);
[368]883  }
[624]884  else
885    setMapInMaps(conf,"lenv","status","15");
886  _updateStatus(conf);
[368]887  freeMaps(&conf);
888  free(conf);
889  Py_RETURN_NONE;
890}
Note: See TracBrowser for help on using the repository browser.

Search

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png