Example #1
0
def _AddFlagsFileFlags(inject, flags_file, parent_locations=None):
  """Recursively append the flags file flags to inject."""

  flag = calliope_base.FLAGS_FILE_FLAG.name

  if parent_locations and parent_locations.FileInStack(flags_file):
    raise parser_errors.ArgumentError(
        '{} recursive reference ({}).'.format(flag, parent_locations))

  # Load the YAML flag:value dict or list of dicts. List of dicts allows
  # flags to be specified more than once.

  if flags_file == '-':
    contents = sys.stdin.read()
  elif not os.path.exists(flags_file):
    raise parser_errors.ArgumentError(
        '{} [{}] not found.'.format(flag, flags_file))
  else:
    contents = files.ReadFileContents(flags_file)
  data = yaml.load(contents, location_value=True)
  group = data if isinstance(data, list) else [data]

  # Generate the list of args to inject.

  for member in group:

    if not isinstance(member.value, dict):
      raise parser_errors.ArgumentError(
          '{}:{}: {} file must contain a dictionary or list of dictionaries '
          'of flags.'.format(flags_file, member.lc.line + 1, flag))

    for arg, obj in six.iteritems(member.value):

      line_col = obj.lc
      value = obj.value

      if arg == flag:
        # The flags-file YAML arg value can be a path or list of paths.
        file_list = obj.value if isinstance(obj.value, list) else [obj.value]
        for path in file_list:
          locations = _ArgLocations(arg, flags_file, line_col, parent_locations)
          _AddFlagsFileFlags(inject, path, locations)
        continue
      if isinstance(value, (type(None), bool)):
        separate_value_arg = False
      elif isinstance(value, (list, dict)):
        separate_value_arg = True
      else:
        separate_value_arg = False
        arg = '{}={}'.format(arg, value)
      inject.append(_FLAG_FILE_LINE_NAME)
      inject.append(_ArgLocations(arg, flags_file, line_col, parent_locations))
      inject.append(arg)
      if separate_value_arg:
        # Add the already lexed arg and with one swoop we sidestep all flag
        # value and command line interpreter quoting issues. The ArgList and
        # ArgDict arg parsers have been adjusted to handle this.
        inject.append(value)
Example #2
0
    def __call__(self, parser, namespace, values, option_string=None):
      """Render a help document according to the style in values.

      Args:
        parser: The ArgParse object.
        namespace: The ArgParse namespace.
        values: The --document flag ArgDict() value:
          style=STYLE
            The output style. Must be specified.
          title=DOCUMENT TITLE
            The document title.
          notes=SENTENCES
            Inserts SENTENCES into the document NOTES section.
        option_string: The ArgParse flag string.

      Raises:
        parser_errors.ArgumentError: For unknown flag value attribute name.
      """
      base.LogCommand(parser.prog, namespace)
      if default_style:
        # --help
        metrics.Loaded()
      style = default_style
      notes = None
      title = None

      for attributes in values:
        for name, value in six.iteritems(attributes):
          if name == 'notes':
            notes = value
          elif name == 'style':
            style = value
          elif name == 'title':
            title = value
          else:
            raise parser_errors.ArgumentError(
                'Unknown document attribute [{0}]'.format(name))

      if title is None:
        title = command.dotted_name

      metrics.Help(command.dotted_name, style)
      # '--help' is set by the --help flag, the others by gcloud <style> ... .
      if style in ('--help', 'help', 'topic'):
        style = 'text'
      md = io.StringIO(markdown.Markdown(command))
      out = (io.StringIO() if console_io.IsInteractive(output=True)
             else None)

      if style == 'linter':
        meta_data = GetCommandMetaData(command)
      else:
        meta_data = None
      render_document.RenderDocument(style, md, out=out or log.out, notes=notes,
                                     title=title, command_metadata=meta_data)
      metrics.Ran()
      if out:
        console_io.More(out.getvalue())

      sys.exit(0)
Example #3
0
    def Run(self, args):
        catalog_ref = args.CONCEPTS.catalog.Parse()
        api_client = product_util.ProductsClient()

        # TODO(b/69863480) Remove this once optional modal groups are fixed
        if (args.bounds
                or args.category) and not (args.bounds and args.category):
            missing = 'bounds' if not args.bounds else 'category'
            raise parser_errors.ArgumentError(
                'Missing [{}]. Both category and bounds must be specified if '
                'either is provided'.format(missing))
        ref_image = api_client.BuildRefImage(
            args.product_id,
            args.image_path,
            bounds=api_client.BuildBoundingPoly(args.bounds),
            product_category=args.category)
        created_image = api_client.CreateRefImage(ref_image,
                                                  catalog_ref.RelativeName())
        log.CreatedResource(created_image.name, kind='ReferenceImage')
        return created_image
Example #4
0
    def Run(self, args):
        config = _LoadConfig(args.config)
        root_dir = config['root_dir']
        changed_config = False

        if args.api_discovery_doc:
            if not os.path.isfile(args.api_discovery_doc):
                raise regen_utils.DiscoveryDocError('File not found {}'.format(
                    args.api_discovery_doc))
            if len(args.api) != 1:
                raise parser_errors.ArgumentError(
                    'Can only specify one api when discovery doc is provided.')

            match = re.match(_API_REGEX, args.api[0])
            if not match:
                raise regen_utils.DiscoveryDocError(
                    'Api name must match {} pattern when discovery doc '
                    'is specified'.format(_API_REGEX))

            api_name, api_version = match.group(1), match.group(2)
            if api_name not in config['apis']:
                log.warning('No such api %s in config, adding...', api_name)
                config['apis'][api_name] = {api_version: {'discovery_doc': ''}}
                changed_config = True
            elif api_version not in config['apis'][api_name]:
                log.warning('No such api version %s in config, adding...',
                            api_version)
                config['apis'][api_name][api_version] = {'discovery_doc': ''}
                changed_config = True

            api_version_config = config['apis'].get(api_name).get(
                api_version, {})
            discovery_doc = api_name + '_' + api_version + '.json'
            new_discovery_doc = os.path.realpath(args.api_discovery_doc)
            old_discovery_doc = os.path.realpath(
                os.path.join(args.base_dir, root_dir, discovery_doc))

            if new_discovery_doc != old_discovery_doc:
                log.status.Print('Copying in {}'.format(new_discovery_doc))
                shutil.copyfile(new_discovery_doc, old_discovery_doc)

            if api_version_config['discovery_doc'] != discovery_doc:
                changed_config = True
                api_version_config['discovery_doc'] = discovery_doc

            regenerate_list = [(match.group(1), match.group(2),
                                api_version_config)]
        else:
            regex_patern = '|'.join(map(fnmatch.translate, args.api))
            regenerate_list = [
                (api_name, api_version, api_config)
                for api_name, api_version_config in six.iteritems(
                    config['apis'])
                for api_version, api_config in six.iteritems(
                    api_version_config)
                if re.match(regex_patern, api_name + '/' + api_version)
            ]

        if not regenerate_list:
            raise regen_utils.UnknownApi(
                'api [{api_name}] not found in "apis" section of '
                '{config_file}. Use [gcloud meta apis list] to see available apis.'
                .format(api_name=','.join(args.api), config_file=args.config))

        base_dir = args.base_dir or os.path.dirname(
            os.path.dirname(googlecloudsdk.__file__))
        for api_name, api_version, api_config in sorted(regenerate_list):
            log.status.Print('Generating {} {} from {}'.format(
                api_name, api_version,
                os.path.join(root_dir, api_config['discovery_doc'])))
            generate.GenerateApi(base_dir, root_dir, api_name, api_version,
                                 api_config)
            generate.GenerateResourceModule(base_dir, root_dir, api_name,
                                            api_version,
                                            api_config['discovery_doc'],
                                            api_config.get('resources', {}))

        generate.GenerateApiMap(base_dir, root_dir, config['apis'])

        # Now that everything passed, config can be updated if needed.
        if changed_config:
            log.warning('Updated %s', args.config)
            with files.FileWriter(args.config) as stream:
                ruamel.yaml.round_trip_dump(config, stream)
Example #5
0
 def DeprecationFunc(value):
     if show_message(value):
         if removed:
             raise parser_errors.ArgumentError(add_help.message)
         else:
             log.warn(add_help.message)
 def testArgumentErrorUnbalanced(self):
     e = parser_errors.ArgumentError('abc [{info] xyz', info='TEST INFO')
     self.assertEqual('abc [{info] xyz', str(e))
 def testArgumentErrorBadSpec(self):
     e = parser_errors.ArgumentError('abc [{:3}] xyz')
     self.assertEqual('abc [{:3}] xyz', str(e))
 def testArgumentErrorUnknownKey(self):
     e = parser_errors.ArgumentError('abc [{info}] xyz', data='TEST INFO')
     self.assertEqual('abc [{info}] xyz', str(e))
 def testArgumentErrorOK(self):
     e = parser_errors.ArgumentError('abc [{info}] xyz', info='TEST INFO')
     self.assertEqual('abc [TEST INFO] xyz', str(e))
def CheckRangeLegacyModeOrRaise(args):
    """Checks for range being used with incompatible mode and raises an error."""
    if args.range is not None:
        if ((args.subnet_mode and args.subnet_mode != 'legacy')
                or (args.mode and args.mode != 'legacy')):
            raise parser_errors.ArgumentError(_RANGE_NON_LEGACY_MODE_ERROR)
  def error(self, message='', context=None, reproduce=False):
    """Overrides argparse.ArgumentParser's .error(message) method.

    Specifically, it avoids reprinting the program name and the string
    "error:".

    Args:
      message: str, The error message to print.
      context: _ErrorContext, An error context with affected parser.
      reproduce: bool, Reproduce a previous call to this method from context.
    """
    if reproduce and context:
      # Reproduce a previous call to this method from the info in context.
      message = context.message
      parser = context.parser
      error = context.error
      if not error:
        error = parser_errors.ArgumentError(message, parser=self)
    else:
      if context:
        message = context.message
        parser = context.parser
        error = context.error
      else:
        if 'Invalid choice:' in message:
          exc = parser_errors.UnrecognizedArgumentsError
        else:
          exc = parser_errors.ArgumentError
        if message:
          message = re.sub(r"\bu'", "'", message)
        error = exc(message, parser=self)
        parser = self
      if ('_ARGCOMPLETE' not in os.environ and
          not isinstance(error, parser_errors.DetailedArgumentError) and
          (
              self._probe_error or
              'Invalid choice' in message or
              'unknown parser' in message
          )
         ):
        if 'unknown parser' in message:
          return
        if self._probe_error and 'expected one argument' in message:
          return
        # Save this context for later. We may be able to deduce a better error
        # message. For instance, argparse might complain about an invalid
        # command choice 'flag-value' for '--unknown-flag flag-value', but
        # with a little finagling in parse_known_args() we can verify that
        # '--unknown-flag' is in fact an unknown flag and error out on that.
        self._SetErrorContext(context or _ErrorContext(message, parser, error))
        return

    # Ignore errors better handled by validate_specified_args().
    if '_ARGCOMPLETE' not in os.environ:
      if re.search('too few arguments', message):
        return
      if (re.search('arguments? .* required', message) and
          not re.search('in dict arg but not provided', message)):
        return

    parser.ReportErrorMetrics(error, message)

    # No need to output help/usage text if we are in completion mode. However,
    # we do need to populate group/command level choices. These choices are not
    # loaded when there is a parser error since we do lazy loading.
    if '_ARGCOMPLETE' in os.environ:
      # pylint:disable=protected-access
      if self._calliope_command._sub_parser:
        self._calliope_command.LoadAllSubElements()
    else:
      message = console_attr.SafeText(message)
      log.error('({prog}) {message}'.format(prog=self.prog, message=message))
      # multi-line message means hints already added, no need for usage.
      # pylint:disable=protected-access
      if '\n' not in message:
        argparse._sys.stderr.write(self._calliope_command.GetUsage())

    self.exit(2, exception=error)
Example #12
0
def CheckRangeLegacyModeOrRaise(args):
  """Checks for range being used with incompatible mode and raises an error."""
  if args.IsSpecified('range') and args.IsSpecified(
      'subnet_mode') and args.subnet_mode != 'legacy':
    raise parser_errors.ArgumentError(_RANGE_NON_LEGACY_MODE_ERROR)
Example #13
0
def CheckIncompatibleFlagsOrRaise(args):
    """Checks for incompatible flags in arguments and raises an error if found."""
    if (HasReplaceAdvertisementFlags(args)
            and HasIncrementalAdvertisementFlags(args)):
        raise parser_errors.ArgumentError(
            _INCOMPATIBLE_INCREMENTAL_FLAGS_ERROR_MESSAGE)