rewrite CLI tools to use argparse, remove Twisted dependency
We used to use twisted.python.usage.Options, hence we depended upon Twisted. Now we depend upon "argparse" instead, which is in the py2.7 stdlib (and on pypi for 2.6). This package will still (eventually) provide Twisted support, but applications which need it will already express a dependency on twisted themselves, so by removing the dependency here, we make life easier for applications that don't use it.
This commit is contained in:
parent
9e7d807171
commit
8e456dea5e
2
setup.py
2
setup.py
|
@ -23,7 +23,7 @@ setup(name="wormhole-sync",
|
|||
"wormhole.test", "wormhole.util"],
|
||||
entry_points={"console_scripts":
|
||||
["wormhole = wormhole.scripts.runner:entry"]},
|
||||
install_requires=["spake2", "pynacl", "requests", "twisted"],
|
||||
install_requires=["spake2", "pynacl", "requests", "argparse"],
|
||||
test_suite="wormhole.test",
|
||||
cmdclass=commands,
|
||||
)
|
||||
|
|
|
@ -6,9 +6,9 @@ from .progress import start_progress, update_progress, finish_progress
|
|||
|
||||
APPID = "lothar.com/wormhole/file-xfer"
|
||||
|
||||
def receive_file(so):
|
||||
def receive_file(args):
|
||||
# we're receiving
|
||||
transit_receiver = TransitReceiver(transit_relay=so.parent["transit-helper"])
|
||||
transit_receiver = TransitReceiver(transit_relay=args.transit_helper)
|
||||
|
||||
mydata = json.dumps({
|
||||
"transit": {
|
||||
|
@ -16,8 +16,8 @@ def receive_file(so):
|
|||
"relay_connection_hints": transit_receiver.get_relay_hints(),
|
||||
},
|
||||
}).encode("utf-8")
|
||||
r = Receiver(APPID, mydata, so.parent["relay-url"])
|
||||
code = so["code"]
|
||||
r = Receiver(APPID, mydata, args.relay_url)
|
||||
code = args.code
|
||||
if not code:
|
||||
code = r.input_code("Enter receive-file wormhole code: ")
|
||||
r.set_code(code)
|
||||
|
@ -44,7 +44,7 @@ def receive_file(so):
|
|||
print("Receiving %d bytes for '%s' (%s).." % (filesize, filename,
|
||||
transit_receiver.describe()))
|
||||
|
||||
target = so["output-file"]
|
||||
target = args.output_file
|
||||
if not target:
|
||||
# allow the sender to specify the filename, but only write to the
|
||||
# current directory, and never overwrite anything
|
||||
|
|
|
@ -4,11 +4,11 @@ from wormhole.blocking.transcribe import Receiver, WrongPasswordError
|
|||
|
||||
APPID = "lothar.com/wormhole/text-xfer"
|
||||
|
||||
def receive_text(so):
|
||||
def receive_text(args):
|
||||
# we're receiving
|
||||
data = json.dumps({"message": "ok"}).encode("utf-8")
|
||||
r = Receiver(APPID, data, so.parent["relay-url"])
|
||||
code = so["code"]
|
||||
r = Receiver(APPID, data, args.relay_url)
|
||||
code = args.code
|
||||
if not code:
|
||||
code = r.input_code("Enter receive-text wormhole code: ")
|
||||
r.set_code(code)
|
||||
|
|
|
@ -6,11 +6,11 @@ from .progress import start_progress, update_progress, finish_progress
|
|||
|
||||
APPID = "lothar.com/wormhole/file-xfer"
|
||||
|
||||
def send_file(so):
|
||||
def send_file(args):
|
||||
# we're sending
|
||||
filename = so["filename"]
|
||||
filename = args.filename
|
||||
assert os.path.isfile(filename)
|
||||
transit_sender = TransitSender(transit_relay=so.parent["transit-helper"])
|
||||
transit_sender = TransitSender(transit_relay=args.transit_helper)
|
||||
|
||||
filesize = os.stat(filename).st_size
|
||||
data = json.dumps({
|
||||
|
@ -24,7 +24,7 @@ def send_file(so):
|
|||
},
|
||||
}).encode("utf-8")
|
||||
|
||||
i = Initiator(APPID, data, so.parent["relay-url"])
|
||||
i = Initiator(APPID, data, args.relay_url)
|
||||
code = i.get_code()
|
||||
print("On the other computer, please run: wormhole receive-file")
|
||||
print("Wormhole code is '%s'" % code)
|
||||
|
|
|
@ -4,12 +4,12 @@ from wormhole.blocking.transcribe import Initiator, WrongPasswordError
|
|||
|
||||
APPID = "lothar.com/wormhole/text-xfer"
|
||||
|
||||
def send_text(so):
|
||||
def send_text(args):
|
||||
# we're sending
|
||||
message = so["text"]
|
||||
message = args.text
|
||||
data = json.dumps({"message": message,
|
||||
}).encode("utf-8")
|
||||
i = Initiator(APPID, data, so.parent["relay-url"])
|
||||
i = Initiator(APPID, data, args.relay_url)
|
||||
code = i.get_code()
|
||||
print("On the other computer, please run: wormhole receive-text")
|
||||
print("Wormhole code is: %s" % code)
|
||||
|
|
|
@ -1,93 +1,69 @@
|
|||
import sys
|
||||
from twisted.python import usage
|
||||
import sys, argparse
|
||||
from textwrap import dedent
|
||||
from .. import public_relay
|
||||
from .. import __version__
|
||||
from . import cmd_send_text, cmd_receive_text, cmd_send_file, cmd_receive_file
|
||||
|
||||
class SendTextOptions(usage.Options):
|
||||
def parseArgs(self, text):
|
||||
self["text"] = text
|
||||
synopsis = "TEXT"
|
||||
parser = argparse.ArgumentParser(
|
||||
usage="wormhole SUBCOMMAND (subcommand-options)",
|
||||
description=dedent("""
|
||||
Create a Magic Wormhole and communicate through it. Wormholes are created
|
||||
by speaking the same magic CODE in two different places at the same time.
|
||||
Wormholes are secure against anyone who doesn't use the same code."""),
|
||||
)
|
||||
parser.add_argument("--version", action="version",
|
||||
version="magic-wormhole "+ __version__)
|
||||
g = parser.add_argument_group("wormhole configuration options")
|
||||
g.add_argument("--relay-url", default=public_relay.RENDEZVOUS_RELAY,
|
||||
metavar="URL", help="rendezvous relay to use")
|
||||
g.add_argument("--transit-helper", default=public_relay.TRANSIT_RELAY,
|
||||
metavar="tcp:HOST:PORT", help="transit relay to use")
|
||||
subparsers = parser.add_subparsers(title="subcommands",
|
||||
dest="subcommand")
|
||||
|
||||
class ReceiveTextOptions(usage.Options):
|
||||
def parseArgs(self, code=None):
|
||||
self["code"] = code
|
||||
synopsis = "[CODE]"
|
||||
|
||||
class SendFileOptions(usage.Options):
|
||||
def parseArgs(self, filename):
|
||||
self["filename"] = filename
|
||||
synopsis = "FILENAME"
|
||||
p = subparsers.add_parser("send-text", description="Send a text mesasge",
|
||||
usage="wormhole send-text TEXT")
|
||||
p.add_argument("text", metavar="TEXT", help="the message to send (a string)")
|
||||
p.set_defaults(func=cmd_send_text.send_text)
|
||||
|
||||
class ReceiveFileOptions(usage.Options):
|
||||
optParameters = [
|
||||
["output-file", "o", None, "File to create"],
|
||||
]
|
||||
def parseArgs(self, code=None):
|
||||
self["code"] = code
|
||||
synopsis = "[CODE]"
|
||||
p = subparsers.add_parser("receive-text", description="Receive a text message",
|
||||
usage="wormhole receive-text [CODE]")
|
||||
p.add_argument("code", nargs="?", default=None, metavar="[CODE]",
|
||||
help=dedent("""\
|
||||
The magic-wormhole code, from the sender. If omitted, the
|
||||
program will ask for it, using tab-completion."""),
|
||||
)
|
||||
p.set_defaults(func=cmd_receive_text.receive_text)
|
||||
|
||||
class Options(usage.Options):
|
||||
synopsis = "\nUsage: wormhole <command>"
|
||||
optParameters = [
|
||||
["relay-url", None, public_relay.RENDEZVOUS_RELAY,
|
||||
"rendezvous relay to use (URL)"],
|
||||
["transit-helper", None, public_relay.TRANSIT_RELAY,
|
||||
"transit relay to use (tcp:HOST:PORT)"],
|
||||
]
|
||||
subCommands = [("send-text", None, SendTextOptions, "Send a text message"),
|
||||
("send-file", None, SendFileOptions, "Send a file"),
|
||||
("receive-text", None, ReceiveTextOptions, "Receive a text message"),
|
||||
("receive-file", None, ReceiveFileOptions, "Receive a file"),
|
||||
]
|
||||
p = subparsers.add_parser("send-file", description="Send a file",
|
||||
usage="wormhole send-file FILENAME")
|
||||
p.add_argument("filename", metavar="FILENAME", help="The file to be sent")
|
||||
p.set_defaults(func=cmd_send_file.send_file)
|
||||
|
||||
def getUsage(self, **kwargs):
|
||||
t = usage.Options.getUsage(self, **kwargs)
|
||||
return t + "\nPlease run 'wormhole <command> --help' for more details on each command.\n"
|
||||
p = subparsers.add_parser("receive-file", description="Receive a file",
|
||||
usage="wormhole receive-file [-o FILENAME] [CODE]")
|
||||
p.add_argument("-o", "--output-file", default=None, metavar="FILENAME",
|
||||
help=dedent("""\
|
||||
The file to create, overriding the filename suggested by the
|
||||
sender"""),
|
||||
)
|
||||
p.add_argument("code", nargs="?", default=None, metavar="[CODE]",
|
||||
help=dedent("""\
|
||||
The magic-wormhole code, from the sender. If omitted, the
|
||||
program will ask for it, using tab-completion."""),
|
||||
)
|
||||
p.set_defaults(func=cmd_receive_file.receive_file)
|
||||
|
||||
def postOptions(self):
|
||||
if not hasattr(self, 'subOptions'):
|
||||
raise usage.UsageError("must specify a command")
|
||||
|
||||
def send_text(*args):
|
||||
from . import cmd_send_text
|
||||
return cmd_send_text.send_text(*args)
|
||||
|
||||
def receive_text(*args):
|
||||
from . import cmd_receive_text
|
||||
return cmd_receive_text.receive_text(*args)
|
||||
|
||||
def send_file(*args):
|
||||
from . import cmd_send_file
|
||||
return cmd_send_file.send_file(*args)
|
||||
|
||||
def receive_file(*args):
|
||||
from . import cmd_receive_file
|
||||
return cmd_receive_file.receive_file(*args)
|
||||
|
||||
DISPATCH = {"send-text": send_text,
|
||||
"receive-text": receive_text,
|
||||
"send-file": send_file,
|
||||
"receive-file": receive_file,
|
||||
}
|
||||
|
||||
def run(args, stdout, stderr, executable=None):
|
||||
"""This is invoked directly by the 'wormhole' entry-point script. It can
|
||||
also invoked by entry() below."""
|
||||
config = Options()
|
||||
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
config.parseOptions(args)
|
||||
except usage.error, e:
|
||||
c = config
|
||||
while hasattr(c, 'subOptions'):
|
||||
c = c.subOptions
|
||||
print >>stderr, str(c)
|
||||
print >>stderr, e.args[0]
|
||||
return 1
|
||||
command = config.subCommand
|
||||
so = config.subOptions
|
||||
so["executable"] = executable
|
||||
try:
|
||||
#rc = DISPATCH[command](so, stdout, stderr)
|
||||
rc = DISPATCH[command](so)
|
||||
#rc = command.func(args, stdout, stderr)
|
||||
rc = args.func(args)
|
||||
return rc
|
||||
except ImportError, e:
|
||||
print >>stderr, "--- ImportError ---"
|
||||
|
@ -100,3 +76,7 @@ def entry():
|
|||
"""This is used by a setuptools entry_point. When invoked this way,
|
||||
setuptools has already put the installed package on sys.path ."""
|
||||
return run(sys.argv[1:], sys.stdout, sys.stderr, executable=sys.argv[0])
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = parser.parse_args()
|
||||
print args
|
||||
|
|
Loading…
Reference in New Issue
Block a user