def testInvalidCharacterInArgException(self): args = ['command', '--foo', b'\xce\x94'] exc = exceptions.InvalidCharacterInArgException(args, args[-1]) self.assertRegexpMatches( six.text_type(exc), 'Failed to read command line argument \\[\\\\u0394\\]') self.assertTrue( six.text_type(exc).endswith(('\n' 'command --foo \\u0394\n' ' ^ invalid character')))
def _ConvertNonAsciiArgsToUnicode(self, args): """Converts non-ascii args to unicode. The args most likely came from sys.argv, and Python 2.7 passes them in as bytestrings instead of unicode. Args: args: [str], The list of args to convert. Raises: InvalidCharacterInArgException if a non-ascii arg cannot be converted to unicode. Returns: A new list of args with non-ascii args converted to unicode. """ console_encoding = console_attr.GetConsoleAttr().GetEncoding() filesystem_encoding = sys.getfilesystemencoding() argv = [] for arg in args: try: arg.encode('ascii') # Already ascii. argv.append(arg) continue except UnicodeError: pass try: # Convert bytestring to unicode using the console encoding. argv.append(unicode(arg, console_encoding)) continue except TypeError: # Already unicode. argv.append(arg) continue except UnicodeError: pass try: # Convert bytestring to unicode using the filesystem encoding. # A pathname could have been passed in rather than typed, and # might not match the user terminal encoding, but still be a valid # path. For example: $ foo $(grep -l bar *) argv.append(unicode(arg, filesystem_encoding)) continue except UnicodeError: pass # Can't convert to unicode -- bail out. raise exceptions.InvalidCharacterInArgException([self.name] + args, arg) return argv
def testInvalidCharacterInArgException_ComplexPath(self): command_path = os.path.join('path', 'to', 'command.py') args = [command_path, '--foo', b'\xce\x94'] exc = exceptions.InvalidCharacterInArgException(args, args[-1]) self.assertRegexpMatches( six.text_type(exc), 'Failed to read command line argument \\[\\\\u0394\\]') self.assertTrue( six.text_type(exc).endswith(('\n' 'command --foo \\u0394\n' ' ^ invalid character'))) self.assertNotIn('path', six.text_type(exc))
def _EnforceAsciiArgs(self, argv): """Fail if any arg in argv is not ascii. Args: argv: [str], The list of args to check. Raises: InvalidCharacterInArgException if there is a non-ascii arg. """ for arg in argv: try: arg.decode('ascii') except UnicodeError: raise exceptions.InvalidCharacterInArgException([self.name] + argv, arg)
def _ConvertNonAsciiArgsToUnicode(self, args): """Converts non-ascii args to unicode. The args most likely came from sys.argv, and Python 2.7 passes them in as bytestrings instead of unicode. Args: args: [str], The list of args to convert. Raises: InvalidCharacterInArgException if a non-ascii arg cannot be converted to unicode. Returns: A new list of args with non-ascii args converted to unicode. """ argv = [] for arg in args: if isinstance(arg, six.text_type): # Arg is already a text string, just use it. argv.append(arg) else: # Argument is a byte string. try: # For now we want to leave byte strings as is if they are only ascii # characters. Later we should always convert everything to text. decoded_arg = arg.decode('ascii') # If this passes, it's ascii only. # Add the original byte string if on PY2, for PY3 start living in the # text only world. argv.append(arg if six.PY2 else decoded_arg) except UnicodeError: # There are unicode characters in the byte string. try: argv.append(console_attr.Decode(arg)) except UnicodeError: raise exceptions.InvalidCharacterInArgException( [self.name] + args, arg) return argv
def Execute(self, args=None, call_arg_complete=True): """Execute the CLI tool with the given arguments. Args: args: [str], The arguments from the command line or None to use sys.argv call_arg_complete: Call the _ArgComplete function if True Returns: The result of executing the command determined by the command implementation. Raises: ValueError: for ill-typed arguments. """ if type(args) is str: raise ValueError( 'Execute expects an iterable of strings, not a string.') if call_arg_complete: self._ArgComplete() if not args: args = sys.argv[1:] # Set the command name in case an exception happens before the command name # is finished parsing. command_path_string = self.__name # Look for a --configuration flag and update property state based on # that before proceeding to the main argparse parse step. named_configs.FLAG_OVERRIDE_STACK.PushFromArgs(args) properties.VALUES.PushInvocationValues() flag_names = None try: for s in args: try: s.decode('ascii') except UnicodeDecodeError: raise exceptions.InvalidCharacterInArgException( [sys.argv[0]] + args, s) args = self.__parser.parse_args(args) flag_names = self.__parser.GetFlagCollection() # -h|--help|--document are dispatched by parse_args and never get here. # Now that we have parsed the args, reload the settings so the flags will # take effect. These will use the values from the properties. log.SetUserOutputEnabled(None) log.SetVerbosity(None) command_path_string = '.'.join(args.command_path) properties.VALUES.SetInvocationValue( properties.VALUES.metrics.command_name, command_path_string, None) metrics.Commands(command_path_string, config.CLOUD_SDK_VERSION, flag_names) for hook in self.__pre_run_hooks: hook.Run(command_path_string) result = args.cmd_func(cli=self, args=args) for hook in self.__post_run_hooks: hook.Run(command_path_string) return result except exceptions.ExitCodeNoError as exc: self._HandleKnownError(command_path_string, exc, flag_names, print_error=False) except core_exceptions.Error as exc: self._HandleKnownError(command_path_string, exc, flag_names, print_error=True) except Exception as exc: if type(exc) in KNOWN_ERRORS: self._HandleKnownError(command_path_string, exc, flag_names, print_error=True) else: # Make sure any uncaught exceptions still make it into the log file. exc_printable = self.SafeExceptionToString(exc) log.debug(exc_printable, exc_info=sys.exc_info()) metrics.Error(command_path_string, exc, flag_names) raise finally: properties.VALUES.PopInvocationValues() named_configs.FLAG_OVERRIDE_STACK.Pop() # Reset these values to their previous state now that we popped the flag # values. log.SetUserOutputEnabled(None) log.SetVerbosity(None)