From 54262bc8e8ce8bc557735be28df8d7f7317e4d98 Mon Sep 17 00:00:00 2001 From: Sarina Canelake Date: Tue, 8 Dec 2015 14:28:04 -0500 Subject: [PATCH] Remove ORA1 management commands --- .../management/commands/openended_post.py | 133 ------------ .../management/commands/openended_stats.py | 136 ------------- .../tests/test_openended_commands.py | 192 ------------------ 3 files changed, 461 deletions(-) delete mode 100644 lms/djangoapps/instructor/management/commands/openended_post.py delete mode 100644 lms/djangoapps/instructor/management/commands/openended_stats.py delete mode 100644 lms/djangoapps/instructor/management/tests/test_openended_commands.py diff --git a/lms/djangoapps/instructor/management/commands/openended_post.py b/lms/djangoapps/instructor/management/commands/openended_post.py deleted file mode 100644 index 6365c9a7b1..0000000000 --- a/lms/djangoapps/instructor/management/commands/openended_post.py +++ /dev/null @@ -1,133 +0,0 @@ -""" -Command to manually re-post open ended submissions to the grader. -""" -from django.contrib.auth.models import User -from django.core.management.base import BaseCommand -from optparse import make_option - -from xmodule.modulestore.django import modulestore -from opaque_keys.edx.locations import SlashSeparatedCourseKey -from xmodule.open_ended_grading_classes.openendedchild import OpenEndedChild -from xmodule.open_ended_grading_classes.open_ended_module import OpenEndedModule - -from courseware.courses import get_course - -from instructor.utils import get_module_for_student - - -class Command(BaseCommand): - """ - Command to manually re-post open ended submissions to the grader. - """ - - help = ("Usage: openended_post --dry-run --task-number=\n" - "The text file should contain a User.id in each line.") - - option_list = BaseCommand.option_list + ( - make_option('-n', '--dry-run', - action='store_true', dest='dry_run', default=False, - help="Do everything except send the submission to the grader. "), - make_option('--task-number', - type='int', default=0, - help="Task number that needs to be submitted."), - ) - - def handle(self, *args, **options): - - dry_run = options['dry_run'] - task_number = options['task_number'] - - if len(args) == 4: - course_id = SlashSeparatedCourseKey.from_deprecated_string(args[0]) - location = course_id.make_usage_key_from_deprecated_string(args[1]) - students_ids = [line.strip() for line in open(args[2])] - hostname = args[3] - else: - print self.help - return - - try: - course = get_course(course_id) - except ValueError as err: - print err - return - - descriptor = modulestore().get_item(location, depth=0) - if descriptor is None: - print "Location not found in course" - return - - if dry_run: - print "Doing a dry run." - - students = User.objects.filter(id__in=students_ids).order_by('username') - print "Number of students: {0}".format(students.count()) - - for student in students: - post_submission_for_student(student, course, location, task_number, dry_run=dry_run, hostname=hostname) - - -def post_submission_for_student(student, course, location, task_number, dry_run=True, hostname=None): - """If the student's task child_state is ASSESSING post submission to grader.""" - - print "{0}:{1}".format(student.id, student.username) - - request = DummyRequest() - request.user = student - request.host = hostname - - try: - module = get_module_for_student(student, location, request=request, course=course) - if module is None: - print " WARNING: No state found." - return False - - latest_task = module.child_module.get_task_number(task_number) - if latest_task is None: - print " WARNING: No task state found." - return False - - if not isinstance(latest_task, OpenEndedModule): - print " ERROR: Not an OpenEndedModule task." - return False - - latest_task_state = latest_task.child_state - - if latest_task_state == OpenEndedChild.INITIAL: - print " WARNING: No submission." - elif latest_task_state == OpenEndedChild.POST_ASSESSMENT or latest_task_state == OpenEndedChild.DONE: - print " WARNING: Submission already graded." - elif latest_task_state == OpenEndedChild.ASSESSING: - latest_answer = latest_task.latest_answer() - if dry_run: - print " Skipped sending submission to grader: {0!r}".format(latest_answer[:100].encode('utf-8')) - else: - latest_task.send_to_grader(latest_answer, latest_task.system) - print " Sent submission to grader: {0!r}".format(latest_answer[:100].encode('utf-8')) - return True - else: - print "WARNING: Invalid task_state: {0}".format(latest_task_state) - except Exception as err: # pylint: disable=broad-except - print err - - return False - - -class DummyRequest(object): - """Dummy request""" - - META = {} - - def __init__(self): - self.session = {} - self.user = None - self.host = None - self.secure = True - - def get_host(self): - """Return a default host.""" - return self.host - - def is_secure(self): - """Always secure.""" - return self.secure diff --git a/lms/djangoapps/instructor/management/commands/openended_stats.py b/lms/djangoapps/instructor/management/commands/openended_stats.py deleted file mode 100644 index 11df4d971a..0000000000 --- a/lms/djangoapps/instructor/management/commands/openended_stats.py +++ /dev/null @@ -1,136 +0,0 @@ -""" -Command to get statistics about open ended problems. -""" -import csv -import time - -from django.core.management.base import BaseCommand -from optparse import make_option - -from xmodule.modulestore.django import modulestore -from opaque_keys.edx.locations import SlashSeparatedCourseKey -from xmodule.open_ended_grading_classes.openendedchild import OpenEndedChild - -from courseware.courses import get_course -from courseware.models import StudentModule -from student.models import anonymous_id_for_user, CourseEnrollment - -from instructor.utils import get_module_for_student - - -class Command(BaseCommand): - """ - Command to get statistics about open ended problems. - """ - - help = "Usage: openended_stats --task-number=\n" - - option_list = BaseCommand.option_list + ( - make_option('--task-number', - type='int', default=0, - help="Task number to get statistics about."), - ) - - def handle(self, *args, **options): - """Handler for command.""" - - task_number = options['task_number'] - - if len(args) == 2: - course_id = SlashSeparatedCourseKey.from_deprecated_string(args[0]) - usage_key = course_id.make_usage_key_from_deprecated_string(args[1]) - else: - print self.help - return - - try: - course = get_course(course_id) - except ValueError as err: - print err - return - - descriptor = modulestore().get_item(usage_key, depth=0) - if descriptor is None: - print "Location {0} not found in course".format(usage_key) - return - - try: - enrolled_students = CourseEnrollment.objects.users_enrolled_in(course_id) - print "Total students enrolled in {0}: {1}".format(course_id, enrolled_students.count()) - - calculate_task_statistics(enrolled_students, course, usage_key, task_number) - - except KeyboardInterrupt: - print "\nOperation Cancelled" - - -def calculate_task_statistics(students, course, location, task_number, write_to_file=True): - """Print stats of students.""" - - stats = { - OpenEndedChild.INITIAL: 0, - OpenEndedChild.ASSESSING: 0, - OpenEndedChild.POST_ASSESSMENT: 0, - OpenEndedChild.DONE: 0 - } - - students_with_saved_answers = [] - students_with_ungraded_submissions = [] # pylint: disable=invalid-name - students_with_graded_submissions = [] # pylint: disable=invalid-name - students_with_no_state = [] - - student_modules = StudentModule.objects.filter(module_state_key=location, student__in=students).order_by('student') - print "Total student modules: {0}".format(student_modules.count()) - - for index, student_module in enumerate(student_modules): - if index % 100 == 0: - print "--- {0} students processed ---".format(index) - - student = student_module.student - print "{0}:{1}".format(student.id, student.username) - - module = get_module_for_student(student, location, course=course) - if module is None: - print " WARNING: No state found" - students_with_no_state.append(student) - continue - - latest_task = module.child_module.get_task_number(task_number) - if latest_task is None: - print " No task state found" - students_with_no_state.append(student) - continue - - task_state = latest_task.child_state - stats[task_state] += 1 - print " State: {0}".format(task_state) - - if task_state == OpenEndedChild.INITIAL: - if latest_task.stored_answer is not None: - students_with_saved_answers.append(student) - elif task_state == OpenEndedChild.ASSESSING: - students_with_ungraded_submissions.append(student) - elif task_state == OpenEndedChild.POST_ASSESSMENT or task_state == OpenEndedChild.DONE: - students_with_graded_submissions.append(student) - - print "----------------------------------" - print "Time: {0}".format(time.strftime("%Y %b %d %H:%M:%S +0000", time.gmtime())) - print "Course: {0}".format(course.id) - print "Location: {0}".format(location) - print "No state: {0}".format(len(students_with_no_state)) - print "Initial State: {0}".format(stats[OpenEndedChild.INITIAL] - len(students_with_saved_answers)) - print "Saved answers: {0}".format(len(students_with_saved_answers)) - print "Submitted answers: {0}".format(stats[OpenEndedChild.ASSESSING]) - print "Received grades: {0}".format(stats[OpenEndedChild.POST_ASSESSMENT] + stats[OpenEndedChild.DONE]) - print "----------------------------------" - - if write_to_file: - filename = "stats.{0}.{1}".format(location.course, location.name) - time_stamp = time.strftime("%Y%m%d-%H%M%S") - with open('{0}.{1}.csv'.format(filename, time_stamp), 'wb') as csv_file: - writer = csv.writer(csv_file, delimiter=' ', quoting=csv.QUOTE_MINIMAL) - for student in students_with_ungraded_submissions: - writer.writerow(("ungraded", student.id, anonymous_id_for_user(student, None), student.username)) - for student in students_with_graded_submissions: - writer.writerow(("graded", student.id, anonymous_id_for_user(student, None), student.username)) - return stats diff --git a/lms/djangoapps/instructor/management/tests/test_openended_commands.py b/lms/djangoapps/instructor/management/tests/test_openended_commands.py deleted file mode 100644 index 4258a42446..0000000000 --- a/lms/djangoapps/instructor/management/tests/test_openended_commands.py +++ /dev/null @@ -1,192 +0,0 @@ -"""Test the openended_post management command.""" - -from datetime import datetime -import json -from mock import patch -from pytz import UTC - -from django.conf import settings -from opaque_keys.edx.locations import Location - -import capa.xqueue_interface as xqueue_interface -from courseware.courses import get_course_with_access -from courseware.tests.factories import StudentModuleFactory, UserFactory -from xmodule.modulestore.django import modulestore -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase -from xmodule.modulestore.xml_importer import import_course_from_xml -from xmodule.open_ended_grading_classes.openendedchild import OpenEndedChild -from xmodule.tests.test_util_open_ended import ( - STATE_INITIAL, STATE_ACCESSING, STATE_POST_ASSESSMENT -) -from student.models import anonymous_id_for_user - -from instructor.management.commands.openended_post import post_submission_for_student -from instructor.management.commands.openended_stats import calculate_task_statistics -from instructor.utils import get_module_for_student - -TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT - - -class OpenEndedPostTest(ModuleStoreTestCase): - """Test the openended_post management command.""" - - def setUp(self): - super(OpenEndedPostTest, self).setUp() - self.user = UserFactory() - store = modulestore() - course_items = import_course_from_xml(store, self.user.id, TEST_DATA_DIR, ['open_ended']) # pylint: disable=maybe-no-member - self.course = course_items[0] - self.course_id = self.course.id - - self.problem_location = Location("edX", "open_ended", "2012_Fall", "combinedopenended", "SampleQuestion") - self.self_assessment_task_number = 0 - self.open_ended_task_number = 1 - - self.student_on_initial = UserFactory() - self.student_on_accessing = UserFactory() - self.student_on_post_assessment = UserFactory() - - StudentModuleFactory.create( - course_id=self.course_id, - module_state_key=self.problem_location, - student=self.student_on_initial, - grade=0, - max_grade=1, - state=STATE_INITIAL - ) - - StudentModuleFactory.create( - course_id=self.course_id, - module_state_key=self.problem_location, - student=self.student_on_accessing, - grade=0, - max_grade=1, - state=STATE_ACCESSING - ) - - StudentModuleFactory.create( - course_id=self.course_id, - module_state_key=self.problem_location, - student=self.student_on_post_assessment, - grade=0, - max_grade=1, - state=STATE_POST_ASSESSMENT - ) - - def test_post_submission_for_student_on_initial(self): - course = get_course_with_access(self.student_on_initial, 'load', self.course_id) - - dry_run_result = post_submission_for_student(self.student_on_initial, course, self.problem_location, self.open_ended_task_number, dry_run=True) - self.assertFalse(dry_run_result) - - result = post_submission_for_student(self.student_on_initial, course, self.problem_location, self.open_ended_task_number, dry_run=False) - self.assertFalse(result) - - def test_post_submission_for_student_on_accessing(self): - course = get_course_with_access(self.student_on_accessing, 'load', self.course_id) - - dry_run_result = post_submission_for_student(self.student_on_accessing, course, self.problem_location, self.open_ended_task_number, dry_run=True) - self.assertFalse(dry_run_result) - - with patch('capa.xqueue_interface.XQueueInterface.send_to_queue') as mock_send_to_queue: - mock_send_to_queue.return_value = (0, "Successfully queued") - - module = get_module_for_student(self.student_on_accessing, self.problem_location) - module.child_module.get_task_number(self.open_ended_task_number) - - student_response = "Here is an answer." - student_anonymous_id = anonymous_id_for_user(self.student_on_accessing, None) - submission_time = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat) - - result = post_submission_for_student(self.student_on_accessing, course, self.problem_location, self.open_ended_task_number, dry_run=False) - - self.assertTrue(result) - mock_send_to_queue_body_arg = json.loads(mock_send_to_queue.call_args[1]['body']) - self.assertEqual(mock_send_to_queue_body_arg['max_score'], 2) - self.assertEqual(mock_send_to_queue_body_arg['student_response'], student_response) - body_arg_student_info = json.loads(mock_send_to_queue_body_arg['student_info']) - self.assertEqual(body_arg_student_info['anonymous_student_id'], student_anonymous_id) - self.assertGreaterEqual(body_arg_student_info['submission_time'], submission_time) - - def test_post_submission_for_student_on_post_assessment(self): - course = get_course_with_access(self.student_on_post_assessment, 'load', self.course_id) - - dry_run_result = post_submission_for_student(self.student_on_post_assessment, course, self.problem_location, self.open_ended_task_number, dry_run=True) - self.assertFalse(dry_run_result) - - result = post_submission_for_student(self.student_on_post_assessment, course, self.problem_location, self.open_ended_task_number, dry_run=False) - self.assertFalse(result) - - def test_post_submission_for_student_invalid_task(self): - course = get_course_with_access(self.student_on_accessing, 'load', self.course_id) - - result = post_submission_for_student(self.student_on_accessing, course, self.problem_location, self.self_assessment_task_number, dry_run=False) - self.assertFalse(result) - - out_of_bounds_task_number = 3 - result = post_submission_for_student(self.student_on_accessing, course, self.problem_location, out_of_bounds_task_number, dry_run=False) - self.assertFalse(result) - - -class OpenEndedStatsTest(ModuleStoreTestCase): - """Test the openended_stats management command.""" - - def setUp(self): - super(OpenEndedStatsTest, self).setUp() - - self.user = UserFactory() - store = modulestore() - course_items = import_course_from_xml(store, self.user.id, TEST_DATA_DIR, ['open_ended']) # pylint: disable=maybe-no-member - self.course = course_items[0] - - self.course_id = self.course.id - self.problem_location = Location("edX", "open_ended", "2012_Fall", "combinedopenended", "SampleQuestion") - self.task_number = 1 - self.invalid_task_number = 3 - - self.student_on_initial = UserFactory() - self.student_on_accessing = UserFactory() - self.student_on_post_assessment = UserFactory() - - StudentModuleFactory.create( - course_id=self.course_id, - module_state_key=self.problem_location, - student=self.student_on_initial, - grade=0, - max_grade=1, - state=STATE_INITIAL - ) - - StudentModuleFactory.create( - course_id=self.course_id, - module_state_key=self.problem_location, - student=self.student_on_accessing, - grade=0, - max_grade=1, - state=STATE_ACCESSING - ) - - StudentModuleFactory.create( - course_id=self.course_id, - module_state_key=self.problem_location, - student=self.student_on_post_assessment, - grade=0, - max_grade=1, - state=STATE_POST_ASSESSMENT - ) - - self.students = [self.student_on_initial, self.student_on_accessing, self.student_on_post_assessment] - - def test_calculate_task_statistics(self): - course = get_course_with_access(self.student_on_accessing, 'load', self.course_id) - stats = calculate_task_statistics(self.students, course, self.problem_location, self.task_number, write_to_file=False) - self.assertEqual(stats[OpenEndedChild.INITIAL], 1) - self.assertEqual(stats[OpenEndedChild.ASSESSING], 1) - self.assertEqual(stats[OpenEndedChild.POST_ASSESSMENT], 1) - self.assertEqual(stats[OpenEndedChild.DONE], 0) - - stats = calculate_task_statistics(self.students, course, self.problem_location, self.invalid_task_number, write_to_file=False) - self.assertEqual(stats[OpenEndedChild.INITIAL], 0) - self.assertEqual(stats[OpenEndedChild.ASSESSING], 0) - self.assertEqual(stats[OpenEndedChild.POST_ASSESSMENT], 0) - self.assertEqual(stats[OpenEndedChild.DONE], 0)