Skip to content

Commit

Permalink
Merge 455cdd6 into 5cac1df
Browse files Browse the repository at this point in the history
  • Loading branch information
meejah committed Oct 30, 2018
2 parents 5cac1df + 455cdd6 commit 0671584
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/releases.rst
Expand Up @@ -20,6 +20,7 @@ unreleased
----------

`git master <https://github.com/meejah/txtorcon>`_ *will likely become v19.0.0*
* add `TorControlProtocol.when_disconnected()` Returns a new deferred to each caller.

v18.3.0
-------
Expand Down
32 changes: 32 additions & 0 deletions test/test_torcontrolprotocol.py
Expand Up @@ -215,6 +215,38 @@ def it_was_called(*args):
self.protocol.connectionLost(f)
self.assertTrue(it_was_called.yes)

def test_when_disconnect(self):
"""
see that we get our callback for when_disconnected if the
transport goes away
"""
def it_was_called(arg):
it_was_called.yes = True
return None
it_was_called.yes = False

d = self.protocol.when_disconnected()
d.addCallback(it_was_called)
f = failure.Failure(error.ConnectionDone("It's all over"))
self.protocol.connectionLost(f)
self.assertTrue(it_was_called.yes)

def test_when_disconnect_error(self):
"""
see that we get our errback for when_disconnected if the
transport goes away
"""
def it_was_called(arg):
it_was_called.yes = True
return None
it_was_called.yes = False

d = self.protocol.when_disconnected()
d.addErrback(it_was_called)
f = failure.Failure(RuntimeError("sadness"))
self.protocol.connectionLost(f)
self.assertTrue(it_was_called.yes)

def test_disconnect_errback(self):
"""
see that we get our callback on_disconnect if the transport
Expand Down
19 changes: 18 additions & 1 deletion txtorcon/torcontrolprotocol.py
Expand Up @@ -23,7 +23,7 @@

from txtorcon.interface import ITorControlProtocol
from .spaghetti import FSM, State, Transition
from .util import maybe_coroutine
from .util import maybe_coroutine, SingleObserver


DEFAULT_VALUE = 'DEFAULT'
Expand Down Expand Up @@ -271,6 +271,11 @@ def __init__(self, password_function=None):
there was an error, the errback is called instead.
"""

self._when_disconnected = SingleObserver()
"""
Private. See :func:`.when_disconnected`
"""

self.post_bootstrap = defer.Deferred()
"""
This Deferred is triggered when we're done setting up
Expand Down Expand Up @@ -648,6 +653,13 @@ def queue_command(self, cmd, arg=None):
self._maybe_issue_command()
return d

def when_disconnected(self):
"""
:returns: a Deferred that fires when (if) we disconnect from our
Tor process.
"""
return self._when_disconnected.when_fired()

# the remaining methods are internal API implementations,
# callbacks and state-tracking methods -- you shouldn't have any
# need to call them.
Expand All @@ -672,6 +684,11 @@ def connectionMade(self):
def connectionLost(self, reason):
"Protocol API"
txtorlog.msg('connection terminated: ' + str(reason))
if reason.check(ConnectionDone):
self._when_disconnected.fire(self)
else:
self._when_disconnected.fire(reason)

# ...and this is why we don't do on_disconnect = Deferred() :(
# and instead should have had on_disconnect() method that
# returned a new Deferred to each caller..(we're checking if
Expand Down

0 comments on commit 0671584

Please sign in to comment.