Commit f0acda19 by Xavier Antoviaque

Merge pull request #46 from dragonfi/opaque-keys

Move to use opaque keys
parents eb76233b 7e54dd78
...@@ -31,7 +31,7 @@ from xblock.fragment import Fragment ...@@ -31,7 +31,7 @@ from xblock.fragment import Fragment
from .light_children import LightChild, Boolean, Scope, String, Integer from .light_children import LightChild, Boolean, Scope, String, Integer
from .models import Answer from .models import Answer
from .utils import render_template from .utils import render_template, serialize_opaque_key
# Globals ########################################################### # Globals ###########################################################
...@@ -137,11 +137,11 @@ class AnswerBlock(LightChild): ...@@ -137,11 +137,11 @@ class AnswerBlock(LightChild):
name = self.name name = self.name
# Consistency check - we should have a name by now # Consistency check - we should have a name by now
if not name: if not name:
raise ValueError, 'AnswerBlock.name field need to be set to a non-null/empty value' raise ValueError('AnswerBlock.name field need to be set to a non-null/empty value')
# TODO: Why do we need to use `xmodule_runtime` and not `runtime`? # TODO: Why do we need to use `xmodule_runtime` and not `runtime`?
student_id = self.xmodule_runtime.anonymous_student_id student_id = self.xmodule_runtime.anonymous_student_id
course_id = self.xmodule_runtime.course_id course_id = serialize_opaque_key(self.xmodule_runtime.course_id)
answer_data, created = Answer.objects.get_or_create( answer_data, created = Answer.objects.get_or_create(
student_id=student_id, student_id=student_id,
......
...@@ -31,7 +31,7 @@ from xblock.core import XBlock ...@@ -31,7 +31,7 @@ from xblock.core import XBlock
from xblock.fragment import Fragment from xblock.fragment import Fragment
from .models import Answer from .models import Answer
from .utils import list2csv, render_template from .utils import list2csv, render_template, serialize_opaque_key
# Globals ########################################################### # Globals ###########################################################
...@@ -70,7 +70,7 @@ class MentoringDataExportBlock(XBlock): ...@@ -70,7 +70,7 @@ class MentoringDataExportBlock(XBlock):
return response return response
def get_csv(self): def get_csv(self):
course_id = self.xmodule_runtime.course_id course_id = serialize_opaque_key(self.xmodule_runtime.course_id)
answers = Answer.objects.filter(course_id=course_id).order_by('student_id', 'name') answers = Answer.objects.filter(course_id=course_id).order_by('student_id', 'name')
answers_names = answers.values_list('name', flat=True).distinct().order_by('name') answers_names = answers.values_list('name', flat=True).distinct().order_by('name')
...@@ -96,4 +96,3 @@ class MentoringDataExportBlock(XBlock): ...@@ -96,4 +96,3 @@ class MentoringDataExportBlock(XBlock):
if row: if row:
yield list2csv(row) yield list2csv(row)
...@@ -44,9 +44,9 @@ try: ...@@ -44,9 +44,9 @@ try:
from xmodule_modifiers import replace_jump_to_id_urls from xmodule_modifiers import replace_jump_to_id_urls
except: except:
# TODO-WORKBENCH-WORKAROUND: To allow to load from the workbench # TODO-WORKBENCH-WORKAROUND: To allow to load from the workbench
replace_jump_to_id_urls = lambda a,b,c,d,frag,f: frag replace_jump_to_id_urls = lambda a, b, c, d, frag, f: frag
from .utils import XBlockWithChildrenFragmentsMixin from .utils import serialize_opaque_key, XBlockWithChildrenFragmentsMixin
# Globals ########################################################### # Globals ###########################################################
...@@ -142,7 +142,7 @@ class LightChildrenMixin(XBlockWithChildrenFragmentsMixin): ...@@ -142,7 +142,7 @@ class LightChildrenMixin(XBlockWithChildrenFragmentsMixin):
frag = getattr(child, view_name)(context) frag = getattr(child, view_name)(context)
frag.content = u'<div class="xblock-light-child" name="{}" data-type="{}">{}</div>'.format( frag.content = u'<div class="xblock-light-child" name="{}" data-type="{}">{}</div>'.format(
child.name, child.__class__.__name__, frag.content) child.name, child.__class__.__name__, frag.content)
return frag return frag
def get_children_fragment(self, context, view_name='student_view', instance_of=None, def get_children_fragment(self, context, view_name='student_view', instance_of=None,
...@@ -188,7 +188,7 @@ class XBlockWithLightChildren(LightChildrenMixin, XBlock): ...@@ -188,7 +188,7 @@ class XBlockWithLightChildren(LightChildrenMixin, XBlock):
""" """
# TODO: Why do we need to use `xmodule_runtime` and not `runtime`? # TODO: Why do we need to use `xmodule_runtime` and not `runtime`?
try: try:
course_id = self.xmodule_runtime.course_id course_id = serialize_opaque_key(self.xmodule_runtime.course_id)
except AttributeError: except AttributeError:
# TODO-WORKBENCH-WORKAROUND: To allow to load from the workbench # TODO-WORKBENCH-WORKAROUND: To allow to load from the workbench
course_id = 'sample-course' course_id = 'sample-course'
...@@ -298,10 +298,10 @@ class LightChild(Plugin, LightChildrenMixin): ...@@ -298,10 +298,10 @@ class LightChild(Plugin, LightChildrenMixin):
name = self.name name = self.name
if not name: if not name:
raise ValueError, 'LightChild.name field need to be set to a non-null/empty value' raise ValueError('LightChild.name field need to be set to a non-null/empty value')
student_id = self.xmodule_runtime.anonymous_student_id student_id = self.xmodule_runtime.anonymous_student_id
course_id = self.xmodule_runtime.course_id course_id = serialize_opaque_key(self.xmodule_runtime.course_id)
url_name = "%s-%s" % (self.xblock_container.url_name, name) url_name = "%s-%s" % (self.xblock_container.url_name, name)
lightchild_data, created = LightChildModel.objects.get_or_create( lightchild_data, created = LightChildModel.objects.get_or_create(
...@@ -349,7 +349,7 @@ class Integer(LightChildField): ...@@ -349,7 +349,7 @@ class Integer(LightChildField):
def __set__(self, instance, value): def __set__(self, instance, value):
try: try:
self.data[instance] = int(value) self.data[instance] = int(value)
except (TypeError, ValueError): # not an integer except (TypeError, ValueError): # not an integer
self.data[instance] = 0 self.data[instance] = 0
......
...@@ -47,6 +47,7 @@ def load_resource(resource_path): ...@@ -47,6 +47,7 @@ def load_resource(resource_path):
resource_content = pkg_resources.resource_string(__name__, resource_path) resource_content = pkg_resources.resource_string(__name__, resource_path)
return unicode(resource_content) return unicode(resource_content)
def render_template(template_path, context={}): def render_template(template_path, context={}):
""" """
Evaluate a template by resource path, applying the provided context Evaluate a template by resource path, applying the provided context
...@@ -55,6 +56,7 @@ def render_template(template_path, context={}): ...@@ -55,6 +56,7 @@ def render_template(template_path, context={}):
template = Template(template_str) template = Template(template_str)
return template.render(Context(context)) return template.render(Context(context))
def list2csv(row): def list2csv(row):
""" """
Convert a list to a CSV string (single row) Convert a list to a CSV string (single row)
...@@ -65,6 +67,7 @@ def list2csv(row): ...@@ -65,6 +67,7 @@ def list2csv(row):
f.seek(0) f.seek(0)
return f.read() return f.read()
def get_scenarios_from_path(scenarios_path, include_identifier=False): def get_scenarios_from_path(scenarios_path, include_identifier=False):
""" """
Returns an array of (title, xmlcontent) from files contained in a specified directory, Returns an array of (title, xmlcontent) from files contained in a specified directory,
...@@ -88,6 +91,7 @@ def get_scenarios_from_path(scenarios_path, include_identifier=False): ...@@ -88,6 +91,7 @@ def get_scenarios_from_path(scenarios_path, include_identifier=False):
return scenarios return scenarios
def load_scenarios_from_path(scenarios_path): def load_scenarios_from_path(scenarios_path):
""" """
Load all xml files contained in a specified directory, as workbench scenarios Load all xml files contained in a specified directory, as workbench scenarios
...@@ -95,6 +99,29 @@ def load_scenarios_from_path(scenarios_path): ...@@ -95,6 +99,29 @@ def load_scenarios_from_path(scenarios_path):
return get_scenarios_from_path(scenarios_path, include_identifier=True) return get_scenarios_from_path(scenarios_path, include_identifier=True)
def serialize_opaque_key(key):
"""
Gracefully handle opaque keys, both before and after the transition.
https://github.com/edx/edx-platform/wiki/Opaque-Keys
From https://github.com/edx/edx-ora2/pull/330
Currently uses `to_deprecated_string()` to ensure that new keys
are backwards-compatible with keys we store in ORA2 database models.
Args:
key (unicode or OpaqueKey subclass): The key to serialize.
Returns:
unicode
"""
if hasattr(key, 'to_deprecated_string'):
return key.to_deprecated_string()
else:
return unicode(key)
# Classes ########################################################### # Classes ###########################################################
class XBlockWithChildrenFragmentsMixin(object): class XBlockWithChildrenFragmentsMixin(object):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment