Commit 417fe21d by Calen Pennington

Enable pure XBlocks, but behind a feature flag

[LMS-226]
[LMS-2013]
parent a6a00431
......@@ -5,6 +5,13 @@ These are notable changes in edx-platform. This is a rolling list of changes,
in roughly chronological order, most recent first. Add your entries at or near
the top. Include a label indicating the component affected.
Common: Add feature flags to allow developer use of pure XBlocks
- ALLOW_ALL_ADVANCED_COMPONENTS disables the hard-coded list of advanced
components in Studio, and allows any xblock to be added as an
advanced component in Studio settings
- XBLOCK_SELECT_FUNCTION allows the insertion of a custom function
to limit loading of XBlocks with (including allowing pure xblocks)
Studio: Add sorting by column to the Files & Uploads page.
See mongo_indexes.md for new indices that should be added.
......
......@@ -9,7 +9,8 @@ from xmodule.modulestore.locator import CourseLocator, BlockUsageLocator, LocalI
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.html_module import HtmlDescriptor
from xmodule.modulestore import inheritance
from xmodule.x_module import XModuleDescriptor
from xmodule.x_module import prefer_xmodules
from xblock.core import XBlock
class TemplateTests(unittest.TestCase):
......@@ -248,9 +249,10 @@ class TemplateTests(unittest.TestCase):
- 'definition':
- '_id' (optional): the usage_id of this. Will generate one if not given one.
"""
class_ = XModuleDescriptor.load_class(
class_ = XBlock.load_class(
json_data.get('category', json_data.get('location', {}).get('category')),
default_class
default_class,
select=prefer_xmodules
)
usage_id = json_data.get('_id', None)
if not '_inherited_settings' in json_data and parent_xblock is not None:
......
......@@ -14,13 +14,14 @@ from xmodule.modulestore.django import modulestore
from xmodule.util.date_utils import get_default_time_display
from xmodule.modulestore.django import loc_mapper
from xmodule.modulestore.locator import BlockUsageLocator
from xmodule.x_module import XModuleDescriptor
from xblock.core import XBlock
from xblock.django.request import webob_to_django_response, django_to_webob_request
from xblock.exceptions import NoSuchHandlerError
from xblock.fields import Scope
from xblock.plugin import PluginMissingError
from xblock.runtime import Mixologist
from xmodule.x_module import prefer_xmodules
from lms.lib.xblock.runtime import unquote_slashes
......@@ -44,12 +45,18 @@ COMPONENT_TYPES = ['discussion', 'html', 'problem', 'video']
OPEN_ENDED_COMPONENT_TYPES = ["combinedopenended", "peergrading"]
NOTE_COMPONENT_TYPES = ['notes']
ADVANCED_COMPONENT_TYPES = [
'annotatable',
'word_cloud',
'graphical_slider_tool',
'lti',
] + OPEN_ENDED_COMPONENT_TYPES + NOTE_COMPONENT_TYPES
if settings.FEATURES.get('ALLOW_ALL_ADVANCED_COMPONENTS'):
ADVANCED_COMPONENT_TYPES = sorted(set(name for name, class_ in XBlock.load_classes()) - set(COMPONENT_TYPES))
else:
ADVANCED_COMPONENT_TYPES = [
'annotatable',
'word_cloud',
'graphical_slider_tool',
'lti',
] + OPEN_ENDED_COMPONENT_TYPES + NOTE_COMPONENT_TYPES
ADVANCED_COMPONENT_CATEGORY = 'advanced'
ADVANCED_COMPONENT_POLICY_KEY = 'advanced_modules'
......@@ -138,7 +145,7 @@ def _load_mixed_class(category):
"""
Load an XBlock by category name, and apply all defined mixins
"""
component_class = XModuleDescriptor.load_class(category)
component_class = XBlock.load_class(category, select=prefer_xmodules)
mixologist = Mixologist(settings.XBLOCK_MIXINS)
return mixologist.mix(component_class)
......
......@@ -9,10 +9,17 @@ from xmodule_modifiers import wrap_xblock
from django.core.exceptions import PermissionDenied
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseBadRequest
from django.views.decorators.http import require_http_methods
from xblock.fields import Scope
from xblock.core import XBlock
from xmodule.modulestore.django import modulestore, loc_mapper
from xmodule.modulestore.inheritance import own_metadata
from xmodule.modulestore.exceptions import ItemNotFoundError, InvalidLocationError
from xmodule.modulestore.inheritance import own_metadata
from xmodule.modulestore.locator import BlockUsageLocator
from xmodule.x_module import prefer_xmodules
from util.json_request import expect_json, JsonResponse
from util.string_utils import str_to_bool
......@@ -23,12 +30,6 @@ from ..utils import get_modulestore
from .access import has_access
from .helpers import _xmodule_recurse
from xmodule.x_module import XModuleDescriptor
from django.views.decorators.http import require_http_methods
from xmodule.modulestore.locator import BlockUsageLocator
from student.models import CourseEnrollment
from django.http import HttpResponseBadRequest
from xblock.fields import Scope
from preview import handler_prefix, get_preview_html
from edxmako.shortcuts import render_to_response, render_to_string
from models.settings.course_grading import CourseGradingModel
......@@ -260,7 +261,7 @@ def _create_item(request):
data = None
template_id = request.json.get('boilerplate')
if template_id is not None:
clz = XModuleDescriptor.load_class(category)
clz = XBlock.load_class(category, select=prefer_xmodules)
if clz is not None:
template = clz.get_template(template_id)
if template is not None:
......
......@@ -31,7 +31,7 @@ from path import path
from lms.lib.xblock.mixin import LmsBlockMixin
from cms.lib.xblock.mixin import CmsBlockMixin
from xmodule.modulestore.inheritance import InheritanceMixin
from xmodule.x_module import XModuleMixin
from xmodule.x_module import XModuleMixin, only_xmodules
from dealer.git import git
############################ FEATURE CONFIGURATION #############################
......@@ -62,6 +62,10 @@ FEATURES = {
# If set to True, new Studio users won't be able to author courses unless
# edX has explicitly added them to the course creator group.
'ENABLE_CREATOR_GROUP': False,
# If set to True, Studio won't restrict the set of advanced components
# to just those pre-approved by edX
'ALLOW_ALL_ADVANCED_COMPONENTS': False,
}
ENABLE_JASMINE = False
......@@ -178,6 +182,15 @@ MIDDLEWARE_CLASSES = (
# once the responsibility of XBlock creation is moved out of modulestore - cpennington
XBLOCK_MIXINS = (LmsBlockMixin, CmsBlockMixin, InheritanceMixin, XModuleMixin)
# Only allow XModules in Studio
XBLOCK_SELECT_FUNCTION = only_xmodules
# Use the following lines to allow any xblock in Studio,
# either by uncommenting them here, or adding them to your private.py
# You should also enable the ALLOW_ALL_ADVANCED_COMPONENTS feature flag, so that
# xblocks can be added via advanced settings
# from xmodule.x_module import prefer_xmodules
# XBLOCK_SELECT_FUNCTION = prefer_xmodules
############################ SIGNAL HANDLERS ################################
# This is imported to register the exception signal handling that logs exceptions
......
......@@ -430,7 +430,7 @@ class ModuleStoreReadBase(ModuleStoreRead):
self,
doc_store_config=None, # ignore if passed up
metadata_inheritance_cache_subsystem=None, request_cache=None,
modulestore_update_signal=None, xblock_mixins=(),
modulestore_update_signal=None, xblock_mixins=(), xblock_select=None,
# temporary parms to enable backward compatibility. remove once all envs migrated
db=None, collection=None, host=None, port=None, tz_aware=True, user=None, password=None
):
......@@ -442,6 +442,7 @@ class ModuleStoreReadBase(ModuleStoreRead):
self.modulestore_update_signal = modulestore_update_signal
self.request_cache = request_cache
self.xblock_mixins = xblock_mixins
self.xblock_select = xblock_select
def _get_errorlog(self, location):
"""
......
......@@ -66,6 +66,7 @@ def create_modulestore_instance(engine, doc_store_config, options):
request_cache=request_cache,
modulestore_update_signal=Signal(providing_args=['modulestore', 'course_id', 'location']),
xblock_mixins=getattr(settings, 'XBLOCK_MIXINS', ()),
xblock_select=getattr(settings, 'XBLOCK_SELECT_FUNCTION', None),
doc_store_config=doc_store_config,
**_options
)
......@@ -83,7 +84,7 @@ def get_default_store_name_for_current_request():
# get mapping information which is defined in configurations
mappings = getattr(settings, 'HOSTNAME_MODULESTORE_DEFAULT_MAPPINGS', None)
# compare hostname against the regex expressions set of mappings
# which will tell us which store name to use
if hostname and mappings:
......
......@@ -25,7 +25,6 @@ from path import path
from importlib import import_module
from xmodule.errortracker import null_error_tracker, exc_info_to_str
from xmodule.mako_module import MakoDescriptorSystem
from xmodule.x_module import XModuleDescriptor
from xmodule.error_module import ErrorDescriptor
from xblock.runtime import DbModel
from xblock.exceptions import InvalidScopeError
......@@ -173,10 +172,8 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
# load the module and apply the inherited metadata
try:
category = json_data['location']['category']
class_ = XModuleDescriptor.load_class(
category,
self.default_class
)
class_ = self.load_block_type(category)
definition = json_data.get('definition', {})
metadata = json_data.get('metadata', {})
for old_name, new_name in getattr(class_, 'metadata_translations', {}).items():
......@@ -506,6 +503,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
render_template=self.render_template,
cached_metadata=cached_metadata,
mixins=self.xblock_mixins,
select=self.xblock_select,
)
return system.load_item(item['location'])
......@@ -627,8 +625,9 @@ class MongoModuleStore(ModuleStoreWriteBase):
render_template=self.render_template,
cached_metadata={},
mixins=self.xblock_mixins,
select=self.xblock_select,
)
xblock_class = XModuleDescriptor.load_class(location.category, self.default_class)
xblock_class = system.load_block_type(location.category)
if definition_data is None:
if hasattr(xblock_class, 'data') and xblock_class.data.default is not None:
definition_data = xblock_class.data.default
......
import sys
import logging
from xmodule.mako_module import MakoDescriptorSystem
from xmodule.x_module import XModuleDescriptor
from xmodule.modulestore.locator import BlockUsageLocator, LocalId
from xmodule.error_module import ErrorDescriptor
from xmodule.errortracker import exc_info_to_str
......@@ -62,10 +61,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
if json_data is None:
raise ItemNotFoundError(block_id)
class_ = XModuleDescriptor.load_class(
json_data.get('category'),
self.default_class
)
class_ = self.load_block_type(json_data.get('category'))
return self.xblock_from_json(class_, block_id, json_data, course_entry_override)
# xblock's runtime does not always pass enough contextual information to figure out
......
......@@ -42,7 +42,7 @@ Representation:
*** 'edited_by': user_id whose edit caused this version of the definition,
*** 'edited_on': datetime of the change causing this version
*** 'previous_version': the definition_id of the previous version of this definition
*** 'original_version': definition_id of the root of the previous version relation on this
*** 'original_version': definition_id of the root of the previous version relation on this
definition. Acts as a pseudo-object identifier.
"""
import threading
......@@ -56,7 +56,7 @@ import copy
from pytz import UTC
from xmodule.errortracker import null_error_tracker
from xmodule.x_module import XModuleDescriptor
from xmodule.x_module import XModuleDescriptor, prefer_xmodules
from xmodule.modulestore.locator import BlockUsageLocator, DefinitionLocator, CourseLocator, VersionTree, LocalId
from xmodule.modulestore.exceptions import InsufficientSpecificationError, VersionConflictError, DuplicateItemError
from xmodule.modulestore import inheritance, ModuleStoreWriteBase, Location, SPLIT_MONGO_MODULESTORE_TYPE
......@@ -68,6 +68,7 @@ from xblock.fields import Scope
from xblock.runtime import Mixologist
from bson.objectid import ObjectId
from xmodule.modulestore.split_mongo.mongo_connection import MongoConnection
from xblock.core import XBlock
log = logging.getLogger(__name__)
#==============================================================================
......@@ -184,7 +185,8 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
error_tracker=self.error_tracker,
render_template=self.render_template,
resources_fs=None,
mixins=self.xblock_mixins
mixins=self.xblock_mixins,
select=self.xblock_select,
)
self._add_cache(course_entry['structure']['_id'], system)
self.cache_items(system, block_ids, depth, lazy)
......@@ -1471,7 +1473,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
"""
if fields is None:
return {}
cls = self.mixologist.mix(XModuleDescriptor.load_class(category))
cls = self.mixologist.mix(XBlock.load_class(category, select=prefer_xmodules))
result = collections.defaultdict(dict)
for field_name, value in fields.iteritems():
field = getattr(cls, field_name)
......@@ -1581,7 +1583,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
destination_block['edit_info']['edited_by'] = user_id
else:
destination_block = self._new_block(
user_id, new_block['category'],
user_id, new_block['category'],
self._filter_blacklist(copy.copy(new_block['fields']), blacklist),
new_block['definition'],
new_block['edit_info']['update_version']
......
......@@ -6,7 +6,8 @@ from uuid import uuid4
from pytz import UTC
from xmodule.modulestore import Location
from xmodule.x_module import XModuleDescriptor
from xmodule.x_module import prefer_xmodules
from xblock.core import XBlock
class Dummy(object):
......@@ -144,7 +145,7 @@ class ItemFactory(XModuleFactory):
if 'boilerplate' in kwargs:
template_id = kwargs.pop('boilerplate')
clz = XModuleDescriptor.load_class(category)
clz = XBlock.load_class(category, select=prefer_xmodules)
template = clz.get_template(template_id)
assert template is not None
metadata.update(template.get('metadata', {}))
......
......@@ -17,7 +17,7 @@ from xmodule.error_module import ErrorDescriptor
from xmodule.errortracker import make_error_tracker, exc_info_to_str
from xmodule.course_module import CourseDescriptor
from xmodule.mako_module import MakoDescriptorSystem
from xmodule.x_module import XMLParsingSystem, XModuleDescriptor
from xmodule.x_module import XMLParsingSystem, prefer_xmodules
from xmodule.html_module import HtmlDescriptor
from xblock.core import XBlock
......@@ -238,7 +238,7 @@ def create_block_from_xml(xml_data, system, org=None, course=None, default_class
"""
node = etree.fromstring(xml_data)
raw_class = XModuleDescriptor.load_class(node.tag, default_class)
raw_class = XBlock.load_class(node.tag, default_class, select=prefer_xmodules)
xblock_class = system.mixologist.mix(raw_class)
# leave next line commented out - useful for low-level debugging
......@@ -460,6 +460,7 @@ class XMLModuleStore(ModuleStoreReadBase):
load_error_modules=self.load_error_modules,
policy=policy,
mixins=self.xblock_mixins,
select=self.xblock_select,
)
course_descriptor = system.process_xml(etree.tostring(course_data, encoding='unicode'))
......
......@@ -132,6 +132,7 @@ def import_from_xml(
course_dirs=course_dirs,
load_error_modules=load_error_modules,
xblock_mixins=store.xblock_mixins,
xblock_select=store.xblock_select,
)
# NOTE: the XmlModuleStore does not implement get_items()
......
......@@ -12,7 +12,7 @@ samples.
import logging
from collections import defaultdict
from .x_module import XModuleDescriptor
from xblock.core import XBlock
log = logging.getLogger(__name__)
......@@ -23,7 +23,9 @@ def all_templates():
"""
# TODO use memcache to memoize w/ expiration
templates = defaultdict(list)
for category, descriptor in XModuleDescriptor.load_classes():
for category, descriptor in XBlock.load_classes():
if not hasattr(descriptor, 'templates'):
continue
templates[category] = descriptor.templates()
return templates
......@@ -13,7 +13,7 @@ from xmodule.xml_module import is_pointer_tag
from xmodule.modulestore import Location
from xmodule.modulestore.xml import ImportSystem, XMLModuleStore
from xmodule.modulestore.inheritance import compute_inherited_metadata
from xmodule.x_module import XModuleMixin
from xmodule.x_module import XModuleMixin, only_xmodules
from xmodule.fields import Date
from xmodule.tests import DATA_DIR
from xmodule.modulestore.inheritance import InheritanceMixin
......@@ -61,7 +61,12 @@ class BaseCourseTestCase(unittest.TestCase):
"""Get a test course by directory name. If there's more than one, error."""
print("Importing {0}".format(name))
modulestore = XMLModuleStore(DATA_DIR, course_dirs=[name], xblock_mixins=(InheritanceMixin,))
modulestore = XMLModuleStore(
DATA_DIR,
course_dirs=[name],
xblock_mixins=(InheritanceMixin,),
xblock_select=only_xmodules,
)
courses = modulestore.get_courses()
self.assertEquals(len(courses), 1)
return courses[0]
......
......@@ -25,6 +25,7 @@ class InMemorySystem(XMLParsingSystem, MakoDescriptorSystem): # pylint: disable
error_tracker=Mock(),
resources_fs=xml_import_data.filesystem,
mixins=xml_import_data.xblock_mixins,
select=xml_import_data.xblock_select,
render_template=lambda template, context: pprint.pformat((template, context))
)
......
......@@ -9,6 +9,7 @@ from factory import Factory, lazy_attribute, post_generation, Sequence
from lxml import etree
from xmodule.modulestore.inheritance import InheritanceMixin
from xmodule.x_module import only_xmodules
class XmlImportData(object):
......@@ -19,7 +20,7 @@ class XmlImportData(object):
def __init__(self, xml_node, xml=None, org=None, course=None,
default_class=None, policy=None,
filesystem=None, parent=None,
xblock_mixins=()):
xblock_mixins=(), xblock_select=None):
self._xml_node = xml_node
self._xml_string = xml
......@@ -28,6 +29,7 @@ class XmlImportData(object):
self.default_class = default_class
self.filesystem = filesystem
self.xblock_mixins = xblock_mixins
self.xblock_select = xblock_select
self.parent = parent
if policy is None:
......@@ -47,7 +49,8 @@ class XmlImportData(object):
return u"XmlImportData{!r}".format((
self._xml_node, self._xml_string, self.org,
self.course, self.default_class, self.policy,
self.filesystem, self.parent, self.xblock_mixins
self.filesystem, self.parent, self.xblock_mixins,
self.xblock_select,
))
......@@ -65,6 +68,7 @@ class XmlImportFactory(Factory):
filesystem = MemoryFS()
xblock_mixins = (InheritanceMixin,)
xblock_select = only_xmodules
url_name = Sequence(str)
attribs = {}
policy = {}
......
......@@ -15,9 +15,10 @@ from xmodule.modulestore.exceptions import ItemNotFoundError, InsufficientSpecif
from xblock.core import XBlock
from xblock.fields import Scope, Integer, Float, List, XBlockMixin, String
from xmodule.fields import RelativeTime
from xblock.fragment import Fragment
from xblock.plugin import default_select
from xblock.runtime import Runtime
from xmodule.fields import RelativeTime
from xmodule.errortracker import exc_info_to_str
from xmodule.modulestore.locator import BlockUsageLocator
......@@ -564,6 +565,22 @@ class ResourceTemplates(object):
return None
def prefer_xmodules(identifier, entry_points):
"""Prefer entry_points from the xmodule package"""
from_xmodule = [entry_point for entry_point in entry_points if entry_point.dist.key == 'xmodule']
if from_xmodule:
return default_select(identifier, from_xmodule)
else:
return default_select(identifier, entry_points)
def only_xmodules(identifier, entry_points):
"""Only use entry_points that are supplied by the xmodule package"""
from_xmodule = [entry_point for entry_point in entry_points if entry_point.dist.key == 'xmodule']
return default_select(identifier, from_xmodule)
@XBlock.needs("i18n")
class XModuleDescriptor(XModuleMixin, HTMLSnippet, ResourceTemplates, XBlock):
"""
......
......@@ -11,7 +11,9 @@ from django.contrib.auth.models import Group, AnonymousUser
from xmodule.course_module import CourseDescriptor
from xmodule.error_module import ErrorDescriptor
from xmodule.modulestore import Location
from xmodule.x_module import XModule, XModuleDescriptor
from xmodule.x_module import XModule
from xblock.core import XBlock
from student.models import CourseEnrollmentAllowed
from external_auth.models import ExternalAuthMap
......@@ -74,13 +76,13 @@ def has_access(user, obj, action, course_context=None):
if isinstance(obj, ErrorDescriptor):
return _has_access_error_desc(user, obj, action, course_context)
# NOTE: any descriptor access checkers need to go above this
if isinstance(obj, XModuleDescriptor):
return _has_access_descriptor(user, obj, action, course_context)
if isinstance(obj, XModule):
return _has_access_xmodule(user, obj, action, course_context)
# NOTE: any descriptor access checkers need to go above this
if isinstance(obj, XBlock):
return _has_access_descriptor(user, obj, action, course_context)
if isinstance(obj, Location):
return _has_access_location(user, obj, action, course_context)
......@@ -338,7 +340,7 @@ def _dispatch(table, action, user, obj):
debug("%s user %s, object %s, action %s",
'ALLOWED' if result else 'DENIED',
user,
obj.location.url() if isinstance(obj, XModuleDescriptor) else str(obj)[:60],
obj.location.url() if isinstance(obj, XBlock) else str(obj)[:60],
action)
return result
......
......@@ -27,6 +27,7 @@ from psychometrics.psychoanalyze import make_psychometrics_data_update_handler
from student.models import anonymous_id_for_user, user_by_anonymous_id
from util.json_request import JsonResponse
from util.sandboxing import can_execute_unsafe_code
from xblock.core import XBlock
from xblock.fields import Scope
from xblock.runtime import DbModel, KeyValueStore
from xblock.exceptions import NoSuchHandlerError
......@@ -38,6 +39,7 @@ from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule_modifiers import replace_course_urls, replace_jump_to_id_urls, replace_static_urls, add_histogram, wrap_xblock
from xmodule.lti_module import LTIModule
from xmodule.x_module import XModuleDescriptor
log = logging.getLogger(__name__)
......@@ -373,7 +375,9 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours
# while giving selected modules a per-course anonymized id.
# As we have the time to manually test more modules, we can add to the list
# of modules that get the per-course anonymized id.
if issubclass(getattr(descriptor, 'module_class', None), LTIModule):
is_pure_xblock = isinstance(descriptor, XBlock) and not isinstance(descriptor, XModuleDescriptor)
is_lti_module = not is_pure_xblock and issubclass(descriptor.module_class, LTIModule)
if is_pure_xblock or is_lti_module:
anonymous_student_id = anonymous_id_for_user(user, course_id)
else:
anonymous_student_id = anonymous_id_for_user(user, '')
......
......@@ -34,6 +34,7 @@ class Command(BaseCommand):
default_class='xmodule.hidden_module.HiddenDescriptor',
load_error_modules=True,
xblock_mixins=settings.XBLOCK_MIXINS,
xblock_select=settings.XBLOCK_SELECT_FUNCTION,
)
export_dir = path(args[0])
......
......@@ -34,7 +34,7 @@ DOC_STORE_CONFIG = {
}
modulestore_options = {
'default_class': 'xmodule.raw_module.RawDescriptor',
'default_class': 'xmodule.hidden_module.HiddenDescriptor',
'fs_root': TEST_ROOT / "data",
'render_template': 'edxmako.shortcuts.render_to_string',
}
......
......@@ -23,7 +23,7 @@ FEATURES['ENABLE_LMS_MIGRATION'] = False
META_UNIVERSITIES = {}
modulestore_options = {
'default_class': 'xmodule.raw_module.RawDescriptor',
'default_class': 'xmodule.hidden_module.HiddenDescriptor',
'fs_root': DATA_DIR,
'render_template': 'edxmako.shortcuts.render_to_string',
}
......
......@@ -31,7 +31,7 @@ MODULESTORE = {
'collection': 'modulestore',
},
'OPTIONS': {
'default_class': 'xmodule.raw_module.RawDescriptor',
'default_class': 'xmodule.hidden_module.HiddenDescriptor',
'fs_root': DATA_DIR,
'render_template': 'edxmako.shortcuts.render_to_string',
}
......
......@@ -32,7 +32,7 @@ from .discussionsettings import *
from lms.lib.xblock.mixin import LmsBlockMixin
from xmodule.modulestore.inheritance import InheritanceMixin
from xmodule.x_module import XModuleMixin
from xmodule.x_module import XModuleMixin, only_xmodules
################################### FEATURES ###################################
# The display name of the platform to be used in templates/emails/etc.
......@@ -406,6 +406,14 @@ INIT_MODULESTORE_ON_STARTUP = True
# once the responsibility of XBlock creation is moved out of modulestore - cpennington
XBLOCK_MIXINS = (LmsBlockMixin, InheritanceMixin, XModuleMixin)
# Only allow XModules in the LMS
XBLOCK_SELECT_FUNCTION = only_xmodules
# Use the following lines to allow any xblock in the LMS,
# either by uncommenting them here, or adding them to your private.py
# from xmodule.x_module import prefer_xmodules
# XBLOCK_SELECT_FUNCTION = prefer_xmodules
#################### Python sandbox ############################################
CODE_JAIL = {
......
......@@ -19,7 +19,7 @@ MODULESTORE = {
'collection': 'modulestore',
},
'OPTIONS': {
'default_class': 'xmodule.raw_module.RawDescriptor',
'default_class': 'xmodule.hidden_module.HiddenDescriptor',
'fs_root': GITHUB_REPO_ROOT,
'render_template': 'edxmako.shortcuts.render_to_string',
}
......
......@@ -15,7 +15,7 @@
-e git+https://github.com/eventbrite/zendesk.git@d53fe0e81b623f084e91776bcf6369f8b7b63879#egg=zendesk
# Our libraries:
-e git+https://github.com/edx/XBlock.git@2a1efc8a413cc140d48f33fa839143ffcbd21d83#egg=XBlock
-e git+https://github.com/edx/XBlock.git@cd77808aadd3ea1c2027ca8c0aa5624d8ccccc52#egg=XBlock
-e git+https://github.com/edx/codejail.git@e3d98f9455#egg=codejail
-e git+https://github.com/edx/diff-cover.git@v0.2.6#egg=diff_cover
-e git+https://github.com/edx/js-test-tool.git@v0.1.5#egg=js_test_tool
......
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