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

Last change on this file since 753 was 738, checked in by knut, 9 years ago

Redefined the API function addToMapWithSize to fix problem with Python/PHP support. Added some variable initializations and NULL pointer checks.

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