def __init__(self, **global_flags): """Creates an object to call dev_appserver.py. Args: **global_flags: {str:str}, A dictionary of global flags to pass to dev_appserver on each invocation. Raises: NoAppengineSDKError, If the App Engine SDK cannot be located. """ self._global_flags = dict(global_flags) self.__executable_path = os.path.join(util.GetAppEngineSDKRoot(), 'dev_appserver.py') verbosity_string = self.__GetVerbosityString() verbosity = log.VALID_VERBOSITY_STRINGS.get(verbosity_string.lower()) if verbosity is not None: log.SetVerbosity(verbosity) # This does nothing without the above statement (since we are not # shelling out). self.AddGlobalFlagIfSet('dev_appserver_log_level', verbosity_string) # Set this as a default. Will be overridden later if the flag is given. self.AddGlobalFlagIfSet('log_level', verbosity_string)
def Run(self, args, command=None, cli_mode=False, pre_run_hooks=None, post_run_hooks=None): """Run this command with the given arguments. Args: args: The arguments for this command as a namespace. command: The bound Command object that is used to run this Command. cli_mode: bool, True if running from the command line, False if running interactively. pre_run_hooks: [_RunHook], Things to run before the command. post_run_hooks: [_RunHook], Things to run after the command. Returns: The object returned by the module's Run() function. Raises: exceptions.Error: if thrown by the Run() function. """ command_path_string = '.'.join(self._path) properties.VALUES.PushArgs(args) # Enable user output for CLI mode only if it is not explicitly set in the # properties (or given in the provided arguments that were just pushed into # the properties object). user_output_enabled = properties.VALUES.core.user_output_enabled.GetBool( ) set_user_output_property = cli_mode and user_output_enabled is None if set_user_output_property: properties.VALUES.core.user_output_enabled.Set(True) # Now that we have pushed the args, reload the settings so the flags will # take effect. These will use the values from the properties. old_user_output_enabled = log.SetUserOutputEnabled(None) old_verbosity = log.SetVerbosity(None) try: if cli_mode and pre_run_hooks: for hook in pre_run_hooks: hook.Run(command_path_string) tool_context = self._config_hooks.load_context() last_group = None for context_filter in self._config_hooks.context_filters: last_group = context_filter(tool_context, args) command_instance = self._common_type( context=tool_context, entry_point=command.EntryPoint(), command=command, group=last_group) def OutputFormatter(obj): command_instance.Display(args, obj) output_formatter = OutputFormatter def Format(obj): if not obj: return resource_printer.Print(obj, args.format or 'yaml', out=log.out) command_instance.format = Format if args.format: output_formatter = command_instance.format log.debug('Running %s with %s.', command_path_string, args) result = command_instance.Run(args) if cli_mode: output_formatter(result) if cli_mode and post_run_hooks: for hook in post_run_hooks: hook.Run(command_path_string) return result except core_exceptions.Error as exc: msg = '({0}) {1}'.format(command_path_string, str(exc)) log.debug(msg, exc_info=sys.exc_info()) if cli_mode: log.error(msg) self._Exit(exc) else: raise except Exception as exc: # Make sure any uncaught exceptions still make it into the log file. log.file_only_logger.debug(str(exc), exc_info=sys.exc_info()) raise finally: if set_user_output_property: properties.VALUES.core.user_output_enabled.Set(None) log.SetUserOutputEnabled(old_user_output_enabled) log.SetVerbosity(old_verbosity) properties.VALUES.PopArgs()
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 isinstance(args, basestring): raise ValueError( 'Execute expects an iterable of strings, not a string.') # The argparse module does not handle unicode args when run in Python 2 # because it uses str(x) even when type(x) is unicode. This sets itself up # for failure because it converts unicode strings back to byte strings which # will trigger ASCII codec exceptions. It works in Python 3 because str() is # equivalent to unicode() in Python 3. The next Pythonically magic and dirty # statement coaxes the Python 3 behavior out of argparse running in # Python 2. Doing it here ensures that the workaround is in place for # calliope argparse use cases. argparse.str = unicode if call_arg_complete: _ArgComplete(self.__top_element.ai) if not args: args = sys.argv[1:] # help ... is the same as ... --help or ... --document=style=help. We use # --document=style=help to signal the metrics.Help() 'help' label in # actions.RenderDocumentAction().Action(). It doesn't matter if we append # to a command that already has --help or --document=style=... because the # first --help/--document from the left takes effect. Note that # `help ... --help` produces help for the help command itself. if args and args[0] == 'help' and '--help' not in args: args = args[1:] + ['--document=style=help'] # 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() # Set the command name in case an exception happens before the command name # is finished parsing. command_path_string = self.__name specified_arg_names = None argv = self._ConvertNonAsciiArgsToUnicode(args) old_user_output_enabled = None old_verbosity = None try: args = self.__parser.parse_args(argv) calliope_command = args._GetCommand() # pylint: disable=protected-access command_path_string = '.'.join(calliope_command.GetPath()) if not calliope_command.IsUnicodeSupported(): self._EnforceAsciiArgs(argv) specified_arg_names = args.GetSpecifiedArgNames() # -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. old_user_output_enabled = log.SetUserOutputEnabled(None) old_verbosity = log.SetVerbosity(None) # Set the command_name property so it is persisted until the process ends. # Only do this for the top level command that can be detected by looking # at the stack. It will have one initial level, and another level added by # the PushInvocationValues earlier in this method. if len(properties.VALUES.GetInvocationStack()) == 2: properties.VALUES.metrics.command_name.Set(command_path_string) # Set the invocation value for all commands, this is lost when popped properties.VALUES.SetInvocationValue( properties.VALUES.metrics.command_name, command_path_string, None) if properties.VALUES.core.capture_session_file.Get() is not None: capturer = session_capturer.SessionCapturer() capturer.CaptureArgs(args) capturer.CaptureState() capturer.CaptureProperties(properties.VALUES.AllValues()) session_capturer.SessionCapturer.capturer = capturer for hook in self.__pre_run_hooks: hook.Run(command_path_string) resources = calliope_command.Run(cli=self, args=args) for hook in self.__post_run_hooks: hook.Run(command_path_string) # Preserve generator or static list resources. if isinstance(resources, types.GeneratorType): def _Yield(): """Activates generator exceptions.""" try: for resource in resources: yield resource except Exception as exc: # pylint: disable=broad-except self._HandleAllErrors(exc, command_path_string, specified_arg_names) return _Yield() # Do this last. If there is an error, the error handler will log the # command execution along with the error. metrics.Commands(command_path_string, config.CLOUD_SDK_VERSION, specified_arg_names) return resources except Exception as exc: # pylint: disable=broad-except self._HandleAllErrors(exc, command_path_string, specified_arg_names) finally: if session_capturer.SessionCapturer.capturer is not None: with open(properties.VALUES.core.capture_session_file.Get(), 'w') as f: session_capturer.SessionCapturer.capturer.Print(f) properties.VALUES.PopInvocationValues() named_configs.FLAG_OVERRIDE_STACK.Pop() # Reset these values to their previous state now that we popped the flag # values. if old_user_output_enabled is not None: log.SetUserOutputEnabled(old_user_output_enabled) if old_verbosity is not None: log.SetVerbosity(old_verbosity)
def Execute(self, args=None, call_arg_complete=True): """Execute the CLI tool with the given arguments. Args: args: 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. """ if call_arg_complete: self._ArgComplete() if not args: args = sys.argv[1:] for s in args: try: s.decode('ascii') except UnicodeError: raise exceptions.InvalidStringException(s) # Set the command name in case an exception happens before the command name # is finished parsing. command_path_string = self.__name try: properties.VALUES.PushInvocationValues() args = self.__parser.parse_args(args) # -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) # TODO(user): put a real version here metrics.Commands(command_path_string, None) 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, print_error=False) except core_exceptions.Error as exc: self._HandleKnownError(command_path_string, exc, print_error=True) except Exception as exc: # Make sure any uncaught exceptions still make it into the log file. log.file_only_logger.debug(str(exc), exc_info=sys.exc_info()) metrics.Error(command_path_string, exc) raise finally: properties.VALUES.PopInvocationValues() # Reset these values to their previous state now that we popped the flag # values. log.SetUserOutputEnabled(None) log.SetVerbosity(None)
def TearDown(self): log.SetVerbosity(self.original_verbosity)
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)
def Run(self, args): """Creates a new Cloud SQL instance. Args: args: argparse.Namespace, The arguments that this command was invoked with. Returns: A dict object representing the operations resource describing the create operation if the create was successful. Raises: HttpException: A http error response was received while executing api request. ToolException: An error other than http error occured while executing the command. """ # Added this temporarily for debugging SQL instance creation failures log.SetVerbosity(logging.DEBUG) sql_client = self.context['sql_client'] sql_messages = self.context['sql_messages'] resources = self.context['registry'] util.ValidateInstanceName(args.instance) instance_ref = resources.Parse(args.instance, collection='sql.instances') instance_resource = util.ConstructInstanceFromArgs(sql_messages, args) if args.master_instance_name: replication = 'ASYNCHRONOUS' activation_policy = 'ALWAYS' else: replication = 'SYNCHRONOUS' activation_policy = 'ON_DEMAND' if not args.replication: instance_resource.settings.replicationType = replication if not args.activation_policy: instance_resource.settings.activationPolicy = activation_policy instance_resource.project = instance_ref.project instance_resource.instance = instance_ref.instance operation_ref = None if args.pricing_plan == 'PACKAGE': if not console_io.PromptContinue( 'Charges will begin accruing immediately. Really create Cloud ' 'SQL instance?'): raise exceptions.ToolException('canceled by the user.') try: result = sql_client.instances.Insert(instance_resource) operation_ref = resources.Create( 'sql.operations', operation=result.operation, project=instance_ref.project, instance=instance_ref.instance, ) if args. async: return sql_client.operations.Get(operation_ref.Request()) util.WaitForOperation(sql_client, operation_ref, 'Creating Cloud SQL instance') log.CreatedResource(instance_ref) rsource = sql_client.instances.Get(instance_ref.Request()) cache = remote_completion.RemoteCompletion() cache.AddToCache(instance_ref.SelfLink()) return rsource except apitools_base.HttpError: log.debug('operation : %s', str(operation_ref)) raise
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 isinstance(args, six.string_types): raise ValueError( 'Execute expects an iterable of strings, not a string.') # The argparse module does not handle unicode args when run in Python 2 # because it uses str(x) even when type(x) is unicode. This sets itself up # for failure because it converts unicode strings back to byte strings which # will trigger ASCII codec exceptions. It works in Python 3 because str() is # equivalent to unicode() in Python 3. The next Pythonically magic and dirty # statement coaxes the Python 3 behavior out of argparse running in # Python 2. Doing it here ensures that the workaround is in place for # calliope argparse use cases. argparse.str = six.text_type # We need the argparse 1.2.1 patch in _SubParsersActionCall. # TODO(b/77288697) delete after py3 tests use non-hermetic python if argparse.__version__ == '1.1': argparse._SubParsersAction.__call__ = _SubParsersActionCall # pylint: disable=protected-access if call_arg_complete: _ArgComplete(self.__top_element.ai) if not args: args = sys.argv[1:] # 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() # Set the command name in case an exception happens before the command name # is finished parsing. command_path_string = self.__name specified_arg_names = None # Convert py2 args to text. argv = [console_attr.Decode(arg) for arg in args] if six.PY2 else args old_user_output_enabled = None old_verbosity = None try: args = self.__parser.parse_args(_ApplyFlagsFile(argv)) if args.CONCEPT_ARGS is not None: args.CONCEPT_ARGS.ParseConcepts() calliope_command = args._GetCommand() # pylint: disable=protected-access command_path_string = '.'.join(calliope_command.GetPath()) specified_arg_names = args.GetSpecifiedArgNames() # If the CLI has not been reloaded since the last command execution (e.g. # in test runs), args.CONCEPTS may contain cached values. if args.CONCEPTS is not None: args.CONCEPTS.Reset() # -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. old_user_output_enabled = log.SetUserOutputEnabled(None) old_verbosity = log.SetVerbosity(None) # Set the command_name property so it is persisted until the process ends. # Only do this for the top level command that can be detected by looking # at the stack. It will have one initial level, and another level added by # the PushInvocationValues earlier in this method. if len(properties.VALUES.GetInvocationStack()) == 2: properties.VALUES.metrics.command_name.Set(command_path_string) # Set the invocation value for all commands, this is lost when popped properties.VALUES.SetInvocationValue( properties.VALUES.metrics.command_name, command_path_string, None) for hook in self.__pre_run_hooks: hook.Run(command_path_string) resources = calliope_command.Run(cli=self, args=args) for hook in self.__post_run_hooks: hook.Run(command_path_string) # Preserve generator or static list resources. if isinstance(resources, types.GeneratorType): def _Yield(): """Activates generator exceptions.""" try: for resource in resources: yield resource except Exception as exc: # pylint: disable=broad-except self._HandleAllErrors(exc, command_path_string, specified_arg_names) return _Yield() # Do this last. If there is an error, the error handler will log the # command execution along with the error. metrics.Commands(command_path_string, config.CLOUD_SDK_VERSION, specified_arg_names) return resources except Exception as exc: # pylint: disable=broad-except self._HandleAllErrors(exc, command_path_string, specified_arg_names) finally: properties.VALUES.PopInvocationValues() named_configs.FLAG_OVERRIDE_STACK.Pop() # Reset these values to their previous state now that we popped the flag # values. if old_user_output_enabled is not None: log.SetUserOutputEnabled(old_user_output_enabled) if old_verbosity is not None: log.SetVerbosity(old_verbosity)
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 isinstance(args, basestring): raise ValueError( 'Execute expects an iterable of strings, not a string.') # The argparse module does not handle unicode args when run in Python 2 # because it uses str(x) even when type(x) is unicode. This sets itself up # for failure because it converts unicode strings back to byte strings which # will trigger ASCII codec exceptions. It works in Python 3 because str() is # equivalent to unicode() in Python 3. The next Pythonically magic and dirty # statement coaxes the Python 3 behavior out of argparse running in # Python 2. Doing it here ensures that the workaround is in place for # calliope argparse use cases. argparse.str = unicode if call_arg_complete: self._ArgComplete() if not args: args = sys.argv[1:] # help ... is the same as ... --help or ... --document=style=help. We use # --document=style=help to signal the metrics.Help() 'help' label in # actions.RenderDocumentAction().Action(). It doesn't matter if we append # to a command that already has --help or --document=style=... because the # first --help/--document from the left takes effect. Note that # `help ... --help` produces help for the help command itself. if args and args[0] == 'help' and '--help' not in args: args = args[1:] + ['--document=style=help'] # 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() # Set the command name in case an exception happens before the command name # is finished parsing. command_path_string = self.__name flag_collection = None argv = self._ConvertNonAsciiArgsToUnicode(args) try: args = self.__parser.parse_args(argv) command_path_string = '.'.join(args.command_path) if not args.calliope_command.IsUnicodeSupported(): self._EnforceAsciiArgs(argv) flag_collection = 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) properties.VALUES.SetInvocationValue( properties.VALUES.metrics.command_name, command_path_string, None) metrics.Commands(command_path_string, config.CLOUD_SDK_VERSION, flag_collection) for hook in self.__pre_run_hooks: hook.Run(command_path_string) resources = args.calliope_command.Run(cli=self, args=args) for hook in self.__post_run_hooks: hook.Run(command_path_string) # Preserve generator or static list resources. if isinstance(resources, types.GeneratorType): def _Yield(): """Activates generator exceptions.""" try: for resource in resources: yield resource except Exception as exc: # pylint: disable=broad-except self._HandleAllErrors(exc, command_path_string, flag_collection) return _Yield() return resources except Exception as exc: # pylint: disable=broad-except self._HandleAllErrors(exc, command_path_string, flag_collection) 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)
def Run(self, cli, args, pre_run_hooks=None, post_run_hooks=None): """Run this command with the given arguments. Args: cli: The cli.CLI object for this command line tool. args: The arguments for this command as a namespace. pre_run_hooks: [_RunHook], Things to run before the command. post_run_hooks: [_RunHook], Things to run after the command. Returns: The object returned by the module's Run() function. Raises: exceptions.Error: if thrown by the Run() function. """ command_path_string = '.'.join(self._path) # TODO(user): user-output-enabled was mostly needed for interactive # mode. There should still be the option to disable output (for things # like completion) but it can be cleaned up to be on by default. # Enable user output for CLI mode only if it is not explicitly set in the # properties (or given in the provided arguments that were just pushed into # the properties object). user_output_enabled = properties.VALUES.core.user_output_enabled.GetBool( ) set_user_output_property = user_output_enabled is None if set_user_output_property: properties.VALUES.core.user_output_enabled.Set(True) # Now that we have pushed the args, reload the settings so the flags will # take effect. These will use the values from the properties. old_user_output_enabled = log.SetUserOutputEnabled(None) old_verbosity = log.SetVerbosity(None) try: if pre_run_hooks: for hook in pre_run_hooks: hook.Run(command_path_string) def Http(**kwargs): # TODO(user) This check is required due to tests that use interactive # mode. Remove this check when all tests are converted to use cli mode. if hasattr(args, 'trace_token'): return core_cli.Http(cmd_path=command_path_string, trace_token=args.trace_token, **kwargs) else: return core_cli.Http(cmd_path=command_path_string, **kwargs) tool_context = self._config_hooks.load_context() last_group = None for context_filter in self._config_hooks.context_filters: last_group = context_filter(tool_context, Http, args) command_instance = self._common_type(cli=cli, context=tool_context, group=last_group, http_func=Http) def OutputFormatter(obj): command_instance.Display(args, obj) output_formatter = OutputFormatter def Format(obj): if not obj: return resource_printer.Print(obj, args.format or 'yaml', out=log.out) command_instance.format = Format if args.format: output_formatter = command_instance.format log.debug('Running %s with %s.', command_path_string, args) result = command_instance.Run(args) if properties.VALUES.core.user_output_enabled.GetBool(): output_formatter(result) if post_run_hooks: for hook in post_run_hooks: hook.Run(command_path_string) return result except exceptions.ExitCodeNoError as exc: msg = '({0}) {1}'.format(command_path_string, str(exc)) log.debug(msg, exc_info=sys.exc_info()) self._Exit(exc) except core_exceptions.Error as exc: msg = '({0}) {1}'.format(command_path_string, str(exc)) log.debug(msg, exc_info=sys.exc_info()) log.error(msg) self._Exit(exc) except Exception as exc: # Make sure any uncaught exceptions still make it into the log file. log.file_only_logger.debug(str(exc), exc_info=sys.exc_info()) raise finally: if set_user_output_property: properties.VALUES.core.user_output_enabled.Set(None) log.SetUserOutputEnabled(old_user_output_enabled) log.SetVerbosity(old_verbosity)
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:] for s in args: try: s.decode('ascii') except (UnicodeEncodeError, UnicodeError): try: s_printable = s.decode('utf-8') except (UnicodeEncodeError, UnicodeError): s_printable = repr(s) raise exceptions.InvalidStringException(s_printable) # Set the command name in case an exception happens before the command name # is finished parsing. command_path_string = self.__name named_configs.FLAG_OVERRIDE_STACK.AllocateFrame() properties.VALUES.PushInvocationValues() try: # 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.ReplaceTop( named_configs.AdhocConfigFlagParse(args), properties.PropertiesFile.Invalidate) args = self.__parser.parse_args(args) # -h|--help|--document are dispatched by parse_args and never get here. # In principle it's possible that the initial round of ad-hoc parsing of # --configuration would not agree with the later parse by argparse. The # following warning is intended to be dead code, but just in case... if named_configs.FLAG_OVERRIDE_STACK.Peek() != args.configuration: log.warn('Problem parsing --configration flag. Using named ' 'flag value --configuration=[{0}].'.format( named_configs.FLAG_OVERRIDE_STACK.Peek())) # 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) metrics.Commands(command_path_string, config.CLOUD_SDK_VERSION) 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, print_error=False) except core_exceptions.Error as exc: self._HandleKnownError(command_path_string, exc, print_error=True) except Exception as exc: if type(exc) in KNOWN_ERRORS: self._HandleKnownError(command_path_string, exc, print_error=True) else: # Make sure any uncaught exceptions still make it into the log file. exc_printable = self.SafeExceptionToString(exc) log.file_only_logger.debug(exc_printable, exc_info=sys.exc_info()) metrics.Error(command_path_string, exc) 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)