diff --git a/awscli/customizations/s3/results.py b/awscli/customizations/s3/results.py index 558f2f956e9b..6e350245038e 100644 --- a/awscli/customizations/s3/results.py +++ b/awscli/customizations/s3/results.py @@ -315,7 +315,9 @@ class ResultPrinter(BaseResultHandler): SRC_DEST_TRANSFER_LOCATION_FORMAT = '{src} to {dest}' SRC_TRANSFER_LOCATION_FORMAT = '{src}' - def __init__(self, result_recorder, out_file=None, error_file=None): + def __init__( + self, result_recorder, out_file=None, error_file=None, frequency=0, oneline=True + ): """Prints status of ongoing transfer :type result_recorder: ResultRecorder @@ -331,6 +333,8 @@ def __init__(self, result_recorder, out_file=None, error_file=None): """ self._result_recorder = result_recorder self._out_file = out_file + self._frequency = frequency + self._first = True if self._out_file is None: self._out_file = sys.stdout self._error_file = error_file @@ -347,12 +351,31 @@ def __init__(self, result_recorder, out_file=None, error_file=None): DryRunResult: self._print_dry_run, FinalTotalSubmissionsResult: self._clear_progress_if_no_more_expected_transfers, } + self._now = time.time() + self._oneline = oneline def __call__(self, result): """Print the progress of the ongoing transfer based on a result""" - self._result_handler_map.get(type(result), self._print_noop)( - result=result - ) + result_handler = self._result_handler_map.get(type(result), self._print_noop) + if type(result) is ProgressResult: + result_handler = self._override_progress_result_handler( + result, result_handler + ) + result_handler(result=result) + + def _override_progress_result_handler(self, result, result_handler): + if ( + type(result) in [ProgressResult] + and ( + self._first + or (self._frequency == 0) + or (time.time() - self._now >= self._frequency) + ) + ): + self._now = time.time() + self._first = False + return result_handler + return self._print_noop def _print_noop(self, **kwargs): # If the result does not have a handler, then do nothing with it. @@ -463,15 +486,19 @@ def _print_progress(self, **kwargs): if not self._result_recorder.expected_totals_are_final(): progress_statement += self._STILL_CALCULATING_TOTALS - # Make sure that it overrides any previous progress bar. - progress_statement = self._adjust_statement_padding( - progress_statement, ending_char='\r' - ) - # We do not want to include the carriage return in this calculation - # as progress length is used for determining whitespace padding. - # So we subtract one off of the length. - self._progress_length = len(progress_statement) - 1 - + if self._oneline: + # Make sure that it overrides any previous progress bar. + progress_statement = self._adjust_statement_padding( + progress_statement, ending_char='\r' + ) + # We do not want to include the carriage return in this calculation + # as progress length is used for determining whitespace padding. + # So we subtract one off of the length. + self._progress_length = len(progress_statement) - 1 + else: + progress_statement = self._adjust_statement_padding( + progress_statement, ending_char='\n' + ) # Print the progress out. self._print_to_out_file(progress_statement) diff --git a/awscli/customizations/s3/s3handler.py b/awscli/customizations/s3/s3handler.py index 23176f30f889..b4a6c7ba5527 100644 --- a/awscli/customizations/s3/s3handler.py +++ b/awscli/customizations/s3/s3handler.py @@ -104,7 +104,11 @@ def _add_result_printer(self, result_recorder, result_processor_handlers): elif not self._cli_params.get('progress'): result_printer = NoProgressResultPrinter(result_recorder) else: - result_printer = ResultPrinter(result_recorder) + result_printer = ResultPrinter( + result_recorder, + frequency=self._cli_params.get('progress_frequency'), + oneline=not self._cli_params.get('progress_multiline'), + ) result_processor_handlers.append(result_printer) diff --git a/awscli/customizations/s3/subcommands.py b/awscli/customizations/s3/subcommands.py index 8dc8a61fa895..97404566279e 100644 --- a/awscli/customizations/s3/subcommands.py +++ b/awscli/customizations/s3/subcommands.py @@ -526,6 +526,28 @@ ), } +PROGRESS_FREQUENCY = { + 'name': 'progress-frequency', + 'dest': 'progress_frequency', + 'cli_type_name': 'integer', + 'default': 0, + 'help_text': ( + 'Number of seconds to wait before updating file ' + 'transfer progress. This flag is only applied when ' + 'the quiet and only-show-errors flags are not ' + 'provided.' + ), +} + +PROGRESS_MULTILINE = { + 'name': 'progress-multiline', + 'dest': 'progress_multiline', + 'action': 'store_true', + 'help_text': ( + 'Show progress on multiple lines.' + ), +} + EXPECTED_SIZE = { 'name': 'expected-size', @@ -669,6 +691,8 @@ SOURCE_REGION, ONLY_SHOW_ERRORS, NO_PROGRESS, + PROGRESS_FREQUENCY, + PROGRESS_MULTILINE, PAGE_SIZE, IGNORE_GLACIER_WARNINGS, FORCE_GLACIER_TRANSFER,