Merge lp:~free.ekanayaka/landscape-client/amp-cleanup into lp:~landscape/landscape-client/trunk
- amp-cleanup
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Free Ekanayaka | ||||
Approved revision: | 662 | ||||
Merged at revision: | 662 | ||||
Proposed branch: | lp:~free.ekanayaka/landscape-client/amp-cleanup | ||||
Merge into: | lp:~landscape/landscape-client/trunk | ||||
Diff against target: |
621 lines (+102/-93) 4 files modified
landscape/lib/amp.py (+46/-49) landscape/lib/tests/test_amp.py (+52/-41) landscape/tests/test_amp.py (+1/-1) landscape/tests/test_configuration.py (+3/-2) |
||||
To merge this branch: | bzr merge lp:~free.ekanayaka/landscape-client/amp-cleanup | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Geoff Teale (community) | Approve | ||
Alberto Donato (community) | Approve | ||
Review via email: mp+159799@code.launchpad.net |
Commit message
This is almost a trivial change, in preparation of some follow-up cleanup work. It's mostly about cosmetics and little details in landscape.lib.amp:
- Change the module docstring to reflect how this machinery's API will change (note
that it hasn't been implemented yet tho). The new style is a bit more Twisted-y,
and doesn't force the use to use unix sockets.
- MethodCallSende
method invokation, rather then MethodCall.response low-level dict. Tests have been
updated accordingly.
- MethodCallSende
Description of the change
This is almost a trivial change, in preparation of some follow-up cleanup work. It's mostly about cosmetics and little details in landscape.lib.amp:
- Change the module docstring to reflect how this machinery's API will change (note
that it hasn't been implemented yet tho). The new style is a bit more Twisted-y,
and doesn't force the use to use unix sockets.
- MethodCallSende
method invokation, rather then MethodCall.response low-level dict. Tests have been
updated accordingly.
- MethodCallSende
Geoff Teale (tealeg) wrote : | # |
Clean as a whistle +1
Preview Diff
1 | === modified file 'landscape/lib/amp.py' | |||
2 | --- landscape/lib/amp.py 2013-04-15 11:00:01 +0000 | |||
3 | +++ landscape/lib/amp.py 2013-04-19 11:37:27 +0000 | |||
4 | @@ -18,29 +18,21 @@ | |||
5 | 18 | Process A can "publish" the greeter object by defining which methods are | 18 | Process A can "publish" the greeter object by defining which methods are |
6 | 19 | exposed remotely and opening a Unix socket for incoming connections:: | 19 | exposed remotely and opening a Unix socket for incoming connections:: |
7 | 20 | 20 | ||
14 | 21 | class GreeterProtocol(MethodCallProtocol): | 21 | factory = MethodCallServerFactory(greeter, ["hello"]) |
9 | 22 | |||
10 | 23 | methods = ["hello"] | ||
11 | 24 | |||
12 | 25 | factory = MethodCallFactory(object=greeter) | ||
13 | 26 | factory.protocol = GreeterProtocol | ||
15 | 27 | reactor.listenUNIX("/some/socket/path", factory) | 22 | reactor.listenUNIX("/some/socket/path", factory) |
16 | 28 | 23 | ||
17 | 29 | Then a second Python process "B" can connect to that socket and build a | 24 | Then a second Python process "B" can connect to that socket and build a |
18 | 30 | "remote" greeter object, i.e. a proxy that forwards method calls to the | 25 | "remote" greeter object, i.e. a proxy that forwards method calls to the |
19 | 31 | real greeter object living in process A:: | 26 | real greeter object living in process A:: |
20 | 32 | 27 | ||
28 | 33 | connector = ClientCreator(reactor, GreeterProtocol) | 28 | factory = MethodCallClientFactory() |
29 | 34 | connected = connector.connectUNIX("/some/socket/path") | 29 | reactor.connectUNIX("/some/socket/path", factory) |
30 | 35 | 30 | ||
31 | 36 | def got_connection(protocol): | 31 | def got_remote(remote_greeter): |
25 | 37 | |||
26 | 38 | remote_greeter = RemoteObject(protocol) | ||
27 | 39 | |||
32 | 40 | deferred = remote_greeter.hello("Ted") | 32 | deferred = remote_greeter.hello("Ted") |
33 | 41 | deferred.addCallback(lambda result: ... # result == "hi Ted!") | 33 | deferred.addCallback(lambda result: ... # result == "hi Ted!") |
34 | 42 | 34 | ||
36 | 43 | connected.addCallback(got_connection) | 35 | factory.getRemoteObject().addCallback(got_remote) |
37 | 44 | 36 | ||
38 | 45 | Note that when invoking a method via the remote proxy, the parameters | 37 | Note that when invoking a method via the remote proxy, the parameters |
39 | 46 | are required to be serializable with bpickle, so that they can be sent | 38 | are required to be serializable with bpickle, so that they can be sent |
40 | @@ -111,14 +103,6 @@ | |||
41 | 111 | errors = {MethodCallError: "METHOD_CALL_ERROR"} | 103 | errors = {MethodCallError: "METHOD_CALL_ERROR"} |
42 | 112 | 104 | ||
43 | 113 | 105 | ||
44 | 114 | class MethodCallServerProtocol(AMP): | ||
45 | 115 | """XXX Placeholder""" | ||
46 | 116 | |||
47 | 117 | |||
48 | 118 | class MethodCallClientProtocol(AMP): | ||
49 | 119 | """XXX Placeholder""" | ||
50 | 120 | |||
51 | 121 | |||
52 | 122 | class MethodCallReceiver(CommandLocator): | 106 | class MethodCallReceiver(CommandLocator): |
53 | 123 | """Expose methods of a local object over AMP. | 107 | """Expose methods of a local object over AMP. |
54 | 124 | 108 | ||
55 | @@ -196,22 +180,20 @@ | |||
56 | 196 | 180 | ||
57 | 197 | 181 | ||
58 | 198 | class MethodCallSender(object): | 182 | class MethodCallSender(object): |
67 | 199 | """Calls methods of a remote object over L{AMP}. | 183 | """Call methods on a remote object over L{AMP} and return the result. |
68 | 200 | 184 | ||
69 | 201 | @note: If the remote method returns a deferred, the associated local | 185 | @param protocol: A connected C{AMP} protocol. |
70 | 202 | deferred returned by L{send_method_call} will result in the same | 186 | @param clock: An object implementing the C{IReactorTime} interface. |
71 | 203 | callback value of the remote deferred. | 187 | |
72 | 204 | @cvar timeout: A timeout for remote methods returning L{Deferred}s, if a | 188 | @ivar timeout: A timeout for remote method class, see L{send_method_call}. |
65 | 205 | response for the deferred is not received within this amount of | ||
66 | 206 | seconds, the remote method call will errback with a L{MethodCallError}. | ||
73 | 207 | """ | 189 | """ |
74 | 208 | timeout = 60 | 190 | timeout = 60 |
76 | 209 | chunk_size = MAX_VALUE_LENGTH | 191 | |
77 | 192 | _chunk_size = MAX_VALUE_LENGTH | ||
78 | 210 | 193 | ||
79 | 211 | def __init__(self, protocol, clock): | 194 | def __init__(self, protocol, clock): |
83 | 212 | self._protocol = protocol | 195 | self.protocol = protocol |
84 | 213 | self._clock = clock | 196 | self.clock = clock |
82 | 214 | self._pending_responses = [] | ||
85 | 215 | self._sequence = 0 | 197 | self._sequence = 0 |
86 | 216 | 198 | ||
87 | 217 | def _create_sequence(self): | 199 | def _create_sequence(self): |
88 | @@ -223,8 +205,8 @@ | |||
89 | 223 | """Send an L{AMP} command that will errback in case of a timeout. | 205 | """Send an L{AMP} command that will errback in case of a timeout. |
90 | 224 | 206 | ||
91 | 225 | @return: A deferred resulting in the command's response (or failure) if | 207 | @return: A deferred resulting in the command's response (or failure) if |
94 | 226 | the peer responds within L{MethodClientProtocol.timeout} seconds, | 208 | the peer responds within C{self.timeout} seconds, or that errbacks |
95 | 227 | or that errbacks with a L{MethodCallError} otherwise. | 209 | with a L{MethodCallError} otherwise. |
96 | 228 | """ | 210 | """ |
97 | 229 | deferred = Deferred() | 211 | deferred = Deferred() |
98 | 230 | 212 | ||
99 | @@ -240,25 +222,32 @@ | |||
100 | 240 | # The peer didn't respond on time, raise an error. | 222 | # The peer didn't respond on time, raise an error. |
101 | 241 | deferred.errback(MethodCallError("timeout")) | 223 | deferred.errback(MethodCallError("timeout")) |
102 | 242 | 224 | ||
104 | 243 | call = self._clock.callLater(self.timeout, handle_timeout) | 225 | call = self.clock.callLater(self.timeout, handle_timeout) |
105 | 244 | 226 | ||
107 | 245 | result = self._protocol.callRemote(command, **kwargs) | 227 | result = self.protocol.callRemote(command, **kwargs) |
108 | 246 | result.addBoth(handle_response) | 228 | result.addBoth(handle_response) |
109 | 247 | return deferred | 229 | return deferred |
110 | 248 | 230 | ||
111 | 249 | def send_method_call(self, method, args=[], kwargs={}): | 231 | def send_method_call(self, method, args=[], kwargs={}): |
112 | 250 | """Send a L{MethodCall} command with the given arguments. | 232 | """Send a L{MethodCall} command with the given arguments. |
113 | 251 | 233 | ||
114 | 234 | If a response from the server is not received within C{self.timeout} | ||
115 | 235 | seconds, the returned deferred will errback with a L{MethodCallError}. | ||
116 | 236 | |||
117 | 252 | @param method: The name of the remote method to invoke. | 237 | @param method: The name of the remote method to invoke. |
118 | 253 | @param args: The positional arguments to pass to the remote method. | 238 | @param args: The positional arguments to pass to the remote method. |
119 | 254 | @param kwargs: The keyword arguments to pass to the remote method. | 239 | @param kwargs: The keyword arguments to pass to the remote method. |
120 | 240 | |||
121 | 241 | @return: A C{Deferred} firing with the return value of the method | ||
122 | 242 | invoked on the remote object. If the remote method itself returns | ||
123 | 243 | a deferred, we fire with the callback value of such deferred. | ||
124 | 255 | """ | 244 | """ |
125 | 256 | arguments = dumps((args, kwargs)) | 245 | arguments = dumps((args, kwargs)) |
126 | 257 | sequence = self._create_sequence() | 246 | sequence = self._create_sequence() |
127 | 258 | 247 | ||
128 | 259 | # Split the given arguments in one or more chunks | 248 | # Split the given arguments in one or more chunks |
131 | 260 | chunks = [arguments[i:i + self.chunk_size] | 249 | chunks = [arguments[i:i + self._chunk_size] |
132 | 261 | for i in xrange(0, len(arguments), self.chunk_size)] | 250 | for i in xrange(0, len(arguments), self._chunk_size)] |
133 | 262 | 251 | ||
134 | 263 | result = Deferred() | 252 | result = Deferred() |
135 | 264 | if len(chunks) > 1: | 253 | if len(chunks) > 1: |
136 | @@ -266,7 +255,7 @@ | |||
137 | 266 | for chunk in chunks[:-1]: | 255 | for chunk in chunks[:-1]: |
138 | 267 | 256 | ||
139 | 268 | def create_send_chunk(sequence, chunk): | 257 | def create_send_chunk(sequence, chunk): |
141 | 269 | send_chunk = lambda x: self._protocol.callRemote( | 258 | send_chunk = lambda x: self.protocol.callRemote( |
142 | 270 | MethodCallChunk, sequence=sequence, chunk=chunk) | 259 | MethodCallChunk, sequence=sequence, chunk=chunk) |
143 | 271 | return send_chunk | 260 | return send_chunk |
144 | 272 | 261 | ||
145 | @@ -278,10 +267,19 @@ | |||
146 | 278 | MethodCall, sequence=sequence, method=method, arguments=chunk) | 267 | MethodCall, sequence=sequence, method=method, arguments=chunk) |
147 | 279 | 268 | ||
148 | 280 | result.addCallback(send_last_chunk) | 269 | result.addCallback(send_last_chunk) |
149 | 270 | result.addCallback(lambda response: response["result"]) | ||
150 | 281 | result.callback(None) | 271 | result.callback(None) |
151 | 282 | return result | 272 | return result |
152 | 283 | 273 | ||
153 | 284 | 274 | ||
154 | 275 | class MethodCallServerProtocol(AMP): | ||
155 | 276 | """XXX Placeholder""" | ||
156 | 277 | |||
157 | 278 | |||
158 | 279 | class MethodCallClientProtocol(AMP): | ||
159 | 280 | """XXX Placeholder""" | ||
160 | 281 | |||
161 | 282 | |||
162 | 285 | class MethodCallProtocol(MethodCallServerProtocol, MethodCallClientProtocol): | 283 | class MethodCallProtocol(MethodCallServerProtocol, MethodCallClientProtocol): |
163 | 286 | """Can be used both for sending and receiving L{MethodCall}s.""" | 284 | """Can be used both for sending and receiving L{MethodCall}s.""" |
164 | 287 | 285 | ||
165 | @@ -410,22 +408,21 @@ | |||
166 | 410 | args=args, | 408 | args=args, |
167 | 411 | kwargs=kwargs) | 409 | kwargs=kwargs) |
168 | 412 | deferred = Deferred() | 410 | deferred = Deferred() |
170 | 413 | result.addCallback(self._handle_response, deferred) | 411 | result.addCallback(self._handle_result, deferred) |
171 | 414 | result.addErrback(self._handle_failure, method, args, kwargs, | 412 | result.addErrback(self._handle_failure, method, args, kwargs, |
172 | 415 | deferred) | 413 | deferred) |
173 | 416 | return deferred | 414 | return deferred |
174 | 417 | 415 | ||
175 | 418 | return send_method_call | 416 | return send_method_call |
176 | 419 | 417 | ||
179 | 420 | def _handle_response(self, response, deferred, call=None): | 418 | def _handle_result(self, result, deferred, call=None): |
180 | 421 | """Handles a successful L{MethodCall} response. | 419 | """Handles a successful C{send_method_call} result. |
181 | 422 | 420 | ||
182 | 423 | @param response: The L{MethodCall} response. | 421 | @param response: The L{MethodCall} response. |
183 | 424 | @param deferred: The deferred that was returned to the caller. | 422 | @param deferred: The deferred that was returned to the caller. |
184 | 425 | @param call: If not C{None}, the scheduled timeout call associated with | 423 | @param call: If not C{None}, the scheduled timeout call associated with |
185 | 426 | the given deferred. | 424 | the given deferred. |
186 | 427 | """ | 425 | """ |
187 | 428 | result = response["result"] | ||
188 | 429 | if call is not None: | 426 | if call is not None: |
189 | 430 | call.cancel() # This is a successful retry, cancel the timeout. | 427 | call.cancel() # This is a successful retry, cancel the timeout. |
190 | 431 | deferred.callback(result) | 428 | deferred.callback(result) |
191 | @@ -478,7 +475,7 @@ | |||
192 | 478 | 475 | ||
193 | 479 | @param protocol: The newly connected protocol instance. | 476 | @param protocol: The newly connected protocol instance. |
194 | 480 | """ | 477 | """ |
196 | 481 | self._sender._protocol = protocol | 478 | self._sender.protocol = protocol |
197 | 482 | if self._retry_on_reconnect: | 479 | if self._retry_on_reconnect: |
198 | 483 | self._retry() | 480 | self._retry() |
199 | 484 | 481 | ||
200 | @@ -495,7 +492,7 @@ | |||
201 | 495 | while requests: | 492 | while requests: |
202 | 496 | deferred, (method, args, kwargs, call) = requests.popitem() | 493 | deferred, (method, args, kwargs, call) = requests.popitem() |
203 | 497 | result = self._sender.send_method_call(method, args, kwargs) | 494 | result = self._sender.send_method_call(method, args, kwargs) |
205 | 498 | result.addCallback(self._handle_response, | 495 | result.addCallback(self._handle_result, |
206 | 499 | deferred=deferred, call=call) | 496 | deferred=deferred, call=call) |
207 | 500 | result.addErrback(self._handle_failure, method, args, kwargs, | 497 | result.addErrback(self._handle_failure, method, args, kwargs, |
208 | 501 | deferred=deferred, call=call) | 498 | deferred=deferred, call=call) |
209 | @@ -564,6 +561,6 @@ | |||
210 | 564 | if self._factory: | 561 | if self._factory: |
211 | 565 | self._factory.stopTrying() | 562 | self._factory.stopTrying() |
212 | 566 | if self._remote: | 563 | if self._remote: |
215 | 567 | if self._remote._sender._protocol.transport: | 564 | if self._remote._sender.protocol.transport: |
216 | 568 | self._remote._sender._protocol.transport.loseConnection() | 565 | self._remote._sender.protocol.transport.loseConnection() |
217 | 569 | self._remote = None | 566 | self._remote = None |
218 | 570 | 567 | ||
219 | === modified file 'landscape/lib/tests/test_amp.py' | |||
220 | --- landscape/lib/tests/test_amp.py 2013-04-15 11:00:01 +0000 | |||
221 | +++ landscape/lib/tests/test_amp.py 2013-04-19 11:37:27 +0000 | |||
222 | @@ -160,6 +160,19 @@ | |||
223 | 160 | factory = WordsFactory | 160 | factory = WordsFactory |
224 | 161 | 161 | ||
225 | 162 | 162 | ||
226 | 163 | METHODS = ["empty", | ||
227 | 164 | "motd", | ||
228 | 165 | "capitalize", | ||
229 | 166 | "is_short", | ||
230 | 167 | "concatenate", | ||
231 | 168 | "lower_case", | ||
232 | 169 | "multiply_alphabetically", | ||
233 | 170 | "translate", | ||
234 | 171 | "meaning_of_life", | ||
235 | 172 | "guess", | ||
236 | 173 | "google"] | ||
237 | 174 | |||
238 | 175 | |||
239 | 163 | class MethodCallTest(LandscapeTest): | 176 | class MethodCallTest(LandscapeTest): |
240 | 164 | 177 | ||
241 | 165 | def setUp(self): | 178 | def setUp(self): |
242 | @@ -190,7 +203,7 @@ | |||
243 | 190 | args=[], | 203 | args=[], |
244 | 191 | kwargs={}) | 204 | kwargs={}) |
245 | 192 | self.connection.flush() | 205 | self.connection.flush() |
247 | 193 | self.assertEqual({"result": None}, self.successResultOf(deferred)) | 206 | self.assertIs(None, self.successResultOf(deferred)) |
248 | 194 | 207 | ||
249 | 195 | def test_with_return_value(self): | 208 | def test_with_return_value(self): |
250 | 196 | """ | 209 | """ |
251 | @@ -201,8 +214,7 @@ | |||
252 | 201 | args=[], | 214 | args=[], |
253 | 202 | kwargs={}) | 215 | kwargs={}) |
254 | 203 | self.connection.flush() | 216 | self.connection.flush() |
257 | 204 | self.assertEqual({"result": "Words are cool"}, | 217 | self.assertEqual("Words are cool", self.successResultOf(deferred)) |
256 | 205 | self.successResultOf(deferred)) | ||
258 | 206 | 218 | ||
259 | 207 | def test_with_one_argument(self): | 219 | def test_with_one_argument(self): |
260 | 208 | """ | 220 | """ |
261 | @@ -213,7 +225,7 @@ | |||
262 | 213 | args=["john"], | 225 | args=["john"], |
263 | 214 | kwargs={}) | 226 | kwargs={}) |
264 | 215 | self.connection.flush() | 227 | self.connection.flush() |
266 | 216 | self.assertEqual({"result": "John"}, self.successResultOf(deferred)) | 228 | self.assertEqual("John", self.successResultOf(deferred)) |
267 | 217 | 229 | ||
268 | 218 | def test_with_boolean_return_value(self): | 230 | def test_with_boolean_return_value(self): |
269 | 219 | """ | 231 | """ |
270 | @@ -223,7 +235,7 @@ | |||
271 | 223 | args=["hi"], | 235 | args=["hi"], |
272 | 224 | kwargs={}) | 236 | kwargs={}) |
273 | 225 | self.connection.flush() | 237 | self.connection.flush() |
275 | 226 | self.assertEqual({"result": True}, self.successResultOf(deferred)) | 238 | self.assertTrue(self.successResultOf(deferred)) |
276 | 227 | 239 | ||
277 | 228 | def test_with_many_arguments(self): | 240 | def test_with_many_arguments(self): |
278 | 229 | """ | 241 | """ |
279 | @@ -233,7 +245,7 @@ | |||
280 | 233 | args=["We ", "rock"], | 245 | args=["We ", "rock"], |
281 | 234 | kwargs={}) | 246 | kwargs={}) |
282 | 235 | self.connection.flush() | 247 | self.connection.flush() |
284 | 236 | self.assertEqual({"result": "We rock"}, self.successResultOf(deferred)) | 248 | self.assertEqual("We rock", self.successResultOf(deferred)) |
285 | 237 | 249 | ||
286 | 238 | def test_with_default_arguments(self): | 250 | def test_with_default_arguments(self): |
287 | 239 | """ | 251 | """ |
288 | @@ -244,7 +256,7 @@ | |||
289 | 244 | args=["OHH"], | 256 | args=["OHH"], |
290 | 245 | kwargs={}) | 257 | kwargs={}) |
291 | 246 | self.connection.flush() | 258 | self.connection.flush() |
293 | 247 | self.assertEqual({"result": "ohh"}, self.successResultOf(deferred)) | 259 | self.assertEqual("ohh", self.successResultOf(deferred)) |
294 | 248 | 260 | ||
295 | 249 | def test_with_overriden_default_arguments(self): | 261 | def test_with_overriden_default_arguments(self): |
296 | 250 | """ | 262 | """ |
297 | @@ -256,7 +268,7 @@ | |||
298 | 256 | args=["OHH"], | 268 | args=["OHH"], |
299 | 257 | kwargs={"index": 2}) | 269 | kwargs={"index": 2}) |
300 | 258 | self.connection.flush() | 270 | self.connection.flush() |
302 | 259 | self.assertEqual({"result": "OHh"}, self.successResultOf(deferred)) | 271 | self.assertEqual("OHh", self.successResultOf(deferred)) |
303 | 260 | 272 | ||
304 | 261 | def test_with_dictionary_arguments(self): | 273 | def test_with_dictionary_arguments(self): |
305 | 262 | """ | 274 | """ |
306 | @@ -267,8 +279,7 @@ | |||
307 | 267 | args=[{"foo": 2, "bar": 3}], | 279 | args=[{"foo": 2, "bar": 3}], |
308 | 268 | kwargs={}) | 280 | kwargs={}) |
309 | 269 | self.connection.flush() | 281 | self.connection.flush() |
312 | 270 | self.assertEqual({"result": "barbarbarfoofoo"}, | 282 | self.assertEqual("barbarbarfoofoo", self.successResultOf(deferred)) |
311 | 271 | self.successResultOf(deferred)) | ||
313 | 272 | 283 | ||
314 | 273 | def test_with_non_serializable_return_value(self): | 284 | def test_with_non_serializable_return_value(self): |
315 | 274 | """ | 285 | """ |
316 | @@ -290,7 +301,7 @@ | |||
317 | 290 | args=["!" * 65535], | 301 | args=["!" * 65535], |
318 | 291 | kwargs={}) | 302 | kwargs={}) |
319 | 292 | self.connection.flush() | 303 | self.connection.flush() |
321 | 293 | self.assertEqual({"result": False}, self.successResultOf(deferred)) | 304 | self.assertFalse(self.successResultOf(deferred)) |
322 | 294 | 305 | ||
323 | 295 | def test_with_long_argument_multiple_calls(self): | 306 | def test_with_long_argument_multiple_calls(self): |
324 | 296 | """ | 307 | """ |
325 | @@ -305,8 +316,8 @@ | |||
326 | 305 | kwargs={}) | 316 | kwargs={}) |
327 | 306 | 317 | ||
328 | 307 | self.connection.flush() | 318 | self.connection.flush() |
331 | 308 | self.assertEqual({"result": False}, self.successResultOf(deferred1)) | 319 | self.assertFalse(self.successResultOf(deferred1)) |
332 | 309 | self.assertEqual({"result": False}, self.successResultOf(deferred2)) | 320 | self.assertFalse(self.successResultOf(deferred2)) |
333 | 310 | 321 | ||
334 | 311 | def test_translate(self): | 322 | def test_translate(self): |
335 | 312 | """ | 323 | """ |
336 | @@ -339,14 +350,14 @@ | |||
337 | 339 | return deferred | 350 | return deferred |
338 | 340 | 351 | ||
339 | 341 | sender.send_method_call = synchronous_send_method_call | 352 | sender.send_method_call = synchronous_send_method_call |
341 | 342 | self.words = RemoteObject(sender) | 353 | self.remote = RemoteObject(sender) |
342 | 343 | 354 | ||
343 | 344 | def test_method_call_sender_with_forbidden_method(self): | 355 | def test_method_call_sender_with_forbidden_method(self): |
344 | 345 | """ | 356 | """ |
345 | 346 | A L{RemoteObject} can send L{MethodCall}s without arguments and withj | 357 | A L{RemoteObject} can send L{MethodCall}s without arguments and withj |
346 | 347 | an empty response. | 358 | an empty response. |
347 | 348 | """ | 359 | """ |
349 | 349 | deferred = self.words.secret() | 360 | deferred = self.remote.secret() |
350 | 350 | self.failureResultOf(deferred).trap(MethodCallError) | 361 | self.failureResultOf(deferred).trap(MethodCallError) |
351 | 351 | 362 | ||
352 | 352 | def test_with_no_arguments(self): | 363 | def test_with_no_arguments(self): |
353 | @@ -354,7 +365,7 @@ | |||
354 | 354 | A L{RemoteObject} can send L{MethodCall}s without arguments and withj | 365 | A L{RemoteObject} can send L{MethodCall}s without arguments and withj |
355 | 355 | an empty response. | 366 | an empty response. |
356 | 356 | """ | 367 | """ |
358 | 357 | deferred = self.words.empty() | 368 | deferred = self.remote.empty() |
359 | 358 | self.assertIs(None, self.successResultOf(deferred)) | 369 | self.assertIs(None, self.successResultOf(deferred)) |
360 | 359 | 370 | ||
361 | 360 | def test_with_return_value(self): | 371 | def test_with_return_value(self): |
362 | @@ -362,7 +373,7 @@ | |||
363 | 362 | A L{RemoteObject} can send L{MethodCall}s without arguments and get | 373 | A L{RemoteObject} can send L{MethodCall}s without arguments and get |
364 | 363 | back the value of the commands's response. | 374 | back the value of the commands's response. |
365 | 364 | """ | 375 | """ |
367 | 365 | deferred = self.words.motd() | 376 | deferred = self.remote.motd() |
368 | 366 | self.assertEqual("Words are cool", self.successResultOf(deferred)) | 377 | self.assertEqual("Words are cool", self.successResultOf(deferred)) |
369 | 367 | 378 | ||
370 | 368 | def test_with_one_argument(self): | 379 | def test_with_one_argument(self): |
371 | @@ -370,27 +381,27 @@ | |||
372 | 370 | A L{RemoteObject} can send L{MethodCall}s with one argument and get | 381 | A L{RemoteObject} can send L{MethodCall}s with one argument and get |
373 | 371 | the response value. | 382 | the response value. |
374 | 372 | """ | 383 | """ |
376 | 373 | deferred = self.words.capitalize("john") | 384 | deferred = self.remote.capitalize("john") |
377 | 374 | self.assertEqual("John", self.successResultOf(deferred)) | 385 | self.assertEqual("John", self.successResultOf(deferred)) |
378 | 375 | 386 | ||
379 | 376 | def test_with_one_keyword_argument(self): | 387 | def test_with_one_keyword_argument(self): |
380 | 377 | """ | 388 | """ |
381 | 378 | A L{RemoteObject} can send L{MethodCall}s with a named argument. | 389 | A L{RemoteObject} can send L{MethodCall}s with a named argument. |
382 | 379 | """ | 390 | """ |
384 | 380 | deferred = self.words.capitalize(word="john") | 391 | deferred = self.remote.capitalize(word="john") |
385 | 381 | self.assertEqual("John", self.successResultOf(deferred)) | 392 | self.assertEqual("John", self.successResultOf(deferred)) |
386 | 382 | 393 | ||
387 | 383 | def test_with_boolean_return_value(self): | 394 | def test_with_boolean_return_value(self): |
388 | 384 | """ | 395 | """ |
389 | 385 | The return value of a L{MethodCall} argument can be a boolean. | 396 | The return value of a L{MethodCall} argument can be a boolean. |
390 | 386 | """ | 397 | """ |
392 | 387 | return self.assertSuccess(self.words.is_short("hi"), True) | 398 | return self.assertSuccess(self.remote.is_short("hi"), True) |
393 | 388 | 399 | ||
394 | 389 | def test_with_many_arguments(self): | 400 | def test_with_many_arguments(self): |
395 | 390 | """ | 401 | """ |
396 | 391 | A L{RemoteObject} can send L{MethodCall}s with more than one argument. | 402 | A L{RemoteObject} can send L{MethodCall}s with more than one argument. |
397 | 392 | """ | 403 | """ |
399 | 393 | deferred = self.words.concatenate("You ", "rock") | 404 | deferred = self.remote.concatenate("You ", "rock") |
400 | 394 | self.assertEqual("You rock", self.successResultOf(deferred)) | 405 | self.assertEqual("You rock", self.successResultOf(deferred)) |
401 | 395 | 406 | ||
402 | 396 | def test_with_many_keyword_arguments(self): | 407 | def test_with_many_keyword_arguments(self): |
403 | @@ -398,7 +409,7 @@ | |||
404 | 398 | A L{RemoteObject} can send L{MethodCall}s with several | 409 | A L{RemoteObject} can send L{MethodCall}s with several |
405 | 399 | named arguments. | 410 | named arguments. |
406 | 400 | """ | 411 | """ |
408 | 401 | deferred = self.words.concatenate(word2="rock", word1="You ") | 412 | deferred = self.remote.concatenate(word2="rock", word1="You ") |
409 | 402 | self.assertEqual("You rock", self.successResultOf(deferred)) | 413 | self.assertEqual("You rock", self.successResultOf(deferred)) |
410 | 403 | 414 | ||
411 | 404 | def test_with_default_arguments(self): | 415 | def test_with_default_arguments(self): |
412 | @@ -406,7 +417,7 @@ | |||
413 | 406 | A L{RemoteObject} can send a L{MethodCall} having an argument with | 417 | A L{RemoteObject} can send a L{MethodCall} having an argument with |
414 | 407 | a default value. | 418 | a default value. |
415 | 408 | """ | 419 | """ |
417 | 409 | deferred = self.words.lower_case("OHH") | 420 | deferred = self.remote.lower_case("OHH") |
418 | 410 | self.assertEqual("ohh", self.successResultOf(deferred)) | 421 | self.assertEqual("ohh", self.successResultOf(deferred)) |
419 | 411 | 422 | ||
420 | 412 | def test_with_overriden_default_arguments(self): | 423 | def test_with_overriden_default_arguments(self): |
421 | @@ -414,7 +425,7 @@ | |||
422 | 414 | A L{RemoteObject} can send L{MethodCall}s overriding the default | 425 | A L{RemoteObject} can send L{MethodCall}s overriding the default |
423 | 415 | value of an argument. | 426 | value of an argument. |
424 | 416 | """ | 427 | """ |
426 | 417 | deferred = self.words.lower_case("OHH", 2) | 428 | deferred = self.remote.lower_case("OHH", 2) |
427 | 418 | self.assertEqual("OHh", self.successResultOf(deferred)) | 429 | self.assertEqual("OHh", self.successResultOf(deferred)) |
428 | 419 | 430 | ||
429 | 420 | def test_with_dictionary_arguments(self): | 431 | def test_with_dictionary_arguments(self): |
430 | @@ -422,7 +433,7 @@ | |||
431 | 422 | A L{RemoteObject} can send a L{MethodCall}s for methods requiring | 433 | A L{RemoteObject} can send a L{MethodCall}s for methods requiring |
432 | 423 | a dictionary arguments. | 434 | a dictionary arguments. |
433 | 424 | """ | 435 | """ |
435 | 425 | deferred = self.words.multiply_alphabetically({"foo": 2, "bar": 3}) | 436 | deferred = self.remote.multiply_alphabetically({"foo": 2, "bar": 3}) |
436 | 426 | self.assertEqual("barbarbarfoofoo", self.successResultOf(deferred)) | 437 | self.assertEqual("barbarbarfoofoo", self.successResultOf(deferred)) |
437 | 427 | 438 | ||
438 | 428 | def test_with_generic_args_and_kwargs(self): | 439 | def test_with_generic_args_and_kwargs(self): |
439 | @@ -430,7 +441,7 @@ | |||
440 | 430 | A L{RemoteObject} behaves well with L{MethodCall}s for methods | 441 | A L{RemoteObject} behaves well with L{MethodCall}s for methods |
441 | 431 | having generic C{*args} and C{**kwargs} arguments. | 442 | having generic C{*args} and C{**kwargs} arguments. |
442 | 432 | """ | 443 | """ |
444 | 433 | deferred = self.words.guess("word", "cool", value=4) | 444 | deferred = self.remote.guess("word", "cool", value=4) |
445 | 434 | self.assertEqual("Guessed!", self.successResultOf(deferred)) | 445 | self.assertEqual("Guessed!", self.successResultOf(deferred)) |
446 | 435 | 446 | ||
447 | 436 | def test_with_successful_deferred(self): | 447 | def test_with_successful_deferred(self): |
448 | @@ -439,7 +450,7 @@ | |||
449 | 439 | transparently. | 450 | transparently. |
450 | 440 | """ | 451 | """ |
451 | 441 | result = [] | 452 | result = [] |
453 | 442 | deferred = self.words.google("Landscape") | 453 | deferred = self.remote.google("Landscape") |
454 | 443 | deferred.addCallback(result.append) | 454 | deferred.addCallback(result.append) |
455 | 444 | 455 | ||
456 | 445 | # At this point the receiver is waiting for method to complete, so | 456 | # At this point the receiver is waiting for method to complete, so |
457 | @@ -458,7 +469,7 @@ | |||
458 | 458 | L{MethodCallError} is raised. | 469 | L{MethodCallError} is raised. |
459 | 459 | """ | 470 | """ |
460 | 460 | result = [] | 471 | result = [] |
462 | 461 | deferred = self.words.google("Weird stuff") | 472 | deferred = self.remote.google("Weird stuff") |
463 | 462 | deferred.addErrback(result.append) | 473 | deferred.addErrback(result.append) |
464 | 463 | 474 | ||
465 | 464 | # At this point the receiver is waiting for method to complete, so | 475 | # At this point the receiver is waiting for method to complete, so |
466 | @@ -476,14 +487,14 @@ | |||
467 | 476 | """ | 487 | """ |
468 | 477 | The target object method can return an already fired L{Deferred}. | 488 | The target object method can return an already fired L{Deferred}. |
469 | 478 | """ | 489 | """ |
471 | 479 | deferred = self.words.google("Easy query") | 490 | deferred = self.remote.google("Easy query") |
472 | 480 | self.assertEqual("Done!", self.successResultOf(deferred)) | 491 | self.assertEqual("Done!", self.successResultOf(deferred)) |
473 | 481 | 492 | ||
474 | 482 | def test_with_already_errback_deferred(self): | 493 | def test_with_already_errback_deferred(self): |
475 | 483 | """ | 494 | """ |
476 | 484 | If the target object method can return an already failed L{Deferred}. | 495 | If the target object method can return an already failed L{Deferred}. |
477 | 485 | """ | 496 | """ |
479 | 486 | deferred = self.words.google("Censored") | 497 | deferred = self.remote.google("Censored") |
480 | 487 | self.failureResultOf(deferred).trap(MethodCallError) | 498 | self.failureResultOf(deferred).trap(MethodCallError) |
481 | 488 | 499 | ||
482 | 489 | def test_with_deferred_timeout(self): | 500 | def test_with_deferred_timeout(self): |
483 | @@ -492,7 +503,7 @@ | |||
484 | 492 | the given timeout, the method call fails. | 503 | the given timeout, the method call fails. |
485 | 493 | """ | 504 | """ |
486 | 494 | result = [] | 505 | result = [] |
488 | 495 | deferred = self.words.google("Long query") | 506 | deferred = self.remote.google("Long query") |
489 | 496 | deferred.addErrback(result.append) | 507 | deferred.addErrback(result.append) |
490 | 497 | 508 | ||
491 | 498 | self.clock.advance(60.0) | 509 | self.clock.advance(60.0) |
492 | @@ -506,7 +517,7 @@ | |||
493 | 506 | already timeout, that response is ignored. | 517 | already timeout, that response is ignored. |
494 | 507 | """ | 518 | """ |
495 | 508 | result = [] | 519 | result = [] |
497 | 509 | deferred = self.words.google("Slowish query") | 520 | deferred = self.remote.google("Slowish query") |
498 | 510 | deferred.addErrback(result.append) | 521 | deferred.addErrback(result.append) |
499 | 511 | 522 | ||
500 | 512 | self.clock.advance(120.0) | 523 | self.clock.advance(120.0) |
501 | @@ -520,7 +531,7 @@ | |||
502 | 520 | def setUp(self): | 531 | def setUp(self): |
503 | 521 | super(MethodCallFactoryTest, self).setUp() | 532 | super(MethodCallFactoryTest, self).setUp() |
504 | 522 | self.clock = Clock() | 533 | self.clock = Clock() |
506 | 523 | self.factory = WordsFactory(reactor=self.clock) | 534 | self.factory = MethodCallFactory(reactor=self.clock) |
507 | 524 | 535 | ||
508 | 525 | def test_max_delay(self): | 536 | def test_max_delay(self): |
509 | 526 | """ | 537 | """ |
510 | @@ -669,7 +680,7 @@ | |||
511 | 669 | If the connection is lost, the L{RemoteObject} created by the creator | 680 | If the connection is lost, the L{RemoteObject} created by the creator |
512 | 670 | will transparently handle the reconnection. | 681 | will transparently handle the reconnection. |
513 | 671 | """ | 682 | """ |
515 | 672 | self.words._sender._protocol.transport.loseConnection() | 683 | self.words._sender.protocol.transport.loseConnection() |
516 | 673 | self.port.stopListening() | 684 | self.port.stopListening() |
517 | 674 | 685 | ||
518 | 675 | def restart_listening(): | 686 | def restart_listening(): |
519 | @@ -698,7 +709,7 @@ | |||
520 | 698 | will transparently retry to perform the L{MethodCall} requests that | 709 | will transparently retry to perform the L{MethodCall} requests that |
521 | 699 | failed due to the broken connection. | 710 | failed due to the broken connection. |
522 | 700 | """ | 711 | """ |
524 | 701 | self.words._sender._protocol.transport.loseConnection() | 712 | self.words._sender.protocol.transport.loseConnection() |
525 | 702 | self.port.stopListening() | 713 | self.port.stopListening() |
526 | 703 | 714 | ||
527 | 704 | def restart_listening(): | 715 | def restart_listening(): |
528 | @@ -713,7 +724,7 @@ | |||
529 | 713 | the L{RemoteObject} will properly propagate the error to the original | 724 | the L{RemoteObject} will properly propagate the error to the original |
530 | 714 | caller. | 725 | caller. |
531 | 715 | """ | 726 | """ |
533 | 716 | self.words._sender._protocol.transport.loseConnection() | 727 | self.words._sender.protocol.transport.loseConnection() |
534 | 717 | self.port.stopListening() | 728 | self.port.stopListening() |
535 | 718 | 729 | ||
536 | 719 | def restart_listening(): | 730 | def restart_listening(): |
537 | @@ -733,12 +744,12 @@ | |||
538 | 733 | connection is ready. If for whatever reason the connection drops | 744 | connection is ready. If for whatever reason the connection drops |
539 | 734 | again very quickly, the C{_retry} method will behave as expected. | 745 | again very quickly, the C{_retry} method will behave as expected. |
540 | 735 | """ | 746 | """ |
542 | 736 | self.words._sender._protocol.transport.loseConnection() | 747 | self.words._sender.protocol.transport.loseConnection() |
543 | 737 | self.port.stopListening() | 748 | self.port.stopListening() |
544 | 738 | 749 | ||
545 | 739 | def handle_reconnect(protocol): | 750 | def handle_reconnect(protocol): |
546 | 740 | # In this precise moment we have a newly connected protocol | 751 | # In this precise moment we have a newly connected protocol |
548 | 741 | self.words._sender._protocol = protocol | 752 | self.words._sender.protocol = protocol |
549 | 742 | 753 | ||
550 | 743 | # Pretend that the connection is lost again very quickly | 754 | # Pretend that the connection is lost again very quickly |
551 | 744 | protocol.transport.loseConnection() | 755 | protocol.transport.loseConnection() |
552 | @@ -773,7 +784,7 @@ | |||
553 | 773 | will be all eventually completed when the connection gets established | 784 | will be all eventually completed when the connection gets established |
554 | 774 | again. | 785 | again. |
555 | 775 | """ | 786 | """ |
557 | 776 | self.words._sender._protocol.transport.loseConnection() | 787 | self.words._sender.protocol.transport.loseConnection() |
558 | 777 | self.port.stopListening() | 788 | self.port.stopListening() |
559 | 778 | 789 | ||
560 | 779 | def restart_listening(): | 790 | def restart_listening(): |
561 | @@ -804,7 +815,7 @@ | |||
562 | 804 | retry to perform requests which failed because the connection was | 815 | retry to perform requests which failed because the connection was |
563 | 805 | lost, however requests made after a reconnection will still succeed. | 816 | lost, however requests made after a reconnection will still succeed. |
564 | 806 | """ | 817 | """ |
566 | 807 | self.words._sender._protocol.transport.loseConnection() | 818 | self.words._sender.protocol.transport.loseConnection() |
567 | 808 | self.port.stopListening() | 819 | self.port.stopListening() |
568 | 809 | 820 | ||
569 | 810 | def restart_listening(): | 821 | def restart_listening(): |
570 | @@ -829,7 +840,7 @@ | |||
571 | 829 | L{MethodCall}s after that amount of seconds, without retrying them when | 840 | L{MethodCall}s after that amount of seconds, without retrying them when |
572 | 830 | the connection established again. | 841 | the connection established again. |
573 | 831 | """ | 842 | """ |
575 | 832 | self.words._sender._protocol.transport.loseConnection() | 843 | self.words._sender.protocol.transport.loseConnection() |
576 | 833 | self.port.stopListening() | 844 | self.port.stopListening() |
577 | 834 | 845 | ||
578 | 835 | def restart_listening(): | 846 | def restart_listening(): |
579 | 836 | 847 | ||
580 | === modified file 'landscape/tests/test_amp.py' | |||
581 | --- landscape/tests/test_amp.py 2013-04-15 09:03:43 +0000 | |||
582 | +++ landscape/tests/test_amp.py 2013-04-19 11:37:27 +0000 | |||
583 | @@ -118,7 +118,7 @@ | |||
584 | 118 | ports.append(self.reactor.listen_unix(socket, factory)) | 118 | ports.append(self.reactor.listen_unix(socket, factory)) |
585 | 119 | 119 | ||
586 | 120 | def connected(remote): | 120 | def connected(remote): |
588 | 121 | remote._sender._protocol.transport.loseConnection() | 121 | remote._sender.protocol.transport.loseConnection() |
589 | 122 | ports[0].stopListening() | 122 | ports[0].stopListening() |
590 | 123 | self.reactor._reactor.callLater(0.01, listen_again) | 123 | self.reactor._reactor.callLater(0.01, listen_again) |
591 | 124 | 124 | ||
592 | 125 | 125 | ||
593 | === modified file 'landscape/tests/test_configuration.py' | |||
594 | --- landscape/tests/test_configuration.py 2013-03-27 22:58:20 +0000 | |||
595 | +++ landscape/tests/test_configuration.py 2013-04-19 11:37:27 +0000 | |||
596 | @@ -6,6 +6,7 @@ | |||
597 | 6 | 6 | ||
598 | 7 | from twisted.internet.defer import succeed, fail | 7 | from twisted.internet.defer import succeed, fail |
599 | 8 | 8 | ||
600 | 9 | from landscape.lib.amp import MethodCallSender | ||
601 | 9 | from landscape.reactor import TwistedReactor | 10 | from landscape.reactor import TwistedReactor |
602 | 10 | from landscape.lib.fetch import HTTPCodeError, PyCurlError | 11 | from landscape.lib.fetch import HTTPCodeError, PyCurlError |
603 | 11 | from landscape.configuration import ( | 12 | from landscape.configuration import ( |
604 | @@ -19,7 +20,7 @@ | |||
605 | 19 | from landscape.tests.helpers import ( | 20 | from landscape.tests.helpers import ( |
606 | 20 | LandscapeTest, BrokerServiceHelper, EnvironSaverHelper) | 21 | LandscapeTest, BrokerServiceHelper, EnvironSaverHelper) |
607 | 21 | from landscape.tests.mocker import ARGS, ANY, MATCH, CONTAINS, expect | 22 | from landscape.tests.mocker import ARGS, ANY, MATCH, CONTAINS, expect |
609 | 22 | from landscape.broker.amp import RemoteBroker, BrokerClientProtocol | 23 | from landscape.broker.amp import RemoteBroker |
610 | 23 | 24 | ||
611 | 24 | 25 | ||
612 | 25 | class LandscapeConfigurationTest(LandscapeTest): | 26 | class LandscapeConfigurationTest(LandscapeTest): |
613 | @@ -1784,7 +1785,7 @@ | |||
614 | 1784 | reactor_mock = self.mocker.patch(TwistedReactor) | 1785 | reactor_mock = self.mocker.patch(TwistedReactor) |
615 | 1785 | remote_mock = self.mocker.patch(RemoteBroker) | 1786 | remote_mock = self.mocker.patch(RemoteBroker) |
616 | 1786 | 1787 | ||
618 | 1787 | protocol_mock = self.mocker.patch(BrokerClientProtocol) | 1788 | protocol_mock = self.mocker.patch(MethodCallSender) |
619 | 1788 | protocol_mock.timeout | 1789 | protocol_mock.timeout |
620 | 1789 | self.mocker.result(0.1) | 1790 | self.mocker.result(0.1) |
621 | 1790 | self.mocker.count(0, None) | 1791 | self.mocker.count(0, None) |
Nice! +1