code: def __discovery_doc_descriptor(self, services, hostname=None):
      merged_api_info = self.__get_merged_api_info(services)
      descriptor = self.get_descriptor_defaults(merged_api_info,
                                                hostname=hostname)
      description = merged_api_info.description
      if not description and len(services) == 1:
        description = services[0].__doc__
      if description:
        descriptor['description'] = description
      descriptor['parameters'] = self.__standard_parameters_descriptor()
      descriptor['auth'] = self.__standard_auth_descriptor(services)
      if merged_api_info.namespace:
        descriptor['ownerDomain'] = merged_api_info.namespace.owner_domain
        descriptor['ownerName'] = merged_api_info.namespace.owner_name
        descriptor['packagePath'] = merged_api_info.namespace.package_path or ''
      else:
        if merged_api_info.owner_domain is not None:
          descriptor['ownerDomain'] = merged_api_info.owner_domain
        if merged_api_info.owner_name is not None:
          descriptor['ownerName'] = merged_api_info.owner_name
        if merged_api_info.package_path is not None:
          descriptor['packagePath'] = merged_api_info.package_path
      method_map = {}
      method_collision_tracker = {}
      rest_collision_tracker = {}
      resource_index = collections.defaultdict(list)
      resource_map = {}
      for service in services:
        remote_methods = service.all_remote_methods()
        for protorpc_meth_name, protorpc_meth_info in remote_methods.iteritems():
          method_info = getattr(protorpc_meth_info, 'method_info', None)
          if method_info is None:
            continue
          path = method_info.get_path(service.api_info)
          method_id = method_info.method_id(service.api_info)
          canonical_method_id = self._get_canonical_method_id(method_id)
          resource_path = self._get_resource_path(method_id)
          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, path)
          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, path,
                 rest_collision_tracker[rest_identifier],
                 service.__name__))
          else:
            rest_collision_tracker[rest_identifier] = service.__name__
          if resource_path:
            resource_index[resource_path[0]].append((service, protorpc_meth_info))
          else:
            method_map[canonical_method_id] = self.__method_descriptor(
                service, method_info, protorpc_meth_info)
      for resource, resource_methods in resource_index.items():
        resource_map[resource] = self.__resource_descriptor(resource,
            resource_methods)
      if method_map:
        descriptor['methods'] = method_map
      if resource_map:
        descriptor['resources'] = resource_map
      schemas = self.__schemas_descriptor()
      if schemas:
        descriptor['schemas'] = schemas
      return descriptor