예제 #1
0
  def __init__(self, api, name, def_dict, method):
    super(Parameter, self).__init__(def_dict, api, parent=method,
                                    wire_name=name)
    self.ValidateName(name)
    self.schema = api

    # TODO(user): Deal with dots in names better. What we should do is:
    # For x.y, x.z create a little class X, with members y and z. Then
    # have the constructor method take an X.

    self._repeated = self.values.get('repeated', False)
    self._required = self.values.get('required', False)
    self._location = (self.values.get('location')
                      or self.values.get('restParameterType')
                      or 'query')
    # TODO(user): Why not just use Schema.Create here?
    referenced_schema = self.values.get('$ref')
    if referenced_schema:
      self._data_type = (api.SchemaByName(referenced_schema) or
                         data_types.SchemaReference(referenced_schema, api))
    elif def_dict.get('type') == 'array':
      self._data_type = Schema.Create(api, name, def_dict, name, method)
    elif self.values.get('enum'):
      self._data_type = data_types.Enum(def_dict,
                                        api,
                                        name,
                                        self.values.get('enum'),
                                        self.values.get('enumDescriptions'),
                                        parent=method)
      self.SetTemplateValue('enumType', self._data_type)
    else:
      self._data_type = data_types.PrimitiveDataType(def_dict, api, parent=self)
    if self._repeated:
      self._data_type = data_types.ArrayDataType(name, self._data_type,
                                                 parent=self)
예제 #2
0
 def _CreateArrayType(cls, api, def_dict, wire_name,
                      class_name, schema_id, parent):
   items = def_dict.get('items')
   if not items:
     raise ApiException('array without items in: %s' % def_dict)
   tentative_class_name = class_name
   # TODO(user): THIS IS STUPID. We should not rename things items.
   # if we have an anonymous type within a map or array, it should be
   # called 'Item', and let the namespacing sort it out.
   if schema_id:
     _LOGGER.debug('Top level schema %s is an array', class_name)
     tentative_class_name += 'Items'
   base_type = api.DataTypeFromJson(items, tentative_class_name,
                                    parent=parent, wire_name=wire_name)
   _LOGGER.debug('  %s is ArrayOf<%s>', class_name, base_type.class_name)
   array_type = data_types.ArrayDataType(tentative_class_name, base_type,
                                         wire_name=wire_name,
                                         parent=parent)
   if schema_id:
     array_type.SetTemplateValue('className', schema_id)
   return array_type
예제 #3
0
    def __init__(self, api, name, def_dict, method):
        super(Parameter, self).__init__(def_dict, api, parent=method)
        self.requires_imports = []
        self.ValidateName(name)
        self.schema = api
        self.SetTemplateValue('wireName', name)

        # TODO(user): Deal with dots in names better. What we should do is:
        # For x.y, x.z create a little class X, with members y and z. Then
        # have the constructor method take an X.

        self._repeated = self.values.get('repeated', False)
        self._required = self.values.get('required', False)
        self._data_type = data_types.BuiltInDataType(def_dict,
                                                     api,
                                                     parent=self)
        if self._repeated:
            self._data_type = data_types.ArrayDataType(self._data_type,
                                                       parent=self)

        if self.values.get('enum'):
            enum = Enum(api, name, self._data_type, self.values.get('enum'),
                        self.values.get('enumDescriptions'))
            self.SetTemplateValue('enumType', enum)
예제 #4
0
    def Create(api, default_name, def_dict, wire_name, parent=None):
        """Construct a Schema or DataType from a discovery dictionary.

    Schemas contain either object declarations, simple type declarations, or
    references to other Schemas.  Object declarations conceptually map to real
    classes.  Simple types will map to a target language built-in type.
    References should effectively be replaced by the referenced Schema.

    Args:
      api: (Api) the Api instance owning the Schema
      default_name: (str) the default name of the Schema. If there is an 'id'
        member in the definition, that is used for the name instead.
      def_dict: (dict) a discovery dictionary
      wire_name: The name which will identify objects of this type in data on
        the wire.
      parent: (Schema) The containing schema. To be used to establish nesting
        for anonymous sub-schemas.

    Returns:
      A Schema or DataType.

    Raises:
      ApiException: If the definition dict is not correct.
    """

        schema_id = def_dict.get('id')
        if schema_id:
            name = schema_id
        else:
            name = default_name
        class_name = api.ToClassName(name, element_type='schema')

        # Schema objects come in several patterns.
        #
        # 1. Simple objects
        #    { type: object, properties: { "foo": {schema} ... }}
        #
        # 2. Maps of objects
        #    { type: object, additionalProperties: { "foo": {inner_schema} ... }}
        #
        #    What we want is a data type which is Map<string, {inner_schema}>
        #    The schema we create here is essentially a built in type which we
        #    don't want to generate a class for.
        #
        # 3. Arrays of objects
        #    { type: array, items: { inner_schema }}
        #
        #    Same kind of issue as the map, but with List<{inner_schema}>
        #
        # 4. Primative data types, described by type and format.
        #    { type: string, format: int32 }
        #
        # 5. Refs to another schema.
        #    { $ref: name }

        if 'type' in def_dict:
            # The 'type' field of the schema can either be 'array', 'object', or a
            # base json type.
            json_type = def_dict['type']
            if json_type == 'object':
                # Look for full object definition.  You can have properties or
                # additionalProperties, but it does not  do anything useful to have
                # both.

                # Replace properties dict with Property's
                props = def_dict.get('properties')
                if props:
                    # This case 1 from above
                    properties = []
                    schema = Schema(api, name, def_dict, parent=parent)
                    if wire_name:
                        schema.SetTemplateValue('wireName', wire_name)
                    for prop_name, prop_dict in props.iteritems():
                        Trace('  adding prop: %s to %s' % (prop_name, name))
                        properties.append(
                            Property(api, schema, prop_name, prop_dict))
                    Trace('Marking %s fully defined' %
                          schema.values['className'])
                    schema.SetTemplateValue('properties', properties)
                    return schema

                # Look for case 2
                additional_props = def_dict.get(_ADDITIONAL_PROPERTIES)
                if additional_props:
                    Trace('Have only additionalProps for %s, dict=%s' %
                          (name, str(additional_props)))
                    # TODO(user): Remove this hack at the next large breaking change
                    # The "Items" added to the end is unneeded and ugly. This is for
                    # temporary backwards compatability.  And in case 3 too.
                    if additional_props.get('type') == 'array':
                        name = '%sItems' % name
                    # Note, since this is an interim, non class just to hold the map
                    # make the parent schema the parent passed in, not myself.
                    base_type = api.DataTypeFromJson(additional_props,
                                                     name,
                                                     parent=parent,
                                                     wire_name=wire_name)
                    map_type = data_types.MapDataType(base_type, parent=parent)
                    Trace('  %s is MapOf<string, %s>' %
                          (class_name, base_type.class_name))
                    return map_type

                raise ApiException('object without properties in: %s' %
                                   def_dict)

            elif json_type == 'array':
                # Case 3: Look for array definition
                items = def_dict.get('items')
                if not items:
                    raise ApiException('array without items in: %s' % def_dict)
                tentative_class_name = class_name
                if schema_id:
                    Trace('Top level schema %s is an array' % class_name)
                    tentative_class_name += 'Items'
                base_type = api.DataTypeFromJson(items,
                                                 tentative_class_name,
                                                 parent=parent,
                                                 wire_name=wire_name)
                Trace('  %s is ArrayOf<%s>' %
                      (class_name, base_type.class_name))
                array_type = data_types.ArrayDataType(base_type, parent=parent)

                # If I am not a top level schema, mark me as not generatable
                if not schema_id:
                    array_type.SetTemplateValue('builtIn', True)
                else:
                    Trace('Top level schema %s is an array' % class_name)
                    array_type.SetTemplateValue('className', schema_id)
                return array_type

            else:
                # Case 4: This must be a basic type.  Create a DataType for it.
                format_type = def_dict.get('format')
                if format_type:
                    Trace(' Found Type: %s with Format: %s' %
                          (json_type, format_type))

                base_type = data_types.BuiltInDataType(def_dict,
                                                       api,
                                                       parent=parent)
                return base_type

        referenced_schema = def_dict.get('$ref')
        if referenced_schema:
            # Case 5: Reference to another Schema.
            #
            # There are 4 ways you can see '$ref' in discovery.
            # 1. In a property of a schema, pointing back to one previously defined
            # 2. In a property of a schema, pointing forward
            # 3. In a method request or response pointing to a defined schema
            # 4. In a method request or response or property of a schema pointing to
            #    something undefined.
            #
            # This code is not reached in case 1.  The way the Generators loads
            # schemas (see _BuildSchemaDefinitions), is to loop over them and add
            # them to a dict of schemas. A backwards reference would be in the table
            # so the DataTypeFromJson call in the Property constructor will resolve
            # to the defined schema.
            #
            # For case 2.  Just creating this placeholder here is fine.  When the
            # actual schema is hit in the loop in _BuildSchemaDefinitions, we will
            # replace the entry and DataTypeFromJson will resolve the to the new def.
            #
            # For case 3, we should not reach this code, because the
            # DataTypeFromJson would
            # have returned the defined schema.
            #
            # For case 4, we punt on the whole API.
            return data_types.SchemaReference(referenced_schema, api)

        raise ApiException('Cannot decode JSON Schema for: %s' % def_dict)