git.fiddlerwoaroof.com
Browse code

fixing bug (undefined variable)

Ed L authored on 06/06/2011 17:55:07
Showing 7 changed files
... ...
@@ -32,4 +32,10 @@
32 32
 #  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 33
 #  
34 34
 #
35
+try: import json
36
+except ImportError:
37
+	import simplejson as json
38
+	import sys
39
+	sys.modules['json'] = json
40
+
35 41
 __version__ = "$Revision: 1.2 $".split(":")[1][:-1].strip()
... ...
@@ -30,6 +30,7 @@
30 30
 #  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 31
 #
32 32
 #
33
+import warnings
33 34
 from jsonrpc.utilities import public
34 35
 import jsonrpc.jsonutil
35 36
 
... ...
@@ -80,18 +81,20 @@ codemap = {0: RPCError}
80 81
 codemap.update( (e.code, e) for e in RPCError.__subclasses__() )
81 82
 
82 83
 class JsonInstantiate:
83
-   @classmethod
84
-   def from_json(cls, json):
85
-      data = jsonrpc.jsonutil.decode(json)
86
-      if isinstance(data, list):
87
-         result = cls.from_list(data)
88
-      else:
89
-         result = cls.from_dict(data)
90
-      return result
84
+	@classmethod
85
+	def from_json(cls, json):
86
+		data = json
87
+		if hasattr(json, 'upper'):
88
+			data = jsonrpc.jsonutil.decode(json)
89
+		if isinstance(data, list):
90
+			result = cls.from_list(data)
91
+		else:
92
+			result = cls.from_dict(data)
93
+		return result
91 94
 
92
-   @classmethod
93
-   def from_list(cls, responses):
94
-      return [cls.from_dict(r) for r in responses]
95
+	@classmethod
96
+	def from_list(cls, responses):
97
+		return [cls.from_dict(r) for r in responses]
95 98
 
96 99
 
97 100
 class Request(object, JsonInstantiate):
... ...
@@ -127,6 +130,9 @@ class Request(object, JsonInstantiate):
127 130
 	def check(self):
128 131
 		if self.version != '2.0': raise InvalidRequest
129 132
 		if not isinstance(self.method, (str, unicode)): raise InvalidRequest
133
+		if not isinstance(self.id, (str, unicode, int, type(None))):
134
+			self.id = None
135
+			raise InvalidRequest
130 136
 
131 137
 
132 138
 	def json_equivalent(self):
... ...
@@ -137,7 +143,7 @@ class Request(object, JsonInstantiate):
137 143
 		if self.args and self.kwargs:
138 144
 			self.kwargs['__args'] = self.args
139 145
 		if self.kwargs:
140
-			result['params'] = self.kwargs
146
+			params = self.kwargs
141 147
 
142 148
 		return dict(
143 149
 			jsonrpc = self.version,
... ...
@@ -82,7 +82,7 @@ class ProxyEvents(object):
82 82
 		self.IDGen = self.IDGen()
83 83
 		self.proxy = proxy
84 84
 
85
-	def get_postdata(self, args, kwargs):
85
+	def get_params(self, args, kwargs):
86 86
 		'''allow a subclass to modify the method's arguments
87 87
 
88 88
 		e.g. if an authentication token is necessary, the subclass can automatically insert it into every call'''
... ...
@@ -108,14 +108,15 @@ class JSONRPCProxy(object):
108 108
 	_eventhandler = ProxyEvents
109 109
 	def customize(self, eventhandler):
110 110
 		self._eventhandler = eventhandler(self)
111
+		return self
111 112
 
112 113
 	def _transformURL(self, serviceURL, path):
113
-		if serviceURL[-1] == '/':
114
+		if serviceURL.endswith('/'):
114 115
 			serviceURL = serviceURL[:-1]
115
-		if path[0] != '/':
116
-			path = '/%s'%path
117
-		if path[-1] != '/' and '?' not in path:
118
-			path = '%s/'%path
116
+		if path.endswith('/'):
117
+			path = path[:-1]
118
+		if path.startswith('/'):
119
+			path = path[1:]
119 120
 		return serviceURL, path
120 121
 
121 122
 
... ...
@@ -131,7 +132,7 @@ class JSONRPCProxy(object):
131 132
 		return cls(url, path, serviceName, ctxid)
132 133
 
133 134
 
134
-	def __init__(self, host, path='/jsonrpc', serviceName=None, *args, **kwargs):
135
+	def __init__(self, host, path='jsonrpc', serviceName=None, *args, **kwargs):
135 136
 		self.serviceURL = host
136 137
 		self._serviceName = serviceName
137 138
 		self._path = path
... ...
@@ -143,19 +144,25 @@ class JSONRPCProxy(object):
143 144
 	def __getattr__(self, name):
144 145
 		if self._serviceName != None:
145 146
 			name = "%s.%s" % (self._serviceName, name)
146
-		return self.__class__(self.serviceURL, path=self._path, serviceName=name)
147
+		return self.__class__(self.serviceURL, path=self._path, serviceName=name).customize(type(self._eventhandler))
147 148
 
148 149
 
149 150
 	def _get_postdata(self, args=None, kwargs=None):
150
-		args,kwargs = self._eventhandler.get_postdata(args, kwargs)
151
+		_args, _kwargs = self._eventhandler.get_params(args, kwargs)
151 152
 		id = self._eventhandler.IDGen
152
-		result = Request(id, self._serviceName, args, kwargs)
153
+		result = Request(id, self._serviceName, _args, _kwargs)
153 154
 		return jsonrpc.jsonutil.encode(result)
154 155
 
156
+	def _get_url(self):
157
+		result = [self.serviceURL]
158
+		if self._path:
159
+			result.append(self._path)
160
+		result.append('')
161
+		return '/'.join(result)
155 162
 
156 163
 	def __call__(self, *args, **kwargs):
157 164
 
158
-		url = '%(host)s%(path)s' % dict(host = self.serviceURL, path = self._path)
165
+		url = self._get_url()
159 166
 		postdata = self._get_postdata(args, kwargs)
160 167
 		respdata = urllib.urlopen(url, postdata).read()
161 168
 		resp = Response.from_dict(jsonrpc.jsonutil.decode(respdata))
... ...
@@ -184,7 +191,7 @@ class JSONRPCProxy(object):
184 191
 		if hasattr(methods, 'items'): methods = methods.items()
185 192
 		data = [ getattr(self, k)._get_postdata(*v) for k, v in methods ]
186 193
 		postdata = '[%s]' % ','.join(data)
187
-		respdata = urllib.urlopen(self.serviceURL, postdata).read()
194
+		respdata = urllib.urlopen(self._get_url(), postdata).read()
188 195
 		resp = Response.from_json(respdata)
189 196
 		try:
190 197
 			result = resp.get_result()
... ...
@@ -107,10 +107,7 @@ class JSON_RPC(Resource):
107 107
 
108 108
 			content = self.eventhandler.processcontent(content, request)
109 109
 
110
-			if isinstance(content, list):
111
-				content = jsonrpc.common.Request.from_list(content)
112
-			else:
113
-				content = jsonrpc.common.Request.from_dict(content)
110
+			content = jsonrpc.common.Request.from_json(content)
114 111
 
115 112
 			try:
116 113
 				if hasattr(content, 'check'):
... ...
@@ -179,6 +176,7 @@ class JSON_RPC(Resource):
179 176
 			except BaseException, e:
180 177
 				err = e
181 178
 		else: err = result
179
+
182 180
 		err = self.render_error(err, id)
183 181
 		self.eventhandler.log(err, request)
184 182
 
... ...
@@ -31,7 +31,7 @@
31 31
 #  
32 32
 #
33 33
 import json
34
-import unittest
34
+from twisted.trial import unittest
35 35
 import collections
36 36
 
37 37
 from jsonrpc import jsonutil
38 38
new file mode 100644
... ...
@@ -0,0 +1,95 @@
1
+import jsonrpc.common
2
+import jsonrpc.proxy
3
+from twisted.trial import unittest
4
+import mock
5
+import urllib
6
+import StringIO
7
+
8
+# Run example server before tests
9
+
10
+class TestJSONRPCProxy(unittest.TestCase):
11
+
12
+	def setUp(self):
13
+		self.proxy = jsonrpc.proxy.JSONRPCProxy('http://localhost:8007', path='aaa')
14
+
15
+	def test_eventhandler(self):
16
+		eventhandler = mock.MagicMock(spec=jsonrpc.proxy.ProxyEvents)
17
+		args = (1,2)
18
+		kwargs = {'a':1, 'b':2}
19
+
20
+		def get_params(self, args, kwargs):
21
+			print args, kwargs
22
+			return args, kwargs
23
+		eventhandler.get_params.side_effect = get_params
24
+
25
+		eventhandler.proc_response.side_effect = lambda _, data: data
26
+
27
+		self.proxy = jsonrpc.proxy.JSONRPCProxy.from_url('http://localhost:8007')
28
+		self.proxy.customize(lambda *a: eventhandler)
29
+		self.assertEqual(self.proxy._get_url(), 'http://localhost:8007/')
30
+
31
+		self.proxy.add(*args)
32
+		self.assertTrue(eventhandler.get_params.called)
33
+		eventhandler.get_params.assert_called_once_with( args, {} )
34
+		self.assertTrue(eventhandler.procresponse.called)
35
+
36
+		eventhandler.reset_mock()
37
+
38
+		self.proxy.add(**kwargs)
39
+		self.assertTrue(eventhandler.get_params.called)
40
+		eventhandler.get_params.assert_called_once_with( (), kwargs )
41
+		self.assertTrue(eventhandler.procresponse.called)
42
+
43
+
44
+	def test_url(self):
45
+		self.proxy = jsonrpc.proxy.JSONRPCProxy.from_url('http://localhost:8007')
46
+		self.assertEqual(self.proxy._get_url(), 'http://localhost:8007/')
47
+
48
+		self.proxy = jsonrpc.proxy.JSONRPCProxy.from_url('http://localhost:8007/aaa/')
49
+		self.assertEqual(self.proxy._get_url(), 'http://localhost:8007/aaa/')
50
+
51
+		self.proxy = jsonrpc.proxy.JSONRPCProxy.from_url('http://localhost:8007/aaa')
52
+		self.assertEqual(self.proxy._get_url(), 'http://localhost:8007/aaa/')
53
+
54
+		self.proxy = jsonrpc.proxy.JSONRPCProxy('http://localhost:8007')
55
+		self.assertEqual(self.proxy._get_url(), 'http://localhost:8007/jsonrpc/')
56
+
57
+		self.proxy = jsonrpc.proxy.JSONRPCProxy('http://localhost:8007', path='aaa')
58
+		self.assertEqual(self.proxy._get_url(), 'http://localhost:8007/aaa/')
59
+
60
+	def test_call(self):
61
+		self.assertEqual(self.proxy.add(1,2), 3)
62
+		self.assertEqual(self.proxy.subtract(2,1), 1)
63
+
64
+	def test_exceptions(self):
65
+		self.assertRaises(jsonrpc.common.RPCError, self.proxy.add, 1,'2')
66
+		self.assertRaises(jsonrpc.common.MethodNotFound, self.proxy.missingmethod)
67
+
68
+	def test_batchcall(self):
69
+		batch =[
70
+			('add',      [ (1,2), {} ]),
71
+			('subtract', [ (2,1), {} ]),
72
+			('add',      [ (1,3), {} ])
73
+		]
74
+		self.assertEqual(self.proxy.batch_call(batch), [(3, None), (1, None), (4, None)])
75
+
76
+		batch =[
77
+			('add',			[ (),    dict(a=1,b=2) ]),
78
+			('subtract',	[ (2,1), dict() ]),
79
+			('add',			[ (1,3), dict() ])
80
+		]
81
+		self.assertEqual(self.proxy.batch_call(batch), [(3, None), (1, None), (4, None)])
82
+
83
+		batch =[
84
+			('add', 			[ (), dict(a=1,b=2) ]),
85
+			('subtract', 	[ (), dict(a=2,b=1) ]),
86
+			('add', 			[ (), dict(a=1,b=3) ])
87
+		]
88
+		self.assertEqual(self.proxy.batch_call(batch), [(3, None), (1, None), (4, None)])
89
+
90
+
91
+	#def test_<testname here>(self):
92
+	#	pass
93
+
94
+if __name__ == '__main__':
95
+	unittest.main()
... ...
@@ -39,7 +39,7 @@ import jsonrpc.server
39 39
 import jsonrpc.jsonutil
40 40
 
41 41
 from twisted.web.test.test_web import DummyRequest
42
-from twisted.internet.defer import succeed
42
+from twisted.internet.defer import succeed, DeferredList
43 43
 from twisted.web.static import server
44 44
 
45 45
 def _render(resource, request):
... ...
@@ -99,6 +99,62 @@ class TestJSONRPCServer(unittest.TestCase):
99 99
 
100 100
 		return d
101 101
 
102
+	def test_requestid(self):
103
+		resource = jsonrpc.server.JSON_RPC()
104
+		resource.customize(SimpleEventHandler)
105
+
106
+		request0 = DummyRequest([''])
107
+		request0.getCookie = mock.Mock()
108
+		request0.content = StringIO.StringIO('{"jsonrpc": "2.0", "params": %s, "method": "echo", "id": "%s"}' % (jsonrpc.jsonutil.encode([self.param]), self.id_))
109
+
110
+		d0 = _render(resource, request0)
111
+		@d0.addCallback
112
+		def rendered(ignored):
113
+			self.assertEqual(len(request0.written), 1)
114
+			data = jsonrpc.jsonutil.decode(request0.written[0])
115
+
116
+			self.assertEqual(data["id"], self.id_)
117
+
118
+
119
+		request1 = DummyRequest([''])
120
+		request1.getCookie = mock.Mock()
121
+		request1.content = StringIO.StringIO('{"jsonrpc": "2.0", "params": %s, "method": "echo", "id": 1}' % jsonrpc.jsonutil.encode([self.param]))
122
+
123
+		d1 = _render(resource, request1)
124
+		@d1.addCallback
125
+		def rendered(ignored):
126
+			self.assertEqual(len(request1.written), 1)
127
+			data = jsonrpc.jsonutil.decode(request1.written[0])
128
+
129
+			self.assertEqual(data["id"], 1)
130
+
131
+
132
+		request3 = DummyRequest([''])
133
+		request3.getCookie = mock.Mock()
134
+		request3.content = StringIO.StringIO('{"jsonrpc": "2.0", "params": %s, "method": "echo", "id": []}' % jsonrpc.jsonutil.encode([self.param]))
135
+
136
+		d3 = _render(resource, request3)
137
+		@d3.addCallback
138
+		def rendered(ignored):
139
+			self.assertEqual(len(request3.written), 1)
140
+			data = jsonrpc.jsonutil.decode(request3.written[0])
141
+
142
+			self.assertNotEqual(data["id"], [])
143
+
144
+		request4 = DummyRequest([''])
145
+		request4.getCookie = mock.Mock()
146
+		request4.content = StringIO.StringIO('{"jsonrpc": "2.0", "params": %s, "method": "echo", "id": {}}' % jsonrpc.jsonutil.encode([self.param]))
147
+
148
+		d4 = _render(resource, request4)
149
+		@d4.addCallback
150
+		def rendered(ignored):
151
+			self.assertEqual(len(request4.written), 1)
152
+			data = jsonrpc.jsonutil.decode(request4.written[0])
153
+
154
+			self.assertNotEqual(data["id"], {})
155
+
156
+		return DeferredList([d0,d1,d3,d4])
157
+
102 158
 
103 159
 	def test_invalid_data(self):
104 160
 		resource = jsonrpc.server.JSON_RPC()