write progress/status messages to stderr, not stdout

This should leave stdout clean for use in `foo | wormhole send --text=-` and
`wormhole rx CODE >foo`, although the forms that want interactive code entry
probably won't work that way.

closes #99
This commit is contained in:
Brian Warner 2016-12-24 00:03:32 -05:00
parent 64cdd426c0
commit 72dfb6eb1c
3 changed files with 61 additions and 65 deletions

View File

@ -42,7 +42,7 @@ class TwistedReceiver:
self._transit_receiver = None self._transit_receiver = None
def _msg(self, *args, **kwargs): def _msg(self, *args, **kwargs):
print(*args, file=self.args.stdout, **kwargs) print(*args, file=self.args.stderr, **kwargs)
@inlineCallbacks @inlineCallbacks
def go(self): def go(self):
@ -201,7 +201,7 @@ class TwistedReceiver:
def _handle_text(self, them_d, w): def _handle_text(self, them_d, w):
# we're receiving a text message # we're receiving a text message
self._msg(them_d["message"]) print(them_d["message"], file=self.args.stdout)
self._send_data({"answer": {"message_ack": "ok"}}, w) self._send_data({"answer": {"message_ack": "ok"}}, w)
def _handle_file(self, them_d): def _handle_file(self, them_d):
@ -283,7 +283,7 @@ class TwistedReceiver:
self._msg(u"Receiving (%s).." % record_pipe.describe()) self._msg(u"Receiving (%s).." % record_pipe.describe())
with self.args.timing.add("rx file"): with self.args.timing.add("rx file"):
progress = tqdm(file=self.args.stdout, progress = tqdm(file=self.args.stderr,
disable=self.args.hide_progress, disable=self.args.hide_progress,
unit="B", unit_scale=True, total=self.xfersize) unit="B", unit_scale=True, total=self.xfersize)
hasher = hashlib.sha256() hasher = hashlib.sha256()

View File

@ -74,7 +74,7 @@ class Sender:
other_cmd += " -0" other_cmd += " -0"
print(u"On the other computer, please run: %s" % other_cmd, print(u"On the other computer, please run: %s" % other_cmd,
file=args.stdout) file=args.stderr)
if args.code: if args.code:
w.set_code(args.code) w.set_code(args.code)
@ -83,10 +83,10 @@ class Sender:
code = yield w.get_code(args.code_length) code = yield w.get_code(args.code_length)
if not args.zeromode: if not args.zeromode:
print(u"Wormhole code is: %s" % code, file=args.stdout) print(u"Wormhole code is: %s" % code, file=args.stderr)
# flush stdout so the code is displayed immediately # flush stderr so the code is displayed immediately
args.stdout.flush() args.stderr.flush()
print(u"", file=args.stdout) print(u"", file=args.stderr)
yield w.establish_key() yield w.establish_key()
def on_slow_connection(): def on_slow_connection():
@ -176,14 +176,14 @@ class Sender:
args = self._args args = self._args
text = args.text text = args.text
if text == "-": if text == "-":
print(u"Reading text message from stdin..", file=args.stdout) print(u"Reading text message from stdin..", file=args.stderr)
text = sys.stdin.read() text = sys.stdin.read()
if not text and not args.what: if not text and not args.what:
text = six.moves.input("Text to send: ") text = six.moves.input("Text to send: ")
if text is not None: if text is not None:
print(u"Sending text message (%s)" % naturalsize(len(text)), print(u"Sending text message (%s)" % naturalsize(len(text)),
file=args.stdout) file=args.stderr)
offer = { "message": text } offer = { "message": text }
fd_to_send = None fd_to_send = None
return offer, fd_to_send return offer, fd_to_send
@ -204,12 +204,12 @@ class Sender:
} }
print(u"Sending %s file named '%s'" print(u"Sending %s file named '%s'"
% (naturalsize(filesize), basename), % (naturalsize(filesize), basename),
file=args.stdout) file=args.stderr)
fd_to_send = open(what, "rb") fd_to_send = open(what, "rb")
return offer, fd_to_send return offer, fd_to_send
if os.path.isdir(what): if os.path.isdir(what):
print(u"Building zipfile..", file=args.stdout) print(u"Building zipfile..", file=args.stderr)
# We're sending a directory. Create a zipfile in a tempdir and # We're sending a directory. Create a zipfile in a tempdir and
# send that. # send that.
fd_to_send = tempfile.SpooledTemporaryFile() fd_to_send = tempfile.SpooledTemporaryFile()
@ -239,7 +239,7 @@ class Sender:
"numfiles": num_files, "numfiles": num_files,
} }
print(u"Sending directory (%s compressed) named '%s'" print(u"Sending directory (%s compressed) named '%s'"
% (naturalsize(filesize), basename), file=args.stdout) % (naturalsize(filesize), basename), file=args.stderr)
return offer, fd_to_send return offer, fd_to_send
raise TypeError("'%s' is neither file nor directory" % args.what) raise TypeError("'%s' is neither file nor directory" % args.what)
@ -248,7 +248,7 @@ class Sender:
def _handle_answer(self, them_answer): def _handle_answer(self, them_answer):
if self._fd_to_send is None: if self._fd_to_send is None:
if them_answer["message_ack"] == "ok": if them_answer["message_ack"] == "ok":
print(u"text message sent", file=self._args.stdout) print(u"text message sent", file=self._args.stderr)
returnValue(None) # terminates this function returnValue(None) # terminates this function
raise TransferError("error sending text: %r" % (them_answer,)) raise TransferError("error sending text: %r" % (them_answer,))
@ -270,11 +270,11 @@ class Sender:
record_pipe = yield ts.connect() record_pipe = yield ts.connect()
self._timing.add("transit connected") self._timing.add("transit connected")
# record_pipe should implement IConsumer, chunks are just records # record_pipe should implement IConsumer, chunks are just records
stdout = self._args.stdout stderr = self._args.stderr
print(u"Sending (%s).." % record_pipe.describe(), file=stdout) print(u"Sending (%s).." % record_pipe.describe(), file=stderr)
hasher = hashlib.sha256() hasher = hashlib.sha256()
progress = tqdm(file=stdout, disable=self._args.hide_progress, progress = tqdm(file=stderr, disable=self._args.hide_progress,
unit="B", unit_scale=True, unit="B", unit_scale=True,
total=filesize) total=filesize)
def _count_and_hash(data): def _count_and_hash(data):
@ -290,7 +290,7 @@ class Sender:
expected_hash = hasher.digest() expected_hash = hasher.digest()
expected_hex = bytes_to_hexstr(expected_hash) expected_hex = bytes_to_hexstr(expected_hash)
print(u"File sent.. waiting for confirmation", file=stdout) print(u"File sent.. waiting for confirmation", file=stderr)
with self._timing.add("get ack") as t: with self._timing.add("get ack") as t:
ack_bytes = yield record_pipe.receive_record() ack_bytes = yield record_pipe.receive_record()
record_pipe.close() record_pipe.close()
@ -303,5 +303,5 @@ class Sender:
if ack[u"sha256"] != expected_hex: if ack[u"sha256"] != expected_hex:
t.detail(datahash="failed") t.detail(datahash="failed")
raise TransferError("Transfer failed (bad remote hash)") raise TransferError("Transfer failed (bad remote hash)")
print(u"Confirmation received. Transfer complete.", file=stdout) print(u"Confirmation received. Transfer complete.", file=stderr)
t.detail(ack="ok") t.detail(ack="ok")

View File

@ -367,18 +367,11 @@ class PregeneratedCode(ServerBase, ScriptsBase, unittest.TestCase):
self.maxDiff = None # show full output for assertion failures self.maxDiff = None # show full output for assertion failures
if mode != "slow-text": key_established = ""
self.failUnlessEqual(send_stderr, "", if mode == "slow-text":
(send_stdout, send_stderr)) key_established = "Key established, waiting for confirmation...\n"
self.failUnlessEqual(receive_stderr, "",
(receive_stdout, receive_stderr)) self.assertEqual(send_stdout, "")
else:
self.assertEqual(send_stderr,
"Key established, waiting for confirmation...\n",
(send_stdout, send_stderr))
self.assertEqual(receive_stderr,
"Key established, waiting for confirmation...\n",
(receive_stdout, receive_stderr))
# check sender # check sender
if mode == "text" or mode == "slow-text": if mode == "text" or mode == "slow-text":
@ -386,53 +379,58 @@ class PregeneratedCode(ServerBase, ScriptsBase, unittest.TestCase):
"On the other computer, please run: " "On the other computer, please run: "
"wormhole receive{NL}" "wormhole receive{NL}"
"Wormhole code is: {code}{NL}{NL}" "Wormhole code is: {code}{NL}{NL}"
"{KE}"
"text message sent{NL}").format(bytes=len(message), "text message sent{NL}").format(bytes=len(message),
code=send_cfg.code, code=send_cfg.code,
NL=NL) NL=NL,
self.failUnlessEqual(send_stdout, expected) KE=key_established)
self.failUnlessEqual(send_stderr, expected)
elif mode == "file": elif mode == "file":
self.failUnlessIn("Sending {size:s} file named '{name}'{NL}" self.failUnlessIn("Sending {size:s} file named '{name}'{NL}"
.format(size=naturalsize(len(message)), .format(size=naturalsize(len(message)),
name=send_filename, name=send_filename,
NL=NL), send_stdout) NL=NL), send_stderr)
self.failUnlessIn("On the other computer, please run: " self.failUnlessIn("On the other computer, please run: "
"wormhole receive{NL}" "wormhole receive{NL}"
"Wormhole code is: {code}{NL}{NL}" "Wormhole code is: {code}{NL}{NL}"
.format(code=send_cfg.code, NL=NL), .format(code=send_cfg.code, NL=NL),
send_stdout) send_stderr)
self.failUnlessIn("File sent.. waiting for confirmation{NL}" self.failUnlessIn("File sent.. waiting for confirmation{NL}"
"Confirmation received. Transfer complete.{NL}" "Confirmation received. Transfer complete.{NL}"
.format(NL=NL), send_stdout) .format(NL=NL), send_stderr)
elif mode == "directory": elif mode == "directory":
self.failUnlessIn("Sending directory", send_stdout) self.failUnlessIn("Sending directory", send_stderr)
self.failUnlessIn("named 'testdir'", send_stdout) self.failUnlessIn("named 'testdir'", send_stderr)
self.failUnlessIn("On the other computer, please run: " self.failUnlessIn("On the other computer, please run: "
"wormhole receive{NL}" "wormhole receive{NL}"
"Wormhole code is: {code}{NL}{NL}" "Wormhole code is: {code}{NL}{NL}"
.format(code=send_cfg.code, NL=NL), send_stdout) .format(code=send_cfg.code, NL=NL), send_stderr)
self.failUnlessIn("File sent.. waiting for confirmation{NL}" self.failUnlessIn("File sent.. waiting for confirmation{NL}"
"Confirmation received. Transfer complete.{NL}" "Confirmation received. Transfer complete.{NL}"
.format(NL=NL), send_stdout) .format(NL=NL), send_stderr)
# check receiver # check receiver
if mode == "text" or mode == "slow-text": if mode == "text" or mode == "slow-text":
self.failUnlessEqual(receive_stdout, message+NL) self.assertEqual(receive_stdout, message+NL)
self.assertEqual(receive_stderr, key_established)
elif mode == "file": elif mode == "file":
self.failUnlessEqual(receive_stdout, "")
self.failUnlessIn("Receiving file ({size:s}) into: {name}" self.failUnlessIn("Receiving file ({size:s}) into: {name}"
.format(size=naturalsize(len(message)), .format(size=naturalsize(len(message)),
name=receive_filename), receive_stdout) name=receive_filename), receive_stderr)
self.failUnlessIn("Received file written to ", receive_stdout) self.failUnlessIn("Received file written to ", receive_stderr)
fn = os.path.join(receive_dir, receive_filename) fn = os.path.join(receive_dir, receive_filename)
self.failUnless(os.path.exists(fn)) self.failUnless(os.path.exists(fn))
with open(fn, "r") as f: with open(fn, "r") as f:
self.failUnlessEqual(f.read(), message) self.failUnlessEqual(f.read(), message)
elif mode == "directory": elif mode == "directory":
self.failUnlessEqual(receive_stdout, "")
want = (r"Receiving directory \(\d+ \w+\) into: {name}/" want = (r"Receiving directory \(\d+ \w+\) into: {name}/"
.format(name=receive_dirname)) .format(name=receive_dirname))
self.failUnless(re.search(want, receive_stdout), self.failUnless(re.search(want, receive_stderr),
(want, receive_stdout)) (want, receive_stderr))
self.failUnlessIn("Received files written to {name}" self.failUnlessIn("Received files written to {name}"
.format(name=receive_dirname), receive_stdout) .format(name=receive_dirname), receive_stderr)
fn = os.path.join(receive_dir, receive_dirname) fn = os.path.join(receive_dir, receive_dirname)
self.failUnless(os.path.exists(fn), fn) self.failUnless(os.path.exists(fn), fn)
for i in range(5): for i in range(5):
@ -547,62 +545,60 @@ class PregeneratedCode(ServerBase, ScriptsBase, unittest.TestCase):
self.maxDiff = None # show full output for assertion failures self.maxDiff = None # show full output for assertion failures
self.failUnlessEqual(send_stderr, "", self.assertEqual(send_stdout, "")
(send_stdout, send_stderr)) self.assertEqual(receive_stdout, "")
self.failUnlessEqual(receive_stderr, "",
(receive_stdout, receive_stderr))
# check sender # check sender
if mode == "file": if mode == "file":
self.failUnlessIn("Sending {size:s} file named '{name}'{NL}" self.failUnlessIn("Sending {size:s} file named '{name}'{NL}"
.format(size=naturalsize(size), .format(size=naturalsize(size),
name=send_filename, name=send_filename,
NL=NL), send_stdout) NL=NL), send_stderr)
self.failUnlessIn("On the other computer, please run: " self.failUnlessIn("On the other computer, please run: "
"wormhole receive{NL}" "wormhole receive{NL}"
"Wormhole code is: {code}{NL}{NL}" "Wormhole code is: {code}{NL}{NL}"
.format(code=send_cfg.code, NL=NL), .format(code=send_cfg.code, NL=NL),
send_stdout) send_stderr)
self.failIfIn("File sent.. waiting for confirmation{NL}" self.failIfIn("File sent.. waiting for confirmation{NL}"
"Confirmation received. Transfer complete.{NL}" "Confirmation received. Transfer complete.{NL}"
.format(NL=NL), send_stdout) .format(NL=NL), send_stderr)
elif mode == "directory": elif mode == "directory":
self.failUnlessIn("Sending directory", send_stdout) self.failUnlessIn("Sending directory", send_stderr)
self.failUnlessIn("named 'testdir'", send_stdout) self.failUnlessIn("named 'testdir'", send_stderr)
self.failUnlessIn("On the other computer, please run: " self.failUnlessIn("On the other computer, please run: "
"wormhole receive{NL}" "wormhole receive{NL}"
"Wormhole code is: {code}{NL}{NL}" "Wormhole code is: {code}{NL}{NL}"
.format(code=send_cfg.code, NL=NL), send_stdout) .format(code=send_cfg.code, NL=NL), send_stderr)
self.failIfIn("File sent.. waiting for confirmation{NL}" self.failIfIn("File sent.. waiting for confirmation{NL}"
"Confirmation received. Transfer complete.{NL}" "Confirmation received. Transfer complete.{NL}"
.format(NL=NL), send_stdout) .format(NL=NL), send_stderr)
# check receiver # check receiver
if mode == "file": if mode == "file":
self.failIfIn("Received file written to ", receive_stdout) self.failIfIn("Received file written to ", receive_stderr)
if failmode == "noclobber": if failmode == "noclobber":
self.failUnlessIn("Error: " self.failUnlessIn("Error: "
"refusing to overwrite existing 'testfile'{NL}" "refusing to overwrite existing 'testfile'{NL}"
.format(NL=NL), receive_stdout) .format(NL=NL), receive_stderr)
else: else:
self.failUnlessIn("Error: " self.failUnlessIn("Error: "
"insufficient free space (0B) for file ({size:d}B){NL}" "insufficient free space (0B) for file ({size:d}B){NL}"
.format(NL=NL, size=size), receive_stdout) .format(NL=NL, size=size), receive_stderr)
elif mode == "directory": elif mode == "directory":
self.failIfIn("Received files written to {name}" self.failIfIn("Received files written to {name}"
.format(name=receive_name), receive_stdout) .format(name=receive_name), receive_stderr)
#want = (r"Receiving directory \(\d+ \w+\) into: {name}/" #want = (r"Receiving directory \(\d+ \w+\) into: {name}/"
# .format(name=receive_name)) # .format(name=receive_name))
#self.failUnless(re.search(want, receive_stdout), #self.failUnless(re.search(want, receive_stderr),
# (want, receive_stdout)) # (want, receive_stderr))
if failmode == "noclobber": if failmode == "noclobber":
self.failUnlessIn("Error: " self.failUnlessIn("Error: "
"refusing to overwrite existing 'testdir'{NL}" "refusing to overwrite existing 'testdir'{NL}"
.format(NL=NL), receive_stdout) .format(NL=NL), receive_stderr)
else: else:
self.failUnlessIn("Error: " self.failUnlessIn("Error: "
"insufficient free space (0B) for directory ({size:d}B){NL}" "insufficient free space (0B) for directory ({size:d}B){NL}"
.format(NL=NL, size=size), receive_stdout) .format(NL=NL, size=size), receive_stderr)
if failmode == "noclobber": if failmode == "noclobber":
fn = os.path.join(receive_dir, receive_name) fn = os.path.join(receive_dir, receive_name)