def get_distinct_values(self, restype='', attr_list=None, res_filter=None): """Returns a list of distinct values for given resource type and list of attribute names. Only supports simple types for the attribute values. Returns a sorted list of values or tuples of values. """ if not restype or type(restype) != str: raise BadRequest("Illegal value for argument restype") if not hasattr(interface.objects, restype): raise BadRequest("Given restype is not a resource type") if not attr_list or not type(attr_list) in (list, tuple): raise BadRequest("Illegal value for argument attr_list") type_cls = getattr(interface.objects, restype) try: if not all(type_cls._schema[an]["type"] in {"str", "int", "float"} for an in attr_list): raise BadRequest("Attribute in attr_list if invalid type") except KeyError: raise BadRequest("Attribute in attr_list unknown") if res_filter and type(res_filter) not in (list, tuple): raise BadRequest("Illegal value for argument res_filter") # NOTE: This can alternatively be implemented as a SELECT DISTINCT query, but this is not # supported by the underlying datastore interface. rq = ResourceQuery() if res_filter: rq.set_filter(rq.eq(rq.ATT_TYPE, restype), res_filter) else: rq.set_filter(rq.eq(rq.ATT_TYPE, restype)) res_list = self.clients.resource_registry.find_resources_ext(query=rq.get_query(), id_only=False) log.debug("Found %s resources of type %s", len(res_list), restype) att_values = sorted({tuple(getattr(res, an) for an in attr_list) for res in res_list}) log.debug("Found %s distinct vales for attribute(s): %s", len(att_values), attr_list) return att_values