provide wormhole() as a function, rather than a class constructor

You must always provide a reactor= argument. In the future, omitting the
reactor= argument is how you ask for a blocking Wormhole.
This commit is contained in:
Brian Warner 2016-05-12 16:36:48 -07:00
parent d87aba40e4
commit 104ef44d53
5 changed files with 37 additions and 26 deletions

View File

@ -77,7 +77,7 @@ before being closed.
To make it easier to call `close()`, the blocking Wormhole objects can be To make it easier to call `close()`, the blocking Wormhole objects can be
used as a context manager. Just put your code in the body of a `with used as a context manager. Just put your code in the body of a `with
Wormhole(ARGS) as w:` statement, and `close()` will automatically be called wormhole(ARGS) as w:` statement, and `close()` will automatically be called
when the block exits (either successfully or due to an exception). when the block exits (either successfully or due to an exception).
## Examples ## Examples
@ -85,10 +85,10 @@ when the block exits (either successfully or due to an exception).
The synchronous+blocking flow looks like this: The synchronous+blocking flow looks like this:
```python ```python
from wormhole.blocking.transcribe import Wormhole from wormhole.blocking.transcribe import wormhole
from wormhole.public_relay import RENDEZVOUS_RELAY from wormhole.public_relay import RENDEZVOUS_RELAY
mydata = b"initiator's data" mydata = b"initiator's data"
with Wormhole(u"appid", RENDEZVOUS_RELAY) as i: with wormhole(u"appid", RENDEZVOUS_RELAY) as i:
code = i.get_code() code = i.get_code()
print("Invitation Code: %s" % code) print("Invitation Code: %s" % code)
i.send(mydata) i.send(mydata)
@ -98,11 +98,11 @@ with Wormhole(u"appid", RENDEZVOUS_RELAY) as i:
```python ```python
import sys import sys
from wormhole.blocking.transcribe import Wormhole from wormhole.blocking.transcribe import wormhole
from wormhole.public_relay import RENDEZVOUS_RELAY from wormhole.public_relay import RENDEZVOUS_RELAY
mydata = b"receiver's data" mydata = b"receiver's data"
code = sys.argv[1] code = sys.argv[1]
with Wormhole(u"appid", RENDEZVOUS_RELAY) as r: with wormhole(u"appid", RENDEZVOUS_RELAY) as r:
r.set_code(code) r.set_code(code)
r.send(mydata) r.send(mydata)
theirdata = r.get() theirdata = r.get()
@ -116,9 +116,9 @@ The Twisted-friendly flow looks like this:
```python ```python
from twisted.internet import reactor from twisted.internet import reactor
from wormhole.public_relay import RENDEZVOUS_RELAY from wormhole.public_relay import RENDEZVOUS_RELAY
from wormhole.twisted.transcribe import Wormhole from wormhole.twisted.transcribe import wormhole
outbound_message = b"outbound data" outbound_message = b"outbound data"
w1 = Wormhole(u"appid", RENDEZVOUS_RELAY) w1 = wormhole(u"appid", RENDEZVOUS_RELAY, reactor)
d = w1.get_code() d = w1.get_code()
def _got_code(code): def _got_code(code):
print "Invitation Code:", code print "Invitation Code:", code
@ -136,7 +136,7 @@ reactor.run()
On the other side, you call `set_code()` instead of waiting for `get_code()`: On the other side, you call `set_code()` instead of waiting for `get_code()`:
```python ```python
w2 = Wormhole(u"appid", RENDEZVOUS_RELAY) w2 = wormhole(u"appid", RENDEZVOUS_RELAY, reactor)
w2.set_code(code) w2.set_code(code)
d = w2.send(my_message) d = w2.send(my_message)
... ...
@ -253,9 +253,8 @@ You may not be able to hold the Wormhole object in memory for the whole sync
process: maybe you allow it to wait for several days, but the program will be process: maybe you allow it to wait for several days, but the program will be
restarted during that time. To support this, you can persist the state of the restarted during that time. To support this, you can persist the state of the
object by calling `data = w.serialize()`, which will return a printable object by calling `data = w.serialize()`, which will return a printable
bytestring (the JSON-encoding of a small dictionary). To restore, use the bytestring (the JSON-encoding of a small dictionary). To restore, use `w =
`from_serialized(data)` classmethod (e.g. `w = wormhole_from_serialized(data, reactor)`.
Wormhole.from_serialized(data)`).
There is exactly one point at which you can serialize the wormhole: *after* There is exactly one point at which you can serialize the wormhole: *after*
establishing the invitation code, but before waiting for `get_verifier()` or establishing the invitation code, but before waiting for `get_verifier()` or

View File

@ -3,7 +3,7 @@ import os, sys, json, binascii, six, tempfile, zipfile
from tqdm import tqdm from tqdm import tqdm
from twisted.internet import reactor from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks, returnValue from twisted.internet.defer import inlineCallbacks, returnValue
from ..twisted.transcribe import Wormhole from ..twisted.transcribe import wormhole
from ..twisted.transit import TransitReceiver from ..twisted.transit import TransitReceiver
from ..errors import TransferError from ..errors import TransferError
@ -45,9 +45,8 @@ class TwistedReceiver:
# can lazy-provide an endpoint, and overlap the startup process # can lazy-provide an endpoint, and overlap the startup process
# with the user handing off the wormhole code # with the user handing off the wormhole code
yield tor_manager.start() yield tor_manager.start()
w = Wormhole(APPID, self.args.relay_url, tor_manager, w = wormhole(APPID, self.args.relay_url, self._reactor,
timing=self.args.timing, tor_manager, timing=self.args.timing)
reactor=self._reactor)
# I wanted to do this instead: # I wanted to do this instead:
# #
# try: # try:

View File

@ -5,7 +5,7 @@ from twisted.protocols import basic
from twisted.internet import reactor from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks, returnValue from twisted.internet.defer import inlineCallbacks, returnValue
from ..errors import TransferError from ..errors import TransferError
from ..twisted.transcribe import Wormhole from ..twisted.transcribe import wormhole
from ..twisted.transit import TransitSender from ..twisted.transit import TransitSender
APPID = u"lothar.com/wormhole/text-or-file-xfer" APPID = u"lothar.com/wormhole/text-or-file-xfer"
@ -49,8 +49,8 @@ def send(args, reactor=reactor):
# user handing off the wormhole code # user handing off the wormhole code
yield tor_manager.start() yield tor_manager.start()
w = Wormhole(APPID, args.relay_url, tor_manager, timing=args.timing, w = wormhole(APPID, args.relay_url, reactor, tor_manager,
reactor=reactor) timing=args.timing)
d = _send(reactor, w, args, phase1, fd_to_send, tor_manager) d = _send(reactor, w, args, phase1, fd_to_send, tor_manager)
d.addBoth(w.close) d.addBoth(w.close)

View File

@ -1,12 +1,17 @@
from __future__ import print_function from __future__ import print_function
import json import json
from twisted.trial import unittest from twisted.trial import unittest
from twisted.internet import reactor
from twisted.internet.defer import gatherResults, inlineCallbacks from twisted.internet.defer import gatherResults, inlineCallbacks
from ..twisted.transcribe import Wormhole, UsageError, WrongPasswordError from ..twisted.transcribe import (wormhole, wormhole_from_serialized,
UsageError, WrongPasswordError)
from .common import ServerBase from .common import ServerBase
APPID = u"appid" APPID = u"appid"
def Wormhole(appid, relayurl):
return wormhole(appid, relayurl, reactor)
class Basic(ServerBase, unittest.TestCase): class Basic(ServerBase, unittest.TestCase):
def doBoth(self, d1, d2): def doBoth(self, d1, d2):
@ -220,7 +225,7 @@ class Basic(ServerBase, unittest.TestCase):
unpacked = json.loads(s) # this is supposed to be JSON unpacked = json.loads(s) # this is supposed to be JSON
self.assertEqual(type(unpacked), dict) self.assertEqual(type(unpacked), dict)
self.new_w1 = Wormhole.from_serialized(s) self.new_w1 = wormhole_from_serialized(s, reactor)
yield self.doBoth(self.new_w1.send(b"data1"), w2.send(b"data2")) yield self.doBoth(self.new_w1.send(b"data1"), w2.send(b"data2"))
dl = yield self.doBoth(self.new_w1.get(), w2.get()) dl = yield self.doBoth(self.new_w1.get(), w2.get())
(dataX, dataY) = dl (dataX, dataY) = dl

View File

@ -2,7 +2,7 @@ from __future__ import print_function
import os, sys, json, re, unicodedata import os, sys, json, re, unicodedata
from six.moves.urllib_parse import urlparse from six.moves.urllib_parse import urlparse
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from twisted.internet import reactor, defer, endpoints, error from twisted.internet import defer, endpoints, error
from twisted.internet.threads import deferToThread, blockingCallFromThread from twisted.internet.threads import deferToThread, blockingCallFromThread
from twisted.internet.defer import inlineCallbacks, returnValue from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.python import log from twisted.python import log
@ -53,13 +53,13 @@ class WSFactory(websocket.WebSocketClientFactory):
proto.wormhole_open = False proto.wormhole_open = False
return proto return proto
class Wormhole: class _Wormhole:
motd_displayed = False motd_displayed = False
version_warning_displayed = False version_warning_displayed = False
_send_confirm = True _send_confirm = True
def __init__(self, appid, relay_url, tor_manager=None, timing=None, def __init__(self, appid, relay_url, reactor,
reactor=reactor): tor_manager=None, timing=None):
if not isinstance(appid, type(u"")): raise TypeError(type(appid)) if not isinstance(appid, type(u"")): raise TypeError(type(appid))
if not isinstance(relay_url, type(u"")): if not isinstance(relay_url, type(u"")):
raise TypeError(type(relay_url)) raise TypeError(type(relay_url))
@ -351,9 +351,9 @@ class Wormhole:
# entry point 3: resume a previously-serialized session # entry point 3: resume a previously-serialized session
@classmethod @classmethod
def from_serialized(klass, data): def from_serialized(klass, data, reactor):
d = json.loads(data) d = json.loads(data)
self = klass(d["appid"], d["relay_url"]) self = klass(d["appid"], d["relay_url"], reactor)
self._side = d["side"] self._side = d["side"]
self._channelid = d["channelid"] self._channelid = d["channelid"]
self._set_code(d["code"]) self._set_code(d["code"])
@ -556,3 +556,11 @@ class Wormhole:
def _ws_handle_deallocated(self, msg): def _ws_handle_deallocated(self, msg):
self._deallocated_status = msg["status"] self._deallocated_status = msg["status"]
self._wakeup() self._wakeup()
def wormhole(appid, relay_url, reactor, tor_manager=None, timing=None):
w = _Wormhole(appid, relay_url, reactor, tor_manager, timing)
return w
def wormhole_from_serialized(data, reactor):
w = _Wormhole.from_serialized(data, reactor)
return w