From ca5c33cdf3d6bfca61d7ffddfcfa0d22c6c9ce6d Mon Sep 17 00:00:00 2001 From: JM Van Thong Date: Wed, 31 Oct 2012 13:46:27 -0400 Subject: [PATCH 01/29] Fixed install by adding mysql --- brew-formulas.txt | 1 + create-dev-env.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/brew-formulas.txt b/brew-formulas.txt index 0aed9645d0..b5b555e2a0 100644 --- a/brew-formulas.txt +++ b/brew-formulas.txt @@ -7,3 +7,4 @@ python yuicompressor node graphviz +mysql diff --git a/create-dev-env.sh b/create-dev-env.sh index 5691315039..656a40524e 100755 --- a/create-dev-env.sh +++ b/create-dev-env.sh @@ -105,7 +105,7 @@ NUMPY_VER="1.6.2" SCIPY_VER="0.10.1" BREW_FILE="$BASE/mitx/brew-formulas.txt" LOG="/var/tmp/install-$(date +%Y%m%d-%H%M%S).log" -APT_PKGS="pkg-config curl git python-virtualenv build-essential python-dev gfortran liblapack-dev libfreetype6-dev libpng12-dev libxml2-dev libxslt-dev yui-compressor coffeescript graphviz graphviz-dev" +APT_PKGS="pkg-config curl git python-virtualenv build-essential python-dev gfortran liblapack-dev libfreetype6-dev libpng12-dev libxml2-dev libxslt-dev yui-compressor coffeescript graphviz graphviz-dev mysql" if [[ $EUID -eq 0 ]]; then error "This script should not be run using sudo or as the root user" From 9cb2fbdd2fad6a553342776a535d1bd74aea6197 Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Wed, 31 Oct 2012 16:26:11 -0400 Subject: [PATCH 02/29] Remove newline from javascript source tags --- common/djangoapps/pipeline_mako/templates/static_content.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/djangoapps/pipeline_mako/templates/static_content.html b/common/djangoapps/pipeline_mako/templates/static_content.html index c153da22fe..302d4d7aa5 100644 --- a/common/djangoapps/pipeline_mako/templates/static_content.html +++ b/common/djangoapps/pipeline_mako/templates/static_content.html @@ -3,8 +3,7 @@ from staticfiles.storage import staticfiles_storage from pipeline_mako import compressed_css, compressed_js %> -<%def name='url(file)'> -<% +<%def name='url(file)'><% try: url = staticfiles_storage.url(file) except: From 6bbe82b697e30fb8852e87db15afa6711a4c7679 Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Wed, 31 Oct 2012 17:05:46 -0400 Subject: [PATCH 03/29] Make work w/ ie8. Still complains that HTMLCanvasElement is undefined but doesn't try to manipulate it. --- common/lib/xmodule/xmodule/js/src/capa/schematic.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/lib/xmodule/xmodule/js/src/capa/schematic.js b/common/lib/xmodule/xmodule/js/src/capa/schematic.js index b01f6e12e8..8fb6769342 100644 --- a/common/lib/xmodule/xmodule/js/src/capa/schematic.js +++ b/common/lib/xmodule/xmodule/js/src/capa/schematic.js @@ -1995,7 +1995,7 @@ cktsim = (function() { // set up each schematic entry widget function update_schematics() { // set up each schematic on the page - var schematics = document.getElementsByClassName('schematic'); + var schematics = $('.schematic'); for (var i = 0; i < schematics.length; ++i) if (schematics[i].getAttribute("loaded") != "true") { try { @@ -2036,7 +2036,7 @@ function add_schematic_handler(other_onload) { // ask each schematic input widget to update its value field for submission function prepare_schematics() { - var schematics = document.getElementsByClassName('schematic'); + var schematics = $('.schematic'); for (var i = schematics.length - 1; i >= 0; i--) schematics[i].schematic.update_value(); } @@ -3339,7 +3339,7 @@ schematic = (function() { } // add method to canvas to compute relative coords for event - HTMLCanvasElement.prototype.relMouseCoords = function(event){ + if (HTMLCanvasElement) HTMLCanvasElement.prototype.relMouseCoords = function(event){ // run up the DOM tree to figure out coords for top,left of canvas var totalOffsetX = 0; var totalOffsetY = 0; @@ -3718,7 +3718,7 @@ schematic = (function() { // look for property input fields in the content and give // them a keypress listener that interprets ENTER as // clicking OK. - var plist = content.getElementsByClassName('property'); + var plist = $(content).find('.property'); for (var i = plist.length - 1; i >= 0; --i) { var field = plist[i]; field.dialog = dialog; // help event handler find us... From 2b5e55b6623af972b7b403a4e82d6771759ce2c8 Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Wed, 31 Oct 2012 17:29:19 -0400 Subject: [PATCH 04/29] Use try/catch to detect undefined globals for canvas --- .../xmodule/xmodule/js/src/capa/schematic.js | 127 ++++++++++-------- 1 file changed, 68 insertions(+), 59 deletions(-) diff --git a/common/lib/xmodule/xmodule/js/src/capa/schematic.js b/common/lib/xmodule/xmodule/js/src/capa/schematic.js index 8fb6769342..d2602d8ac3 100644 --- a/common/lib/xmodule/xmodule/js/src/capa/schematic.js +++ b/common/lib/xmodule/xmodule/js/src/capa/schematic.js @@ -3339,23 +3339,28 @@ schematic = (function() { } // add method to canvas to compute relative coords for event - if (HTMLCanvasElement) HTMLCanvasElement.prototype.relMouseCoords = function(event){ - // run up the DOM tree to figure out coords for top,left of canvas - var totalOffsetX = 0; - var totalOffsetY = 0; - var currentElement = this; - do { - totalOffsetX += currentElement.offsetLeft; - totalOffsetY += currentElement.offsetTop; - } - while (currentElement = currentElement.offsetParent); - - // now compute relative position of click within the canvas - this.mouse_x = event.pageX - totalOffsetX; - this.mouse_y = event.pageY - totalOffsetY; - - this.page_x = event.pageX; - this.page_y = event.pageY; + try { + if (HTMLCanvasElement) + HTMLCanvasElement.prototype.relMouseCoords = function(event){ + // run up the DOM tree to figure out coords for top,left of canvas + var totalOffsetX = 0; + var totalOffsetY = 0; + var currentElement = this; + do { + totalOffsetX += currentElement.offsetLeft; + totalOffsetY += currentElement.offsetTop; + } + while (currentElement = currentElement.offsetParent); + + // now compute relative position of click within the canvas + this.mouse_x = event.pageX - totalOffsetX; + this.mouse_y = event.pageY - totalOffsetY; + + this.page_x = event.pageX; + this.page_y = event.pageY; + } + } + catch (err) { // ignore } /////////////////////////////////////////////////////////////////////////////// @@ -4091,48 +4096,52 @@ schematic = (function() { // add dashed lines! // from http://davidowens.wordpress.com/2010/09/07/html-5-canvas-and-dashed-lines/ - CanvasRenderingContext2D.prototype.dashedLineTo = function(fromX, fromY, toX, toY, pattern) { - // Our growth rate for our line can be one of the following: - // (+,+), (+,-), (-,+), (-,-) - // Because of this, our algorithm needs to understand if the x-coord and - // y-coord should be getting smaller or larger and properly cap the values - // based on (x,y). - var lt = function (a, b) { return a <= b; }; - var gt = function (a, b) { return a >= b; }; - var capmin = function (a, b) { return Math.min(a, b); }; - var capmax = function (a, b) { return Math.max(a, b); }; - - var checkX = { thereYet: gt, cap: capmin }; - var checkY = { thereYet: gt, cap: capmin }; - - if (fromY - toY > 0) { - checkY.thereYet = lt; - checkY.cap = capmax; - } - if (fromX - toX > 0) { - checkX.thereYet = lt; - checkX.cap = capmax; - } - - this.moveTo(fromX, fromY); - var offsetX = fromX; - var offsetY = fromY; - var idx = 0, dash = true; - while (!(checkX.thereYet(offsetX, toX) && checkY.thereYet(offsetY, toY))) { - var ang = Math.atan2(toY - fromY, toX - fromX); - var len = pattern[idx]; - - offsetX = checkX.cap(toX, offsetX + (Math.cos(ang) * len)); - offsetY = checkY.cap(toY, offsetY + (Math.sin(ang) * len)); - - if (dash) this.lineTo(offsetX, offsetY); - else this.moveTo(offsetX, offsetY); - - idx = (idx + 1) % pattern.length; - dash = !dash; - } - }; - + try { + if (CanvasRenderingContext2D) + CanvasRenderingContext2D.prototype.dashedLineTo = function(fromX, fromY, toX, toY, pattern) { + // Our growth rate for our line can be one of the following: + // (+,+), (+,-), (-,+), (-,-) + // Because of this, our algorithm needs to understand if the x-coord and + // y-coord should be getting smaller or larger and properly cap the values + // based on (x,y). + var lt = function (a, b) { return a <= b; }; + var gt = function (a, b) { return a >= b; }; + var capmin = function (a, b) { return Math.min(a, b); }; + var capmax = function (a, b) { return Math.max(a, b); }; + + var checkX = { thereYet: gt, cap: capmin }; + var checkY = { thereYet: gt, cap: capmin }; + + if (fromY - toY > 0) { + checkY.thereYet = lt; + checkY.cap = capmax; + } + if (fromX - toX > 0) { + checkX.thereYet = lt; + checkX.cap = capmax; + } + + this.moveTo(fromX, fromY); + var offsetX = fromX; + var offsetY = fromY; + var idx = 0, dash = true; + while (!(checkX.thereYet(offsetX, toX) && checkY.thereYet(offsetY, toY))) { + var ang = Math.atan2(toY - fromY, toX - fromX); + var len = pattern[idx]; + + offsetX = checkX.cap(toX, offsetX + (Math.cos(ang) * len)); + offsetY = checkY.cap(toY, offsetY + (Math.sin(ang) * len)); + + if (dash) this.lineTo(offsetX, offsetY); + else this.moveTo(offsetX, offsetY); + + idx = (idx + 1) % pattern.length; + dash = !dash; + } + }; + } + catch (err) { //noop + } // given a range of values, return a new range [vmin',vmax'] where the limits // have been chosen "nicely". Taken from matplotlib.ticker.LinearLocator function view_limits(vmin,vmax) { From 74e23546af9dcad10d162e9491862b78f5310efe Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Wed, 31 Oct 2012 18:40:10 -0400 Subject: [PATCH 05/29] More inputtype refactor - add an Attribute class - input types just need to declare which attributes they want, and how to transform and validate them, and the base class will do all the rest. - change OptionInput to new format. --- common/lib/capa/capa/inputtypes.py | 156 +++++++++++++++++++++++------ 1 file changed, 124 insertions(+), 32 deletions(-) diff --git a/common/lib/capa/capa/inputtypes.py b/common/lib/capa/capa/inputtypes.py index de29b5e664..f154569fe4 100644 --- a/common/lib/capa/capa/inputtypes.py +++ b/common/lib/capa/capa/inputtypes.py @@ -32,8 +32,7 @@ graded status as'status' # makes sense, but a bunch of problems have markup that assumes block. Bigger TODO: figure out a # general css and layout strategy for capa, document it, then implement it. - - +from collections import namedtuple import json import logging from lxml import etree @@ -50,6 +49,58 @@ log = logging.getLogger('mitx.' + __name__) registry = TagRegistry() +class Attribute(object): + """ + Allows specifying required and optional attributes for input types. + """ + + # want to allow default to be None, but also allow required objects + _sentinel = object() + + def __init__(self, name, default=_sentinel, transform=None, validate=None): + """ + Define an attribute + + name (str): then name of the attribute--should be alphanumeric (valid for an XML attribute) + + default (any type): If not specified, this attribute is required. If specified, use this as the default value + if the attribute is not specified. Note that this value will not be transformed or validated. + + transform (function str -> any type): If not None, will be called to transform the parsed value into an internal + representation. + + validate (function str-or-return-type-of-tranform -> unit or exception): If not None, called to validate the + (possibly transformed) value of the attribute. Should raise ValueError with a helpful message if + the value is invalid. + """ + self.name = name + self.default = default + self.validate = validate + self.transform = transform + + def parse_from_xml(self, element): + """ + Given an etree xml element that should have this attribute, do the obvious thing: + - look for it. raise ValueError if not found and required. + - transform and validate. pass through any exceptions from transform or validate. + """ + val = element.get(self.name) + if self.default == self._sentinel and val is None: + raise ValueError('Missing required attribute {0}.'.format(self.name)) + + if val is None: + # not required, so return default + return self.default + + if self.transform is not None: + val = self.transform(val) + + if self.validate is not None: + self.validate(val) + + return val + + class InputTypeBase(object): """ Abstract base class for input types. @@ -102,9 +153,12 @@ class InputTypeBase(object): self.status = state.get('status', 'unanswered') - # Call subclass "constructor" -- means they don't have to worry about calling - # super().__init__, and are isolated from changes to the input constructor interface. try: + # Pre-parse and propcess all the declared requirements. + self.process_requirements() + + # Call subclass "constructor" -- means they don't have to worry about calling + # super().__init__, and are isolated from changes to the input constructor interface. self.setup() except Exception as err: # Something went wrong: add xml to message, but keep the traceback @@ -112,6 +166,32 @@ class InputTypeBase(object): raise Exception, msg, sys.exc_info()[2] + @classmethod + def get_attributes(cls): + """ + Should return a list of Attribute objects (see docstring there for details). Subclasses should override. e.g. + + return super(MyClass, cls).attributes + [Attribute('unicorn', True), + Attribute('num_dragons', 12, transform=int), ...] + """ + return [] + + + def process_requirements(self): + """ + Subclasses can declare lists of required and optional attributes. This + function parses the input xml and pulls out those attributes. This + isolates most simple input types from needing to deal with xml parsing at all. + + Processes attributes, putting the results in the self.loaded_attributes dictionary. + """ + # Use a local dict so that if there are exceptions, we don't end up in a partially-initialized state. + d = {} + for a in self.get_attributes(): + d[a.name] = a.parse_from_xml(self.xml) + + self.loaded_attributes = d + def setup(self): """ InputTypes should override this to do any needed initialization. It is called after the @@ -122,14 +202,28 @@ class InputTypeBase(object): """ pass + def _get_render_context(self): """ - Abstract method. Subclasses should implement to return the dictionary - of keys needed to render their template. + Should return a dictionary of keys needed to render the template for the input type. (Separate from get_html to faciliate testing of logic separately from the rendering) + + The default implementation gets the following rendering context: basic things like value, id, + status, and msg, as well as everything in self.loaded_attributes. + + This means that input types that only parse attributes get everything they need, and don't need + to override this method. """ - raise NotImplementedError + context = { + 'id': self.id, + 'value': self.value, + 'status': self.status, + 'msg': self.msg, + } + context.update(self.loaded_attributes) + return context + def get_html(self): """ @@ -139,7 +233,10 @@ class InputTypeBase(object): raise NotImplementedError("no rendering template specified for class {0}" .format(self.__class__)) - html = self.system.render_template(self.template, self._get_render_context()) + context = self._default_render_context() + context.update(self._get_render_context()) + + html = self.system.render_template(self.template, context) return etree.XML(html) @@ -158,33 +255,28 @@ class OptionInput(InputTypeBase): template = "optioninput.html" tags = ['optioninput'] - def setup(self): - # Extract the options... - options = self.xml.get('options') - if not options: - raise ValueError("optioninput: Missing 'options' specification.") + @classmethod + def get_attributes(cls): + """ + Convert options to a convenient format. + """ - # parse the set of possible options - oset = shlex.shlex(options[1:-1]) - oset.quotes = "'" - oset.whitespace = "," - oset = [x[1:-1] for x in list(oset)] + def parse_options(options): + """Given options string, convert it into an ordered list of (option, option) tuples + (Why? I don't know--that's what the template uses at the moment) + """ + # parse the set of possible options + oset = shlex.shlex(options[1:-1]) + oset.quotes = "'" + oset.whitespace = "," + oset = [x[1:-1] for x in list(oset)] - # make ordered list with (key, value) same - self.osetdict = [(oset[x], oset[x]) for x in range(len(oset))] - # TODO: allow ordering to be randomized + # make ordered list with (key, value) same + return [(oset[x], oset[x]) for x in range(len(oset))] - def _get_render_context(self): - - context = { - 'id': self.id, - 'value': self.value, - 'status': self.status, - 'msg': self.msg, - 'options': self.osetdict, - 'inline': self.xml.get('inline',''), - } - return context + return super(OptionInput, cls).get_attributes() + [ + Attribute('options', transform=parse_options), + Attribute('inline', '')] registry.register(OptionInput) From 7fcf02a0cc91e12e3889844e233c9b4b0ff26b8b Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Wed, 31 Oct 2012 23:40:19 -0400 Subject: [PATCH 06/29] Further refactor - small Attribute and InputTypeBase interface changes to make things cleaner - move html quoting into templates (use ${blah | h} syntax) - converting input types to use new format. --- common/lib/capa/capa/inputtypes.py | 230 +++++++++--------- .../capa/capa/templates/filesubmission.html | 2 +- .../capa/capa/templates/javascriptinput.html | 2 +- common/lib/capa/capa/templates/textline.html | 2 +- common/lib/capa/capa/tests/test_inputtypes.py | 28 ++- 5 files changed, 144 insertions(+), 120 deletions(-) diff --git a/common/lib/capa/capa/inputtypes.py b/common/lib/capa/capa/inputtypes.py index f154569fe4..bd3642220f 100644 --- a/common/lib/capa/capa/inputtypes.py +++ b/common/lib/capa/capa/inputtypes.py @@ -57,7 +57,7 @@ class Attribute(object): # want to allow default to be None, but also allow required objects _sentinel = object() - def __init__(self, name, default=_sentinel, transform=None, validate=None): + def __init__(self, name, default=_sentinel, transform=None, validate=None, render=True): """ Define an attribute @@ -72,11 +72,14 @@ class Attribute(object): validate (function str-or-return-type-of-tranform -> unit or exception): If not None, called to validate the (possibly transformed) value of the attribute. Should raise ValueError with a helpful message if the value is invalid. + + render (bool): if False, don't include this attribute in the template context. """ self.name = name self.default = default self.validate = validate self.transform = transform + self.render = render def parse_from_xml(self, element): """ @@ -171,8 +174,7 @@ class InputTypeBase(object): """ Should return a list of Attribute objects (see docstring there for details). Subclasses should override. e.g. - return super(MyClass, cls).attributes + [Attribute('unicorn', True), - Attribute('num_dragons', 12, transform=int), ...] + return [Attribute('unicorn', True), Attribute('num_dragons', 12, transform=int), ...] """ return [] @@ -183,14 +185,19 @@ class InputTypeBase(object): function parses the input xml and pulls out those attributes. This isolates most simple input types from needing to deal with xml parsing at all. - Processes attributes, putting the results in the self.loaded_attributes dictionary. + Processes attributes, putting the results in the self.loaded_attributes dictionary. Also creates a set + self.to_render, containing the names of attributes that should be included in the context by default. """ - # Use a local dict so that if there are exceptions, we don't end up in a partially-initialized state. - d = {} + # Use local dicts and sets so that if there are exceptions, we don't end up in a partially-initialized state. + loaded = {} + to_render = set() for a in self.get_attributes(): - d[a.name] = a.parse_from_xml(self.xml) + loaded[a.name] = a.parse_from_xml(self.xml) + if a.render: + to_render.add(a.name) - self.loaded_attributes = d + self.loaded_attributes = loaded + self.to_render = to_render def setup(self): """ @@ -209,11 +216,11 @@ class InputTypeBase(object): (Separate from get_html to faciliate testing of logic separately from the rendering) - The default implementation gets the following rendering context: basic things like value, id, - status, and msg, as well as everything in self.loaded_attributes. + The default implementation gets the following rendering context: basic things like value, id, status, and msg, + as well as everything in self.loaded_attributes, and everything returned by self._extra_context(). - This means that input types that only parse attributes get everything they need, and don't need - to override this method. + This means that input types that only parse attributes and pass them to the template get everything they need, + and don't need to override this method. """ context = { 'id': self.id, @@ -221,9 +228,17 @@ class InputTypeBase(object): 'status': self.status, 'msg': self.msg, } - context.update(self.loaded_attributes) + context.update((a, v) for (a, v) in self.loaded_attributes.iteritems() if a in self.to_render) + context.update(self._extra_context()) return context + def _extra_context(self): + """ + Subclasses can override this to return extra context that should be passed to their templates for rendering. + + This is useful when the input type requires computing new template variables from the parsed attributes. + """ + return {} def get_html(self): """ @@ -233,8 +248,7 @@ class InputTypeBase(object): raise NotImplementedError("no rendering template specified for class {0}" .format(self.__class__)) - context = self._default_render_context() - context.update(self._get_render_context()) + context = self._get_render_context() html = self.system.render_template(self.template, context) return etree.XML(html) @@ -255,28 +269,32 @@ class OptionInput(InputTypeBase): template = "optioninput.html" tags = ['optioninput'] + @staticmethod + def parse_options(options): + """ + Given options string, convert it into an ordered list of (option_id, option_description) tuples, where + id==description for now. TODO: make it possible to specify different id and descriptions. + """ + # parse the set of possible options + lexer = shlex.shlex(options[1:-1]) + lexer.quotes = "'" + # Allow options to be separated by whitespace as well as commas + lexer.whitespace = ", " + + # remove quotes + tokens = [x[1:-1] for x in list(lexer)] + + # make list of (option_id, option_description), with description=id + return [(t, t) for t in tokens] + + @classmethod def get_attributes(cls): """ Convert options to a convenient format. """ - - def parse_options(options): - """Given options string, convert it into an ordered list of (option, option) tuples - (Why? I don't know--that's what the template uses at the moment) - """ - # parse the set of possible options - oset = shlex.shlex(options[1:-1]) - oset.quotes = "'" - oset.whitespace = "," - oset = [x[1:-1] for x in list(oset)] - - # make ordered list with (key, value) same - return [(oset[x], oset[x]) for x in range(len(oset))] - - return super(OptionInput, cls).get_attributes() + [ - Attribute('options', transform=parse_options), - Attribute('inline', '')] + return [Attribute('options', transform=cls.parse_options), + Attribute('inline', '')] registry.register(OptionInput) @@ -315,26 +333,22 @@ class ChoiceGroup(InputTypeBase): # value. (VS: would be nice to make this less hackish). if self.tag == 'choicegroup': self.suffix = '' - self.element_type = "radio" + self.html_input_type = "radio" elif self.tag == 'radiogroup': - self.element_type = "radio" + self.html_input_type = "radio" self.suffix = '[]' elif self.tag == 'checkboxgroup': - self.element_type = "checkbox" + self.html_input_type = "checkbox" self.suffix = '[]' else: raise Exception("ChoiceGroup: unexpected tag {0}".format(self.tag)) self.choices = extract_choices(self.xml) - def _get_render_context(self): - context = {'id': self.id, - 'value': self.value, - 'status': self.status, - 'input_type': self.element_type, - 'choices': self.choices, - 'name_array_suffix': self.suffix} - return context + def _extra_context(self): + return {'input_type': self.html_input_type, + 'choices': self.choices, + 'name_array_suffix': self.suffix} def extract_choices(element): ''' @@ -384,33 +398,23 @@ class JavascriptInput(InputTypeBase): template = "javascriptinput.html" tags = ['javascriptinput'] + @classmethod + def get_attributes(cls): + """ + Register the attributes. + """ + return [Attribute('params', None), + Attribute('problem_state', None), + Attribute('display_class', None), + Attribute('display_file', None),] + + def setup(self): # Need to provide a value that JSON can parse if there is no # student-supplied value yet. if self.value == "": self.value = 'null' - self.params = self.xml.get('params') - self.problem_state = self.xml.get('problem_state') - self.display_class = self.xml.get('display_class') - self.display_file = self.xml.get('display_file') - - - def _get_render_context(self): - escapedict = {'"': '"'} - value = saxutils.escape(self.value, escapedict) - msg = saxutils.escape(self.msg, escapedict) - - context = {'id': self.id, - 'params': self.params, - 'display_file': self.display_file, - 'display_class': self.display_class, - 'problem_state': self.problem_state, - 'value': value, - 'evaluation': msg, - } - return context - registry.register(JavascriptInput) @@ -418,51 +422,53 @@ registry.register(JavascriptInput) class TextLine(InputTypeBase): """ - + A text line input. Can do math preview if "math"="1" is specified. """ template = "textline.html" tags = ['textline'] + + @classmethod + def get_attributes(cls): + """ + Register the attributes. + """ + return [ + Attribute('size', None), + + # if specified, then textline is hidden and input id is stored + # in div with name=self.hidden. (TODO: is this functionality used by anyone?) + Attribute('hidden', False), + Attribute('inline', False), + + # Attributes below used in setup(), not rendered directly. + Attribute('math', None, render=False), + # TODO: 'dojs' flag is temporary, for backwards compatibility with 8.02x + Attribute('dojs', None, render=False), + Attribute('preprocessorClassName', None, render=False), + Attribute('preprocessorSrc', None, render=False), + ] + + def setup(self): - self.size = self.xml.get('size') + self.do_math = bool(self.loaded_attributes['math'] or + self.loaded_attributes['dojs']) - # if specified, then textline is hidden and input id is stored - # in div with name=self.hidden. - self.hidden = self.xml.get('hidden', False) - - self.inline = self.xml.get('inline', False) - - # TODO: 'dojs' flag is temporary, for backwards compatibility with 8.02x - self.do_math = bool(self.xml.get('math') or self.xml.get('dojs')) # TODO: do math checking using ajax instead of using js, so # that we only have one math parser. self.preprocessor = None if self.do_math: # Preprocessor to insert between raw input and Mathjax - self.preprocessor = {'class_name': self.xml.get('preprocessorClassName',''), - 'script_src': self.xml.get('preprocessorSrc','')} - if '' in self.preprocessor.values(): + self.preprocessor = {'class_name': self.loaded_attributes['preprocessorClassName'], + 'script_src': self.loaded_attributes['preprocessorSrc']} + if None in self.preprocessor.values(): self.preprocessor = None - - def _get_render_context(self): - # Escape answers with quotes, so they don't crash the system! - escapedict = {'"': '"'} - value = saxutils.escape(self.value, escapedict) - - context = {'id': self.id, - 'value': value, - 'status': self.status, - 'size': self.size, - 'msg': self.msg, - 'hidden': self.hidden, - 'inline': self.inline, - 'do_math': self.do_math, - 'preprocessor': self.preprocessor, - } - return context + def _extra_context(self): + return {'do_math': self.do_math, + 'preprocessor': self.preprocessor,} registry.register(TextLine) @@ -480,13 +486,26 @@ class FileSubmission(InputTypeBase): submitted_msg = ("Your file(s) have been submitted; as soon as your submission is" " graded, this message will be replaced with the grader's feedback.") - def setup(self): - escapedict = {'"': '"'} - self.allowed_files = json.dumps(self.xml.get('allowed_files', '').split()) - self.allowed_files = saxutils.escape(self.allowed_files, escapedict) - self.required_files = json.dumps(self.xml.get('required_files', '').split()) - self.required_files = saxutils.escape(self.required_files, escapedict) + @staticmethod + def parse_files(files): + """ + Given a string like 'a.py b.py c.out', split on whitespace and return as a json list. + """ + return json.dumps(files.split()) + @classmethod + def get_attributes(cls): + """ + Convert the list of allowed files to a convenient format. + """ + return [Attribute('allowed_files', '[]', transform=cls.parse_files), + Attribute('required_files', '[]', transform=cls.parse_files),] + + def setup(self): + """ + Do some magic to handle queueing status (render as "queued" instead of "incomplete"), + pull queue_len from the msg field. (TODO: get rid of the queue_len hack). + """ # Check if problem has been queued self.queue_len = 0 # Flag indicating that the problem has been queued, 'msg' is length of queue @@ -495,15 +514,8 @@ class FileSubmission(InputTypeBase): self.queue_len = self.msg self.msg = FileSubmission.submitted_msg - def _get_render_context(self): - - context = {'id': self.id, - 'status': self.status, - 'msg': self.msg, - 'value': self.value, - 'queue_len': self.queue_len, - 'allowed_files': self.allowed_files, - 'required_files': self.required_files,} + def _extra_context(self): + return {'queue_len': self.queue_len,} return context registry.register(FileSubmission) diff --git a/common/lib/capa/capa/templates/filesubmission.html b/common/lib/capa/capa/templates/filesubmission.html index 2572b25f8a..930469dc0d 100644 --- a/common/lib/capa/capa/templates/filesubmission.html +++ b/common/lib/capa/capa/templates/filesubmission.html @@ -12,7 +12,7 @@ % endif

${status}

- +
${msg|n}
diff --git a/common/lib/capa/capa/templates/javascriptinput.html b/common/lib/capa/capa/templates/javascriptinput.html index 8b4c8f7115..b4d007e4d8 100644 --- a/common/lib/capa/capa/templates/javascriptinput.html +++ b/common/lib/capa/capa/templates/javascriptinput.html @@ -2,7 +2,7 @@
+ data-submission="${value|h}" data-evaluation="${msg|h}">
diff --git a/common/lib/capa/capa/templates/textline.html b/common/lib/capa/capa/templates/textline.html index 97c512fc00..fbb5467b67 100644 --- a/common/lib/capa/capa/templates/textline.html +++ b/common/lib/capa/capa/templates/textline.html @@ -20,7 +20,7 @@
% endif - This is foil One.'), ('foil2', 'This is foil Two.'), @@ -119,12 +133,13 @@ class JavascriptInputTest(unittest.TestCase): context = the_input._get_render_context() expected = {'id': 'prob_1_2', + 'status': 'unanswered', + 'msg': '', + 'value': '3', 'params': params, 'display_file': display_file, 'display_class': display_class, - 'problem_state': problem_state, - 'value': '3', - 'evaluation': '',} + 'problem_state': problem_state,} self.assertEqual(context, expected) @@ -204,9 +219,6 @@ class FileSubmissionTest(unittest.TestCase): element = etree.fromstring(xml_str) - escapedict = {'"': '"'} - esc = lambda s: saxutils.escape(s, escapedict) - state = {'value': 'BumbleBee.py', 'status': 'incomplete', 'feedback' : {'message': '3'}, } @@ -220,8 +232,8 @@ class FileSubmissionTest(unittest.TestCase): 'msg': input_class.submitted_msg, 'value': 'BumbleBee.py', 'queue_len': '3', - 'allowed_files': esc('["runme.py", "nooooo.rb", "ohai.java"]'), - 'required_files': esc('["cookies.py"]')} + 'allowed_files': '["runme.py", "nooooo.rb", "ohai.java"]', + 'required_files': '["cookies.py"]'} self.assertEqual(context, expected) From b78fb8dff665cb15de2c378440d305d217c79456 Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Thu, 1 Nov 2012 00:05:48 -0400 Subject: [PATCH 07/29] Refactored the rest of the input types --- common/lib/capa/capa/inputtypes.py | 218 ++++++++---------- .../capa/capa/templates/crystallography.html | 2 +- .../lib/capa/capa/templates/vsepr_input.html | 2 +- common/lib/capa/capa/tests/test_inputtypes.py | 18 +- 4 files changed, 110 insertions(+), 130 deletions(-) diff --git a/common/lib/capa/capa/inputtypes.py b/common/lib/capa/capa/inputtypes.py index bd3642220f..2ff926479a 100644 --- a/common/lib/capa/capa/inputtypes.py +++ b/common/lib/capa/capa/inputtypes.py @@ -21,12 +21,14 @@ Each input type takes the xml tree as 'element', the previous answer as 'value', graded status as'status' """ -# TODO: there is a lot of repetitive "grab these elements from xml attributes, with these defaults, -# put them in the context" code. Refactor so class just specifies required and optional attrs (with -# defaults for latter), and InputTypeBase does the right thing. +# TODO: make hints do something + +# TODO: make all inputtypes actually render msg + +# TODO: remove unused fields (e.g. 'hidden' in a few places) + +# TODO: add validators so that content folks get better error messages. -# TODO: Quoting and unquoting is handled in a pretty ad-hoc way. Also something that could be done -# properly once in InputTypeBase. # Possible todo: make inline the default for textlines and other "one-line" inputs. It probably # makes sense, but a bunch of problems have markup that assumes block. Bigger TODO: figure out a @@ -39,7 +41,6 @@ from lxml import etree import re import shlex # for splitting quoted strings import sys -import xml.sax.saxutils as saxutils from registry import TagRegistry @@ -535,13 +536,30 @@ class CodeInput(InputTypeBase): # non-codemirror editor. ] + # pulled out for testing + submitted_msg = ("Your file(s) have been submitted; as soon as your submission is" + " graded, this message will be replaced with the grader's feedback.") + + @classmethod + def get_attributes(cls): + """ + Convert options to a convenient format. + """ + return [Attribute('rows', '30'), + Attribute('cols', '80'), + Attribute('hidden', ''), + + # For CodeMirror + Attribute('mode', 'python'), + Attribute('linenumbers', 'true'), + # Template expects tabsize to be an int it can do math with + Attribute('tabsize', 4, transform=int), + ] def setup(self): - self.rows = self.xml.get('rows') or '30' - self.cols = self.xml.get('cols') or '80' - # if specified, then textline is hidden and id is stored in div of name given by hidden - self.hidden = self.xml.get('hidden', '') - + """ + Implement special logic: handle queueing state, and default input. + """ # if no student input yet, then use the default input given by the problem if not self.value: self.value = self.xml.text @@ -552,28 +570,11 @@ class CodeInput(InputTypeBase): if self.status == 'incomplete': self.status = 'queued' self.queue_len = self.msg - self.msg = 'Submitted to grader.' + self.msg = self.submitted_msg - # For CodeMirror - self.mode = self.xml.get('mode', 'python') - self.linenumbers = self.xml.get('linenumbers', 'true') - self.tabsize = int(self.xml.get('tabsize', '4')) - - def _get_render_context(self): - - context = {'id': self.id, - 'value': self.value, - 'status': self.status, - 'msg': self.msg, - 'mode': self.mode, - 'linenumbers': self.linenumbers, - 'rows': self.rows, - 'cols': self.cols, - 'hidden': self.hidden, - 'tabsize': self.tabsize, - 'queue_len': self.queue_len, - } - return context + def _extra_context(self): + """Defined queue_len, add it """ + return {'queue_len': self.queue_len,} registry.register(CodeInput) @@ -586,26 +587,19 @@ class Schematic(InputTypeBase): template = "schematicinput.html" tags = ['schematic'] - def setup(self): - self.height = self.xml.get('height') - self.width = self.xml.get('width') - self.parts = self.xml.get('parts') - self.analyses = self.xml.get('analyses') - self.initial_value = self.xml.get('initial_value') - self.submit_analyses = self.xml.get('submit_analyses') + @classmethod + def get_attributes(cls): + """ + Convert options to a convenient format. + """ + return [ + Attribute('height', None), + Attribute('width', None), + Attribute('parts', None), + Attribute('analyses', None), + Attribute('initial_value', None), + Attribute('submit_analyses', None),] - - def _get_render_context(self): - - context = {'id': self.id, - 'value': self.value, - 'initial_value': self.initial_value, - 'status': self.status, - 'width': self.width, - 'height': self.height, - 'parts': self.parts, - 'analyses': self.analyses, - 'submit_analyses': self.submit_analyses,} return context registry.register(Schematic) @@ -626,12 +620,20 @@ class ImageInput(InputTypeBase): template = "imageinput.html" tags = ['imageinput'] - def setup(self): - self.src = self.xml.get('src') - self.height = self.xml.get('height') - self.width = self.xml.get('width') + @classmethod + def get_attributes(cls): + """ + Note: src, height, and width are all required. + """ + return [Attribute('src'), + Attribute('height'), + Attribute('width'),] - # if value is of the form [x,y] then parse it and send along coordinates of previous answer + + def setup(self): + """ + if value is of the form [x,y] then parse it and send along coordinates of previous answer + """ m = re.match('\[([0-9]+),([0-9]+)]', self.value.strip().replace(' ', '')) if m: # Note: we subtract 15 to compensate for the size of the dot on the screen. @@ -641,19 +643,10 @@ class ImageInput(InputTypeBase): (self.gx, self.gy) = (0, 0) - def _get_render_context(self): + def _extra_context(self): - context = {'id': self.id, - 'value': self.value, - 'height': self.height, - 'width': self.width, - 'src': self.src, - 'gx': self.gx, - 'gy': self.gy, - 'status': self.status, - 'msg': self.msg, - } - return context + return {'gx': self.gx, + 'gy': self.gy} registry.register(ImageInput) @@ -669,30 +662,18 @@ class Crystallography(InputTypeBase): template = "crystallography.html" tags = ['crystallography'] + @classmethod + def get_attributes(cls): + """ + Note: height, width are required. + """ + return [Attribute('size', None), + Attribute('height'), + Attribute('width'), - def setup(self): - self.height = self.xml.get('height') - self.width = self.xml.get('width') - self.size = self.xml.get('size') - - # if specified, then textline is hidden and id is stored in div of name given by hidden - self.hidden = self.xml.get('hidden', '') - - # Escape answers with quotes, so they don't crash the system! - escapedict = {'"': '"'} - self.value = saxutils.escape(self.value, escapedict) - - def _get_render_context(self): - context = {'id': self.id, - 'value': self.value, - 'status': self.status, - 'size': self.size, - 'msg': self.msg, - 'hidden': self.hidden, - 'width': self.width, - 'height': self.height, - } - return context + # can probably be removed (textline should prob be always-hidden) + Attribute('hidden', ''), + ] registry.register(Crystallography) @@ -707,29 +688,16 @@ class VseprInput(InputTypeBase): template = 'vsepr_input.html' tags = ['vsepr_input'] - def setup(self): - self.height = self.xml.get('height') - self.width = self.xml.get('width') - - # Escape answers with quotes, so they don't crash the system! - escapedict = {'"': '"'} - self.value = saxutils.escape(self.value, escapedict) - - self.molecules = self.xml.get('molecules') - self.geometries = self.xml.get('geometries') - - def _get_render_context(self): - - context = {'id': self.id, - 'value': self.value, - 'status': self.status, - 'msg': self.msg, - 'width': self.width, - 'height': self.height, - 'molecules': self.molecules, - 'geometries': self.geometries, - } - return context + @classmethod + def get_attributes(cls): + """ + Note: height, width are required. + """ + return [Attribute('height'), + Attribute('width'), + Attribute('molecules'), + Attribute('geometries'), + ] registry.register(VseprInput) @@ -750,17 +718,17 @@ class ChemicalEquationInput(InputTypeBase): template = "chemicalequationinput.html" tags = ['chemicalequationinput'] - def setup(self): - self.size = self.xml.get('size', '20') + @classmethod + def get_attributes(cls): + """ + Can set size of text field. + """ + return [Attribute('size', '20'),] - def _get_render_context(self): - context = { - 'id': self.id, - 'value': self.value, - 'status': self.status, - 'size': self.size, - 'previewer': '/static/js/capa/chemical_equation_preview.js', - } - return context + def _extra_context(self): + """ + TODO (vshnayder): Get rid of this once we have a standard way of requiring js to be loaded. + """ + return {'previewer': '/static/js/capa/chemical_equation_preview.js',} registry.register(ChemicalEquationInput) diff --git a/common/lib/capa/capa/templates/crystallography.html b/common/lib/capa/capa/templates/crystallography.html index f46e2f753a..2370f59dd2 100644 --- a/common/lib/capa/capa/templates/crystallography.html +++ b/common/lib/capa/capa/templates/crystallography.html @@ -19,7 +19,7 @@
% endif - % endif - diff --git a/common/lib/capa/capa/tests/test_inputtypes.py b/common/lib/capa/capa/tests/test_inputtypes.py index 5fbe73503f..826d304717 100644 --- a/common/lib/capa/capa/tests/test_inputtypes.py +++ b/common/lib/capa/capa/tests/test_inputtypes.py @@ -2,9 +2,18 @@ Tests of input types. TODO: +- refactor: so much repetive code (have factory methods that build xml elements directly, etc) + +- test error cases + +- check rendering -- e.g. msg should appear in the rendered output. If possible, test that + templates are escaping things properly. + + - test unicode in values, parameters, etc. - test various html escapes - test funny xml chars -- should never get xml parse error if things are escaped properly. + """ from lxml import etree @@ -267,14 +276,15 @@ class CodeInputTest(unittest.TestCase): 'status': 'incomplete', 'feedback' : {'message': '3'}, } - the_input = lookup_tag('codeinput')(test_system, element, state) + input_class = lookup_tag('codeinput') + the_input = input_class(test_system, element, state) context = the_input._get_render_context() expected = {'id': 'prob_1_2', 'value': 'print "good evening"', 'status': 'queued', - 'msg': 'Submitted to grader.', + 'msg': input_class.submitted_msg, 'mode': mode, 'linenumbers': linenumbers, 'rows': rows, @@ -323,8 +333,9 @@ class SchematicTest(unittest.TestCase): expected = {'id': 'prob_1_2', 'value': value, - 'initial_value': initial_value, 'status': 'unsubmitted', + 'msg': '', + 'initial_value': initial_value, 'width': width, 'height': height, 'parts': parts, @@ -488,6 +499,7 @@ class ChemicalEquationTest(unittest.TestCase): expected = {'id': 'prob_1_2', 'value': 'H2OYeah', 'status': 'unanswered', + 'msg': '', 'size': size, 'previewer': '/static/js/capa/chemical_equation_preview.js', } From 2203a0bd7031da2e7d96bb20b5724e8082588528 Mon Sep 17 00:00:00 2001 From: Aaron Culich Date: Thu, 1 Nov 2012 14:05:11 +0000 Subject: [PATCH 08/29] Updated APT_PKGS with valid Ubuntu package name: mysql -> mysql-server --- create-dev-env.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/create-dev-env.sh b/create-dev-env.sh index 656a40524e..c872f1dcbc 100755 --- a/create-dev-env.sh +++ b/create-dev-env.sh @@ -105,7 +105,7 @@ NUMPY_VER="1.6.2" SCIPY_VER="0.10.1" BREW_FILE="$BASE/mitx/brew-formulas.txt" LOG="/var/tmp/install-$(date +%Y%m%d-%H%M%S).log" -APT_PKGS="pkg-config curl git python-virtualenv build-essential python-dev gfortran liblapack-dev libfreetype6-dev libpng12-dev libxml2-dev libxslt-dev yui-compressor coffeescript graphviz graphviz-dev mysql" +APT_PKGS="pkg-config curl git python-virtualenv build-essential python-dev gfortran liblapack-dev libfreetype6-dev libpng12-dev libxml2-dev libxslt-dev yui-compressor coffeescript graphviz graphviz-dev mysql-server" if [[ $EUID -eq 0 ]]; then error "This script should not be run using sudo or as the root user" From 4712a039dc25214369eb26be8942874667279227 Mon Sep 17 00:00:00 2001 From: Aaron Culich Date: Thu, 1 Nov 2012 14:06:03 +0000 Subject: [PATCH 09/29] Added DEBIAN_FRONTEND=noninteractive to sudo apt-get which is required for silent mysql-server installation --- create-dev-env.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/create-dev-env.sh b/create-dev-env.sh index c872f1dcbc..96ec51d928 100755 --- a/create-dev-env.sh +++ b/create-dev-env.sh @@ -193,7 +193,8 @@ case `uname -s` in maya|lisa|natty|oneiric|precise|quantal) output "Installing ubuntu requirements" sudo apt-get -y update - sudo apt-get -y install $APT_PKGS + # DEBIAN_FRONTEND=noninteractive is required for silent mysql-server installation + sudo DEBIAN_FRONTEND=noninteractive apt-get -y install $APT_PKGS clone_repos ;; *) From 40ce5d2ff61861955a1f31ff3fb73d42729030e7 Mon Sep 17 00:00:00 2001 From: Aaron Culich Date: Thu, 1 Nov 2012 14:08:24 +0000 Subject: [PATCH 10/29] Fixed dependency problem introduced by MySQL-python by forcing distribute version >= 0.6.28 in pre-requirements --- pre-requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/pre-requirements.txt b/pre-requirements.txt index 24ce15ab7e..6eb4669059 100644 --- a/pre-requirements.txt +++ b/pre-requirements.txt @@ -1 +1,2 @@ numpy +distribute>=0.6.28 From 32498f3468fade5a344bb2b7018d3337691ac896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s=20Rocha?= Date: Thu, 1 Nov 2012 13:21:40 -0400 Subject: [PATCH 11/29] Remove learning designer and producer openings from job page --- lms/templates/static_templates/jobs.html | 67 ------------------------ 1 file changed, 67 deletions(-) diff --git a/lms/templates/static_templates/jobs.html b/lms/templates/static_templates/jobs.html index c78ce266ed..4bb8830eb1 100644 --- a/lms/templates/static_templates/jobs.html +++ b/lms/templates/static_templates/jobs.html @@ -49,79 +49,12 @@

If you are interested in this position, please send an email to jobs@edx.org

-
-
-

Learning Designer/Interaction Learning Designer

-

The Learning Designer will work as part of the content and development team to plan, develop and deliver highly engaging and media rich online courses. The learning designer will be a flexible thinker, able to determine and apply sound pedagogical strategies to unique situations and a diverse set of academic disciplines. This is a 6-12 months contract opportunity.

-

Specific Responsibilities include:

-
    -
  • Work with producers, product developers and course staff on implementing instructional design approaches in the development of media and other course materials.
  • -
  • Articulate learning objectives and align them to content design strategy and assessments.
  • -
  • Write effective instructional text, and audio and video scripts.
  • -
  • Coordinate workflows with video and content development team
  • -
  • Identify best practices and share these with the course staff and faculty as needed.
  • -
  • Create course communication style guides. Train and coach teaching staff on best practices for communication and discussion management.
  • -
  • Develop use case guides as needed on the use of edX courseware and new technologies.
  • -
  • Serve as a liaison to instructional design teams located at X universities.
  • -
  • Design peer review processes to be used by learners in selected courses.
  • -
  • Ability to apply game-based learning theory and design into selected courses as appropriate.
  • -
  • Use learning analytics and metrics to inform course design and revision process.
  • -
  • Work closely with the Content Research Director on articulating best practices for MOOC teaching and learning and course design.
  • -
  • Assist in the development of pilot courses used for sponsored research initiatives.
  • -
-

Qualifications:

-

Master's Degree in Educational Technology, Instructional Design or related field. Experience in higher education with additional experience in a start-up or research environment desirable. Excellent interpersonal and communication (written and verbal), project management, problem-solving and time management skills. The ability to be flexible with projects and to work on multiple courses essential. Ability to meet deadlines and manage expectations of constituents. Capacity to develop new and relevant technology skills.  Experience using game theory design and learning analytics to inform instructional design decisions and strategy.

-

Technical Skills:

-

Video and screencasting experience. LMS Platform experience, xml, HTML, CSS, Adobe Design Suite, Camtasia or Captivate experience. Experience with web 2.0 collaboration tools.

-

If you are interested in this position, please send an email to jobs@edx.org

-
-
-
-
-

Production Coordinator

-

The Production Coordinator supports video editors and course staff in all video related tasks, such as ingesting footage, transcoding, tracking live dates, transcriptions, organizing project deliverables and archiving completed projects.

-

Primary responsibilities:

-
    -
  • organize, track, and manage video and associated assets across the video workflow
  • -
  • manage project data and spreadsheets
  • -
  • route incoming source footage, and apply metadata tags
  • -
  • run encoding/transcoding jobs
  • -
  • prepare and process associated video assets, such as slides and image files
  • -
  • manage the transcription process
  • -
      -
    • traffic files among project staff and video transcription services
    • -
    • coordinate transcript reviews with course staff
    • -
    • integrate transcripts in course pages
    • -
    -
  • other video-related tasks as assigned.
  • -
-
-

Qualifications

-

The ideal candidate for the Production Coordinator position will have

-
    -
  • relentless attention to detail
  • -
  • ability to communicate and collaborate effectively across the organization
  • -
  • knowledge and understanding of digital media production tools and processes
  • -
  • experience with compression techniques, image processing, and presentation software preferred
  • -
  • proficiency with standard office applications
  • -
      -
    • spreadsheets
    • -
    • word processing
    • -
    • presentation
    • -
    -
  • experience with web publishing, e.g., HTML, XML, CSS, a plus
  • -
-

If you are interested in this position, please send an email to jobs@edx.org

-
-

Positions

How to Apply

E-mail your resume, coverletter and any other materials to jobs@edx.org

From 4db61f253166eeebd0201a3560c35d9cbb57c7b4 Mon Sep 17 00:00:00 2001 From: Aaron Culich Date: Thu, 1 Nov 2012 19:31:19 +0000 Subject: [PATCH 12/29] Fixed mysql_config not found error by adding libmysqlclient-dev to APT_PKGS --- create-dev-env.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/create-dev-env.sh b/create-dev-env.sh index 96ec51d928..f1d496a48f 100755 --- a/create-dev-env.sh +++ b/create-dev-env.sh @@ -105,7 +105,7 @@ NUMPY_VER="1.6.2" SCIPY_VER="0.10.1" BREW_FILE="$BASE/mitx/brew-formulas.txt" LOG="/var/tmp/install-$(date +%Y%m%d-%H%M%S).log" -APT_PKGS="pkg-config curl git python-virtualenv build-essential python-dev gfortran liblapack-dev libfreetype6-dev libpng12-dev libxml2-dev libxslt-dev yui-compressor coffeescript graphviz graphviz-dev mysql-server" +APT_PKGS="pkg-config curl git python-virtualenv build-essential python-dev gfortran liblapack-dev libfreetype6-dev libpng12-dev libxml2-dev libxslt-dev yui-compressor coffeescript graphviz graphviz-dev mysql-server libmysqlclient-dev" if [[ $EUID -eq 0 ]]; then error "This script should not be run using sudo or as the root user" From 8d40b19c940f1acd47541b4f021f8e9d4516be77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= Date: Fri, 2 Nov 2012 15:27:49 +0200 Subject: [PATCH 13/29] adde sphinx to pip req --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index ebc818b29d..944751f3c1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -52,3 +52,4 @@ pil nltk dogstatsd-python MySQL-python +sphinx From b8dc44c6cab36645e3d8ff9a9d3793c66f5c1ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= Date: Fri, 2 Nov 2012 17:17:12 +0200 Subject: [PATCH 14/29] commands for viewing and compiling docs --- rakefile | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/rakefile b/rakefile index 90cd5fe87f..30716ca365 100644 --- a/rakefile +++ b/rakefile @@ -250,3 +250,24 @@ task :autodeploy_properties do file.puts("UPSTREAM_REVISION=#{COMMIT}") end end + +desc "Invoke sphinx 'make build' to generate docs." +task :builddocs do + Dir.chdir('docs') do + sh('make html') + end +end + +desc "Show doc in browser (mac only for now) TODO add linux support" +task :showdocs do + Dir.chdir('docs/build/html') do + sh('open index.html') + end +end + +desc "Build docs and show them in browser" +task :doc => :builddocs do + Dir.chdir('docs/build/html') do + sh('open index.html') + end +end \ No newline at end of file From d55565791bcbfde5bf537ae8b261069a4086d49b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= Date: Fri, 2 Nov 2012 17:19:51 +0200 Subject: [PATCH 15/29] sphinx documentations, beginnings, capa module added --- docs/Makefile | 153 +++++++++++++++++++++ docs/source/common.rst | 54 ++++++++ docs/source/conf.py | 248 +++++++++++++++++++++++++++++++++++ docs/source/index.rst | 22 ++++ docs/source/lms.rst | 12 ++ docs/source/mitx_modules.rst | 14 ++ 6 files changed, 503 insertions(+) create mode 100644 docs/Makefile create mode 100644 docs/source/common.rst create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst create mode 100644 docs/source/lms.rst create mode 100644 docs/source/mitx_modules.rst diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000000..1d3bb030a1 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,153 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/MITx.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/MITx.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/MITx" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/MITx" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/docs/source/common.rst b/docs/source/common.rst new file mode 100644 index 0000000000..f83d89f52d --- /dev/null +++ b/docs/source/common.rst @@ -0,0 +1,54 @@ +******************************************* +Capa module +******************************************* + +.. module:: capa + +Calc +==== + +.. automodule:: capa.calc + :members: + :show-inheritance: + +Capa_problem +============ + +.. automodule:: capa.capa_problem + :members: + :show-inheritance: + +Checker +======= + +.. automodule:: capa.checker + :members: + :show-inheritance: + +Correctmap +========== + +.. automodule:: capa.correctmap + :members: + :show-inheritance: + +Customrender +============ + +.. automodule:: capa.customrender + :members: + :show-inheritance: + +Inputtypes +========== + +.. automodule:: capa.inputtypes + :members: + :show-inheritance: + +Resposetypes +============ + +.. automodule:: capa.responsetypes + :members: + :show-inheritance: diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000000..3ef480555d --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,248 @@ +# -*- coding: utf-8 -*- +# +# MITx documentation build configuration file, created by +# sphinx-quickstart on Fri Nov 2 15:43:00 2012. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('.')) +sys.path.insert(0, os.path.abspath('../..')) # mitx folder +sys.path.insert(0, os.path.join(os.path.abspath('../..'), 'common', 'lib', 'capa')) +# import ipdb; ipdb.set_trace() +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.pngmath', 'sphinx.ext.mathjax', 'sphinx.ext.viewcode'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'MITx' +copyright = u'2012, MITx team' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'sphinxdoc' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'MITxdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'MITx.tex', u'MITx Documentation', + u'MITx team', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'mitx', u'MITx Documentation', + [u'MITx team'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'MITx', u'MITx Documentation', + u'MITx team', 'MITx', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000000..4c8827189e --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,22 @@ +.. MITx documentation master file, created by + sphinx-quickstart on Fri Nov 2 15:43:00 2012. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to MITx's documentation! +================================ + +Contents: + +.. toctree:: + :maxdepth: 2 + + mitx_modules.rst + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/docs/source/lms.rst b/docs/source/lms.rst new file mode 100644 index 0000000000..0606942b99 --- /dev/null +++ b/docs/source/lms.rst @@ -0,0 +1,12 @@ +******************************************* +LMS appication +******************************************* + +.. module:: lms + +Models +====== + +.. automodule:: lms.lib + :members: + :show-inheritance: diff --git a/docs/source/mitx_modules.rst b/docs/source/mitx_modules.rst new file mode 100644 index 0000000000..027fc15a89 --- /dev/null +++ b/docs/source/mitx_modules.rst @@ -0,0 +1,14 @@ +MITx Modules +=============================== +Contents: + +.. toctree:: + :maxdepth: 2 + + .. askbot.rst + .. cms.rst + common.rst + .. doc.rst + .. docs.rst + .. fixtures.rst + .. lms.rst \ No newline at end of file From 037b6823f565e34835a26cb37d3f8d1e401cf266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= Date: Fri, 2 Nov 2012 19:45:05 +0200 Subject: [PATCH 16/29] doc logo prototype --- docs/source/_static/homepage-bg.jpg | Bin 0 -> 160660 bytes docs/source/_templates/layout.html | 5 +++++ 2 files changed, 5 insertions(+) create mode 100644 docs/source/_static/homepage-bg.jpg create mode 100644 docs/source/_templates/layout.html diff --git a/docs/source/_static/homepage-bg.jpg b/docs/source/_static/homepage-bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..61da5545c1e5eb65731ba0ef9b8627597e977d1c GIT binary patch literal 160660 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%0D(eoh)%6mY%P|xM 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

{zt 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 z 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

ycb9q0Lh*@I3B=5~+CP#)10 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 z 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%0A;%c`;o$VfclmXaBtO^AQkE6ENQK}C9HY4=gS@A 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 literal 0 HcmV?d00001 diff --git a/docs/source/_templates/layout.html b/docs/source/_templates/layout.html new file mode 100644 index 0000000000..3bf6372445 --- /dev/null +++ b/docs/source/_templates/layout.html @@ -0,0 +1,5 @@ +{% extends "!layout.html" %} + +{% block header %} +Edx logo +{% endblock %} \ No newline at end of file From 79174259cbbbc1f1756daf27d9048f5b408cfec9 Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Fri, 2 Nov 2012 14:00:51 -0400 Subject: [PATCH 17/29] Address Ike's comments. - change a few comments / strings - move extract_choices into the ChoiceGroup class --- common/lib/capa/capa/inputtypes.py | 54 ++++++++++++++++-------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/common/lib/capa/capa/inputtypes.py b/common/lib/capa/capa/inputtypes.py index 2ff926479a..0b2250f98d 100644 --- a/common/lib/capa/capa/inputtypes.py +++ b/common/lib/capa/capa/inputtypes.py @@ -265,6 +265,8 @@ class OptionInput(InputTypeBase): Example: The location of the sky + + # TODO: allow ordering to be randomized """ template = "optioninput.html" @@ -288,7 +290,6 @@ class OptionInput(InputTypeBase): # make list of (option_id, option_description), with description=id return [(t, t) for t in tokens] - @classmethod def get_attributes(cls): """ @@ -344,39 +345,40 @@ class ChoiceGroup(InputTypeBase): else: raise Exception("ChoiceGroup: unexpected tag {0}".format(self.tag)) - self.choices = extract_choices(self.xml) + self.choices = self.extract_choices(self.xml) def _extra_context(self): return {'input_type': self.html_input_type, 'choices': self.choices, 'name_array_suffix': self.suffix} -def extract_choices(element): - ''' - Extracts choices for a few input types, such as ChoiceGroup, RadioGroup and - CheckboxGroup. + @staticmethod + def extract_choices(element): + ''' + Extracts choices for a few input types, such as ChoiceGroup, RadioGroup and + CheckboxGroup. - returns list of (choice_name, choice_text) tuples + returns list of (choice_name, choice_text) tuples - TODO: allow order of choices to be randomized, following lon-capa spec. Use - "location" attribute, ie random, top, bottom. - ''' + TODO: allow order of choices to be randomized, following lon-capa spec. Use + "location" attribute, ie random, top, bottom. + ''' - choices = [] + choices = [] - for choice in element: - if choice.tag != 'choice': - raise Exception( - "[capa.inputtypes.extract_choices] Expected a tag; got %s instead" - % choice.tag) - choice_text = ''.join([etree.tostring(x) for x in choice]) - if choice.text is not None: - # TODO: fix order? - choice_text += choice.text + for choice in element: + if choice.tag != 'choice': + raise Exception( + "[capa.inputtypes.extract_choices] Expected a tag; got %s instead" + % choice.tag) + choice_text = ''.join([etree.tostring(x) for x in choice]) + if choice.text is not None: + # TODO: fix order? + choice_text += choice.text - choices.append((choice.get("name"), choice_text)) + choices.append((choice.get("name"), choice_text)) - return choices + return choices registry.register(ChoiceGroup) @@ -424,6 +426,9 @@ registry.register(JavascriptInput) class TextLine(InputTypeBase): """ A text line input. Can do math preview if "math"="1" is specified. + + If the hidden attribute is specified, the textline is hidden and the input id is stored in a div with name equal + to the value of the hidden attribute. This is used e.g. for embedding simulations turned into questions. """ template = "textline.html" @@ -438,8 +443,7 @@ class TextLine(InputTypeBase): return [ Attribute('size', None), - # if specified, then textline is hidden and input id is stored - # in div with name=self.hidden. (TODO: is this functionality used by anyone?) + Attribute('hidden', False), Attribute('inline', False), @@ -537,7 +541,7 @@ class CodeInput(InputTypeBase): ] # pulled out for testing - submitted_msg = ("Your file(s) have been submitted; as soon as your submission is" + submitted_msg = ("Submitted. As soon as your submission is" " graded, this message will be replaced with the grader's feedback.") @classmethod From afabb4ab1612f63734de62176a8262553c03b5f3 Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Fri, 2 Nov 2012 14:25:25 -0400 Subject: [PATCH 18/29] Don't call fn before defined. [ie8 is only browser which seems to care.] --- lms/templates/staff_problem_info.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lms/templates/staff_problem_info.html b/lms/templates/staff_problem_info.html index 6d9d1a3a30..9d51a119c6 100644 --- a/lms/templates/staff_problem_info.html +++ b/lms/templates/staff_problem_info.html @@ -61,8 +61,6 @@ function setup_debug_${element_id}(){ $('#${element_id}_xqa_form').submit(sendlog_${element_id}); } -setup_debug_${element_id}(); - function sendlog_${element_id}(){ var xqaLog = {authkey: '${xqa_key}', @@ -97,6 +95,8 @@ function sendlog_${element_id}(){ }); return false; }; + +setup_debug_${element_id}(); function getlog_${element_id}(){ From b75a814f7ae12aeb83a5fea793abd6689509aaa8 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Fri, 2 Nov 2012 15:08:45 -0400 Subject: [PATCH 19/29] add django performance metering --- lms/envs/cms/dev.py | 10 ++++++++++ requirements.txt | 2 ++ 2 files changed, 12 insertions(+) diff --git a/lms/envs/cms/dev.py b/lms/envs/cms/dev.py index 3d2c0c3c3b..4b6b0a12f0 100644 --- a/lms/envs/cms/dev.py +++ b/lms/envs/cms/dev.py @@ -33,3 +33,13 @@ CONTENTSTORE = { 'db': 'xcontent', } } + +INSTALLED_APPS += ( + # Mongo perf stats + 'debug_toolbar_mongo', + ) + + +DEBUG_TOOLBAR_PANELS += ( + 'debug_toolbar_mongo.panel.MongoDebugPanel', + ) diff --git a/requirements.txt b/requirements.txt index 2ebca50bc5..c1738bf98c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -50,3 +50,5 @@ pygraphviz -r repo-requirements.txt pil nltk +django-debug-toolbar-mongo + From 8089be33540bcd7c3473a5cfdf11f1ff8d240768 Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Fri, 2 Nov 2012 15:31:02 -0400 Subject: [PATCH 20/29] Minor stylistic change on jQuery pattern. --- common/lib/xmodule/xmodule/js/src/capa/schematic.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/lib/xmodule/xmodule/js/src/capa/schematic.js b/common/lib/xmodule/xmodule/js/src/capa/schematic.js index d2602d8ac3..e65b0ecad6 100644 --- a/common/lib/xmodule/xmodule/js/src/capa/schematic.js +++ b/common/lib/xmodule/xmodule/js/src/capa/schematic.js @@ -3723,7 +3723,7 @@ schematic = (function() { // look for property input fields in the content and give // them a keypress listener that interprets ENTER as // clicking OK. - var plist = $(content).find('.property'); + var plist = content.$('.property'); for (var i = plist.length - 1; i >= 0; --i) { var field = plist[i]; field.dialog = dialog; // help event handler find us... From 55a0cada7b5299147b65251ac5e50d5c08f9ac32 Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Fri, 2 Nov 2012 16:59:41 -0400 Subject: [PATCH 21/29] Fix a bug with pointer-tag detection on load if a tag has text but no children, wasn't properly detected as an inline definition. --- .../lib/xmodule/xmodule/tests/test_import.py | 29 +++++++++++++++++++ common/lib/xmodule/xmodule/xml_module.py | 7 +++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/common/lib/xmodule/xmodule/tests/test_import.py b/common/lib/xmodule/xmodule/tests/test_import.py index 21dd8968f6..e8a9719422 100644 --- a/common/lib/xmodule/xmodule/tests/test_import.py +++ b/common/lib/xmodule/xmodule/tests/test_import.py @@ -176,6 +176,33 @@ class ImportTestCase(unittest.TestCase): self.assertEqual(chapter_xml.tag, 'chapter') self.assertFalse('graceperiod' in chapter_xml.attrib) + def test_is_pointer_tag(self): + """ + Check that is_pointer_tag works properly. + """ + + yes = ["""""", + """""", + """ """, + """""", + """"""] + + no = ["""""", + """some text""", + """tree""", + """ + 3 + + """] + + for xml_str in yes: + print "should be True for {0}".format(xml_str) + self.assertTrue(is_pointer_tag(etree.fromstring(xml_str))) + + for xml_str in no: + print "should be False for {0}".format(xml_str) + self.assertFalse(is_pointer_tag(etree.fromstring(xml_str))) + def test_metadata_inherit(self): """Make sure that metadata is inherited properly""" @@ -311,3 +338,5 @@ class ImportTestCase(unittest.TestCase): system = self.get_system(False) self.assertRaises(etree.XMLSyntaxError, system.process_xml, bad_xml) + + diff --git a/common/lib/xmodule/xmodule/xml_module.py b/common/lib/xmodule/xmodule/xml_module.py index a5b3460f17..ec755af4ef 100644 --- a/common/lib/xmodule/xmodule/xml_module.py +++ b/common/lib/xmodule/xmodule/xml_module.py @@ -25,7 +25,7 @@ def name_to_pathname(name): def is_pointer_tag(xml_obj): """ Check if xml_obj is a pointer tag: . - No children, one attribute named url_name. + No children, one attribute named url_name, no text. Special case for course roots: the pointer is @@ -40,7 +40,10 @@ def is_pointer_tag(xml_obj): expected_attr = set(['url_name', 'course', 'org']) actual_attr = set(xml_obj.attrib.keys()) - return len(xml_obj) == 0 and actual_attr == expected_attr + + has_text = xml_obj.text is not None and len(xml_obj.text.strip()) > 0 + + return len(xml_obj) == 0 and actual_attr == expected_attr and not has_text def get_metadata_from_xml(xml_object, remove=True): meta = xml_object.find('meta') From d1aa0a254eba1c56544537401ab36c64d9a8ae24 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Fri, 2 Nov 2012 17:21:00 -0400 Subject: [PATCH 22/29] Use one of our test courses when testing course permissions for the discussion client, because we now have course policy level overrides. --- lms/djangoapps/django_comment_client/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lms/djangoapps/django_comment_client/tests.py b/lms/djangoapps/django_comment_client/tests.py index 55f18de8ea..2f3126be2c 100644 --- a/lms/djangoapps/django_comment_client/tests.py +++ b/lms/djangoapps/django_comment_client/tests.py @@ -19,7 +19,7 @@ class PermissionsTestCase(TestCase): def setUp(self): - self.course_id = "MITx/6.002x/2012_Fall" + self.course_id = "edX/toy/2012_Fall" self.moderator_role = Role.objects.get_or_create(name="Moderator", course_id=self.course_id)[0] self.student_role = Role.objects.get_or_create(name="Student", course_id=self.course_id)[0] From 86189b3b7c4b39c91f4b0e72e287947bd10bd83d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= Date: Mon, 5 Nov 2012 14:03:18 +0200 Subject: [PATCH 23/29] changed witdh to 100% --- docs/source/_templates/layout.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/_templates/layout.html b/docs/source/_templates/layout.html index 3bf6372445..66ff998af1 100644 --- a/docs/source/_templates/layout.html +++ b/docs/source/_templates/layout.html @@ -1,5 +1,5 @@ {% extends "!layout.html" %} {% block header %} -Edx logo +Edx logo {% endblock %} \ No newline at end of file From 31d3144532ea2c1d02a03ac0e4cc024540687ce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s=20Rocha?= Date: Mon, 5 Nov 2012 10:23:58 -0500 Subject: [PATCH 24/29] Remove openings from job page --- lms/templates/static_templates/jobs.html | 32 ++++++++---------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/lms/templates/static_templates/jobs.html b/lms/templates/static_templates/jobs.html index 4bb8830eb1..15fcbfcdca 100644 --- a/lms/templates/static_templates/jobs.html +++ b/lms/templates/static_templates/jobs.html @@ -30,32 +30,20 @@


-
+
-
-
-
-

Platform Developer

-

Platform Developers build the core learning platform that powers edX, writing both front-end and back-end code. They tackle a wide range of technical challenges, and so the best candidates will have a strong background in one or more of the following areas: machine learning, education, user interaction design, big data, social network analysis, and devops. Specialists are encouraged to apply, but team members often wear many hats. Our ideal candidate would have excellent coding skills, a proven history of delivering projects, and a deep research background.

-

If you are interested in this position, please send an email to jobs@edx.org

-
+

We're hiring!

+

Are you passionate? Want to help change the world? Good, you've found the right company! We're growing and our team needs the best and brightest in creating the next evolution in interactive online education.

+

Want to apply to edX?

+

Send your resume and cover letter to jobs@edx.org.

+

Note: We'll review each and every resume but please note you may not get a response due to the volume of inquiries.

-

Positions

- + + + +

How to Apply

E-mail your resume, coverletter and any other materials to jobs@edx.org

Our Location

From 5bae4455387c34eb958f05e290aa5e63e116e5cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= Date: Mon, 5 Nov 2012 18:56:02 +0200 Subject: [PATCH 25/29] docs close to structure, add snippet to autodoc django models --- docs/source/{common.rst => capa.rst} | 0 docs/source/cms.rst | 54 ++++++++ docs/source/common-lib.rst | 9 ++ docs/source/conf.py | 97 ++++++++++++++- docs/source/djangoapps-common.rst | 54 ++++++++ docs/source/djangoapps.rst | 10 ++ docs/source/index.rst | 5 +- docs/source/lms.rst | 141 ++++++++++++++++++++- docs/source/mitx_modules.rst | 14 --- docs/source/overview.rst | 20 +++ docs/source/xmodule.rst | 180 +++++++++++++++++++++++++++ 11 files changed, 564 insertions(+), 20 deletions(-) rename docs/source/{common.rst => capa.rst} (100%) create mode 100644 docs/source/cms.rst create mode 100644 docs/source/common-lib.rst create mode 100644 docs/source/djangoapps-common.rst create mode 100644 docs/source/djangoapps.rst delete mode 100644 docs/source/mitx_modules.rst create mode 100644 docs/source/overview.rst create mode 100644 docs/source/xmodule.rst diff --git a/docs/source/common.rst b/docs/source/capa.rst similarity index 100% rename from docs/source/common.rst rename to docs/source/capa.rst diff --git a/docs/source/cms.rst b/docs/source/cms.rst new file mode 100644 index 0000000000..f83d89f52d --- /dev/null +++ b/docs/source/cms.rst @@ -0,0 +1,54 @@ +******************************************* +Capa module +******************************************* + +.. module:: capa + +Calc +==== + +.. automodule:: capa.calc + :members: + :show-inheritance: + +Capa_problem +============ + +.. automodule:: capa.capa_problem + :members: + :show-inheritance: + +Checker +======= + +.. automodule:: capa.checker + :members: + :show-inheritance: + +Correctmap +========== + +.. automodule:: capa.correctmap + :members: + :show-inheritance: + +Customrender +============ + +.. automodule:: capa.customrender + :members: + :show-inheritance: + +Inputtypes +========== + +.. automodule:: capa.inputtypes + :members: + :show-inheritance: + +Resposetypes +============ + +.. automodule:: capa.responsetypes + :members: + :show-inheritance: diff --git a/docs/source/common-lib.rst b/docs/source/common-lib.rst new file mode 100644 index 0000000000..4fa5eaeb0a --- /dev/null +++ b/docs/source/common-lib.rst @@ -0,0 +1,9 @@ +Common / lib +=============================== +Contents: + +.. toctree:: + :maxdepth: 2 + + xmodule.rst + capa.rst \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index 3ef480555d..555dfd4e13 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -18,8 +18,23 @@ import sys, os # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('.')) sys.path.insert(0, os.path.abspath('../..')) # mitx folder -sys.path.insert(0, os.path.join(os.path.abspath('../..'), 'common', 'lib', 'capa')) +sys.path.insert(0, os.path.join(os.path.abspath('../..'), 'common', 'lib', 'capa')) # capa module +sys.path.insert(0, os.path.join(os.path.abspath('../..'), 'common', 'lib', 'xmodule')) # xmodule +sys.path.insert(0, os.path.join(os.path.abspath('../..'), 'lms', 'djangoapps')) # lms djangoapps +sys.path.insert(0, os.path.join(os.path.abspath('../..'), 'cms', 'djangoapps')) # cms djangoapps +sys.path.insert(0, os.path.join(os.path.abspath('../..'), 'common', 'djangoapps')) # common djangoapps + + + +# django specific # import ipdb; ipdb.set_trace() +# Set up the Django settings/environment +# STATIC_URL = '/static/' +# sys.path.insert(0, os.path.join(os.path.abspath('../..'), 'lms', 'envs')) # lms djangoapps +# from django.core.management import setup_environ +# import lms.envs.dev +# import ipdb; ipdb.set_trace() +# setup_environ(lms.envs.dev) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. @@ -246,3 +261,83 @@ texinfo_documents = [ # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'http://docs.python.org/': None} + +# from http://djangosnippets.org/snippets/2533/ +# autogenerate models definitions +# THIS_DIR = os.path.dirname(__file__) +# PROJECT_DIR = os.path.join(THIS_DIR, 'relative/path/to/your/project/') +# sys.path.append(PROJECT_DIR) + +import inspect +import lms.envs.dev +from django.core.management import setup_environ +from django.utils.html import strip_tags +from django.utils.encoding import force_unicode + +setup_environ(lms.envs.dev) + + +def process_docstring(app, what, name, obj, options, lines): + # This causes import errors if left outside the function + from django.db import models + from django import forms + from django.forms.models import BaseInlineFormSet + + # Only look at objects that inherit from Django's base MODEL class + if inspect.isclass(obj) and issubclass(obj, models.Model): + # Grab the field list from the meta class + fields = obj._meta._fields() + + for field in fields: + # Decode and strip any html out of the field's help text + help_text = strip_tags(force_unicode(field.help_text)) + + # Decode and capitalize the verbose name, for use if there isn't + # any help text + verbose_name = force_unicode(field.verbose_name).capitalize() + + if help_text: + # Add the model field to the end of the docstring as a param + # using the help text as the description + lines.append(u':param %s: %s' % (field.attname, help_text)) + else: + # Add the model field to the end of the docstring as a param + # using the verbose name as the description + lines.append(u':param %s: %s' % (field.attname, verbose_name)) + + # Add the field's type to the docstring + lines.append(u':type %s: %s' % (field.attname, type(field).__name__)) + # Only look at objects that inherit from Django's base FORM class + # elif (inspect.isclass(obj) and issubclass(obj, forms.ModelForm) or issubclass(obj, forms.ModelForm) or issubclass(obj, BaseInlineFormSet)): + # pass + # # Grab the field list from the meta class + # import ipdb; ipdb.set_trace() + # fields = obj._meta._fields() + # import ipdb; ipdb.set_trace() + # for field in fields: + # import ipdb; ipdb.set_trace() + # # Decode and strip any html out of the field's help text + # help_text = strip_tags(force_unicode(field.help_text)) + + # # Decode and capitalize the verbose name, for use if there isn't + # # any help text + # verbose_name = force_unicode(field.verbose_name).capitalize() + + # if help_text: + # # Add the model field to the end of the docstring as a param + # # using the help text as the description + # lines.append(u':param %s: %s' % (field.attname, help_text)) + # else: + # # Add the model field to the end of the docstring as a param + # # using the verbose name as the description + # lines.append(u':param %s: %s' % (field.attname, verbose_name)) + + # # Add the field's type to the docstring + # lines.append(u':type %s: %s' % (field.attname, type(field).__name__)) + # Return the extended docstring + return lines + + +def setup(app): + # Register the docstring processor with sphinx + app.connect('autodoc-process-docstring', process_docstring) \ No newline at end of file diff --git a/docs/source/djangoapps-common.rst b/docs/source/djangoapps-common.rst new file mode 100644 index 0000000000..f83d89f52d --- /dev/null +++ b/docs/source/djangoapps-common.rst @@ -0,0 +1,54 @@ +******************************************* +Capa module +******************************************* + +.. module:: capa + +Calc +==== + +.. automodule:: capa.calc + :members: + :show-inheritance: + +Capa_problem +============ + +.. automodule:: capa.capa_problem + :members: + :show-inheritance: + +Checker +======= + +.. automodule:: capa.checker + :members: + :show-inheritance: + +Correctmap +========== + +.. automodule:: capa.correctmap + :members: + :show-inheritance: + +Customrender +============ + +.. automodule:: capa.customrender + :members: + :show-inheritance: + +Inputtypes +========== + +.. automodule:: capa.inputtypes + :members: + :show-inheritance: + +Resposetypes +============ + +.. automodule:: capa.responsetypes + :members: + :show-inheritance: diff --git a/docs/source/djangoapps.rst b/docs/source/djangoapps.rst new file mode 100644 index 0000000000..7a8414189a --- /dev/null +++ b/docs/source/djangoapps.rst @@ -0,0 +1,10 @@ +Django applications +=============================== +Contents: + +.. toctree:: + :maxdepth: 2 + + lms.rst + cms.rst + djangoapps-common.rst \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index 4c8827189e..92c535a624 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -11,7 +11,10 @@ Contents: .. toctree:: :maxdepth: 2 - mitx_modules.rst + overview.rst + common-lib.rst + djangoapps.rst + Indices and tables ================== diff --git a/docs/source/lms.rst b/docs/source/lms.rst index 0606942b99..ad114a3088 100644 --- a/docs/source/lms.rst +++ b/docs/source/lms.rst @@ -1,12 +1,145 @@ ******************************************* -LMS appication +LMS module ******************************************* .. module:: lms -Models -====== +Branding +======== -.. automodule:: lms.lib +.. automodule:: branding + :members: + :show-inheritance: + +Views +----- + +.. automodule:: branding.views + :members: + :show-inheritance: + +Certificates +============ + +.. automodule:: certificates + :members: + :show-inheritance: + +Models +------ + +.. automodule:: certificates.models + :members: + :show-inheritance: + +Views +----- + +.. automodule:: certificates.views + :members: + :show-inheritance: + +Tests +----- + +.. automodule:: certificates.tests + :members: + :show-inheritance: + +Circuit +======= + +.. automodule:: circuit + :members: + :show-inheritance: + +Course_wiki +=========== + +.. automodule:: course_wiki + :members: + :show-inheritance: + +Courseware +========== + +.. automodule:: courseware + :members: + :show-inheritance: + +Dashboard +========= + +.. automodule:: dashboard + :members: + :show-inheritance: + +Django comment client +===================== + +.. automodule:: django_comment_client + :members: + :show-inheritance: + +Heartbeat +========= + +.. automodule:: heartbeat + :members: + :show-inheritance: + +Instructor +========== + +.. automodule:: instructor + :members: + :show-inheritance: + +Lisenses +======== + +.. automodule:: licenses + :members: + :show-inheritance: + +LMS migration +============= + +.. automodule:: lms_migration + :members: + :show-inheritance: + +Multicourse +=========== + +.. automodule:: multicourse + :members: + :show-inheritance: + +Psychometrics +============= + +.. automodule:: psychometrics + :members: + :show-inheritance: + +Simple wiki +=========== + +.. automodule:: simplewiki + :members: + :show-inheritance: + +Static template view +==================== + +.. automodule:: static_template_view + :members: + :show-inheritance: + +Static book +=========== + +.. automodule:: staticbook :members: :show-inheritance: diff --git a/docs/source/mitx_modules.rst b/docs/source/mitx_modules.rst deleted file mode 100644 index 027fc15a89..0000000000 --- a/docs/source/mitx_modules.rst +++ /dev/null @@ -1,14 +0,0 @@ -MITx Modules -=============================== -Contents: - -.. toctree:: - :maxdepth: 2 - - .. askbot.rst - .. cms.rst - common.rst - .. doc.rst - .. docs.rst - .. fixtures.rst - .. lms.rst \ No newline at end of file diff --git a/docs/source/overview.rst b/docs/source/overview.rst new file mode 100644 index 0000000000..007c7582ad --- /dev/null +++ b/docs/source/overview.rst @@ -0,0 +1,20 @@ +******************************************* +What the pieces are? +******************************************* + +What +==== + +... + +How +=== + +... + + +Who +=== + + +... \ No newline at end of file diff --git a/docs/source/xmodule.rst b/docs/source/xmodule.rst new file mode 100644 index 0000000000..45caa82c30 --- /dev/null +++ b/docs/source/xmodule.rst @@ -0,0 +1,180 @@ +******************************************* +Xmodule +******************************************* + +.. module:: xmodule + +Abtest +====== + +.. automodule:: xmodule.abtest_module + :members: + :show-inheritance: + +Back compatibility +================== + +.. automodule:: xmodule.backcompat_module + :members: + :show-inheritance: + +Capa +==== + +.. automodule:: xmodule.capa_module + :members: + :show-inheritance: + +Course +====== + +.. automodule:: xmodule.course_module + :members: + :show-inheritance: + +Discussion +========== + +.. automodule:: xmodule.discussion_module + :members: + :show-inheritance: + +Editing +======= + +.. automodule:: xmodule.editing_module + :members: + :show-inheritance: + +Error +===== + +.. automodule:: xmodule.error_module + :members: + :show-inheritance: + +Error tracker +============= + +.. automodule:: xmodule.errortracker + :members: + :show-inheritance: + +Exceptions +========== + +.. automodule:: xmodule.exceptions + :members: + :show-inheritance: + +Graders +======= + +.. automodule:: xmodule.graders + :members: + :show-inheritance: + +Hidden +====== + +.. automodule:: xmodule.hidden_module + :members: + :show-inheritance: + +Html checker +============ + +.. automodule:: xmodule.html_checker + :members: + :show-inheritance: + +Html +==== + +.. automodule:: xmodule.html_module + :members: + :show-inheritance: + +Mako +==== + +.. automodule:: xmodule.mako_module + :members: + :show-inheritance: + +Progress +======== + +.. automodule:: xmodule.progress + :members: + :show-inheritance: + +Schematic +========= + +.. automodule:: xmodule.schematic_module + :members: + :show-inheritance: + +Sequence +======== + +.. automodule:: xmodule.seq_module + :members: + :show-inheritance: + +Stringify +========= + +.. automodule:: xmodule.stringify + :members: + :show-inheritance: + +Template +======== + +.. automodule:: xmodule.template_module + :members: + :show-inheritance: + +Templates +========= + +.. automodule:: xmodule.templates + :members: + :show-inheritance: + +Time parse +========== + +.. automodule:: xmodule.timeparse + :members: + :show-inheritance: + +Vertical +======== + +.. automodule:: xmodule.vertical_module + :members: + :show-inheritance: + +Video +===== + +.. automodule:: xmodule.video_module + :members: + :show-inheritance: + +X += + +.. automodule:: xmodule.x_module + :members: + :show-inheritance: + +Xml +=== + +.. automodule:: xmodule.xml_module + :members: + :show-inheritance: From 7f4bb63dff596ebd8ded0afa48a31c03196cc17c Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Mon, 5 Nov 2012 13:55:09 -0500 Subject: [PATCH 26/29] Final ie8 fixes hopefully. Now renders correctly for staff. Moved the debug fns from per problem to part of courseware w/ context info passed as parms. Known issues: ie8 complains that getlog is not defined if you click on QA and does not show the debug info popup. --- lms/djangoapps/courseware/views.py | 1 + lms/templates/courseware/courseware.html | 4 +- lms/templates/courseware/xqa_interface.html | 73 ++++++++++++++++ lms/templates/staff_problem_info.html | 94 +++++---------------- 4 files changed, 99 insertions(+), 73 deletions(-) create mode 100644 lms/templates/courseware/xqa_interface.html diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py index 58bd6924af..d8def76473 100644 --- a/lms/djangoapps/courseware/views.py +++ b/lms/djangoapps/courseware/views.py @@ -217,6 +217,7 @@ def index(request, course_id, chapter=None, section=None, 'init': '', 'content': '', 'staff_access': staff_access, + 'xqa_server': settings.MITX_FEATURES.get('USE_XQA_SERVER','http://xqa:server@content-qa.mitx.mit.edu/xqa') } chapter_descriptor = course.get_child_by_url_name(chapter) diff --git a/lms/templates/courseware/courseware.html b/lms/templates/courseware/courseware.html index 62af7d6f82..1ea3df1b5a 100644 --- a/lms/templates/courseware/courseware.html +++ b/lms/templates/courseware/courseware.html @@ -25,7 +25,9 @@ <%static:js group='discussion'/> <%include file="../discussion/_js_body_dependencies.html" /> - + % if staff_access: + <%include file="xqa_interface.html"/> + % endif + \ No newline at end of file diff --git a/lms/templates/staff_problem_info.html b/lms/templates/staff_problem_info.html index 9d51a119c6..0f1893ee4f 100644 --- a/lms/templates/staff_problem_info.html +++ b/lms/templates/staff_problem_info.html @@ -1,6 +1,14 @@ ${module_content} %if edit_link: - +
+ Edit / + QA +
% endif @@ -50,77 +58,19 @@ category = ${category | h}
-## leanModal needs to be included here otherwise this breaks when in a - - From 3bae16fbdfb680419a6d98aa59b9afbf0e7a3e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= Date: Tue, 6 Nov 2012 14:39:53 +0200 Subject: [PATCH 27/29] update of documentation --- docs/source/cms.rst | 83 +++++++--- docs/source/conf.py | 21 +-- docs/source/djangoapps-common.rst | 60 +++---- docs/source/lms.rst | 256 ++++++++++++++++++++++++++++++ 4 files changed, 351 insertions(+), 69 deletions(-) diff --git a/docs/source/cms.rst b/docs/source/cms.rst index f83d89f52d..02dcaccb5a 100644 --- a/docs/source/cms.rst +++ b/docs/source/cms.rst @@ -1,54 +1,89 @@ ******************************************* -Capa module +CMS module ******************************************* -.. module:: capa +.. module:: cms -Calc +Auth ==== -.. automodule:: capa.calc +.. automodule:: auth :members: :show-inheritance: -Capa_problem -============ +Authz +----- -.. automodule:: capa.capa_problem +.. automodule:: auth.authz :members: :show-inheritance: -Checker -======= +Content store +============= -.. automodule:: capa.checker +.. .. automodule:: contentstore +.. :members: +.. :show-inheritance: + +.. Utils +.. ----- + +.. .. automodule:: contentstore.untils +.. :members: +.. :show-inheritance: + +.. Views +.. ----- + +.. .. automodule:: contentstore.views +.. :members: +.. :show-inheritance: + +.. Management +.. ---------- + +.. .. automodule:: contentstore.management +.. :members: +.. :show-inheritance: + +.. Tests +.. ----- + +.. .. automodule:: contentstore.tests +.. :members: +.. :show-inheritance: + +Github sync +=========== + +.. automodule:: github_sync :members: :show-inheritance: -Correctmap -========== +Exceptions +---------- -.. automodule:: capa.correctmap +.. automodule:: github_sync.exceptions :members: :show-inheritance: -Customrender -============ +Views +----- -.. automodule:: capa.customrender +.. automodule:: github_sync.views :members: :show-inheritance: -Inputtypes -========== +Management +---------- -.. automodule:: capa.inputtypes +.. automodule:: github_sync.management :members: :show-inheritance: -Resposetypes -============ +Tests +----- -.. automodule:: capa.responsetypes - :members: - :show-inheritance: +.. .. automodule:: github_sync.tests +.. :members: +.. :show-inheritance: \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index 555dfd4e13..b9c1deadfc 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -24,17 +24,11 @@ sys.path.insert(0, os.path.join(os.path.abspath('../..'), 'lms', 'djangoapps')) sys.path.insert(0, os.path.join(os.path.abspath('../..'), 'cms', 'djangoapps')) # cms djangoapps sys.path.insert(0, os.path.join(os.path.abspath('../..'), 'common', 'djangoapps')) # common djangoapps +# django configuration - careful here +import os +os.environ['DJANGO_SETTINGS_MODULE'] = 'lms.envs.dev' -# django specific -# import ipdb; ipdb.set_trace() -# Set up the Django settings/environment -# STATIC_URL = '/static/' -# sys.path.insert(0, os.path.join(os.path.abspath('../..'), 'lms', 'envs')) # lms djangoapps -# from django.core.management import setup_environ -# import lms.envs.dev -# import ipdb; ipdb.set_trace() -# setup_environ(lms.envs.dev) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. @@ -268,20 +262,17 @@ intersphinx_mapping = {'http://docs.python.org/': None} # PROJECT_DIR = os.path.join(THIS_DIR, 'relative/path/to/your/project/') # sys.path.append(PROJECT_DIR) + import inspect -import lms.envs.dev -from django.core.management import setup_environ from django.utils.html import strip_tags from django.utils.encoding import force_unicode -setup_environ(lms.envs.dev) - def process_docstring(app, what, name, obj, options, lines): # This causes import errors if left outside the function from django.db import models - from django import forms - from django.forms.models import BaseInlineFormSet + # from django import forms + # from django.forms.models import BaseInlineFormSet # Only look at objects that inherit from Django's base MODEL class if inspect.isclass(obj) and issubclass(obj, models.Model): diff --git a/docs/source/djangoapps-common.rst b/docs/source/djangoapps-common.rst index f83d89f52d..0d67dfd591 100644 --- a/docs/source/djangoapps-common.rst +++ b/docs/source/djangoapps-common.rst @@ -1,54 +1,54 @@ ******************************************* -Capa module +Common ******************************************* -.. module:: capa +.. module:: common.djangoapps -Calc -==== - -.. automodule:: capa.calc - :members: - :show-inheritance: - -Capa_problem -============ - -.. automodule:: capa.capa_problem - :members: - :show-inheritance: - -Checker +Student ======= -.. automodule:: capa.checker +.. automodule:: student :members: :show-inheritance: -Correctmap -========== +Models +------ -.. automodule:: capa.correctmap +.. automodule:: student.models :members: :show-inheritance: -Customrender -============ +Views +----- -.. automodule:: capa.customrender +.. automodule:: student.views :members: :show-inheritance: -Inputtypes -========== +Admin +----- -.. automodule:: capa.inputtypes +.. automodule:: student.admin :members: :show-inheritance: -Resposetypes -============ +Tests +----- -.. automodule:: capa.responsetypes +.. automodule:: student.tests :members: :show-inheritance: + +Management +---------- + +.. automodule:: student.management + :members: + :show-inheritance: + +Migrations +---------- + +.. automodule:: student.migrations + :members: + :show-inheritance: \ No newline at end of file diff --git a/docs/source/lms.rst b/docs/source/lms.rst index ad114a3088..36622114ab 100644 --- a/docs/source/lms.rst +++ b/docs/source/lms.rst @@ -53,6 +53,28 @@ Circuit :members: :show-inheritance: +Models +------ + +.. automodule:: circuit.models + :members: + :show-inheritance: + +Views +----- + +.. automodule:: circuit.views + :members: + :show-inheritance: + +Tests +----- + +.. automodule:: circuit.tests + :members: + :show-inheritance: + + Course_wiki =========== @@ -60,6 +82,27 @@ Course_wiki :members: :show-inheritance: +Course Nav +---------- + +.. .. automodule:: course_wiki.course_nav +.. :members: +.. :show-inheritance: + +Views +----- + +.. automodule:: course_wiki.views + :members: + :show-inheritance: + +Editors +------- + +.. automodule:: course_wiki.editors + :members: + :show-inheritance: + Courseware ========== @@ -67,6 +110,56 @@ Courseware :members: :show-inheritance: +Access +------ + +.. automodule:: courseware.access + :members: + :show-inheritance: + +Admin +----- + +.. automodule:: courseware.admin + :members: + :show-inheritance: + +Courses +------- + +.. automodule:: courseware.courses + :members: + :show-inheritance: + +Grades +------ + +.. automodule:: courseware.grades + :members: + :show-inheritance: + +Models +------ + +.. automodule:: courseware.models + :members: + :show-inheritance: + +Progress +-------- + +.. automodule:: courseware.progress + :members: + :show-inheritance: + +Tabs +---- + +.. automodule:: courseware.tabs + :members: + :show-inheritance: + + Dashboard ========= @@ -74,6 +167,27 @@ Dashboard :members: :show-inheritance: +Models +------ + +.. automodule:: dashboard.models + :members: + :show-inheritance: + +Views +----- + +.. automodule:: dashboard.views + :members: + :show-inheritance: + +Tests +----- + +.. automodule:: dashboard.tests + :members: + :show-inheritance: + Django comment client ===================== @@ -81,6 +195,20 @@ Django comment client :members: :show-inheritance: +Models +------ + +.. automodule:: django_comment_client.models + :members: + :show-inheritance: + +Tests +----- + +.. automodule:: django_comment_client.tests + :members: + :show-inheritance: + Heartbeat ========= @@ -95,6 +223,20 @@ Instructor :members: :show-inheritance: +Views +----- + +.. automodule:: instructor.views + :members: + :show-inheritance: + +Tests +----- + +.. .. automodule:: instructor.tests +.. :members: +.. :show-inheritance: + Lisenses ======== @@ -102,6 +244,27 @@ Lisenses :members: :show-inheritance: +Models +------ + +.. automodule:: licenses.models + :members: + :show-inheritance: + +Views +----- + +.. automodule:: licenses.views + :members: + :show-inheritance: + +Tests +----- + +.. automodule:: licenses.tests + :members: + :show-inheritance: + LMS migration ============= @@ -109,6 +272,13 @@ LMS migration :members: :show-inheritance: +Migration +--------- + +.. automodule:: lms_migration.migrate + :members: + :show-inheritance: + Multicourse =========== @@ -123,6 +293,27 @@ Psychometrics :members: :show-inheritance: +Models +------ + +.. automodule:: psychometrics.models + :members: + :show-inheritance: + +Admin +----- + +.. automodule:: psychometrics.admin + :members: + :show-inheritance: + +Psychoanalyze +------------- + +.. automodule:: psychometrics.psychoanalyze + :members: + :show-inheritance: + Simple wiki =========== @@ -130,6 +321,28 @@ Simple wiki :members: :show-inheritance: +Models +------ + +.. automodule:: simplewiki.models + :members: + :show-inheritance: + +Views +----- + +.. automodule:: simplewiki.views + :members: + :show-inheritance: + +Tests +----- + +.. automodule:: simplewiki.tests + :members: + :show-inheritance: + + Static template view ==================== @@ -137,9 +350,52 @@ Static template view :members: :show-inheritance: +Models +------ + +.. automodule:: static_template_view.models + :members: + :show-inheritance: + +Views +----- + +.. automodule:: static_template_view.views + :members: + :show-inheritance: + +Tests +----- + +.. automodule:: static_template_view.tests + :members: + :show-inheritance: + + Static book =========== .. automodule:: staticbook :members: :show-inheritance: + +Models +------ + +.. automodule:: staticbook.models + :members: + :show-inheritance: + +Views +----- + +.. automodule:: staticbook.views + :members: + :show-inheritance: + +Tests +----- + +.. automodule:: staticbook.tests + :members: + :show-inheritance: From 95960d090159412ebe5adc199a76868a82e3dccb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= Date: Tue, 6 Nov 2012 14:41:15 +0200 Subject: [PATCH 28/29] claning --- docs/source/conf.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index b9c1deadfc..3b1e9dc5b9 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -258,10 +258,6 @@ intersphinx_mapping = {'http://docs.python.org/': None} # from http://djangosnippets.org/snippets/2533/ # autogenerate models definitions -# THIS_DIR = os.path.dirname(__file__) -# PROJECT_DIR = os.path.join(THIS_DIR, 'relative/path/to/your/project/') -# sys.path.append(PROJECT_DIR) - import inspect from django.utils.html import strip_tags @@ -331,4 +327,4 @@ def process_docstring(app, what, name, obj, options, lines): def setup(app): # Register the docstring processor with sphinx - app.connect('autodoc-process-docstring', process_docstring) \ No newline at end of file + app.connect('autodoc-process-docstring', process_docstring) From 1162f6f3195ab714fff2c8c405831ae23f3697cc Mon Sep 17 00:00:00 2001 From: ichuang Date: Tue, 6 Nov 2012 09:29:23 -0500 Subject: [PATCH 29/29] add doc file about use of mongo (by cms+lms) --- doc/mongo.md | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 doc/mongo.md diff --git a/doc/mongo.md b/doc/mongo.md new file mode 100644 index 0000000000..efe3b4494f --- /dev/null +++ b/doc/mongo.md @@ -0,0 +1,145 @@ +# Notes on using mongodb backed LMS and CMS + +These are some random notes for developers, on how things are stored in mongodb, and how to debug mongodb data. + +## Databases + +Two mongodb databases are used: + +- xmodule: stores module definitions and metadata (modulestore) +- xcontent: stores filesystem content, like PDF files + +modulestore documents are stored with an _id which has fields like this: + + {"_id": {"tag":"i4x","org":"HarvardX","course":"CS50x","category":"chapter","name":"Week_1","revision":null}} + +## Document fields + +### Problems + +Here is an example showing the fields available in problem documents: + + { + "_id" : { + "tag" : "i4x", + "org" : "MITx", + "course" : "6.00x", + "category" : "problem", + "name" : "ps03:ps03-Hangman_part_2_The_Game", + "revision" : null + }, + "definition" : { + "data" : " ..." + }, + "metadata" : { + "display_name" : "Hangman Part 2: The Game", + "attempts" : "30", + "title" : "Hangman, Part 2", + "data_dir" : "6.00x", + "type" : "lecture" + } + } + +## Sample interaction with mongodb + +1. "mongo" +2. "use xmodule" +3. "show collections" should give "modulestore" and "system.indexes" +4. 'db.modulestore.find( {"_id.org": "MITx"} )' will produce a list of all MITx course documents +5. 'db.modulestore.find( {"_id.org": "MITx", "_id.category": "problem"} )' will produce a list of all problems in MITx courses + +Example query for finding all files with "image" in the filename: + +- use xcontent +- db.fs.files.find({'filename': /image/ } ) +- db.fs.files.find({'filename': /image/ } ).count() + +## Debugging the mongodb contents + +A convenient tool is http://phpmoadmin.com/ (needs php) + +Under ubuntu, do: + + - apt-get install php5-fpm php-pear + - pecl install mongo + - edit /etc/php5/fpm/php.ini to add "extension=mongo.so" + - /etc/init.d/php5-fpm restart + +and also setup nginx to run php through fastcgi. + +## Backing up mongodb + +- mogodump (dumps all dbs) +- mongodump --collection modulestore --db xmodule (dumps just xmodule/modulestore) +- mongodump -d xmodule -q '{"_id.org": "MITx"}' (dumps just MITx documents in xmodule) +- mongodump -q '{"_id.org": "MITx"}' (dumps all MITx documents) + +## Deleting course content + +Use "remove" instead of "find": + +- db.modulestore.remove( {"_id.course": "8.01greytak"}) + +## Finding useful information from the mongodb modulestore + +- Organizations + + > db.modulestore.distinct( "_id.org") + [ "HarvardX", "MITx", "edX", "edx" ] + +- Courses + + > db.modulestore.distinct( "_id.course") + [ + "CS50x", + "PH207x", + "3.091x", + "6.002x", + "6.00x", + "8.01esg", + "8.01rq_MW", + "8.02teal", + "8.02x", + "edx4edx", + "toy", + "templates" + ] + +- Find a problem which has the word "quantum" in its definition + + db.modulestore.findOne( {"definition.data":/quantum/})n + +- Find Location for all problems with the word "quantum" in its definition + + db.modulestore.find( {"definition.data":/quantum/}, {'_id':1}) + +- Number of problems in each course + + db.runCommand({ + mapreduce: "modulestore", + query: { '_id.category': 'problem' }, + map: function(){ emit(this._id.course, {count:1}); }, + reduce: function(key, values){ + var result = {count:0}; + values.forEach(function(value) { + result.count += value.count; + }); + return result; + }, + out: 'pbyc', + verbose: true + }); + + produces: + + > db.pbyc.find() + { "_id" : "3.091x", "value" : { "count" : 184 } } + { "_id" : "6.002x", "value" : { "count" : 176 } } + { "_id" : "6.00x", "value" : { "count" : 147 } } + { "_id" : "8.01esg", "value" : { "count" : 184 } } + { "_id" : "8.01rq_MW", "value" : { "count" : 73 } } + { "_id" : "8.02teal", "value" : { "count" : 5 } } + { "_id" : "8.02x", "value" : { "count" : 99 } } + { "_id" : "PH207x", "value" : { "count" : 25 } } + { "_id" : "edx4edx", "value" : { "count" : 50 } } + { "_id" : "templates", "value" : { "count" : 11 } }