diff --git a/lms/djangoapps/analytics/csvs.py b/lms/djangoapps/analytics/csvs.py index 0e3f6d19f3..eb4cf69e30 100644 --- a/lms/djangoapps/analytics/csvs.py +++ b/lms/djangoapps/analytics/csvs.py @@ -31,9 +31,16 @@ def create_csv_response(filename, header, datarows): return response -def format_dictlist(dictlist): +def format_dictlist(dictlist, features): """ - Convert FROM [ + Convert a list of dictionaries to be compatible with create_csv_response + + `dictlist` is a list of dictionaries + all dictionaries should have keys from features + `features` is a list of features + + example code: + dictlist = [ { 'label1': 'value-1,1', 'label2': 'value-1,2', @@ -48,32 +55,26 @@ def format_dictlist(dictlist): } ] - TO { - 'header': ['label1', 'label2', 'label3', 'label4'], - 'datarows': [['value-1,1', 'value-1,2', 'value-1,3', 'value-1,4'], - ['value-2,1', 'value-2,2', 'value-2,3', 'value-2,4']] - } + header, datarows = format_dictlist(dictlist, ['label1', 'label4']) - Assumes all keys for input dicts are the same. + # results in + header = ['label1', 'label4'] + datarows = [['value-1,1', 'value-1,4'], + ['value-2,1', 'value-2,4']] + } """ - if len(dictlist) > 0: - header = dictlist[0].keys() - else: - header = [] - def dict_to_entry(dct): - """ Convert dictionary to list for a csv row """ - ordered = sorted(dct.items(), key=lambda (k, v): header.index(k)) + """ Convert dictionary to a list for a csv row """ + relevant_items = [(k, v) for (k, v) in dct.items() if k in features] + ordered = sorted(relevant_items, key=lambda (k, v): header.index(k)) vals = [v for (_, v) in ordered] return vals + header = features datarows = map(dict_to_entry, dictlist) - return { - 'header': header, - 'datarows': datarows, - } + return header, datarows def format_instances(instances, features): diff --git a/lms/djangoapps/analytics/tests/test_csvs.py b/lms/djangoapps/analytics/tests/test_csvs.py index ef1e6faee8..d6673b95a4 100644 --- a/lms/djangoapps/analytics/tests/test_csvs.py +++ b/lms/djangoapps/analytics/tests/test_csvs.py @@ -41,7 +41,7 @@ class TestAnalyticsFormatDictlist(TestCase): """ Test format_dictlist method """ def test_format_dictlist(self): - data_in = [ + dictlist = [ { 'label1': 'value-1,1', 'label2': 'value-1,2', @@ -53,22 +53,23 @@ class TestAnalyticsFormatDictlist(TestCase): 'label2': 'value-2,2', 'label3': 'value-2,3', 'label4': 'value-2,4', - }, + } ] - data_out = { - 'header': ['label1', 'label2', 'label3', 'label4'], - 'datarows': [['value-1,1', 'value-1,2', 'value-1,3', 'value-1,4'], - ['value-2,1', 'value-2,2', 'value-2,3', 'value-2,4']], - } + features = ['label1', 'label4'] + header, datarows = format_dictlist(dictlist, features) - self.assertEqual(format_dictlist(data_in), data_out) + ideal_header = ['label1', 'label4'] + ideal_datarows = [['value-1,1', 'value-1,4'], + ['value-2,1', 'value-2,4']] + + self.assertEqual(header, ideal_header) + self.assertEqual(datarows, ideal_datarows) def test_format_dictlist_empty(self): - self.assertEqual(format_dictlist([]), { - 'header': [], - 'datarows': [], - }) + header, datarows = format_dictlist([], []) + self.assertEqual(header, []) + self.assertEqual(datarows, []) def test_create_csv_response(self): header = ['Name', 'Email'] diff --git a/lms/djangoapps/analytics/tests/test_distributions.py b/lms/djangoapps/analytics/tests/test_distributions.py index 39352a28b0..0c565cf756 100644 --- a/lms/djangoapps/analytics/tests/test_distributions.py +++ b/lms/djangoapps/analytics/tests/test_distributions.py @@ -19,7 +19,7 @@ class TestAnalyticsDistributions(TestCase): profile__year_of_birth=i + 1930 ) for i in xrange(30)] - self.ces = tuple(CourseEnrollment.objects.create(course_id=self.course_id, user=user) for user in self.users) + self.ces = [CourseEnrollment.objects.create(course_id=self.course_id, user=user) for user in self.users] @raises(ValueError) def test_profile_distribution_bad_feature(self): @@ -53,13 +53,13 @@ class TestAnalyticsDistributionsNoData(TestCase): def setUp(self): self.course_id = 'some/robot/course/id' - self.users = tuple(UserFactory( + self.users = [UserFactory( profile__year_of_birth=i + 1930, - ) for i in xrange(5)) + ) for i in xrange(5)] - self.nodata_users = tuple(UserFactory( + self.nodata_users = [UserFactory( profile__year_of_birth=None, - ) for _ in xrange(4)) + ) for _ in xrange(4)] self.users += self.nodata_users diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index ecab296d13..96f03fcc66 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -279,8 +279,8 @@ def enrolled_students_features(request, course_id, csv=False): ) return response else: - formatted = analytics.csvs.format_dictlist(student_data) - return analytics.csvs.create_csv_response("enrolled_profiles.csv", formatted['header'], formatted['datarows']) + header, datarows = analytics.csvs.format_dictlist(student_data) + return analytics.csvs.create_csv_response("enrolled_profiles.csv", header, datarows) @ensure_csrf_cookie