Merge branch 'jordan' of ssh://git.onelab.eu/git/myslice into jordan
[myslice.git] / manifold / manifoldapi.py
1 # Manifold API Python interface
2 import xmlrpclib
3
4 from myslice.config import Config
5
6 from manifoldresult import ManifoldResult, ManifoldCode, ManifoldException
7
8 debug=False
9 debug=True
10
11 class ManifoldAPI:
12
13     def __init__(self, auth=None, cainfo=None):
14         
15         config = Config()
16         self.auth = auth
17         self.cainfo = cainfo
18         self.errors = []
19         self.trace = []
20         self.calls = {}
21         self.multicall = False
22         self.url = config.manifold_url
23         self.server = xmlrpclib.Server(self.url, verbose=False, allow_none=True)
24
25     def __repr__ (self): return "ManifoldAPI[%s]"%self.url
26
27     # a one-liner to give a hint of what the return value looks like
28     def _print_result (self, result):
29         if not result:                        print "[no/empty result]"
30         elif isinstance (result,str):         print "result is '%s'"%result
31         elif isinstance (result,list):        print "result is a %d-elts list"%len(result)
32         else:                                 print "[dont know how to display result]"
33
34     # xxx temporary code for scaffolding a ManifolResult on top of an API that does not expose error info
35     # as of march 2013 we work with an API that essentially either returns the value, or raises 
36     # an xmlrpclib.Fault exception with always the same 8002 code
37     # since most of the time we're getting this kind of issues for expired sessions
38     # (looks like sessions are rather short-lived), for now the choice is to map these errors on 
39     # a SESSION_EXPIRED code
40     def __getattr__(self, methodName):
41         def func(*args, **kwds):
42             try:
43                 if debug: print "====> ManifoldAPI.%s"%methodName,"args",args,"kwds",kwds
44                 result=getattr(self.server, methodName)(self.auth, *args, **kwds)
45                 if debug:
46                     print '<==== backend call %s(*%s,**%s) returned'%(methodName,args,kwds),
47                     print '.ctd. Authmethod=',self.auth['AuthMethod'], self.url,'->',
48                     self._print_result(result)
49                 ### attempt to cope with old APIs and new APIs
50                 if isinstance (result, dict) and 'code' in result:
51                     if debug: print "taken as new API"
52                     # this sounds like a result from a new API
53                     # minimal treatment is required, but we do want to turn this into a 
54                     # class instance
55                     if result['code'] != 2: # in the manifold world, this can be either
56                                             # 0 (ok) 1 (partial result) or 2 which means error
57                         if debug: print "OK (new API)"
58                         return ManifoldResult(code=result['code'], value=result['value'])
59                     else:
60                         if debug: print "KO (new API) - raising ManifoldException"
61                         raise ManifoldException(ManifoldResult(code=result['code'], output=result['description']))
62                 else:
63                     if debug: print "taken as old API"
64                     # we're talking to an old API
65                     # so if we make it here it should mean success
66                     return ManifoldResult (code=ManifoldCode.SUCCESS, value=result)
67             except xmlrpclib.Fault, error:
68                 ### xxx this is very rough for now
69                 # until we have some agreement about how the API calls should return error conditions
70                 # in some less unpolite way than this anonymous exception, we assume it's a problem with the session
71                 # that needs to be refreshed
72                 if error.faultCode == 8002:
73                     if debug: print "KO (old API - 8002) - raising ManifoldException"
74                     reason="most likely your session has expired"
75                     reason += " (the manifold API has no unambiguous error reporting mechanism yet)"
76                     raise ManifoldException ( ManifoldResult (code=ManifoldCode.SESSION_EXPIRED, output=reason))
77                 else:
78                     if debug: print "KO (old API - other) - raising ManifoldException"
79                     reason="xmlrpclib.Fault with faultCode = %s (not taken as session expired)"%error.faultCode
80                     raise ManifoldException ( ManifoldResult (code=ManifoldCode.UNKNOWN_ERROR, output=reason))
81             except Exception,error:
82                 if debug: print "KO (unexpected exception)",error
83                 raise ManifoldException ( ManifoldResult (code=ManifoldCode.UNKNOWN_ERROR, output="%s"%error) )
84         return func
85
86     def send_manifold_query (self, query):
87         # We use a dictionary representation of the query for forwarding it to the API
88         ret = self.forward(query.to_dict())
89         if debug:
90             print "="*80
91             print "Result:"
92             print ret
93             print "="*80
94         return ret