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

Last change on this file since 784 was 784, checked in by djay, 8 years ago

Give the capability to store the main.cfg file in sysconfdir and the services in servicePath if defined in the [main] section.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 21.3 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
59 *  - "updte_status" corresponding to the PythonUpdateStatus function
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){
[451]148  char *pythonpath;
149  char *python_path;
[1]150  maps* m=*main_conf;
151  maps* inputs=*real_inputs;
152  maps* outputs=*real_outputs;
[392]153  map* tmp0=getMapFromMaps(*main_conf,"lenv","cwd");
154  char *ntmp=tmp0->value;
[1]155  map* tmp=NULL;
[451]156  int hasToClean=0;
[1]157  tmp=getMapFromMaps(*main_conf,"env","PYTHONPATH");
[63]158#ifdef DEBUG
[9]159  fprintf(stderr,"PYTHON SUPPORT \n");
[63]160#endif
[1]161  if(tmp!=NULL){
[63]162#ifdef DEBUG
[9]163    fprintf(stderr,"PYTHON SUPPORT (%i)\n",strlen(tmp->value));
[63]164#endif
[9]165    python_path=(char*)malloc((strlen(tmp->value))*sizeof(char));
166    sprintf(python_path,"%s",tmp->value);
[451]167    hasToClean=1;
[1]168  }
169  else{
[784]170    map* cwdMap=getMapFromMaps(*main_conf,"main","servicePath");
171    if(cwdMap!=NULL)
172      python_path=cwdMap->value;
173    else
174      python_path=(char*)".";
[1]175  }
176  tmp=NULL;
177  tmp=getMap(request,"metapath");
[392]178  if(tmp!=NULL && strcmp(tmp->value,"")!=0){
179    pythonpath=(char*)malloc((4+strlen(python_path)+strlen(ntmp)+strlen(tmp->value))*sizeof(char));
[1]180#ifdef WIN32
[451]181  sprintf(pythonpath,"%s/%s/;%s",ntmp,tmp->value,python_path);
[1]182#else
[451]183  sprintf(pythonpath,"%s/%s/:%s",ntmp,tmp->value,python_path);
[1]184#endif
[392]185  }
186  else{
187    pythonpath=(char*)malloc((2+strlen(python_path)+strlen(ntmp))*sizeof(char));
[1]188#ifdef WIN32
189    sprintf(pythonpath,"%s;%s",ntmp,python_path);
190#else
[392]191    sprintf(pythonpath,"%s:%s",ntmp,python_path);
[1]192#endif
[392]193  }
[67]194#ifdef DEBUG
[9]195    fprintf(stderr,"PYTHONPATH=%s\n",pythonpath);
[67]196#endif
[1]197#ifndef WIN32
198  setenv("PYTHONPATH",pythonpath,1);
199#else
200  SetEnvironmentVariable("PYTHONPATH",pythonpath);
[364]201  char* toto=(char*)malloc((strlen(pythonpath)+12)*sizeof(char));
202  sprintf(toto,"PYTHONPATH=%s",pythonpath);
203  putenv(toto);
[451]204  free(toto);
[1]205#endif
[451]206  if(hasToClean>0)
207    free(python_path);
[1]208  free(pythonpath);
[9]209
[295]210  PyThreadState *mainstate;
[392]211#if PY_MAJOR_VERSION >= 3
212  PyImport_AppendInittab("zoo", init_zoo);
213#else
[295]214  PyEval_InitThreads();
[392]215#endif
[1]216  Py_Initialize();
[392]217#if PY_MAJOR_VERSION >= 3
218  PyEval_InitThreads();
219  PyImport_ImportModule("zoo");
220#else
[368]221  init_zoo();
[392]222#endif
[295]223  mainstate = PyThreadState_Swap(NULL);
224  PyEval_ReleaseLock();
225  PyGILState_STATE gstate;
226  gstate = PyGILState_Ensure();
[1]227  PyObject *pName, *pModule, *pFunc;
228  tmp=getMap(s->content,"serviceProvider");
[505]229  map* mp=getMap(request,"metapath");
230  if(tmp!=NULL){
231    if(mp!=NULL && strlen(mp->value)>0){
232      char *mps=zStrdup(mp->value);
233      int i,len=strlen(mps);
234      int j=0;
235      for(i=0;i<len;i++){
236        if(mps[i]=='/'){
237          mps[i]='.';
238        }
239      }
240      char *mn=(char*)malloc((strlen(mps)+strlen(tmp->value)+2)*sizeof(char));
241      sprintf(mn,"%s.%s",mps,tmp->value);
242      pName = PyString_FromString(mn);
243      free(mn);
244      free(mps);
245    }
246    else{
247      pName = PyString_FromString(tmp->value);
248    }
249  }
[9]250  else{
[576]251    errorException (m, "Unable to parse serviceProvider please check your zcfg file.", "NoApplicableCode", NULL);
[9]252    exit(-1);
253  }
[1]254  pModule = PyImport_Import(pName);
255  int res=SERVICE_FAILED;
256  if (pModule != NULL) {
257    pFunc=PyObject_GetAttrString(pModule,s->name);
258    if (pFunc && PyCallable_Check(pFunc)){
[114]259      PyObject *pValue;
[1]260      PyDictObject* arg1=PyDict_FromMaps(m);
261      PyDictObject* arg2=PyDict_FromMaps(inputs);
262      PyDictObject* arg3=PyDict_FromMaps(outputs);
263      PyObject *pArgs=PyTuple_New(3);
[114]264      if (!pArgs)
265        return -1;
[1]266      PyTuple_SetItem(pArgs, 0, (PyObject *)arg1);
267      PyTuple_SetItem(pArgs, 1, (PyObject *)arg2);
268      PyTuple_SetItem(pArgs, 2, (PyObject *)arg3);
269      pValue = PyObject_CallObject(pFunc, pArgs);
270      if (pValue != NULL) {
271        res=PyInt_AsLong(pValue);
[9]272        freeMaps(real_outputs);
273        free(*real_outputs);
[59]274        freeMaps(main_conf);
275        free(*main_conf);
[57]276        *main_conf=mapsFromPyDict(arg1);
[9]277        *real_outputs=mapsFromPyDict(arg3);
[1]278#ifdef DEBUG
279        fprintf(stderr,"Result of call: %i\n", PyInt_AsLong(pValue));
280        dumpMaps(inputs);
[364]281        dumpMaps(*real_outputs);
[1]282#endif
[9]283      }else{     
[576]284        PythonZooReport(m,tmp->value,0);
[295]285        res=-1;
[1]286      }
287    }
288    else{
289      char tmpS[1024];
[295]290      sprintf(tmpS, "Cannot find the %s function in the %s file.\n", s->name, tmp->value);
[576]291      errorException(m,tmpS,"NoApplicableCode",NULL);
[295]292      res=-1;
[1]293    }
294  } else{
[576]295    PythonZooReport(m,tmp->value,1);
[295]296    res=-1;
[1]297  } 
[392]298#if PY_MAJOR_VERSION < 3
[295]299  PyGILState_Release(gstate);
[478]300  PyEval_AcquireLock();
[392]301#endif
[295]302  PyThreadState_Swap(mainstate);
[1]303  Py_Finalize();
304  return res;
305}
306
[579]307/**
[580]308 * Report Python error which may occur on loading the Python module or at
[579]309 * runtime.
310 *
311 * @param m the conf maps containing the main.cfg settings
312 * @param module the service name
313 * @param load 1 if the Python module was not loaded yet
314 */
[576]315void PythonZooReport(maps* m,const char* module,int load){
316  PyObject *pName, *pModule, *pFunc;
317  PyObject *ptype, *pvalue, *ptraceback,*pValue,*pArgs;
318  PyErr_Fetch(&ptype, &pvalue, &ptraceback);
319  char *pStrErrorMessage = PyString_AsString(pvalue);
320  char *tmp0=_("Python module %s cannot be loaded. Message: %s\n");
321 
322  PyObject *trace=PyObject_Str(pvalue);
323  char *pbt=NULL;
324  if(PyString_Check(trace)){
325    pbt=(char*)malloc((7+strlen(PyString_AsString(trace))+1)*sizeof(char));
326    sprintf(pbt,"TRACE: %s",PyString_AsString(trace));
327  }
328  else
329    fprintf(stderr,"EMPTY TRACE ?");
330 
331  trace=NULL;
332 
333  trace=PyObject_Str(ptype);
334  if(PyString_Check(trace)){
335    char *tpbt=zStrdup(pbt);
336    if(pbt!=NULL)
337      free(pbt);
338    pbt=(char*)malloc((1+strlen(tpbt)+strlen(PyString_AsString(trace))+1)*sizeof(char));
339    sprintf(pbt,"%s\n%s",tpbt,PyString_AsString(trace));
340    free(tpbt);
341  }
342  else
343    fprintf(stderr,"EMPTY TRACE ?");
344 
345  if(ptraceback!=NULL){
346    char *tpbt=zStrdup(pbt);
347    pName = PyString_FromString("traceback");
348    pModule = PyImport_Import(pName);
349    pArgs = PyTuple_New(1);
350    PyTuple_SetItem(pArgs, 0, ptraceback);
351    pFunc = PyObject_GetAttrString(pModule,"format_tb");
352    pValue = PyObject_CallObject(pFunc, pArgs);
353    trace=NULL;
354    trace=PyObject_Str(pValue);
355    if(PyString_Check(trace)){
356      if(pbt!=NULL)
357        free(pbt);
358      pbt=(char*)malloc((90+strlen(tpbt)+strlen(PyString_AsString(trace))+1)*sizeof(char));
359      sprintf(pbt,_("%s\nUnable to run your python process properly. Please check the following messages : %s"),tpbt,PyString_AsString(trace));
360    }
361    else{
362      if(pbt!=NULL)
363        free(pbt);
364      pbt=(char*)malloc((90+strlen(tpbt)+strlen(PyString_AsString(trace))+1)*sizeof(char));     
[781]365      sprintf(pbt,_("%s \n Unable to run your python process properly. Unable to provide any further information."),tpbt);
[576]366    }
367    free(tpbt);
368  }
369  if(load>0){
370    char *tmpS=(char*)malloc((strlen(tmp0)+strlen(module)+strlen(pbt)+1)*sizeof(char));
371    sprintf(tmpS,tmp0,module,pbt);
372    errorException(m,tmpS,"NoApplicableCode",NULL);
373    free(tmpS);
374  }else
375    errorException(m,pbt,"NoApplicableCode",NULL);
376  free(pbt);
377}
378
[579]379/**
380 * Convert a maps to a Python dictionary
381 *
382 * @param t the maps to convert
383 * @return a new PyDictObject containing the converted maps
384 * @see PyDict_FromMap
[781]385 * @warning make sure to free resources returned by this function
[579]386 */
[1]387PyDictObject* PyDict_FromMaps(maps* t){
388  PyObject* res=PyDict_New( );
389  maps* tmp=t;
390  while(tmp!=NULL){
[295]391    PyObject* value=(PyObject*)PyDict_FromMap(tmp->content);
[453]392    PyObject* name=PyString_FromString(tmp->name);
[295]393    if(PyDict_SetItem(res,name,value)<0){
394      fprintf(stderr,"Unable to set map value ...");
395      return NULL;
[1]396    }
[295]397    Py_DECREF(name);
[1]398    tmp=tmp->next;
399  } 
400  return (PyDictObject*) res;
401}
402
[579]403/**
404 * Convert a map to a Python dictionary
405 *
406 * @param t the map to convert
407 * @return a new PyDictObject containing the converted maps
[781]408 * @warning make sure to free resources returned by this function
[579]409 */
[1]410PyDictObject* PyDict_FromMap(map* t){
411  PyObject* res=PyDict_New( );
412  map* tmp=t;
[360]413  int hasSize=0;
414  map* isArray=getMap(tmp,"isArray");
[58]415  map* size=getMap(tmp,"size");
[360]416  map* tmap=getMapType(tmp);
[1]417  while(tmp!=NULL){
[453]418    PyObject* name=PyString_FromString(tmp->name);
[360]419    if(strcasecmp(tmp->name,"value")==0) {
420      if(isArray!=NULL){
421        map* len=getMap(tmp,"length");
422        int cnt=atoi(len->value);
423        PyObject* value=PyList_New(cnt);
424        PyObject* mvalue=PyList_New(cnt);
425        PyObject* svalue=PyList_New(cnt);
426
427        for(int i=0;i<cnt;i++){
428         
429          map* vMap=getMapArray(tmp,"value",i);     
430          map* sMap=getMapArray(tmp,"size",i);
431
432          if(vMap!=NULL){
433           
434            PyObject* lvalue;
435            PyObject* lsvalue;
436            if(sMap==NULL){
437              lvalue=PyString_FromString(vMap->value);
438              lsvalue=Py_None;
439            }
[453]440            else{   
[360]441              lvalue=PyString_FromStringAndSize(vMap->value,atoi(sMap->value));
442              lsvalue=PyString_FromString(sMap->value);
443              hasSize=1;
444            }
445
446            if(PyList_SetItem(value,i,lvalue)<0){
447              fprintf(stderr,"Unable to set key value pair...");
448              return NULL;
449            } 
450            if(PyList_SetItem(svalue,i,lsvalue)<0){
451              fprintf(stderr,"Unable to set key value pair...");
452              return NULL;
453            } 
454          }
455         
456          map* mMap=getMapArray(tmp,tmap->name,i);
457          PyObject* lmvalue;
458          if(mMap!=NULL){
459            lmvalue=PyString_FromString(mMap->value);
460          }else
461            lmvalue=Py_None;
462         
463          if(PyList_SetItem(mvalue,i,lmvalue)<0){
464              fprintf(stderr,"Unable to set key value pair...");
465              return NULL;
466          } 
467         
468        }
469
470        if(PyDict_SetItem(res,name,value)<0){
471          fprintf(stderr,"Unable to set key value pair...");
472          return NULL;
473        }
474        if(PyDict_SetItem(res,PyString_FromString(tmap->name),mvalue)<0){
475          fprintf(stderr,"Unable to set key value pair...");
476          return NULL;
477        }
478        if(hasSize>0)
479          if(PyDict_SetItem(res,PyString_FromString("size"),svalue)<0){
480            fprintf(stderr,"Unable to set key value pair...");
481            return NULL;
482          }
483      }
484      else if(size!=NULL){
[453]485        PyObject* value=PyString_FromStringAndSize(tmp->value,atoi(size->value));
[59]486        if(PyDict_SetItem(res,name,value)<0){
[471]487          Py_DECREF(value);
[295]488          fprintf(stderr,"Unable to set key value pair...");
489          return NULL;
[43]490        }
[471]491        Py_DECREF(value);
[58]492      }
[59]493      else{
[453]494        PyObject* value=PyString_FromString(tmp->value);
[59]495        if(PyDict_SetItem(res,name,value)<0){
[471]496          Py_DECREF(value);
[295]497          fprintf(stderr,"Unable to set key value pair...");
498          return NULL;
[43]499        }
[471]500        Py_DECREF(value);
[59]501      }
502    }
503    else{
[360]504      if(PyDict_GetItem(res,name)==NULL){
[453]505        PyObject* value=PyString_FromString(tmp->value);
[360]506        if(PyDict_SetItem(res,name,value)<0){
[471]507          Py_DECREF(value);
[360]508          fprintf(stderr,"Unable to set key value pair...");
509          return NULL;
510        }
[471]511        Py_DECREF(value);
[43]512      }
[59]513    }
514    Py_DECREF(name);
[1]515    tmp=tmp->next;
516  }
517  return (PyDictObject*) res;
518}
519
[579]520/**
521 * Convert a Python dictionary to a maps
522 *
523 * @param t the PyDictObject to convert
524 * @return a new maps containing the converted PyDictObject
[781]525 * @warning make sure to free resources returned by this function
[579]526 */
[1]527maps* mapsFromPyDict(PyDictObject* t){
528  maps* res=NULL;
[682]529  maps* cursor=NULL;
[1]530  PyObject* list=PyDict_Keys((PyObject*)t);
531  int nb=PyList_Size(list);
532  int i;
[682]533  PyObject* key;
534  PyObject* value;
[1]535  for(i=0;i<nb;i++){
536#ifdef DEBUG
537    fprintf(stderr,">> parsing maps %d\n",i);
538#endif
[682]539    key=PyList_GetItem(list,i);
540    value=PyDict_GetItem((PyObject*)t,key);
[1]541#ifdef DEBUG
542    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
543            PyString_AsString(key),PyString_AsString(value));
544#endif
[9]545    cursor=(maps*)malloc(MAPS_SIZE);
[682]546    cursor->name=zStrdup(PyString_AsString(key));
[295]547    cursor->content=mapFromPyDict((PyDictObject*)value);
[1]548#ifdef DEBUG
[295]549    dumpMap(cursor->content);
[1]550#endif
551    cursor->next=NULL;
552    if(res==NULL)
[59]553      res=dupMaps(&cursor);
[1]554    else
555      addMapsToMaps(&res,cursor);
[59]556    freeMap(&cursor->content);
557    free(cursor->content);
558    free(cursor);
[1]559#ifdef DEBUG
560    dumpMaps(res);
561    fprintf(stderr,">> parsed maps %d\n",i);
562#endif
563  }
[505]564  Py_DECREF(list);
[1]565  return res;
566}
567
[579]568/**
[738]569 * Convert a Python dictionary to a maps
570 *
571 * @param t the PyDictObject to convert
572 * @return a new maps containing the converted PyDictObject
573 * @warning make sure to free resources returned by this function
574 */
575maps* _mapsFromPyDict(PyDictObject* t){
576       
577        PyObject* list = PyDict_Keys((PyObject*)t); // new ref 
578        int nb = PyList_Size(list);     
579       
580        if (nb < 1) {
581                Py_DECREF(list);
582                return NULL;
583        }
584
585        maps* ptr = (maps*) malloc(MAPS_SIZE);
586        maps* res = ptr;       
587       
588        PyObject* key;
589        PyObject* value;
590       
591        for(int i = 0; i < nb; i++) {
592               
593                key = PyList_GetItem(list,i); // borrowed ref
594                value = PyDict_GetItem((PyObject*) t, key); // borrowed ref
595               
596                ptr->name = zStrdup(PyString_AsString(key));
597                ptr->content = mapFromPyDict((PyDictObject*) value);
598               
599                ptr->next = i < nb - 1 ? (maps*) malloc(MAPS_SIZE) : NULL;
600                ptr = ptr->next;
601        }
602        Py_DECREF(list);
603
604        return res;
605} // mapsFromPyDict
606
607/**
[579]608 * Convert a Python dictionary to a map
609 *
610 * @param t the PyDictObject to convert
611 * @return a new map containing the converted PyDictObject
[781]612 * @warning make sure to free resources returned by this function
[579]613 */
[1]614map* mapFromPyDict(PyDictObject* t){
615  map* res=NULL;
616  PyObject* list=PyDict_Keys((PyObject*)t);
617  int nb=PyList_Size(list);
618  int i;
[682]619  PyObject* key;
620  PyObject* value;
[1]621  for(i=0;i<nb;i++){
[682]622    key=PyList_GetItem(list,i);
623    value=PyDict_GetItem((PyObject*)t,key);
[1]624#ifdef DEBUG
625    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
626            PyString_AsString(key),PyString_AsString(value));
627#endif
[453]628   
[623]629    if(strncmp(PyString_AsString(key),"value",5)==0){
[100]630      char *buffer=NULL;
[67]631      Py_ssize_t size;
[392]632#if PY_MAJOR_VERSION >= 3
[682]633      if(PyBytes_Check(value)){
634        size=PyBytes_Size(value);
635        buffer=PyBytes_AsString(value);
636      }
637      else
638        if(PyUnicode_Check(value) && PyUnicode_READY(value) == 0){
639          buffer=PyUnicode_AsUTF8AndSize(value,&size);
640        }
641        else{
[738]642#ifdef DEBUG
[682]643          fprintf(stderr,"Unsupported return value.");
[738]644#endif
[682]645          return NULL;
646        }
[392]647#else
[67]648      PyString_AsStringAndSize(value,&buffer,&size);
[738]649#endif     
650          res = addToMapWithSize(res,PyString_AsString(key),buffer,size);
[67]651    }else{
[471]652      char* lkey=PyString_AsString(key);
653      char* lvalue=PyString_AsString(value);
[392]654      if(res!=NULL){
[411]655        if(PyString_Size(value)>0)
[471]656          addToMap(res,lkey,lvalue);
[392]657      }
658      else{
[411]659        if(PyString_Size(value)>0)
[471]660          res=createMap(lkey,lvalue);
[392]661      }
[67]662    }
[1]663  }
[505]664  Py_DECREF(list);
[1]665  return res;
666}
[368]667
[579]668/**
[738]669 * Convert a Python dictionary to a map
670 *
671 * @param t the PyDictObject to convert
672 * @return a new map containing the converted PyDictObject
673 * @warning make sure to free resources returned by this function
674 */
675map* _mapFromPyDict(PyDictObject* t) {
676       
677        PyObject* list = PyDict_Keys((PyObject*) t); // new ref
678        int nb = PyList_Size(list);
679       
680        if (nb < 1) {
681                Py_DECREF(list);
682                return NULL;
683        }       
684       
685        map* ptr = (map*) malloc(MAP_SIZE);
686        map* res = ptr;
687       
688        PyObject* key;
689        PyObject* value;
690        char *buffer = NULL;
691        Py_ssize_t size;
692        for(int i = 0; i < nb; i++) {
693               
694                key = PyList_GetItem(list, i); // borrowed ref
695                value = PyDict_GetItem((PyObject*) t, key); // borrowed ref             
696                               
697                ptr->name = zStrdup(PyString_AsString(key));           
698                map* msize = NULL;
699               
700        #if PY_MAJOR_VERSION >= 3
701                if (PyBytes_Check(value)) {
702                // value is byte array
703                        size = PyBytes_Size(value);                             
704                        buffer = PyBytes_AsString(value); // pointer to internal buffer
705                        char sz[32];
706                        sprintf(sz, "%d", (int) size); 
707                        msize = createMap("size", sz);                 
708                }
709                else if (PyUnicode_Check(value) && PyUnicode_READY(value) == 0) {
710                // value is string object               
711                        buffer = PyUnicode_AsUTF8AndSize(value, &size);
712                        size++;
713                }
714                else {
715                        printf("Type not recognized\n");
716                        // error handling
717                        // ...
718                }
719        #else   
720                PyString_AsStringAndSize(value, &buffer, &size);
721                size++;
722                // to do: handle byte arrays
723        #endif
724               
725                ptr->value = (char*) malloc(size); // check for NULL pointer
726                memmove(ptr->value, buffer, size);
727                       
728                if (msize != NULL) {
729                        ptr->next = msize;
730                        ptr = ptr->next;
731                }                                               
732               
733                ptr->next = i < nb - 1 ? (map*) malloc(MAP_SIZE) : NULL;
734                ptr = ptr->next;
735        }       
736        Py_DECREF(list);
737                       
738        return res;
739} // mapFromPyDict
740
741/**
[580]742 * Use the ZOO-Services messages translation function from the Python
[579]743 * environment
744 *
745 * @param self the Python object on which we can run the method
746 * @param args the Python arguments given from the Python environment
[581]747 * @return a new Python string containing the translated value
[579]748 * @see _ss
749 */
[368]750PyObject*
[376]751PythonTranslate(PyObject* self, PyObject* args)
752{
753  char *str;
754  if (!PyArg_ParseTuple(args, "s", &str)){
755#ifdef DEBUG
756    fprintf(stderr,"Incorrect arguments to update status function");
757#endif
758    return NULL;
759  }
760  return PyString_FromString(_ss(str));
761}
762
[579]763/**
764 * Update the ongoing status of a running service from the Python environment
765 *
766 * @param self the Python object on which we can run the method
767 * @param args the Python arguments given from the Python environment
768 * @return None to the Python environment
769 * @see _updateStatus
770 */
[376]771PyObject*
[368]772PythonUpdateStatus(PyObject* self, PyObject* args)
773{
774  maps* conf;
775  PyObject* confdict;
776  int istatus;
[624]777  char* status=NULL;
[368]778  if (!PyArg_ParseTuple(args, "O!i", &PyDict_Type, &confdict, &istatus)){
779#ifdef DEBUG
780    fprintf(stderr,"Incorrect arguments to update status function");
781#endif
[624]782    Py_RETURN_NONE;
[368]783  }
784  if (istatus < 0 || istatus > 100){
785     PyErr_SetString(ZooError, "Status must be a percentage.");
[624]786     Py_RETURN_NONE;
[368]787  }else{
788     char tmpStatus[4];
789     snprintf(tmpStatus, 4, "%i", istatus);
[453]790     status = zStrdup(tmpStatus);
[368]791  }
[624]792  // create a local copy and update the lenv map
[368]793  conf = mapsFromPyDict((PyDictObject*)confdict);
[624]794  if(status!=NULL){
795    setMapInMaps(conf,"lenv","status",status);
796    free(status);
[368]797  }
[624]798  else
799    setMapInMaps(conf,"lenv","status","15");
800  _updateStatus(conf);
[368]801  freeMaps(&conf);
802  free(conf);
803  Py_RETURN_NONE;
804}
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