Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
c65f0cac
Commit
c65f0cac
authored
Aug 05, 2013
by
Peter Baratta
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Address misc. comments from PR
parent
762943b5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
120 additions
and
53 deletions
+120
-53
common/lib/calc/calc.py
+7
-6
common/lib/calc/preview.py
+1
-1
common/lib/calc/tests/test_calc.py
+38
-27
common/lib/capa/capa/inputtypes.py
+18
-11
common/lib/capa/capa/tests/test_inputtypes.py
+56
-8
No files found.
common/lib/calc/calc.py
View file @
c65f0cac
...
@@ -60,10 +60,10 @@ DEFAULT_VARIABLES = {
...
@@ -60,10 +60,10 @@ DEFAULT_VARIABLES = {
'j'
:
numpy
.
complex
(
0
,
1
),
'j'
:
numpy
.
complex
(
0
,
1
),
'e'
:
numpy
.
e
,
'e'
:
numpy
.
e
,
'pi'
:
numpy
.
pi
,
'pi'
:
numpy
.
pi
,
'k'
:
scipy
.
constants
.
k
,
'k'
:
scipy
.
constants
.
k
,
# Boltzmann: 1.3806488e-23 (Joules/Kelvin)
'c'
:
scipy
.
constants
.
c
,
'c'
:
scipy
.
constants
.
c
,
# Light Speed: 2.998e8 (m/s)
'T'
:
298.15
,
'T'
:
298.15
,
# 0 deg C = T Kelvin
'q'
:
scipy
.
constants
.
e
'q'
:
scipy
.
constants
.
e
# Fund. Charge: 1.602176565e-19 (Coulombs)
}
}
# We eliminated the following extreme suffixes:
# We eliminated the following extreme suffixes:
...
@@ -126,8 +126,9 @@ def eval_atom(parse_result):
...
@@ -126,8 +126,9 @@ def eval_atom(parse_result):
In the case of parenthesis, ignore them.
In the case of parenthesis, ignore them.
"""
"""
float_children
=
[
k
for
k
in
parse_result
if
isinstance
(
k
,
numbers
.
Number
)]
# Find first number in the list
return
float_children
[
0
]
result
=
next
(
k
for
k
in
parse_result
if
isinstance
(
k
,
numbers
.
Number
))
return
result
def
eval_power
(
parse_result
):
def
eval_power
(
parse_result
):
...
...
common/lib/calc/preview.py
View file @
c65f0cac
...
@@ -158,7 +158,7 @@ def function_closure(functions, casify):
...
@@ -158,7 +158,7 @@ def function_closure(functions, casify):
"""
"""
fname
=
children
[
0
]
.
latex
fname
=
children
[
0
]
.
latex
if
casify
(
fname
)
not
in
functions
:
if
casify
(
fname
)
not
in
functions
:
pass
pass
# TODO turn unknown function red or give some kind of error
# Wrap the input of the function with parens or braces.
# Wrap the input of the function with parens or braces.
inner
=
children
[
1
]
.
latex
inner
=
children
[
1
]
.
latex
...
...
common/lib/calc/tests/test_calc.py
View file @
c65f0cac
...
@@ -50,10 +50,7 @@ class EvaluatorTest(unittest.TestCase):
...
@@ -50,10 +50,7 @@ class EvaluatorTest(unittest.TestCase):
"""
"""
Test that things like '4.' will be 4 and not throw an error
Test that things like '4.' will be 4 and not throw an error
"""
"""
try
:
self
.
assertEqual
(
4.0
,
calc
.
evaluator
({},
{},
'4.'
))
self
.
assertEqual
(
4.0
,
calc
.
evaluator
({},
{},
'4.'
))
except
ParseException
:
# pragma: no cover
self
.
fail
(
"'4.' is a valid input, but threw an exception"
)
def
test_exponential_answer
(
self
):
def
test_exponential_answer
(
self
):
"""
"""
...
@@ -362,17 +359,14 @@ class EvaluatorTest(unittest.TestCase):
...
@@ -362,17 +359,14 @@ class EvaluatorTest(unittest.TestCase):
# Of the form ('expr', python value, tolerance (or None for exact))
# Of the form ('expr', python value, tolerance (or None for exact))
default_variables
=
[
default_variables
=
[
(
'i'
,
1
j
,
None
),
(
'j'
,
1
j
,
None
),
(
'j'
,
1
j
,
None
),
(
'e'
,
2.7183
,
1e-3
),
(
'e'
,
2.7183
,
1e-4
),
(
'pi'
,
3.1416
,
1e-3
),
(
'pi'
,
3.1416
,
1e-4
),
# c = speed of light
(
'k'
,
1.3806488e-23
,
1e-26
),
# Boltzmann constant (Joules/Kelvin)
(
'c'
,
2.998e8
,
1e5
),
(
'c'
,
2.998e8
,
1e5
),
# Light Speed in (m/s)
# 0 deg C = T Kelvin
(
'T'
,
298.15
,
0.01
),
# 0 deg C = T Kelvin
(
'T'
,
298.15
,
0.01
),
(
'q'
,
1.602176565e-19
,
1e-22
)
# Fund. Charge (Coulombs)
# Note k = scipy.constants.k = 1.3806488e-23
(
'k'
,
1.3806488e-23
,
1e-26
),
# Note q = scipy.constants.e = 1.602176565e-19
(
'q'
,
1.602176565e-19
,
1e-22
)
]
]
for
(
variable
,
value
,
tolerance
)
in
default_variables
:
for
(
variable
,
value
,
tolerance
)
in
default_variables
:
fail_msg
=
"Failed on constant '{0}', not within bounds"
.
format
(
fail_msg
=
"Failed on constant '{0}', not within bounds"
.
format
(
...
@@ -382,8 +376,10 @@ class EvaluatorTest(unittest.TestCase):
...
@@ -382,8 +376,10 @@ class EvaluatorTest(unittest.TestCase):
if
tolerance
is
None
:
if
tolerance
is
None
:
self
.
assertEqual
(
value
,
result
,
msg
=
fail_msg
)
self
.
assertEqual
(
value
,
result
,
msg
=
fail_msg
)
else
:
else
:
self
.
assertAlmostEqual
(
value
,
result
,
self
.
assertAlmostEqual
(
delta
=
tolerance
,
msg
=
fail_msg
)
value
,
result
,
delta
=
tolerance
,
msg
=
fail_msg
)
def
test_complex_expression
(
self
):
def
test_complex_expression
(
self
):
"""
"""
...
@@ -514,20 +510,35 @@ class EvaluatorTest(unittest.TestCase):
...
@@ -514,20 +510,35 @@ class EvaluatorTest(unittest.TestCase):
-
1
,
delta
=
1e-3
-
1
,
delta
=
1e-3
)
)
def
test_function_case_
sensitivity
(
self
):
def
test_function_case_
insensitive
(
self
):
"""
"""
Test the case sensitivity of functions
Test case insensitive evaluation
Normal functions with some capitals should be fine
"""
"""
functions
=
{
'f'
:
lambda
x
:
x
,
'F'
:
lambda
x
:
x
+
1
}
self
.
assertAlmostEqual
(
-
0.28
,
calc
.
evaluator
({},
{},
'SiN(6)'
,
case_sensitive
=
False
),
delta
=
1e-3
)
def
test_function_case_sensitive
(
self
):
"""
Test case sensitive evaluation
# Test case insensitive evaluation
Incorrectly capitilized should fail
# Both evaulations should call the same function
Also, it should pick the correct version of a function.
self
.
assertEqual
(
calc
.
evaluator
({},
functions
,
'f(6)'
),
"""
calc
.
evaluator
({},
functions
,
'F(6)'
))
with
self
.
assertRaisesRegexp
(
calc
.
UndefinedVariable
,
'SiN'
):
# Test case sensitive evaluation
calc
.
evaluator
({},
{},
'SiN(6)'
,
case_sensitive
=
True
)
self
.
assertNotEqual
(
calc
.
evaluator
({},
functions
,
'f(6)'
,
case_sensitive
=
True
),
# With case sensitive turned on, it should pick the right function
calc
.
evaluator
({},
functions
,
'F(6)'
,
case_sensitive
=
True
)
functions
=
{
'f'
:
lambda
x
:
x
,
'F'
:
lambda
x
:
x
+
1
}
self
.
assertEqual
(
calc
.
evaluator
({},
functions
,
'f(6)'
,
case_sensitive
=
True
),
6
)
self
.
assertEqual
(
calc
.
evaluator
({},
functions
,
'F(6)'
,
case_sensitive
=
True
),
7
)
)
def
test_undefined_vars
(
self
):
def
test_undefined_vars
(
self
):
...
...
common/lib/capa/capa/inputtypes.py
View file @
c65f0cac
...
@@ -1040,15 +1040,16 @@ class ChemicalEquationInput(InputTypeBase):
...
@@ -1040,15 +1040,16 @@ class ChemicalEquationInput(InputTypeBase):
result
=
{
'preview'
:
''
,
result
=
{
'preview'
:
''
,
'error'
:
''
}
'error'
:
''
}
formula
=
data
[
'formula'
]
try
:
if
formula
is
None
:
formula
=
data
[
'formula'
]
except
KeyError
:
result
[
'error'
]
=
"No formula specified."
result
[
'error'
]
=
"No formula specified."
return
result
return
result
try
:
try
:
result
[
'preview'
]
=
chemcalc
.
render_to_html
(
formula
)
result
[
'preview'
]
=
chemcalc
.
render_to_html
(
formula
)
except
pyparsing
.
ParseException
as
p
:
except
pyparsing
.
ParseException
as
p
:
result
[
'error'
]
=
"Couldn't parse formula: {0}"
.
format
(
p
)
result
[
'error'
]
=
u"Couldn't parse formula: {0}"
.
format
(
p
.
msg
)
except
Exception
:
except
Exception
:
# this is unexpected, so log
# this is unexpected, so log
log
.
warning
(
log
.
warning
(
...
@@ -1100,12 +1101,12 @@ class FormulaEquationInput(InputTypeBase):
...
@@ -1100,12 +1101,12 @@ class FormulaEquationInput(InputTypeBase):
def
preview_formcalc
(
self
,
get
):
def
preview_formcalc
(
self
,
get
):
"""
"""
Render an
html preview of a formula formula or equation. get
should
Render an
preview of a formula or equation. `get`
should
contain a key 'formula'
and value 'some formula string'
.
contain a key 'formula'
with a math expression
.
Returns a json dictionary:
Returns a json dictionary:
{
{
'preview' : '
the-preview-html
' or ''
'preview' : '
<some latex>
' or ''
'error' : 'the-error' or ''
'error' : 'the-error' or ''
'request_start' : <time sent with request>
'request_start' : <time sent with request>
}
}
...
@@ -1113,17 +1114,23 @@ class FormulaEquationInput(InputTypeBase):
...
@@ -1113,17 +1114,23 @@ class FormulaEquationInput(InputTypeBase):
result
=
{
'preview'
:
''
,
result
=
{
'preview'
:
''
,
'error'
:
''
}
'error'
:
''
}
formula
=
get
[
'formula'
]
if
formula
is
None
:
try
:
formula
=
get
[
'formula'
]
except
KeyError
:
result
[
'error'
]
=
"No formula specified."
result
[
'error'
]
=
"No formula specified."
return
result
return
result
result
[
'request_start'
]
=
int
(
get
[
'request_start'
]
)
result
[
'request_start'
]
=
int
(
get
.
get
(
'request_start'
,
0
)
)
try
:
try
:
result
[
'preview'
]
=
latex_preview
(
formula
)
# TODO add references to variables, etc&
# TODO add references to valid variables and functions
# At some point, we might want to mark invalid variables as red
# or something, and this is where we would need to pass those in.
result
[
'preview'
]
=
latex_preview
(
formula
)
except
pyparsing
.
ParseException
as
err
:
except
pyparsing
.
ParseException
as
err
:
result
[
'error'
]
=
u"Couldn't parse formula: {0}"
.
format
(
err
.
message
)
result
[
'error'
]
=
u"Couldn't parse formula: {}"
.
format
(
err
.
msg
)
result
[
'formula'
]
=
formula
except
Exception
:
except
Exception
:
# this is unexpected, so log
# this is unexpected, so log
log
.
warning
(
log
.
warning
(
...
...
common/lib/capa/capa/tests/test_inputtypes.py
View file @
c65f0cac
...
@@ -729,10 +729,57 @@ class ChemicalEquationTest(unittest.TestCase):
...
@@ -729,10 +729,57 @@ class ChemicalEquationTest(unittest.TestCase):
data
=
{
'formula'
:
"H"
}
data
=
{
'formula'
:
"H"
}
response
=
self
.
the_input
.
handle_ajax
(
"preview_chemcalc"
,
data
)
response
=
self
.
the_input
.
handle_ajax
(
"preview_chemcalc"
,
data
)
self
.
assert
True
(
'preview'
in
response
)
self
.
assert
In
(
'preview'
,
response
)
self
.
assertNotEqual
(
response
[
'preview'
],
''
)
self
.
assertNotEqual
(
response
[
'preview'
],
''
)
self
.
assertEqual
(
response
[
'error'
],
""
)
self
.
assertEqual
(
response
[
'error'
],
""
)
def
test_ajax_bad_method
(
self
):
"""
With a bad dispatch, we shouldn't recieve anything
"""
response
=
self
.
the_input
.
handle_ajax
(
"obviously_not_real"
,
{})
self
.
assertEqual
(
response
,
{})
def
test_ajax_no_formula
(
self
):
"""
When we ask for a formula rendering, there should be an error if no formula
"""
response
=
self
.
the_input
.
handle_ajax
(
"preview_chemcalc"
,
{})
self
.
assertIn
(
'error'
,
response
)
self
.
assertEqual
(
response
[
'error'
],
"No formula specified."
)
def
test_ajax_parse_err
(
self
):
"""
With parse errors, ChemicalEquationInput should give an error message
"""
# Simulate answering a problem that raises the exception
with
patch
(
'capa.inputtypes.chemcalc.render_to_html'
)
as
mock_render
:
mock_render
.
side_effect
=
ParseException
(
u"ȧƈƈḗƞŧḗḓ ŧḗẋŧ ƒǿř ŧḗşŧīƞɠ"
)
response
=
self
.
the_input
.
handle_ajax
(
"preview_chemcalc"
,
{
'formula'
:
'H2O + invalid chemistry'
}
)
self
.
assertIn
(
'error'
,
response
)
self
.
assertTrue
(
"Couldn't parse formula"
in
response
[
'error'
])
@patch
(
'capa.inputtypes.log'
)
def
test_ajax_other_err
(
self
,
mock_log
):
"""
With other errors, test that ChemicalEquationInput also logs it
"""
with
patch
(
'capa.inputtypes.chemcalc.render_to_html'
)
as
mock_render
:
mock_render
.
side_effect
=
Exception
()
response
=
self
.
the_input
.
handle_ajax
(
"preview_chemcalc"
,
{
'formula'
:
'H2O + superterrible chemistry'
}
)
mock_log
.
warning
.
assert_called_once_with
(
"Error while previewing chemical formula"
,
exc_info
=
True
)
self
.
assertIn
(
'error'
,
response
)
self
.
assertEqual
(
response
[
'error'
],
"Error while rendering preview"
)
class
FormulaEquationTest
(
unittest
.
TestCase
):
class
FormulaEquationTest
(
unittest
.
TestCase
):
"""
"""
...
@@ -744,7 +791,7 @@ class FormulaEquationTest(unittest.TestCase):
...
@@ -744,7 +791,7 @@ class FormulaEquationTest(unittest.TestCase):
element
=
etree
.
fromstring
(
xml_str
)
element
=
etree
.
fromstring
(
xml_str
)
state
=
{
'value'
:
'x^2+1/2'
,
}
state
=
{
'value'
:
'x^2+1/2'
}
self
.
the_input
=
lookup_tag
(
'formulaequationinput'
)(
test_system
(),
element
,
state
)
self
.
the_input
=
lookup_tag
(
'formulaequationinput'
)(
test_system
(),
element
,
state
)
def
test_rendering
(
self
):
def
test_rendering
(
self
):
...
@@ -769,7 +816,7 @@ class FormulaEquationTest(unittest.TestCase):
...
@@ -769,7 +816,7 @@ class FormulaEquationTest(unittest.TestCase):
data
=
{
'formula'
:
"x^2+1/2"
,
'request_start'
:
0
}
data
=
{
'formula'
:
"x^2+1/2"
,
'request_start'
:
0
}
response
=
self
.
the_input
.
handle_ajax
(
"preview_formcalc"
,
data
)
response
=
self
.
the_input
.
handle_ajax
(
"preview_formcalc"
,
data
)
self
.
assert
True
(
'preview'
in
response
)
self
.
assert
In
(
'preview'
,
response
)
self
.
assertNotEqual
(
response
[
'preview'
],
''
)
self
.
assertNotEqual
(
response
[
'preview'
],
''
)
self
.
assertEqual
(
response
[
'error'
],
""
)
self
.
assertEqual
(
response
[
'error'
],
""
)
self
.
assertEqual
(
response
[
'request_start'
],
data
[
'request_start'
])
self
.
assertEqual
(
response
[
'request_start'
],
data
[
'request_start'
])
...
@@ -787,9 +834,9 @@ class FormulaEquationTest(unittest.TestCase):
...
@@ -787,9 +834,9 @@ class FormulaEquationTest(unittest.TestCase):
"""
"""
response
=
self
.
the_input
.
handle_ajax
(
response
=
self
.
the_input
.
handle_ajax
(
"preview_formcalc"
,
"preview_formcalc"
,
{
'
formula'
:
None
,
'
request_start'
:
1
,
}
{
'request_start'
:
1
,
}
)
)
self
.
assert
True
(
'error'
in
response
)
self
.
assert
In
(
'error'
,
response
)
self
.
assertEqual
(
response
[
'error'
],
"No formula specified."
)
self
.
assertEqual
(
response
[
'error'
],
"No formula specified."
)
def
test_ajax_parse_err
(
self
):
def
test_ajax_parse_err
(
self
):
...
@@ -804,8 +851,9 @@ class FormulaEquationTest(unittest.TestCase):
...
@@ -804,8 +851,9 @@ class FormulaEquationTest(unittest.TestCase):
{
'formula'
:
'x^2+1/2'
,
'request_start'
:
1
,
}
{
'formula'
:
'x^2+1/2'
,
'request_start'
:
1
,
}
)
)
self
.
assertTrue
(
'error'
in
response
)
self
.
assertIn
(
'error'
,
response
)
self
.
assertTrue
(
"Couldn't parse formula"
in
response
[
'error'
])
self
.
assertEqual
(
response
[
'error'
],
u"Couldn't parse formula: ȧƈƈḗƞŧḗḓ ŧḗẋŧ ƒǿř ŧḗşŧīƞɠ"
)
@patch
(
'capa.inputtypes.log'
)
@patch
(
'capa.inputtypes.log'
)
def
test_ajax_other_err
(
self
,
mock_log
):
def
test_ajax_other_err
(
self
,
mock_log
):
...
@@ -821,7 +869,7 @@ class FormulaEquationTest(unittest.TestCase):
...
@@ -821,7 +869,7 @@ class FormulaEquationTest(unittest.TestCase):
mock_log
.
warning
.
assert_called_once_with
(
mock_log
.
warning
.
assert_called_once_with
(
"Error while previewing formula"
,
exc_info
=
True
"Error while previewing formula"
,
exc_info
=
True
)
)
self
.
assert
True
(
'error'
in
response
)
self
.
assert
In
(
'error'
,
response
)
self
.
assertEqual
(
response
[
'error'
],
"Error while rendering preview"
)
self
.
assertEqual
(
response
[
'error'
],
"Error while rendering preview"
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment