Example #1
0
    def _GenerateResourceArg(self):
        """Gets the flags to add to the parser that appear in the method path.

    Returns:
      {str, calliope.base.Argument}, A map of field name to argument.
    """
        args = []
        field_names = (self.method.request_collection.detailed_params
                       if self.method.request_collection else None)
        if not field_names:
            return args
        field_helps = arg_utils.FieldHelpDocs(self.method.GetRequestType())
        default_help = 'For substitution into: ' + self.method.detailed_path

        # Make a dedicated positional in addition to the flags for each part of
        # the URI path.
        arg = base.Argument(AutoArgumentGenerator.FLAT_RESOURCE_ARG_NAME,
                            nargs='?',
                            help='The GRI for the resource being operated on.')
        args.append(arg)

        for field in field_names:
            arg = base.Argument(
                '--' + field,
                metavar=resource_property.ConvertToAngrySnakeCase(field),
                category='RESOURCE',
                help=field_helps.get(field, default_help))
            args.append(arg)
        return args
Example #2
0
  def _FlagForMessageField(self, name, field, field_helps):
    """Gets a flag for a single field in a message.

    Args:
      name: The name of the field.
      field: The apitools field object.
      field_helps: {str: str}, A mapping of field name to help text.

    Returns:
      {str: str}, A mapping of field name to help text.
    """
    help_text = field_helps.get(field.name, None)
    if self._IsOutputField(help_text):
      return None
    variant = field.variant
    t = ArgumentGenerator.TYPES.get(variant, None)
    choices = None
    if variant == messages.Variant.ENUM:
      choices = field.type.names()
    return base.Argument(
        # TODO(b/38000796): Consider not using camel case for flags.
        '--' + name,
        metavar=resource_property.ConvertToAngrySnakeCase(field.name),
        category='MESSAGE',
        action='store',
        type=t,
        choices=choices,
        help=help_text,
    )
    def _GenerateResourceArg(self):
        """Generates the flags to add to the parser that appear in the method path.

    Returns:
      {str, calliope.base.Argument}, A map of field name to argument.
    """
        resource_args = self.resource_arg_info
        if not resource_args:
            return {}

        args = {}
        anchor_field = resource_args[-1].api_field

        for attributes in resource_args:
            # Don't generate any placeholder arguments for ignored fields.
            if not attributes.generate:
                continue
            is_anchor = attributes.api_field == anchor_field
            is_positional = is_anchor and not self.method.IsList()

            arg_name = attributes.arg_name
            arg = base.Argument(
                arg_name if is_positional else '--' + arg_name,
                metavar=resource_property.ConvertToAngrySnakeCase(
                    attributes.arg_name),
                completer=attributes.completer,
                help=attributes.help_text)
            if is_anchor and not is_positional:
                arg.kwargs['required'] = True
            args[arg.name] = arg
        return args
Example #4
0
def GenerateFlag(field, attributes, fix_bools=True, category=None):
    """Generates a flag for a single field in a message.

  Args:
    field: The apitools field object.
    attributes: yaml_command_schema.Argument, The attributes to use to
      generate the arg.
    fix_bools: True to generate boolean flags as switches that take a value or
      False to just generate them as regular string flags.
    category: The help category to put the flag in.

  Returns:
    calliope.base.Argument, The generated argument.
  """
    variant = field.variant if field else None
    t = attributes.type or TYPES.get(variant, None)

    choices = None
    if attributes.choices is not None:
        choices = sorted(attributes.choices.keys())
    elif variant == messages.Variant.ENUM:
        choices = [
            EnumNameToChoice(name) for name in sorted(field.type.names())
        ]

    action = attributes.action
    if fix_bools and not action and variant == messages.Variant.BOOL:
        action = 'store_true'

    # Note that a field will never be a message at this point, always a scalar.
    # pylint: disable=g-explicit-bool-comparison, only an explicit False should
    # override this, None just means to do the default.
    if (field and field.repeated) and attributes.repeated != False:
        t = arg_parsers.ArgList(element_type=t, choices=choices)
    name = attributes.arg_name
    arg = base.Argument(
        # TODO(b/38000796): Consider not using camel case for flags.
        name if attributes.is_positional else '--' + name,
        category=category if not attributes.is_positional else None,
        action=action,
        completer=attributes.completer,
        help=attributes.help_text,
        hidden=attributes.hidden,
    )
    if attributes.default is not None:
        arg.kwargs['default'] = attributes.default
    if action != 'store_true':
        # For this special action type, it won't accept a bunch of the common
        # kwargs, so we can only add them if not generating a boolean flag.
        metavar = attributes.metavar or name
        arg.kwargs['metavar'] = resource_property.ConvertToAngrySnakeCase(
            metavar.replace('-', '_'))
        arg.kwargs['type'] = t
        arg.kwargs['choices'] = choices

    if not attributes.is_positional:
        arg.kwargs['required'] = attributes.required
    return arg
    def _GenerateResourceArg(self):
        """Gets the flags to add to the parser that appear in the method path.

    Returns:
      {str, calliope.base.Argument}, A map of field name to argument.
    """
        field_names = self.method.ResourceFieldNames()
        if not field_names:
            return {}

        message = self.method.GetRequestType()
        field_helps = _FieldHelpDocs(message)
        default_help = 'For substitution into: ' + self.method.detailed_path

        args = {}
        if not self.clean_surface:
            # Make a dedicated positional in addition to the flags for each part of
            # the URI path.
            args[ArgumentGenerator.FLAT_RESOURCE_ARG_NAME] = base.Argument(
                ArgumentGenerator.FLAT_RESOURCE_ARG_NAME,
                nargs='?',
                help='The GRI for the resource being operated on.')

        anchor_arg_name = self._GetArgAttributes(field_names[-1],
                                                 required=True).arg_name

        for field in field_names:
            attributes = self._GetArgAttributes(field,
                                                field_helps,
                                                default_help,
                                                required=True)
            param = attributes.arg_name
            # If the request params match, this means this method takes the same
            # params as the get method and so the last item should be positional.
            # If it doesn't (like for a list command) then we are omitting the last
            # arg so all other should be flags and none should be made positional.
            is_positional = (self.clean_surface and param == anchor_arg_name
                             and self.method.request_params_match_resource)
            args[param] = base.Argument(
                param if is_positional else '--' + param,
                metavar=resource_property.ConvertToAngrySnakeCase(param),
                # TODO(b/64147277): Usage a proper arg group to make the positional
                # and flags for the resource argument show up together.
                # category=(None if param == self.anchor_arg_name and
                # self.is_positional else 'RESOURCE'),
                type=attributes.type or str,
                completer=attributes.completer,
                help=attributes.help_text)
            if (self.clean_surface and param == anchor_arg_name
                    and not is_positional):
                args[param].kwargs['required'] = True
        return args
Example #6
0
  def ResourceFlags(self):
    """Get the arguments to add to the parser that appear in the method path.

    Returns:
      {str, calliope.base.Argument}, A map of field name to argument.
    """
    message = self.method.GetRequestType()
    field_helps = self._FieldHelpDocs(message)
    default_help = 'For substitution into: ' + self.method.detailed_path

    args = {}
    for param in set(self.method.ResourceFieldNames()):
      args[param] = base.Argument(
          # TODO(b/38000796): Consider not using camel case for flags.
          '--' + param,
          metavar=resource_property.ConvertToAngrySnakeCase(param),
          category='RESOURCE',
          type=str,
          help=field_helps.get(param, default_help))
    return args
    def _GenerateMessageFieldFlag(self, attributes, prefix, field):
        """Gets a flag for a single field in a message.

    Args:
      attributes: yaml_command_schema.Argument, The attributes to use to
        generate the arg.
      prefix: str, The flag prefix for the sub-message being generated.
      field: The apitools field object.

    Returns:
      calliope.base.Argument, The generated argument.
    """
        if _IsOutputField(attributes.help_text):
            return None
        variant = field.variant
        choices = None
        if variant == messages.Variant.ENUM:
            choices = field.type.names()
        t = attributes.type or _TYPES.get(variant, None)
        # Note that a field will never be a message at this point, always a scalar.
        if field.repeated:
            t = arg_parsers.ArgList(element_type=t, choices=choices)
        name = attributes.arg_name
        arg = base.Argument(
            # TODO(b/38000796): Consider not using camel case for flags.
            name if attributes.is_positional else '--' + name,
            metavar=resource_property.ConvertToAngrySnakeCase(
                name[len(prefix):]),
            category=None if attributes.is_positional else 'MESSAGE',
            action=attributes.action,
            type=t,
            default=attributes.default,
            choices=choices,
            completer=attributes.completer,
            help=attributes.help_text,
            hidden=attributes.hidden,
        )
        if not attributes.is_positional:
            arg.kwargs['required'] = attributes.required
        return arg
Example #8
0
    def _GenerateResourceArg(self):
        """Generates the flags to add to the parser that appear in the method path.

    Returns:
      {str, calliope.base.Argument}, A map of field name to argument.
    """
        resource_args = self.resource_arg_info
        if not resource_args:
            return {}

        args = {}
        anchor_field = resource_args[-1].api_field

        for attributes in resource_args:
            # Don't generate any placeholder arguments for ignored fields.
            if not attributes.generate:
                continue
            is_anchor = attributes.api_field == anchor_field
            # pylint: disable=g-explicit-bool-comparison, only an explicit False
            # should, None just means to do the default.
            # The anchor arg is positional unless explicitly overridden by the
            # attributes or for list commands (where everything should be a flag since
            # the parent resource collection is being used).
            is_positional = (is_anchor
                             and not (attributes.is_positional == False
                                      or self.method.IsList()))

            arg_name = attributes.arg_name
            arg = base.Argument(
                arg_name if is_positional else '--' + arg_name,
                metavar=resource_property.ConvertToAngrySnakeCase(
                    attributes.arg_name),
                completer=attributes.completer,
                help=attributes.help_text,
                hidden=attributes.hidden)

            if is_anchor and not is_positional and not attributes.fallback:
                arg.kwargs['required'] = True
            args[arg.name] = arg
        return args
Example #9
0
def GenerateFlag(field, attributes, fix_bools=True, category=None):
    """Generates a flag for a single field in a message.

  Args:
    field: The apitools field object.
    attributes: yaml_command_schema.Argument, The attributes to use to
      generate the arg.
    fix_bools: True to generate boolean flags as switches that take a value or
      False to just generate them as regular string flags.
    category: The help category to put the flag in.

  Raises:
    ArgumentGenerationError: When an argument could not be generated from the
      API field.

  Returns:
    calliope.base.Argument, The generated argument.
  """
    variant = field.variant if field else None
    t = attributes.type or TYPES.get(variant, None)

    choices = None
    if attributes.choices is not None:
        choice_map = {c.arg_value: c.help_text for c in attributes.choices}
        # If help text is provided, give a choice map. Otherwise, just use the
        # choice values.
        choices = (choice_map
                   if any(choice_map.values()) else sorted(choice_map.keys()))
    elif variant == messages.Variant.ENUM:
        choices = [
            EnumNameToChoice(name) for name in sorted(field.type.names())
        ]

    action = attributes.action
    if t == bool and fix_bools and not action:
        # For boolean flags, we want to create a flag with action 'store_true'
        # rather than a flag that takes a value and converts it to a boolean. Only
        # do this if not using a custom action.
        action = 'store_true'
    # Default action is store if one was not provided.
    action = action or 'store'

    # pylint: disable=g-explicit-bool-comparison, only an explicit False should
    # override this, None just means to do the default.
    repeated = (field and field.repeated) and attributes.repeated != False

    if repeated:
        if action != 'store':
            raise ArgumentGenerationError(
                field.name,
                'The field is repeated but is but is using a custom action. You might'
                ' want to set repeated: False in your arg spec.')
        if t:
            # A special ArgDict wrapper type was given, bind it to the message so it
            # can generate the message from the key/value pairs.
            if isinstance(t, RepeatedMessageBindableType):
                action = t.Action()
                t = t.GenerateType(field.type)
            # If a simple type was provided, just use a list of that type (even if it
            # is a message). The type function will be responsible for converting to
            # the correct value. If type is an ArgList or ArgDict, don't try to wrap
            # it.
            elif not isinstance(t, arg_parsers.ArgList):
                t = arg_parsers.ArgList(element_type=t, choices=choices)
                # Don't register the choices on the argparse arg because it is validated
                # by the ArgList.
                choices = None
    elif isinstance(t, RepeatedMessageBindableType):
        raise ArgumentGenerationError(
            field.name, 'The given type can only be used on repeated fields.')

    if field and not t and action == 'store' and not attributes.processor:
        # The type is unknown and there is no custom action or processor, we don't
        # know what to do with this.
        raise ArgumentGenerationError(
            field.name,
            'The field is of an unknown type. You can specify a type '
            'function or a processor to manually handle this argument.')

    name = attributes.arg_name
    arg = base.Argument(
        name if attributes.is_positional else '--' + name,
        category=category if not attributes.is_positional else None,
        action=action,
        completer=attributes.completer,
        help=attributes.help_text,
        hidden=attributes.hidden,
    )
    if attributes.default is not None:
        arg.kwargs['default'] = attributes.default
    if action != 'store_true':
        # For this special action type, it won't accept a bunch of the common
        # kwargs, so we can only add them if not generating a boolean flag.
        metavar = attributes.metavar or name
        arg.kwargs['metavar'] = resource_property.ConvertToAngrySnakeCase(
            metavar.replace('-', '_'))
        arg.kwargs['type'] = t
        arg.kwargs['choices'] = choices

    if not attributes.is_positional:
        arg.kwargs['required'] = attributes.required
    return arg
    def _GenerateMessageFieldFlag(self, attributes, prefix, field):
        """Gets a flag for a single field in a message.

    Args:
      attributes: yaml_command_schema.Argument, The attributes to use to
        generate the arg.
      prefix: str, The flag prefix for the sub-message being generated.
      field: The apitools field object.

    Returns:
      calliope.base.Argument, The generated argument.
    """
        if _IsOutputField(attributes.help_text):
            return None
        variant = field.variant
        choices = None
        if attributes.choices is not None:
            choices = attributes.choices.keys()
        elif variant == messages.Variant.ENUM:
            choices = [_EnumNameToChoice(name) for name in field.type.names()]
        t = attributes.type or _TYPES.get(variant, None)
        action = attributes.action
        if not action:
            if variant == messages.Variant.BOOL and self.clean_surface:
                # Create proper boolean flags for declarative surfaces
                action = 'store_true'
            else:
                action = 'store'

        # Note that a field will never be a message at this point, always a scalar.
        if field.repeated:
            t = arg_parsers.ArgList(element_type=t, choices=choices)

        name = attributes.arg_name
        metavar = name
        if metavar.startswith(prefix):
            metavar = metavar[len(prefix):]
        category = None
        if self.arg_info is None and not attributes.is_positional:
            category = 'MESSAGE'
        arg = base.Argument(
            # TODO(b/38000796): Consider not using camel case for flags.
            name if attributes.is_positional else '--' + name,
            category=category,
            action=action,
            completer=attributes.completer,
            help=attributes.help_text,
            hidden=attributes.hidden,
        )
        if attributes.default is not None:
            arg.kwargs['default'] = attributes.default
        if action != 'store_true':
            # For this special action type, it won't accept a bunch of the common
            # kwargs, so we can only add them if not generating a boolean flag.
            arg.kwargs['metavar'] = resource_property.ConvertToAngrySnakeCase(
                metavar.replace('-', '_'))
            arg.kwargs['type'] = t
            arg.kwargs['choices'] = choices

        if not attributes.is_positional:
            arg.kwargs['required'] = attributes.required
        return arg