Merge lp:~free.ekanayaka/landscape-client/amp-cleanup into lp:~landscape/landscape-client/trunk

Proposed by Free Ekanayaka
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
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.

- MethodCallSender.send_method_call now returns directly the result of the remote
  method invokation, rather then MethodCall.response low-level dict. Tests have been
  updated accordingly.

- MethodCallSender.protocol is now public, and can be set by calling code.

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.

- MethodCallSender.send_method_call now returns directly the result of the remote
  method invokation, rather then MethodCall.response low-level dict. Tests have been
  updated accordingly.

- MethodCallSender.protocol is now public, and can be set by calling code.

To post a comment you must log in.
Revision history for this message
Alberto Donato (ack) wrote :

Nice! +1

review: Approve
Revision history for this message
Geoff Teale (tealeg) wrote :

Clean as a whistle +1

review: Approve

Preview Diff

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

Subscribers

People subscribed via source and target branches

to all changes: