Commit 682d06bc by Vik Paruchuri

Fix a lot of pep8 violations

parent f72659fa
...@@ -104,11 +104,14 @@ class CombinedOpenEndedModule(CombinedOpenEndedFields, XModule): ...@@ -104,11 +104,14 @@ class CombinedOpenEndedModule(CombinedOpenEndedFields, XModule):
icon_class = 'problem' icon_class = 'problem'
js = {'coffee': js = {
[resource_string(__name__, 'js/src/combinedopenended/display.coffee'), 'coffee':
resource_string(__name__, 'js/src/collapsible.coffee'), [
resource_string(__name__, 'js/src/javascript_loader.coffee'), resource_string(__name__, 'js/src/combinedopenended/display.coffee'),
]} resource_string(__name__, 'js/src/collapsible.coffee'),
resource_string(__name__, 'js/src/javascript_loader.coffee'),
]
}
js_module_name = "CombinedOpenEnded" js_module_name = "CombinedOpenEnded"
css = {'scss': [resource_string(__name__, 'css/combinedopenended/display.scss')]} css = {'scss': [resource_string(__name__, 'css/combinedopenended/display.scss')]}
......
...@@ -294,9 +294,8 @@ class CombinedOpenEndedV1Module(): ...@@ -294,9 +294,8 @@ class CombinedOpenEndedV1Module():
if self.current_task_number > 0: if self.current_task_number > 0:
last_response_data = self.get_last_response(self.current_task_number - 1) last_response_data = self.get_last_response(self.current_task_number - 1)
current_response_data = self.get_current_attributes(self.current_task_number) current_response_data = self.get_current_attributes(self.current_task_number)
if (current_response_data['min_score_to_attempt'] > last_response_data['score'] if (current_response_data['min_score_to_attempt'] > last_response_data['score']
or current_response_data['max_score_to_attempt'] < last_response_data['score']): or current_response_data['max_score_to_attempt'] < last_response_data['score']):
self.state = self.DONE self.state = self.DONE
self.ready_to_reset = True self.ready_to_reset = True
...@@ -662,9 +661,10 @@ class CombinedOpenEndedV1Module(): ...@@ -662,9 +661,10 @@ class CombinedOpenEndedV1Module():
return { return {
'success': False, 'success': False,
#This is a student_facing_error #This is a student_facing_error
'error': ('You have attempted this question {0} times. ' 'error': (
'You are only allowed to attempt it {1} times.').format( 'You have attempted this question {0} times. '
self.student_attempts, self.attempts) 'You are only allowed to attempt it {1} times.'
).format(self.student_attempts, self.attempts)
} }
self.state = self.INITIAL self.state = self.INITIAL
self.ready_to_reset = False self.ready_to_reset = False
...@@ -815,7 +815,6 @@ class CombinedOpenEndedV1Module(): ...@@ -815,7 +815,6 @@ class CombinedOpenEndedV1Module():
'error': 'The problem state got out-of-sync. Please try reloading the page.'} 'error': 'The problem state got out-of-sync. Please try reloading the page.'}
class CombinedOpenEndedV1Descriptor(): class CombinedOpenEndedV1Descriptor():
""" """
Module for adding combined open ended questions Module for adding combined open ended questions
...@@ -861,7 +860,6 @@ class CombinedOpenEndedV1Descriptor(): ...@@ -861,7 +860,6 @@ class CombinedOpenEndedV1Descriptor():
return {'task_xml': parse_task('task'), 'prompt': parse('prompt'), 'rubric': parse('rubric')} return {'task_xml': parse_task('task'), 'prompt': parse('prompt'), 'rubric': parse('rubric')}
def definition_to_xml(self, resource_fs): def definition_to_xml(self, resource_fs):
'''Return an xml element representing this definition.''' '''Return an xml element representing this definition.'''
elt = etree.Element('combinedopenended') elt = etree.Element('combinedopenended')
......
...@@ -76,7 +76,6 @@ class GradingService(object): ...@@ -76,7 +76,6 @@ class GradingService(object):
return r.text return r.text
def _try_with_login(self, operation): def _try_with_login(self, operation):
""" """
Call operation(), which should return a requests response object. If Call operation(), which should return a requests response object. If
...@@ -87,7 +86,7 @@ class GradingService(object): ...@@ -87,7 +86,7 @@ class GradingService(object):
""" """
response = operation() response = operation()
if (response.json if (response.json
and response.json.get('success') == False and response.json.get('success') is False
and response.json.get('error') == 'login_required'): and response.json.get('error') == 'login_required'):
# apparrently we aren't logged in. Try to fix that. # apparrently we aren't logged in. Try to fix that.
r = self._login() r = self._login()
......
...@@ -72,7 +72,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -72,7 +72,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
self._parse(oeparam, self.child_prompt, self.child_rubric, system) self._parse(oeparam, self.child_prompt, self.child_rubric, system)
if self.child_created == True and self.child_state == self.ASSESSING: if self.child_created is True and self.child_state == self.ASSESSING:
self.child_created = False self.child_created = False
self.send_to_grader(self.latest_answer(), system) self.send_to_grader(self.latest_answer(), system)
self.child_created = False self.child_created = False
...@@ -159,9 +159,11 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -159,9 +159,11 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
score = int(survey_responses['score']) score = int(survey_responses['score'])
except: except:
#This is a dev_facing_error #This is a dev_facing_error
error_message = ("Could not parse submission id, grader id, " error_message = (
"or feedback from message_post ajax call. Here is the message data: {0}".format( "Could not parse submission id, grader id, "
survey_responses)) "or feedback from message_post ajax call. "
"Here is the message data: {0}".format(survey_responses)
)
log.exception(error_message) log.exception(error_message)
#This is a student_facing_error #This is a student_facing_error
return {'success': False, 'msg': "There was an error saving your feedback. Please contact course staff."} return {'success': False, 'msg': "There was an error saving your feedback. Please contact course staff."}
...@@ -179,8 +181,9 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -179,8 +181,9 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
queue_name=self.message_queue_name queue_name=self.message_queue_name
) )
student_info = {'anonymous_student_id': anonymous_student_id, student_info = {
'submission_time': qtime, 'anonymous_student_id': anonymous_student_id,
'submission_time': qtime,
} }
contents = { contents = {
'feedback': feedback, 'feedback': feedback,
...@@ -190,8 +193,10 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -190,8 +193,10 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
'student_info': json.dumps(student_info), 'student_info': json.dumps(student_info),
} }
(error, msg) = qinterface.send_to_queue(header=xheader, (error, msg) = qinterface.send_to_queue(
body=json.dumps(contents)) header=xheader,
body=json.dumps(contents)
)
#Convert error to a success value #Convert error to a success value
success = True success = True
...@@ -224,15 +229,18 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -224,15 +229,18 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
anonymous_student_id + anonymous_student_id +
str(len(self.child_history))) str(len(self.child_history)))
xheader = xqueue_interface.make_xheader(lms_callback_url=system.xqueue['construct_callback'](), xheader = xqueue_interface.make_xheader(
lms_callback_url=system.xqueue['construct_callback'](),
lms_key=queuekey, lms_key=queuekey,
queue_name=self.queue_name) queue_name=self.queue_name
)
contents = self.payload.copy() contents = self.payload.copy()
# Metadata related to the student submission revealed to the external grader # Metadata related to the student submission revealed to the external grader
student_info = {'anonymous_student_id': anonymous_student_id, student_info = {
'submission_time': qtime, 'anonymous_student_id': anonymous_student_id,
'submission_time': qtime,
} }
#Update contents with student response and student info #Update contents with student response and student info
...@@ -243,12 +251,16 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -243,12 +251,16 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
}) })
# Submit request. When successful, 'msg' is the prior length of the queue # Submit request. When successful, 'msg' is the prior length of the queue
qinterface.send_to_queue(header=xheader, qinterface.send_to_queue(
body=json.dumps(contents)) header=xheader,
body=json.dumps(contents)
)
# State associated with the queueing request # State associated with the queueing request
queuestate = {'key': queuekey, queuestate = {
'time': qtime, } 'key': queuekey,
'time': qtime,
}
return True return True
def _update_score(self, score_msg, queuekey, system): def _update_score(self, score_msg, queuekey, system):
...@@ -302,11 +314,13 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -302,11 +314,13 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
# We want to display available feedback in a particular order. # We want to display available feedback in a particular order.
# This dictionary specifies which goes first--lower first. # This dictionary specifies which goes first--lower first.
priorities = {# These go at the start of the feedback priorities = {
'spelling': 0, # These go at the start of the feedback
'grammar': 1, 'spelling': 0,
# needs to be after all the other feedback 'grammar': 1,
'markup_text': 3} # needs to be after all the other feedback
'markup_text': 3
}
do_not_render = ['topicality', 'prompt-overlap'] do_not_render = ['topicality', 'prompt-overlap']
default_priority = 2 default_priority = 2
...@@ -393,7 +407,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -393,7 +407,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
rubric_feedback = "" rubric_feedback = ""
feedback = self._convert_longform_feedback_to_html(response_items) feedback = self._convert_longform_feedback_to_html(response_items)
rubric_scores = [] rubric_scores = []
if response_items['rubric_scores_complete'] == True: if response_items['rubric_scores_complete'] is True:
rubric_renderer = CombinedOpenEndedRubric(system, True) rubric_renderer = CombinedOpenEndedRubric(system, True)
rubric_dict = rubric_renderer.render_rubric(response_items['rubric_xml']) rubric_dict = rubric_renderer.render_rubric(response_items['rubric_xml'])
success = rubric_dict['success'] success = rubric_dict['success']
...@@ -401,8 +415,10 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -401,8 +415,10 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
rubric_scores = rubric_dict['rubric_scores'] rubric_scores = rubric_dict['rubric_scores']
if not response_items['success']: if not response_items['success']:
return system.render_template("{0}/open_ended_error.html".format(self.TEMPLATE_DIR), return system.render_template(
{'errors': feedback}) "{0}/open_ended_error.html".format(self.TEMPLATE_DIR),
{'errors': feedback}
)
feedback_template = system.render_template("{0}/open_ended_feedback.html".format(self.TEMPLATE_DIR), { feedback_template = system.render_template("{0}/open_ended_feedback.html".format(self.TEMPLATE_DIR), {
'grader_type': response_items['grader_type'], 'grader_type': response_items['grader_type'],
...@@ -545,8 +561,11 @@ class OpenEndedModule(openendedchild.OpenEndedChild): ...@@ -545,8 +561,11 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
if not self.child_history: if not self.child_history:
return "" return ""
feedback_dict = self._parse_score_msg(self.child_history[-1].get('post_assessment', ""), system, feedback_dict = self._parse_score_msg(
join_feedback=join_feedback) self.child_history[-1].get('post_assessment', ""),
system,
join_feedback=join_feedback
)
if not short_feedback: if not short_feedback:
return feedback_dict['feedback'] if feedback_dict['valid'] else '' return feedback_dict['feedback'] if feedback_dict['valid'] else ''
if feedback_dict['valid']: if feedback_dict['valid']:
...@@ -734,8 +753,9 @@ class OpenEndedDescriptor(): ...@@ -734,8 +753,9 @@ class OpenEndedDescriptor():
"""Assumes that xml_object has child k""" """Assumes that xml_object has child k"""
return xml_object.xpath(k)[0] return xml_object.xpath(k)[0]
return {'oeparam': parse('openendedparam')} return {
'oeparam': parse('openendedparam')
}
def definition_to_xml(self, resource_fs): def definition_to_xml(self, resource_fs):
'''Return an xml element representing this definition.''' '''Return an xml element representing this definition.'''
......
...@@ -101,8 +101,9 @@ class OpenEndedChild(object): ...@@ -101,8 +101,9 @@ class OpenEndedChild(object):
# completion (doesn't matter if you self-assessed correct/incorrect). # completion (doesn't matter if you self-assessed correct/incorrect).
if system.open_ended_grading_interface: if system.open_ended_grading_interface:
self.peer_gs = PeerGradingService(system.open_ended_grading_interface, system) self.peer_gs = PeerGradingService(system.open_ended_grading_interface, system)
self.controller_qs = controller_query_service.ControllerQueryService(system.open_ended_grading_interface, self.controller_qs = controller_query_service.ControllerQueryService(
system) system.open_ended_grading_interface,system
)
else: else:
self.peer_gs = MockPeerGradingService() self.peer_gs = MockPeerGradingService()
self.controller_qs = None self.controller_qs = None
...@@ -180,8 +181,8 @@ class OpenEndedChild(object): ...@@ -180,8 +181,8 @@ class OpenEndedChild(object):
try: try:
answer = autolink_html(answer) answer = autolink_html(answer)
cleaner = Cleaner(style=True, links=True, add_nofollow=False, page_structure=True, safe_attrs_only=True, cleaner = Cleaner(style=True, links=True, add_nofollow=False, page_structure=True, safe_attrs_only=True,
host_whitelist=open_ended_image_submission.TRUSTED_IMAGE_DOMAINS, host_whitelist=open_ended_image_submission.TRUSTED_IMAGE_DOMAINS,
whitelist_tags=set(['embed', 'iframe', 'a', 'img'])) whitelist_tags=set(['embed', 'iframe', 'a', 'img']))
clean_html = cleaner.clean_html(answer) clean_html = cleaner.clean_html(answer)
clean_html = re.sub(r'</p>$', '', re.sub(r'^<p>', '', clean_html)) clean_html = re.sub(r'</p>$', '', re.sub(r'^<p>', '', clean_html))
except: except:
...@@ -282,7 +283,7 @@ class OpenEndedChild(object): ...@@ -282,7 +283,7 @@ class OpenEndedChild(object):
""" """
#This is a dev_facing_error #This is a dev_facing_error
log.warning("Open ended child state out sync. state: %r, get: %r. %s", log.warning("Open ended child state out sync. state: %r, get: %r. %s",
self.child_state, get, msg) self.child_state, get, msg)
#This is a student_facing_error #This is a student_facing_error
return {'success': False, return {'success': False,
'error': 'The problem state got out-of-sync. Please try reloading the page.'} 'error': 'The problem state got out-of-sync. Please try reloading the page.'}
...@@ -343,7 +344,7 @@ class OpenEndedChild(object): ...@@ -343,7 +344,7 @@ class OpenEndedChild(object):
try: try:
image_data.seek(0) image_data.seek(0)
success, s3_public_url = open_ended_image_submission.upload_to_s3(image_data, image_key, success, s3_public_url = open_ended_image_submission.upload_to_s3(image_data, image_key,
self.s3_interface) self.s3_interface)
except: except:
log.exception("Could not upload image to S3.") log.exception("Could not upload image to S3.")
...@@ -462,7 +463,7 @@ class OpenEndedChild(object): ...@@ -462,7 +463,7 @@ class OpenEndedChild(object):
allowed_to_submit = False allowed_to_submit = False
#This is a student_facing_error #This is a student_facing_error
error_message = error_string.format(count_required - count_graded, count_graded, count_required, error_message = error_string.format(count_required - count_graded, count_graded, count_required,
student_sub_count) student_sub_count)
return success, allowed_to_submit, error_message return success, allowed_to_submit, error_message
def get_eta(self): def get_eta(self):
......
...@@ -498,7 +498,6 @@ class PeerGradingModule(PeerGradingFields, XModule): ...@@ -498,7 +498,6 @@ class PeerGradingModule(PeerGradingFields, XModule):
log.error("Problem {0} does not exist in this course".format(location)) log.error("Problem {0} does not exist in this course".format(location))
raise raise
for problem in problem_list: for problem in problem_list:
problem_location = problem['location'] problem_location = problem['location']
descriptor = _find_corresponding_module_for_location(problem_location) descriptor = _find_corresponding_module_for_location(problem_location)
......
...@@ -18,7 +18,7 @@ import logging ...@@ -18,7 +18,7 @@ import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
from .import test_system from . import test_system
ORG = 'edX' ORG = 'edX'
COURSE = 'open_ended' # name of directory with course data COURSE = 'open_ended' # name of directory with course data
...@@ -70,8 +70,7 @@ class OpenEndedChildTest(unittest.TestCase): ...@@ -70,8 +70,7 @@ class OpenEndedChildTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.test_system = test_system() self.test_system = test_system()
self.openendedchild = OpenEndedChild(self.test_system, self.location, self.openendedchild = OpenEndedChild(self.test_system, self.location,
self.definition, self.descriptor, self.static_data, self.metadata) self.definition, self.descriptor, self.static_data, self.metadata)
def test_latest_answer_empty(self): def test_latest_answer_empty(self):
answer = self.openendedchild.latest_answer() answer = self.openendedchild.latest_answer()
...@@ -117,7 +116,7 @@ class OpenEndedChildTest(unittest.TestCase): ...@@ -117,7 +116,7 @@ class OpenEndedChildTest(unittest.TestCase):
post_assessment = "Post assessment" post_assessment = "Post assessment"
self.openendedchild.record_latest_post_assessment(post_assessment) self.openendedchild.record_latest_post_assessment(post_assessment)
self.assertEqual(post_assessment, self.assertEqual(post_assessment,
self.openendedchild.latest_post_assessment(self.test_system)) self.openendedchild.latest_post_assessment(self.test_system))
def test_get_score(self): def test_get_score(self):
new_answer = "New Answer" new_answer = "New Answer"
...@@ -144,12 +143,12 @@ class OpenEndedChildTest(unittest.TestCase): ...@@ -144,12 +143,12 @@ class OpenEndedChildTest(unittest.TestCase):
self.openendedchild.new_history_entry(new_answer) self.openendedchild.new_history_entry(new_answer)
self.openendedchild.record_latest_score(self.static_data['max_score']) self.openendedchild.record_latest_score(self.static_data['max_score'])
self.assertEqual(self.openendedchild.is_last_response_correct(), self.assertEqual(self.openendedchild.is_last_response_correct(),
'correct') 'correct')
self.openendedchild.new_history_entry(new_answer) self.openendedchild.new_history_entry(new_answer)
self.openendedchild.record_latest_score(0) self.openendedchild.record_latest_score(0)
self.assertEqual(self.openendedchild.is_last_response_correct(), self.assertEqual(self.openendedchild.is_last_response_correct(),
'incorrect') 'incorrect')
class OpenEndedModuleTest(unittest.TestCase): class OpenEndedModuleTest(unittest.TestCase):
...@@ -207,7 +206,7 @@ class OpenEndedModuleTest(unittest.TestCase): ...@@ -207,7 +206,7 @@ class OpenEndedModuleTest(unittest.TestCase):
'default_queuename': 'testqueue', 'default_queuename': 'testqueue',
'waittime': 1} 'waittime': 1}
self.openendedmodule = OpenEndedModule(self.test_system, self.location, self.openendedmodule = OpenEndedModule(self.test_system, self.location,
self.definition, self.descriptor, self.static_data, self.metadata) self.definition, self.descriptor, self.static_data, self.metadata)
def test_message_post(self): def test_message_post(self):
get = {'feedback': 'feedback text', get = {'feedback': 'feedback text',
...@@ -372,21 +371,20 @@ class CombinedOpenEndedModuleTest(unittest.TestCase): ...@@ -372,21 +371,20 @@ class CombinedOpenEndedModuleTest(unittest.TestCase):
descriptor = Mock(data=full_definition) descriptor = Mock(data=full_definition)
test_system = test_system() test_system = test_system()
combinedoe_container = CombinedOpenEndedModule(test_system, combinedoe_container = CombinedOpenEndedModule(test_system,
location, location,
descriptor, descriptor,
model_data={'data': full_definition, 'weight': '1'}) model_data={'data': full_definition, 'weight': '1'})
def setUp(self): def setUp(self):
# TODO: this constructor call is definitely wrong, but neither branch # TODO: this constructor call is definitely wrong, but neither branch
# of the merge matches the module constructor. Someone (Vik?) should fix this. # of the merge matches the module constructor. Someone (Vik?) should fix this.
self.combinedoe = CombinedOpenEndedV1Module(self.test_system, self.combinedoe = CombinedOpenEndedV1Module(self.test_system,
self.location, self.location,
self.definition, self.definition,
self.descriptor, self.descriptor,
static_data=self.static_data, static_data=self.static_data,
metadata=self.metadata, metadata=self.metadata,
instance_state=self.static_data) instance_state=self.static_data)
def test_get_tag_name(self): def test_get_tag_name(self):
name = self.combinedoe.get_tag_name("<t>Tag</t>") name = self.combinedoe.get_tag_name("<t>Tag</t>")
...@@ -441,12 +439,12 @@ class CombinedOpenEndedModuleTest(unittest.TestCase): ...@@ -441,12 +439,12 @@ class CombinedOpenEndedModuleTest(unittest.TestCase):
definition = {'prompt': etree.XML(self.prompt), 'rubric': etree.XML(self.rubric), 'task_xml': xml} definition = {'prompt': etree.XML(self.prompt), 'rubric': etree.XML(self.rubric), 'task_xml': xml}
descriptor = Mock(data=definition) descriptor = Mock(data=definition)
combinedoe = CombinedOpenEndedV1Module(self.test_system, combinedoe = CombinedOpenEndedV1Module(self.test_system,
self.location, self.location,
definition, definition,
descriptor, descriptor,
static_data=self.static_data, static_data=self.static_data,
metadata=self.metadata, metadata=self.metadata,
instance_state=self.static_data) instance_state=self.static_data)
changed = combinedoe.update_task_states() changed = combinedoe.update_task_states()
self.assertFalse(changed) self.assertFalse(changed)
...@@ -471,12 +469,12 @@ class CombinedOpenEndedModuleTest(unittest.TestCase): ...@@ -471,12 +469,12 @@ class CombinedOpenEndedModuleTest(unittest.TestCase):
'task_xml': [self.task_xml1, self.task_xml2]} 'task_xml': [self.task_xml1, self.task_xml2]}
descriptor = Mock(data=definition) descriptor = Mock(data=definition)
combinedoe = CombinedOpenEndedV1Module(self.test_system, combinedoe = CombinedOpenEndedV1Module(self.test_system,
self.location, self.location,
definition, definition,
descriptor, descriptor,
static_data=self.static_data, static_data=self.static_data,
metadata=self.metadata, metadata=self.metadata,
instance_state=instance_state) instance_state=instance_state)
score_dict = combinedoe.get_score() score_dict = combinedoe.get_score()
self.assertEqual(score_dict['score'], 15.0) self.assertEqual(score_dict['score'], 15.0)
self.assertEqual(score_dict['total'], 15.0) self.assertEqual(score_dict['total'], 15.0)
......
...@@ -18,11 +18,11 @@ S3_INTERFACE = { ...@@ -18,11 +18,11 @@ S3_INTERFACE = {
"aws_bucket_name": "", "aws_bucket_name": "",
} }
class MockQueryDict(dict): class MockQueryDict(dict):
""" """
Mock a query dict so that it can be used in test classes Mock a query dict so that it can be used in test classes
""" """
def getlist(self, key, default=None): def getlist(self, key, default=None):
try: try:
return super(MockQueryDict, self).__getitem__(key) return super(MockQueryDict, self).__getitem__(key)
...@@ -51,4 +51,4 @@ class DummyModulestore(object): ...@@ -51,4 +51,4 @@ class DummyModulestore(object):
if not isinstance(location, Location): if not isinstance(location, Location):
location = Location(location) location = Location(location)
descriptor = self.modulestore.get_instance(course.id, location, depth=None) descriptor = self.modulestore.get_instance(course.id, location, depth=None)
return descriptor.xmodule(self.test_system) return descriptor.xmodule(self.test_system)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment