def __api_descriptor(self, services, hostname=None):
merged_api_info = self.__get_merged_api_info(services)<EOL>descriptor = self.get_descriptor_defaults(merged_api_info,<EOL>hostname=hostname)<EOL>description = merged_api_info.description<EOL>if not description and len(services) == <NUM_LIT:1>:<EOL><INDENT>description = services[<NUM_LIT:0>].__doc__<EOL><DEDENT>if description:<EOL><INDENT>descriptor['<STR_LIT:description>'] = description<EOL><DEDENT>auth_descriptor = self.__auth_descriptor(merged_api_info)<EOL>if auth_descriptor:<EOL><INDENT>descriptor['<STR_LIT>'] = auth_descriptor<EOL><DEDENT>frontend_limit_descriptor = self.__frontend_limit_descriptor(<EOL>merged_api_info)<EOL>if frontend_limit_descriptor:<EOL><INDENT>descriptor['<STR_LIT>'] = frontend_limit_descriptor<EOL><DEDENT>method_map = {}<EOL>method_collision_tracker = {}<EOL>rest_collision_tracker = {}<EOL>for service in services:<EOL><INDENT>remote_methods = service.all_remote_methods()<EOL>for protorpc_meth_name, protorpc_meth_info in remote_methods.iteritems():<EOL><INDENT>method_info = getattr(protorpc_meth_info, '<STR_LIT>', None)<EOL>if method_info is None:<EOL><INDENT>continue<EOL><DEDENT>method_id = method_info.method_id(service.api_info)<EOL>rosy_method = '<STR_LIT>' % (service.__name__, protorpc_meth_name)<EOL>self.__id_from_name[rosy_method] = method_id<EOL>method_map[method_id] = self.__method_descriptor(<EOL>service, method_info, rosy_method, protorpc_meth_info)<EOL>if method_id in method_collision_tracker:<EOL><INDENT>raise api_exceptions.ApiConfigurationError(<EOL>'<STR_LIT>' %<EOL>(method_id, method_collision_tracker[method_id],<EOL>service.__name__))<EOL><DEDENT>else:<EOL><INDENT>method_collision_tracker[method_id] = service.__name__<EOL><DEDENT>rest_identifier = (method_info.http_method,<EOL>method_info.get_path(service.api_info))<EOL>if rest_identifier in rest_collision_tracker:<EOL><INDENT>raise api_exceptions.ApiConfigurationError(<EOL>'<STR_LIT>' %<EOL>(method_info.http_method, method_info.get_path(service.api_info),<EOL>rest_collision_tracker[rest_identifier],<EOL>service.__name__))<EOL><DEDENT>else:<EOL><INDENT>rest_collision_tracker[rest_identifier] = service.__name__<EOL><DEDENT><DEDENT><DEDENT>if method_map:<EOL><INDENT>descriptor['<STR_LIT>'] = method_map<EOL>descriptor['<STR_LIT>'] = self.__schema_descriptor(services)<EOL><DEDENT>return descriptor<EOL>
Builds a description of an API.

        Args:
          services: List of protorpc.remote.Service instances implementing an
            api/version.
          hostname: string, Hostname of the API, to override the value set on the
            current service. Defaults to None.

        Returns:
          A dictionary that can be deserialized into JSON and stored as an API
          description document.

        Raises:
          ApiConfigurationError: If there's something wrong with the API
            configuration, such as a multiclass API decorated with different API
            descriptors (see the docstring for api()), or a repeated method
            signature.