def RunListCommand(cli, command, parse_output=False, list_command_updates_cache=False): """Runs a cli list comman with a visual progress tracker/spinner. Args: cli: The calliope cli object. command: The list command that generates the completion data. parse_output: If True then the output of command is read and split into a resource data list, one item per line. If False then the command return value is the resource data list. list_command_updates_cache: True if running the list command updates the cache. Returns: The resource data list. """ if parse_output: log_out = log.out out = StringIO.StringIO() log.out = out elif list_command_updates_cache: command.append('--format=none') else: command.append('--format=disable') with progress_tracker.CompletionProgressTracker() as tracker: items = cli().Execute(command, call_arg_complete=False) if parse_output: log.out = log_out if tracker.timed_out: return [] if parse_output: return out.getvalue().rstrip('\n').split('\n') return list(items)
def __call__(self, prefix='', parsed_args=None, **kwargs): """A completer function called by argparse in arg_complete mode.""" with progress_tracker.CompletionProgressTracker(): with resource_cache.ResourceCache() as cache: if len(parsed_args._GetCommand().ai.positional_completers) > 1: # pylint: disable=protected-access qualified_parameter_names = {'collection'} else: qualified_parameter_names = set() completer = None try: completer = self._completer_class( cache=cache, qualified_parameter_names=qualified_parameter_names) parameter_info = completer.ParameterInfo(parsed_args, self._argument) return completer.Complete(prefix, parameter_info) except BaseException as e: # pylint: disable=broad-except, e shall not pass # Fatal completer errors return two "completions", each an error # message that is displayed by the shell completers, and look more # like a pair of error messages than completions. This is much better # than the default that falls back to the file completer, typically # yielding the list of all files in the current directory. # # NOTICE: Each message must start with different characters, # otherwise they will be taken as valid completions. Also, the # messages are sorted in the display, so choose the first char wisely. if completer: completer_name = completer.collection else: completer_name = self._completer_class.__name__ return self._MakeCompletionErrorMessages([ u'{}ERROR: {} resource completer failed.'.format( prefix, completer_name), u'{}REASON: {}'.format(prefix, unicode(e)), ])
def testSpinnerToStream(self): ofile = io.StringIO() with progress_tracker.CompletionProgressTracker(ofile, autotick=True) as t: for _ in range(0, 5): t._Spin() actual = ofile.getvalue() ofile.close() self.assertFalse(t._TimedOut()) self.assertEqual('/\b-\b\\\b|\b/\b \b', actual)
def testNoOp(self): for style in (properties.VALUES.core.InteractiveUXStyles.OFF.name, properties.VALUES.core.InteractiveUXStyles.TESTING.name): properties.VALUES.core.interactive_ux_style.Set(style) ofile = io.StringIO() with progress_tracker.CompletionProgressTracker('tracker', autotick=True): pass actual = ofile.getvalue() ofile.close() self.assertEqual('', actual)
def testSpinnerToFile(self): with self.OpenCompletionFile('w'): with progress_tracker.CompletionProgressTracker(autotick=True) as t: for _ in range(0, 5): t._Spin() with self.OpenCompletionFile('r') as r: preliminary = r.read() self.assertFalse(t._TimedOut()) self.assertEqual('/\b-\b\\\b|\b/\b', preliminary) with self.OpenCompletionFile('r') as r: final = r.read() self.assertEqual('/\b-\b\\\b|\b/\b \b', final)
def testTimedOut(self): # return_value=0 exercises the background code. self.StartObjectPatch(os, 'fork', return_value=0) ofile = io.StringIO() with progress_tracker.CompletionProgressTracker( ofile, autotick=True, timeout=0.4, tick_delay=0.1, background_ttl=0.1) as t: # Spin enough to time out. for _ in range(0, 6): t._Spin() # Bypass signal.setitimer() in unit tests. actual = ofile.getvalue() ofile.close() self.assertEqual('/\b-\b\\\b|\b/\b?\b', actual)
def __call__(self, prefix='', parsed_args=None, **kwargs): """A completer function called by argparse in arg_complete mode.""" with progress_tracker.CompletionProgressTracker(): completer = None try: completer = self._completer_class() parameter_info = completer.ParameterInfo( parsed_args, self._argument) if (hasattr(completer, 'GetListCommand') and not isinstance( completer, deprecated_completers.DeprecatedListCommandCompleter)): list_command = ' '.join( completer.GetListCommand(parameter_info)) completer = deprecated_completers.DeprecatedListCommandCompleter( collection=completer.collection, list_command=list_command) return completer.Complete(prefix, parameter_info) except (Exception, SystemExit) as e: # pylint: disable=broad-except, e shall not pass # Fatal completer errors return two "completions", each an error # message that is displayed by the shell completers, and look more # like a pair of error messages than completions. This is much better # than the default that falls back to the file completer, typically # yielding the list of all files in the current directory. # # NOTICE: Each message must start with different characters, # otherwise they will be taken as valid completions. Also, the # messages are sorted in the display, so choose the first words wisely. if properties.VALUES.core.print_completion_tracebacks.Get(): raise if completer: completer_name = completer.collection else: completer_name = self._completer_class.__name__ return self._MakeCompletionErrorMessages([ u'{} [[ERROR: {} resource completer failed.]]'.format( prefix, completer_name), u'{} [[REASON: {}]]'.format(prefix, unicode(e)), ])