Commit e6dfa8e8 by cahrens

Merge branch 'master' into feature/christina/metadata-ui

parents 6c06599d 46967a78
......@@ -61,6 +61,8 @@
<div class="wrapper wrapper-view">
<%include file="widgets/header.html" />
## remove this block after advanced settings notification is rewritten
<%block name="view_alerts"></%block>
<div id="page-alert"></div>
<%block name="content"></%block>
......@@ -72,9 +74,13 @@
<%include file="widgets/footer.html" />
<%include file="widgets/tender.html" />
## remove this block after advanced settings notification is rewritten
<%block name="view_notifications"></%block>
<div id="page-notification"></div>
</div>
## remove this block after advanced settings notification is rewritten
<%block name="view_prompts"></%block>
<div id="page-prompt"></div>
<%block name="jsextra"></%block>
</body>
......
# .coveragerc for common/lib/calc
[run]
data_file = reports/common/lib/calc/.coverage
source = common/lib/calc
branch = true
[report]
ignore_errors = True
[html]
title = Calc Python Test Coverage Report
directory = reports/common/lib/calc/cover
[xml]
output = reports/common/lib/calc/coverage.xml
......@@ -144,6 +144,8 @@ def evaluator(variables, functions, string, cs=False):
return x
def parallel(x): # Parallel resistors [ 1 2 ] => 2/3
# convert from pyparsing.ParseResults, which doesn't support '0 in x'
x = list(x)
if len(x) == 1:
return x[0]
if 0 in x:
......@@ -230,27 +232,3 @@ def evaluator(variables, functions, string, cs=False):
expr << Optional((plus | minus)) + term + ZeroOrMore((plus | minus) + term) # -5 + 4 - 3
expr = expr.setParseAction(sum_parse_action)
return (expr + stringEnd).parseString(string)[0]
if __name__ == '__main__':
variables = {'R1': 2.0, 'R3': 4.0}
functions = {'sin': numpy.sin, 'cos': numpy.cos}
print "X", evaluator(variables, functions, "10000||sin(7+5)-6k")
print "X", evaluator(variables, functions, "13")
print evaluator({'R1': 2.0, 'R3': 4.0}, {}, "13")
print evaluator({'e1': 1, 'e2': 1.0, 'R3': 7, 'V0': 5, 'R5': 15, 'I1': 1, 'R4': 6}, {}, "e2")
print evaluator({'a': 2.2997471478310274, 'k': 9, 'm': 8, 'x': 0.66009498411213041}, {}, "5")
print evaluator({}, {}, "-1")
print evaluator({}, {}, "-(7+5)")
print evaluator({}, {}, "-0.33")
print evaluator({}, {}, "-.33")
print evaluator({}, {}, "5+1*j")
print evaluator({}, {}, "j||1")
print evaluator({}, {}, "e^(j*pi)")
print evaluator({}, {}, "fact(5)")
print evaluator({}, {}, "factorial(5)")
try:
print evaluator({}, {}, "5+7 QWSEKO")
except UndefinedVariable:
print "Successfully caught undefined variable"
"""
Unit tests for calc.py
"""
import unittest
import numpy
import calc
class EvaluatorTest(unittest.TestCase):
"""
Run tests for calc.evaluator
Go through all functionalities as specifically as possible--
work from number input to functions and complex expressions
Also test custom variable substitutions (i.e.
`evaluator({'x':3.0},{}, '3*x')`
gives 9.0) and more.
"""
def test_number_input(self):
"""
Test different kinds of float inputs
"""
easy_eval = lambda x: calc.evaluator({}, {}, x)
self.assertEqual(easy_eval("13"), 13)
self.assertEqual(easy_eval("3.14"), 3.14)
self.assertEqual(easy_eval(".618033989"), 0.618033989)
self.assertEqual(easy_eval("-13"), -13)
self.assertEqual(easy_eval("-3.14"), -3.14)
self.assertEqual(easy_eval("-.618033989"), -0.618033989)
# See also test_exponential_answer and test_si_suffix
def test_exponential_answer(self):
"""
Test for correct interpretation of scientific notation
"""
answer = 50
correct_responses = ["50", "50.0", "5e1", "5e+1",
"50e0", "50.0e0", "500e-1"]
incorrect_responses = ["", "3.9", "4.1", "0", "5.01e1"]
for input_str in correct_responses:
result = calc.evaluator({}, {}, input_str)
fail_msg = "Expected '{0}' to equal {1}".format(
input_str, answer)
self.assertEqual(answer, result, msg=fail_msg)
for input_str in incorrect_responses:
result = calc.evaluator({}, {}, input_str)
fail_msg = "Expected '{0}' to not equal {1}".format(
input_str, answer)
self.assertNotEqual(answer, result, msg=fail_msg)
def test_si_suffix(self):
"""
Test calc.py's unique functionality of interpreting si 'suffixes'.
For instance 'k' stand for 'kilo-' so '1k' should be 1,000
"""
test_mapping = [('4.2%', 0.042), ('2.25k', 2250), ('8.3M', 8300000),
('9.9G', 9.9e9), ('1.2T', 1.2e12), ('7.4c', 0.074),
('5.4m', 0.0054), ('8.7u', 0.0000087),
('5.6n', 5.6e-9), ('4.2p', 4.2e-12)]
for (expr, answer) in test_mapping:
tolerance = answer * 1e-6 # Make rel. tolerance, because of floats
fail_msg = "Failure in testing suffix '{0}': '{1}' was not {2}"
fail_msg = fail_msg.format(expr[-1], expr, answer)
self.assertAlmostEqual(calc.evaluator({}, {}, expr), answer,
delta=tolerance, msg=fail_msg)
def test_operator_sanity(self):
"""
Test for simple things like '5+2' and '5/2'
"""
var1 = 5.0
var2 = 2.0
operators = [('+', 7), ('-', 3), ('*', 10), ('/', 2.5), ('^', 25)]
for (operator, answer) in operators:
input_str = "{0} {1} {2}".format(var1, operator, var2)
result = calc.evaluator({}, {}, input_str)
fail_msg = "Failed on operator '{0}': '{1}' was not {2}".format(
operator, input_str, answer)
self.assertEqual(answer, result, msg=fail_msg)
def test_raises_zero_division_err(self):
"""
Ensure division by zero gives an error
"""
self.assertRaises(ZeroDivisionError, calc.evaluator,
{}, {}, '1/0')
self.assertRaises(ZeroDivisionError, calc.evaluator,
{}, {}, '1/0.0')
self.assertRaises(ZeroDivisionError, calc.evaluator,
{'x': 0.0}, {}, '1/x')
def test_parallel_resistors(self):
"""
Test the parallel resistor operator ||
The formula is given by
a || b || c ...
= 1 / (1/a + 1/b + 1/c + ...)
It is the resistance of a parallel circuit of resistors with resistance
a, b, c, etc&. See if this evaulates correctly.
"""
self.assertEqual(calc.evaluator({}, {}, '1||1'), 0.5)
self.assertEqual(calc.evaluator({}, {}, '1||1||2'), 0.4)
self.assertEqual(calc.evaluator({}, {}, "j||1"), 0.5 + 0.5j)
def test_parallel_resistors_with_zero(self):
"""
Check the behavior of the || operator with 0
"""
self.assertTrue(numpy.isnan(calc.evaluator({}, {}, '0||1')))
self.assertTrue(numpy.isnan(calc.evaluator({}, {}, '0.0||1')))
self.assertTrue(numpy.isnan(calc.evaluator({'x': 0.0}, {}, 'x||1')))
def assert_function_values(self, fname, ins, outs, tolerance=1e-3):
"""
Helper function to test many values at once
Test the accuracy of evaluator's use of the function given by fname
Specifically, the equality of `fname(ins[i])` against outs[i].
This is used later to test a whole bunch of f(x) = y at a time
"""
for (arg, val) in zip(ins, outs):
input_str = "{0}({1})".format(fname, arg)
result = calc.evaluator({}, {}, input_str)
fail_msg = "Failed on function {0}: '{1}' was not {2}".format(
fname, input_str, val)
self.assertAlmostEqual(val, result, delta=tolerance, msg=fail_msg)
def test_trig_functions(self):
"""
Test the trig functions provided in calc.py
which are: sin, cos, tan, arccos, arcsin, arctan
"""
angles = ['-pi/4', '0', 'pi/6', 'pi/5', '5*pi/4', '9*pi/4', '1 + j']
sin_values = [-0.707, 0, 0.5, 0.588, -0.707, 0.707, 1.298 + 0.635j]
cos_values = [0.707, 1, 0.866, 0.809, -0.707, 0.707, 0.834 - 0.989j]
tan_values = [-1, 0, 0.577, 0.727, 1, 1, 0.272 + 1.084j]
# Cannot test tan(pi/2) b/c pi/2 is a float and not precise...
self.assert_function_values('sin', angles, sin_values)
self.assert_function_values('cos', angles, cos_values)
self.assert_function_values('tan', angles, tan_values)
# Include those where the real part is between -pi/2 and pi/2
arcsin_inputs = ['-0.707', '0', '0.5', '0.588', '1.298 + 0.635*j']
arcsin_angles = [-0.785, 0, 0.524, 0.629, 1 + 1j]
self.assert_function_values('arcsin', arcsin_inputs, arcsin_angles)
# Rather than throwing an exception, numpy.arcsin gives nan
# self.assertTrue(numpy.isnan(calc.evaluator({}, {}, 'arcsin(-1.1)')))
# self.assertTrue(numpy.isnan(calc.evaluator({}, {}, 'arcsin(1.1)')))
# Disabled for now because they are giving a runtime warning... :-/
# Include those where the real part is between 0 and pi
arccos_inputs = ['1', '0.866', '0.809', '0.834-0.989*j']
arccos_angles = [0, 0.524, 0.628, 1 + 1j]
self.assert_function_values('arccos', arccos_inputs, arccos_angles)
# self.assertTrue(numpy.isnan(calc.evaluator({}, {}, 'arccos(-1.1)')))
# self.assertTrue(numpy.isnan(calc.evaluator({}, {}, 'arccos(1.1)')))
# Has the same range as arcsin
arctan_inputs = ['-1', '0', '0.577', '0.727', '0.272 + 1.084*j']
arctan_angles = arcsin_angles
self.assert_function_values('arctan', arctan_inputs, arctan_angles)
def test_other_functions(self):
"""
Test the non-trig functions provided in calc.py
Specifically:
sqrt, log10, log2, ln, abs,
fact, factorial
"""
# Test sqrt
self.assert_function_values('sqrt',
[0, 1, 2, 1024], # -1
[0, 1, 1.414, 32]) # 1j
# sqrt(-1) is NAN not j (!!).
# Test logs
self.assert_function_values('log10',
[0.1, 1, 3.162, 1000000, '1+j'],
[-1, 0, 0.5, 6, 0.151 + 0.341j])
self.assert_function_values('log2',
[0.5, 1, 1.414, 1024, '1+j'],
[-1, 0, 0.5, 10, 0.5 + 1.133j])
self.assert_function_values('ln',
[0.368, 1, 1.649, 2.718, 42, '1+j'],
[-1, 0, 0.5, 1, 3.738, 0.347 + 0.785j])
# Test abs
self.assert_function_values('abs', [-1, 0, 1, 'j'], [1, 0, 1, 1])
# Test factorial
fact_inputs = [0, 1, 3, 7]
fact_values = [1, 1, 6, 5040]
self.assert_function_values('fact', fact_inputs, fact_values)
self.assert_function_values('factorial', fact_inputs, fact_values)
self.assertRaises(ValueError, calc.evaluator, {}, {}, "fact(-1)")
self.assertRaises(ValueError, calc.evaluator, {}, {}, "fact(0.5)")
self.assertRaises(ValueError, calc.evaluator, {}, {}, "factorial(-1)")
self.assertRaises(ValueError, calc.evaluator, {}, {}, "factorial(0.5)")
def test_constants(self):
"""
Test the default constants provided in calc.py
which are: j (complex number), e, pi, k, c, T, q
"""
# Of the form ('expr', python value, tolerance (or None for exact))
default_variables = [('j', 1j, None),
('e', 2.7183, 1e-3),
('pi', 3.1416, 1e-3),
# c = speed of light
('c', 2.998e8, 1e5),
# 0 deg C = T Kelvin
('T', 298.15, 0.01),
# 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:
fail_msg = "Failed on constant '{0}', not within bounds".format(
variable)
result = calc.evaluator({}, {}, variable)
if tolerance is None:
self.assertEqual(value, result, msg=fail_msg)
else:
self.assertAlmostEqual(value, result,
delta=tolerance, msg=fail_msg)
def test_complex_expression(self):
"""
Calculate combinations of operators and default functions
"""
self.assertAlmostEqual(
calc.evaluator({}, {}, "(2^2+1.0)/sqrt(5e0)*5-1"),
10.180,
delta=1e-3)
self.assertAlmostEqual(
calc.evaluator({}, {}, "1+1/(1+1/(1+1/(1+1)))"),
1.6,
delta=1e-3)
self.assertAlmostEqual(
calc.evaluator({}, {}, "10||sin(7+5)"),
-0.567, delta=0.01)
self.assertAlmostEqual(calc.evaluator({}, {}, "sin(e)"),
0.41, delta=0.01)
self.assertAlmostEqual(calc.evaluator({}, {}, "k*T/q"),
0.025, delta=1e-3)
self.assertAlmostEqual(calc.evaluator({}, {}, "e^(j*pi)"),
-1, delta=1e-5)
def test_simple_vars(self):
"""
Substitution of variables into simple equations
"""
variables = {'x': 9.72, 'y': 7.91, 'loooooong': 6.4}
# Should not change value of constant
# even with different numbers of variables...
self.assertEqual(calc.evaluator({'x': 9.72}, {}, '13'), 13)
self.assertEqual(calc.evaluator({'x': 9.72, 'y': 7.91}, {}, '13'), 13)
self.assertEqual(calc.evaluator(variables, {}, '13'), 13)
# Easy evaluation
self.assertEqual(calc.evaluator(variables, {}, 'x'), 9.72)
self.assertEqual(calc.evaluator(variables, {}, 'y'), 7.91)
self.assertEqual(calc.evaluator(variables, {}, 'loooooong'), 6.4)
# Test a simple equation
self.assertAlmostEqual(calc.evaluator(variables, {}, '3*x-y'),
21.25, delta=0.01) # = 3 * 9.72 - 7.91
self.assertAlmostEqual(calc.evaluator(variables, {}, 'x*y'),
76.89, delta=0.01)
self.assertEqual(calc.evaluator({'x': 9.72, 'y': 7.91}, {}, "13"), 13)
self.assertEqual(calc.evaluator(variables, {}, "13"), 13)
self.assertEqual(
calc.evaluator({
'a': 2.2997471478310274, 'k': 9, 'm': 8,
'x': 0.66009498411213041},
{}, "5"),
5)
def test_variable_case_sensitivity(self):
"""
Test the case sensitivity flag and corresponding behavior
"""
self.assertEqual(
calc.evaluator({'R1': 2.0, 'R3': 4.0}, {}, "r1*r3"),
8.0)
variables = {'t': 1.0}
self.assertEqual(calc.evaluator(variables, {}, "t"), 1.0)
self.assertEqual(calc.evaluator(variables, {}, "T"), 1.0)
self.assertEqual(calc.evaluator(variables, {}, "t", cs=True), 1.0)
# Recall 'T' is a default constant, with value 298.15
self.assertAlmostEqual(calc.evaluator(variables, {}, "T", cs=True),
298, delta=0.2)
def test_simple_funcs(self):
"""
Subsitution of custom functions
"""
variables = {'x': 4.712}
functions = {'id': lambda x: x}
self.assertEqual(calc.evaluator({}, functions, 'id(2.81)'), 2.81)
self.assertEqual(calc.evaluator({}, functions, 'id(2.81)'), 2.81)
self.assertEqual(calc.evaluator(variables, functions, 'id(x)'), 4.712)
functions.update({'f': numpy.sin})
self.assertAlmostEqual(calc.evaluator(variables, functions, 'f(x)'),
-1, delta=1e-3)
def test_function_case_sensitivity(self):
"""
Test the case sensitivity of functions
"""
functions = {'f': lambda x: x,
'F': lambda x: x + 1}
# Test case insensitive evaluation
# Both evaulations should call the same function
self.assertEqual(calc.evaluator({}, functions, 'f(6)'),
calc.evaluator({}, functions, 'F(6)'))
# Test case sensitive evaluation
self.assertNotEqual(calc.evaluator({}, functions, 'f(6)', cs=True),
calc.evaluator({}, functions, 'F(6)', cs=True))
def test_undefined_vars(self):
"""
Check to see if the evaluator catches undefined variables
"""
variables = {'R1': 2.0, 'R3': 4.0}
self.assertRaises(calc.UndefinedVariable, calc.evaluator,
{}, {}, "5+7 QWSEKO")
self.assertRaises(calc.UndefinedVariable, calc.evaluator,
{'r1': 5}, {}, "r1+r2")
self.assertRaises(calc.UndefinedVariable, calc.evaluator,
variables, {}, "r1*r3", cs=True)
......@@ -10,7 +10,6 @@ import random
import unittest
import textwrap
import mock
import textwrap
from . import new_loncapa_problem, test_system
......@@ -190,7 +189,7 @@ class SymbolicResponseTest(ResponseTest):
def test_grade_single_input(self):
problem = self.build_problem(math_display=True,
expect="2*x+3*y")
expect="2*x+3*y")
# Correct answers
correct_inputs = [
......@@ -223,7 +222,6 @@ class SymbolicResponseTest(ResponseTest):
for (input_str, input_mathml) in incorrect_inputs:
self._assert_symbolic_grade(problem, input_str, input_mathml, 'incorrect')
def test_complex_number_grade(self):
problem = self.build_problem(math_display=True,
expect="[[cos(theta),i*sin(theta)],[i*sin(theta),cos(theta)]]",
......@@ -241,7 +239,7 @@ class SymbolicResponseTest(ResponseTest):
# Correct answer
with mock.patch.object(requests, 'post') as mock_post:
# Simulate what the LaTeX-to-MathML server would
# Simulate what the LaTeX-to-MathML server would
# send for the correct response input
mock_post.return_value.text = correct_snuggletex_response
......@@ -323,7 +321,7 @@ class SymbolicResponseTest(ResponseTest):
dynamath_input,
expected_correctness):
input_dict = {'1_2_1': str(student_input),
'1_2_1_dynamath': str(dynamath_input) }
'1_2_1_dynamath': str(dynamath_input)}
correct_map = problem.grade_answers(input_dict)
......@@ -349,10 +347,18 @@ class OptionResponseTest(ResponseTest):
class FormulaResponseTest(ResponseTest):
"""
Test the FormulaResponse class
"""
from response_xml_factory import FormulaResponseXMLFactory
xml_factory_class = FormulaResponseXMLFactory
def test_grade(self):
"""
Test basic functionality of FormulaResponse
Specifically, if it can understand equivalence of formulae
"""
# Sample variables x and y in the range [-10, 10]
sample_dict = {'x': (-10, 10), 'y': (-10, 10)}
......@@ -373,6 +379,9 @@ class FormulaResponseTest(ResponseTest):
self.assert_grade(problem, input_formula, "incorrect")
def test_hint(self):
"""
Test the hint-giving functionality of FormulaResponse
"""
# Sample variables x and y in the range [-10, 10]
sample_dict = {'x': (-10, 10), 'y': (-10, 10)}
......@@ -401,6 +410,10 @@ class FormulaResponseTest(ResponseTest):
'Try including the variable x')
def test_script(self):
"""
Test if python script can be used to generate answers
"""
# Calculate the answer using a script
script = "calculated_ans = 'x+x'"
......@@ -419,7 +432,9 @@ class FormulaResponseTest(ResponseTest):
self.assert_grade(problem, '3*x', 'incorrect')
def test_parallel_resistors(self):
"""Test parallel resistors"""
"""
Test parallel resistors
"""
sample_dict = {'R1': (10, 10), 'R2': (2, 2), 'R3': (5, 5), 'R4': (1, 1)}
# Test problem
......@@ -440,8 +455,11 @@ class FormulaResponseTest(ResponseTest):
self.assert_grade(problem, input_formula, "incorrect")
def test_default_variables(self):
"""Test the default variables provided in common/lib/capa/capa/calc.py"""
# which are: j (complex number), e, pi, k, c, T, q
"""
Test the default variables provided in calc.py
which are: j (complex number), e, pi, k, c, T, q
"""
# Sample x in the range [-10,10]
sample_dict = {'x': (-10, 10)}
......@@ -464,11 +482,14 @@ class FormulaResponseTest(ResponseTest):
msg="Failed on variable {0}; the given, incorrect answer was {1} but graded 'correct'".format(var, incorrect))
def test_default_functions(self):
"""Test the default functions provided in common/lib/capa/capa/calc.py"""
# which are: sin, cos, tan, sqrt, log10, log2, ln,
# arccos, arcsin, arctan, abs,
# fact, factorial
"""
Test the default functions provided in common/lib/capa/capa/calc.py
which are:
sin, cos, tan, sqrt, log10, log2, ln,
arccos, arcsin, arctan, abs,
fact, factorial
"""
w = random.randint(3, 10)
sample_dict = {'x': (-10, 10), # Sample x in the range [-10,10]
'y': (1, 10), # Sample y in the range [1,10] - logs, arccos need positive inputs
......@@ -496,8 +517,10 @@ class FormulaResponseTest(ResponseTest):
msg="Failed on function {0}; the given, incorrect answer was {1} but graded 'correct'".format(func, incorrect))
def test_grade_infinity(self):
# This resolves a bug where a problem with relative tolerance would
# pass with any arbitrarily large student answer.
"""
Test that a large input on a problem with relative tolerance isn't
erroneously marked as correct.
"""
sample_dict = {'x': (1, 2)}
......@@ -514,8 +537,9 @@ class FormulaResponseTest(ResponseTest):
self.assert_grade(problem, input_formula, "incorrect")
def test_grade_nan(self):
# Attempt to produce a value which causes the student's answer to be
# evaluated to nan. See if this is resolved correctly.
"""
Test that expressions that evaluate to NaN are not marked as correct.
"""
sample_dict = {'x': (1, 2)}
......@@ -532,6 +556,18 @@ class FormulaResponseTest(ResponseTest):
input_formula = "x + 0*1e999"
self.assert_grade(problem, input_formula, "incorrect")
def test_raises_zero_division_err(self):
"""
See if division by zero raises an error.
"""
sample_dict = {'x': (1, 2)}
problem = self.build_problem(sample_dict=sample_dict,
num_samples=10,
tolerance="1%",
answer="x") # Answer doesn't matter
input_dict = {'1_2_1': '1/0'}
self.assertRaises(StudentInputError, problem.grade_answers, input_dict)
class StringResponseTest(ResponseTest):
from response_xml_factory import StringResponseXMLFactory
......@@ -592,7 +628,7 @@ class StringResponseTest(ResponseTest):
problem = self.build_problem(
answer="Michigan",
hintfn="gimme_a_hint",
script = textwrap.dedent("""
script=textwrap.dedent("""
def gimme_a_hint(answer_ids, student_answers, new_cmap, old_cmap):
aid = answer_ids[0]
answer = student_answers[aid]
......@@ -898,6 +934,14 @@ class NumericalResponseTest(ResponseTest):
incorrect_responses = ["", "3.9", "4.1", "0", "5.01e1"]
self.assert_multiple_grade(problem, correct_responses, incorrect_responses)
def test_raises_zero_division_err(self):
"""See if division by zero is handled correctly"""
problem = self.build_problem(question_text="What 5 * 10?",
explanation="The answer is 50",
answer="5e+1") # Answer doesn't matter
input_dict = {'1_2_1': '1/0'}
self.assertRaises(StudentInputError, problem.grade_answers, input_dict)
class CustomResponseTest(ResponseTest):
from response_xml_factory import CustomResponseXMLFactory
......@@ -947,8 +991,8 @@ class CustomResponseTest(ResponseTest):
#
# 'answer_given' is the answer the student gave (if there is just one input)
# or an ordered list of answers (if there are multiple inputs)
#
# The function should return a dict of the form
#
# The function should return a dict of the form
# { 'ok': BOOL, 'msg': STRING }
#
script = textwrap.dedent("""
......
This source diff could not be displayed because it is too large. You can view the blob instead.
34d1996e44f78168a73297217b3a0973c2ae90e1
\ No newline at end of file
......@@ -115,6 +115,11 @@ xmodule can be tested independently, with this:
rake test_common/lib/xmodule
other module level tests include
* `rake test_common/lib/capa`
* `rake test_common/lib/calc`
To run a single django test class:
rake test_lms[courseware.tests.tests:testViewAuth]
......
b154ce99fb5c8d413ba769e8cc0df94ed674c3f4
\ No newline at end of file
2b8c58b098bdb17f9ddcbb2098f94c50fdcedf60
\ No newline at end of file
7d8b9879f7e5b859910edba7249661eedd3fcf37
\ No newline at end of file
caf8b43337faa75cef5da5cd090010215a67b1bd
\ No newline at end of file
b4d043bb1ca4a8815d4a388a2c9d96038211417b
\ No newline at end of file
6718f0c6e851376b5478baff94e1f1f4449bd938
\ No newline at end of file
......@@ -10,6 +10,9 @@ end
# the ENV_TOKENS to the templating context.
def preprocess_with_mako(filename)
# simple command-line invocation of Mako engine
# cdodge: the .gsub() are used to translate true->True and false->False to make the generated
# python actually valid python. This is just a short term hack to unblock the release train
# until a real fix can be made by people who know this better
mako = "from mako.template import Template;" +
"print Template(filename=\"#{filename}\")" +
# Total hack. It works because a Python dict literal has
......
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