diff --git a/lms/djangoapps/analytics/basic.py b/lms/djangoapps/analytics/basic.py index a32335edac..aace7096ae 100644 --- a/lms/djangoapps/analytics/basic.py +++ b/lms/djangoapps/analytics/basic.py @@ -9,7 +9,8 @@ import xmodule.graders as xmgraders STUDENT_FEATURES = ('username', 'first_name', 'last_name', 'is_staff', 'email') -PROFILE_FEATURES = ('name', 'language', 'location', 'year_of_birth', 'gender', 'level_of_education', 'mailing_address', 'goals') +PROFILE_FEATURES = ('name', 'language', 'location', 'year_of_birth', 'gender', + 'level_of_education', 'mailing_address', 'goals') AVAILABLE_FEATURES = STUDENT_FEATURES + PROFILE_FEATURES @@ -19,17 +20,19 @@ def enrolled_students_profiles(course_id, features): """ # enrollments = CourseEnrollment.objects.filter(course_id=course_id) # students = [enrollment.user for enrollment in enrollments] - students = User.objects.filter(courseenrollment__course_id=course_id).order_by('username').select_related('profile') - print len(students) - print students + students = User.objects.filter(courseenrollment__course_id=course_id)\ + .order_by('username').select_related('profile') def extract_student(student): - student_features = [feature for feature in features if feature in STUDENT_FEATURES] - profile_features = [feature for feature in features if feature in PROFILE_FEATURES] + """ convert student to dictionary """ + student_features = [x for x in STUDENT_FEATURES if x in features] + profile_features = [x for x in PROFILE_FEATURES if x in features] - student_dict = dict((feature, getattr(student, feature)) for feature in student_features) + student_dict = dict((feature, getattr(student, feature)) + for feature in student_features) profile = student.profile - profile_dict = dict((feature, getattr(profile, feature)) for feature in profile_features) + profile_dict = dict((feature, getattr(profile, feature)) + for feature in profile_features) student_dict.update(profile_dict) return student_dict @@ -38,12 +41,14 @@ def enrolled_students_profiles(course_id, features): def dump_grading_context(course): """ - Render information about course grading context (eg which problems are graded in what assignments) + Render information about course grading context + (e.g. which problems are graded in what assignments) Useful for debugging grading_policy.json and policy.json Returns HTML string """ - msg = "-----------------------------------------------------------------------------\n" + hbar = "{}\n".format("-" * 77) + msg = hbar msg += "Course grader:\n" msg += '%s\n' % course.grader.__class__ @@ -52,34 +57,36 @@ def dump_grading_context(course): msg += '\n' msg += "Graded sections:\n" for subgrader, category, weight in course.grader.sections: - msg += " subgrader=%s, type=%s, category=%s, weight=%s\n" % (subgrader.__class__, subgrader.type, category, weight) + msg += " subgrader=%s, type=%s, category=%s, weight=%s\n"\ + % (subgrader.__class__, subgrader.type, category, weight) subgrader.index = 1 graders[subgrader.type] = subgrader - msg += "-----------------------------------------------------------------------------\n" + msg += hbar msg += "Listing grading context for course %s\n" % course.id - gc = course.grading_context + gcontext = course.grading_context msg += "graded sections:\n" - msg += '%s\n' % gc['graded_sections'].keys() - for (gs, gsvals) in gc['graded_sections'].items(): - msg += "--> Section %s:\n" % (gs) + msg += '%s\n' % gcontext['graded_sections'].keys() + for (gsomething, gsvals) in gcontext['graded_sections'].items(): + msg += "--> Section %s:\n" % (gsomething) for sec in gsvals: - s = sec['section_descriptor'] - format = getattr(s.lms, 'format', None) + sdesc = sec['section_descriptor'] + frmat = getattr(sdesc.lms, 'format', None) aname = '' - if format in graders: - g = graders[format] - aname = '%s %02d' % (g.short_label, g.index) - g.index += 1 - elif s.display_name in graders: - g = graders[s.display_name] - aname = '%s' % g.short_label + if frmat in graders: + gform = graders[frmat] + aname = '%s %02d' % (gform.short_label, gform.index) + gform.index += 1 + elif sdesc.display_name in graders: + gform = graders[sdesc.display_name] + aname = '%s' % gform.short_label notes = '' - if getattr(s, 'score_by_attempt', False): + if getattr(sdesc, 'score_by_attempt', False): notes = ', score by attempt!' - msg += " %s (format=%s, Assignment=%s%s)\n" % (s.display_name, format, aname, notes) + msg += " %s (format=%s, Assignment=%s%s)\n"\ + % (sdesc.display_name, frmat, aname, notes) msg += "all descriptors:\n" - msg += "length=%d\n" % len(gc['all_descriptors']) - msg = '
%s
' % msg.replace('<','<') + msg += "length=%d\n" % len(gcontext['all_descriptors']) + msg = '
%s
' % msg.replace('<', '<') return msg diff --git a/lms/djangoapps/analytics/csvs.py b/lms/djangoapps/analytics/csvs.py index 5a2ff18af3..2de88fea5d 100644 --- a/lms/djangoapps/analytics/csvs.py +++ b/lms/djangoapps/analytics/csvs.py @@ -16,8 +16,14 @@ def create_csv_response(filename, header, datarows): datarows e.g. [['Jim', 'jim@edy.org'], ['Jake', 'jake@edy.org'], ...] """ response = HttpResponse(mimetype='text/csv') - response['Content-Disposition'] = 'attachment; filename={0}'.format(filename) - csvwriter = csv.writer(response, dialect='excel', quotechar='"', quoting=csv.QUOTE_ALL) + response['Content-Disposition'] = 'attachment; filename={0}'\ + .format(filename) + csvwriter = csv.writer( + response, + dialect='excel', + quotechar='"', + quoting=csv.QUOTE_ALL) + csvwriter.writerow(header) for datarow in datarows: encoded_row = [unicode(s).encode('utf-8') for s in datarow] @@ -56,14 +62,15 @@ def format_dictlist(dictlist): else: header = [] - def dict_to_entry(d): - ordered = sorted(d.items(), key=lambda (k, v): header.index(k)) - vals = map(lambda (k, v): v, ordered) + def dict_to_entry(dct): + """ Convert dictionary to list for a csv row """ + ordered = sorted(dct.items(), key=lambda (k, v): header.index(k)) + vals = [v for (_, v) in ordered] return vals datarows = map(dict_to_entry, dictlist) return { - 'header': header, + 'header': header, 'datarows': datarows, } diff --git a/lms/djangoapps/analytics/distributions.py b/lms/djangoapps/analytics/distributions.py index ba320f0b82..696717eab8 100644 --- a/lms/djangoapps/analytics/distributions.py +++ b/lms/djangoapps/analytics/distributions.py @@ -3,7 +3,6 @@ Profile Distributions """ from django.db.models import Count -from django.contrib.auth.models import User, Group from student.models import CourseEnrollment, UserProfile AVAILABLE_PROFILE_FEATURES = ['gender', 'level_of_education', 'year_of_birth'] diff --git a/lms/djangoapps/analytics/tests/test_basic.py b/lms/djangoapps/analytics/tests/test_basic.py index 4278ff299c..2e5fa2571d 100644 --- a/lms/djangoapps/analytics/tests/test_basic.py +++ b/lms/djangoapps/analytics/tests/test_basic.py @@ -1,14 +1,16 @@ +""" +Tests for instructor.basic +""" + from django.test import TestCase -from django.contrib.auth.models import User, Group from student.models import CourseEnrollment -from xmodule.modulestore.tests.factories import CourseFactory from student.tests.factories import UserFactory from analytics.basic import enrolled_students_profiles, AVAILABLE_FEATURES, STUDENT_FEATURES, PROFILE_FEATURES class TestAnalyticsBasic(TestCase): - '''Test basic analytics functions.''' + """ Test basic analytics functions. """ def setUp(self): self.course_id = 'some/robot/course/id' diff --git a/lms/djangoapps/analytics/tests/test_csvs.py b/lms/djangoapps/analytics/tests/test_csvs.py index 220acaa0b1..be294afcd1 100644 --- a/lms/djangoapps/analytics/tests/test_csvs.py +++ b/lms/djangoapps/analytics/tests/test_csvs.py @@ -1,3 +1,5 @@ +""" Tests for analytics.csvs """ + from django.test import TestCase from analytics.csvs import create_csv_response, format_dictlist @@ -57,7 +59,6 @@ class TestAnalyticsCSVS(TestCase): self.assertEqual(format_dictlist(data_in), data_out) - def test_format_dictlist_empty(self): self.assertEqual(format_dictlist([]), { 'header': [], diff --git a/lms/djangoapps/analytics/tests/test_distributions.py b/lms/djangoapps/analytics/tests/test_distributions.py index 3eb509c01b..37343a0f90 100644 --- a/lms/djangoapps/analytics/tests/test_distributions.py +++ b/lms/djangoapps/analytics/tests/test_distributions.py @@ -1,8 +1,8 @@ +""" Tests for analytics.distributions """ + from django.test import TestCase from nose.tools import raises -from django.contrib.auth.models import User, Group from student.models import CourseEnrollment -from xmodule.modulestore.tests.factories import CourseFactory from student.tests.factories import UserFactory from analytics.distributions import profile_distribution, AVAILABLE_PROFILE_FEATURES diff --git a/lms/djangoapps/instructor/access.py b/lms/djangoapps/instructor/access.py index b07a8b3d39..d2e2952c02 100644 --- a/lms/djangoapps/instructor/access.py +++ b/lms/djangoapps/instructor/access.py @@ -9,12 +9,13 @@ TODO sync instructor and staff flags {instructor: true, staff: true} """ -from django.contrib.auth.models import User, Group -from courseware.access import get_access_group_name, course_beta_test_group_name -from django_comment_common.models import (Role, - FORUM_ROLE_ADMINISTRATOR, - FORUM_ROLE_MODERATOR, - FORUM_ROLE_COMMUNITY_TA) +from django.contrib.auth.models import Group +from courseware.access import (get_access_group_name, + course_beta_test_group_name) +from django_comment_common.models import Role + # FORUM_ROLE_ADMINISTRATOR, + # FORUM_ROLE_MODERATOR, + # FORUM_ROLE_COMMUNITY_TA) def list_with_level(course, level): diff --git a/lms/djangoapps/instructor/enrollment.py b/lms/djangoapps/instructor/enrollment.py index 6779e05469..fc4a3fec2c 100644 --- a/lms/djangoapps/instructor/enrollment.py +++ b/lms/djangoapps/instructor/enrollment.py @@ -28,10 +28,10 @@ def enroll_emails(course_id, student_emails, auto_enroll=False): auto_string = {False: 'allowed', True: 'willautoenroll'}[auto_enroll] status_map = { - 'user/ce/alreadyenrolled': [], - 'user/!ce/enrolled': [], - 'user/!ce/rejected': [], - '!user/cea/' + auto_string: [], + 'user/ce/alreadyenrolled': [], + 'user/!ce/enrolled': [], + 'user/!ce/rejected': [], + '!user/cea/' + auto_string: [], '!user/!cea/' + auto_string: [], } @@ -48,11 +48,11 @@ def enroll_emails(course_id, student_emails, auto_enroll=False): except CourseEnrollment.DoesNotExist: # status: user/!ce/enrolled try: - ce = CourseEnrollment(user=user, course_id=course_id) - ce.save() + cenr = CourseEnrollment(user=user, course_id=course_id) + cenr.save() status_map['user/!ce/enrolled'].append(student_email) # status: user/!ce/rejected - except: + except Exception: status_map['user/!ce/rejected'].append(student_email) # status: !user except User.DoesNotExist: @@ -106,9 +106,9 @@ def unenroll_emails(course_id, student_emails): # delete CourseEnrollment try: - ce = CourseEnrollment.objects.get(course_id=course_id, user__email=student_email) + cenr = CourseEnrollment.objects.get(course_id=course_id, user__email=student_email) try: - ce.delete() + cenr.delete() status_map['ce/unenrolled'].append(student_email) except Exception: status_map['ce/rejected'].append(student_email) diff --git a/lms/djangoapps/instructor/tests/test_access.py b/lms/djangoapps/instructor/tests/test_access.py index a5e2a9a304..98cc8cb159 100644 --- a/lms/djangoapps/instructor/tests/test_access.py +++ b/lms/djangoapps/instructor/tests/test_access.py @@ -1,6 +1,9 @@ -from django.test import TestCase +""" +Test instructor.access +""" + from nose.tools import raises -from django.contrib.auth.models import User, Group +from django.contrib.auth.models import Group from student.tests.factories import UserFactory from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase @@ -9,10 +12,9 @@ from django.test.utils import override_settings from django.conf import settings from uuid import uuid4 -from student.models import CourseEnrollment, CourseEnrollmentAllowed from courseware.access import get_access_group_name from django_comment_common.models import (Role, - FORUM_ROLE_ADMINISTRATOR, + # FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA) from instructor.access import allow_access, revoke_access, list_with_level, update_forum_role_membership @@ -24,11 +26,11 @@ from instructor.access import allow_access, revoke_access, list_with_level, upda # moved here from old courseware/tests/tests.py # when it disappeared this test broke. def mongo_store_config(data_dir): - ''' + """ Defines default module store using MongoModuleStore Use of this config requires mongo to be running - ''' + """ store = { 'default': { 'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore', @@ -52,7 +54,7 @@ TEST_DATA_MONGO_MODULESTORE = mongo_store_config(TEST_DATA_DIR) @override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) class TestInstructorAccessControlDB(ModuleStoreTestCase): - '''Test instructor access administration against database effects''' + """ Test instructor access administration against database effects """ def setUp(self): # self.course_id = 'jus:/a/fake/c::rse/id' @@ -132,12 +134,16 @@ class TestInstructorAccessControlDB(ModuleStoreTestCase): @override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) class TestInstructorAccessControlPrefilledDB(ModuleStoreTestCase): + """ + Test access with existing users. + """ def setUp(self): self.course = CourseFactory.create() # setup instructors self.instructors = set([UserFactory.create(), UserFactory.create()]) - [allow_access(self.course, user, 'instructor') for user in self.instructors] + for user in self.instructors: + allow_access(self.course, user, 'instructor') def test_list_with_level(self): instructors = set(list_with_level(self.course, 'instructor')) @@ -155,63 +161,68 @@ class TestInstructorAccessControlPrefilledDB(ModuleStoreTestCase): self.assertEqual(set(), beta_testers_result) beta_testers = set([UserFactory.create(), UserFactory.create()]) - [allow_access(self.course, user, 'beta') for user in beta_testers] + for user in beta_testers: + allow_access(self.course, user, 'beta') beta_testers_result = set(list_with_level(self.course, 'beta')) self.assertEqual(beta_testers, beta_testers_result) @override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) class TestInstructorAccessForumDB(ModuleStoreTestCase): + """ + Test forum access control. + """ def setUp(self): self.course = CourseFactory.create() self.moderators = set([UserFactory.create() for _ in xrange(4)]) self.mod_role = Role.objects.create(course_id=self.course.id, name=FORUM_ROLE_MODERATOR) - [self.mod_role.users.add(user) for user in self.moderators] + for user in self.moderators: + self.mod_role.users.add(user) - def test_update_forum_role_membership_allow_existing_role(self): + def test_update_forum_membership_allow_existing_role(self): user = UserFactory.create() update_forum_role_membership(self.course.id, user, FORUM_ROLE_MODERATOR, 'allow') self.assertIn(user, self.mod_role.users.all()) - def test_update_forum_role_membership_allow_existing_role_allowed_user(self): + def test_update_forum_membership_allow_existing_role_allowed_user(self): user = UserFactory.create() update_forum_role_membership(self.course.id, user, FORUM_ROLE_MODERATOR, 'allow') update_forum_role_membership(self.course.id, user, FORUM_ROLE_MODERATOR, 'allow') self.assertIn(user, self.mod_role.users.all()) @raises(Role.DoesNotExist) - def test_update_forum_role_membership_allow_not_existing_role(self): + def test_update_forum_membership_allow_not_existing_role(self): user = UserFactory.create() update_forum_role_membership(self.course.id, user, FORUM_ROLE_COMMUNITY_TA, 'allow') - def test_update_forum_role_membership_revoke_existing_role(self): + def test_update_forum_membership_revoke_existing_role(self): user = iter(self.moderators).next() update_forum_role_membership(self.course.id, user, FORUM_ROLE_MODERATOR, 'revoke') self.assertNotIn(user, self.mod_role.users.all()) - def test_update_forum_role_membership_revoke_existing_role_revoked_user(self): + def test_update_forum_membership_existing_role_revoked_user(self): user = iter(self.moderators).next() update_forum_role_membership(self.course.id, user, FORUM_ROLE_MODERATOR, 'revoke') update_forum_role_membership(self.course.id, user, FORUM_ROLE_MODERATOR, 'revoke') self.assertNotIn(user, self.mod_role.users.all()) @raises(Role.DoesNotExist) - def test_update_forum_role_membership_revoke_not_existing_role(self): + def test_update_forum_membership_revoke_not_existing_role(self): user = iter(self.moderators).next() update_forum_role_membership(self.course.id, user, FORUM_ROLE_COMMUNITY_TA, 'revoke') @raises(Role.DoesNotExist) - def test_update_forum_role_membership_bad_role_allow(self): + def test_update_forum_membership_bad_role_allow(self): user = UserFactory.create() update_forum_role_membership(self.course.id, user, 'robot-definitely-not-a-forum-role', 'allow') @raises(Role.DoesNotExist) - def test_update_forum_role_membership_bad_role_revoke(self): + def test_update_forum_membership_bad_role_revoke(self): user = UserFactory.create() update_forum_role_membership(self.course.id, user, 'robot-definitely-not-a-forum-role', 'revoke') @raises(ValueError) - def test_update_forum_role_membership_bad_mode(self): + def test_update_forum_membership_bad_mode(self): user = iter(self.moderators).next() update_forum_role_membership(self.course.id, user, FORUM_ROLE_MODERATOR, 'robot-not-a-mode') diff --git a/lms/djangoapps/instructor/tests/test_enrollment.py b/lms/djangoapps/instructor/tests/test_enrollment.py index f4c7228b2b..857098952f 100644 --- a/lms/djangoapps/instructor/tests/test_enrollment.py +++ b/lms/djangoapps/instructor/tests/test_enrollment.py @@ -3,7 +3,7 @@ Unit tests for instructor.enrollment methods. """ import json -from django.contrib.auth.models import Group, User +from django.contrib.auth.models import User # from courseware.access import _course_staff_group_name from courseware.models import StudentModule from django.test import TestCase @@ -25,13 +25,13 @@ class TestInstructorEnrollmentDB(TestCase): strings.append("Lorem@ipsum.dolor, sit@amet.consectetur\nadipiscing@elit.Aenean\r convallis@at.lacus\r, ut@lacinia.Sed") lists.append(['Lorem@ipsum.dolor', 'sit@amet.consectetur', 'adipiscing@elit.Aenean', 'convallis@at.lacus', 'ut@lacinia.Sed']) - for (s, l) in zip(strings, lists): - self.assertEqual(split_input_list(s), l) + for (stng, lst) in zip(strings, lists): + self.assertEqual(split_input_list(stng), lst) def test_enroll_emails_userexists_alreadyenrolled(self): user = UserFactory() - ce = CourseEnrollment(course_id=self.course_id, user=user) - ce.save() + cenr = CourseEnrollment(course_id=self.course_id, user=user) + cenr.save() self.assertEqual(CourseEnrollment.objects.filter(course_id=self.course_id, user__email=user.email).count(), 1) @@ -49,7 +49,7 @@ class TestInstructorEnrollmentDB(TestCase): self.assertEqual(CourseEnrollment.objects.filter(course_id=self.course_id, user__email=user.email).count(), 1) def test_enroll_emails_nouser_alreadyallowed(self): - email_without_user = 'test_enroll_emails_nouser_alreadyallowed@test.org' + email_without_user = 'robot_enroll_emails_nouser_alreadyallowed@test.org' self.assertEqual(User.objects.filter(email=email_without_user).count(), 0) self.assertEqual(CourseEnrollment.objects.filter(course_id=self.course_id, user__email=email_without_user).count(), 0) @@ -65,7 +65,7 @@ class TestInstructorEnrollmentDB(TestCase): self.assertEqual(CourseEnrollmentAllowed.objects.get(course_id=self.course_id, email=email_without_user).auto_enroll, False) def test_enroll_emails_nouser_suceedallow(self): - email_without_user = 'test_enroll_emails_nouser_suceedallow@test.org' + email_without_user = 'robot_enroll_emails_nouser_suceedallow@test.org' self.assertEqual(User.objects.filter(email=email_without_user).count(), 0) self.assertEqual(CourseEnrollment.objects.filter(course_id=self.course_id, user__email=email_without_user).count(), 0) @@ -81,9 +81,9 @@ class TestInstructorEnrollmentDB(TestCase): user1 = UserFactory() user2 = UserFactory() user3 = UserFactory() - email_without_user1 = 'test_enroll_emails_nouser_suceedallow_1@test.org' - email_without_user2 = 'test_enroll_emails_nouser_suceedallow_2@test.org' - email_without_user3 = 'test_enroll_emails_nouser_suceedallow_3@test.org' + email_without_user1 = 'robot_enroll_emails_nouser_suceedallow_1@test.org' + email_without_user2 = 'robot_enroll_emails_nouser_suceedallow_2@test.org' + email_without_user3 = 'robot_enroll_emails_nouser_suceedallow_3@test.org' def test_db(auto_enroll): for user in [user1, user2, user3]: @@ -101,7 +101,7 @@ class TestInstructorEnrollmentDB(TestCase): test_db(False) def test_unenroll_alreadyallowed(self): - email_without_user = 'test_unenroll_alreadyallowed@test.org' + email_without_user = 'robot_unenroll_alreadyallowed@test.org' cea = CourseEnrollmentAllowed(course_id=self.course_id, email=email_without_user, auto_enroll=False) cea.save() @@ -113,8 +113,8 @@ class TestInstructorEnrollmentDB(TestCase): def test_unenroll_alreadyenrolled(self): user = UserFactory() - ce = CourseEnrollment(course_id=self.course_id, user=user) - ce.save() + cenr = CourseEnrollment(course_id=self.course_id, user=user) + cenr.save() unenroll_emails(self.course_id, [user.email]) @@ -130,7 +130,7 @@ class TestInstructorEnrollmentDB(TestCase): self.assertEqual(CourseEnrollmentAllowed.objects.filter(course_id=self.course_id, email=user.email).count(), 0) def test_unenroll_nosuchuser(self): - email_without_user = 'test_unenroll_nosuchuser@test.org' + email_without_user = 'robot_unenroll_nosuchuser@test.org' unenroll_emails(self.course_id, [email_without_user]) diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index f82de025f2..dfea9b3964 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -52,7 +52,9 @@ def students_update_enrollment_email(request, course_id): - emails is string containing a list of emails separated by anything split_input_list can handle. - auto_enroll is a boolean (defaults to false) """ - course = get_course_with_access(request.user, course_id, 'staff', depth=None) + course = get_course_with_access( + request.user, course_id, 'staff', depth=None + ) action = request.GET.get('action') emails = split_input_list(request.GET.get('emails')) @@ -66,11 +68,13 @@ def students_update_enrollment_email(request, course_id): raise ValueError("unrecognized action '{}'".format(action)) response_payload = { - 'action': action, - 'results': results, + 'action': action, + 'results': results, 'auto_enroll': auto_enroll, } - response = HttpResponse(json.dumps(response_payload), content_type="application/json") + response = HttpResponse( + json.dumps(response_payload), content_type="application/json" + ) return response @@ -87,7 +91,9 @@ def access_allow_revoke(request, course_id): rolename is one of ['instructor', 'staff', 'beta'] mode is one of ['allow', 'revoke'] """ - course = get_course_with_access(request.user, course_id, 'instructor', depth=None) + course = get_course_with_access( + request.user, course_id, 'instructor', depth=None + ) email = request.GET.get('email') rolename = request.GET.get('rolename') @@ -105,7 +111,9 @@ def access_allow_revoke(request, course_id): response_payload = { 'DONE': 'YES', } - response = HttpResponse(json.dumps(response_payload), content_type="application/json") + response = HttpResponse( + json.dumps(response_payload), content_type="application/json" + ) return response @@ -118,7 +126,9 @@ def list_course_role_members(request, course_id): rolename is one of ['instructor', 'staff', 'beta'] """ - course = get_course_with_access(request.user, course_id, 'staff', depth=None) + course = get_course_with_access( + request.user, course_id, 'staff', depth=None + ) rolename = request.GET.get('rolename') @@ -134,10 +144,14 @@ def list_course_role_members(request, course_id): } response_payload = { - 'course_id': course_id, - rolename: map(extract_user_info, access.list_with_level(course, rolename)), + 'course_id': course_id, + rolename: map(extract_user_info, access.list_with_level( + course, rolename + )), } - response = HttpResponse(json.dumps(response_payload), content_type="application/json") + response = HttpResponse( + json.dumps(response_payload), content_type="application/json" + ) return response @@ -149,14 +163,18 @@ def grading_config(request, course_id): TODO maybe this shouldn't be html already """ - course = get_course_with_access(request.user, course_id, 'staff', depth=None) + course = get_course_with_access( + request.user, course_id, 'staff', depth=None + ) grading_config_summary = analytics.basic.dump_grading_context(course) response_payload = { 'course_id': course_id, 'grading_config_summary': grading_config_summary, } - response = HttpResponse(json.dumps(response_payload), content_type="application/json") + response = HttpResponse( + json.dumps(response_payload), content_type="application/json" + ) return response @@ -170,7 +188,9 @@ def enrolled_students_profiles(request, course_id, csv=False): TODO accept requests for different attribute sets """ - course = get_course_with_access(request.user, course_id, 'staff', depth=None) + course = get_course_with_access( + request.user, course_id, 'staff', depth=None + ) available_features = analytics.basic.AVAILABLE_FEATURES query_features = ['username', 'name', 'email', 'language', 'location', 'year_of_birth', 'gender', @@ -180,13 +200,15 @@ def enrolled_students_profiles(request, course_id, csv=False): if not csv: response_payload = { - 'course_id': course_id, - 'students': student_data, - 'students_count': len(student_data), - 'queried_features': query_features, + 'course_id': course_id, + 'students': student_data, + 'students_count': len(student_data), + 'queried_features': query_features, 'available_features': available_features, } - response = HttpResponse(json.dumps(response_payload), content_type="application/json") + response = HttpResponse( + json.dumps(response_payload), content_type="application/json" + ) return response else: formatted = analytics.csvs.format_dictlist(student_data) @@ -213,7 +235,9 @@ def profile_distribution(request, course_id): TODO how should query parameter interpretation work? TODO respond to csv requests as well """ - course = get_course_with_access(request.user, course_id, 'staff', depth=None) + course = get_course_with_access( + request.user, course_id, 'staff', depth=None + ) try: features = json.loads(request.GET.get('features')) @@ -230,17 +254,19 @@ def profile_distribution(request, course_id): raise e response_payload = { - 'course_id': course_id, - 'queried_features': features, + 'course_id': course_id, + 'queried_features': features, 'available_features': analytics.distributions.AVAILABLE_PROFILE_FEATURES, - 'display_names': { + 'display_names': { 'gender': 'Gender', 'level_of_education': 'Level of Education', 'year_of_birth': 'Year Of Birth', }, - 'feature_results': feature_results, + 'feature_results': feature_results, } - response = HttpResponse(json.dumps(response_payload), content_type="application/json") + response = HttpResponse( + json.dumps(response_payload), content_type="application/json" + ) return response @@ -256,7 +282,9 @@ def get_student_progress_url(request, course_id): 'progress_url': '/../...' } """ - course = get_course_with_access(request.user, course_id, 'staff', depth=None) + course = get_course_with_access( + request.user, course_id, 'staff', depth=None + ) student_email = request.GET.get('student_email') if not student_email: @@ -267,10 +295,12 @@ def get_student_progress_url(request, course_id): progress_url = reverse('student_progress', kwargs={'course_id': course_id, 'student_id': user.id}) response_payload = { - 'course_id': course_id, + 'course_id': course_id, 'progress_url': progress_url, } - response = HttpResponse(json.dumps(response_payload), content_type="application/json") + response = HttpResponse( + json.dumps(response_payload), content_type="application/json" + ) return response @@ -284,7 +314,9 @@ def redirect_to_student_progress(request, course_id): Takes query parameter student_email """ - course = get_course_with_access(request.user, course_id, 'staff', depth=None) + course = get_course_with_access( + request.user, course_id, 'staff', depth=None + ) student_email = request.GET.get('student_email') if not student_email: @@ -295,10 +327,12 @@ def redirect_to_student_progress(request, course_id): progress_url = reverse('student_progress', kwargs={'course_id': course_id, 'student_id': user.id}) response_payload = { - 'course_id': course_id, + 'course_id': course_id, 'progress_url': progress_url, } - response = HttpResponse(json.dumps(response_payload), content_type="application/json") + response = HttpResponse( + json.dumps(response_payload), content_type="application/json" + ) return response @@ -316,7 +350,9 @@ def reset_student_attempts(request, course_id): - all_students is a boolean - delete_module is a boolean """ - course = get_course_with_access(request.user, course_id, 'staff', depth=None) + course = get_course_with_access( + request.user, course_id, 'staff', depth=None + ) problem_to_reset = request.GET.get('problem_to_reset') student_email = request.GET.get('student_email') @@ -345,7 +381,9 @@ def reset_student_attempts(request, course_id): else: return HttpResponseBadRequest() - response = HttpResponse(json.dumps(response_payload), content_type="application/json") + response = HttpResponse( + json.dumps(response_payload), content_type="application/json" + ) return response @@ -364,7 +402,9 @@ def rescore_problem(request, course_id): all_students will be ignored if student_email is present """ - course = get_course_with_access(request.user, course_id, 'staff', depth=None) + course = get_course_with_access( + request.user, course_id, 'staff', depth=None + ) problem_to_reset = request.GET.get('problem_to_reset') student_email = request.GET.get('student_email', False) @@ -389,7 +429,9 @@ def rescore_problem(request, course_id): else: return HttpResponseBadRequest() - response = HttpResponse(json.dumps(response_payload), content_type="application/json") + response = HttpResponse( + json.dumps(response_payload), content_type="application/json" + ) return response @@ -404,7 +446,9 @@ def list_instructor_tasks(request, course_id): - (optional) problem_urlname (same format as problem_to_reset in other api methods) - (optional) student_email """ - course = get_course_with_access(request.user, course_id, 'instructor', depth=None) + course = get_course_with_access( + request.user, course_id, 'instructor', depth=None + ) problem_urlname = request.GET.get('problem_urlname', False) student_email = request.GET.get('student_email', False) @@ -429,7 +473,9 @@ def list_instructor_tasks(request, course_id): response_payload = { 'tasks': map(extract_task_features, tasks), } - response = HttpResponse(json.dumps(response_payload), content_type="application/json") + response = HttpResponse( + json.dumps(response_payload), content_type="application/json" + ) return response @@ -442,7 +488,9 @@ def list_forum_members(request, course_id): Takes query parameter rolename """ - course = get_course_with_access(request.user, course_id, 'staff', depth=None) + course = get_course_with_access( + request.user, course_id, 'staff', depth=None + ) rolename = request.GET.get('rolename') @@ -465,9 +513,11 @@ def list_forum_members(request, course_id): response_payload = { 'course_id': course_id, - rolename: map(extract_user_info, users), + rolename: map(extract_user_info, users), } - response = HttpResponse(json.dumps(response_payload), content_type="application/json") + response = HttpResponse( + json.dumps(response_payload), content_type="application/json" + ) return response @@ -483,7 +533,9 @@ def update_forum_role_membership(request, course_id): rolename is one of [FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA] mode is one of ['allow', 'revoke'] """ - course = get_course_with_access(request.user, course_id, 'instructor', depth=None) + course = get_course_with_access( + request.user, course_id, 'instructor', depth=None + ) email = request.GET.get('email') rolename = request.GET.get('rolename') @@ -500,10 +552,12 @@ def update_forum_role_membership(request, course_id): response_payload = { 'course_id': course_id, - 'mode': mode, + 'mode': mode, 'DONE': 'YES', } - response = HttpResponse(json.dumps(response_payload), content_type="application/json") + response = HttpResponse( + json.dumps(response_payload), content_type="application/json" + ) return response diff --git a/lms/djangoapps/instructor/views/instructor_dashboard.py b/lms/djangoapps/instructor/views/instructor_dashboard.py index 6d622dd26f..e69954b4a7 100644 --- a/lms/djangoapps/instructor/views/instructor_dashboard.py +++ b/lms/djangoapps/instructor/views/instructor_dashboard.py @@ -4,12 +4,6 @@ Instructor Dashboard Views TODO add tracking """ -import csv -import json -import logging -import os -import re -import requests from django_future.csrf import ensure_csrf_cookie from django.views.decorators.cache import cache_control from mitxmako.shortcuts import render_to_response @@ -17,12 +11,13 @@ from django.core.urlresolvers import reverse from django.utils.html import escape from django.http import Http404 -from django.conf import settings -from courseware.access import has_access, get_access_group_name, course_beta_test_group_name +from courseware.access import has_access from courseware.courses import get_course_by_id from django_comment_client.utils import has_forum_access -from instructor.offline_gradecalc import student_grades, offline_grades_available -from django_comment_common.models import Role, FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA +from django_comment_common.models import (Role, + FORUM_ROLE_ADMINISTRATOR, + FORUM_ROLE_MODERATOR, + FORUM_ROLE_COMMUNITY_TA) from xmodule.modulestore.django import modulestore from student.models import CourseEnrollment @@ -36,9 +31,12 @@ def instructor_dashboard_2(request, course_id): access = { 'admin': request.user.is_staff, - 'instructor': has_access(request.user, course, 'instructor'), # an instructor can manage staff lists - 'staff': has_access(request.user, course, 'staff'), - 'forum_admin': has_forum_access(request.user, course_id, FORUM_ROLE_ADMINISTRATOR), + # an instructor can manage staff lists + 'instructor': has_access(request.user, course, 'instructor'), + 'staff': has_access(request.user, course, 'staff'), + 'forum_admin': has_forum_access( + request.user, course_id, FORUM_ROLE_ADMINISTRATOR + ), } if not access['staff']: @@ -107,7 +105,7 @@ def _section_membership(course_id, access): 'section_key': 'membership', 'section_display_name': 'Membership', 'access': access, - 'enroll_button_url': reverse('students_update_enrollment_email', kwargs={'course_id': course_id}), + 'enroll_button_url': reverse('students_update_enrollment_email', kwargs={'course_id': course_id}), 'unenroll_button_url': reverse('students_update_enrollment_email', kwargs={'course_id': course_id}), 'list_course_role_members_url': reverse('list_course_role_members', kwargs={'course_id': course_id}), 'access_allow_revoke_url': reverse('access_allow_revoke', kwargs={'course_id': course_id}), @@ -136,7 +134,7 @@ def _section_data_download(course_id): section_data = { 'section_key': 'data_download', 'section_display_name': 'Data Download', - 'grading_config_url': reverse('grading_config', kwargs={'course_id': course_id}), + 'grading_config_url': reverse('grading_config', kwargs={'course_id': course_id}), 'enrolled_students_profiles_url': reverse('enrolled_students_profiles', kwargs={'course_id': course_id}), } return section_data