git.fiddlerwoaroof.com
Browse code

Writing documentation, tweaking example server and proxy

Ed L authored on 02/06/2011 21:41:39
Showing 5 changed files
... ...
@@ -71,6 +71,7 @@ source_suffix = '.rst'
71 71
 
72 72
 # The encoding of source files.
73 73
 #source_encoding = 'utf-8-sig'
74
+highlight_language = 'python'
74 75
 
75 76
 # The master toctree document.
76 77
 master_doc = 'index'
77 78
new file mode 100644
... ...
@@ -0,0 +1,63 @@
1
+.. Copyright (c) 2011 Edward Langley
2
+   All rights reserved.
3
+   
4
+   Redistribution and use in source and binary forms, with or without
5
+   modification, are permitted provided that the following conditions
6
+   are met:
7
+   
8
+   Redistributions of source code must retain the above copyright notice,
9
+   this list of conditions and the following disclaimer.
10
+   
11
+   Redistributions in binary form must reproduce the above copyright
12
+   notice, this list of conditions and the following disclaimer in the
13
+   documentation and/or other materials provided with the distribution.
14
+   
15
+   Neither the name of the project's author nor the names of its
16
+   contributors may be used to endorse or promote products derived from
17
+   this software without specific prior written permission.
18
+   
19
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22
+   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25
+   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ 
31
+
32
+Getting Started
33
+===============
34
+This code will create a server that logs all requests, and provides two methods to clients:
35
+add and subtract:
36
+
37
+.. literalinclude:: ../../jsonrpc/example_server.py
38
+   :language: python
39
+   :linenos:
40
+   :tab-width: 2
41
+   :lines: 2,3,34-
42
+
43
+To use the server, start the client this way:
44
+
45
+.. code-block:: bash
46
+
47
+   # Python 2.6
48
+   % python2.6 -i -m jsonrpc.__main__ http://localhost:8007
49
+
50
+   # Python 2.7
51
+   % python2.7 -i -m jsonrpc http://localhost:8007
52
+   
53
+.. code-block:: python
54
+
55
+   >>> server.add(1,2)
56
+   3
57
+   >>> server.subtract(3,2)
58
+   1
59
+   >>> server.batch_call(dict(
60
+   ...   add = ((3, 2), {} ),
61
+   ...   subtract = ((), {'a': 3, 'b': 2})
62
+   ... ))
63
+   [(5, None), (1, None)]
... ...
@@ -44,6 +44,7 @@ Contents:
44 44
 .. toctree::
45 45
    :maxdepth: 2
46 46
 
47
+   getting_started
47 48
    server
48 49
    proxy
49 50
    jsonutil
... ...
@@ -30,26 +30,35 @@
30 30
 #  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 31
 #
32 32
 #
33
+
33 34
 from twisted.internet import reactor, ssl
34 35
 from twisted.web import server
35 36
 import traceback
36 37
 
37 38
 from jsonrpc.server import ServerEvents, JSON_RPC
38 39
 
39
-class JSONRPCTest(ServerEvents):
40
+class ExampleServer(ServerEvents):
41
+	# inherited hooks
40 42
 	def log(self, responses, txrequest):
41 43
 		if isinstance(responses, list):
42 44
 			for response in responses:
43
-				print txrequest, response.id, response.result or response.error
45
+				msg = self.get_msg(response)
46
+				print txrequest, msg
44 47
 		else:
45
-			print txrequest, responses.id, responses.result or responses.error
48
+			msg = self.get_msg(response)
49
+			print txrequest, msg
46 50
 
47 51
 	def findmethod(self, method):
48
-		if method in set(['add', 'subtract']):
52
+		if method in self.methods:
49 53
 			return getattr(self, method)
50 54
 		else:
51 55
 			return None
52 56
 
57
+	# helper methods
58
+	methods = set(['add', 'subtract'])
59
+	def _get_msg(self, response):
60
+		return ' '.join([response.id, response.result or response.error])
61
+
53 62
 	def subtract(self, a, b):
54 63
 		return a-b
55 64
 
... ...
@@ -65,6 +74,3 @@ PORT = 8007
65 74
 print 'Listening on port %d...' % PORT
66 75
 reactor.listenTCP(PORT, site)
67 76
 reactor.run()
68
-
69
-
70
-__version__ = "$Revision: 1.8 $".split(":")[1][:-1].strip()
... ...
@@ -80,11 +80,12 @@ class ProxyEvents(object):
80 80
 	'''An event handler for JSONRPCProxy'''
81 81
 
82 82
 	#: an instance of a class which defines a __get__ method, used to generate a request id
83
-	IDGen = IDGen()
83
+	IDGen = IDGen
84 84
 
85 85
 
86 86
 	def __init__(self, proxy):
87 87
 		'''Allow a subclass to do its own initialization, gets any arguments leftover from __init__'''
88
+		self.IDGen = self.IDGen()
88 89
 		self.proxy = proxy
89 90
 
90 91
 	def get_postdata(self, args, kwargs):
... ...
@@ -98,9 +99,32 @@ class ProxyEvents(object):
98 99
 		return data
99 100
 
100 101
 
102
+class Request(object):
103
+
104
+	def __init__(self, id, method, args=None, kwargs=None):
105
+		self.version = '2.0'
106
+		self.id = id
107
+		self.method = method
108
+		self.args = args
109
+		self.kwargs = kwargs
110
+
111
+	def json_equivalent(self):
112
+		if kwargs.has_key('__args'):
113
+			raise ValueError, 'invalid argument name: __args'
114
+
115
+		result = dict(
116
+			jsonrpc = self.version,
117
+			id = self.id,
118
+			method = self.method
119
+		)
120
+
121
+		if self.args and self.kwargs:
122
+			self.kwargs['__args'] = self.args
123
+
124
+
125
+
101 126
 
102 127
 
103
-inst = lambda x:x()
104 128
 class JSONRPCProxy(object):
105 129
 	'''A class implementing a JSON-RPC Proxy.
106 130
 
... ...
@@ -128,20 +152,6 @@ class JSONRPCProxy(object):
128 152
 		return serviceURL, path
129 153
 
130 154
 
131
-	def _get_postdata(self, args, kwargs):
132
-		args,kwargs = self._eventhandler.get_postdata(args, kwargs)
133
-
134
-		if kwargs.has_key('__args'):
135
-			raise ValueError, 'invalid argument name: __args'
136
-		kwargs['__args'] = args or ()
137
-		postdata = jsonrpc.jsonutil.encode({
138
-			"method": self._serviceName,
139
-			'params': kwargs,
140
-			'id': self._eventhandler.IDGen,
141
-			'jsonrpc': '2.0'
142
-		})
143
-		return postdata
144
-
145 155
 	## Public interface
146 156
 	@classmethod
147 157
 	def from_url(cls, url, ctxid=None, serviceName=None):
... ...
@@ -169,6 +179,12 @@ class JSONRPCProxy(object):
169 179
 		return self.__class__(self.serviceURL, path=self._path, serviceName=name)
170 180
 
171 181
 
182
+	def _get_postdata(self, args=None, kwargs=None):
183
+		args,kwargs = self._eventhandler.get_postdata(args, kwargs)
184
+		id = self._eventhandler.IDGen
185
+		return Request(id, self._serviceNams, args, kwargs)
186
+		postdata = jsonrpc.jsonutil.encode({	})
187
+		return postdata
172 188
 
173 189
 
174 190
 	def __call__(self, *args, **kwargs):