Merge pull request #6892 from edx/hotfix/2015-02-04
Don't instantiate bogus modulestores just to get template rendering in o...
This commit is contained in:
@@ -138,7 +138,7 @@ class CombinedOpenEndedV1Module():
|
||||
self.skip_basic_checks = instance_state.get('skip_spelling_checks', SKIP_BASIC_CHECKS) in TRUE_DICT
|
||||
|
||||
if system.open_ended_grading_interface:
|
||||
self.peer_gs = PeerGradingService(system.open_ended_grading_interface, system)
|
||||
self.peer_gs = PeerGradingService(system.open_ended_grading_interface, system.render_template)
|
||||
else:
|
||||
self.peer_gs = MockPeerGradingService()
|
||||
|
||||
@@ -159,7 +159,7 @@ class CombinedOpenEndedV1Module():
|
||||
raise
|
||||
self.display_due_date = self.timeinfo.display_due_date
|
||||
|
||||
self.rubric_renderer = CombinedOpenEndedRubric(system, True)
|
||||
self.rubric_renderer = CombinedOpenEndedRubric(system.render_template, True)
|
||||
rubric_string = stringify_children(definition['rubric'])
|
||||
self._max_score = self.rubric_renderer.check_if_rubric_is_parseable(rubric_string, location, MAX_SCORE_ALLOWED)
|
||||
|
||||
|
||||
@@ -40,10 +40,10 @@ class RubricParsingError(Exception):
|
||||
class CombinedOpenEndedRubric(object):
|
||||
TEMPLATE_DIR = "combinedopenended/openended"
|
||||
|
||||
def __init__(self, system, view_only=False):
|
||||
def __init__(self, render_template, view_only=False):
|
||||
self.has_score = False
|
||||
self.view_only = view_only
|
||||
self.system = system
|
||||
self.render_template = render_template
|
||||
|
||||
def render_rubric(self, rubric_xml, score_list=None):
|
||||
'''
|
||||
@@ -70,7 +70,7 @@ class CombinedOpenEndedRubric(object):
|
||||
rubric_template = '{0}/open_ended_rubric.html'.format(self.TEMPLATE_DIR)
|
||||
if self.view_only:
|
||||
rubric_template = '{0}/open_ended_view_only_rubric.html'.format(self.TEMPLATE_DIR)
|
||||
html = self.system.render_template(
|
||||
html = self.render_template(
|
||||
rubric_template,
|
||||
{
|
||||
'categories': rubric_categories,
|
||||
@@ -254,7 +254,7 @@ class CombinedOpenEndedRubric(object):
|
||||
else:
|
||||
correct.append(.5)
|
||||
|
||||
html = self.system.render_template(
|
||||
html = self.render_template(
|
||||
'{0}/open_ended_combined_rubric.html'.format(self.TEMPLATE_DIR),
|
||||
{
|
||||
'categories': rubric_categories,
|
||||
|
||||
@@ -13,8 +13,8 @@ class ControllerQueryService(GradingService):
|
||||
|
||||
METRIC_NAME = 'edxapp.open_ended_grading.controller_query_service'
|
||||
|
||||
def __init__(self, config, system):
|
||||
config['system'] = system
|
||||
def __init__(self, config, render_template):
|
||||
config['render_template'] = render_template
|
||||
super(ControllerQueryService, self).__init__(config)
|
||||
self.url = config['url'] + config['grading_controller']
|
||||
self.login_url = self.url + '/login/'
|
||||
@@ -105,7 +105,7 @@ class MockControllerQueryService(object):
|
||||
Mock controller query service for testing
|
||||
"""
|
||||
|
||||
def __init__(self, config, system):
|
||||
def __init__(self, config, render_template):
|
||||
pass
|
||||
|
||||
def check_for_eta(self, *args, **kwargs):
|
||||
|
||||
@@ -27,7 +27,7 @@ class GradingService(object):
|
||||
self.username = config['username']
|
||||
self.password = config['password']
|
||||
self.session = requests.Session()
|
||||
self.system = config['system']
|
||||
self.render_template = config['render_template']
|
||||
|
||||
def _login(self):
|
||||
"""
|
||||
@@ -142,7 +142,7 @@ class GradingService(object):
|
||||
try:
|
||||
if 'rubric' in response:
|
||||
rubric = response['rubric']
|
||||
rubric_renderer = CombinedOpenEndedRubric(self.system, view_only)
|
||||
rubric_renderer = CombinedOpenEndedRubric(self.render_template, view_only)
|
||||
rubric_dict = rubric_renderer.render_rubric(rubric)
|
||||
success = rubric_dict['success']
|
||||
rubric_html = rubric_dict['html']
|
||||
|
||||
@@ -484,7 +484,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
|
||||
feedback = self._convert_longform_feedback_to_html(response_items)
|
||||
rubric_scores = []
|
||||
if response_items['rubric_scores_complete'] is True:
|
||||
rubric_renderer = CombinedOpenEndedRubric(system, True)
|
||||
rubric_renderer = CombinedOpenEndedRubric(system.render_template, True)
|
||||
rubric_dict = rubric_renderer.render_rubric(response_items['rubric_xml'])
|
||||
success = rubric_dict['success']
|
||||
rubric_feedback = rubric_dict['html']
|
||||
|
||||
@@ -145,9 +145,9 @@ class OpenEndedChild(object):
|
||||
# Used for progress / grading. Currently get credit just for
|
||||
# completion (doesn't matter if you self-assessed correct/incorrect).
|
||||
if system.open_ended_grading_interface:
|
||||
self.peer_gs = PeerGradingService(system.open_ended_grading_interface, system)
|
||||
self.peer_gs = PeerGradingService(system.open_ended_grading_interface, system.render_template)
|
||||
self.controller_qs = controller_query_service.ControllerQueryService(
|
||||
system.open_ended_grading_interface, system
|
||||
system.open_ended_grading_interface, system.render_template
|
||||
)
|
||||
else:
|
||||
self.peer_gs = MockPeerGradingService()
|
||||
|
||||
@@ -14,8 +14,8 @@ class PeerGradingService(GradingService):
|
||||
|
||||
METRIC_NAME = 'edxapp.open_ended_grading.peer_grading_service'
|
||||
|
||||
def __init__(self, config, system):
|
||||
config['system'] = system
|
||||
def __init__(self, config, render_template):
|
||||
config['render_template'] = render_template
|
||||
super(PeerGradingService, self).__init__(config)
|
||||
self.url = config['url'] + config['peer_grading']
|
||||
self.login_url = self.url + '/login/'
|
||||
@@ -27,7 +27,6 @@ class PeerGradingService(GradingService):
|
||||
self.get_problem_list_url = self.url + '/get_problem_list/'
|
||||
self.get_notifications_url = self.url + '/get_notifications/'
|
||||
self.get_data_for_location_url = self.url + '/get_data_for_location/'
|
||||
self.system = system
|
||||
|
||||
def get_data_for_location(self, problem_location, student_id):
|
||||
if isinstance(problem_location, UsageKey):
|
||||
|
||||
@@ -119,7 +119,7 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
|
||||
if self.child_state == self.INITIAL:
|
||||
return ''
|
||||
|
||||
rubric_renderer = CombinedOpenEndedRubric(system, False)
|
||||
rubric_renderer = CombinedOpenEndedRubric(system.render_template, False)
|
||||
rubric_dict = rubric_renderer.render_rubric(self.child_rubric)
|
||||
success = rubric_dict['success']
|
||||
rubric_html = rubric_dict['html']
|
||||
|
||||
@@ -125,7 +125,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
|
||||
# We need to set the location here so the child modules can use it.
|
||||
self.runtime.set('location', self.location)
|
||||
if (self.runtime.open_ended_grading_interface):
|
||||
self.peer_gs = PeerGradingService(self.system.open_ended_grading_interface, self.system)
|
||||
self.peer_gs = PeerGradingService(self.system.open_ended_grading_interface, self.system.render_template)
|
||||
else:
|
||||
self.peer_gs = MockPeerGradingService()
|
||||
|
||||
@@ -497,7 +497,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
|
||||
try:
|
||||
response = self.peer_gs.save_calibration_essay(**data_dict)
|
||||
if 'actual_rubric' in response:
|
||||
rubric_renderer = combined_open_ended_rubric.CombinedOpenEndedRubric(self.system, True)
|
||||
rubric_renderer = combined_open_ended_rubric.CombinedOpenEndedRubric(self.system.render_template, True)
|
||||
response['actual_rubric'] = rubric_renderer.render_rubric(response['actual_rubric'])['html']
|
||||
return response
|
||||
except GradingServiceError:
|
||||
|
||||
@@ -10,7 +10,6 @@ from xmodule.open_ended_grading_classes.controller_query_service import Controll
|
||||
from xmodule.modulestore.django import ModuleI18nService
|
||||
|
||||
from courseware.access import has_access
|
||||
from lms.djangoapps.lms_xblock.runtime import LmsModuleSystem
|
||||
from edxmako.shortcuts import render_to_string
|
||||
from student.models import unique_id_for_user
|
||||
from util.cache import cache
|
||||
@@ -66,17 +65,7 @@ def staff_grading_notifications(course, user):
|
||||
|
||||
|
||||
def peer_grading_notifications(course, user):
|
||||
system = LmsModuleSystem(
|
||||
track_function=None,
|
||||
get_module=None,
|
||||
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)
|
||||
peer_gs = peer_grading_service.PeerGradingService(settings.OPEN_ENDED_GRADING_INTERFACE, render_to_string)
|
||||
pending_grading = False
|
||||
img_path = ""
|
||||
course_id = course.id
|
||||
@@ -128,20 +117,8 @@ def combined_notifications(course, user):
|
||||
if not user.is_authenticated():
|
||||
return notification_dict
|
||||
|
||||
#Define a mock modulesystem
|
||||
system = LmsModuleSystem(
|
||||
static_url="/static",
|
||||
track_function=None,
|
||||
get_module=None,
|
||||
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)
|
||||
controller_qs = ControllerQueryService(settings.OPEN_ENDED_GRADING_INTERFACE, render_to_string)
|
||||
student_id = unique_id_for_user(user)
|
||||
user_is_staff = has_access(user, 'staff', course)
|
||||
course_id = course.id
|
||||
|
||||
@@ -14,7 +14,6 @@ from xmodule.open_ended_grading_classes.grading_service_module import GradingSer
|
||||
from xmodule.modulestore.django import ModuleI18nService
|
||||
|
||||
from courseware.access import has_access
|
||||
from lms.djangoapps.lms_xblock.runtime import LmsModuleSystem
|
||||
from edxmako.shortcuts import render_to_string
|
||||
from student.models import unique_id_for_user
|
||||
|
||||
@@ -90,17 +89,7 @@ class StaffGradingService(GradingService):
|
||||
METRIC_NAME = 'edxapp.open_ended_grading.staff_grading_service'
|
||||
|
||||
def __init__(self, config):
|
||||
config['system'] = LmsModuleSystem(
|
||||
static_url='/static',
|
||||
track_function=None,
|
||||
get_module=None,
|
||||
render_template=render_to_string,
|
||||
replace_urls=None,
|
||||
descriptor_runtime=None,
|
||||
services={
|
||||
'i18n': ModuleI18nService(),
|
||||
},
|
||||
)
|
||||
config['render_template'] = render_to_string
|
||||
super(StaffGradingService, self).__init__(config)
|
||||
self.url = config['url'] + config['staff_grading']
|
||||
self.login_url = self.url + '/login/'
|
||||
|
||||
@@ -469,7 +469,7 @@ class TestPanel(ModuleStoreTestCase):
|
||||
Mock(
|
||||
return_value=controller_query_service.MockControllerQueryService(
|
||||
settings.OPEN_ENDED_GRADING_INTERFACE,
|
||||
utils.SYSTEM
|
||||
utils.render_to_string
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -9,7 +9,6 @@ from xmodule.open_ended_grading_classes.grading_service_module import GradingSer
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.conf import settings
|
||||
|
||||
from lms.djangoapps.lms_xblock.runtime import LmsModuleSystem
|
||||
from edxmako.shortcuts import render_to_string
|
||||
|
||||
|
||||
@@ -26,18 +25,6 @@ GRADER_DISPLAY_NAMES = {
|
||||
STUDENT_ERROR_MESSAGE = _("Error occurred while contacting the grading service. Please notify course staff.")
|
||||
STAFF_ERROR_MESSAGE = _("Error occurred while contacting the grading service. Please notify your edX point of contact.")
|
||||
|
||||
SYSTEM = LmsModuleSystem(
|
||||
static_url='/static',
|
||||
track_function=None,
|
||||
get_module=None,
|
||||
render_template=render_to_string,
|
||||
replace_urls=None,
|
||||
descriptor_runtime=None,
|
||||
services={
|
||||
'i18n': ModuleI18nService(),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def generate_problem_url(problem_url_parts, base_course_url):
|
||||
"""
|
||||
@@ -85,7 +72,7 @@ def create_controller_query_service():
|
||||
"""
|
||||
Return an instance of a service that can query edX ORA.
|
||||
"""
|
||||
return ControllerQueryService(settings.OPEN_ENDED_GRADING_INTERFACE, SYSTEM)
|
||||
return ControllerQueryService(settings.OPEN_ENDED_GRADING_INTERFACE, render_to_string)
|
||||
|
||||
|
||||
class StudentProblemList(object):
|
||||
|
||||
@@ -481,10 +481,18 @@ class Order(models.Model):
|
||||
log.exception('Exception at creating pdf file.')
|
||||
pdf_file = None
|
||||
|
||||
self.send_confirmation_emails(
|
||||
orderitems, self.order_type == OrderTypes.BUSINESS,
|
||||
csv_file, pdf_file, site_name, courses_info
|
||||
)
|
||||
try:
|
||||
self.send_confirmation_emails(
|
||||
orderitems, self.order_type == OrderTypes.BUSINESS,
|
||||
csv_file, pdf_file, site_name, courses_info
|
||||
)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# Catch all exceptions here, since the Django view implicitly
|
||||
# wraps this in a transaction. If the order completes successfully,
|
||||
# we don't want to roll back just because we couldn't send
|
||||
# the confirmation email.
|
||||
log.exception('Error occurred while sending payment confirmation email')
|
||||
|
||||
self._emit_order_event('Completed Order', orderitems)
|
||||
|
||||
def refund(self):
|
||||
@@ -1460,7 +1468,9 @@ class CertificateItem(OrderItem):
|
||||
"If you haven't verified your identity yet, please start the verification process ({verification_url})."
|
||||
).format(verification_url=verification_url)
|
||||
|
||||
return "{verification_reminder} {refund_reminder}".format(
|
||||
# Need this to be unicode in case the reminder strings
|
||||
# have been translated and contain non-ASCII unicode
|
||||
return u"{verification_reminder} {refund_reminder}".format(
|
||||
verification_reminder=verification_reminder,
|
||||
refund_reminder=refund_reminder
|
||||
)
|
||||
|
||||
@@ -375,6 +375,34 @@ class OrderTest(ModuleStoreTestCase):
|
||||
cart.generate_receipt_instructions()
|
||||
mock_gen_inst.assert_called_with()
|
||||
|
||||
def test_confirmation_email_error(self):
|
||||
CourseMode.objects.create(
|
||||
course_id=self.course_key,
|
||||
mode_slug="verified",
|
||||
mode_display_name="Verified",
|
||||
min_price=self.cost
|
||||
)
|
||||
|
||||
cart = Order.get_cart_for_user(self.user)
|
||||
CertificateItem.add_to_order(cart, self.course_key, self.cost, 'verified')
|
||||
|
||||
# Simulate an error when sending the confirmation
|
||||
# email. This should NOT raise an exception.
|
||||
# If it does, then the implicit view-level
|
||||
# transaction could cause a roll-back, effectively
|
||||
# reversing order fulfillment.
|
||||
with patch.object(mail.message.EmailMessage, 'send') as mock_send:
|
||||
mock_send.side_effect = Exception("Kaboom!")
|
||||
cart.purchase()
|
||||
|
||||
# Verify that the purchase completed successfully
|
||||
self.assertEqual(cart.status, 'purchased')
|
||||
|
||||
# Verify that the user is enrolled as "verified"
|
||||
mode, is_active = CourseEnrollment.enrollment_mode_for_user(self.user, self.course_key)
|
||||
self.assertTrue(is_active)
|
||||
self.assertEqual(mode, 'verified')
|
||||
|
||||
|
||||
class OrderItemTest(TestCase):
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user