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
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     # xxx temporary code for scaffolding a ManifolResult on top of an API that does not expose error info
28     # as of march 2013 we work with an API that essentially either returns the value, or raises 
29     # an xmlrpclib.Fault exception with always the same 8002 code
30     # since most of the time we're getting this kind of issues for expired sessions
31     # (looks like sessions are rather short-lived), for now the choice is to map these errors on 
32     # a SESSION_EXPIRED code
33     def __getattr__(self, methodName):
34         def func(*args, **kwds):
35             if (debug): 
36                 print "entering ManifoldAPI.%s"%methodName,
37                 print "args",args,
38                 print "kwds",kwds
39             try:
40                 result=getattr(self.server, methodName)(self.auth, *args, **kwds)
41                 ### attempt to cope with old APIs and new APIs
42                 if isinstance (result, dict) and 'code' in result:
43                     # this sounds like a result from a new API, leave it untouched
44                     # XXX jordan : we need to wrap it into a ResultValue structure
45                     # XXX this is not good until we merge both repos
46                     if result['code'] != 2:
47                         return ManifoldResult(code=result['code'], value=result['result'])
48                     else:
49                         return ManifoldResult(code=result['code'], output=result['description'])
50                 else:
51                     if debug:
52                         print '<=== backend call', methodName, args, kwds
53                         print '.... ctd', 'Authmethod=',self.auth['AuthMethod'], self.url,'->',
54                         if not result:                        print "[no/empty result]"
55                         elif isinstance (result,str):         print "result is '%s'"%result
56                         elif isinstance (result,list):        print "result is a %d-elts list"%len(result)
57                         else:                                 print "[dont know how to display result]"
58                     return ManifoldResult (code=ManifoldCode.SUCCESS, value=result)
59             except xmlrpclib.Fault, error:
60                 ### xxx this is very rough for now
61                 # until we have some agreement about how the API calls should return error conditions
62                 # in some less unpolite way than this anonymous exception, we assume it's a problem with the session
63                 # that needs to be refreshed
64                 if error.faultCode == 8002:
65                     reason="most likely your session has expired"
66                     reason += " (the manifold API has no unambiguous error reporting mechanism yet)"
67                     return ManifoldResult (code=ManifoldCode.SESSION_EXPIRED, output=reason)
68                 else:
69                     reason="xmlrpclib.Fault with faultCode = %s (not taken as session expired)"%error.faultCode
70                     return ManifoldResult (code=ManifoldCode.UNKNOWN_ERROR, output=reason)
71             except Exception,error:
72                 print "ManifoldAPI: unexpected exception",error
73                 return ManifoldResult (code=ManifoldCode.UNKNOWN_ERROR, output="%s"%error)
74         return func
75
76     def send_manifold_query (self, query):
77         # We use a dictionary representation of the query for forwarding it to the API
78         ret = self.forward(query.to_dict())
79         if debug:
80             print "="*80
81             print "Result:"
82             print ret
83             print "="*80
84         return ret
85
86 #old#        (action,subject)= (query.action,query.subject)
87 #old#        # use e.g. self.Get rather than self.server.Get so we use the __getattr__ code
88 #old#        if action=='get':
89 #old## this makes the backend to squeak and one can't login anymore...
90 #old##            return self.Get(subject, query.filters, query.timestamp, query.fields)
91 #old#            return self.Get(subject, query.filters, {}, query.fields)
92 #old#        elif action=='update':
93 #old#            answer=self.Update(subject, query.filters, query.params, query.fields)
94 #old#            if not isinstance (answer, ManifoldResult): print "UNEXECPECTED answer", answer
95 #old#            return answer
96 #old#        else:
97 #old#            warning="WARNING: ManifoldAPI.send_manifold_query: %s not implemented for now"%action
98 #old#            print warning
99 #old#            print 3
100 #old#            return ManifoldResult(code=ManifoldCode.NOT_IMPLEMENTED, output=warning)