blob: b9e1121f0183e58eefc89385a71613f4cde32b82 [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)
Alex Miller4a193692013-08-21 13:59:01 -070059 for cls in (exceptions.CrosDynamicSuiteException.__subclasses__() +
60 exceptions.RPCException.__subclasses__()):
Chris Masonef8b53062012-05-08 22:14:18 -070061 if error['name'] == cls.__name__:
62 return cls(error_message)
Chris Masone47c9e642012-04-25 14:22:18 -070063 return JSONRPCException(error_message)
64
mblighe8819cd2008-02-15 16:48:40 +000065class ServiceProxy(object):
66 def __init__(self, serviceURL, serviceName=None, headers=None):
67 self.__serviceURL = serviceURL
68 self.__serviceName = serviceName
showard8e855a22008-04-15 17:32:20 +000069 self.__headers = headers or {}
mblighe8819cd2008-02-15 16:48:40 +000070
71 def __getattr__(self, name):
mblighd876f452008-12-03 15:09:17 +000072 if self.__serviceName is not None:
mblighe8819cd2008-02-15 16:48:40 +000073 name = "%s.%s" % (self.__serviceName, name)
74 return ServiceProxy(self.__serviceURL, name, self.__headers)
75
76 def __call__(self, *args, **kwargs):
Alex Miller4f341702013-03-25 12:39:12 -070077 # pull in json imports lazily so that the library isn't required
jadmanski656b3b82010-01-27 23:42:27 +000078 # unless you actually need to do encoding and decoding
Alex Miller4f341702013-03-25 12:39:12 -070079 from json import decoder, encoder
jadmanski656b3b82010-01-27 23:42:27 +000080
jadmanski08ff9ad2010-01-27 23:42:42 +000081 postdata = encoder.JSONEncoder().encode({"method": self.__serviceName,
82 'params': args + (kwargs,),
83 'id':'jsonrpc'})
jadmanski0afbb632008-06-06 21:10:57 +000084 request = urllib2.Request(self.__serviceURL, data=postdata,
85 headers=self.__headers)
86 respdata = urllib2.urlopen(request).read()
87 try:
jadmanski08ff9ad2010-01-27 23:42:42 +000088 resp = decoder.JSONDecoder().decode(respdata)
jadmanski0afbb632008-06-06 21:10:57 +000089 except ValueError:
90 raise JSONRPCException('Error decoding JSON reponse:\n' + respdata)
mblighd876f452008-12-03 15:09:17 +000091 if resp['error'] is not None:
Chris Masone47c9e642012-04-25 14:22:18 -070092 raise BuildException(resp['error'])
jadmanski0afbb632008-06-06 21:10:57 +000093 else:
94 return resp['result']