Example #1
0
 def test_override_fixture(self, app):
     mr = MockRows(
         io.StringIO('sid,first_name,last_name\n20000000,Martin,Van Buren'))
     with register_mock(data_loch.get_sis_section_enrollments, mr):
         data = data_loch.get_sis_section_enrollments(2178, 12345)
     assert len(data) == 1
     assert {
         'sid': 20000000,
         'first_name': 'Martin',
         'last_name': 'Van Buren'
     } == data[0]
Example #2
0
 def test_fixture_not_found(self, app):
     no_db = data_loch.get_sis_section_enrollments(0, 0)
     # TODO Real data_loch queries will return an empty list if the course is not found.
     assert no_db is None
Example #3
0
def get_course_student_profiles(term_id, section_id, offset=None, limit=None, featured=None):
    benchmark = get_benchmarker('get_course_student_profiles')
    benchmark('begin')
    enrollment_rows = data_loch.get_sis_section_enrollments(
        term_id,
        section_id,
        offset=offset,
        limit=limit,
    )
    sids = [str(r['sid']) for r in enrollment_rows]
    if offset or len(sids) >= 50:
        count_result = data_loch.get_sis_section_enrollments_count(term_id, section_id)
        total_student_count = count_result[0]['count']
    else:
        total_student_count = len(sids)

    # If we have a featured UID not already present in the result set, add the corresponding SID only if the
    # student is enrolled.
    if featured and not next((r for r in enrollment_rows if str(r['uid']) == featured), None):
        featured_enrollment_rows = data_loch.get_sis_section_enrollment_for_uid(term_id, section_id, featured)
        if featured_enrollment_rows:
            sids = [str(featured_enrollment_rows[0]['sid'])] + sids

    # TODO It's probably more efficient to store class profiles in the loch, rather than distilling them
    # on the fly from full profiles.
    students = get_full_student_profiles(sids)

    benchmark('begin enrollments query')
    enrollments_for_term = data_loch.get_enrollments_for_term(term_id, sids)
    benchmark('end enrollments query')
    enrollments_by_sid = {row['sid']: json.loads(row['enrollment_term']) for row in enrollments_for_term}
    academic_standing = get_academic_standing_by_sid(sids, as_dicts=True)
    term_gpas = get_term_gpas_by_sid(sids, as_dicts=True)
    all_canvas_sites = {}
    benchmark('begin profile transformation')
    for student in students:
        # Strip SIS details to lighten the API load.
        sis_profile = student.pop('sisProfile', None)
        if sis_profile:
            student['academicCareerStatus'] = sis_profile.get('academicCareerStatus')
            student['cumulativeGPA'] = sis_profile.get('cumulativeGPA')
            student['cumulativeUnits'] = sis_profile.get('cumulativeUnits')
            student['degree'] = sis_profile.get('degree')
            student['level'] = _get_sis_level_description(sis_profile)
            student['currentTerm'] = sis_profile.get('currentTerm')
            student['majors'] = _get_active_plan_descriptions(sis_profile)
            student['transfer'] = sis_profile.get('transfer')
        term = enrollments_by_sid.get(student['sid'])
        if term:
            # Strip the enrollments list down to the section of interest.
            enrollments = term.pop('enrollments', [])
            for enrollment in enrollments:
                _section = next((s for s in enrollment['sections'] if str(s['ccn']) == section_id), None)
                if _section:
                    canvas_sites = enrollment.get('canvasSites', [])
                    student['enrollment'] = {
                        'canvasSites': canvas_sites,
                        'enrollmentStatus': _section.get('enrollmentStatus', None),
                        'grade': enrollment.get('grade', None),
                        'gradingBasis': enrollment.get('gradingBasis', None),
                        'midtermGrade': enrollment.get('midtermGrade', None),
                    }
                    student['analytics'] = analytics.mean_metrics_across_sites(canvas_sites, 'student')
                    # If more than one course site is associated with this section, derive mean metrics from as many sites as possible.
                    for site in canvas_sites:
                        if site['canvasCourseId'] not in all_canvas_sites:
                            all_canvas_sites[site['canvasCourseId']] = site
                    continue
        student['academicStanding'] = academic_standing.get(student['sid'])
        student['termGpa'] = term_gpas.get(student['sid'])
    benchmark('end profile transformation')
    mean_metrics = analytics.mean_metrics_across_sites(all_canvas_sites.values(), 'courseMean')
    mean_metrics['gpa'] = {}
    mean_gpas = data_loch.get_sis_section_mean_gpas(term_id, section_id)
    for row in mean_gpas:
        mean_metrics['gpa'][str(row['gpa_term_id'])] = row['avg_gpa']
    benchmark('end')
    return {
        'students': students,
        'totalStudentCount': total_student_count,
        'meanMetrics': mean_metrics,
    }
Example #4
0
def get_course_student_profiles(term_id, section_id, offset=None, limit=None):
    enrollment_rows = data_loch.get_sis_section_enrollments(
        term_id,
        section_id,
        scope=get_student_query_scope(),
        offset=offset,
        limit=limit,
    )
    sids = [str(r['sid']) for r in enrollment_rows]
    if offset or len(sids) >= 50:
        count_result = data_loch.get_sis_section_enrollments_count(
            term_id, section_id, scope=get_student_query_scope())
        total_student_count = count_result[0]['count']
    else:
        total_student_count = len(sids)
    # TODO It's probably more efficient to store class profiles in the loch, rather than distilling them
    # on the fly from full profiles.
    students = get_full_student_profiles(sids)

    enrollments_for_term = data_loch.get_enrollments_for_term(term_id, sids)
    enrollments_by_sid = {
        row['sid']: json.loads(row['enrollment_term'])
        for row in enrollments_for_term
    }
    all_canvas_sites = {}
    for student in students:
        # Strip SIS details to lighten the API load.
        sis_profile = student.pop('sisProfile', None)
        if sis_profile:
            student['cumulativeGPA'] = sis_profile.get('cumulativeGPA')
            student['cumulativeUnits'] = sis_profile.get('cumulativeUnits')
            student['level'] = sis_profile.get('level', {}).get('description')
            student['majors'] = sorted(
                plan.get('description')
                for plan in sis_profile.get('plans', []))
        term = enrollments_by_sid.get(student['sid'])
        student['hasCurrentTermEnrollments'] = False
        if term:
            # Strip the enrollments list down to the section of interest.
            enrollments = term.pop('enrollments', [])
            for enrollment in enrollments:
                _section = next((s for s in enrollment['sections']
                                 if str(s['ccn']) == section_id), None)
                if _section:
                    canvas_sites = enrollment.get('canvasSites', [])
                    student['enrollment'] = {
                        'canvasSites': canvas_sites,
                        'enrollmentStatus':
                        _section.get('enrollmentStatus', None),
                        'grade': enrollment.get('grade', None),
                        'gradingBasis': enrollment.get('gradingBasis', None),
                    }
                    student['analytics'] = analytics.mean_metrics_across_sites(
                        canvas_sites, 'student')
                    # If more than one course site is associated with this section, derive mean metrics from as many sites as possible.
                    for site in canvas_sites:
                        if site['canvasCourseId'] not in all_canvas_sites:
                            all_canvas_sites[site['canvasCourseId']] = site
                    continue
    mean_metrics = analytics.mean_metrics_across_sites(
        all_canvas_sites.values(), 'courseMean')
    return {
        'students': students,
        'totalStudentCount': total_student_count,
        'meanMetrics': mean_metrics,
    }