blob: 718bac3a6f9cb38505796307a4ee50d8ee3190f6 [file] [log] [blame]
mblighe8819cd2008-02-15 16:48:40 +00001
2"""
3 Copyright (c) 2007 Jan-Klaas Kollhof
4
5 This file is part of jsonrpc.
6
7 jsonrpc is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 This software is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with this software; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20"""
21
22import urllib2
Chris Masonef8b53062012-05-08 22:14:18 -070023from autotest_lib.client.common_lib import error as exceptions
mblighe8819cd2008-02-15 16:48:40 +000024
25class JSONRPCException(Exception):
26 pass
27
Chris Masone47c9e642012-04-25 14:22:18 -070028class ValidationError(JSONRPCException):
29 """Raised when the RPC is malformed."""
30 def __init__(self, error, formatted_message):
31 """Constructor.
32
33 @param error: a dict of error info like so:
34 {error['name']: 'ErrorKind',
35 error['message']: 'Pithy error description.',
36 error['traceback']: 'Multi-line stack trace'}
37 @formatted_message: string representation of this exception.
38 """
39 self.problem_keys = eval(error['message'])
40 self.traceback = error['traceback']
41 super(ValidationError, self).__init__(formatted_message)
42
43def BuildException(error):
44 """Exception factory.
45
46 Given a dict of error info, determine which subclass of
47 JSONRPCException to build and return. If can't determine the right one,
48 just return a JSONRPCException with a pretty-printed error string.
49
50 @param error: a dict of error info like so:
51 {error['name']: 'ErrorKind',
52 error['message']: 'Pithy error description.',
53 error['traceback']: 'Multi-line stack trace'}
54 """
55 error_message = '%(name)s: %(message)s\n%(traceback)s' % error
56 for cls in JSONRPCException.__subclasses__():
57 if error['name'] == cls.__name__:
58 return cls(error, error_message)
Chris Masonef8b53062012-05-08 22:14:18 -070059 for cls in exceptions.CrosDynamicSuiteException.__subclasses__():
60 if error['name'] == cls.__name__:
61 return cls(error_message)
Chris Masone47c9e642012-04-25 14:22:18 -070062 return JSONRPCException(error_message)
63
mblighe8819cd2008-02-15 16:48:40 +000064class ServiceProxy(object):
65 def __init__(self, serviceURL, serviceName=None, headers=None):
66 self.__serviceURL = serviceURL
67 self.__serviceName = serviceName
showard8e855a22008-04-15 17:32:20 +000068 self.__headers = headers or {}
mblighe8819cd2008-02-15 16:48:40 +000069
70 def __getattr__(self, name):
mblighd876f452008-12-03 15:09:17 +000071 if self.__serviceName is not None:
mblighe8819cd2008-02-15 16:48:40 +000072 name = "%s.%s" % (self.__serviceName, name)
73 return ServiceProxy(self.__serviceURL, name, self.__headers)
74
75 def __call__(self, *args, **kwargs):
jadmanski656b3b82010-01-27 23:42:27 +000076 # pull in simplejson imports lazily so that the library isn't required
77 # unless you actually need to do encoding and decoding
78 from simplejson import decoder, encoder
79
jadmanski08ff9ad2010-01-27 23:42:42 +000080 postdata = encoder.JSONEncoder().encode({"method": self.__serviceName,
81 'params': args + (kwargs,),
82 'id':'jsonrpc'})
jadmanski0afbb632008-06-06 21:10:57 +000083 request = urllib2.Request(self.__serviceURL, data=postdata,
84 headers=self.__headers)
85 respdata = urllib2.urlopen(request).read()
86 try:
jadmanski08ff9ad2010-01-27 23:42:42 +000087 resp = decoder.JSONDecoder().decode(respdata)
jadmanski0afbb632008-06-06 21:10:57 +000088 except ValueError:
89 raise JSONRPCException('Error decoding JSON reponse:\n' + respdata)
mblighd876f452008-12-03 15:09:17 +000090 if resp['error'] is not None:
Chris Masone47c9e642012-04-25 14:22:18 -070091 raise BuildException(resp['error'])
jadmanski0afbb632008-06-06 21:10:57 +000092 else:
93 return resp['result']