various fixes
[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['value'])
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