Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix several major errors in the implementation of output #1315

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions S3/Progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
import S3.Utils

class Progress(object):
_stdout = sys.stdout
_stderr = sys.stderr
_last_display = 0

def __init__(self, labels, total_size):
self._stdout = sys.stdout
self._stderr = sys.stderr
self.new_file(labels, total_size)

def new_file(self, labels, total_size):
Expand Down Expand Up @@ -52,8 +52,8 @@ def done(self, message):
self.display(done_message = message)

def output_labels(self):
self._stdout.write(u"%(action)s: '%(source)s' -> '%(destination)s' %(extra)s\n" % self.labels)
self._stdout.flush()
self._stderr.write(u"%(action)s: '%(source)s' -> '%(destination)s' %(extra)s\n" % self.labels)
self._stderr.flush()

def _display_needed(self):
# We only need to update the display every so often.
Expand All @@ -79,18 +79,18 @@ def display(self, new_file = False, done_message = None):
timedelta = self.time_current - self.time_start
sec_elapsed = timedelta.days * 86400 + timedelta.seconds + float(timedelta.microseconds) / 1000000.0
print_speed = S3.Utils.formatSize((self.current_position - self.initial_position) / sec_elapsed, True, True)
self._stdout.write("100%% %s%s in %.2fs (%.2f %sB/s)\n" %
self._stderr.write("100%% %s%s in %.2fs (%.2f %sB/s)\n" %
(print_size[0], print_size[1], sec_elapsed, print_speed[0], print_speed[1]))
self._stdout.flush()
self._stderr.flush()
return

rel_position = (self.current_position * 100) // self.total_size
if rel_position >= self.last_milestone:
# Move by increments of 5.
# NOTE: to check: Looks like to not do what is looks like to be designed to do
self.last_milestone = (rel_position // 5) * 5
self._stdout.write("%d%% ", self.last_milestone)
self._stdout.flush()
self._stderr.write("%d%% ", self.last_milestone)
self._stderr.flush()
return

class ProgressANSI(Progress):
Expand All @@ -110,8 +110,8 @@ def display(self, new_file = False, done_message = None):
"""
if new_file:
self.output_labels()
self._stdout.write(self.ANSI_save_cursor_pos)
self._stdout.flush()
self._stderr.write(self.ANSI_save_cursor_pos)
self._stderr.flush()
return

# Only display progress every so often
Expand All @@ -124,9 +124,9 @@ def display(self, new_file = False, done_message = None):
print_speed = S3.Utils.formatSize((self.current_position - self.initial_position) / sec_elapsed, True, True)
else:
print_speed = (0, "")
self._stdout.write(self.ANSI_restore_cursor_pos)
self._stdout.write(self.ANSI_erase_to_eol)
self._stdout.write("%(current)s of %(total)s %(percent)3d%% in %(elapsed)ds %(speed).2f %(speed_coeff)sB/s" % {
self._stderr.write(self.ANSI_restore_cursor_pos)
self._stderr.write(self.ANSI_erase_to_eol)
self._stderr.write("%(current)s of %(total)s %(percent)3d%% in %(elapsed)ds %(speed).2f %(speed_coeff)sB/s" % {
"current" : str(self.current_position).rjust(len(str(self.total_size))),
"total" : self.total_size,
"percent" : self.total_size and ((self.current_position * 100) // self.total_size) or 0,
Expand All @@ -136,9 +136,9 @@ def display(self, new_file = False, done_message = None):
})

if done_message:
self._stdout.write(" %s\n" % done_message)
self._stderr.write(" %s\n" % done_message)

self._stdout.flush()
self._stderr.flush()

class ProgressCR(Progress):
## Uses CR char (Carriage Return) just like other progress bars do.
Expand All @@ -162,7 +162,7 @@ def display(self, new_file = False, done_message = None):
print_speed = S3.Utils.formatSize((self.current_position - self.initial_position) / sec_elapsed, True, True)
else:
print_speed = (0, "")
self._stdout.write(self.CR_char)
self._stderr.write(self.CR_char)
output = " %(current)s of %(total)s %(percent)3d%% in %(elapsed)4ds %(speed)7.2f %(speed_coeff)sB/s" % {
"current" : str(self.current_position).rjust(len(str(self.total_size))),
"total" : self.total_size,
Expand All @@ -171,11 +171,11 @@ def display(self, new_file = False, done_message = None):
"speed" : print_speed[0],
"speed_coeff" : print_speed[1]
}
self._stdout.write(output)
self._stderr.write(output)
if done_message:
self._stdout.write(" %s\n" % done_message)
self._stderr.write(" %s\n" % done_message)

self._stdout.flush()
self._stderr.flush()

class StatsInfo(object):
"""Holding info for stats totals"""
Expand Down
14 changes: 10 additions & 4 deletions s3cmd
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ from __future__ import absolute_import, print_function, division

import sys

output = lambda s: (sys.stdout.write(s + "\n"), sys.stdout.flush()) # to be reset in main()

if sys.version_info < (2, 6):
sys.stderr.write(u"ERROR: Python 2.6 or higher required, sorry.\n")
# 72 == EX_OSFILE
Expand Down Expand Up @@ -84,10 +86,6 @@ if not PY3:
pass


def output(message):
sys.stdout.write(message + "\n")
sys.stdout.flush()

def check_args_type(args, type, verbose_type):
"""NOTE: This function looks like to not be used."""
for arg in args:
Expand Down Expand Up @@ -3109,6 +3107,7 @@ def main():
optparser.add_option( "--max-retries", dest="max_retries", action="store", help="Maximum number of times to retry a failed request before giving up. Default is 5", metavar="NUM")
optparser.add_option( "--content-disposition", dest="content_disposition", action="store", help="Provide a Content-Disposition for signed URLs, e.g., \"inline; filename=myvideo.mp4\"")
optparser.add_option( "--content-type", dest="content_type", action="store", help="Provide a Content-Type for signed URLs, e.g., \"video/mp4\"")
optparser.add_option("-2", "--stderr-output", dest="stderr_output", action="store", help="Write all output to STDERR rather than STDOUT")

optparser.set_usage(optparser.usage + " COMMAND [parameters]")
optparser.set_description('S3cmd is a tool for managing objects in '+
Expand All @@ -3126,6 +3125,12 @@ def main():
format='%(levelname)s: %(message)s',
stream = sys.stderr)

def output(message):
pipe = sys.stderr if args.stderr_output else sys.stdout
pipe.write(message + "\n")
pipe.flush()


if options.show_version:
output(u"s3cmd version %s" % PkgInfo.version)
sys.exit(EX_OK)
Expand All @@ -3135,6 +3140,7 @@ def main():
try:
f = open("/dev/null", "w")
sys.stdout = f
sys.stderr = f
except IOError:
warning(u"Unable to open /dev/null: --quiet disabled.")

Expand Down