From aba4b1f00bb572fa009e2d966d62520751d32e1b Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Sun, 25 Sep 2011 14:48:00 -0700 Subject: [PATCH 1/3] Typo fix --- fabric/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fabric/main.py b/fabric/main.py index 8bfc8f659c..e7a8a7b39e 100644 --- a/fabric/main.py +++ b/fabric/main.py @@ -540,7 +540,7 @@ def main(): # Split host string and apply to env dict username, hostname, port = interpret_host_string(host) # Log to stdout - if state.output.running and not hasattr(task, 'return_value'): + if state.output.running and not hasattr(command, 'return_value'): print("[%s] Executing task '%s'" % (host, name)) # Actually run command commands[name](*args, **kwargs) From e0af2492a97b5bee7ec92abf5e2d6cf7203607ed Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Mon, 26 Sep 2011 10:30:46 -0700 Subject: [PATCH 2/3] Comment --- fabric/io.py | 1 + 1 file changed, 1 insertion(+) diff --git a/fabric/io.py b/fabric/io.py index fa813b1648..f77eaf4290 100644 --- a/fabric/io.py +++ b/fabric/io.py @@ -40,6 +40,7 @@ def output_loop(chan, which, capture): while True: # Handle actual read/write byte = func(1) + # Empty byte == EOS if byte == '': break # A None capture variable implies that we're in open_shell() From 712ea2b50fccc8b270c4c15a3919501f184824a0 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Mon, 26 Sep 2011 14:45:19 -0700 Subject: [PATCH 3/3] Fix IO bug with spurious line prefixes. Fixes #182 --- docs/changelog.rst | 3 +++ fabric/io.py | 18 ++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 73b9670248..7f897d2850 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -25,6 +25,9 @@ would have also been included in the 1.2 line. Changelog ========= +* :bug:`182` During display of remote stdout/stderr, Fabric occasionally + printed extraneous line prefixes (which in turn sometimes overwrote wrapped + text.) This has been fixed. * :bug:`430` Tasks decorated with `~fabric.decorators.runs_once` printed extraneous 'Executing...' status lines on subsequent invocations. This is noisy at best and misleading at worst, and has been corrected. Thanks to diff --git a/fabric/io.py b/fabric/io.py index f77eaf4290..566ab7a7a5 100644 --- a/fabric/io.py +++ b/fabric/io.py @@ -23,8 +23,19 @@ def _endswith(char_list, substring): substring = list(substring) return tail == substring +def _was_newline(capture, byte): + """ + Determine if we are 'past' a newline and need to print the line prefix. + """ + endswith_newline = _endswith(capture, '\n') or _endswith(capture, '\r') + currently_newline = byte in ('\n', '\r') + return endswith_newline and not currently_newline + def output_loop(chan, which, capture): + # Internal capture-buffer-like buffer, used solely for state keeping. + # Unlike 'capture', nothing is ever purged from this. + _buffer = [] # Obtain stdout or stderr related values func = getattr(chan, which) if which == 'recv': @@ -59,16 +70,15 @@ def output_loop(chan, which, capture): # Print to user if printing: # Initial prefix - if not initial_prefix_printed: + if not initial_prefix_printed or _was_newline(_buffer, byte): _flush(pipe, _prefix) initial_prefix_printed = True # Byte itself _flush(pipe, byte) - # Trailing prefix to start off next line - if byte in ("\n", "\r"): - _flush(pipe, _prefix) # Store in capture buffer capture += byte + # Store in internal buffer + _buffer += byte # Handle prompts prompt = _endswith(capture, env.sudo_prompt) try_again = (_endswith(capture, env.again_prompt + '\n')