code: def __api_openapi_descriptor(self, services, hostname=None, x_google_api_name=False):
      merged_api_info = self.__get_merged_api_info(services)
      descriptor = self.get_descriptor_defaults(merged_api_info,
                                                hostname=hostname,
                                                x_google_api_name=x_google_api_name)
      description = merged_api_info.description
      if not description and len(services) == 1:
        description = services[0].__doc__
      if description:
        descriptor['info']['description'] = description
      security_definitions = self.__security_definitions_descriptor(
          merged_api_info.issuers)
      method_map = {}
      method_collision_tracker = {}
      rest_collision_tracker = {}
      for service in services:
        remote_methods = service.all_remote_methods()
        for protorpc_meth_name in sorted(remote_methods.iterkeys()):
          protorpc_meth_info = remote_methods[protorpc_meth_name]
          method_info = getattr(protorpc_meth_info, 'method_info', None)
          if method_info is None:
            continue
          method_id = method_info.method_id(service.api_info)
          is_api_key_required = method_info.is_api_key_required(service.api_info)
          path = '/{0}/{1}/{2}'.format(merged_api_info.name,
                                       merged_api_info.path_version,
                                       method_info.get_path(service.api_info))
          verb = method_info.http_method.lower()
          if path not in method_map:
            method_map[path] = {}
          if is_api_key_required and _API_KEY not in security_definitions:
            security_definitions[_API_KEY] = {
                'type': 'apiKey',
                'name': _API_KEY_PARAM,
                'in': 'query'
            }
          operation_id = self._construct_operation_id(
              service.__name__, protorpc_meth_name)
          method_map[path][verb] = self.__method_descriptor(
              service, method_info, operation_id, protorpc_meth_info,
              security_definitions)
          if method_id in method_collision_tracker:
            raise api_exceptions.ApiConfigurationError(
                'Method %s used multiple times, in classes %s and %s' %
                (method_id, method_collision_tracker[method_id],
                 service.__name__))
          else:
            method_collision_tracker[method_id] = service.__name__
          rest_identifier = (method_info.http_method,
                             method_info.get_path(service.api_info))
          if rest_identifier in rest_collision_tracker:
            raise api_exceptions.ApiConfigurationError(
                '%s path "%s" used multiple times, in classes %s and %s' %
                (method_info.http_method, method_info.get_path(service.api_info),
                 rest_collision_tracker[rest_identifier],
                 service.__name__))
          else:
            rest_collision_tracker[rest_identifier] = service.__name__
      if method_map:
        descriptor['paths'] = method_map
      definitions = self.__definitions_descriptor()
      if definitions:
        descriptor['definitions'] = definitions
      descriptor['securityDefinitions'] = security_definitions
      limit_definitions = self.__x_google_quota_definitions_descriptor(
          merged_api_info.limit_definitions)
      if limit_definitions:
        descriptor['x-google-management'] = limit_definitions
      return descriptor