source: branches/prototype-v0/zoo-project/zoo-kernel/service_internal_python.c @ 863

Last change on this file since 863 was 863, checked in by djay, 6 years ago

Change the default ZOO-Kernel behavior, if an input has been passed by reference, the ZOO-Service will receive a cache_file map rather than the value field which was usually returned, same for array value apply. To use the previous behavior, one can add "memory=load" to the main section of the main.cfg file. Update ZOO-Services for using this new field if available.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 22.5 KB
Line 
1/*
2 * Author : Gérald FENOY
3 *
4 * Copyright (c) 2009-2014 GeoLabs SARL
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
27/**
28 * The state for the zoo Python module
29 */
30struct module_state {
31   PyObject *error;
32};
33
34#if PY_MAJOR_VERSION >= 3
35#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
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
43#else
44#define GETSTATE(m) (&_state)
45static struct module_state _state;
46#endif
47
48/**
49 * The exception for the zoo Python module
50 */
51static PyObject* ZooError;
52
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 *  - "update_status" corresponding to the PythonUpdateStatus function
60 * @see PythonTranslate, PythonUpdateStatus
61 */
62PyMethodDef zooMethods[] = {
63  {"_", PythonTranslate, METH_VARARGS, "Translate a string using the zoo-services textdomain."},
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
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
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 */
98PyMODINIT_FUNC init_zoo(){
99  PyObject *tmp,*d;
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
110    return;
111#endif
112  }
113
114  struct module_state *st = GETSTATE(module);
115
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
125  tmp = PyString_FromString(ZOO_VERSION);
126  PyDict_SetItemString(d, "VERSION", tmp);
127  Py_DECREF(tmp);
128
129  ZooError = PyErr_NewException((char*)"zoo.error", NULL, NULL);
130  Py_INCREF(ZooError);
131  PyModule_AddObject(module, "error", ZooError);
132#if PY_MAJOR_VERSION >= 3
133  return module;
134#endif
135}
136
137/**
138 * Load a Python module then run the function corresponding to the service
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 */
147int zoo_python_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
148  char *pythonpath;
149  char *python_path;
150  maps* m=*main_conf;
151  maps* inputs=*real_inputs;
152  maps* outputs=*real_outputs;
153  map* tmp0=getMapFromMaps(*main_conf,"lenv","cwd");
154  char *ntmp=tmp0->value;
155  map* tmp=NULL;
156  int hasToClean=0;
157  tmp=getMapFromMaps(*main_conf,"env","PYTHONPATH");
158#ifdef DEBUG
159  fprintf(stderr,"PYTHON SUPPORT \n");
160#endif
161  if(tmp!=NULL){
162#ifdef DEBUG
163    fprintf(stderr,"PYTHON SUPPORT (%i)\n",strlen(tmp->value));
164#endif
165    python_path=(char*)malloc((strlen(tmp->value)+1)*sizeof(char));
166    sprintf(python_path,"%s",tmp->value);
167    hasToClean=1;
168  }
169  else{
170    map* cwdMap=getMapFromMaps(*main_conf,"main","servicePath");
171    if(cwdMap!=NULL)
172      python_path=cwdMap->value;
173    else
174      python_path=(char*)".";
175  }
176  tmp=NULL;
177  tmp=getMap(request,"metapath");
178  if(tmp!=NULL && strcmp(tmp->value,"")!=0){
179    pythonpath=(char*)malloc((4+strlen(python_path)+strlen(ntmp)+strlen(tmp->value))*sizeof(char));
180#ifdef WIN32
181  sprintf(pythonpath,"%s/%s/;%s",ntmp,tmp->value,python_path);
182#else
183  sprintf(pythonpath,"%s/%s/:%s",ntmp,tmp->value,python_path);
184#endif
185  }
186  else{
187    pythonpath=(char*)malloc((2+strlen(python_path)+strlen(ntmp))*sizeof(char));
188#ifdef WIN32
189    sprintf(pythonpath,"%s;%s",ntmp,python_path);
190#else
191    sprintf(pythonpath,"%s:%s",ntmp,python_path);
192#endif
193  }
194#ifdef DEBUG
195    fprintf(stderr,"PYTHONPATH=%s\n",pythonpath);
196#endif
197#ifndef WIN32
198  setenv("PYTHONPATH",pythonpath,1);
199#else
200  SetEnvironmentVariable("PYTHONPATH",pythonpath);
201  char* toto=(char*)malloc((strlen(pythonpath)+12)*sizeof(char));
202  sprintf(toto,"PYTHONPATH=%s",pythonpath);
203  putenv(toto);
204  free(toto);
205#endif
206  if(hasToClean>0)
207    free(python_path);
208  free(pythonpath);
209
210  PyThreadState *mainstate;
211#if PY_MAJOR_VERSION >= 3
212  PyImport_AppendInittab("zoo", init_zoo);
213#else
214  PyEval_InitThreads();
215#endif
216  Py_Initialize();
217#if PY_MAJOR_VERSION >= 3
218  PyEval_InitThreads();
219  PyImport_ImportModule("zoo");
220#else
221  init_zoo();
222#endif
223  mainstate = PyThreadState_Swap(NULL);
224  PyEval_ReleaseLock();
225  PyGILState_STATE gstate;
226  gstate = PyGILState_Ensure();
227  PyObject *pName, *pModule, *pFunc;
228  tmp=getMap(s->content,"serviceProvider");
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  }
250  else{
251    errorException (m, "Unable to parse serviceProvider please check your zcfg file.", "NoApplicableCode", NULL);
252    exit(-1);
253  }
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)){
259      PyObject *pValue;
260      PyDictObject* arg1=PyDict_FromMaps(m);
261      PyDictObject* arg2=PyDict_FromMaps(inputs);
262      PyDictObject* arg3=PyDict_FromMaps(outputs);
263      PyObject *pArgs=PyTuple_New(3);
264      if (!pArgs)
265        return -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);
272        freeMaps(real_outputs);
273        free(*real_outputs);
274        freeMaps(main_conf);
275        free(*main_conf);
276        *main_conf=mapsFromPyDict(arg1);
277        *real_outputs=mapsFromPyDict(arg3);
278#ifdef DEBUG
279        fprintf(stderr,"Result of call: %i\n", PyInt_AsLong(pValue));
280        dumpMaps(inputs);
281        dumpMaps(*real_outputs);
282#endif
283      }else{
284        PythonZooReport(m,tmp->value,0);
285        res=-1;
286      }
287    }
288    else{
289      char tmpS[1024];
290      sprintf(tmpS, "Cannot find the %s function in the %s file.\n", s->name, tmp->value);
291      errorException(m,tmpS,"NoApplicableCode",NULL);
292      res=-1;
293    }
294  } else{
295    PythonZooReport(m,tmp->value,1);
296    res=-1;
297  } 
298#if PY_MAJOR_VERSION < 3
299  PyGILState_Release(gstate);
300  PyEval_AcquireLock();
301#endif
302  PyThreadState_Swap(mainstate);
303  Py_Finalize();
304  return res;
305}
306
307/**
308 * Report Python error which may occur on loading the Python module or at
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 */
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((8+strlen(PyString_AsString(trace)))*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      char* format=_("%s\nUnable to run your python process properly. Please check the following messages : %s");
359      pbt=(char*)malloc((strlen(format)+strlen(tpbt)+strlen(PyString_AsString(trace))+1)*sizeof(char));
360      sprintf(pbt,format,tpbt,PyString_AsString(trace));
361    }
362    else{
363      if(pbt!=NULL)
364        free(pbt);
365      char* format=_("%s \n Unable to run your python process properly. Unable to provide any further information.");
366      pbt=(char*)malloc((strlen(format)+strlen(tpbt)+strlen(PyString_AsString(trace))+1)*sizeof(char));
367      sprintf(pbt,format,tpbt);
368    }
369    free(tpbt);
370  }
371  if(load>0){
372    char *tmpS=(char*)malloc((strlen(tmp0)+strlen(module)+strlen(pbt)+1)*sizeof(char));
373    sprintf(tmpS,tmp0,module,pbt);
374    errorException(m,tmpS,"NoApplicableCode",NULL);
375    free(tmpS);
376  }else
377    errorException(m,pbt,"NoApplicableCode",NULL);
378  free(pbt);
379}
380
381/**
382 * Convert a maps to a Python dictionary
383 *
384 * @param t the maps to convert
385 * @return a new PyDictObject containing the converted maps
386 * @see PyDict_FromMap
387 * @warning make sure to free resources returned by this function
388 */
389PyDictObject* PyDict_FromMaps(maps* t){
390  PyObject* res=PyDict_New( );
391  maps* tmp=t;
392  while(tmp!=NULL){
393    PyObject* value=(PyObject*)PyDict_FromMap(tmp->content);
394    if(tmp->child!=NULL){
395      PyObject* cname=PyString_FromString("child");
396      PyObject* childs=(PyObject*)PyDict_FromMaps(tmp->child);
397      if(PyDict_SetItem(value,cname,childs)<0){
398        fprintf(stderr,"Unable to set map value ...");
399        return NULL;
400      } 
401      Py_DECREF(cname);
402    }
403    PyObject* name=PyString_FromString(tmp->name);
404    if(PyDict_SetItem(res,name,value)<0){
405      fprintf(stderr,"Unable to set map value ...");
406      return NULL;
407    }
408    Py_DECREF(name);
409    tmp=tmp->next;
410  } 
411  return (PyDictObject*) res;
412}
413
414/**
415 * Convert a map to a Python dictionary
416 *
417 * @param t the map to convert
418 * @return a new PyDictObject containing the converted maps
419 * @warning make sure to free resources returned by this function
420 */
421PyDictObject* PyDict_FromMap(map* t){
422  PyObject* res=PyDict_New( );
423  map* tmp=t;
424  int hasSize=0;
425  map* isArray=getMap(tmp,"isArray");
426  map* size=getMap(tmp,"size");
427  map* useFile=getMap(tmp,"use_file");
428  map* cacheFile=getMap(tmp,"cache_file");
429  map* tmap=getMapType(tmp);
430  while(tmp!=NULL){
431    PyObject* name=PyString_FromString(tmp->name);
432    if(strcasecmp(tmp->name,"value")==0) {
433      if(isArray!=NULL){
434        map* len=getMap(tmp,"length");
435        int cnt=atoi(len->value);
436        PyObject* value=PyList_New(cnt);
437        PyObject* mvalue=PyList_New(cnt);
438        PyObject* svalue=PyList_New(cnt);
439        PyObject* cvalue=PyList_New(cnt);
440
441        for(int i=0;i<cnt;i++){
442         
443          map* vMap=getMapArray(t,"value",i);
444          map* uMap=getMapArray(t,"use_file",i);
445          map* sMap=getMapArray(t,"size",i);
446          map* cMap=getMapArray(t,"cache_file",i);
447
448          if(vMap!=NULL){
449           
450            PyObject* lvalue;
451            PyObject* lsvalue;
452            PyObject* lcvalue;
453            if(sMap==NULL || uMap!=NULL){
454              lvalue=PyString_FromString(vMap->value);
455            }
456            else{   
457              lvalue=PyString_FromStringAndSize(vMap->value,atoi(sMap->value));
458            }
459            if(sMap!=NULL){
460              lsvalue=PyString_FromString(sMap->value);
461              hasSize=1;
462            }
463            else
464              lsvalue=Py_None;
465            if(uMap!=NULL){
466              lcvalue=PyString_FromString(cMap->value);;
467            }else
468              lcvalue=Py_None;
469
470            if(PyList_SetItem(value,i,lvalue)<0){
471              fprintf(stderr,"Unable to set key value pair...");
472              return NULL;
473            } 
474            if(PyList_SetItem(svalue,i,lsvalue)<0){
475              fprintf(stderr,"Unable to set key value pair...");
476              return NULL;
477            } 
478            if(PyList_SetItem(cvalue,i,lcvalue)<0){
479              fprintf(stderr,"Unable to set key value pair...");
480              return NULL;
481            }
482          }
483         
484          PyObject* lmvalue;
485          map* mMap=getMapArray(tmp,tmap->name,i);
486          if(mMap!=NULL){
487            lmvalue=PyString_FromString(mMap->value);
488          }else
489            lmvalue=Py_None;
490         
491          if(PyList_SetItem(mvalue,i,lmvalue)<0){
492              fprintf(stderr,"Unable to set key value pair...");
493              return NULL;
494          } 
495         
496        }
497
498        if(PyDict_SetItem(res,name,value)<0){
499          fprintf(stderr,"Unable to set key value pair...");
500          return NULL;
501        }
502        if(PyDict_SetItem(res,PyString_FromString(tmap->name),mvalue)<0){
503          fprintf(stderr,"Unable to set key value pair...");
504          return NULL;
505        }
506        if(PyDict_SetItem(res,PyString_FromString("cache_file"),cvalue)<0){
507          fprintf(stderr,"Unable to set key value pair...");
508          return NULL;
509        }
510        if(hasSize>0)
511          if(PyDict_SetItem(res,PyString_FromString("size"),svalue)<0){
512            fprintf(stderr,"Unable to set key value pair...");
513            return NULL;
514          }
515      }
516      else if(size!=NULL && useFile==NULL){
517        PyObject* value=PyString_FromStringAndSize(tmp->value,atoi(size->value));
518        if(PyDict_SetItem(res,name,value)<0){
519          Py_DECREF(value);
520          fprintf(stderr,"Unable to set key value pair...");
521          return NULL;
522        }
523        Py_DECREF(value);
524      }
525      else{
526        PyObject* value=PyString_FromString(tmp->value);
527        if(PyDict_SetItem(res,name,value)<0){
528          Py_DECREF(value);
529          fprintf(stderr,"Unable to set key value pair...");
530          return NULL;
531        }
532        Py_DECREF(value);
533      }
534    }
535    else{
536      if(PyDict_GetItem(res,name)==NULL){
537        PyObject* value=PyString_FromString(tmp->value);
538        if(PyDict_SetItem(res,name,value)<0){
539          Py_DECREF(value);
540          fprintf(stderr,"Unable to set key value pair...");
541          return NULL;
542        }
543        Py_DECREF(value);
544      }
545    }
546    Py_DECREF(name);
547    tmp=tmp->next;
548  }
549  return (PyDictObject*) res;
550}
551
552/**
553 * Convert a Python dictionary to a maps
554 *
555 * @param t the PyDictObject to convert
556 * @return a new maps containing the converted PyDictObject
557 * @warning make sure to free resources returned by this function
558 */
559maps* mapsFromPyDict(PyDictObject* t){
560  maps* res=NULL;
561  maps* cursor=NULL;
562  PyObject* list=PyDict_Keys((PyObject*)t);
563  int nb=PyList_Size(list);
564  int i;
565  PyObject* key;
566  PyObject* value;
567  for(i=0;i<nb;i++){
568#ifdef DEBUG
569    fprintf(stderr,">> parsing maps %d\n",i);
570#endif
571    key=PyList_GetItem(list,i);
572    value=PyDict_GetItem((PyObject*)t,key);
573#ifdef DEBUG
574    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
575            PyString_AsString(key),PyString_AsString(value));
576#endif
577    cursor=createMaps(PyString_AsString(key));
578    cursor->content=mapFromPyDict((PyDictObject*)value);
579    PyObject* cname=PyString_FromString("child");
580    PyObject* childs=PyDict_GetItem((PyObject*)value,cname);
581    if(childs!=NULL)
582      cursor->child=mapsFromPyDict((PyDictObject*)childs);
583    Py_DECREF(cname);
584#ifdef DEBUG
585    dumpMap(cursor->content);
586#endif
587    cursor->next=NULL;
588    if(res==NULL)
589      res=dupMaps(&cursor);
590    else
591      addMapsToMaps(&res,cursor);
592    freeMap(&cursor->content);
593    free(cursor->content);
594    free(cursor);
595#ifdef DEBUG
596    dumpMaps(res);
597    fprintf(stderr,">> parsed maps %d\n",i);
598#endif
599  }
600  Py_DECREF(list);
601  return res;
602}
603
604/**
605 * Convert a Python dictionary to a maps
606 *
607 * @param t the PyDictObject to convert
608 * @return a new maps containing the converted PyDictObject
609 * @warning make sure to free resources returned by this function
610 */
611maps* _mapsFromPyDict(PyDictObject* t){
612       
613        PyObject* list = PyDict_Keys((PyObject*)t); // new ref 
614        int nb = PyList_Size(list);     
615       
616        if (nb < 1) {
617                Py_DECREF(list);
618                return NULL;
619        }
620
621        maps* ptr = (maps*) malloc(MAPS_SIZE);
622        maps* res = ptr;       
623       
624        PyObject* key;
625        PyObject* value;
626       
627        for(int i = 0; i < nb; i++) {
628               
629                key = PyList_GetItem(list,i); // borrowed ref
630                value = PyDict_GetItem((PyObject*) t, key); // borrowed ref
631               
632                ptr->name = zStrdup(PyString_AsString(key));
633                ptr->content = mapFromPyDict((PyDictObject*) value);
634               
635                ptr->next = i < nb - 1 ? (maps*) malloc(MAPS_SIZE) : NULL;
636                ptr = ptr->next;
637        }
638        Py_DECREF(list);
639
640        return res;
641} // mapsFromPyDict
642
643/**
644 * Convert a Python dictionary to a map
645 *
646 * @param t the PyDictObject to convert
647 * @return a new map containing the converted PyDictObject
648 * @warning make sure to free resources returned by this function
649 */
650map* mapFromPyDict(PyDictObject* t){
651  map* res=NULL;
652  PyObject* list=PyDict_Keys((PyObject*)t);
653  int nb=PyList_Size(list);
654  int i;
655  PyObject* key;
656  PyObject* value;
657  for(i=0;i<nb;i++){
658    key=PyList_GetItem(list,i);
659    value=PyDict_GetItem((PyObject*)t,key);
660#ifdef DEBUG
661    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
662            PyString_AsString(key),PyString_AsString(value));
663#endif
664    if(strncmp(PyString_AsString(key),"child",5)!=0){
665      if(strncmp(PyString_AsString(key),"value",5)==0){
666        char *buffer=NULL;
667        Py_ssize_t size;
668#if PY_MAJOR_VERSION >= 3
669        if(PyBytes_Check(value)){
670          size=PyBytes_Size(value);
671          buffer=PyBytes_AsString(value);
672        }
673        else
674          if(PyUnicode_Check(value) && PyUnicode_READY(value) == 0){
675            buffer=PyUnicode_AsUTF8AndSize(value,&size);
676          }
677          else{
678#ifdef DEBUG
679            fprintf(stderr,"Unsupported return value.");
680#endif
681            return NULL;
682          }
683#else
684        PyString_AsStringAndSize(value,&buffer,&size);
685#endif     
686        res = addToMapWithSize(res,PyString_AsString(key),buffer,size);
687      }else{
688        char* lkey=PyString_AsString(key);
689        char* lvalue=PyString_AsString(value);
690        if(res!=NULL){
691          if(PyString_Size(value)>0)
692            addToMap(res,lkey,lvalue);
693        }
694        else{
695          if(PyString_Size(value)>0)
696            res=createMap(lkey,lvalue);
697        }
698      }
699    }
700  }
701  Py_DECREF(list);
702  return res;
703}
704
705/**
706 * Convert a Python dictionary to a map
707 *
708 * @param t the PyDictObject to convert
709 * @return a new map containing the converted PyDictObject
710 * @warning make sure to free resources returned by this function
711 */
712map* _mapFromPyDict(PyDictObject* t) {
713       
714        PyObject* list = PyDict_Keys((PyObject*) t); // new ref
715        int nb = PyList_Size(list);
716       
717        if (nb < 1) {
718                Py_DECREF(list);
719                return NULL;
720        }       
721       
722        map* ptr = (map*) malloc(MAP_SIZE);
723        map* res = ptr;
724       
725        PyObject* key;
726        PyObject* value;
727        char *buffer = NULL;
728        Py_ssize_t size;
729        for(int i = 0; i < nb; i++) {
730               
731                key = PyList_GetItem(list, i); // borrowed ref
732                value = PyDict_GetItem((PyObject*) t, key); // borrowed ref             
733                               
734                ptr->name = zStrdup(PyString_AsString(key));           
735                map* msize = NULL;
736               
737        #if PY_MAJOR_VERSION >= 3
738                if (PyBytes_Check(value)) {
739                // value is byte array
740                        size = PyBytes_Size(value);                             
741                        buffer = PyBytes_AsString(value); // pointer to internal buffer
742                        char sz[32];
743                        sprintf(sz, "%d", (int) size); 
744                        msize = createMap("size", sz);                 
745                }
746                else if (PyUnicode_Check(value) && PyUnicode_READY(value) == 0) {
747                // value is string object               
748                        buffer = PyUnicode_AsUTF8AndSize(value, &size);
749                        size++;
750                }
751                else {
752                        printf("Type not recognized\n");
753                        // error handling
754                        // ...
755                }
756        #else   
757                PyString_AsStringAndSize(value, &buffer, &size);
758                size++;
759                // to do: handle byte arrays
760        #endif
761               
762                ptr->value = (char*) malloc(size); // check for NULL pointer
763                memmove(ptr->value, buffer, size);
764                       
765                if (msize != NULL) {
766                        ptr->next = msize;
767                        ptr = ptr->next;
768                }                                               
769               
770                ptr->next = i < nb - 1 ? (map*) malloc(MAP_SIZE) : NULL;
771                ptr = ptr->next;
772        }       
773        Py_DECREF(list);
774                       
775        return res;
776} // mapFromPyDict
777
778/**
779 * Use the ZOO-Services messages translation function from the Python
780 * environment
781 *
782 * @param self the Python object on which we can run the method
783 * @param args the Python arguments given from the Python environment
784 * @return a new Python string containing the translated value
785 * @see _ss
786 */
787PyObject*
788PythonTranslate(PyObject* self, PyObject* args)
789{
790  char *str;
791  if (!PyArg_ParseTuple(args, "s", &str)){
792#ifdef DEBUG
793    fprintf(stderr,"Incorrect arguments to update status function");
794#endif
795    return NULL;
796  }
797  return PyString_FromString(_ss(str));
798}
799
800/**
801 * Update the ongoing status of a running service from the Python environment
802 *
803 * @param self the Python object on which we can run the method
804 * @param args the Python arguments given from the Python environment
805 * @return None to the Python environment
806 * @see _updateStatus
807 */
808PyObject*
809PythonUpdateStatus(PyObject* self, PyObject* args)
810{
811  maps* conf;
812  PyObject* confdict;
813  int istatus;
814  char* status=NULL;
815  if (!PyArg_ParseTuple(args, "O!i", &PyDict_Type, &confdict, &istatus)){
816#ifdef DEBUG
817    fprintf(stderr,"Incorrect arguments to update status function");
818#endif
819    Py_RETURN_NONE;
820  }
821  if (istatus < 0 || istatus > 100){
822     PyErr_SetString(ZooError, "Status must be a percentage.");
823     Py_RETURN_NONE;
824  }else{
825     char tmpStatus[4];
826     snprintf(tmpStatus, 4, "%i", istatus);
827     status = zStrdup(tmpStatus);
828  }
829  // create a local copy and update the lenv map
830  conf = mapsFromPyDict((PyDictObject*)confdict);
831  if(status!=NULL){
832    setMapInMaps(conf,"lenv","status",status);
833    free(status);
834  }
835  else
836    setMapInMaps(conf,"lenv","status","15");
837  _updateStatus(conf);
838  freeMaps(&conf);
839  free(conf);
840  Py_RETURN_NONE;
841}
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