Пример #1
0
  def link_group(self, group):
    """Links a schema group object.

    Args:
      group: schema group object
    """

    group.interface = self.get_obj(group.desc.type_name)

    options = group.desc.options.Extensions[wdl_options_pb2.implconfig]

    parent_interface = self.get_obj(group.desc.parent.parent.full_name)

    for mapping in options.trait_mapping:
      from_component = parent_interface.component_list.by_name(
          getattr(mapping, 'from'))
      to_component = group.interface.component_list.by_name(mapping.to)
      if not from_component or not to_component:
        raise exception.InvalidUsage('Implements mapping for %s is invalid.' %
                                     parent_interface.full_name)
      ref = schema.GroupComponentRef(to_component.base_name,
                                     to_component.number, '')
      ref.source_component = from_component
      group.component_list.append(ref)

    if options.HasField('min_version'):
      group.min_version = options.min_version
Пример #2
0
 def get_extends(self, extends_name):
   extends = None
   if extends_name:
     extends = self.get_obj(extends_name)
     if not extends:
       raise exception.InvalidUsage('Cannot find extended object %s' %
                                    (extends_name))
   return extends
Пример #3
0
  def link_enum(self, enum):
    """Parses the protobuf enum descriptor turns into a Google Weave Enum.

    Args:
      enum: A protobuf enum description to add to schema

    Raises:
      InvalidType: Encountered an invalid type while linking
      DuplicateObject: Duplicate enum value pair encountered
      InvalidUsage: Option used in an invalid way
    """

    options = enum.desc.options.Extensions[wdl_options_pb2.enumopts]
    enum_pairs = enum.pair_list

    if self.is_common(enum.full_name):
      self.link_common_enum(enum)
    elif (not enum.desc.parent or not isinstance(
        self.get_obj(enum.desc.parent.full_name),
        schema.StructEnumCollectionBase)):
      raise exception.InvalidType(
          ('Unexpected enum %s defined outside a typespace or trait' % enum))

    if options is not None:
      if options.compatibility.HasField('min_version'):
        enum.min_version = options.compatibility.min_version
      if options.compatibility.HasField('max_version'):
        enum.max_version = options.compatibility.max_version

    for value in enum.desc.values.values():
      description = self.parse_comments(value)
      pair_opts = value.options.Extensions[wdl_options_pb2.enumvalue]

      value.full_name.replace(
          inflection.underscore(enum.base_name).decode('utf-8').upper() + '_',
          '')

      enum_pair = schema.EnumPair(value.full_name, value.number, description)
      enum_pair.source_file = enum.source_file

      if pair_opts is not None:
        if pair_opts.compatibility.HasField('min_version'):
          enum_pair.min_version = pair_opts.compatibility.min_version
        if pair_opts.compatibility.HasField('max_version'):
          enum_pair.max_version = pair_opts.compatibility.max_version

      try:
        enum_pairs.append(enum_pair)
      except exception.DuplicateObject:
        pass

    enum.is_bitmask = options.bitmask

    if options.extends:
      raise exception.InvalidUsage('Extending enums is not yet supported.')
Пример #4
0
  def validate_extendable(self, options, fields, parent_fields_dict=None):
    """Checks that the fields extend the parent fields.

    Args:
      options: The descriptor options.
      fields: The fields to check.
      parent_fields_dict: the parent fields to check against.
    """

    if options.extendable:
      if (options.reserved_tag_min <= 0 or options.reserved_tag_max <= 1 or
          options.reserved_tag_max <= options.reserved_tag_min):
        raise exception.InvalidUsage('Extendable options are invalid')
      for field in fields:
        if (parent_fields_dict is not None and
            field.base_name in parent_fields_dict):
          continue  # Ignore fields that are in parent
        if (field.number > options.reserved_tag_max or
            field.number < options.reserved_tag_min):
          raise exception.InvalidUsage(
              'Field %s in %s number %d is outside reserved range. %d-%d' %
              (field.base_name, field.parent.full_name, field.number,
               options.reserved_tag_min, options.reserved_tag_max))
Пример #5
0
  def link_resource_component(self, component):
    """Link and initialize an nwv resource component.

    Args:
      component: Uninitialized component objcet
    """

    options = component.desc.options
    if options.HasExtension(wdl_options_pb2.traitinst):
      instance_id = options.Extensions[wdl_options_pb2.traitinst].instance
      component.instance_id = instance_id
    if not options.HasExtension(wdl_options_pb2.traitconfig):
      raise exception.InvalidUsage(
          'Trait config missing on {}. Every trait instance '
          'component must define trait config options.'.format(
              component.full_name))
    config_options = options.Extensions[wdl_options_pb2.traitconfig]
    component.published_by = schema.ResourceComponent.PublishedBy(
        config_options.published_by)
    if component.published_by == schema.ResourceComponent.PublishedBy.SELF:
      if not config_options.HasField('proxied'):
        raise exception.InvalidUsage(
            'Trait component {} is published by SELF but does not '
            'explicitly define proxied.'.format(component.full_name))
    elif (component.published_by ==
          schema.ResourceComponent.PublishedBy.EXTERNAL):
      if not config_options.HasField('subscribed'):
        raise exception.InvalidUsage(
            'Trait component {} is published by EXTERNAL but does '
            'not explicitly define subscribed.'.format(component.full_name))
    component.subscribed = config_options.subscribed
    component.proxied = config_options.proxied
    component.trait = self.get_obj(component.desc.type_name)

    if config_options.HasField('min_version'):
      component.min_version = config_options.min_version

    refinement_options = config_options.prop_refinement
    for refinement_option in refinement_options:
      prop_name = refinement_option.property
      prop = component.trait.state_list.by_name(prop_name)
      if not prop:
        raise exception.InvalidType('Property {} does not exist on trait {}'
                                    .format(prop_name, component.full_name))
      refinement = component.property_refinements[
          prop_name] = schema.FieldRefinement(prop)
      refinement.implemented = not refinement_option.unimplemented
      field_desc = refinement.field.desc
      field_type = WRAPPER_TYPES.get(field_desc.type_name, field_desc.type)
      if refinement_option.initial_bool_value:
        if field_type != field_desc.TYPE_BOOL:
          raise exception.InvalidType(
              'Inital value for for {} on {} is type {}, expected {}'.format(
                  prop_name, component.full_name, field_desc.type, 'BOOL'))
        refinement.initial_value = refinement_option.initial_bool_value
      if refinement_option.initial_int_value:
        if field_type not in (field_desc.TYPE_INT32, field_desc.TYPE_INT64):
          raise exception.InvalidType(
              'Inital value for for {} on {} is type {}, expected {}'.format(
                  prop_name, component.full_name, field_desc.type,
                  'INT32 or INT64'))
        refinement.initial_value = refinement_option.initial_int_value
      if refinement_option.initial_uint_value:
        if field_type not in (field_desc.TYPE_UINT32, field_desc.TYPE_UINT64):
          raise exception.InvalidType(
              'Inital value for for {} on {} is type {}, expected {}'.format(
                  prop_name, component.full_name, field_desc.type,
                  'UINT32 or UINT64'))
        refinement.initial_value = refinement_option.initial_uint_value
      if refinement_option.initial_number_value:
        if field_type not in (field_desc.TYPE_FLOAT, field_desc.TYPE_DOUBLE):
          raise exception.InvalidType(
              'Inital value for for {} on {} is type {}, expected {}'.format(
                  prop_name, component.full_name, field_desc.type,
                  'FLOAT or DOUBLE'))
        refinement.initial_value = refinement_option.initial_number_value
      if refinement_option.initial_string_value:
        if field_type != field_desc.TYPE_STRING:
          raise exception.InvalidType(
              'Inital value for for {} on {} is type {}, expected {}'.format(
                  prop_name, component.full_name, field_desc.type, 'STRING'))
        refinement.initial_value = refinement_option.initial_string_value
      if refinement_option.initial_bytes_base16_value:
        if field_type != field_desc.TYPE_BYTES:
          raise exception.InvalidType(
              'Inital value for for {} on {} is type {}, expected {}'.format(
                  prop_name, component.full_name, field_desc.type, 'BYTES'))
        value = refinement_option.initial_bytes_base16_value
        refinement.initial_bytes_base16_value = value
      if refinement_option.initial_resource_id_value:
        if field_desc.type_name != '.weave.common.ResourceId':
          raise exception.InvalidType(
              'Inital value for for {} on {} is type {}, expected {}'.format(
                  prop_name, component.full_name, field_desc.component,
                  'weave.common.ResourceId'))
        refinement.initial_value = refinement_option.initial_resource_id_value
      if refinement_option.initial_duration_value:
        if field_desc.type_name != '.google.protobuf.Duration':
          raise exception.InvalidType(
              'Inital value for for {} on {} is type {}, expected {}'.format(
                  prop_name, component.full_name, field_desc.type_name,
                  'google.protobuf.Duration'))
        refinement.initial_value = [{
            'seconds': o.seconds,
            'nanos': o.nanos
        } for o in refinement_option.initial_duration_value]
      if refinement_option.initial_timestamp_value:
        if field_desc.type_name != '.google.protobuf.Timestamp':
          raise exception.InvalidType(
              'Inital value for for {} on {} is type {}, expected {}'.format(
                  prop_name, component.full_name, field_desc.type_name,
                  'google.protobuf.Timestamp'))
        refinement.initial_value = [{
            'seconds': o.seconds,
            'nanos': o.nanos
        } for o in refinement_option.initial_timestamp_value]
      if refinement_option.initial_enum_value_name:
        if field_type != field_desc.TYPE_ENUM:
          raise exception.InvalidType(
              'Inital value for for {} on {} is type {}, expected {}'.format(
                  prop_name, component.full_name, field_desc.type_name, 'ENUM'))
        refinement.initial_value = refinement_option.initial_enum_value_name
      if refinement_option.initial_struct_value:
        raise exception.InvalidUsage(
            'Component {} defines an initial value; initial values for'
            ' structs is not implemented.'.format(component.full_name))

      # Every initial value option is an array
      # Flatten the array if the target property is not an array
      if (refinement.initial_value and
          field_desc.label != field_desc.LABEL_REPEATED):
        if len(refinement.initial_value) > 1:
          raise exception.InvalidType(
              'Array of initial values given for {}, which is not'
              ' an array'.format(component.full_name))
        refinement.initial_value = refinement.initial_value[0]
Пример #6
0
  def link_field(self, field):
    """Links a schema field object.

    Args:
        field: Unintialized schema field object
    """

    options = None
    if field.desc.options.HasExtension(wdl_options_pb2.prop):
      options = field.desc.options.Extensions[wdl_options_pb2.prop]
    elif field.desc.options.HasExtension(wdl_options_pb2.param):
      options = field.desc.options.Extensions[wdl_options_pb2.param]

    parent_writable = True
    if field.desc.parent.options.HasExtension(wdl_options_pb2.properties):
      props = field.desc.parent.options.Extensions[wdl_options_pb2.properties]
      if props.HasField('writable'):
        parent_writable = (
            wdl_options_pb2.WriteAccess.Name(props.writable) == 'READ_WRITE')

    field.objc_class_prefix = field.desc.file.options.objc_class_prefix
    field.java_outer_classname = field.desc.file.options.java_outer_classname
    field.source_file = field.desc.file.name
    field.is_oneof = field.desc.is_oneof()
    if options:
      field.is_nullable = options.nullable

    field.writable = parent_writable
    if field.desc.options.HasExtension(wdl_options_pb2.prop):
      props = field.desc.options.Extensions[wdl_options_pb2.prop]
      if options.HasField('writable'):
        field.writable = (
            wdl_options_pb2.WriteAccess.Name(props.writable) == 'READ_WRITE')
      field.is_optional = options.optional
      field.is_ephemeral = options.ephemeral

    if options is not None:
      if options.compatibility.HasField('min_version'):
        field.min_version = options.compatibility.min_version
      if options.compatibility.HasField('max_version'):
        field.max_version = options.compatibility.max_version

    field_desc = field.desc
    if field_desc.is_map():
      # Unwrap maps to value field
      field_desc = field.desc.message_type.fields['value']
      field.map_key = self.get_obj(
          field.desc.message_type.fields['key'].full_name)
      self.parse_options(field.map_key,
                         field.desc.options.Extensions[wdl_options_pb2.keyprop])
      field.map_value = self.get_obj(
          field.desc.message_type.fields['value'].full_name)
      self.parse_options(field.map_value, options)
      field.is_map = True
    else:
      field.is_array = field.desc.label == field_desc.LABEL_REPEATED

    field_type = field_desc.type
    if field_desc.type_name in WRAPPER_TYPES:
      field_type = WRAPPER_TYPES[field_desc.type_name]
      if not field.is_nullable and not self.is_common(field.full_name):
        # The fact that this was wrapped is lost,  so can't be checked in
        # separate validator
        raise exception.InvalidUsage(
            'Field %s is a wrapper type '
            'but is not nullable.' % field_desc.full_name)
    elif field.is_nullable and field_type != field_desc.TYPE_MESSAGE:
      raise exception.InvalidUsage('Field %s is nullable, but '
                                   'is not a wrapper or strudct '
                                   'type.' % field_desc.full_name)
    field.data_type = {
        field_desc.TYPE_FLOAT: schema.Field.DataType.FLOAT,
        field_desc.TYPE_DOUBLE: schema.Field.DataType.DOUBLE,
        field_desc.TYPE_UINT64: schema.Field.DataType.UINT64,
        field_desc.TYPE_UINT32: schema.Field.DataType.UINT32,
        field_desc.TYPE_INT64: schema.Field.DataType.INT64,
        field_desc.TYPE_INT32: schema.Field.DataType.INT32,
        field_desc.TYPE_FIXED64: schema.Field.DataType.INT64,
        field_desc.TYPE_FIXED32: schema.Field.DataType.INT32,
        field_desc.TYPE_SINT64: schema.Field.DataType.INT64,
        field_desc.TYPE_SINT32: schema.Field.DataType.INT32,
        field_desc.TYPE_STRING: schema.Field.DataType.STRING,
        field_desc.TYPE_ENUM: schema.Field.DataType.ENUM,
        field_desc.TYPE_BOOL: schema.Field.DataType.BOOL,
        field_desc.TYPE_BYTES: schema.Field.DataType.BYTES,
        field_desc.TYPE_MESSAGE: schema.Field.DataType.STRUCT,
    }[field_type]

    if field.data_type is schema.Field.DataType.STRUCT:
      field.struct_type = self.get_obj(field_desc.type_name)
      if not isinstance(field.struct_type, schema.Struct):
        raise exception.InvalidType(
            'Message {}, referenced by field {}, is not a struct. '
            'Fields may only reference structs.'.format(
                field.struct_type.full_name, field.full_name))
      # set metadata for legacy support
      field.metadata = field.struct_type
    elif field.data_type is schema.Field.DataType.ENUM:
      field.enum_type = self.get_obj(field_desc.type_name)
      # set metadata for legacy support
      field.metadata = field.enum_type

    self.parse_options(field, options)