Merge pull request #5828 from edx/sarina/moar-pep8
Remove more pep8 violations
This commit is contained in:
@@ -16,6 +16,7 @@ from django.conf import settings
|
||||
from mako.template import Template
|
||||
import textwrap
|
||||
|
||||
|
||||
class Command(NoArgsCommand):
|
||||
"""
|
||||
Basic management command to preprocess asset template files.
|
||||
@@ -45,7 +46,6 @@ class Command(NoArgsCommand):
|
||||
self.__preprocess(os.path.join(root, filename),
|
||||
os.path.join(root, outfile))
|
||||
|
||||
|
||||
def __context(self):
|
||||
"""
|
||||
Return a dict that contains all of the available context
|
||||
@@ -55,10 +55,9 @@ class Command(NoArgsCommand):
|
||||
# TODO: do this with the django-settings-context-processor
|
||||
return {
|
||||
"FEATURES": settings.FEATURES,
|
||||
"THEME_NAME" : getattr(settings, "THEME_NAME", None),
|
||||
"THEME_NAME": getattr(settings, "THEME_NAME", None),
|
||||
}
|
||||
|
||||
|
||||
def __preprocess(self, infile, outfile):
|
||||
"""
|
||||
Run `infile` through the Mako template engine, storing the
|
||||
@@ -73,4 +72,3 @@ class Command(NoArgsCommand):
|
||||
*/
|
||||
""" % infile))
|
||||
_outfile.write(Template(filename=str(infile)).render(env=self.__context()))
|
||||
|
||||
|
||||
@@ -168,8 +168,8 @@ class TestSafeExecCaching(unittest.TestCase):
|
||||
|
||||
def test_unicode_submission(self):
|
||||
# Check that using non-ASCII unicode does not raise an encoding error.
|
||||
# Try several non-ASCII unicode characters
|
||||
for code in [129, 500, 2**8 - 1, 2**16 - 1]:
|
||||
# Try several non-ASCII unicode characters.
|
||||
for code in [129, 500, 2 ** 8 - 1, 2 ** 16 - 1]:
|
||||
code_with_unichr = unicode("# ") + unichr(code)
|
||||
try:
|
||||
safe_exec(code_with_unichr, {}, cache=DictCache({}))
|
||||
@@ -194,7 +194,7 @@ class TestUpdateHash(unittest.TestCase):
|
||||
make them different.
|
||||
|
||||
"""
|
||||
d1 = {k:1 for k in "abcdefghijklmnopqrstuvwxyz"}
|
||||
d1 = {k: 1 for k in "abcdefghijklmnopqrstuvwxyz"}
|
||||
d2 = dict(d1)
|
||||
for i in xrange(10000):
|
||||
d2[i] = 1
|
||||
@@ -216,8 +216,8 @@ class TestUpdateHash(unittest.TestCase):
|
||||
self.assertNotEqual(h1, hs1)
|
||||
|
||||
def test_list_ordering(self):
|
||||
h1 = self.hash_obj({'a': [1,2,3]})
|
||||
h2 = self.hash_obj({'a': [3,2,1]})
|
||||
h1 = self.hash_obj({'a': [1, 2, 3]})
|
||||
h2 = self.hash_obj({'a': [3, 2, 1]})
|
||||
self.assertNotEqual(h1, h2)
|
||||
|
||||
def test_dict_ordering(self):
|
||||
@@ -228,8 +228,8 @@ class TestUpdateHash(unittest.TestCase):
|
||||
|
||||
def test_deep_ordering(self):
|
||||
d1, d2 = self.equal_but_different_dicts()
|
||||
o1 = {'a':[1, 2, [d1], 3, 4]}
|
||||
o2 = {'a':[1, 2, [d2], 3, 4]}
|
||||
o1 = {'a': [1, 2, [d1], 3, 4]}
|
||||
o2 = {'a': [1, 2, [d2], 3, 4]}
|
||||
h1 = self.hash_obj(o1)
|
||||
h2 = self.hash_obj(o2)
|
||||
self.assertEqual(h1, h2)
|
||||
|
||||
@@ -134,9 +134,11 @@ class ResponseXMLFactory(object):
|
||||
len(choice_names) == len(choices)
|
||||
"""
|
||||
# Names of group elements
|
||||
group_element_names = {'checkbox': 'checkboxgroup',
|
||||
'radio': 'radiogroup',
|
||||
'multiple': 'choicegroup'}
|
||||
group_element_names = {
|
||||
'checkbox': 'checkboxgroup',
|
||||
'radio': 'radiogroup',
|
||||
'multiple': 'choicegroup'
|
||||
}
|
||||
|
||||
# Retrieve **kwargs
|
||||
choices = kwargs.get('choices', [True])
|
||||
@@ -441,7 +443,6 @@ class FormulaResponseXMLFactory(ResponseXMLFactory):
|
||||
sample_str = self._sample_str(sample_dict, num_samples, tolerance)
|
||||
response_element.set("samples", sample_str)
|
||||
|
||||
|
||||
# Set the tolerance
|
||||
responseparam_element = etree.SubElement(response_element, "responseparam")
|
||||
responseparam_element.set("type", "tolerance")
|
||||
@@ -487,10 +488,12 @@ class FormulaResponseXMLFactory(ResponseXMLFactory):
|
||||
variables = [str(v) for v in sample_dict.keys()]
|
||||
low_range_vals = [str(f[0]) for f in sample_dict.values()]
|
||||
high_range_vals = [str(f[1]) for f in sample_dict.values()]
|
||||
sample_str = (",".join(sample_dict.keys()) + "@" +
|
||||
",".join(low_range_vals) + ":" +
|
||||
",".join(high_range_vals) +
|
||||
"#" + str(num_samples))
|
||||
sample_str = (
|
||||
",".join(sample_dict.keys()) + "@" +
|
||||
",".join(low_range_vals) + ":" +
|
||||
",".join(high_range_vals) +
|
||||
"#" + str(num_samples)
|
||||
)
|
||||
return sample_str
|
||||
|
||||
|
||||
@@ -501,7 +504,6 @@ class ImageResponseXMLFactory(ResponseXMLFactory):
|
||||
""" Create the <imageresponse> element."""
|
||||
return etree.Element("imageresponse")
|
||||
|
||||
|
||||
def create_input_element(self, **kwargs):
|
||||
""" Create the <imageinput> element.
|
||||
|
||||
@@ -578,7 +580,7 @@ class JavascriptResponseXMLFactory(ResponseXMLFactory):
|
||||
# Both display_src and display_class given,
|
||||
# or neither given
|
||||
assert((display_src and display_class) or
|
||||
(not display_src and not display_class))
|
||||
(not display_src and not display_class))
|
||||
|
||||
# Create the <javascriptresponse> element
|
||||
response_element = etree.Element("javascriptresponse")
|
||||
@@ -764,7 +766,7 @@ class AnnotationResponseXMLFactory(ResponseXMLFactory):
|
||||
text_children = [
|
||||
{'tag': 'title', 'text': kwargs.get('title', 'super cool annotation')},
|
||||
{'tag': 'text', 'text': kwargs.get('text', 'texty text')},
|
||||
{'tag': 'comment', 'text':kwargs.get('comment', 'blah blah erudite comment blah blah')},
|
||||
{'tag': 'comment', 'text': kwargs.get('comment', 'blah blah erudite comment blah blah')},
|
||||
{'tag': 'comment_prompt', 'text': kwargs.get('comment_prompt', 'type a commentary below')},
|
||||
{'tag': 'tag_prompt', 'text': kwargs.get('tag_prompt', 'select one tag')}
|
||||
]
|
||||
@@ -772,7 +774,7 @@ class AnnotationResponseXMLFactory(ResponseXMLFactory):
|
||||
for child in text_children:
|
||||
etree.SubElement(input_element, child['tag']).text = child['text']
|
||||
|
||||
default_options = [('green', 'correct'),('eggs', 'incorrect'), ('ham', 'partially-correct')]
|
||||
default_options = [('green', 'correct'), ('eggs', 'incorrect'), ('ham', 'partially-correct')]
|
||||
options = kwargs.get('options', default_options)
|
||||
options_element = etree.SubElement(input_element, 'options')
|
||||
|
||||
|
||||
@@ -96,9 +96,11 @@ def sub_miller(segments):
|
||||
'''
|
||||
fracts = [segment_to_fraction(segment) for segment in segments]
|
||||
common_denominator = reduce(lcm, [fract.denominator for fract in fracts])
|
||||
miller = ([fract.numerator * math.fabs(common_denominator) /
|
||||
fract.denominator for fract in fracts])
|
||||
return'(' + ','.join(map(str, map(decimal.Decimal, miller))) + ')'
|
||||
miller_indices = ([
|
||||
fract.numerator * math.fabs(common_denominator) / fract.denominator
|
||||
for fract in fracts
|
||||
])
|
||||
return'(' + ','.join(map(str, map(decimal.Decimal, miller_indices))) + ')'
|
||||
|
||||
|
||||
def miller(points):
|
||||
@@ -145,19 +147,22 @@ def miller(points):
|
||||
O = np.array([0, 0, 0])
|
||||
P = points[0] # point of plane
|
||||
Ccs = map(np.array, [[1.0, 0, 0], [0, 1.0, 0], [0, 0, 1.0]])
|
||||
segments = ([np.dot(P - O, N) / np.dot(ort, N) if np.dot(ort, N) != 0 else
|
||||
np.nan for ort in Ccs])
|
||||
segments = ([
|
||||
np.dot(P - O, N) / np.dot(ort, N) if np.dot(ort, N) != 0
|
||||
else np.nan for ort in Ccs
|
||||
])
|
||||
if any(x == 0 for x in segments): # Plane goes through origin.
|
||||
vertices = [ # top:
|
||||
np.array([1.0, 1.0, 1.0]),
|
||||
np.array([0.0, 0.0, 1.0]),
|
||||
np.array([1.0, 0.0, 1.0]),
|
||||
np.array([0.0, 1.0, 1.0]),
|
||||
# bottom, except 0,0,0:
|
||||
np.array([1.0, 0.0, 0.0]),
|
||||
np.array([0.0, 1.0, 0.0]),
|
||||
np.array([1.0, 1.0, 1.0]),
|
||||
]
|
||||
vertices = [
|
||||
# top:
|
||||
np.array([1.0, 1.0, 1.0]),
|
||||
np.array([0.0, 0.0, 1.0]),
|
||||
np.array([1.0, 0.0, 1.0]),
|
||||
np.array([0.0, 1.0, 1.0]),
|
||||
# bottom, except 0,0,0:
|
||||
np.array([1.0, 0.0, 0.0]),
|
||||
np.array([0.0, 1.0, 0.0]),
|
||||
np.array([1.0, 1.0, 1.0]),
|
||||
]
|
||||
for vertex in vertices:
|
||||
if np.dot(vertex - O, N) != 0: # vertex not in plane
|
||||
new_origin = vertex
|
||||
|
||||
@@ -9,7 +9,8 @@ from os.path import abspath, realpath, dirname, join as joinpath
|
||||
from django.core.exceptions import SuspiciousOperation
|
||||
import logging
|
||||
|
||||
log = logging.getLogger(__name__) # pylint: disable=C0103
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def resolved(rpath):
|
||||
"""
|
||||
@@ -17,12 +18,14 @@ def resolved(rpath):
|
||||
"""
|
||||
return realpath(abspath(rpath))
|
||||
|
||||
|
||||
def _is_bad_path(path, base):
|
||||
"""
|
||||
Is (the canonical absolute path of) `path` outside `base`?
|
||||
"""
|
||||
return not resolved(joinpath(base, path)).startswith(base)
|
||||
|
||||
|
||||
def _is_bad_link(info, base):
|
||||
"""
|
||||
Does the file sym- ord hard-link to files outside `base`?
|
||||
@@ -31,6 +34,7 @@ def _is_bad_link(info, base):
|
||||
tip = resolved(joinpath(base, dirname(info.name)))
|
||||
return _is_bad_path(info.linkname, base=tip)
|
||||
|
||||
|
||||
def safemembers(members):
|
||||
"""
|
||||
Check that all elements of a tar file are safe.
|
||||
@@ -43,19 +47,20 @@ def safemembers(members):
|
||||
log.debug("File %r is blocked (illegal path)", finfo.name)
|
||||
raise SuspiciousOperation("Illegal path")
|
||||
elif finfo.issym() and _is_bad_link(finfo, base):
|
||||
log.debug( "File %r is blocked: Hard link to %r", finfo.name, finfo.linkname)
|
||||
log.debug("File %r is blocked: Hard link to %r", finfo.name, finfo.linkname)
|
||||
raise SuspiciousOperation("Hard link")
|
||||
elif finfo.islnk() and _is_bad_link(finfo, base):
|
||||
log.debug("File %r is blocked: Symlink to %r", finfo.name,
|
||||
finfo.linkname)
|
||||
finfo.linkname)
|
||||
raise SuspiciousOperation("Symlink")
|
||||
elif finfo.isdev():
|
||||
log.debug("File %r is blocked: FIFO, device or character file",
|
||||
finfo.name)
|
||||
finfo.name)
|
||||
raise SuspiciousOperation("Dev file")
|
||||
|
||||
return members
|
||||
|
||||
|
||||
def safetar_extractall(tarf, *args, **kwargs):
|
||||
"""
|
||||
Safe version of `tarf.extractall()`.
|
||||
|
||||
@@ -21,13 +21,14 @@ log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def symmath_check_simple(expect, ans, adict={}, symtab=None, extra_options=None):
|
||||
'''
|
||||
"""
|
||||
Check a symbolic mathematical expression using sympy.
|
||||
The input is an ascii string (not MathML) converted to math using sympy.sympify.
|
||||
'''
|
||||
"""
|
||||
|
||||
options = {'__MATRIX__': False, '__ABC__': False, '__LOWER__': False}
|
||||
if extra_options: options.update(extra_options)
|
||||
if extra_options:
|
||||
options.update(extra_options)
|
||||
for op in options: # find options in expect string
|
||||
if op in expect:
|
||||
expect = expect.replace(op, '')
|
||||
@@ -145,6 +146,7 @@ def make_error_message(msg):
|
||||
msg = '<div class="capa_alert">%s</div>' % msg
|
||||
return msg
|
||||
|
||||
|
||||
def is_within_tolerance(expected, actual, tolerance):
|
||||
if expected == 0:
|
||||
return (abs(actual) < tolerance)
|
||||
@@ -158,7 +160,7 @@ def is_within_tolerance(expected, actual, tolerance):
|
||||
|
||||
|
||||
def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None):
|
||||
'''
|
||||
"""
|
||||
Check a symbolic mathematical expression using sympy.
|
||||
The input may be presentation MathML. Uses formula.
|
||||
|
||||
@@ -181,7 +183,7 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None
|
||||
-qubit - passed to my_sympify
|
||||
-imaginary - used in formla, presumably to signal to use i as sqrt(-1)?
|
||||
-numerical - force numerical comparison.
|
||||
'''
|
||||
"""
|
||||
|
||||
msg = ''
|
||||
# msg += '<p/>abname=%s' % abname
|
||||
@@ -208,7 +210,6 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None
|
||||
msg += '<p>Error %s in parsing OUR expected answer "%s"</p>' % (err, expect)
|
||||
return {'ok': False, 'msg': make_error_message(msg)}
|
||||
|
||||
|
||||
###### Sympy input #######
|
||||
# if expected answer is a number, try parsing provided answer as a number also
|
||||
try:
|
||||
@@ -217,8 +218,8 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None
|
||||
fans = None
|
||||
|
||||
# do a numerical comparison if both expected and answer are numbers
|
||||
if (hasattr(fexpect, 'is_number') and fexpect.is_number
|
||||
and hasattr(fans, 'is_number') and fans.is_number):
|
||||
if hasattr(fexpect, 'is_number') and fexpect.is_number \
|
||||
and hasattr(fans, 'is_number') and fans.is_number:
|
||||
if is_within_tolerance(fexpect, fans, threshold):
|
||||
return {'ok': True, 'msg': msg}
|
||||
else:
|
||||
@@ -236,7 +237,6 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None
|
||||
msg += '<p>You entered: %s</p>' % to_latex(fans)
|
||||
return {'ok': True, 'msg': msg}
|
||||
|
||||
|
||||
###### PMathML input ######
|
||||
# convert mathml answer to formula
|
||||
try:
|
||||
@@ -298,7 +298,8 @@ def symmath_check(expect, ans, dynamath=None, options=None, debug=None, xml=None
|
||||
return {'ok': False, 'msg': make_error_message(msg)}
|
||||
except Exception, err:
|
||||
msg += "<p>Error %s in comparing expected (a list) and your answer</p>" % str(err).replace('<', '<')
|
||||
if DEBUG: msg += "<p/><pre>%s</pre>" % traceback.format_exc()
|
||||
if DEBUG:
|
||||
msg += "<p/><pre>%s</pre>" % traceback.format_exc()
|
||||
return {'ok': False, 'msg': make_error_message(msg)}
|
||||
|
||||
#diff = (fexpect-fsym).simplify()
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
"""
|
||||
Tests of symbolic math
|
||||
"""
|
||||
|
||||
|
||||
import unittest
|
||||
import formula
|
||||
import re
|
||||
from lxml import etree
|
||||
|
||||
|
||||
def stripXML(xml):
|
||||
xml = xml.replace('\n', '')
|
||||
xml = re.sub(r'\> +\<', '><', xml)
|
||||
return xml
|
||||
|
||||
|
||||
class FormulaTest(unittest.TestCase):
|
||||
# for readability later
|
||||
mathml_start = '<math xmlns="http://www.w3.org/1998/Math/MathML"><mstyle displaystyle="true">'
|
||||
@@ -41,7 +41,6 @@ class FormulaTest(unittest.TestCase):
|
||||
# success?
|
||||
self.assertEqual(test, expected)
|
||||
|
||||
|
||||
def test_fix_simple_superscripts(self):
|
||||
expr = '''
|
||||
<msup>
|
||||
@@ -91,7 +90,6 @@ class FormulaTest(unittest.TestCase):
|
||||
# success?
|
||||
self.assertEqual(test, expected)
|
||||
|
||||
|
||||
def test_fix_msubsup(self):
|
||||
expr = '''
|
||||
<msubsup>
|
||||
@@ -100,7 +98,7 @@ class FormulaTest(unittest.TestCase):
|
||||
<mi>c</mi>
|
||||
</msubsup>'''
|
||||
|
||||
expected = '<msup><mi>a_b</mi><mi>c</mi></msup>' # which is (a_b)^c
|
||||
expected = '<msup><mi>a_b</mi><mi>c</mi></msup>' # which is (a_b)^c
|
||||
|
||||
# wrap
|
||||
expr = stripXML(self.mathml_start + expr + self.mathml_end)
|
||||
|
||||
@@ -257,7 +257,6 @@ class CombinedOpenEndedV1Module():
|
||||
"""
|
||||
return all(self.is_initial_child_state(child) for child in task_state)
|
||||
|
||||
|
||||
def states_sort_key(self, idx_task_states):
|
||||
"""
|
||||
Return a key for sorting a list of indexed task_states, by how far the student got
|
||||
@@ -544,8 +543,8 @@ class CombinedOpenEndedV1Module():
|
||||
last_response_data = self.get_last_response(self.current_task_number - 1)
|
||||
current_response_data = self.get_current_attributes(self.current_task_number)
|
||||
|
||||
if (current_response_data['min_score_to_attempt'] > last_response_data['score']
|
||||
or current_response_data['max_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']:
|
||||
self.state = self.DONE
|
||||
self.ready_to_reset = True
|
||||
|
||||
@@ -818,7 +817,7 @@ class CombinedOpenEndedV1Module():
|
||||
log.error("Invalid response from grading server for location {0} and student {1}".format(self.location, student_id))
|
||||
error_message = "Received invalid response from the graders. Please notify course staff."
|
||||
return success, allowed_to_submit, error_message
|
||||
if count_graded >= count_required or count_available==0:
|
||||
if count_graded >= count_required or count_available == 0:
|
||||
error_message = ""
|
||||
return success, allowed_to_submit, error_message
|
||||
else:
|
||||
@@ -853,7 +852,7 @@ class CombinedOpenEndedV1Module():
|
||||
contexts = []
|
||||
rubric_number = self.current_task_number
|
||||
if self.ready_to_reset:
|
||||
rubric_number+=1
|
||||
rubric_number += 1
|
||||
response = self.get_last_response(rubric_number)
|
||||
score_length = len(response['grader_types'])
|
||||
for z in xrange(score_length):
|
||||
@@ -861,7 +860,7 @@ class CombinedOpenEndedV1Module():
|
||||
try:
|
||||
feedback = response['feedback_dicts'][z].get('feedback', '')
|
||||
except TypeError:
|
||||
return {'success' : False}
|
||||
return {'success': False}
|
||||
rubric_scores = [[response['rubric_scores'][z]]]
|
||||
grader_types = [[response['grader_types'][z]]]
|
||||
feedback_items = [[response['feedback_items'][z]]]
|
||||
@@ -879,14 +878,14 @@ class CombinedOpenEndedV1Module():
|
||||
# That longer string appears when a user is viewing a graded rubric
|
||||
# returned from one of the graders of their openended response problem.
|
||||
'task_name': ugettext('Scored rubric'),
|
||||
'feedback' : feedback
|
||||
'feedback': feedback
|
||||
})
|
||||
|
||||
context = {
|
||||
'results': contexts,
|
||||
}
|
||||
html = self.system.render_template('{0}/combined_open_ended_results.html'.format(self.TEMPLATE_DIR), context)
|
||||
return {'html': html, 'success': True, 'hide_reset' : False}
|
||||
return {'html': html, 'success': True, 'hide_reset': False}
|
||||
|
||||
def get_legend(self, _data):
|
||||
"""
|
||||
@@ -978,7 +977,7 @@ class CombinedOpenEndedV1Module():
|
||||
max_number_of_attempts=self.max_attempts
|
||||
)
|
||||
}
|
||||
self.student_attempts +=1
|
||||
self.student_attempts += 1
|
||||
self.state = self.INITIAL
|
||||
self.ready_to_reset = False
|
||||
for i in xrange(len(self.task_xml)):
|
||||
|
||||
@@ -245,7 +245,7 @@ class OpenEndedChild(object):
|
||||
Replaces "\n" newlines with <br/>
|
||||
"""
|
||||
retv = re.sub(r'</p>$', '', re.sub(r'^<p>', '', html))
|
||||
return re.sub("\n","<br/>", retv)
|
||||
return re.sub("\n", "<br/>", retv)
|
||||
|
||||
def new_history_entry(self, answer):
|
||||
"""
|
||||
@@ -293,7 +293,7 @@ class OpenEndedChild(object):
|
||||
'child_attempts': self.child_attempts,
|
||||
'child_created': self.child_created,
|
||||
'stored_answer': self.stored_answer,
|
||||
}
|
||||
}
|
||||
return json.dumps(state)
|
||||
|
||||
def _allow_reset(self):
|
||||
@@ -333,13 +333,13 @@ class OpenEndedChild(object):
|
||||
previous_answer = latest
|
||||
else:
|
||||
previous_answer = ""
|
||||
previous_answer = previous_answer.replace("<br/>","\n").replace("<br>", "\n")
|
||||
previous_answer = previous_answer.replace("<br/>", "\n").replace("<br>", "\n")
|
||||
else:
|
||||
if latest is not None and len(latest) > 0:
|
||||
previous_answer = latest
|
||||
else:
|
||||
previous_answer = ""
|
||||
previous_answer = previous_answer.replace("\n","<br/>")
|
||||
previous_answer = previous_answer.replace("\n", "<br/>")
|
||||
|
||||
return previous_answer
|
||||
|
||||
@@ -439,16 +439,16 @@ class OpenEndedChild(object):
|
||||
image_tag = ""
|
||||
|
||||
# Ensure that a valid file was uploaded.
|
||||
if ('valid_files_attached' in data
|
||||
and data['valid_files_attached'] in ['true', '1', True]
|
||||
and data['student_file'] is not None
|
||||
and len(data['student_file']) > 0):
|
||||
has_file_to_upload = True
|
||||
student_file = data['student_file'][0]
|
||||
if 'valid_files_attached' in data and \
|
||||
data['valid_files_attached'] in ['true', '1', True] and \
|
||||
data['student_file'] is not None and \
|
||||
len(data['student_file']) > 0:
|
||||
has_file_to_upload = True
|
||||
student_file = data['student_file'][0]
|
||||
|
||||
# Upload the file to S3 and generate html to embed a link.
|
||||
s3_public_url = self.upload_file_to_s3(student_file)
|
||||
image_tag = self.generate_file_link_html_from_url(s3_public_url, student_file.name)
|
||||
# Upload the file to S3 and generate html to embed a link.
|
||||
s3_public_url = self.upload_file_to_s3(student_file)
|
||||
image_tag = self.generate_file_link_html_from_url(s3_public_url, student_file.name)
|
||||
|
||||
return has_file_to_upload, image_tag
|
||||
|
||||
@@ -521,7 +521,7 @@ class OpenEndedChild(object):
|
||||
|
||||
# Find all links in the string.
|
||||
links = re.findall(r'(https?://\S+)', string)
|
||||
if len(links)>0:
|
||||
if len(links) > 0:
|
||||
has_link = True
|
||||
|
||||
# Autolink by wrapping links in anchor tags.
|
||||
|
||||
@@ -41,10 +41,12 @@ class PollFields(object):
|
||||
class PollModule(PollFields, XModule):
|
||||
"""Poll Module"""
|
||||
js = {
|
||||
'coffee': [resource_string(__name__, 'js/src/javascript_loader.coffee')],
|
||||
'js': [resource_string(__name__, 'js/src/poll/poll.js'),
|
||||
resource_string(__name__, 'js/src/poll/poll_main.js')]
|
||||
}
|
||||
'coffee': [resource_string(__name__, 'js/src/javascript_loader.coffee')],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/poll/poll.js'),
|
||||
resource_string(__name__, 'js/src/poll/poll_main.js')
|
||||
]
|
||||
}
|
||||
css = {'scss': [resource_string(__name__, 'css/poll/display.scss')]}
|
||||
js_module_name = "Poll"
|
||||
|
||||
@@ -94,11 +96,11 @@ class PollModule(PollFields, XModule):
|
||||
def get_html(self):
|
||||
"""Renders parameters to template."""
|
||||
params = {
|
||||
'element_id': self.location.html_id(),
|
||||
'element_class': self.location.category,
|
||||
'ajax_url': self.system.ajax_url,
|
||||
'configuration_json': self.dump_poll(),
|
||||
}
|
||||
'element_id': self.location.html_id(),
|
||||
'element_class': self.location.category,
|
||||
'ajax_url': self.system.ajax_url,
|
||||
'configuration_json': self.dump_poll(),
|
||||
}
|
||||
self.content = self.system.render_template('poll.html', params)
|
||||
return self.content
|
||||
|
||||
@@ -127,13 +129,15 @@ class PollModule(PollFields, XModule):
|
||||
answers_to_json[answer['id']] = cgi.escape(answer['text'])
|
||||
self.poll_answers = temp_poll_answers
|
||||
|
||||
return json.dumps({'answers': answers_to_json,
|
||||
return json.dumps({
|
||||
'answers': answers_to_json,
|
||||
'question': cgi.escape(self.question),
|
||||
# to show answered poll after reload:
|
||||
'poll_answer': self.poll_answer,
|
||||
'poll_answers': self.poll_answers if self.voted else {},
|
||||
'total': sum(self.poll_answers.values()) if self.voted else 0,
|
||||
'reset': str(self.descriptor.xml_attributes.get('reset', 'true')).lower()})
|
||||
'reset': str(self.descriptor.xml_attributes.get('reset', 'true')).lower()
|
||||
})
|
||||
|
||||
|
||||
class PollDescriptor(PollFields, MakoModuleDescriptor, XmlDescriptor):
|
||||
|
||||
@@ -12,6 +12,7 @@ from opaque_keys.edx.locations import Location
|
||||
|
||||
from . import get_test_system
|
||||
|
||||
|
||||
class AnnotatableModuleTestCase(unittest.TestCase):
|
||||
sample_xml = '''
|
||||
<annotatable display_name="Iliad">
|
||||
@@ -42,7 +43,7 @@ class AnnotatableModuleTestCase(unittest.TestCase):
|
||||
el = etree.fromstring('<annotation title="bar" body="foo" problem="0">test</annotation>')
|
||||
|
||||
expected_attr = {
|
||||
'data-comment-body': {'value': 'foo', '_delete': 'body' },
|
||||
'data-comment-body': {'value': 'foo', '_delete': 'body'},
|
||||
'data-comment-title': {'value': 'bar', '_delete': 'title'},
|
||||
'data-problem-id': {'value': '0', '_delete': 'problem'}
|
||||
}
|
||||
@@ -56,7 +57,7 @@ class AnnotatableModuleTestCase(unittest.TestCase):
|
||||
xml = '<annotation title="x" body="y" problem="0">test</annotation>'
|
||||
el = etree.fromstring(xml)
|
||||
|
||||
expected_attr = { 'class': { 'value': 'annotatable-span highlight' } }
|
||||
expected_attr = {'class': {'value': 'annotatable-span highlight'}}
|
||||
actual_attr = self.annotatable._get_annotation_class_attr(0, el)
|
||||
|
||||
self.assertIsInstance(actual_attr, dict)
|
||||
@@ -69,9 +70,11 @@ class AnnotatableModuleTestCase(unittest.TestCase):
|
||||
el = etree.fromstring(xml.format(highlight=color))
|
||||
value = 'annotatable-span highlight highlight-{highlight}'.format(highlight=color)
|
||||
|
||||
expected_attr = { 'class': {
|
||||
'value': value,
|
||||
'_delete': 'highlight' }
|
||||
expected_attr = {
|
||||
'class': {
|
||||
'value': value,
|
||||
'_delete': 'highlight'
|
||||
}
|
||||
}
|
||||
actual_attr = self.annotatable._get_annotation_class_attr(0, el)
|
||||
|
||||
@@ -83,9 +86,11 @@ class AnnotatableModuleTestCase(unittest.TestCase):
|
||||
|
||||
for invalid_color in ['rainbow', 'blink', 'invisible', '', None]:
|
||||
el = etree.fromstring(xml.format(highlight=invalid_color))
|
||||
expected_attr = { 'class': {
|
||||
'value': 'annotatable-span highlight',
|
||||
'_delete': 'highlight' }
|
||||
expected_attr = {
|
||||
'class': {
|
||||
'value': 'annotatable-span highlight',
|
||||
'_delete': 'highlight'
|
||||
}
|
||||
}
|
||||
actual_attr = self.annotatable._get_annotation_class_attr(0, el)
|
||||
|
||||
|
||||
@@ -11,46 +11,60 @@ class DateTest(unittest.TestCase):
|
||||
date = Date()
|
||||
|
||||
def compare_dates(self, dt1, dt2, expected_delta):
|
||||
self.assertEqual(dt1 - dt2, expected_delta, str(dt1) + "-"
|
||||
+ str(dt2) + "!=" + str(expected_delta))
|
||||
self.assertEqual(
|
||||
dt1 - dt2,
|
||||
expected_delta,
|
||||
str(dt1) + "-" + str(dt2) + "!=" + str(expected_delta)
|
||||
)
|
||||
|
||||
def test_from_json(self):
|
||||
'''Test conversion from iso compatible date strings to struct_time'''
|
||||
"""Test conversion from iso compatible date strings to struct_time"""
|
||||
self.compare_dates(
|
||||
DateTest.date.from_json("2013-01-01"),
|
||||
DateTest.date.from_json("2012-12-31"),
|
||||
datetime.timedelta(days=1))
|
||||
datetime.timedelta(days=1)
|
||||
)
|
||||
self.compare_dates(
|
||||
DateTest.date.from_json("2013-01-01T00"),
|
||||
DateTest.date.from_json("2012-12-31T23"),
|
||||
datetime.timedelta(hours=1))
|
||||
datetime.timedelta(hours=1)
|
||||
)
|
||||
self.compare_dates(
|
||||
DateTest.date.from_json("2013-01-01T00:00"),
|
||||
DateTest.date.from_json("2012-12-31T23:59"),
|
||||
datetime.timedelta(minutes=1))
|
||||
datetime.timedelta(minutes=1)
|
||||
)
|
||||
self.compare_dates(
|
||||
DateTest.date.from_json("2013-01-01T00:00:00"),
|
||||
DateTest.date.from_json("2012-12-31T23:59:59"),
|
||||
datetime.timedelta(seconds=1))
|
||||
datetime.timedelta(seconds=1)
|
||||
)
|
||||
self.compare_dates(
|
||||
DateTest.date.from_json("2013-01-01T00:00:00Z"),
|
||||
DateTest.date.from_json("2012-12-31T23:59:59Z"),
|
||||
datetime.timedelta(seconds=1))
|
||||
datetime.timedelta(seconds=1)
|
||||
)
|
||||
self.compare_dates(
|
||||
DateTest.date.from_json("2012-12-31T23:00:01-01:00"),
|
||||
DateTest.date.from_json("2013-01-01T00:00:00+01:00"),
|
||||
datetime.timedelta(hours=1, seconds=1))
|
||||
datetime.timedelta(hours=1, seconds=1)
|
||||
)
|
||||
|
||||
def test_enforce_type(self):
|
||||
self.assertEqual(DateTest.date.enforce_type(None), None)
|
||||
self.assertEqual(DateTest.date.enforce_type(""), None)
|
||||
self.assertEqual(DateTest.date.enforce_type("2012-12-31T23:00:01"),
|
||||
datetime.datetime(2012, 12, 31, 23, 0, 1, tzinfo=UTC()))
|
||||
self.assertEqual(DateTest.date.enforce_type(1234567890000),
|
||||
datetime.datetime(2009, 2, 13, 23, 31, 30, tzinfo=UTC()))
|
||||
self.assertEqual(DateTest.date.enforce_type(
|
||||
datetime.datetime(2014, 5, 9, 21, 1, 27, tzinfo=UTC())),
|
||||
datetime.datetime(2014, 5, 9, 21, 1, 27, tzinfo=UTC()))
|
||||
self.assertEqual(
|
||||
DateTest.date.enforce_type("2012-12-31T23:00:01"),
|
||||
datetime.datetime(2012, 12, 31, 23, 0, 1, tzinfo=UTC())
|
||||
)
|
||||
self.assertEqual(
|
||||
DateTest.date.enforce_type(1234567890000),
|
||||
datetime.datetime(2009, 2, 13, 23, 31, 30, tzinfo=UTC())
|
||||
)
|
||||
self.assertEqual(
|
||||
DateTest.date.enforce_type(datetime.datetime(2014, 5, 9, 21, 1, 27, tzinfo=UTC())),
|
||||
datetime.datetime(2014, 5, 9, 21, 1, 27, tzinfo=UTC())
|
||||
)
|
||||
with self.assertRaises(TypeError):
|
||||
DateTest.date.enforce_type([1])
|
||||
|
||||
@@ -64,10 +78,12 @@ class DateTest(unittest.TestCase):
|
||||
current = datetime.datetime.today()
|
||||
self.assertEqual(
|
||||
datetime.datetime(current.year, 3, 12, 12, tzinfo=UTC()),
|
||||
DateTest.date.from_json("March 12 12:00"))
|
||||
DateTest.date.from_json("March 12 12:00")
|
||||
)
|
||||
self.assertEqual(
|
||||
datetime.datetime(current.year, 12, 4, 16, 30, tzinfo=UTC()),
|
||||
DateTest.date.from_json("December 4 16:30"))
|
||||
DateTest.date.from_json("December 4 16:30")
|
||||
)
|
||||
self.assertIsNone(DateTest.date.from_json("12 12:00"))
|
||||
|
||||
def test_non_std_from_json(self):
|
||||
@@ -76,27 +92,29 @@ class DateTest(unittest.TestCase):
|
||||
"""
|
||||
now = datetime.datetime.now(UTC())
|
||||
delta = now - datetime.datetime.fromtimestamp(0, UTC())
|
||||
self.assertEqual(DateTest.date.from_json(delta.total_seconds() * 1000),
|
||||
now)
|
||||
self.assertEqual(
|
||||
DateTest.date.from_json(delta.total_seconds() * 1000), # pylint: disable=maybe-no-member
|
||||
now
|
||||
)
|
||||
yesterday = datetime.datetime.now(UTC()) - datetime.timedelta(days=-1)
|
||||
self.assertEqual(DateTest.date.from_json(yesterday), yesterday)
|
||||
|
||||
def test_to_json(self):
|
||||
'''
|
||||
"""
|
||||
Test converting time reprs to iso dates
|
||||
'''
|
||||
"""
|
||||
self.assertEqual(
|
||||
DateTest.date.to_json(
|
||||
datetime.datetime.strptime("2012-12-31T23:59:59Z", "%Y-%m-%dT%H:%M:%SZ")),
|
||||
"2012-12-31T23:59:59Z")
|
||||
DateTest.date.to_json(datetime.datetime.strptime("2012-12-31T23:59:59Z", "%Y-%m-%dT%H:%M:%SZ")),
|
||||
"2012-12-31T23:59:59Z"
|
||||
)
|
||||
self.assertEqual(
|
||||
DateTest.date.to_json(
|
||||
DateTest.date.from_json("2012-12-31T23:59:59Z")),
|
||||
"2012-12-31T23:59:59Z")
|
||||
DateTest.date.to_json(DateTest.date.from_json("2012-12-31T23:59:59Z")),
|
||||
"2012-12-31T23:59:59Z"
|
||||
)
|
||||
self.assertEqual(
|
||||
DateTest.date.to_json(
|
||||
DateTest.date.from_json("2012-12-31T23:00:01-01:00")),
|
||||
"2012-12-31T23:00:01-01:00")
|
||||
DateTest.date.to_json(DateTest.date.from_json("2012-12-31T23:00:01-01:00")),
|
||||
"2012-12-31T23:00:01-01:00"
|
||||
)
|
||||
with self.assertRaises(TypeError):
|
||||
DateTest.date.to_json('2012-12-31T23:00:01-01:00')
|
||||
|
||||
@@ -117,11 +135,14 @@ class TimedeltaTest(unittest.TestCase):
|
||||
|
||||
def test_enforce_type(self):
|
||||
self.assertEqual(TimedeltaTest.delta.enforce_type(None), None)
|
||||
self.assertEqual(TimedeltaTest.delta.enforce_type(
|
||||
datetime.timedelta(days=1, seconds=46799)),
|
||||
datetime.timedelta(days=1, seconds=46799))
|
||||
self.assertEqual(TimedeltaTest.delta.enforce_type('1 day 46799 seconds'),
|
||||
datetime.timedelta(days=1, seconds=46799))
|
||||
self.assertEqual(
|
||||
TimedeltaTest.delta.enforce_type(datetime.timedelta(days=1, seconds=46799)),
|
||||
datetime.timedelta(days=1, seconds=46799)
|
||||
)
|
||||
self.assertEqual(
|
||||
TimedeltaTest.delta.enforce_type('1 day 46799 seconds'),
|
||||
datetime.timedelta(days=1, seconds=46799)
|
||||
)
|
||||
with self.assertRaises(TypeError):
|
||||
TimedeltaTest.delta.enforce_type([1])
|
||||
|
||||
@@ -137,8 +158,10 @@ class TimeInfoTest(unittest.TestCase):
|
||||
due_date = datetime.datetime(2000, 4, 14, 10, tzinfo=UTC())
|
||||
grace_pd_string = '1 day 12 hours 59 minutes 59 seconds'
|
||||
timeinfo = TimeInfo(due_date, grace_pd_string)
|
||||
self.assertEqual(timeinfo.close_date,
|
||||
due_date + Timedelta().from_json(grace_pd_string))
|
||||
self.assertEqual(
|
||||
timeinfo.close_date,
|
||||
due_date + Timedelta().from_json(grace_pd_string)
|
||||
)
|
||||
|
||||
|
||||
class RelativeTimeTest(unittest.TestCase):
|
||||
@@ -168,11 +191,14 @@ class RelativeTimeTest(unittest.TestCase):
|
||||
|
||||
def test_enforce_type(self):
|
||||
self.assertEqual(RelativeTimeTest.delta.enforce_type(None), None)
|
||||
self.assertEqual(RelativeTimeTest.delta.enforce_type(
|
||||
datetime.timedelta(days=1, seconds=46799)),
|
||||
datetime.timedelta(days=1, seconds=46799))
|
||||
self.assertEqual(RelativeTimeTest.delta.enforce_type('0:05:07'),
|
||||
datetime.timedelta(seconds=307))
|
||||
self.assertEqual(
|
||||
RelativeTimeTest.delta.enforce_type(datetime.timedelta(days=1, seconds=46799)),
|
||||
datetime.timedelta(days=1, seconds=46799)
|
||||
)
|
||||
self.assertEqual(
|
||||
RelativeTimeTest.delta.enforce_type('0:05:07'),
|
||||
datetime.timedelta(seconds=307)
|
||||
)
|
||||
with self.assertRaises(TypeError):
|
||||
RelativeTimeTest.delta.enforce_type([1])
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ from xmodule.html_module import HtmlModule
|
||||
|
||||
from . import get_test_system
|
||||
|
||||
|
||||
class HtmlModuleSubstitutionTestCase(unittest.TestCase):
|
||||
descriptor = Mock()
|
||||
|
||||
@@ -17,7 +18,6 @@ class HtmlModuleSubstitutionTestCase(unittest.TestCase):
|
||||
module = HtmlModule(self.descriptor, module_system, field_data, Mock())
|
||||
self.assertEqual(module.get_html(), str(module_system.anonymous_student_id))
|
||||
|
||||
|
||||
def test_substitution_without_magic_string(self):
|
||||
sample_xml = '''
|
||||
<html>
|
||||
@@ -29,7 +29,6 @@ class HtmlModuleSubstitutionTestCase(unittest.TestCase):
|
||||
module = HtmlModule(self.descriptor, module_system, field_data, Mock())
|
||||
self.assertEqual(module.get_html(), sample_xml)
|
||||
|
||||
|
||||
def test_substitution_without_anonymous_student_id(self):
|
||||
sample_xml = '''%%USER_ID%%'''
|
||||
field_data = DictFieldData({'data': sample_xml})
|
||||
@@ -37,4 +36,3 @@ class HtmlModuleSubstitutionTestCase(unittest.TestCase):
|
||||
module_system.anonymous_student_id = None
|
||||
module = HtmlModule(self.descriptor, module_system, field_data, Mock())
|
||||
self.assertEqual(module.get_html(), sample_xml)
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ S3_INTERFACE = {
|
||||
"storage_bucket_name": "",
|
||||
}
|
||||
|
||||
|
||||
class MockS3Key(object):
|
||||
"""
|
||||
Mock an S3 Key object from boto. Used for file upload testing.
|
||||
@@ -96,6 +97,7 @@ class DummyModulestore(object):
|
||||
descriptor.xmodule_runtime = self.get_module_system(descriptor)
|
||||
return descriptor
|
||||
|
||||
|
||||
def serialize_child_history(task_state):
|
||||
"""
|
||||
To json serialize feedback and post_assessment in child_history of task state.
|
||||
@@ -107,6 +109,7 @@ def serialize_child_history(task_state):
|
||||
attempt["post_assessment"]["feedback"] = json.dumps(attempt["post_assessment"].get("feedback"))
|
||||
task_state["child_history"][i]["post_assessment"] = json.dumps(attempt["post_assessment"])
|
||||
|
||||
|
||||
def serialize_open_ended_instance_state(json_str):
|
||||
"""
|
||||
To json serialize task_states and old_task_states in instance state.
|
||||
@@ -933,4 +936,4 @@ TEST_STATE_AI2_INVALID = ["{\"child_created\": false, \"child_attempts\": 0, \"v
|
||||
TEST_STATE_SINGLE = ["{\"child_created\": false, \"child_attempts\": 1, \"version\": 1, \"child_history\": [{\"answer\": \"'All of us can think of a book that we hope none of our children or any other children have taken off the shelf. But if I have the right to remove that book from the shelf -- that work I abhor -- then you also have exactly the same right and so does everyone else. And then we have no books left on the shelf for any of us.' --Katherine Paterson, Author\\r<br><br>Write a persuasive essay to a newspaper reflecting your views on censorship in libraries. Do you believe that certain materials, such as books, music, movies, magazines, etc., should be removed from the shelves if they are found offensive? Support your position with convincing arguments from your own experience, observations, and/or reading. \", \"post_assessment\": \"[3, 3, 2, 2, 2]\", \"score\": 12}], \"max_score\": 12, \"child_state\": \"done\"}"]
|
||||
|
||||
# Peer grading state.
|
||||
TEST_STATE_PE_SINGLE = ["{\"child_created\": false, \"child_attempts\": 0, \"version\": 1, \"child_history\": [{\"answer\": \"Passage its ten led hearted removal cordial. Preference any astonished unreserved mrs. Prosperous understood middletons in conviction an uncommonly do. Supposing so be resolving breakfast am or perfectly. Is drew am hill from mr. Valley by oh twenty direct me so. Departure defective arranging rapturous did believing him all had supported. Family months lasted simple set nature vulgar him. Picture for attempt joy excited ten carried manners talking how. Suspicion neglected he resolving agreement perceived at an. \\r<br><br>Ye on properly handsome returned throwing am no whatever. In without wishing he of picture no exposed talking minutes. Curiosity continual belonging offending so explained it exquisite. Do remember to followed yourself material mr recurred carriage. High drew west we no or at john. About or given on witty event. Or sociable up material bachelor bringing landlord confined. Busy so many in hung easy find well up. So of exquisite my an explained remainder. Dashwood denoting securing be on perceive my laughing so. \\r<br><br>Ought these are balls place mrs their times add she. Taken no great widow spoke of it small. Genius use except son esteem merely her limits. Sons park by do make on. It do oh cottage offered cottage in written. Especially of dissimilar up attachment themselves by interested boisterous. Linen mrs seems men table. Jennings dashwood to quitting marriage bachelor in. On as conviction in of appearance apartments boisterous. \", \"post_assessment\": \"{\\\"submission_id\\\": 1439, \\\"score\\\": [0], \\\"feedback\\\": [\\\"{\\\\\\\"feedback\\\\\\\": \\\\\\\"\\\\\\\"}\\\"], \\\"success\\\": true, \\\"grader_id\\\": [5337], \\\"grader_type\\\": \\\"PE\\\", \\\"rubric_scores_complete\\\": [true], \\\"rubric_xml\\\": [\\\"<rubric><category><description>\\\\nIdeas\\\\n</description><score>0</score><option points='0'>\\\\nDifficult for the reader to discern the main idea. Too brief or too repetitive to establish or maintain a focus.\\\\n</option><option points='1'>\\\\nAttempts a main idea. Sometimes loses focus or ineffectively displays focus.\\\\n</option><option points='2'>\\\\nPresents a unifying theme or main idea, but may include minor tangents. Stays somewhat focused on topic and task.\\\\n</option><option points='3'>\\\\nPresents a unifying theme or main idea without going off on tangents. Stays completely focused on topic and task.\\\\n</option></category><category><description>\\\\nContent\\\\n</description><score>0</score><option points='0'>\\\\nIncludes little information with few or no details or unrelated details. Unsuccessful in attempts to explore any facets of the topic.\\\\n</option><option points='1'>\\\\nIncludes little information and few or no details. Explores only one or two facets of the topic.\\\\n</option><option points='2'>\\\\nIncludes sufficient information and supporting details. (Details may not be fully developed; ideas may be listed.) Explores some facets of the topic.\\\\n</option><option points='3'>\\\\nIncludes in-depth information and exceptional supporting details that are fully developed. Explores all facets of the topic.\\\\n</option></category><category><description>\\\\nOrganization\\\\n</description><score>0</score><option points='0'>\\\\nIdeas organized illogically, transitions weak, and response difficult to follow.\\\\n</option><option points='1'>\\\\nAttempts to logically organize ideas. Attempts to progress in an order that enhances meaning, and demonstrates use of transitions.\\\\n</option><option points='2'>\\\\nIdeas organized logically. Progresses in an order that enhances meaning. Includes smooth transitions.\\\\n</option></category><category><description>\\\\nStyle\\\\n</description><score>0</score><option points='0'>\\\\nContains limited vocabulary, with many words used incorrectly. Demonstrates problems with sentence patterns.\\\\n</option><option points='1'>\\\\nContains basic vocabulary, with words that are predictable and common. Contains mostly simple sentences (although there may be an attempt at more varied sentence patterns).\\\\n</option><option points='2'>\\\\nIncludes vocabulary to make explanations detailed and precise. Includes varied sentence patterns, including complex sentences.\\\\n</option></category><category><description>\\\\nVoice\\\\n</description><score>0</score><option points='0'>\\\\nDemonstrates language and tone that may be inappropriate to task and reader.\\\\n</option><option points='1'>\\\\nDemonstrates an attempt to adjust language and tone to task and reader.\\\\n</option><option points='2'>\\\\nDemonstrates effective adjustment of language and tone to task and reader.\\\\n</option></category></rubric>\\\"]}\", \"score\": 0}], \"max_score\": 12, \"child_state\": \"done\"}"]
|
||||
TEST_STATE_PE_SINGLE = ["{\"child_created\": false, \"child_attempts\": 0, \"version\": 1, \"child_history\": [{\"answer\": \"Passage its ten led hearted removal cordial. Preference any astonished unreserved mrs. Prosperous understood middletons in conviction an uncommonly do. Supposing so be resolving breakfast am or perfectly. Is drew am hill from mr. Valley by oh twenty direct me so. Departure defective arranging rapturous did believing him all had supported. Family months lasted simple set nature vulgar him. Picture for attempt joy excited ten carried manners talking how. Suspicion neglected he resolving agreement perceived at an. \\r<br><br>Ye on properly handsome returned throwing am no whatever. In without wishing he of picture no exposed talking minutes. Curiosity continual belonging offending so explained it exquisite. Do remember to followed yourself material mr recurred carriage. High drew west we no or at john. About or given on witty event. Or sociable up material bachelor bringing landlord confined. Busy so many in hung easy find well up. So of exquisite my an explained remainder. Dashwood denoting securing be on perceive my laughing so. \\r<br><br>Ought these are balls place mrs their times add she. Taken no great widow spoke of it small. Genius use except son esteem merely her limits. Sons park by do make on. It do oh cottage offered cottage in written. Especially of dissimilar up attachment themselves by interested boisterous. Linen mrs seems men table. Jennings dashwood to quitting marriage bachelor in. On as conviction in of appearance apartments boisterous. \", \"post_assessment\": \"{\\\"submission_id\\\": 1439, \\\"score\\\": [0], \\\"feedback\\\": [\\\"{\\\\\\\"feedback\\\\\\\": \\\\\\\"\\\\\\\"}\\\"], \\\"success\\\": true, \\\"grader_id\\\": [5337], \\\"grader_type\\\": \\\"PE\\\", \\\"rubric_scores_complete\\\": [true], \\\"rubric_xml\\\": [\\\"<rubric><category><description>\\\\nIdeas\\\\n</description><score>0</score><option points='0'>\\\\nDifficult for the reader to discern the main idea. Too brief or too repetitive to establish or maintain a focus.\\\\n</option><option points='1'>\\\\nAttempts a main idea. Sometimes loses focus or ineffectively displays focus.\\\\n</option><option points='2'>\\\\nPresents a unifying theme or main idea, but may include minor tangents. Stays somewhat focused on topic and task.\\\\n</option><option points='3'>\\\\nPresents a unifying theme or main idea without going off on tangents. Stays completely focused on topic and task.\\\\n</option></category><category><description>\\\\nContent\\\\n</description><score>0</score><option points='0'>\\\\nIncludes little information with few or no details or unrelated details. Unsuccessful in attempts to explore any facets of the topic.\\\\n</option><option points='1'>\\\\nIncludes little information and few or no details. Explores only one or two facets of the topic.\\\\n</option><option points='2'>\\\\nIncludes sufficient information and supporting details. (Details may not be fully developed; ideas may be listed.) Explores some facets of the topic.\\\\n</option><option points='3'>\\\\nIncludes in-depth information and exceptional supporting details that are fully developed. Explores all facets of the topic.\\\\n</option></category><category><description>\\\\nOrganization\\\\n</description><score>0</score><option points='0'>\\\\nIdeas organized illogically, transitions weak, and response difficult to follow.\\\\n</option><option points='1'>\\\\nAttempts to logically organize ideas. Attempts to progress in an order that enhances meaning, and demonstrates use of transitions.\\\\n</option><option points='2'>\\\\nIdeas organized logically. Progresses in an order that enhances meaning. Includes smooth transitions.\\\\n</option></category><category><description>\\\\nStyle\\\\n</description><score>0</score><option points='0'>\\\\nContains limited vocabulary, with many words used incorrectly. Demonstrates problems with sentence patterns.\\\\n</option><option points='1'>\\\\nContains basic vocabulary, with words that are predictable and common. Contains mostly simple sentences (although there may be an attempt at more varied sentence patterns).\\\\n</option><option points='2'>\\\\nIncludes vocabulary to make explanations detailed and precise. Includes varied sentence patterns, including complex sentences.\\\\n</option></category><category><description>\\\\nVoice\\\\n</description><score>0</score><option points='0'>\\\\nDemonstrates language and tone that may be inappropriate to task and reader.\\\\n</option><option points='1'>\\\\nDemonstrates an attempt to adjust language and tone to task and reader.\\\\n</option><option points='2'>\\\\nDemonstrates effective adjustment of language and tone to task and reader.\\\\n</option></category></rubric>\\\"]}\", \"score\": 0}], \"max_score\": 12, \"child_state\": \"done\"}"]
|
||||
|
||||
@@ -132,7 +132,6 @@ class InheritingFieldDataTest(unittest.TestCase):
|
||||
self.assertEqual(child.not_inherited, "nothing")
|
||||
|
||||
|
||||
|
||||
class EditableMetadataFieldsTest(unittest.TestCase):
|
||||
def test_display_name_field(self):
|
||||
editable_fields = self.get_xml_editable_fields(DictFieldData({}))
|
||||
@@ -331,7 +330,6 @@ class TestDeserializeInteger(TestDeserialize):
|
||||
# 2.78 can be converted to int, so the string will be deserialized
|
||||
self.assertDeserializeEqual(-2.78, '-2.78')
|
||||
|
||||
|
||||
def test_deserialize_unsupported_types(self):
|
||||
self.assertDeserializeEqual('[3]', '[3]')
|
||||
# '2.78' cannot be converted to int, so input value is returned
|
||||
@@ -415,7 +413,7 @@ class TestDeserializeAny(TestDeserialize):
|
||||
def test_deserialize(self):
|
||||
self.assertDeserializeEqual('hAlf', '"hAlf"')
|
||||
self.assertDeserializeEqual('false', '"false"')
|
||||
self.assertDeserializeEqual({'bar': 'hat', 'frog' : 'green'}, '{"bar": "hat", "frog": "green"}')
|
||||
self.assertDeserializeEqual({'bar': 'hat', 'frog': 'green'}, '{"bar": "hat", "frog": "green"}')
|
||||
self.assertDeserializeEqual([3.5, 5.6], '[3.5, 5.6]')
|
||||
self.assertDeserializeEqual('[', '[')
|
||||
self.assertDeserializeEqual(False, 'false')
|
||||
@@ -457,10 +455,14 @@ class TestDeserializeTimedelta(TestDeserialize):
|
||||
test_field = Timedelta
|
||||
|
||||
def test_deserialize(self):
|
||||
self.assertDeserializeEqual('1 day 12 hours 59 minutes 59 seconds',
|
||||
'1 day 12 hours 59 minutes 59 seconds')
|
||||
self.assertDeserializeEqual('1 day 12 hours 59 minutes 59 seconds',
|
||||
'"1 day 12 hours 59 minutes 59 seconds"')
|
||||
self.assertDeserializeEqual(
|
||||
'1 day 12 hours 59 minutes 59 seconds',
|
||||
'1 day 12 hours 59 minutes 59 seconds'
|
||||
)
|
||||
self.assertDeserializeEqual(
|
||||
'1 day 12 hours 59 minutes 59 seconds',
|
||||
'"1 day 12 hours 59 minutes 59 seconds"'
|
||||
)
|
||||
self.assertDeserializeNonString()
|
||||
|
||||
|
||||
|
||||
@@ -46,5 +46,3 @@ class ProblemPage(PageObject):
|
||||
Is there a "correct" status showing?
|
||||
"""
|
||||
return self.q(css="div.problem div.capa_inputtype.textline div.correct p.status").is_present()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user