Move files into xmodule module per comment on #326
* move html_checker.py * move stringify.py * move tests into module * remove duplicate progress.py * fix module imports
This commit is contained in:
@@ -1,157 +0,0 @@
|
||||
'''
|
||||
Progress class for modules. Represents where a student is in a module.
|
||||
|
||||
Useful things to know:
|
||||
- Use Progress.to_js_status_str() to convert a progress into a simple
|
||||
status string to pass to js.
|
||||
- Use Progress.to_js_detail_str() to convert a progress into a more detailed
|
||||
string to pass to js.
|
||||
|
||||
In particular, these functions have a canonical handing of None.
|
||||
|
||||
For most subclassing needs, you should only need to reimplement
|
||||
frac() and __str__().
|
||||
'''
|
||||
|
||||
from collections import namedtuple
|
||||
import numbers
|
||||
|
||||
|
||||
class Progress(object):
|
||||
'''Represents a progress of a/b (a out of b done)
|
||||
|
||||
a and b must be numeric, but not necessarily integer, with
|
||||
0 <= a <= b and b > 0.
|
||||
|
||||
Progress can only represent Progress for modules where that makes sense. Other
|
||||
modules (e.g. html) should return None from get_progress().
|
||||
|
||||
TODO: add tag for module type? Would allow for smarter merging.
|
||||
'''
|
||||
|
||||
def __init__(self, a, b):
|
||||
'''Construct a Progress object. a and b must be numbers, and must have
|
||||
0 <= a <= b and b > 0
|
||||
'''
|
||||
|
||||
# Want to do all checking at construction time, so explicitly check types
|
||||
if not (isinstance(a, numbers.Number) and
|
||||
isinstance(b, numbers.Number)):
|
||||
raise TypeError('a and b must be numbers. Passed {0}/{1}'.format(a, b))
|
||||
|
||||
if not (0 <= a <= b and b > 0):
|
||||
raise ValueError(
|
||||
'fraction a/b = {0}/{1} must have 0 <= a <= b and b > 0'.format(a, b))
|
||||
|
||||
self._a = a
|
||||
self._b = b
|
||||
|
||||
def frac(self):
|
||||
''' Return tuple (a,b) representing progress of a/b'''
|
||||
return (self._a, self._b)
|
||||
|
||||
def percent(self):
|
||||
''' Returns a percentage progress as a float between 0 and 100.
|
||||
|
||||
subclassing note: implemented in terms of frac(), assumes sanity
|
||||
checking is done at construction time.
|
||||
'''
|
||||
(a, b) = self.frac()
|
||||
return 100.0 * a / b
|
||||
|
||||
def started(self):
|
||||
''' Returns True if fractional progress is greater than 0.
|
||||
|
||||
subclassing note: implemented in terms of frac(), assumes sanity
|
||||
checking is done at construction time.
|
||||
'''
|
||||
return self.frac()[0] > 0
|
||||
|
||||
def inprogress(self):
|
||||
''' Returns True if fractional progress is strictly between 0 and 1.
|
||||
|
||||
subclassing note: implemented in terms of frac(), assumes sanity
|
||||
checking is done at construction time.
|
||||
'''
|
||||
(a, b) = self.frac()
|
||||
return a > 0 and a < b
|
||||
|
||||
def done(self):
|
||||
''' Return True if this represents done.
|
||||
|
||||
subclassing note: implemented in terms of frac(), assumes sanity
|
||||
checking is done at construction time.
|
||||
'''
|
||||
(a, b) = self.frac()
|
||||
return a == b
|
||||
|
||||
def ternary_str(self):
|
||||
''' Return a string version of this progress: either
|
||||
"none", "in_progress", or "done".
|
||||
|
||||
subclassing note: implemented in terms of frac()
|
||||
'''
|
||||
(a, b) = self.frac()
|
||||
if a == 0:
|
||||
return "none"
|
||||
if a < b:
|
||||
return "in_progress"
|
||||
return "done"
|
||||
|
||||
def __eq__(self, other):
|
||||
''' Two Progress objects are equal if they have identical values.
|
||||
Implemented in terms of frac()'''
|
||||
if not isinstance(other, Progress):
|
||||
return False
|
||||
(a, b) = self.frac()
|
||||
(a2, b2) = other.frac()
|
||||
return a == a2 and b == b2
|
||||
|
||||
def __ne__(self, other):
|
||||
''' The opposite of equal'''
|
||||
return not self.__eq__(other)
|
||||
|
||||
def __str__(self):
|
||||
''' Return a string representation of this string.
|
||||
|
||||
subclassing note: implemented in terms of frac().
|
||||
'''
|
||||
(a, b) = self.frac()
|
||||
return "{0}/{1}".format(a, b)
|
||||
|
||||
@staticmethod
|
||||
def add_counts(a, b):
|
||||
'''Add two progress indicators, assuming that each represents items done:
|
||||
(a / b) + (c / d) = (a + c) / (b + d).
|
||||
If either is None, returns the other.
|
||||
'''
|
||||
if a is None:
|
||||
return b
|
||||
if b is None:
|
||||
return a
|
||||
# get numerators + denominators
|
||||
(n, d) = a.frac()
|
||||
(n2, d2) = b.frac()
|
||||
return Progress(n + n2, d + d2)
|
||||
|
||||
@staticmethod
|
||||
def to_js_status_str(progress):
|
||||
'''
|
||||
Return the "status string" version of the passed Progress
|
||||
object that should be passed to js. Use this function when
|
||||
sending Progress objects to js to limit dependencies.
|
||||
'''
|
||||
if progress is None:
|
||||
return "NA"
|
||||
return progress.ternary_str()
|
||||
|
||||
@staticmethod
|
||||
def to_js_detail_str(progress):
|
||||
'''
|
||||
Return the "detail string" version of the passed Progress
|
||||
object that should be passed to js. Use this function when
|
||||
passing Progress objects to js to limit dependencies.
|
||||
'''
|
||||
if progress is None:
|
||||
return "NA"
|
||||
return str(progress)
|
||||
@@ -1,9 +0,0 @@
|
||||
from nose.tools import assert_equals
|
||||
from lxml import etree
|
||||
from stringify import stringify_children
|
||||
|
||||
def test_stringify():
|
||||
html = '''<html a="b" foo="bar">Hi <div x="foo">there <span>Bruce</span><b>!</b></div></html>'''
|
||||
xml = etree.fromstring(html)
|
||||
out = stringify_children(xml)
|
||||
assert_equals(out, '''Hi <div x="foo">there <span>Bruce</span><b>!</b></div>''')
|
||||
@@ -5,11 +5,11 @@ import os
|
||||
import sys
|
||||
from lxml import etree
|
||||
|
||||
from xmodule.x_module import XModule
|
||||
from xmodule.xml_module import XmlDescriptor
|
||||
from xmodule.editing_module import EditingDescriptor
|
||||
from stringify import stringify_children
|
||||
from html_checker import check_html
|
||||
from .x_module import XModule
|
||||
from .xml_module import XmlDescriptor
|
||||
from .editing_module import EditingDescriptor
|
||||
from .stringify import stringify_children
|
||||
from .html_checker import check_html
|
||||
|
||||
log = logging.getLogger("mitx.courseware")
|
||||
|
||||
|
||||
10
common/lib/xmodule/xmodule/tests/test_stringify.py
Normal file
10
common/lib/xmodule/xmodule/tests/test_stringify.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from nose.tools import assert_equals
|
||||
from lxml import etree
|
||||
from xmodule.stringify import stringify_children
|
||||
|
||||
def test_stringify():
|
||||
text = 'Hi <div x="foo">there <span>Bruce</span><b>!</b></div>'
|
||||
html = '''<html a="b" foo="bar">{0}</html>'''.format(text)
|
||||
xml = etree.fromstring(html)
|
||||
out = stringify_children(xml)
|
||||
assert_equals(out, text)
|
||||
Reference in New Issue
Block a user