diff --git a/cms/djangoapps/contentstore/views/preview.py b/cms/djangoapps/contentstore/views/preview.py index 92cba7a16e..5689ef558a 100644 --- a/cms/djangoapps/contentstore/views/preview.py +++ b/cms/djangoapps/contentstore/views/preview.py @@ -188,7 +188,7 @@ def _preview_module_system(request, descriptor, field_data): mako_service = MakoService(namespace_prefix='lms.') if settings.FEATURES.get("LICENSING", False): # stick the license wrapper in front - wrappers.insert(0, wrap_with_license) + wrappers.insert(0, partial(wrap_with_license, mako_service=mako_service)) return PreviewModuleSystem( static_url=settings.STATIC_URL, diff --git a/cms/lib/xblock/authoring_mixin.py b/cms/lib/xblock/authoring_mixin.py index 39f8f10628..342c5ff054 100644 --- a/cms/lib/xblock/authoring_mixin.py +++ b/cms/lib/xblock/authoring_mixin.py @@ -39,7 +39,7 @@ class AuthoringMixin(XBlockMixin): """ fragment = Fragment() from cms.djangoapps.contentstore.utils import reverse_course_url - fragment.add_content(self.system.render_template('visibility_editor.html', { + fragment.add_content(self.runtime.service(self, 'mako').render_template('visibility_editor.html', { 'xblock': self, 'manage_groups_url': reverse_course_url('group_configurations_list_handler', self.location.course_key), })) diff --git a/common/lib/xmodule/xmodule/annotatable_module.py b/common/lib/xmodule/xmodule/annotatable_module.py index 1c7a80122b..e07f81231d 100644 --- a/common/lib/xmodule/xmodule/annotatable_module.py +++ b/common/lib/xmodule/xmodule/annotatable_module.py @@ -6,6 +6,7 @@ import textwrap from lxml import etree from pkg_resources import resource_string from web_fragments.fragment import Fragment +from xblock.core import XBlock from xblock.fields import Scope, String from openedx.core.djangolib.markup import HTML, Text @@ -29,6 +30,7 @@ log = logging.getLogger(__name__) _ = lambda text: text +@XBlock.needs('mako') class AnnotatableBlock( RawMixin, XmlMixin, @@ -201,7 +203,7 @@ class AnnotatableBlock( 'content_html': self._render_content() } - return self.system.render_template('annotatable.html', context) + return self.runtime.service(self, 'mako').render_template('annotatable.html', context) def student_view(self, context): # lint-amnesty, pylint: disable=unused-argument """ @@ -219,7 +221,7 @@ class AnnotatableBlock( Return the studio view. """ fragment = Fragment( - self.system.render_template(self.mako_template, self.get_context()) + self.runtime.service(self, 'mako').render_template(self.mako_template, self.get_context()) ) add_webpack_to_fragment(fragment, 'AnnotatableBlockStudio') shim_xmodule_js(fragment, self.studio_js_module_name) diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index 25a133d19e..26a42d59d6 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -120,6 +120,7 @@ class Randomization(String): @XBlock.needs('user') @XBlock.needs('i18n') +@XBlock.needs('mako') @XBlock.wants('call_to_action') class ProblemBlock( ScorableXBlockMixin, @@ -392,7 +393,7 @@ class ProblemBlock( Return the studio view. """ fragment = Fragment( - self.system.render_template(self.mako_template, self.get_context()) + self.runtime.service(self, 'mako').render_template(self.mako_template, self.get_context()) ) add_webpack_to_fragment(fragment, 'ProblemBlockStudio') shim_xmodule_js(fragment, 'MarkdownEditingDescriptor') @@ -821,7 +822,7 @@ class ProblemBlock( filestore=self.runtime.filestore, i18n=self.runtime.service(self, "i18n"), node_path=self.runtime.node_path, - render_template=self.runtime.render_template, + render_template=self.runtime.service(self, 'mako').render_template, seed=seed, # Why do we do this if we have self.seed? STATIC_URL=self.runtime.STATIC_URL, xqueue=self.runtime.xqueue, @@ -915,7 +916,7 @@ class ProblemBlock( """ curr_score, total_possible = self.get_display_progress() - return self.runtime.render_template('problem_ajax.html', { + return self.runtime.service(self, 'mako').render_template('problem_ajax.html', { 'element_id': self.location.html_id(), 'id': str(self.location), 'ajax_url': self.ajax_url, @@ -1263,7 +1264,7 @@ class ProblemBlock( 'submit_disabled_cta': submit_disabled_ctas[0] if submit_disabled_ctas else None, } - html = self.runtime.render_template('problem.html', context) + html = self.runtime.service(self, 'mako').render_template('problem.html', context) if encapsulate: html = HTML('
{html}
').format( @@ -1573,7 +1574,7 @@ class ProblemBlock( return { 'answers': new_answers, - 'correct_status_html': self.runtime.render_template( + 'correct_status_html': self.runtime.service(self, 'mako').render_template( 'status_span.html', {'status': Status('correct', self.runtime.service(self, "i18n").ugettext)} ) diff --git a/common/lib/xmodule/xmodule/conditional_module.py b/common/lib/xmodule/xmodule/conditional_module.py index 8a2d50c63b..3605f36bf8 100644 --- a/common/lib/xmodule/xmodule/conditional_module.py +++ b/common/lib/xmodule/xmodule/conditional_module.py @@ -11,6 +11,7 @@ from lxml import etree from opaque_keys.edx.locator import BlockUsageLocator from pkg_resources import resource_string from web_fragments.fragment import Fragment +from xblock.core import XBlock from xblock.fields import ReferenceList, Scope, String from openedx.core.djangolib.markup import HTML, Text @@ -38,6 +39,7 @@ log = logging.getLogger('edx.' + __name__) _ = lambda text: text +@XBlock.needs('mako') class ConditionalBlock( SequenceMixin, MakoTemplateBlockBase, @@ -245,7 +247,7 @@ class ConditionalBlock( def get_html(self): required_html_ids = [descriptor.location.html_id() for descriptor in self.get_required_blocks] - return self.system.render_template('conditional_ajax.html', { + return self.runtime.service(self, 'mako').render_template('conditional_ajax.html', { 'element_id': self.location.html_id(), 'ajax_url': self.ajax_url, 'depends': ';'.join(required_html_ids) @@ -271,7 +273,7 @@ class ConditionalBlock( Return the studio view. """ fragment = Fragment( - self.system.render_template(self.mako_template, self.get_context()) + self.runtime.service(self, 'mako').render_template(self.mako_template, self.get_context()) ) add_webpack_to_fragment(fragment, 'ConditionalBlockStudio') shim_xmodule_js(fragment, self.studio_js_module_name) @@ -284,8 +286,7 @@ class ConditionalBlock( if not self.is_condition_satisfied(): context = {'module': self, 'message': self.conditional_message} - html = self.system.render_template('conditional_module.html', - context) + html = self.runtime.service(self, 'mako').render_template('conditional_module.html', context) return json.dumps({'fragments': [{'content': html}], 'message': bool(self.conditional_message)}) fragments = [child.render(STUDENT_VIEW).to_dict() for child in self.get_display_items()] diff --git a/common/lib/xmodule/xmodule/error_module.py b/common/lib/xmodule/xmodule/error_module.py index 2cefcc9da9..a96631954e 100644 --- a/common/lib/xmodule/xmodule/error_module.py +++ b/common/lib/xmodule/xmodule/error_module.py @@ -11,6 +11,7 @@ import sys from lxml import etree from web_fragments.fragment import Fragment +from xblock.core import XBlock from xblock.field_data import DictFieldData from xblock.fields import Scope, ScopeIds, String @@ -43,6 +44,7 @@ class ErrorFields: display_name = String(scope=Scope.settings) +@XBlock.needs('mako') class ErrorBlock( ErrorFields, XModuleDescriptorToXBlockMixin, @@ -62,7 +64,7 @@ class ErrorBlock( """ Return a fragment that contains the html for the student view. """ - fragment = Fragment(self.system.render_template('module-error.html', { + fragment = Fragment(self.runtime.service(self, 'mako').render_template('module-error.html', { 'staff_access': True, 'data': self.contents, 'error': self.error_msg, @@ -209,7 +211,7 @@ class NonStaffErrorBlock(ErrorBlock): # pylint: disable=abstract-method """ Return a fragment that contains the html for the student view. """ - fragment = Fragment(self.system.render_template('module-error.html', { + fragment = Fragment(self.runtime.service(self, 'mako').render_template('module-error.html', { 'staff_access': False, 'data': '', 'error': '', diff --git a/common/lib/xmodule/xmodule/html_module.py b/common/lib/xmodule/xmodule/html_module.py index 0329bd0bc2..de22e1a823 100644 --- a/common/lib/xmodule/xmodule/html_module.py +++ b/common/lib/xmodule/xmodule/html_module.py @@ -43,6 +43,7 @@ _ = lambda text: text @XBlock.needs("i18n") +@XBlock.needs("mako") @XBlock.needs("user") class HtmlBlockMixin( # lint-amnesty, pylint: disable=abstract-method XmlMixin, EditingMixin, @@ -131,7 +132,7 @@ class HtmlBlockMixin( # lint-amnesty, pylint: disable=abstract-method Return the studio view. """ fragment = Fragment( - self.system.render_template(self.mako_template, self.get_context()) + self.runtime.service(self, 'mako').render_template(self.mako_template, self.get_context()) ) add_webpack_to_fragment(fragment, 'HtmlBlockStudio') shim_xmodule_js(fragment, 'HTMLEditingDescriptor') @@ -484,7 +485,10 @@ class CourseInfoBlock(CourseInfoFields, HtmlBlockMixin): # lint-amnesty, pylint 'visible_updates': course_updates[:3], 'hidden_updates': course_updates[3:], } - return self.system.render_template(f"{self.TEMPLATE_DIR}/course_updates.html", context) + return self.runtime.service(self, 'mako').render_template( + f"{self.TEMPLATE_DIR}/course_updates.html", + context, + ) @classmethod def order_updates(self, updates): # lint-amnesty, pylint: disable=bad-classmethod-argument diff --git a/common/lib/xmodule/xmodule/library_content_module.py b/common/lib/xmodule/xmodule/library_content_module.py index 43d9961703..d81cb98048 100644 --- a/common/lib/xmodule/xmodule/library_content_module.py +++ b/common/lib/xmodule/xmodule/library_content_module.py @@ -68,6 +68,7 @@ def _get_capa_types(): @XBlock.wants('library_tools') # Only needed in studio @XBlock.wants('studio_user_permissions') # Only available in studio @XBlock.wants('user') +@XBlock.needs('mako') class LibraryContentBlock( MakoTemplateBlockBase, XmlMixin, @@ -364,7 +365,7 @@ class LibraryContentBlock( 'content': rendered_child.content, }) - fragment.add_content(self.system.render_template('vert_module.html', { + fragment.add_content(self.runtime.service(self, 'mako').render_template('vert_module.html', { 'items': contents, 'xblock_context': context, 'show_bookmark_button': False, @@ -386,10 +387,11 @@ class LibraryContentBlock( if is_root: # User has clicked the "View" link. Show a preview of all possible children: if self.children: # pylint: disable=no-member - fragment.add_content(self.system.render_template("library-block-author-preview-header.html", { - 'max_count': self.max_count, - 'display_name': self.display_name or self.url_name, - })) + fragment.add_content(self.runtime.service(self, 'mako').render_template( + "library-block-author-preview-header.html", { + 'max_count': self.max_count, + 'display_name': self.display_name or self.url_name, + })) context['can_edit_visibility'] = False context['can_move'] = False self.render_children(context, fragment, can_reorder=False, can_add=False) @@ -406,7 +408,7 @@ class LibraryContentBlock( Return the studio view. """ fragment = Fragment( - self.system.render_template(self.mako_template, self.get_context()) + self.runtime.service(self, 'mako').render_template(self.mako_template, self.get_context()) ) add_webpack_to_fragment(fragment, 'LibraryContentBlockStudio') shim_xmodule_js(fragment, self.studio_js_module_name) diff --git a/common/lib/xmodule/xmodule/library_root_xblock.py b/common/lib/xmodule/xmodule/library_root_xblock.py index ed2fc452a3..32581330aa 100644 --- a/common/lib/xmodule/xmodule/library_root_xblock.py +++ b/common/lib/xmodule/xmodule/library_root_xblock.py @@ -17,6 +17,7 @@ log = logging.getLogger(__name__) _ = lambda text: text +@XBlock.needs('mako') class LibraryRoot(XBlock): """ The LibraryRoot is the root XBlock of a content library. All other blocks in @@ -103,7 +104,7 @@ class LibraryRoot(XBlock): }) fragment.add_content( - self.runtime.render_template("studio_render_paged_children_view.html", { + self.runtime.service(self, 'mako').render_template("studio_render_paged_children_view.html", { 'items': contents, 'xblock_context': context, 'can_add': can_add, diff --git a/common/lib/xmodule/xmodule/lti_module.py b/common/lib/xmodule/xmodule/lti_module.py index f38cb482e8..29acd2b155 100644 --- a/common/lib/xmodule/xmodule/lti_module.py +++ b/common/lib/xmodule/xmodule/lti_module.py @@ -270,6 +270,7 @@ class LTIFields: @XBlock.needs("i18n") +@XBlock.needs("mako") @XBlock.needs("user") class LTIBlock( LTIFields, @@ -401,7 +402,7 @@ class LTIBlock( # Add our specific template information (the raw data body) context.update({'data': self.data}) fragment = Fragment( - self.system.render_template(self.mako_template, context) + self.runtime.service(self, 'mako').render_template(self.mako_template, context) ) add_webpack_to_fragment(fragment, 'LTIBlockStudio') shim_xmodule_js(fragment, self.studio_js_module_name) @@ -517,7 +518,7 @@ class LTIBlock( Return the student view. """ fragment = Fragment() - fragment.add_content(self.system.render_template('lti.html', self.get_context())) + fragment.add_content(self.runtime.service(self, 'mako').render_template('lti.html', self.get_context())) add_webpack_to_fragment(fragment, 'LTIBlockPreview') shim_xmodule_js(fragment, 'LTI') return fragment @@ -527,7 +528,7 @@ class LTIBlock( """ This is called to get context with new oauth params to iframe. """ - template = self.system.render_template('lti_form.html', self.get_context()) + template = self.runtime.service(self, 'mako').render_template('lti_form.html', self.get_context()) return Response(template, content_type='text/html') def get_user_id(self): diff --git a/common/lib/xmodule/xmodule/mako_module.py b/common/lib/xmodule/xmodule/mako_module.py index ab1a5ed513..b34e040798 100644 --- a/common/lib/xmodule/xmodule/mako_module.py +++ b/common/lib/xmodule/xmodule/mako_module.py @@ -9,11 +9,25 @@ from .x_module import DescriptorSystem, XModuleDescriptor, shim_xmodule_js class MakoDescriptorSystem(DescriptorSystem): # lint-amnesty, pylint: disable=abstract-method + """ + Descriptor system that renders mako templates. + """ def __init__(self, render_template, **kwargs): super().__init__(**kwargs) self.render_template = render_template + # Add the MakoService to the descriptor system. + # + # This is not needed by most XBlocks, because they are initialized with a full runtime ModuleSystem that already + # has the MakoService. + # However, there are a few cases where the XBlock only has the descriptor system instead of the full module + # runtime. Specifically: + # * in the Instructor Dashboard bulk emails tab, when rendering the HtmlBlock for its WYSIWYG editor. + # * during testing, when using the ModuleSystemTestCase to fetch factory-created blocks. + from common.djangoapps.edxmako.services import MakoService + self._services['mako'] = MakoService() + class MakoTemplateBlockBase: """ diff --git a/common/lib/xmodule/xmodule/poll_module.py b/common/lib/xmodule/xmodule/poll_module.py index 6c739f4a91..6ec06009e5 100644 --- a/common/lib/xmodule/xmodule/poll_module.py +++ b/common/lib/xmodule/xmodule/poll_module.py @@ -18,6 +18,7 @@ from web_fragments.fragment import Fragment from lxml import etree from openedx.core.djangolib.markup import Text, HTML +from xblock.core import XBlock from xblock.fields import Boolean, Dict, List, Scope, String # lint-amnesty, pylint: disable=wrong-import-order from xmodule.mako_module import MakoTemplateBlockBase from xmodule.stringify import stringify_children @@ -36,6 +37,7 @@ log = logging.getLogger(__name__) _ = lambda text: text +@XBlock.needs('mako') class PollBlock( MakoTemplateBlockBase, XmlMixin, @@ -162,7 +164,7 @@ class PollBlock( 'ajax_url': self.ajax_url, 'configuration_json': self.dump_poll(), } - fragment.add_content(self.system.render_template('poll.html', params)) + fragment.add_content(self.runtime.service(self, 'mako').render_template('poll.html', params)) add_webpack_to_fragment(fragment, 'PollBlockPreview') shim_xmodule_js(fragment, 'Poll') return fragment diff --git a/common/lib/xmodule/xmodule/seq_module.py b/common/lib/xmodule/xmodule/seq_module.py index 6ccd4fea8a..c71ffce6b3 100644 --- a/common/lib/xmodule/xmodule/seq_module.py +++ b/common/lib/xmodule/xmodule/seq_module.py @@ -244,6 +244,7 @@ class ProctoringFields: @XBlock.needs('user') @XBlock.needs('bookmarks') @XBlock.needs('i18n') +@XBlock.needs('mako') @XBlock.wants('content_type_gating') class SequenceBlock( SequenceMixin, @@ -537,7 +538,7 @@ class SequenceBlock( if not self._can_user_view_content(course): banner_text = self._hidden_content_banner_text(course) - hidden_content_html = self.system.render_template( + hidden_content_html = self.runtime.service(self, 'mako').render_template( 'hidden_content.html', { 'self_paced': course.self_paced, @@ -606,7 +607,7 @@ class SequenceBlock( fragment = Fragment() params = self._get_render_metadata(context, display_items, prereq_met, prereq_meta_info, banner_text, view, fragment) # lint-amnesty, pylint: disable=line-too-long - fragment.add_content(self.system.render_template("seq_module.html", params)) + fragment.add_content(self.runtime.service(self, 'mako').render_template("seq_module.html", params)) self._capture_full_seq_item_metrics(display_items) self._capture_current_unit_metrics(display_items) diff --git a/common/lib/xmodule/xmodule/split_test_module.py b/common/lib/xmodule/xmodule/split_test_module.py index 734ea19c2c..870f6ea5e0 100644 --- a/common/lib/xmodule/xmodule/split_test_module.py +++ b/common/lib/xmodule/xmodule/split_test_module.py @@ -123,6 +123,7 @@ def get_split_user_partitions(user_partitions): @XBlock.needs("i18n") @XBlock.needs('user_tags') # pylint: disable=abstract-method +@XBlock.needs('mako') @XBlock.needs('partitions') @XBlock.needs('user') class SplitTestBlock( # lint-amnesty, pylint: disable=abstract-method @@ -301,7 +302,7 @@ class SplitTestBlock( # lint-amnesty, pylint: disable=abstract-method sorted_inactive_contents = sorted(inactive_contents, key=itemgetter('group_name')) # Use the new template - fragment.add_content(self.system.render_template('split_test_staff_view.html', { + fragment.add_content(self.runtime.service(self, 'mako').render_template('split_test_staff_view.html', { 'items': sorted_active_contents + sorted_inactive_contents, })) fragment.add_css('.split-test-child { display: none; }') @@ -328,7 +329,7 @@ class SplitTestBlock( # lint-amnesty, pylint: disable=abstract-method fragment, inactive_children, context ) - fragment.add_content(self.system.render_template('split_test_author_view.html', { + fragment.add_content(self.runtime.service(self, 'mako').render_template('split_test_author_view.html', { 'split_test': self, 'is_root': is_root, 'is_configured': self.is_configured, @@ -367,7 +368,7 @@ class SplitTestBlock( # lint-amnesty, pylint: disable=abstract-method Return the studio view. """ fragment = Fragment( - self.system.render_template(self.mako_template, self.get_context()) + self.runtime.service(self, 'mako').render_template(self.mako_template, self.get_context()) ) add_webpack_to_fragment(fragment, 'SplitTestBlockStudio') shim_xmodule_js(fragment, self.studio_js_module_name) @@ -386,7 +387,7 @@ class SplitTestBlock( # lint-amnesty, pylint: disable=abstract-method return self._staff_view(context) else: child_fragment = self.child.render(STUDENT_VIEW, context) - fragment = Fragment(self.system.render_template('split_test_student_view.html', { + fragment = Fragment(self.runtime.service(self, 'mako').render_template('split_test_student_view.html', { 'child_content': child_fragment.content, 'child_id': self.child.scope_ids.usage_id, })) diff --git a/common/lib/xmodule/xmodule/studio_editable.py b/common/lib/xmodule/xmodule/studio_editable.py index 8352c781d1..cd62283bc2 100644 --- a/common/lib/xmodule/xmodule/studio_editable.py +++ b/common/lib/xmodule/xmodule/studio_editable.py @@ -1,15 +1,20 @@ """ Mixin to support editing in Studio. """ +from xblock.core import XBlock from xmodule.x_module import AUTHOR_VIEW, STUDENT_VIEW, module_attr +@XBlock.needs('mako') class StudioEditableBlock: """ Helper methods for supporting Studio editing of XBlocks. This class is only intended to be used with an XBlock! """ + # Avoids AttributeError caused by the @XBlock.needs decorator. + _services_requested = {} + has_author_view = True def render_children(self, context, fragment, can_reorder=False, can_add=False): @@ -31,7 +36,7 @@ class StudioEditableBlock: 'content': rendered_child.content }) - fragment.add_content(self.system.render_template("studio_render_children_view.html", { # pylint: disable=no-member + fragment.add_content(self.runtime.service(self, 'mako').render_template("studio_render_children_view.html", { # pylint: disable=no-member 'items': contents, 'xblock_context': context, 'can_add': can_add, diff --git a/common/lib/xmodule/xmodule/template_module.py b/common/lib/xmodule/xmodule/template_module.py index 8729190a07..51bc6ff2b2 100644 --- a/common/lib/xmodule/xmodule/template_module.py +++ b/common/lib/xmodule/xmodule/template_module.py @@ -3,6 +3,7 @@ Template module """ from string import Template +from xblock.core import XBlock from lxml import etree from pkg_resources import resource_string @@ -40,6 +41,7 @@ class CustomTagTemplateBlock( # pylint: disable=abstract-method """ +@XBlock.needs('mako') class CustomTagBlock(CustomTagTemplateBlock): # pylint: disable=abstract-method """ This module supports tags of the form @@ -85,7 +87,7 @@ class CustomTagBlock(CustomTagTemplateBlock): # pylint: disable=abstract-method Return the studio view. """ fragment = Fragment( - self.system.render_template(self.mako_template, self.get_context()) + self.runtime.service(self, 'mako').render_template(self.mako_template, self.get_context()) ) add_webpack_to_fragment(fragment, 'CustomTagBlockStudio') shim_xmodule_js(fragment, 'XMLEditingDescriptor') diff --git a/common/lib/xmodule/xmodule/tests/test_html_module.py b/common/lib/xmodule/xmodule/tests/test_html_module.py index 5695941d0b..13fa83d268 100644 --- a/common/lib/xmodule/xmodule/tests/test_html_module.py +++ b/common/lib/xmodule/xmodule/tests/test_html_module.py @@ -315,7 +315,7 @@ class CourseInfoBlockTestCase(unittest.TestCase): template_name = f"{info_module.TEMPLATE_DIR}/course_updates.html" info_module.get_html() # Assertion to validate that render function is called with the expected context - info_module.system.render_template.assert_called_once_with( + info_module.runtime.service(info_module, 'mako').render_template.assert_called_once_with( template_name, expected_context ) diff --git a/common/lib/xmodule/xmodule/vertical_block.py b/common/lib/xmodule/xmodule/vertical_block.py index 4d1c82477b..14baf86784 100644 --- a/common/lib/xmodule/xmodule/vertical_block.py +++ b/common/lib/xmodule/xmodule/vertical_block.py @@ -48,7 +48,7 @@ class VerticalFields: ) -@XBlock.needs('user', 'bookmarks') +@XBlock.needs('user', 'bookmarks', 'mako') @XBlock.wants('completion') @XBlock.wants('call_to_action') class VerticalBlock( @@ -151,7 +151,7 @@ class VerticalBlock( child_context['username'], str(self.location)), # pylint: disable=no-member }) - fragment.add_content(self.system.render_template('vert_module.html', fragment_context)) + fragment.add_content(self.runtime.service(self, 'mako').render_template('vert_module.html', fragment_context)) add_webpack_to_fragment(fragment, 'VerticalStudentView') fragment.initialize_js('VerticalStudentView') diff --git a/common/lib/xmodule/xmodule/video_module/video_module.py b/common/lib/xmodule/xmodule/video_module/video_module.py index 8bcccb6306..2216c88488 100644 --- a/common/lib/xmodule/xmodule/video_module/video_module.py +++ b/common/lib/xmodule/xmodule/video_module/video_module.py @@ -108,6 +108,7 @@ EXPORT_IMPORT_STATIC_DIR = 'static' @XBlock.wants('settings', 'completion', 'i18n', 'request_cache') +@XBlock.needs('mako') class VideoBlock( VideoFields, VideoTranscriptsMixin, VideoStudioViewHandlers, VideoStudentViewHandlers, TabsEditingMixin, EmptyDataRawMixin, XmlMixin, EditingMixin, @@ -245,7 +246,7 @@ class VideoBlock( Return the studio view. """ fragment = Fragment( - self.system.render_template(self.mako_template, self.get_context()) + self.runtime.service(self, 'mako').render_template(self.mako_template, self.get_context()) ) add_webpack_to_fragment(fragment, 'VideoBlockStudio') shim_xmodule_js(fragment, 'TabsEditingDescriptor') @@ -468,7 +469,7 @@ class VideoBlock( 'transcript_download_formats_list': self.fields['transcript_download_format'].values, # lint-amnesty, pylint: disable=unsubscriptable-object 'license': getattr(self, "license", None), } - return self.system.render_template('video.html', context) + return self.runtime.service(self, 'mako').render_template('video.html', context) def validate(self): """ diff --git a/common/lib/xmodule/xmodule/word_cloud_module.py b/common/lib/xmodule/xmodule/word_cloud_module.py index 8ada5d1436..5fc1c737be 100644 --- a/common/lib/xmodule/xmodule/word_cloud_module.py +++ b/common/lib/xmodule/xmodule/word_cloud_module.py @@ -44,6 +44,7 @@ def pretty_bool(value): return value in bool_dict +@XBlock.needs('mako') class WordCloudBlock( # pylint: disable=abstract-method EmptyDataRawMixin, XmlMixin, @@ -279,7 +280,7 @@ class WordCloudBlock( # pylint: disable=abstract-method Renders the output that a student will see. """ fragment = Fragment() - fragment.add_content(self.system.render_template('word_cloud.html', { + fragment.add_content(self.runtime.service(self, 'mako').render_template('word_cloud.html', { 'ajax_url': self.ajax_url, 'display_name': self.display_name, 'instructions': self.instructions, @@ -304,7 +305,7 @@ class WordCloudBlock( # pylint: disable=abstract-method Return the studio view. """ fragment = Fragment( - self.system.render_template(self.mako_template, self.get_context()) + self.runtime.service(self, 'mako').render_template(self.mako_template, self.get_context()) ) add_webpack_to_fragment(fragment, 'WordCloudBlockStudio') shim_xmodule_js(fragment, self.studio_js_module_name) diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index 53530e0e2c..056528ebd4 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -1748,7 +1748,6 @@ class ModuleSystemShim: """ @property -<<<<<<< HEAD def anonymous_student_id(self): """ Returns the anonymous user ID for the current user and course. diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index c409f97ff3..b4acc4c3f6 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -705,7 +705,7 @@ def get_module_system_for_user( mako_service = MakoService() if settings.FEATURES.get("LICENSING", False): - block_wrappers.append(wrap_with_license) + block_wrappers.append(partial(wrap_with_license, mako_service=mako_service)) # Wrap the output display in a single div to allow for the XModule # javascript to be bound correctly diff --git a/openedx/core/lib/license/wrapper.py b/openedx/core/lib/license/wrapper.py index 2d17015408..23fb4f0492 100644 --- a/openedx/core/lib/license/wrapper.py +++ b/openedx/core/lib/license/wrapper.py @@ -3,12 +3,12 @@ Code to wrap web fragments with a license. """ -def wrap_with_license(block, view, frag, context): # pylint: disable=unused-argument +def wrap_with_license(block, view, frag, context, mako_service): # pylint: disable=unused-argument """ In the LMS, display the custom license underneath the XBlock. """ license = getattr(block, "license", None) # pylint: disable=redefined-builtin if license: context = {"license": license} - frag.content += block.runtime.render_template('license_wrapper.html', context) + frag.content += mako_service.render_template('license_wrapper.html', context) return frag diff --git a/openedx/core/lib/xblock_builtin/xblock_discussion/xblock_discussion/__init__.py b/openedx/core/lib/xblock_builtin/xblock_discussion/xblock_discussion/__init__.py index 079b1765cb..61ad62e25d 100644 --- a/openedx/core/lib/xblock_builtin/xblock_discussion/xblock_discussion/__init__.py +++ b/openedx/core/lib/xblock_builtin/xblock_discussion/xblock_discussion/__init__.py @@ -32,6 +32,7 @@ def _(text): @XBlock.needs('user') # pylint: disable=abstract-method @XBlock.needs('i18n') +@XBlock.needs('mako') class DiscussionXBlock(XBlock, StudioEditableXBlockMixin, XmlParserMixin): # lint-amnesty, pylint: disable=abstract-method """ Provides a discussion forum that is inline with other content in the courseware. @@ -202,7 +203,8 @@ class DiscussionXBlock(XBlock, StudioEditableXBlockMixin, XmlParserMixin): # li 'login_msg': login_msg, } - fragment.add_content(self.runtime.render_template('discussion/_discussion_inline.html', context)) + fragment.add_content(self.runtime.service(self, 'mako').render_template('discussion/_discussion_inline.html', + context)) fragment.initialize_js('DiscussionInlineBlock') return fragment @@ -212,7 +214,7 @@ class DiscussionXBlock(XBlock, StudioEditableXBlockMixin, XmlParserMixin): # li Renders author view for Studio. """ fragment = Fragment() - fragment.add_content(self.runtime.render_template( + fragment.add_content(self.runtime.service(self, 'mako').render_template( 'discussion/_discussion_inline_studio.html', {'discussion_id': self.discussion_id} ))