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

Last change on this file was 967, checked in by djay, 10 months ago

Add support for the two inputs / outputs syntaxes discussed in SWG in both the ZOO-Kernel and the HTML basic UI. Update documentation, add a section for the ZOO-API in Python language section. Rename variables in service.c to ease readabiliy.

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

Search

Context Navigation

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