Commit 1abeec78 by Bridger Maxwell

Merge

parents ca44cf07 cbd8a964
...@@ -74,8 +74,10 @@ def login_user(request, error=""): ...@@ -74,8 +74,10 @@ def login_user(request, error=""):
log.critical("Login failed - Could not create session. Is memcached running?") log.critical("Login failed - Could not create session. Is memcached running?")
log.exception(e) log.exception(e)
log.info("Login success - {0} ({1})".format(username, email))
return HttpResponse(json.dumps({'success':True})) return HttpResponse(json.dumps({'success':True}))
log.warning("Login failed - Account not active for user {0}".format(username))
return HttpResponse(json.dumps({'success':False, return HttpResponse(json.dumps({'success':False,
'error': 'Account not active. Check your e-mail.'})) 'error': 'Account not active. Check your e-mail.'}))
......
...@@ -133,7 +133,7 @@ class LoncapaProblem(object): ...@@ -133,7 +133,7 @@ class LoncapaProblem(object):
for entry in problems_simple.xpath("//"+"|//".join(response_properties+entry_types)): for entry in problems_simple.xpath("//"+"|//".join(response_properties+entry_types)):
answer = entry.get('correct_answer') answer = entry.get('correct_answer')
if answer != None: if answer != None:
answer_map[entry.get('id')] = contextualize_text(answer, self.context()) answer_map[entry.get('id')] = contextualize_text(answer, self.context)
return answer_map return answer_map
......
...@@ -3,12 +3,16 @@ from util import contextualize_text ...@@ -3,12 +3,16 @@ from util import contextualize_text
from calc import evaluator from calc import evaluator
import random, math import random, math
from django.conf import settings from django.conf import settings
import eia
import calc
# TODO: Should be the same object as in capa_problem # TODO: Should be the same object as in capa_problem
global_context={'random':random, global_context={'random':random,
'numpy':numpy, 'numpy':numpy,
'math':math, 'math':math,
'scipy':scipy} 'scipy':scipy,
'calc':calc,
'eia':eia}
class numericalresponse(object): class numericalresponse(object):
def __init__(self, xml, context): def __init__(self, xml, context):
......
import math
from numpy import eye, array
import operator
from pyparsing import Word, alphas, nums, oneOf, Literal
from pyparsing import ZeroOrMore, OneOrMore, StringStart
from pyparsing import StringEnd, Optional, Forward
from pyparsing import CaselessLiteral, Group, StringEnd
from pyparsing import NoMatch, stringEnd
base_units = ['meter', 'gram', 'second', 'ampere', 'kelvin', 'mole', 'cd']
unit_vectors = dict([(base_units[i], eye(len(base_units))[:,i]) for i in range(len(base_units))])
def unit_evaluator(unit_string, units=unit_map):
''' Evaluate an expression. Variables are passed as a dictionary
from string to value. Unary functions are passed as a dictionary
from string to function '''
if string.strip() == "":
return float('nan')
ops = { "^" : operator.pow,
"*" : operator.mul,
"/" : operator.truediv,
}
prefixes={'%':0.01,'k':1e3,'M':1e6,'G':1e9,
'T':1e12,#'P':1e15,'E':1e18,'Z':1e21,'Y':1e24,
'c':1e-2,'m':1e-3,'u':1e-6,
'n':1e-9,'p':1e-12}#,'f':1e-15,'a':1e-18,'z':1e-21,'y':1e-24}
def super_float(text):
''' Like float, but with si extensions. 1k goes to 1000'''
if text[-1] in suffixes:
return float(text[:-1])*suffixes[text[-1]]
else:
return float(text)
def number_parse_action(x): # [ '7' ] -> [ 7 ]
return [super_float("".join(x))]
def exp_parse_action(x): # [ 2 ^ 3 ^ 2 ] -> 512
x = [e for e in x if type(e) == float] # Ignore ^
x.reverse()
x=reduce(lambda a,b:b**a, x)
return x
def parallel(x): # Parallel resistors [ 1 2 ] => 2/3
if len(x) == 1:
return x[0]
if 0 in x:
return float('nan')
x = [1./e for e in x if type(e) == float] # Ignore ^
return 1./sum(x)
def sum_parse_action(x): # [ 1 + 2 - 3 ] -> 0
total = 0.0
op = ops['+']
for e in x:
if e in set('+-'):
op = ops[e]
else:
total=op(total, e)
return total
def prod_parse_action(x): # [ 1 * 2 / 3 ] => 0.66
prod = 1.0
op = ops['*']
for e in x:
if e in set('*/'):
op = ops[e]
else:
prod=op(prod, e)
return prod
def func_parse_action(x):
return [functions[x[0]](x[1])]
number_suffix=reduce(lambda a,b:a|b, map(Literal,suffixes.keys()), NoMatch()) # SI suffixes and percent
(dot,minus,plus,times,div,lpar,rpar,exp)=map(Literal,".-+*/()^")
number_part=Word(nums)
inner_number = ( number_part+Optional("."+number_part) ) | ("."+number_part) # 0.33 or 7 or .34
number=Optional(minus | plus)+ inner_number + \
Optional(CaselessLiteral("E")+Optional("-")+number_part)+ \
Optional(number_suffix) # 0.33k or -17
number=number.setParseAction( number_parse_action ) # Convert to number
# Predefine recursive variables
expr = Forward()
factor = Forward()
def sreduce(f, l):
''' Same as reduce, but handle len 1 and len 0 lists sensibly '''
if len(l)==0:
return NoMatch()
if len(l)==1:
return l[0]
return reduce(f, l)
# Handle variables passed in. E.g. if we have {'R':0.5}, we make the substitution.
# Special case for no variables because of how we understand PyParsing is put together
if len(variables)>0:
varnames = sreduce(lambda x,y:x|y, map(lambda x: CaselessLiteral(x), variables.keys()))
varnames.setParseAction(lambda x:map(lambda y:variables[y], x))
else:
varnames=NoMatch()
# Same thing for functions.
if len(functions)>0:
funcnames = sreduce(lambda x,y:x|y, map(lambda x: CaselessLiteral(x), functions.keys()))
function = funcnames+lpar.suppress()+expr+rpar.suppress()
function.setParseAction(func_parse_action)
else:
function = NoMatch()
atom = number | varnames | lpar+expr+rpar | function
factor << (atom + ZeroOrMore(exp+atom)).setParseAction(exp_parse_action) # 7^6
paritem = factor + ZeroOrMore(Literal('||')+factor) # 5k || 4k
paritem=paritem.setParseAction(parallel)
term = paritem + ZeroOrMore((times|div)+paritem) # 7 * 5 / 4 - 3
term = term.setParseAction(prod_parse_action)
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':math.sin, 'cos':math.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({'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+7 QWSEKO")
from x_module import XModule import logging
from lxml import etree
import json import json
## TODO: Abstract out from Django ## TODO: Abstract out from Django
from django.conf import settings from django.conf import settings
from djangomako.shortcuts import render_to_response, render_to_string from djangomako.shortcuts import render_to_response, render_to_string
from lxml import etree
from x_module import XModule
log = logging.getLogger("mitx.courseware.modules")
class VideoModule(XModule): class VideoModule(XModule):
#id_attribute = 'youtube' #id_attribute = 'youtube'
video_time = 0 video_time = 0
def handle_ajax(self, dispatch, get): def handle_ajax(self, dispatch, get):
print "GET", get log.debug(u"GET {0}".format(get))
print "DISPATCH", dispatch log.debug(u"DISPATCH {0}".format(dispatch))
if dispatch=='goto_position': if dispatch == 'goto_position':
self.position = int(float(get['position'])) self.position = int(float(get['position']))
print "NEW POSITION", self.position log.debug(u"NEW POSITION {0}".format(self.position))
return json.dumps({'success':True}) return json.dumps({'success':True})
raise Http404() raise Http404()
def get_state(self): def get_state(self):
print "STATE POSITION", self.position log.debug(u"STATE POSITION {0}".format(self.position))
return json.dumps({ 'position':self.position }) return json.dumps({ 'position':self.position })
def get_xml_tags(): def get_xml_tags():
''' Tags in the courseware file guaranteed to correspond to the module ''' '''Tags in the courseware file guaranteed to correspond to the module'''
return "video" return "video"
def video_list(self): def video_list(self):
l=self.youtube.split(',') l = self.youtube.split(',')
l=[i.split(":") for i in l] l = [i.split(":") for i in l]
return json.dumps(dict(l)) return json.dumps(dict(l))
def get_html(self): def get_html(self):
...@@ -39,24 +42,25 @@ class VideoModule(XModule): ...@@ -39,24 +42,25 @@ class VideoModule(XModule):
'position':self.position}) 'position':self.position})
def get_init_js(self): def get_init_js(self):
''' JavaScript code to be run when problem is shown. Be aware '''JavaScript code to be run when problem is shown. Be aware
that this may happen several times on the same page that this may happen several times on the same page
(e.g. student switching tabs). Common functions should be put (e.g. student switching tabs). Common functions should be put
in the main course .js files for now. ''' in the main course .js files for now. '''
print "INIT POSITION", self.position log.debug(u"INIT POSITION {0}".format(self.position))
return render_to_string('video_init.js',{'streams':self.video_list(), return render_to_string('video_init.js',{'streams':self.video_list(),
'id':self.item_id, 'id':self.item_id,
'position':self.position}) 'position':self.position})
def get_destroy_js(self): def get_destroy_js(self):
return "videoDestroy(\""+self.item_id+"\");" return "videoDestroy(\"{0}\");".format(self.item_id)
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None, render_function = None): def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None, render_function = None):
XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function, render_function) XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function, render_function)
self.youtube = etree.XML(xml).get('youtube') self.youtube = etree.XML(xml).get('youtube')
self.position = 0 self.position = 0
if state!=None: if state != None:
state = json.loads(state) state = json.loads(state)
if 'position' in state: self.position = int(float(state['position'])) if 'position' in state:
print "POOSITION IN STATE" self.position = int(float(state['position']))
print "LOAD POSITION", self.position log.debug("POSITION IN STATE")
log.debug(u"LOAD POSITION {0}".format(self.position))
...@@ -155,7 +155,7 @@ LOGGING = { ...@@ -155,7 +155,7 @@ LOGGING = {
'stream' : sys.stderr, 'stream' : sys.stderr,
}, },
'app' : { 'app' : {
'level' : 'INFO', 'level' : 'DEBUG' if DEBUG else 'INFO',
'class' : 'logging.handlers.TimedRotatingFileHandler', 'class' : 'logging.handlers.TimedRotatingFileHandler',
'formatter' : 'standard', 'formatter' : 'standard',
'filename' : LOG_DIR + '/mitx.log', # temporary location for proof of concept 'filename' : LOG_DIR + '/mitx.log', # temporary location for proof of concept
...@@ -262,6 +262,7 @@ site.addsitedir(os.path.join(os.path.dirname(askbot.__file__), 'deps')) ...@@ -262,6 +262,7 @@ site.addsitedir(os.path.join(os.path.dirname(askbot.__file__), 'deps'))
TEMPLATE_LOADERS = TEMPLATE_LOADERS + ('askbot.skins.loaders.filesystem_load_template_source',) TEMPLATE_LOADERS = TEMPLATE_LOADERS + ('askbot.skins.loaders.filesystem_load_template_source',)
MIDDLEWARE_CLASSES = MIDDLEWARE_CLASSES + ( MIDDLEWARE_CLASSES = MIDDLEWARE_CLASSES + (
'util.middleware.ExceptionLoggingMiddleware',
'askbot.middleware.anon_user.ConnectToSessionMessagesMiddleware', 'askbot.middleware.anon_user.ConnectToSessionMessagesMiddleware',
'askbot.middleware.forum_mode.ForumModeMiddleware', 'askbot.middleware.forum_mode.ForumModeMiddleware',
'askbot.middleware.cancel.CancelActionMiddleware', 'askbot.middleware.cancel.CancelActionMiddleware',
......
...@@ -5,7 +5,7 @@ import os ...@@ -5,7 +5,7 @@ import os
from django.conf import settings from django.conf import settings
from django.http import Http404 from django.http import Http404
def index(request, page=1): def index(request, page=0):
if not request.user.is_authenticated(): if not request.user.is_authenticated():
return redirect('/') return redirect('/')
return render_to_response('staticbook.html',{'page':int(page)}) return render_to_response('staticbook.html',{'page':int(page)})
...@@ -5,10 +5,11 @@ from django.conf import settings ...@@ -5,10 +5,11 @@ from django.conf import settings
import views import views
class TrackMiddleware: class TrackMiddleware:
def process_request (self, request): def process_request(self, request):
try: try:
# We're already logging events # We're already logging events, and we don't want to capture user
if request.META['PATH_INFO'] == '/event': # names/passwords.
if request.META['PATH_INFO'] in ['/event', '/login']:
return return
event = { 'GET' : dict(request.GET), event = { 'GET' : dict(request.GET),
......
...@@ -19,7 +19,7 @@ urlpatterns = ('', ...@@ -19,7 +19,7 @@ urlpatterns = ('',
url(r'^activate/(?P<key>[^/]*)$', 'auth.views.activate_account'), url(r'^activate/(?P<key>[^/]*)$', 'auth.views.activate_account'),
url(r'^$', 'auth.views.index'), url(r'^$', 'auth.views.index'),
url(r'^password_reset/$', 'django.contrib.auth.views.password_reset', url(r'^password_reset/$', 'django.contrib.auth.views.password_reset',
dict(from_email='6002-admin@mit.edu'),name='auth_password_reset'), dict(from_email='registration@mitx.mit.edu'),name='auth_password_reset'),
url(r'^password_change/$',django.contrib.auth.views.password_change,name='auth_password_change'), url(r'^password_change/$',django.contrib.auth.views.password_change,name='auth_password_change'),
url(r'^password_change_done/$',django.contrib.auth.views.password_change_done,name='auth_password_change_done'), url(r'^password_change_done/$',django.contrib.auth.views.password_change_done,name='auth_password_change_done'),
url(r'^password_reset_confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',django.contrib.auth.views.password_reset_confirm, url(r'^password_reset_confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',django.contrib.auth.views.password_reset_confirm,
......
import logging
from django.http import HttpResponse
log = logging.getLogger("mitx")
class ExceptionLoggingMiddleware(object):
"""Just here to log unchecked exceptions that go all the way up the Django
stack"""
def process_exception(self, request, exception):
log.exception(exception)
return HttpResponse("Server Error - Please try again later.")
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