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

Last change on this file since 453 was 453, checked in by djay, 7 years ago

Add the optional Ruby Language Support to the ZOO-Kernel with an API similar to the Python ZOO-API. Small rewrite of Python support. Fix issue #86 and #87. Add usid in [lenv] section, this value is used to generate an unique identifier based on time and the process identifier. This usid is now used to name the stored result or the mapfile generated. Remove *some* warning messages displayed at compilation time.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 15.0 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
27struct module_state {
28    PyObject *error;
29};
30
31#if PY_MAJOR_VERSION >= 3
32#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
33#define PyInt_FromLong PyLong_FromLong
34#define PyInt_AsLong PyLong_AsLong
35#define PyString_FromString PyUnicode_FromString
36#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
37#define PyString_Check PyUnicode_Check
38#define PyString_AsString _PyUnicode_AsString
39#define PyString_Size PyUnicode_GetSize
40#else
41#define GETSTATE(m) (&_state)
42static struct module_state _state;
43#endif
44
45static PyObject* ZooError;
46
47PyMethodDef zooMethods[] = {
48  {"_", PythonTranslate, METH_VARARGS, "Translate a string using the zoo-services textdomain."},
49  {"update_status", PythonUpdateStatus, METH_VARARGS, "Update status percentage of a running process."},
50  {NULL, NULL, 0, NULL} /* tempt not the blade, all fear the sentinel */
51};
52
53#if PY_MAJOR_VERSION >= 3
54
55static int myextension_traverse(PyObject *m, visitproc visit, void *arg) {
56  Py_VISIT(GETSTATE(m)->error);
57  return 0;
58}
59
60static int myextension_clear(PyObject *m) {
61  Py_CLEAR(GETSTATE(m)->error);
62  return 0;
63}
64
65static struct PyModuleDef moduledef = {
66  PyModuleDef_HEAD_INIT,
67  "zoo",
68  NULL,
69  sizeof(struct module_state),
70  zooMethods,
71  NULL,
72  myextension_traverse,
73  myextension_clear,
74  NULL
75};
76#endif
77
78PyMODINIT_FUNC init_zoo(){
79  PyObject *tmp,*d;
80  PyObject *module = 
81#if PY_MAJOR_VERSION >= 3
82    PyModule_Create(&moduledef);
83#else
84    Py_InitModule("zoo", zooMethods);
85#endif
86  if (module == NULL){
87#if PY_MAJOR_VERSION >= 3
88    return NULL;
89#else
90    return;
91#endif
92  }
93
94  struct module_state *st = GETSTATE(module);
95
96  d = PyModule_GetDict(module);
97  tmp = PyInt_FromLong(3);
98  PyDict_SetItemString(d, "SERVICE_SUCCEEDED", tmp);
99  Py_DECREF(tmp);
100
101  tmp = PyInt_FromLong(4);
102  PyDict_SetItemString(d, "SERVICE_FAILED", tmp);
103  Py_DECREF(tmp);
104
105  ZooError = PyErr_NewException("zoo.error", NULL, NULL);
106  Py_INCREF(ZooError);
107  PyModule_AddObject(module, "error", ZooError);
108#if PY_MAJOR_VERSION >= 3
109  return module;
110#endif
111}
112
113int zoo_python_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
114  char *pythonpath;
115  char *python_path;
116  maps* m=*main_conf;
117  maps* inputs=*real_inputs;
118  maps* outputs=*real_outputs;
119  map* tmp0=getMapFromMaps(*main_conf,"lenv","cwd");
120  char *ntmp=tmp0->value;
121  map* tmp=NULL;
122  int hasToClean=0;
123  tmp=getMapFromMaps(*main_conf,"env","PYTHONPATH");
124#ifdef DEBUG
125  fprintf(stderr,"PYTHON SUPPORT \n");
126#endif
127  if(tmp!=NULL){
128#ifdef DEBUG
129    fprintf(stderr,"PYTHON SUPPORT (%i)\n",strlen(tmp->value));
130#endif
131    python_path=(char*)malloc((strlen(tmp->value))*sizeof(char));
132    sprintf(python_path,"%s",tmp->value);
133    hasToClean=1;
134  }
135  else{
136    python_path=".";
137  }
138  tmp=NULL;
139  tmp=getMap(request,"metapath");
140  if(tmp!=NULL && strcmp(tmp->value,"")!=0){
141    pythonpath=(char*)malloc((4+strlen(python_path)+strlen(ntmp)+strlen(tmp->value))*sizeof(char));
142#ifdef WIN32
143  sprintf(pythonpath,"%s/%s/;%s",ntmp,tmp->value,python_path);
144#else
145  sprintf(pythonpath,"%s/%s/:%s",ntmp,tmp->value,python_path);
146#endif
147  }
148  else{
149    pythonpath=(char*)malloc((2+strlen(python_path)+strlen(ntmp))*sizeof(char));
150#ifdef WIN32
151    sprintf(pythonpath,"%s;%s",ntmp,python_path);
152#else
153    sprintf(pythonpath,"%s:%s",ntmp,python_path);
154#endif
155  }
156#ifdef DEBUG
157    fprintf(stderr,"PYTHONPATH=%s\n",pythonpath);
158#endif
159#ifndef WIN32
160  setenv("PYTHONPATH",pythonpath,1);
161#else
162  SetEnvironmentVariable("PYTHONPATH",pythonpath);
163  char* toto=(char*)malloc((strlen(pythonpath)+12)*sizeof(char));
164  sprintf(toto,"PYTHONPATH=%s",pythonpath);
165  putenv(toto);
166  free(toto);
167#endif
168  if(hasToClean>0)
169    free(python_path);
170  free(pythonpath);
171
172  PyThreadState *mainstate;
173#if PY_MAJOR_VERSION >= 3
174  PyImport_AppendInittab("zoo", init_zoo);
175#else
176  PyEval_InitThreads();
177#endif
178  Py_Initialize();
179#if PY_MAJOR_VERSION >= 3
180  PyEval_InitThreads();
181  PyImport_ImportModule("zoo");
182#else
183  init_zoo();
184#endif
185  mainstate = PyThreadState_Swap(NULL);
186  PyEval_ReleaseLock();
187  PyGILState_STATE gstate;
188  gstate = PyGILState_Ensure();
189  PyObject *pName, *pModule, *pFunc;
190  tmp=getMap(s->content,"serviceProvider");
191  if(tmp!=NULL)
192    pName = PyString_FromString(tmp->value);
193  else{
194    map* err=createMap("text","Unable to parse serviceProvider please check your zcfg file.");
195    addToMap(err,"code","NoApplicableCode");
196    printExceptionReportResponse(m,err);
197    exit(-1);
198  }
199  pModule = PyImport_Import(pName);
200  int res=SERVICE_FAILED;
201  if (pModule != NULL) {
202    pFunc=PyObject_GetAttrString(pModule,s->name);
203    if (pFunc && PyCallable_Check(pFunc)){
204      PyObject *pValue;
205      PyDictObject* arg1=PyDict_FromMaps(m);
206      PyDictObject* arg2=PyDict_FromMaps(inputs);
207      PyDictObject* arg3=PyDict_FromMaps(outputs);
208      PyObject *pArgs=PyTuple_New(3);
209      if (!pArgs)
210        return -1;
211      PyTuple_SetItem(pArgs, 0, (PyObject *)arg1);
212      PyTuple_SetItem(pArgs, 1, (PyObject *)arg2);
213      PyTuple_SetItem(pArgs, 2, (PyObject *)arg3);
214      pValue = PyObject_CallObject(pFunc, pArgs);
215      if (pValue != NULL) {
216        res=PyInt_AsLong(pValue);
217        freeMaps(real_outputs);
218        free(*real_outputs);
219        freeMaps(main_conf);
220        free(*main_conf);
221        *main_conf=mapsFromPyDict(arg1);
222        *real_outputs=mapsFromPyDict(arg3);
223#ifdef DEBUG
224        fprintf(stderr,"Result of call: %i\n", PyInt_AsLong(pValue));
225        dumpMaps(inputs);
226        dumpMaps(*real_outputs);
227#endif
228      }else{     
229        PyObject *ptype,*pvalue, *ptraceback;
230        PyErr_Fetch(&ptype, &pvalue, &ptraceback);
231        PyObject *trace=PyObject_Str(pvalue);
232        char pbt[10240];
233        if(PyString_Check(trace))
234          sprintf(pbt,"TRACE : %s",PyString_AsString(trace));
235        else
236          fprintf(stderr,"EMPTY TRACE ?");
237        trace=NULL;
238        trace=PyObject_Str(ptype);
239        if(PyString_Check(trace)){
240          char *tpbt=zStrdup(pbt);
241          sprintf(pbt,"%s\n%s\0",tpbt,PyString_AsString(trace));
242          free(tpbt);
243        }
244        else
245          fprintf(stderr,"EMPTY TRACE ?");
246       
247        char *tpbt=zStrdup(pbt);
248        pName = PyString_FromString("traceback");
249        pModule = PyImport_Import(pName);
250        pArgs = PyTuple_New(1);
251        PyTuple_SetItem(pArgs, 0, ptraceback);
252        pFunc = PyObject_GetAttrString(pModule,"format_tb");
253        pValue = PyObject_CallObject(pFunc, pArgs);
254        trace=NULL;
255        trace=PyObject_Str(pValue);
256        if(PyString_Check(trace))
257          sprintf(pbt,"%s\nUnable to run your python process properly. Please check the following messages : %s",tpbt,PyString_AsString(trace));
258        else
259          sprintf(pbt,"%s \n Unable to run your python process properly. Unable to provide any futher informations. %s",tpbt);
260        free(tpbt);
261        map* err=createMap("text",pbt);
262        addToMap(err,"code","NoApplicableCode");
263        printExceptionReportResponse(m,err);
264        res=-1;
265      }
266    }
267    else{
268      char tmpS[1024];
269      sprintf(tmpS, "Cannot find the %s function in the %s file.\n", s->name, tmp->value);
270      map* tmps=createMap("text",tmpS);
271      printExceptionReportResponse(m,tmps);
272      res=-1;
273    }
274  } else{
275    char tmpS[1024];
276    sprintf(tmpS, "Python module %s cannot be loaded.\n", tmp->value);
277    map* tmps=createMap("text",tmpS);
278    printExceptionReportResponse(m,tmps);
279    if (PyErr_Occurred())
280      PyErr_Print();
281    PyErr_Clear();
282    res=-1;
283    //exit(-1);
284  } 
285#if PY_MAJOR_VERSION < 3
286  PyGILState_Release(gstate);
287  PyEval_AcquireLock();
288#endif
289  PyThreadState_Swap(mainstate);
290  Py_Finalize();
291  return res;
292}
293
294PyDictObject* PyDict_FromMaps(maps* t){
295  PyObject* res=PyDict_New( );
296  maps* tmp=t;
297  while(tmp!=NULL){
298    PyObject* value=(PyObject*)PyDict_FromMap(tmp->content);
299    PyObject* name=PyString_FromString(tmp->name);
300    if(PyDict_SetItem(res,name,value)<0){
301      fprintf(stderr,"Unable to set map value ...");
302      return NULL;
303    }
304    Py_DECREF(name);
305    tmp=tmp->next;
306  } 
307  return (PyDictObject*) res;
308}
309
310PyDictObject* PyDict_FromMap(map* t){
311  PyObject* res=PyDict_New( );
312  map* tmp=t;
313  int hasSize=0;
314  map* isArray=getMap(tmp,"isArray");
315  map* size=getMap(tmp,"size");
316  map* tmap=getMapType(tmp);
317  while(tmp!=NULL){
318    PyObject* name=PyString_FromString(tmp->name);
319    if(strcasecmp(tmp->name,"value")==0) {
320      if(isArray!=NULL){
321        map* len=getMap(tmp,"length");
322        int cnt=atoi(len->value);
323        PyObject* value=PyList_New(cnt);
324        PyObject* mvalue=PyList_New(cnt);
325        PyObject* svalue=PyList_New(cnt);
326
327        for(int i=0;i<cnt;i++){
328         
329          map* vMap=getMapArray(tmp,"value",i);     
330          map* sMap=getMapArray(tmp,"size",i);
331
332          if(vMap!=NULL){
333           
334            PyObject* lvalue;
335            PyObject* lsvalue;
336            if(sMap==NULL){
337              lvalue=PyString_FromString(vMap->value);
338              lsvalue=Py_None;
339            }
340            else{   
341              lvalue=PyString_FromStringAndSize(vMap->value,atoi(sMap->value));
342              lsvalue=PyString_FromString(sMap->value);
343              hasSize=1;
344            }
345
346            if(PyList_SetItem(value,i,lvalue)<0){
347              fprintf(stderr,"Unable to set key value pair...");
348              return NULL;
349            } 
350            if(PyList_SetItem(svalue,i,lsvalue)<0){
351              fprintf(stderr,"Unable to set key value pair...");
352              return NULL;
353            } 
354          }
355         
356          map* mMap=getMapArray(tmp,tmap->name,i);
357          PyObject* lmvalue;
358          if(mMap!=NULL){
359            lmvalue=PyString_FromString(mMap->value);
360          }else
361            lmvalue=Py_None;
362         
363          if(PyList_SetItem(mvalue,i,lmvalue)<0){
364              fprintf(stderr,"Unable to set key value pair...");
365              return NULL;
366          } 
367         
368        }
369
370        if(PyDict_SetItem(res,name,value)<0){
371          fprintf(stderr,"Unable to set key value pair...");
372          return NULL;
373        }
374        if(PyDict_SetItem(res,PyString_FromString(tmap->name),mvalue)<0){
375          fprintf(stderr,"Unable to set key value pair...");
376          return NULL;
377        }
378        if(hasSize>0)
379          if(PyDict_SetItem(res,PyString_FromString("size"),svalue)<0){
380            fprintf(stderr,"Unable to set key value pair...");
381            return NULL;
382          }
383      }
384      else if(size!=NULL){
385        PyObject* value=PyString_FromStringAndSize(tmp->value,atoi(size->value));
386        if(PyDict_SetItem(res,name,value)<0){
387          fprintf(stderr,"Unable to set key value pair...");
388          return NULL;
389        }
390      }
391      else{
392        PyObject* value=PyString_FromString(tmp->value);
393        if(PyDict_SetItem(res,name,value)<0){
394          fprintf(stderr,"Unable to set key value pair...");
395          return NULL;
396        }
397      }
398    }
399    else{
400      if(PyDict_GetItem(res,name)==NULL){
401        PyObject* value=PyString_FromString(tmp->value);
402        if(PyDict_SetItem(res,name,value)<0){
403          fprintf(stderr,"Unable to set key value pair...");
404          return NULL;
405        }
406      }
407    }
408    Py_DECREF(name);
409    tmp=tmp->next;
410  }
411  return (PyDictObject*) res;
412}
413
414maps* mapsFromPyDict(PyDictObject* t){
415  maps* res=NULL;
416  maps* cursor=res;
417  PyObject* list=PyDict_Keys((PyObject*)t);
418  int nb=PyList_Size(list);
419  int i;
420  for(i=0;i<nb;i++){
421#ifdef DEBUG
422    fprintf(stderr,">> parsing maps %d\n",i);
423#endif
424    PyObject* key=PyList_GetItem(list,i);
425    PyObject* value=PyDict_GetItem((PyObject*)t,key);
426#ifdef DEBUG
427    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
428            PyString_AsString(key),PyString_AsString(value));
429#endif
430    cursor=(maps*)malloc(MAPS_SIZE);
431    cursor->name=PyString_AsString(key);
432    cursor->content=mapFromPyDict((PyDictObject*)value);
433#ifdef DEBUG
434    dumpMap(cursor->content);
435#endif
436    cursor->next=NULL;
437    if(res==NULL)
438      res=dupMaps(&cursor);
439    else
440      addMapsToMaps(&res,cursor);
441    freeMap(&cursor->content);
442    free(cursor->content);
443    free(cursor);
444#ifdef DEBUG
445    dumpMaps(res);
446    fprintf(stderr,">> parsed maps %d\n",i);
447#endif
448  }
449  return res;
450}
451
452map* mapFromPyDict(PyDictObject* t){
453  map* res=NULL;
454  PyObject* list=PyDict_Keys((PyObject*)t);
455  int nb=PyList_Size(list);
456  int i;
457  for(i=0;i<nb;i++){
458    PyObject* key=PyList_GetItem(list,i);
459    PyObject* value=PyDict_GetItem((PyObject*)t,key);
460#ifdef DEBUG
461    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
462            PyString_AsString(key),PyString_AsString(value));
463#endif
464   
465    if(strcmp(PyString_AsString(key),"value")==0){
466      char *buffer=NULL;
467      Py_ssize_t size;
468#if PY_MAJOR_VERSION >= 3
469      buffer=_PyUnicode_AsStringAndSize(value,&size);
470#else
471      PyString_AsStringAndSize(value,&buffer,&size);
472#endif
473      if(res!=NULL){
474        addToMap(res,PyString_AsString(key),"");
475      }else{
476        res=createMap(PyString_AsString(key),"");
477      }
478      map* tmpR=getMap(res,"value");
479      free(tmpR->value);
480      tmpR->value=(char*)malloc((size+1)*sizeof(char));
481      memmove(tmpR->value,buffer,size*sizeof(char));
482      tmpR->value[size]=0;
483      char sin[1024];
484      sprintf(sin,"%d",size);
485      addToMap(res,"size",sin);
486    }else{
487      if(res!=NULL){
488        if(PyString_Size(value)>0)
489          addToMap(res,PyString_AsString(key),PyString_AsString(value));
490      }
491      else{
492        if(PyString_Size(value)>0)
493          res=createMap(PyString_AsString(key),PyString_AsString(value));
494      }
495    }
496  }
497  return res;
498}
499
500PyObject*
501PythonTranslate(PyObject* self, PyObject* args)
502{
503  char *str;
504  if (!PyArg_ParseTuple(args, "s", &str)){
505#ifdef DEBUG
506    fprintf(stderr,"Incorrect arguments to update status function");
507#endif
508    return NULL;
509  }
510  return PyString_FromString(_ss(str));
511}
512
513PyObject*
514PythonUpdateStatus(PyObject* self, PyObject* args)
515{
516  maps* conf;
517  PyObject* confdict;
518  int istatus;
519  char* status;
520  if (!PyArg_ParseTuple(args, "O!i", &PyDict_Type, &confdict, &istatus)){
521#ifdef DEBUG
522    fprintf(stderr,"Incorrect arguments to update status function");
523#endif
524    return NULL;
525  }
526  if (istatus < 0 || istatus > 100){
527     PyErr_SetString(ZooError, "Status must be a percentage.");
528     return NULL;
529  }else{
530     char tmpStatus[4];
531     snprintf(tmpStatus, 4, "%i", istatus);
532     status = zStrdup(tmpStatus);
533  }
534  /* now update the map */
535  {
536    PyObject* lenv = PyMapping_GetItemString(confdict, "lenv");
537    if (lenv && PyMapping_Check(lenv)){
538      PyObject* valobj = PyString_FromString(status);
539      PyMapping_SetItemString(lenv, "status", valobj);
540      Py_DECREF(valobj);
541    }
542    Py_DECREF(lenv);
543  }
544  conf = mapsFromPyDict((PyDictObject*)confdict);
545  if (getMapFromMaps(conf,"lenv","status") != NULL){
546    fprintf(stderr,"STATUS RETURNED : %s\n",status);
547    if(status!=NULL){
548      setMapInMaps(conf,"lenv","status",status);
549      free(status);
550    }
551    else
552      setMapInMaps(conf,"lenv","status","15");
553    updateStatus(conf);
554  }
555  freeMaps(&conf);
556  free(conf);
557  Py_RETURN_NONE;
558}
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