Merge branch 'master' into pmitros/dexml
This commit is contained in:
8
brew-formulas.txt
Normal file
8
brew-formulas.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
readline
|
||||||
|
sqlite
|
||||||
|
gdbm
|
||||||
|
pkg-config
|
||||||
|
gfortran
|
||||||
|
python
|
||||||
|
yuicompressor
|
||||||
|
node
|
||||||
273
create-dev-env.sh
Executable file
273
create-dev-env.sh
Executable file
@@ -0,0 +1,273 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
trap "ouch" ERR
|
||||||
|
|
||||||
|
ouch() {
|
||||||
|
printf '\E[31m'
|
||||||
|
|
||||||
|
cat<<EOL
|
||||||
|
|
||||||
|
!! ERROR !!
|
||||||
|
|
||||||
|
The last command did not complete successfully,
|
||||||
|
see $LOG for more details or trying running the
|
||||||
|
script again with the -v flag.
|
||||||
|
|
||||||
|
EOL
|
||||||
|
|
||||||
|
}
|
||||||
|
error() {
|
||||||
|
printf '\E[31m'; echo "$@"; printf '\E[0m'
|
||||||
|
}
|
||||||
|
output() {
|
||||||
|
printf '\E[36m'; echo "$@"; printf '\E[0m'
|
||||||
|
}
|
||||||
|
usage() {
|
||||||
|
cat<<EO
|
||||||
|
|
||||||
|
Usage: $PROG [-c] [-v] [-h]
|
||||||
|
|
||||||
|
-c compile scipy and numpy
|
||||||
|
-v set -x + spew
|
||||||
|
-h this
|
||||||
|
|
||||||
|
EO
|
||||||
|
info
|
||||||
|
}
|
||||||
|
|
||||||
|
info() {
|
||||||
|
|
||||||
|
cat<<EO
|
||||||
|
MITx base dir : $BASE
|
||||||
|
Python dir : $PYTHON_DIR
|
||||||
|
Ruby dir : $RUBY_DIR
|
||||||
|
Ruby ver : $RUBY_VER
|
||||||
|
|
||||||
|
EO
|
||||||
|
}
|
||||||
|
|
||||||
|
clone_repos() {
|
||||||
|
cd "$BASE"
|
||||||
|
output "Cloning mitx"
|
||||||
|
if [[ -d "$BASE/mitx" ]]; then
|
||||||
|
mv "$BASE/mitx" "${BASE}/mitx.bak.$$"
|
||||||
|
fi
|
||||||
|
git clone git@github.com:MITx/mitx.git >>$LOG
|
||||||
|
output "Cloning askbot-devel"
|
||||||
|
if [[ -d "$BASE/askbot-devel" ]]; then
|
||||||
|
mv "$BASE/askbot-devel" "${BASE}/askbot-devel.bak.$$"
|
||||||
|
fi
|
||||||
|
git clone git@github.com:MITx/askbot-devel >>$LOG
|
||||||
|
output "Cloning data"
|
||||||
|
if [[ -d "$BASE/data" ]]; then
|
||||||
|
mv "$BASE/data" "${BASE}/data.bak.$$"
|
||||||
|
fi
|
||||||
|
hg clone ssh://hg-content@gp.mitx.mit.edu/data >>$LOG
|
||||||
|
}
|
||||||
|
|
||||||
|
PROG=${0##*/}
|
||||||
|
BASE="$HOME/mitx_all"
|
||||||
|
PYTHON_DIR="$BASE/python"
|
||||||
|
RUBY_DIR="$BASE/ruby"
|
||||||
|
RUBY_VER="1.9.3"
|
||||||
|
NUMPY_VER="1.6.2"
|
||||||
|
SCIPY_VER="0.10.1"
|
||||||
|
BREW_FILE="$BASE/mitx/brew-formulas.txt"
|
||||||
|
LOG="/var/tmp/install.log"
|
||||||
|
APT_PKGS="curl git mercurial python-virtualenv build-essential python-dev gfortran liblapack-dev libfreetype6-dev libpng12-dev libxml2-dev libxslt-dev yui-compressor coffeescript"
|
||||||
|
|
||||||
|
if [[ $EUID -eq 0 ]]; then
|
||||||
|
error "This script should not be run using sudo or as the root user"
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
ARGS=$(getopt "cvh" "$*")
|
||||||
|
if [[ $? != 0 ]]; then
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
eval set -- "$ARGS"
|
||||||
|
while true; do
|
||||||
|
case $1 in
|
||||||
|
-c)
|
||||||
|
compile=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-v)
|
||||||
|
set -x
|
||||||
|
verbose=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
cat<<EO
|
||||||
|
|
||||||
|
This script will setup a local MITx environment, this
|
||||||
|
includes
|
||||||
|
|
||||||
|
* Django
|
||||||
|
* A local copy of Python and library dependencies
|
||||||
|
* A local copy of Ruby and library dependencies
|
||||||
|
|
||||||
|
It will also attempt to install operating system dependencies
|
||||||
|
with apt(debian) or brew(OSx).
|
||||||
|
|
||||||
|
To compile scipy and numpy from source use the -c option
|
||||||
|
|
||||||
|
STDOUT is redirected to /var/tmp/install.log, run
|
||||||
|
$ tail -f /var/tmp/install.log
|
||||||
|
to monitor progress
|
||||||
|
|
||||||
|
EO
|
||||||
|
info
|
||||||
|
output "Press return to begin or control-C to abort"
|
||||||
|
read dummy
|
||||||
|
|
||||||
|
if [[ -f $HOME/.rvmrc ]]; then
|
||||||
|
output "$HOME/.rvmrc alredy exists, not adding $RUBY_DIR"
|
||||||
|
else
|
||||||
|
output "Creating $HOME/.rmrc so rvm uses $RUBY_DIR"
|
||||||
|
echo "export rvm_path=$RUBY_DIR" > $HOME/.rvmrc
|
||||||
|
fi
|
||||||
|
mkdir -p $BASE
|
||||||
|
rm -f $LOG
|
||||||
|
case `uname -s` in
|
||||||
|
[Ll]inux)
|
||||||
|
command -v lsb_release &>/dev/null || {
|
||||||
|
error "Please install lsb-release."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
distro=`lsb_release -cs`
|
||||||
|
case $distro in
|
||||||
|
lisa|natty|oneiric|precise)
|
||||||
|
output "Installing ubuntu requirements"
|
||||||
|
sudo apt-get -y update
|
||||||
|
sudo apt-get -y install $APT_PKGS
|
||||||
|
clone_repos
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
error "Unsupported distribution - $distro"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
Darwin)
|
||||||
|
command -v brew &>/dev/null || {
|
||||||
|
output "Installing brew"
|
||||||
|
/usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/master/Library/Contributions/install_homebrew.rb)"
|
||||||
|
}
|
||||||
|
command -v git &>/dev/null || {
|
||||||
|
output "Installing git"
|
||||||
|
brew install git >> $LOG
|
||||||
|
}
|
||||||
|
command -v hg &>/dev/null || {
|
||||||
|
output "Installaing mercurial"
|
||||||
|
brew install mercurial >> $LOG
|
||||||
|
}
|
||||||
|
|
||||||
|
clone_repos
|
||||||
|
|
||||||
|
output "Installing OSX requirements"
|
||||||
|
if [[ ! -r $BREW_FILE ]]; then
|
||||||
|
error "$BREW_FILE does not exist, needed to install brew deps"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# brew errors if the package is already installed
|
||||||
|
for pkg in $(cat $BREW_FILE); do
|
||||||
|
grep $pkg <(brew list) &>/dev/null || {
|
||||||
|
output "Installing $pkg"
|
||||||
|
brew install $pkg >>$LOG
|
||||||
|
}
|
||||||
|
done
|
||||||
|
command -v pip &>/dev/null || {
|
||||||
|
output "Installing pip"
|
||||||
|
sudo easy_install pip >>$LOG
|
||||||
|
}
|
||||||
|
command -v virtualenv &>/dev/null || {
|
||||||
|
output "Installing virtualenv"
|
||||||
|
sudo pip install virtualenv virtualenvwrapper >> $LOG
|
||||||
|
}
|
||||||
|
command -v coffee &>/dev/null || {
|
||||||
|
output "Installing coffee script"
|
||||||
|
curl http://npmjs.org/install.sh | sh
|
||||||
|
npm install -g coffee-script
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
error "Unsupported platform"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
output "Installing rvm and ruby"
|
||||||
|
curl -sL get.rvm.io | bash -s stable
|
||||||
|
source $RUBY_DIR/scripts/rvm
|
||||||
|
rvm install $RUBY_VER
|
||||||
|
virtualenv "$PYTHON_DIR"
|
||||||
|
source $PYTHON_DIR/bin/activate
|
||||||
|
output "Installing gem bundler"
|
||||||
|
gem install bundler
|
||||||
|
output "Installing ruby packages"
|
||||||
|
# hack :(
|
||||||
|
cd $BASE/mitx || true
|
||||||
|
bundle install
|
||||||
|
|
||||||
|
cd $BASE
|
||||||
|
|
||||||
|
if [[ -n $compile ]]; then
|
||||||
|
output "Downloading numpy and scipy"
|
||||||
|
curl -sL -o numpy.tar.gz http://downloads.sourceforge.net/project/numpy/NumPy/${NUMPY_VER}/numpy-${NUMPY_VER}.tar.gz
|
||||||
|
curl -sL -o scipy.tar.gz http://downloads.sourceforge.net/project/scipy/scipy/${SCIPY_VER}/scipy-${SCIPY_VER}.tar.gz
|
||||||
|
tar xf numpy.tar.gz
|
||||||
|
tar xf scipy.tar.gz
|
||||||
|
rm -f numpy.tar.gz scipy.tar.gz
|
||||||
|
output "Compiling numpy"
|
||||||
|
cd "$BASE/numpy-${NUMPY_VER}"
|
||||||
|
python setup.py install >>$LOG 2>&1
|
||||||
|
output "Compiling scipy"
|
||||||
|
cd "$BASE/scipy-${SCIPY_VER}"
|
||||||
|
python setup.py install >>$LOG 2>&1
|
||||||
|
cd "$BASE"
|
||||||
|
rm -rf numpy-${NUMPY_VER} scipy-${SCIPY_VER}
|
||||||
|
fi
|
||||||
|
|
||||||
|
output "Installing askbot requirements"
|
||||||
|
pip install -r askbot-devel/askbot_requirements.txt >>$LOG
|
||||||
|
pip install -r askbot-devel/askbot_requirements_dev.txt >>$LOG
|
||||||
|
output "Installing MITx requirements"
|
||||||
|
pip install -r mitx/pre-requirements.txt >> $LOG
|
||||||
|
pip install -r mitx/requirements.txt >>$LOG
|
||||||
|
|
||||||
|
mkdir "$BASE/log" || true
|
||||||
|
mkdir "$BASE/db" || true
|
||||||
|
|
||||||
|
cat<<END
|
||||||
|
|
||||||
|
Success!!
|
||||||
|
|
||||||
|
To start using Django you will need
|
||||||
|
to activate the local Python and Ruby
|
||||||
|
environment:
|
||||||
|
|
||||||
|
$ source $RUBY_DIR/scripts/rvm
|
||||||
|
$ source $PYTHON_DIR/bin/activate
|
||||||
|
|
||||||
|
To initialize and start a local instance of Django:
|
||||||
|
|
||||||
|
$ cd $BASE/mitx
|
||||||
|
$ django-admin.py syncdb --settings=envs.dev --pythonpath=.
|
||||||
|
$ django-admin.py migrate --settings=envs.dev --pythonpath=.
|
||||||
|
$ django-admin.py runserver --settings=envs.dev --pythonpath=.
|
||||||
|
|
||||||
|
END
|
||||||
|
exit 0
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ class LoncapaProblem(object):
|
|||||||
self.problem_id = id
|
self.problem_id = id
|
||||||
self.system = system
|
self.system = system
|
||||||
|
|
||||||
if seed != None:
|
if seed is not None:
|
||||||
self.seed = seed
|
self.seed = seed
|
||||||
|
|
||||||
if state:
|
if state:
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ class SimpleInput():# XModule
|
|||||||
|
|
||||||
|
|
||||||
def register_render_function(fn, names=None, cls=SimpleInput):
|
def register_render_function(fn, names=None, cls=SimpleInput):
|
||||||
if names == None:
|
if names is None:
|
||||||
SimpleInput.xml_tags[fn.__name__] = fn
|
SimpleInput.xml_tags[fn.__name__] = fn
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ class MultipleChoiceResponse(GenericResponse):
|
|||||||
if rtype not in ["MultipleChoice"]:
|
if rtype not in ["MultipleChoice"]:
|
||||||
response.set("type", "MultipleChoice") # force choicegroup to be MultipleChoice if not valid
|
response.set("type", "MultipleChoice") # force choicegroup to be MultipleChoice if not valid
|
||||||
for choice in list(response):
|
for choice in list(response):
|
||||||
if choice.get("name") == None:
|
if choice.get("name") is None:
|
||||||
choice.set("name", "choice_"+str(i))
|
choice.set("name", "choice_"+str(i))
|
||||||
i+=1
|
i+=1
|
||||||
else:
|
else:
|
||||||
@@ -121,7 +121,7 @@ class TrueFalseResponse(MultipleChoiceResponse):
|
|||||||
for response in self.xml.xpath("choicegroup"):
|
for response in self.xml.xpath("choicegroup"):
|
||||||
response.set("type", "TrueFalse")
|
response.set("type", "TrueFalse")
|
||||||
for choice in list(response):
|
for choice in list(response):
|
||||||
if choice.get("name") == None:
|
if choice.get("name") is None:
|
||||||
choice.set("name", "choice_"+str(i))
|
choice.set("name", "choice_"+str(i))
|
||||||
i+=1
|
i+=1
|
||||||
else:
|
else:
|
||||||
@@ -292,7 +292,7 @@ def sympy_check2():
|
|||||||
self.code = ''
|
self.code = ''
|
||||||
else:
|
else:
|
||||||
answer_src = answer.get('src')
|
answer_src = answer.get('src')
|
||||||
if answer_src != None:
|
if answer_src is not None:
|
||||||
self.code = open(settings.DATA_DIR+'src/'+answer_src).read()
|
self.code = open(settings.DATA_DIR+'src/'+answer_src).read()
|
||||||
else:
|
else:
|
||||||
self.code = answer.text
|
self.code = answer.text
|
||||||
@@ -418,7 +418,7 @@ class ExternalResponse(GenericResponse):
|
|||||||
id=xml.get('id'))[0]
|
id=xml.get('id'))[0]
|
||||||
|
|
||||||
answer_src = answer.get('src')
|
answer_src = answer.get('src')
|
||||||
if answer_src != None:
|
if answer_src is not None:
|
||||||
self.code = open(settings.DATA_DIR+'src/'+answer_src).read()
|
self.code = open(settings.DATA_DIR+'src/'+answer_src).read()
|
||||||
else:
|
else:
|
||||||
self.code = answer.text
|
self.code = answer.text
|
||||||
@@ -489,7 +489,7 @@ class FormulaResponse(GenericResponse):
|
|||||||
|
|
||||||
self.context = context
|
self.context = context
|
||||||
ts = xml.get('type')
|
ts = xml.get('type')
|
||||||
if ts == None:
|
if ts is None:
|
||||||
typeslist = []
|
typeslist = []
|
||||||
else:
|
else:
|
||||||
typeslist = ts.split(',')
|
typeslist = ts.split(',')
|
||||||
@@ -558,7 +558,7 @@ class SchematicResponse(GenericResponse):
|
|||||||
answer = xml.xpath('//*[@id=$id]//answer',
|
answer = xml.xpath('//*[@id=$id]//answer',
|
||||||
id=xml.get('id'))[0]
|
id=xml.get('id'))[0]
|
||||||
answer_src = answer.get('src')
|
answer_src = answer.get('src')
|
||||||
if answer_src != None:
|
if answer_src is not None:
|
||||||
self.code = self.system.filestore.open('src/'+answer_src).read() # Untested; never used
|
self.code = self.system.filestore.open('src/'+answer_src).read() # Untested; never used
|
||||||
else:
|
else:
|
||||||
self.code = answer.text
|
self.code = answer.text
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ def propogate_downward_tag(element, attribute_name, parent_attribute = None):
|
|||||||
child (A) already has that attribute, A will keep the same attribute and
|
child (A) already has that attribute, A will keep the same attribute and
|
||||||
all of A's children will inherit A's attribute. This is a recursive call.'''
|
all of A's children will inherit A's attribute. This is a recursive call.'''
|
||||||
|
|
||||||
if (parent_attribute == None): #This is the entry call. Select all elements with this attribute
|
if (parent_attribute is None): #This is the entry call. Select all elements with this attribute
|
||||||
all_attributed_elements = element.xpath("//*[@" + attribute_name +"]")
|
all_attributed_elements = element.xpath("//*[@" + attribute_name +"]")
|
||||||
for attributed_element in all_attributed_elements:
|
for attributed_element in all_attributed_elements:
|
||||||
attribute_value = attributed_element.get(attribute_name)
|
attribute_value = attributed_element.get(attribute_name)
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ def get_score(user, problem, cache, coursename=None):
|
|||||||
correct=float(response.grade)
|
correct=float(response.grade)
|
||||||
|
|
||||||
# Grab max grade from cache, or if it doesn't exist, compute and save to DB
|
# Grab max grade from cache, or if it doesn't exist, compute and save to DB
|
||||||
if id in cache and response.max_grade != None:
|
if id in cache and response.max_grade is not None:
|
||||||
total = response.max_grade
|
total = response.max_grade
|
||||||
else:
|
else:
|
||||||
## HACK 1: We shouldn't specifically reference capa_module
|
## HACK 1: We shouldn't specifically reference capa_module
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ def grade_histogram(module_id):
|
|||||||
|
|
||||||
grades = list(cursor.fetchall())
|
grades = list(cursor.fetchall())
|
||||||
grades.sort(key=lambda x:x[0]) # Probably not necessary
|
grades.sort(key=lambda x:x[0]) # Probably not necessary
|
||||||
if (len(grades) == 1 and grades[0][0] == None):
|
if (len(grades) == 1 and grades[0][0] is None):
|
||||||
return []
|
return []
|
||||||
return grades
|
return grades
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class Module(XModule):
|
|||||||
reset_button = False
|
reset_button = False
|
||||||
|
|
||||||
# We don't need a "save" button if infinite number of attempts and non-randomized
|
# We don't need a "save" button if infinite number of attempts and non-randomized
|
||||||
if self.max_attempts == None and self.rerandomize != "always":
|
if self.max_attempts is None and self.rerandomize != "always":
|
||||||
save_button = False
|
save_button = False
|
||||||
|
|
||||||
# Check if explanation is available, and if so, give a link
|
# Check if explanation is available, and if so, give a link
|
||||||
@@ -225,7 +225,7 @@ class Module(XModule):
|
|||||||
''' Is the student still allowed to submit answers? '''
|
''' Is the student still allowed to submit answers? '''
|
||||||
if self.attempts == self.max_attempts:
|
if self.attempts == self.max_attempts:
|
||||||
return True
|
return True
|
||||||
if self.close_date != None and datetime.datetime.utcnow() > self.close_date:
|
if self.close_date is not None and datetime.datetime.utcnow() > self.close_date:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class Module(XModule):
|
|||||||
## Returns a set of all types of all sub-children
|
## Returns a set of all types of all sub-children
|
||||||
child_classes = [set([i.tag for i in e.iter()]) for e in self.xmltree]
|
child_classes = [set([i.tag for i in e.iter()]) for e in self.xmltree]
|
||||||
|
|
||||||
titles = ["\n".join([i.get("name").strip() for i in e.iter() if i.get("name") != None]) \
|
titles = ["\n".join([i.get("name").strip() for i in e.iter() if i.get("name") is not None]) \
|
||||||
for e in self.xmltree]
|
for e in self.xmltree]
|
||||||
|
|
||||||
self.contents = self.rendered_children()
|
self.contents = self.rendered_children()
|
||||||
@@ -86,7 +86,7 @@ class Module(XModule):
|
|||||||
|
|
||||||
self.position = 1
|
self.position = 1
|
||||||
|
|
||||||
if state != None:
|
if state is not None:
|
||||||
state = json.loads(state)
|
state = json.loads(state)
|
||||||
if 'position' in state: self.position = int(state['position'])
|
if 'position' in state: self.position = int(state['position'])
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class Module(XModule):
|
|||||||
self.youtube = xmltree.get('youtube')
|
self.youtube = xmltree.get('youtube')
|
||||||
self.name = xmltree.get('name')
|
self.name = xmltree.get('name')
|
||||||
self.position = 0
|
self.position = 0
|
||||||
if state != None:
|
if state is not None:
|
||||||
state = json.loads(state)
|
state = json.loads(state)
|
||||||
if 'position' in state:
|
if 'position' in state:
|
||||||
self.position = int(float(state['position']))
|
self.position = int(float(state['position']))
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ def profile(request, student_id = None):
|
|||||||
''' User profile. Show username, location, etc, as well as grades .
|
''' User profile. Show username, location, etc, as well as grades .
|
||||||
We need to allow the user to change some of these settings .'''
|
We need to allow the user to change some of these settings .'''
|
||||||
|
|
||||||
if student_id == None:
|
if student_id is None:
|
||||||
student = request.user
|
student = request.user
|
||||||
else:
|
else:
|
||||||
if 'course_admin' not in content_parser.user_groups(request.user):
|
if 'course_admin' not in content_parser.user_groups(request.user):
|
||||||
@@ -194,7 +194,7 @@ def index(request, course=None, chapter="Using the System", section="Hints"):
|
|||||||
else:
|
else:
|
||||||
module_wrapper = dom_module[0]
|
module_wrapper = dom_module[0]
|
||||||
|
|
||||||
if module_wrapper == None:
|
if module_wrapper is None:
|
||||||
module = None
|
module = None
|
||||||
elif module_wrapper.get("src"):
|
elif module_wrapper.get("src"):
|
||||||
module = content_parser.section_file(user=user, section=module_wrapper.get("src"), coursename=course)
|
module = content_parser.section_file(user=user, section=module_wrapper.get("src"), coursename=course)
|
||||||
@@ -202,7 +202,7 @@ def index(request, course=None, chapter="Using the System", section="Hints"):
|
|||||||
module = etree.XML(etree.tostring(module_wrapper[0])) # Copy the element out of the tree
|
module = etree.XML(etree.tostring(module_wrapper[0])) # Copy the element out of the tree
|
||||||
|
|
||||||
module_ids = []
|
module_ids = []
|
||||||
if module:
|
if module is not None:
|
||||||
module_ids = module.xpath("//@id",
|
module_ids = module.xpath("//@id",
|
||||||
course=course, chapter=chapter, section=section)
|
course=course, chapter=chapter, section=section)
|
||||||
|
|
||||||
|
|||||||
@@ -482,7 +482,7 @@ def check_permissions(request, article, check_read=False, check_write=False, che
|
|||||||
|
|
||||||
locked_err = check_locked and article.locked
|
locked_err = check_locked and article.locked
|
||||||
|
|
||||||
if revision == None:
|
if revision is None:
|
||||||
revision = article.current_revision
|
revision = article.current_revision
|
||||||
deleted_err = check_deleted and not (revision.deleted == 0)
|
deleted_err = check_deleted and not (revision.deleted == 0)
|
||||||
if (request.user.is_superuser):
|
if (request.user.is_superuser):
|
||||||
|
|||||||
78
install.txt
Normal file
78
install.txt
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
This document describes how to set up the MITx development environment
|
||||||
|
for both Linux (Ubuntu) and MacOS (OSX Lion).
|
||||||
|
|
||||||
|
There is also a script "create-dev-env.sh" that automates these steps.
|
||||||
|
|
||||||
|
1) Make an mitx_all directory and clone the repos
|
||||||
|
(download and install git and mercurial if you don't have them already)
|
||||||
|
|
||||||
|
mkdir ~/mitx_all
|
||||||
|
cd ~/mitx_all
|
||||||
|
git clone git@github.com:MITx/mitx.git
|
||||||
|
git clone git@github.com:MITx/askbot-devel
|
||||||
|
hg clone ssh://hg-content@gp.mitx.mit.edu/data
|
||||||
|
|
||||||
|
2) Install OSX dependencies (Mac users only)
|
||||||
|
|
||||||
|
a) Install the brew utility if necessary
|
||||||
|
/usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/master/Library/Contributions/install_homebrew.rb)"
|
||||||
|
|
||||||
|
b) Install the brew package list
|
||||||
|
cat ~/mitx_all/mitx/brew-formulas.txt | xargs brew install
|
||||||
|
|
||||||
|
c) Install python pip if necessary
|
||||||
|
sudo easy_install pip
|
||||||
|
|
||||||
|
d) Install python virtualenv if necessary
|
||||||
|
sudo pip install virtualenv virtualenvwrapper
|
||||||
|
|
||||||
|
e) Install coffee script
|
||||||
|
curl http://npmjs.org/install.sh | sh
|
||||||
|
npm install -g coffee-script
|
||||||
|
|
||||||
|
3) Install Ubuntu dependencies (Linux users only)
|
||||||
|
|
||||||
|
sudo apt-get install curl python-virtualenv build-essential python-dev gfortran liblapack-dev libfreetype6-dev libpng12-dev libxml2-dev libxslt-dev yui-compressor coffeescript
|
||||||
|
|
||||||
|
|
||||||
|
4) Install rvm, ruby, and libraries
|
||||||
|
|
||||||
|
echo "export rvm_path=$HOME/mitx_all/ruby" > $HOME/.rvmrc
|
||||||
|
curl -sL get.rvm.io | bash -s stable
|
||||||
|
source ~/mitx_all/ruby/scripts/rvm
|
||||||
|
rvm install 1.9.3
|
||||||
|
gem install bundler
|
||||||
|
cd ~/mitx_all/mitx
|
||||||
|
bundle install
|
||||||
|
|
||||||
|
5) Install python libraries
|
||||||
|
|
||||||
|
source ~/mitx_all/python/bin/activate
|
||||||
|
cd ~/mitx_all
|
||||||
|
pip install -r askbot-devel/askbot_requirements.txt
|
||||||
|
pip install -r askbot-devel/askbot_requirements_dev.txt
|
||||||
|
pip install -r mitx/pre-requirements.txt
|
||||||
|
pip install -r mitx/requirements.txt
|
||||||
|
|
||||||
|
6) Create log and db dirs
|
||||||
|
|
||||||
|
mkdir ~/mitx_all/log
|
||||||
|
mkdir ~/mitx_all/db
|
||||||
|
|
||||||
|
7) Start the dev server
|
||||||
|
|
||||||
|
To start using Django you will need
|
||||||
|
to activate the local Python and Ruby
|
||||||
|
environment:
|
||||||
|
|
||||||
|
$ source ~/mitx_all/ruby/scripts/rvm
|
||||||
|
$ source ~/mitx_all/python/bin/activate
|
||||||
|
|
||||||
|
To initialize and start a local instance of Django:
|
||||||
|
|
||||||
|
$ cd ~/mitx_all/mitx
|
||||||
|
$ django-admin.py syncdb --settings=envs.dev --pythonpath=.
|
||||||
|
$ django-admin.py migrate --settings=envs.dev --pythonpath=.
|
||||||
|
$ django-admin.py runserver --settings=envs.dev --pythonpath=.
|
||||||
|
|
||||||
|
|
||||||
@@ -126,6 +126,14 @@ describe 'VideoPlayer', ->
|
|||||||
it 'trigger pause event', ->
|
it 'trigger pause event', ->
|
||||||
expect('pause').toHaveBeenTriggeredOn @player
|
expect('pause').toHaveBeenTriggeredOn @player
|
||||||
|
|
||||||
|
describe 'when the video is unstarted', ->
|
||||||
|
beforeEach ->
|
||||||
|
spyOnEvent @player, 'pause'
|
||||||
|
@player.onStateChange data: YT.PlayerState.UNSTARTED
|
||||||
|
|
||||||
|
it 'trigger pause event', ->
|
||||||
|
expect('pause').toHaveBeenTriggeredOn @player
|
||||||
|
|
||||||
describe 'when the video is ended', ->
|
describe 'when the video is ended', ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
spyOnEvent @player, 'ended'
|
spyOnEvent @player, 'ended'
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ $ ->
|
|||||||
window.onTouchBasedDevice = ->
|
window.onTouchBasedDevice = ->
|
||||||
navigator.userAgent.match /iPhone|iPod|iPad/i
|
navigator.userAgent.match /iPhone|iPod|iPad/i
|
||||||
|
|
||||||
|
$('body').addClass 'touch-based-device' if onTouchBasedDevice()
|
||||||
|
|
||||||
$("a[rel*=leanModal]").leanModal()
|
$("a[rel*=leanModal]").leanModal()
|
||||||
$('#csrfmiddlewaretoken').attr 'value', $.cookie('csrftoken')
|
$('#csrfmiddlewaretoken').attr 'value', $.cookie('csrftoken')
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
class @VideoPlayer
|
class @VideoPlayer
|
||||||
constructor: (@video) ->
|
constructor: (@video) ->
|
||||||
|
# Define a missing constant of Youtube API
|
||||||
|
YT.PlayerState.UNSTARTED = -1
|
||||||
|
|
||||||
@currentTime = 0
|
@currentTime = 0
|
||||||
@element = $("#video_#{@video.id}")
|
@element = $("#video_#{@video.id}")
|
||||||
@render()
|
@render()
|
||||||
@@ -57,7 +60,7 @@ class @VideoPlayer
|
|||||||
switch event.data
|
switch event.data
|
||||||
when YT.PlayerState.PLAYING
|
when YT.PlayerState.PLAYING
|
||||||
$(@).trigger('play')
|
$(@).trigger('play')
|
||||||
when YT.PlayerState.PAUSED
|
when YT.PlayerState.PAUSED, YT.PlayerState.UNSTARTED
|
||||||
$(@).trigger('pause')
|
$(@).trigger('pause')
|
||||||
when YT.PlayerState.ENDED
|
when YT.PlayerState.ENDED
|
||||||
$(@).trigger('ended')
|
$(@).trigger('ended')
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ class @VideoSpeedControl
|
|||||||
$(@player).bind('speedChange', @onSpeedChange)
|
$(@player).bind('speedChange', @onSpeedChange)
|
||||||
@$('.video_speeds a').click @changeVideoSpeed
|
@$('.video_speeds a').click @changeVideoSpeed
|
||||||
if onTouchBasedDevice()
|
if onTouchBasedDevice()
|
||||||
@$('.speeds').click -> $(this).toggleClass('open')
|
@$('.speeds').click (event) ->
|
||||||
|
event.preventDefault()
|
||||||
|
$(this).toggleClass('open')
|
||||||
else
|
else
|
||||||
@$('.speeds').mouseenter ->
|
@$('.speeds').mouseenter ->
|
||||||
$(this).addClass('open')
|
$(this).addClass('open')
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ nav.sequence-nav {
|
|||||||
background-position: center;
|
background-position: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
background: #333;
|
background: #333;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
display: none;
|
display: none;
|
||||||
@@ -231,6 +231,10 @@ nav.sequence-nav {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.touch-based-device & ol li a:hover p {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -304,3 +308,4 @@ section.course-content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
% if name is not UNDEFINED and name != None:
|
% if name is not UNDEFINED and name is not None:
|
||||||
<h1> ${name} </h1>
|
<h1> ${name} </h1>
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user