Пример #1
0
def get_course(code):
    """Returns all information for course identified by course code. Search is
    case sensitive

    """
    with pool.get_connection() as sc:
        # Make sure there is a course with the given code
        triples = sc.query(Triple(code, "rdf:type", "Course"))
        if not triples:
            msg = 'There is no course with code "{0}".'.format(code)
            raise Exception(msg)

        course = fetch_rdf_graph(code, dont_follow=["department"])
        course["code"] = code

        # Fetch department and faculty codes separately, as the structure
        # constructed by fetch_rdf_graph becomes sanely does not
        # contain the codes. These just go and assume that every course
        # has both faculty and department. With Noppa scraping this
        # is necessarily true.
        triples = sc.query(Triple(course["code"], "department", None))
        course["department"] = str(triples[0].object)

        triples = sc.query(Triple(course["department"], "faculty", None))
        course["faculty"] = str(triples[0].object)

        return course
Пример #2
0
def search(query):
    """Return users based on their real names and usernames.

    Arguments:
    query -- The search term. Every user whose name or user name contains the
             query string will be returned.

    """
    with pool.get_connection() as sc:
        query = query.lower()
        if isinstance(query, unicode):
            query = query.encode('utf8')

        user_ids = set()

        username_triples = sc.query(
            Triple(None, '{0}#username'.format(PEOPLE_BASE_URI), None))
        unstructured_triples = sc.query(
            Triple(None, '{0}#unstructured'.format(PEOPLE_BASE_URI), None))

        for triple in chain(username_triples, unstructured_triples):
            name = str(triple.object)
            if query in name.lower():
                if triple.predicate.endswith('unstructured'):
                    name_triples = sc.query(Triple(None,
                        '{0}#name'.format(PEOPLE_BASE_URI),
                        triple.subject))
                    user_uri = name_triples[0].subject
                else:
                    user_uri = triple.subject

                namespace, uid = user_uri.split('#')
                user_ids.add(uid)

        return list(user_ids)
Пример #3
0
def search(query):
    """Search for courses whose course code or name contains the query
    string. Search is case insensitive

    Arguments:
    query -- The query string. Please use unicode query string, if you want to
             have a case insensitive search for unicode characters also.

    """
    query = query.lower()
    if isinstance(query, unicode):
        query = query.encode("utf8")

    with pool.get_connection() as sc:
        # This unfortunately must be done in Python. WQL could possibly help
        # here. Of course SIB (or Python-KP) is slow as molasses anyway.

        # Get a list of valid course codes as also Faculties and Departments
        # have 'name' predicate.
        course_triples = sc.query(Triple(None, "rdf:type", "Course"))
        valid_courses = set(str(triple.subject) for triple in course_triples)

        name_triples = sc.query(Triple(None, "name", None))

        course_codes = []
        for triple in name_triples:
            course_code = str(triple.subject)
            course_name = str(triple.object)
            if course_code not in valid_courses:
                continue
            if query in course_code.lower() or query in course_name.lower():
                course_codes.append(course_code)

        return sorted(course_codes)
Пример #4
0
def fetch_rdf_graph(subject, dont_follow=None):
    """Fetch all triples related to a subject and transform them to a graph.

    First this function fetches all triples with the given subject. Then it
    calls itself recursively for all such triples that have an URI as their
    object. The end result is a clean graph of all these triples similar to
    the output of make_graph().

    Arguments:
    subject -- The subject of triples to fetch.
    dont_follow -- A list of predicates which are not followed recursively.
        This is useful if the RDF graph contains recursive references that
        cause infinite recursion in this function.

    """
    if dont_follow is None:
        dont_follow = []

    with pool.get_connection() as sc:
        triples = sc.query(Triple(subject, None, None))

    graph = {}
    if not triples:
        return graph

    for triple in triples:
        # Skip triples that define RDF ontology
        if triple.predicate.startswith(RDF_SYNTAX_NS_URI):
            continue

        subject = wrap_if_not_none(str, triple.subject)
        predicate = wrap_if_not_none(str, triple.predicate)
        object_ = wrap_if_not_none(str, triple.object)

        # Strip namespace uri from predicate
        if isinstance(triple.predicate, uri):
            predicate = predicate.split('#')[-1]

        # The last condition is there to prevent wandering into RDF
        # ontology definitions
        if isinstance(triple.object, uri) and \
                str(triple.predicate) not in dont_follow and \
                not object_.startswith(RDF_SCHEMA_URI):
            value = fetch_rdf_graph(object_, dont_follow)
        else:
            value = object_

        if subject not in graph:
            graph[subject] = {}
        if predicate not in graph[subject]:
            graph[subject][predicate] = value
        elif isinstance(graph[subject][predicate], list):
            graph[subject][predicate].append(value)
        else:
            graph[subject][predicate] = [graph[subject][predicate], value]

    return graph[subject]
Пример #5
0
def get_all():
    """Return a list of user_ids of all users.

    """
    uids = []
    with pool.get_connection() as sc:
        triples = sc.query(Triple(None, 'rdf:type',
            uri('{0}#Person'.format(PEOPLE_BASE_URI))))
        for triple in triples:
            uid = triple.subject.split('#')[-1]
            uids.append(uid)
    return uids
Пример #6
0
def get_faculties():
    """Returns faculties listed in Noppa system ordered by their id."""
    with pool.get_connection() as sc:
        # Get list of faculties with their ids
        triples = sc.query(Triple(None, "rdf:type", "Faculty"))
        faculties_ids = [str(triple.subject) for triple in triples]

        # Get id-name triplets by ids
        faculties = []
        for faculty_id in faculties_ids:
            faculty = get_faculty_info(faculty_id)
            faculties.append(faculty)

        # Sort the list of faculties by their code
        return sorted(faculties, key=lambda faculty: faculty["code"])
Пример #7
0
def get_courses_by_department(code):
    """Returns courses by given department as identified by department code.
    Department code is case sensitive

    """
    with pool.get_connection() as sc:
        triples = sc.query(Triple(None, "department", uri(code)))
        course_codes = [str(triple.subject) for triple in triples]

        courses = []
        for course_code in course_codes:
            course = get_course(course_code)
            courses.append(course)

        # Sort the list of courses by their code
        return sorted(courses, key=lambda course: course["code"])
Пример #8
0
def get_friends(user_id):
    """Get a list of user's friends.

    Arguments:
    user_id -- The user id of the user.

    """
    friend_ids = []
    with pool.get_connection() as sc:
        friend_triples = sc.query(Triple(
            '{0}/ID#{1}'.format(PEOPLE_BASE_URI, user_id),
            '{0}#Friend'.format(PEOPLE_BASE_URI), None))
        for triple in friend_triples:
            friend_id = triple.object.split('#')[-1]
            friend_ids.append(friend_id)

    return friend_ids
Пример #9
0
    def get_pending_friend_requests(self):
        """Returns a list of people who have requested to connect to this user.

        A friend request is accepted by making the same request in the opposite
        direction.

        """
        pending_friend_ids = []
        with pool.get_connection() as sc:
            friend_triples = sc.query(Triple(
                '{0}/ID#{1}'.format(PEOPLE_BASE_URI, self.user_id),
                '{0}#PendingFriend'.format(PEOPLE_BASE_URI), None))
            for triple in friend_triples:
                friend_id = triple.object.split('#')[-1]
                pending_friend_ids.append(friend_id)

        return pending_friend_ids
Пример #10
0
def get_faculty_info(code):
    """Returns faculty info by the given faculty code.

    Arguments:
    code -- Faculty code as seen in Noppa's URL when viewing courses by
            faculty. This is case sensitive.

    """
    with pool.get_connection() as sc:
        # Make sure there is a faculty with the given code
        triples = sc.query(Triple(code, "rdf:type", "Faculty"))
        if not triples:
            msg = 'There is no faculty with code "{0}".'.format(code)
            raise Exception(msg)

        name_triple = sc.query(Triple(code, "name", None))
        faculty = {"code": code, "name": str(name_triple[0].object)}
        return faculty
Пример #11
0
def get_department_info(code):
    """Returns department info by the given department code.

    Arguments:
    code -- Case sensitive department code

    """
    with pool.get_connection() as sc:
        # Make sure there is a department with the given code
        triples = sc.query(Triple(code, "rdf:type", "Department"))
        if not triples:
            msg = 'There is no department with code "{0}".'.format(code)
            raise Exception(msg)

        name_triple = sc.query(Triple(code, "name", None))
        department = {"code": code, "name": str(name_triple[0].object)}

        return department
Пример #12
0
def get_departments_by_faculty(faculty_code):
    """Returns departments by a faculty.

    Arguments:
    faculty_code -- The code of the faculty whose departments are returned.
                    Faculty code is case sensitive.

    """
    with pool.get_connection() as sc:
        triples = sc.query(Triple(None, "faculty", uri(faculty_code)))
        department_ids = [str(triple.subject) for triple in triples]

        departments = []
        for department_id in department_ids:
            department = get_department_info(department_id)
            departments.append(department)

        # Sort the list of departments by their code
        return sorted(departments, key=lambda department: department["code"])
Пример #13
0
def get_completed_courses(user_id):
    """Returns the completed courses for the given user sorted by most recent
    completion first.

    """
    user_uri = '{0}/ID#{1}'.format(PEOPLE_BASE_URI, user_id)

    with pool.get_connection() as sc:
        all_completed_course_uris = set(triple.subject
            for triple in sc.query(
                Triple(None, 'rdf:type', 'CompletedCourse')))
        all_user_uris = set(triple.subject
            for triple in sc.query(Triple(None, 'user', uri(user_uri))))
        completed_course_uris = all_completed_course_uris & all_user_uris

        completed_courses = []
        for subject in completed_course_uris:
            completed_course = fetch_rdf_graph(
                subject, dont_follow=['user'])
            del completed_course['user']
            completed_courses.append(completed_course)

        return sorted(completed_courses, key=lambda item: item['date'],
            reverse=True)
Пример #14
0
 def is_completed_course(self, course_code):
     subject = '{0}people/{1}/courses/completed/{2}'.format(
         CLOUDSIZZLE_RDF_BASE, self.user_id, course_code)
     triple = Triple(subject, 'rdf:type', 'CompletedCourse')
     with pool.get_connection() as sc:
         return len(sc.query(triple)) > 0