Merge pull request #2659 from edx/ned/more-pervasive-date-l10n
Make the i18n service available everywhere.
This commit is contained in:
@@ -11,7 +11,7 @@ from edxmako.shortcuts import render_to_string
|
||||
from xmodule_modifiers import replace_static_urls, wrap_xblock
|
||||
from xmodule.error_module import ErrorDescriptor
|
||||
from xmodule.exceptions import NotFoundError, ProcessingError
|
||||
from xmodule.modulestore.django import modulestore, loc_mapper
|
||||
from xmodule.modulestore.django import modulestore, loc_mapper, ModuleI18nService
|
||||
from xmodule.modulestore.locator import Locator
|
||||
from xmodule.x_module import ModuleSystem
|
||||
from xblock.runtime import KvsFieldData
|
||||
@@ -132,6 +132,9 @@ def _preview_module_system(request, descriptor):
|
||||
# If descriptor.location is a CourseLocator, course_id is unused.
|
||||
get_user_role=lambda: get_user_role(request.user, descriptor.location, course_id),
|
||||
descriptor_runtime=descriptor.runtime,
|
||||
services={
|
||||
"i18n": ModuleI18nService(),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ Tests for util.date_utils
|
||||
"""
|
||||
|
||||
from datetime import datetime, timedelta, tzinfo
|
||||
from functools import partial
|
||||
import unittest
|
||||
|
||||
import ddt
|
||||
@@ -118,18 +117,22 @@ def test_almost_same_datetime():
|
||||
)
|
||||
|
||||
|
||||
def fake_ugettext(text, translations):
|
||||
def fake_ugettext(translations):
|
||||
"""
|
||||
A fake implementation of ugettext, for testing.
|
||||
Create a fake implementation of ugettext, for testing.
|
||||
"""
|
||||
return translations.get(text, text)
|
||||
def _ugettext(text): # pylint: disable=missing-docstring
|
||||
return translations.get(text, text)
|
||||
return _ugettext
|
||||
|
||||
|
||||
def fake_pgettext(context, text, translations):
|
||||
def fake_pgettext(translations):
|
||||
"""
|
||||
A fake implementation of pgettext, for testing.
|
||||
Create a fake implementation of pgettext, for testing.
|
||||
"""
|
||||
return translations.get((context, text), text)
|
||||
def _pgettext(context, text): # pylint: disable=missing-docstring
|
||||
return translations.get((context, text), text)
|
||||
return _pgettext
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -161,7 +164,7 @@ class StrftimeLocalizedTest(unittest.TestCase):
|
||||
dtime = datetime(2013, 02, 14, 16, 41, 17)
|
||||
self.assertEqual(expected, strftime_localized(dtime, fmt))
|
||||
|
||||
@patch('util.date_utils.pgettext', partial(fake_pgettext, translations={
|
||||
@patch('util.date_utils.pgettext', fake_pgettext(translations={
|
||||
("abbreviated month name", "Feb"): "XXfebXX",
|
||||
("month name", "February"): "XXfebruaryXX",
|
||||
("abbreviated weekday name", "Thu"): "XXthuXX",
|
||||
@@ -179,7 +182,7 @@ class StrftimeLocalizedTest(unittest.TestCase):
|
||||
dtime = datetime(2013, 02, 14, 16, 41, 17)
|
||||
self.assertEqual(expected, strftime_localized(dtime, fmt))
|
||||
|
||||
@patch('util.date_utils.ugettext', partial(fake_ugettext, translations={
|
||||
@patch('util.date_utils.ugettext', fake_ugettext(translations={
|
||||
"SHORT_DATE_FORMAT": "date(%Y.%m.%d)",
|
||||
"LONG_DATE_FORMAT": "date(%A.%Y.%B.%d)",
|
||||
"DATE_TIME_FORMAT": "date(%Y.%m.%d@%H.%M)",
|
||||
@@ -198,7 +201,7 @@ class StrftimeLocalizedTest(unittest.TestCase):
|
||||
dtime = datetime(2013, 02, 14, 16, 41, 17)
|
||||
self.assertEqual(expected, strftime_localized(dtime, fmt))
|
||||
|
||||
@patch('util.date_utils.ugettext', partial(fake_ugettext, translations={
|
||||
@patch('util.date_utils.ugettext', fake_ugettext(translations={
|
||||
"SHORT_DATE_FORMAT": "oops date(%Y.%x.%d)",
|
||||
"TIME_FORMAT": "oops %Hh.%Xm.%Ss",
|
||||
}))
|
||||
|
||||
@@ -408,7 +408,7 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
|
||||
# set the due_date_display_format to what would have been shown previously (with no timezone).
|
||||
# Then remove show_timezone so that if the user clears out the due_date_display_format,
|
||||
# they get the default date display.
|
||||
self.due_date_display_format = u"%b %d, %Y at %H:%M"
|
||||
self.due_date_display_format = "DATE_TIME"
|
||||
delattr(self, 'show_timezone')
|
||||
|
||||
# NOTE: relies on the modulestore to call set_grading_policy() right after
|
||||
|
||||
@@ -6,15 +6,17 @@ Passes settings.MODULESTORE as kwargs to MongoModuleStore
|
||||
|
||||
from __future__ import absolute_import
|
||||
from importlib import import_module
|
||||
|
||||
import re
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.cache import get_cache, InvalidCacheBackendError
|
||||
from django.dispatch import Signal
|
||||
import django.utils
|
||||
|
||||
from xmodule.modulestore.loc_mapper_store import LocMapperStore
|
||||
from xmodule.util.django import get_current_request_hostname
|
||||
|
||||
|
||||
# We may not always have the request_cache module available
|
||||
try:
|
||||
from request_cache.middleware import RequestCache
|
||||
@@ -38,7 +40,7 @@ def load_function(path):
|
||||
return getattr(import_module(module_path), name)
|
||||
|
||||
|
||||
def create_modulestore_instance(engine, doc_store_config, options):
|
||||
def create_modulestore_instance(engine, doc_store_config, options, i18n_service=None):
|
||||
"""
|
||||
This will return a new instance of a modulestore given an engine and options
|
||||
"""
|
||||
@@ -68,6 +70,7 @@ def create_modulestore_instance(engine, doc_store_config, options):
|
||||
xblock_mixins=getattr(settings, 'XBLOCK_MIXINS', ()),
|
||||
xblock_select=getattr(settings, 'XBLOCK_SELECT_FUNCTION', None),
|
||||
doc_store_config=doc_store_config,
|
||||
i18n_service=i18n_service or ModuleI18nService(),
|
||||
**_options
|
||||
)
|
||||
|
||||
@@ -186,3 +189,33 @@ def editable_modulestore(name='default'):
|
||||
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class ModuleI18nService(object):
|
||||
"""
|
||||
Implement the XBlock runtime "i18n" service.
|
||||
|
||||
Mostly a pass-through to Django's translation module.
|
||||
django.utils.translation implements the gettext.Translations interface (it
|
||||
has ugettext, ungettext, etc), so we can use it directly as the runtime
|
||||
i18n service.
|
||||
|
||||
"""
|
||||
def __getattr__(self, name):
|
||||
return getattr(django.utils.translation, name)
|
||||
|
||||
def strftime(self, *args, **kwargs):
|
||||
"""
|
||||
A locale-aware implementation of strftime.
|
||||
"""
|
||||
# This is the wrong place to import this function. I'm putting it here
|
||||
# because the xmodule test suite can't import this module, because
|
||||
# Django is not available in that suite. This function isn't called in
|
||||
# that suite, so this hides the import so the test won't fail.
|
||||
#
|
||||
# As I said, this is wrong. But Cale says this code will soon be
|
||||
# refactored to a place that will be right, and the code can be made
|
||||
# right there. If you are reading this comment after April 1, 2014,
|
||||
# then Cale was a liar.
|
||||
from util.date_utils import strftime_localized
|
||||
return strftime_localized(*args, **kwargs)
|
||||
|
||||
@@ -23,7 +23,7 @@ class MixedModuleStore(ModuleStoreWriteBase):
|
||||
ModuleStore knows how to route requests to the right persistence ms and how to convert any
|
||||
references in the xblocks to the type required by the app and the persistence layer.
|
||||
"""
|
||||
def __init__(self, mappings, stores, reference_type=None, **kwargs):
|
||||
def __init__(self, mappings, stores, reference_type=None, i18n_service=None, **kwargs):
|
||||
"""
|
||||
Initialize a MixedModuleStore. Here we look into our passed in kwargs which should be a
|
||||
collection of other modulestore configuration informations
|
||||
@@ -55,7 +55,8 @@ class MixedModuleStore(ModuleStoreWriteBase):
|
||||
store['ENGINE'],
|
||||
# XMLModuleStore's don't have doc store configs
|
||||
store.get('DOC_STORE_CONFIG', {}),
|
||||
store['OPTIONS']
|
||||
store['OPTIONS'],
|
||||
i18n_service=i18n_service,
|
||||
)
|
||||
|
||||
def _get_modulestore_for_courseid(self, course_id):
|
||||
|
||||
@@ -263,6 +263,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
|
||||
def __init__(self, doc_store_config, fs_root, render_template,
|
||||
default_class=None,
|
||||
error_tracker=null_error_tracker,
|
||||
i18n_service=None,
|
||||
**kwargs):
|
||||
"""
|
||||
:param doc_store_config: must have a host, db, and collection entries. Other common entries: port, tz_aware.
|
||||
@@ -312,6 +313,8 @@ class MongoModuleStore(ModuleStoreWriteBase):
|
||||
self.fs_root = path(fs_root)
|
||||
self.error_tracker = error_tracker
|
||||
self.render_template = render_template
|
||||
self.i18n_service = i18n_service
|
||||
|
||||
self.ignore_write_events_on_courses = []
|
||||
|
||||
def compute_metadata_inheritance_tree(self, location):
|
||||
@@ -498,6 +501,10 @@ class MongoModuleStore(ModuleStoreWriteBase):
|
||||
if apply_cached_metadata:
|
||||
cached_metadata = self.get_cached_metadata_inheritance_tree(location)
|
||||
|
||||
services = {}
|
||||
if self.i18n_service:
|
||||
services["i18n"] = self.i18n_service
|
||||
|
||||
# TODO (cdodge): When the 'split module store' work has been completed, we should remove
|
||||
# the 'metadata_inheritance_tree' parameter
|
||||
system = CachingDescriptorSystem(
|
||||
@@ -510,6 +517,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
|
||||
cached_metadata=cached_metadata,
|
||||
mixins=self.xblock_mixins,
|
||||
select=self.xblock_select,
|
||||
services=services,
|
||||
)
|
||||
return system.load_item(location)
|
||||
|
||||
@@ -631,6 +639,10 @@ class MongoModuleStore(ModuleStoreWriteBase):
|
||||
if metadata is None:
|
||||
metadata = {}
|
||||
if system is None:
|
||||
services = {}
|
||||
if self.i18n_service:
|
||||
services["i18n"] = self.i18n_service
|
||||
|
||||
system = CachingDescriptorSystem(
|
||||
modulestore=self,
|
||||
module_data={},
|
||||
@@ -641,6 +653,7 @@ class MongoModuleStore(ModuleStoreWriteBase):
|
||||
cached_metadata={},
|
||||
mixins=self.xblock_mixins,
|
||||
select=self.xblock_select,
|
||||
services=services,
|
||||
)
|
||||
xblock_class = system.load_block_type(location.category)
|
||||
if definition_data is None:
|
||||
|
||||
@@ -105,6 +105,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
|
||||
default_class=None,
|
||||
error_tracker=null_error_tracker,
|
||||
loc_mapper=None,
|
||||
i18n_service=None,
|
||||
**kwargs):
|
||||
"""
|
||||
:param doc_store_config: must have a host, db, and collection entries. Other common entries: port, tz_aware.
|
||||
@@ -129,6 +130,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
|
||||
self.fs_root = path(fs_root)
|
||||
self.error_tracker = error_tracker
|
||||
self.render_template = render_template
|
||||
self.i18n_service = i18n_service
|
||||
|
||||
# TODO: Don't have a runtime just to generate the appropriate mixin classes (cpennington)
|
||||
# This is only used by _partition_fields_by_scope, which is only needed because
|
||||
@@ -180,6 +182,10 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
|
||||
'''
|
||||
system = self._get_cache(course_entry['structure']['_id'])
|
||||
if system is None:
|
||||
services = {}
|
||||
if self.i18n_service:
|
||||
services["i18n"] = self.i18n_service
|
||||
|
||||
system = CachingDescriptorSystem(
|
||||
modulestore=self,
|
||||
course_entry=course_entry,
|
||||
@@ -191,6 +197,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
|
||||
resources_fs=None,
|
||||
mixins=self.xblock_mixins,
|
||||
select=self.xblock_select,
|
||||
services=services,
|
||||
)
|
||||
self._add_cache(course_entry['structure']['_id'], system)
|
||||
self.cache_items(system, block_ids, depth, lazy)
|
||||
|
||||
@@ -347,8 +347,10 @@ class XMLModuleStore(ModuleStoreReadBase):
|
||||
"""
|
||||
An XML backed ModuleStore
|
||||
"""
|
||||
def __init__(self, data_dir, default_class=None, course_dirs=None, course_ids=None,
|
||||
load_error_modules=True, **kwargs):
|
||||
def __init__(
|
||||
self, data_dir, default_class=None, course_dirs=None, course_ids=None,
|
||||
load_error_modules=True, i18n_service=None, **kwargs
|
||||
):
|
||||
"""
|
||||
Initialize an XMLModuleStore from data_dir
|
||||
|
||||
@@ -382,6 +384,8 @@ class XMLModuleStore(ModuleStoreReadBase):
|
||||
# All field data will be stored in an inheriting field data.
|
||||
self.field_data = inheriting_field_data(kvs=DictKeyValueStore())
|
||||
|
||||
self.i18n_service = i18n_service
|
||||
|
||||
# If we are specifically asked for missing courses, that should
|
||||
# be an error. If we are asked for "all" courses, find the ones
|
||||
# that have a course.xml. We sort the dirs in alpha order so we always
|
||||
@@ -522,6 +526,10 @@ class XMLModuleStore(ModuleStoreReadBase):
|
||||
"""
|
||||
return policy.get(policy_key(usage_id), {})
|
||||
|
||||
services = {}
|
||||
if self.i18n_service:
|
||||
services['i18n'] = self.i18n_service
|
||||
|
||||
system = ImportSystem(
|
||||
xmlstore=self,
|
||||
course_id=course_id,
|
||||
@@ -534,6 +542,7 @@ class XMLModuleStore(ModuleStoreReadBase):
|
||||
default_class=self.default_class,
|
||||
select=self.xblock_select,
|
||||
field_data=self.field_data,
|
||||
services=services,
|
||||
)
|
||||
|
||||
course_descriptor = system.process_xml(etree.tostring(course_data, encoding='unicode'))
|
||||
|
||||
@@ -37,7 +37,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2014-02-19 15:39-0500\n"
|
||||
"POT-Creation-Date: 2014-02-20 13:02-0500\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
||||
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 0.1a\n"
|
||||
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
|
||||
"POT-Creation-Date: 2014-02-19 15:38-0500\n"
|
||||
"PO-Revision-Date: 2014-02-19 20:39:50.876422\n"
|
||||
"POT-Creation-Date: 2014-02-20 13:01-0500\n"
|
||||
"PO-Revision-Date: 2014-02-20 18:02:05.375610\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: openedx-translation <openedx-translation@googlegroups.com>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
||||
@@ -13,7 +13,6 @@ from django.core.cache import cache
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import Http404, HttpResponse
|
||||
import django.utils
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
from capa.xqueue_interface import XQueueInterface
|
||||
@@ -33,14 +32,13 @@ from xblock.django.request import django_to_webob_request, webob_to_django_respo
|
||||
from xmodule.error_module import ErrorDescriptor, NonStaffErrorDescriptor
|
||||
from xmodule.exceptions import NotFoundError, ProcessingError
|
||||
from xmodule.modulestore import Location
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.django import modulestore, ModuleI18nService
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
from xmodule.util.duedate import get_extended_due_date
|
||||
from xmodule_modifiers import replace_course_urls, replace_jump_to_id_urls, replace_static_urls, add_staff_debug_info, wrap_xblock
|
||||
from xmodule.lti_module import LTIModule
|
||||
from xmodule.x_module import XModuleDescriptor
|
||||
|
||||
from util.date_utils import strftime_localized
|
||||
from util.json_request import JsonResponse
|
||||
from util.sandboxing import can_execute_unsafe_code
|
||||
|
||||
@@ -651,20 +649,3 @@ def _check_files_limits(files):
|
||||
return msg
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class ModuleI18nService(object):
|
||||
"""
|
||||
Implement the XBlock runtime "i18n" service.
|
||||
|
||||
Mostly a pass-through to Django's translation module.
|
||||
django.utils.translation implements the gettext.Translations interface (it
|
||||
has ugettext, ungettext, etc), so we can use it directly as the runtime
|
||||
i18n service.
|
||||
|
||||
"""
|
||||
def __getattr__(self, name):
|
||||
return getattr(django.utils.translation, name)
|
||||
|
||||
def strftime(self, *args, **kwargs):
|
||||
return strftime_localized(*args, **kwargs)
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
Tests courseware views.py
|
||||
"""
|
||||
import unittest
|
||||
from mock import MagicMock, patch
|
||||
from datetime import datetime
|
||||
|
||||
from mock import MagicMock, patch
|
||||
from pytz import UTC
|
||||
|
||||
from django.test import TestCase
|
||||
@@ -30,15 +31,16 @@ from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE
|
||||
from course_modes.models import CourseMode
|
||||
import shoppingcart
|
||||
|
||||
from util.tests.test_date_utils import fake_ugettext, fake_pgettext
|
||||
|
||||
|
||||
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
|
||||
class TestJumpTo(TestCase):
|
||||
"""
|
||||
Check the jumpto link for a course.
|
||||
Check the jumpto link for a course.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
|
||||
# Use toy course from XML
|
||||
self.course_name = 'edX/toy/2012_Fall'
|
||||
|
||||
@@ -71,7 +73,9 @@ class TestJumpTo(TestCase):
|
||||
|
||||
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
|
||||
class ViewsTestCase(TestCase):
|
||||
""" Tests for views.py methods. """
|
||||
"""
|
||||
Tests for views.py methods.
|
||||
"""
|
||||
def setUp(self):
|
||||
self.user = User.objects.create(username='dummy', password='123456',
|
||||
email='test@mit.edu')
|
||||
@@ -366,3 +370,57 @@ class TestAccordionDueDate(BaseDueDateTests):
|
||||
return views.render_accordion(
|
||||
self.request, course, course.get_children()[0].id, None, None
|
||||
)
|
||||
|
||||
|
||||
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
|
||||
class StartDateTests(ModuleStoreTestCase):
|
||||
"""
|
||||
Test that start dates are properly localized and displayed on the student
|
||||
dashboard.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.request_factory = RequestFactory()
|
||||
self.user = UserFactory.create()
|
||||
self.request = self.request_factory.get("foo")
|
||||
self.request.user = self.user
|
||||
|
||||
def set_up_course(self):
|
||||
"""
|
||||
Create a stock course with a specific due date.
|
||||
|
||||
:param course_kwargs: All kwargs are passed to through to the :class:`CourseFactory`
|
||||
"""
|
||||
course = CourseFactory(start=datetime(2013, 9, 16, 7, 17, 28))
|
||||
course = modulestore().get_instance(course.id, course.location) # pylint: disable=no-member
|
||||
return course
|
||||
|
||||
def get_about_text(self, course_id):
|
||||
"""
|
||||
Get the text of the /about page for the course.
|
||||
"""
|
||||
text = views.course_about(self.request, course_id).content
|
||||
return text
|
||||
|
||||
@patch('util.date_utils.pgettext', fake_pgettext(translations={
|
||||
("abbreviated month name", "Sep"): "SEPTEMBER",
|
||||
}))
|
||||
@patch('util.date_utils.ugettext', fake_ugettext(translations={
|
||||
"SHORT_DATE_FORMAT": "%Y-%b-%d",
|
||||
}))
|
||||
def test_format_localized_in_studio_course(self):
|
||||
course = self.set_up_course()
|
||||
text = self.get_about_text(course.id)
|
||||
# The start date is set in the set_up_course function above.
|
||||
self.assertIn("2013-SEPTEMBER-16", text)
|
||||
|
||||
@patch('util.date_utils.pgettext', fake_pgettext(translations={
|
||||
("abbreviated month name", "Jul"): "JULY",
|
||||
}))
|
||||
@patch('util.date_utils.ugettext', fake_ugettext(translations={
|
||||
"SHORT_DATE_FORMAT": "%Y-%b-%d",
|
||||
}))
|
||||
def test_format_localized_in_xml_course(self):
|
||||
text = self.get_about_text('edX/toy/TT_2012_Fall')
|
||||
# The start date is set in common/test/data/two_toys/policies/TT_2012_Fall/policy.json
|
||||
self.assertIn("2015-JULY-17", text)
|
||||
|
||||
@@ -7,6 +7,8 @@ from django.conf import settings
|
||||
from xmodule.open_ended_grading_classes import peer_grading_service
|
||||
from xmodule.open_ended_grading_classes.controller_query_service import ControllerQueryService
|
||||
|
||||
from xmodule.modulestore.django import ModuleI18nService
|
||||
|
||||
from courseware.access import has_access
|
||||
from lms.lib.xblock.runtime import LmsModuleSystem
|
||||
from edxmako.shortcuts import render_to_string
|
||||
@@ -70,6 +72,9 @@ def peer_grading_notifications(course, user):
|
||||
render_template=render_to_string,
|
||||
replace_urls=None,
|
||||
descriptor_runtime=None,
|
||||
services={
|
||||
'i18n': ModuleI18nService(),
|
||||
},
|
||||
)
|
||||
peer_gs = peer_grading_service.PeerGradingService(settings.OPEN_ENDED_GRADING_INTERFACE, system)
|
||||
pending_grading = False
|
||||
@@ -131,6 +136,9 @@ def combined_notifications(course, user):
|
||||
render_template=render_to_string,
|
||||
replace_urls=None,
|
||||
descriptor_runtime=None,
|
||||
services={
|
||||
'i18n': ModuleI18nService(),
|
||||
},
|
||||
)
|
||||
#Initialize controller query service using our mock system
|
||||
controller_qs = ControllerQueryService(settings.OPEN_ENDED_GRADING_INTERFACE, system)
|
||||
|
||||
@@ -11,6 +11,7 @@ from django.utils.translation import ugettext as _
|
||||
|
||||
from xmodule.course_module import CourseDescriptor
|
||||
from xmodule.open_ended_grading_classes.grading_service_module import GradingService, GradingServiceError
|
||||
from xmodule.modulestore.django import ModuleI18nService
|
||||
|
||||
from courseware.access import has_access
|
||||
from lms.lib.xblock.runtime import LmsModuleSystem
|
||||
@@ -84,6 +85,9 @@ class StaffGradingService(GradingService):
|
||||
render_template=render_to_string,
|
||||
replace_urls=None,
|
||||
descriptor_runtime=None,
|
||||
services={
|
||||
'i18n': ModuleI18nService(),
|
||||
},
|
||||
)
|
||||
super(StaffGradingService, self).__init__(config)
|
||||
self.url = config['url'] + config['staff_grading']
|
||||
|
||||
@@ -2,7 +2,7 @@ import json
|
||||
import logging
|
||||
|
||||
from xmodule.modulestore import search
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.django import modulestore, ModuleI18nService
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError, NoPathToItem
|
||||
from xmodule.open_ended_grading_classes.controller_query_service import ControllerQueryService
|
||||
from xmodule.open_ended_grading_classes.grading_service_module import GradingServiceError
|
||||
@@ -34,6 +34,9 @@ SYSTEM = LmsModuleSystem(
|
||||
render_template=render_to_string,
|
||||
replace_urls=None,
|
||||
descriptor_runtime=None,
|
||||
services={
|
||||
'i18n': ModuleI18nService(),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user