From f35478e2dca74ce600cac9c8f3d285c241e701d4 Mon Sep 17 00:00:00 2001 From: stv Date: Sun, 15 Feb 2015 17:20:09 -0800 Subject: [PATCH 01/31] Fix Pylint: E0101(return-in-init) --- common/lib/xmodule/xmodule/exceptions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/lib/xmodule/xmodule/exceptions.py b/common/lib/xmodule/xmodule/exceptions.py index a6d3686ca2fd..d1f05171da47 100644 --- a/common/lib/xmodule/xmodule/exceptions.py +++ b/common/lib/xmodule/xmodule/exceptions.py @@ -53,4 +53,4 @@ def __init__(self, msg, service): In addition to a msg, provide the name of the service. """ self.service = service - return super(HeartbeatFailure, self).__init__(msg) + super(HeartbeatFailure, self).__init__(msg) From 3311ce989a77fe92d2c223029f07e4f7ed6413d6 Mon Sep 17 00:00:00 2001 From: stv Date: Sun, 15 Feb 2015 17:26:24 -0800 Subject: [PATCH 02/31] Fix Pylint: E0211(no-method-argument) I can find no other record of this class. --- lms/djangoapps/django_comment_client/tests/test_models.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lms/djangoapps/django_comment_client/tests/test_models.py b/lms/djangoapps/django_comment_client/tests/test_models.py index 41a012a618fe..03c981528acb 100644 --- a/lms/djangoapps/django_comment_client/tests/test_models.py +++ b/lms/djangoapps/django_comment_client/tests/test_models.py @@ -34,10 +34,6 @@ def setUp(self): self.TA_role_2 = models.Role.objects.get_or_create(name="Community TA", course_id=self.course_id_2)[0] - class Dummy(): - def render_template(): - pass - def test_has_permission(self): # Whenever you add a permission to student_role, # Roles with the same FORUM_ROLE in same class also receives the same From 6389c6f09cde79b0d5bd2fab1a6307879a17fa6d Mon Sep 17 00:00:00 2001 From: stv Date: Sun, 15 Feb 2015 17:49:27 -0800 Subject: [PATCH 03/31] Fix Pylint: C0103(invalid-name) --- cms/urls.py | 22 ++-- .../management/commands/ungenerated_certs.py | 12 +- lms/djangoapps/certificates/models.py | 12 +- lms/djangoapps/certificates/views.py | 8 +- lms/djangoapps/circuit/views.py | 20 ++-- .../plugins/markdownedx/mdx_circuit.py | 10 +- .../plugins/markdownedx/mdx_mathjax.py | 6 +- lms/djangoapps/courseware/views.py | 10 +- lms/djangoapps/debug/views.py | 16 +-- .../django_comment_client/permissions.py | 9 +- .../staff_grading_service.py | 32 +++--- lms/djangoapps/open_ended_grading/tests.py | 12 +- lms/djangoapps/open_ended_grading/views.py | 8 +- lms/djangoapps/psychometrics/models.py | 16 +-- lms/djangoapps/psychometrics/psychoanalyze.py | 89 ++++++++------- .../shoppingcart/processors/CyberSource.py | 6 +- .../shoppingcart/processors/CyberSource2.py | 6 +- .../processors/tests/test_CyberSource.py | 6 +- .../shoppingcart/tests/test_views.py | 105 ++++++++++-------- .../verify_student/tests/test_views.py | 20 ++-- lms/urls.py | 51 +++++---- 21 files changed, 259 insertions(+), 217 deletions(-) diff --git a/cms/urls.py b/cms/urls.py index 4ca692f10975..fbcc594276a8 100644 --- a/cms/urls.py +++ b/cms/urls.py @@ -114,16 +114,20 @@ url(r'^api/val/v0/', include('edxval.urls')), ) -js_info_dict = { - 'domain': 'djangojs', - # We need to explicitly include external Django apps that are not in LOCALE_PATHS. - 'packages': ('openassessment',), -} - -urlpatterns += patterns( - '', +urlpatterns += ( # Serve catalog of localized strings to be rendered by Javascript - url(r'^i18n.js$', 'django.views.i18n.javascript_catalog', js_info_dict), + url( + r'^jsi18n/$', + 'django.views.i18n.javascript_catalog', + { + 'domain': 'djangojs', + # We need to explicitly include external Django apps that + # are not in LOCALE_PATHS. + 'packages': ( + 'openassessment', + ), + }, + ), ) if settings.FEATURES.get('ENABLE_CONTENT_LIBRARIES'): diff --git a/lms/djangoapps/certificates/management/commands/ungenerated_certs.py b/lms/djangoapps/certificates/management/commands/ungenerated_certs.py index 838e4224a3b0..2c01546efbe7 100644 --- a/lms/djangoapps/certificates/management/commands/ungenerated_certs.py +++ b/lms/djangoapps/certificates/management/commands/ungenerated_certs.py @@ -81,7 +81,7 @@ def handle(self, *args, **options): # Print update after this many students - STATUS_INTERVAL = 500 + status_interval = 500 if options['course']: # try to parse out the course from the serialized form @@ -108,21 +108,21 @@ def handle(self, *args, **options): courseenrollment__course_id=course_key ) - xq = XQueueCertInterface() + xqueue = XQueueCertInterface() if options['insecure']: - xq.use_https = False + xqueue.use_https = False total = enrolled_students.count() count = 0 start = datetime.datetime.now(UTC) for student in enrolled_students: count += 1 - if count % STATUS_INTERVAL == 0: + if count % status_interval == 0: # Print a status update with an approximation of # how much time is left based on how long the last # interval took diff = datetime.datetime.now(UTC) - start - timeleft = diff * (total - count) / STATUS_INTERVAL + timeleft = diff * (total - count) / status_interval hours, remainder = divmod(timeleft.seconds, 3600) minutes, seconds = divmod(remainder, 60) print "{0}/{1} completed ~{2:02}:{3:02}m remaining".format( @@ -144,7 +144,7 @@ def handle(self, *args, **options): if not options['noop']: # Add the certificate request to the queue - ret = xq.add_cert(student, course_key, course=course) + ret = xqueue.add_cert(student, course_key, course=course) if ret == 'generating': LOGGER.info( diff --git a/lms/djangoapps/certificates/models.py b/lms/djangoapps/certificates/models.py index 0476579da597..1692daad155f 100644 --- a/lms/djangoapps/certificates/models.py +++ b/lms/djangoapps/certificates/models.py @@ -165,14 +165,16 @@ def certificate_status_for_student(student, course_id): try: generated_certificate = GeneratedCertificate.objects.get( user=student, course_id=course_id) - d = {'status': generated_certificate.status, - 'mode': generated_certificate.mode} + data = { + 'status': generated_certificate.status, + 'mode': generated_certificate.mode, + } if generated_certificate.grade: - d['grade'] = generated_certificate.grade + data['grade'] = generated_certificate.grade if generated_certificate.status == CertificateStatuses.downloadable: - d['download_url'] = generated_certificate.download_url + data['download_url'] = generated_certificate.download_url - return d + return data except GeneratedCertificate.DoesNotExist: pass return {'status': CertificateStatuses.unavailable, 'mode': GeneratedCertificate.MODES.honor} diff --git a/lms/djangoapps/certificates/views.py b/lms/djangoapps/certificates/views.py index 13d341dc1aab..b45d35e31125 100644 --- a/lms/djangoapps/certificates/views.py +++ b/lms/djangoapps/certificates/views.py @@ -14,7 +14,7 @@ from xmodule.modulestore.django import modulestore from opaque_keys.edx.locations import SlashSeparatedCourseKey -logger = logging.getLogger(__name__) +LOGGER = logging.getLogger(__name__) @csrf_exempt @@ -37,7 +37,7 @@ def request_certificate(request): status = certificate_status_for_student(student, course_key)['status'] if status in [CertificateStatuses.unavailable, CertificateStatuses.notpassing, CertificateStatuses.error]: log_msg = u'Grading and certification requested for user %s in course %s via /request_certificate call' - logger.info(log_msg, username, course_key) + LOGGER.info(log_msg, username, course_key) status = xqci.add_cert(student, course_key, course=course) return HttpResponse(json.dumps({'add_status': status}), mimetype='application/json') return HttpResponse(json.dumps({'add_status': 'ERRORANONYMOUSUSER'}), mimetype='application/json') @@ -69,7 +69,7 @@ def update_certificate(request): key=xqueue_header['lms_key']) except GeneratedCertificate.DoesNotExist: - logger.critical('Unable to lookup certificate\n' + LOGGER.critical('Unable to lookup certificate\n' 'xqueue_body: {0}\n' 'xqueue_header: {1}'.format( xqueue_body, xqueue_header)) @@ -103,7 +103,7 @@ def update_certificate(request): elif cert.status in [status.deleting]: cert.status = status.deleted else: - logger.critical('Invalid state for cert update: {0}'.format( + LOGGER.critical('Invalid state for cert update: {0}'.format( cert.status)) return HttpResponse( json.dumps({ diff --git a/lms/djangoapps/circuit/views.py b/lms/djangoapps/circuit/views.py index 5af9ce1b4456..5def57ae970d 100644 --- a/lms/djangoapps/circuit/views.py +++ b/lms/djangoapps/circuit/views.py @@ -15,8 +15,8 @@ def circuit_line(circuit): if not circuit.isalnum(): raise Http404() try: - sc = ServerCircuit.objects.get(name=circuit) - schematic = sc.schematic + server_circuit = ServerCircuit.objects.get(name=circuit) + schematic = server_circuit.schematic except: schematic = '' @@ -33,9 +33,9 @@ def circuit_line(circuit): def edit_circuit(request, circuit): try: - sc = ServerCircuit.objects.get(name=circuit) + server_circuit = ServerCircuit.objects.get(name=circuit) except: - sc = None + server_circuit = None if not circuit.isalnum(): raise Http404() @@ -52,13 +52,13 @@ def save_circuit(request, circuit): schematic = request.POST['schematic'] print schematic try: - sc = ServerCircuit.objects.get(name=circuit) + server_circuit = ServerCircuit.objects.get(name=circuit) except: - sc = ServerCircuit() - sc.name = circuit - sc.schematic = schematic - print ":", sc.schematic - sc.save() + server_circuit = ServerCircuit() + server_circuit.name = circuit + server_circuit.schematic = schematic + print ":", server_circuit.schematic + server_circuit.save() json_str = json.dumps({'results': 'success'}) response = HttpResponse(json_str, mimetype='application/json') response['Cache-Control'] = 'no-cache' diff --git a/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_circuit.py b/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_circuit.py index f90cb61123bf..162661aac303 100755 --- a/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_circuit.py +++ b/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_circuit.py @@ -50,9 +50,9 @@ class CircuitPreprocessor(markdown.preprocessors.Preprocessor): def run(self, lines): def convertLine(line): - m = self.preRegex.match(line) - if m: - return 'processed-schematic:{0}processed-schematic-end'.format(m.group('data')) + match = self.preRegex.match(line) + if match: + return 'processed-schematic:{0}processed-schematic-end'.format(match.group('data')) else: return line @@ -60,8 +60,8 @@ def convertLine(line): class CircuitLink(markdown.inlinepatterns.Pattern): - def handleMatch(self, m): - data = m.group('data') + def handleMatch(self, match): + data = match.group('data') data = escape(data) return etree.fromstring("
") diff --git a/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_mathjax.py b/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_mathjax.py index b14803744b70..7b5f26b71236 100644 --- a/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_mathjax.py +++ b/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_mathjax.py @@ -15,9 +15,9 @@ def __init__(self): markdown.inlinepatterns.Pattern.__init__(self, r'(? 0: return _err_response('Missing required keys {0}'.format( ', '.join(missing))) - success, message = check_feedback_length(p) + success, message = check_feedback_length(post) if not success: return _err_response(message) grader_id = unique_id_for_user(request.user) - location = course_key.make_usage_key_from_deprecated_string(p['location']) + location = course_key.make_usage_key_from_deprecated_string(post['location']) try: - result = staff_grading_service().save_grade(course_key, - grader_id, - p['submission_id'], - p['score'], - p['feedback'], - skipped, - p.getlist('rubric_scores[]'), - p['submission_flagged']) + result = staff_grading_service().save_grade( + course_key, + grader_id, + post['submission_id'], + post['score'], + post['feedback'], + skipped, + post.getlist('rubric_scores[]'), + post['submission_flagged'], + ) except GradingServiceError: #This is a dev_facing_error log.exception( diff --git a/lms/djangoapps/open_ended_grading/tests.py b/lms/djangoapps/open_ended_grading/tests.py index 35d0fd2a05e2..38bb38b1acc5 100644 --- a/lms/djangoapps/open_ended_grading/tests.py +++ b/lms/djangoapps/open_ended_grading/tests.py @@ -313,9 +313,9 @@ def test_get_next_submission_success(self): def test_get_next_submission_missing_location(self): data = {} - d = self.peer_module.get_next_submission(data) - self.assertFalse(d['success']) - self.assertEqual(d['error'], "Missing required keys: location") + response = self.peer_module.get_next_submission(data) + self.assertFalse(response['success']) + self.assertEqual(response['error'], 'Missing required keys: location') def test_save_grade_success(self): data = { @@ -345,9 +345,9 @@ def fake_get_item(key): def test_save_grade_missing_keys(self): data = {} - d = self.peer_module.save_grade(data) - self.assertFalse(d['success']) - self.assertTrue(d['error'].find('Missing required keys:') > -1) + response = self.peer_module.save_grade(data) + self.assertFalse(response['success']) + self.assertTrue(response['error'].find('Missing required keys:') > -1) def test_is_calibrated_success(self): data = {'location': self.location_string} diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py index 1fe0d82e3921..8fddfccacbe1 100644 --- a/lms/djangoapps/open_ended_grading/views.py +++ b/lms/djangoapps/open_ended_grading/views.py @@ -316,10 +316,10 @@ def take_action_on_flags(request, course_id): } return HttpResponse(json.dumps(response), mimetype="application/json") - p = request.POST - submission_id = p['submission_id'] - action_type = p['action_type'] - student_id = p['student_id'] + post = request.POST + submission_id = post['submission_id'] + action_type = post['action_type'] + student_id = post['student_id'] student_id = student_id.strip(' \t\n\r') submission_id = submission_id.strip(' \t\n\r') action_type = action_type.lower().strip(' \t\n\r') diff --git a/lms/djangoapps/psychometrics/models.py b/lms/djangoapps/psychometrics/models.py index 4af5544c6cc1..dbb73f0c182e 100644 --- a/lms/djangoapps/psychometrics/models.py +++ b/lms/djangoapps/psychometrics/models.py @@ -34,10 +34,12 @@ class PsychometricData(models.Model): # location = studentmodule.module_state_key def __unicode__(self): - sm = self.studentmodule - return "[PsychometricData] %s url=%s, grade=%s, max=%s, attempts=%s, ct=%s" % (sm.student, - sm.module_state_key, - sm.grade, - sm.max_grade, - self.attempts, - self.checktimes) + student_module = self.studentmodule + return "[PsychometricData] %s url=%s, grade=%s, max=%s, attempts=%s, ct=%s" % ( + student_module.student, + student_module.module_state_key, + student_module.grade, + student_module.max_grade, + self.attempts, + self.checktimes, + ) diff --git a/lms/djangoapps/psychometrics/psychoanalyze.py b/lms/djangoapps/psychometrics/psychoanalyze.py index bc164219c467..6af917a6853b 100644 --- a/lms/djangoapps/psychometrics/psychoanalyze.py +++ b/lms/djangoapps/psychometrics/psychoanalyze.py @@ -30,12 +30,12 @@ # fit functions -def func_2pl(x, a, b): +def func_2pl(x_axis, a, b): """ 2-parameter logistic function """ D = 1.7 - edax = np.exp(D * a * (x - b)) + edax = np.exp(D * a * (x_axis - b)) return edax / (1 + edax) #----------------------------------------------------------------------------- @@ -54,21 +54,21 @@ def __init__(self, unit=1): self.min = None self.max = None - def add(self, x): - if x is None: + def add(self, x_axis): + if x_axis is None: return if self.min is None: - self.min = x + self.min = x_axis else: - if x < self.min: - self.min = x + if x_axis < self.min: + self.min = x_axis if self.max is None: - self.max = x + self.max = x_axis else: - if x > self.max: - self.max = x - self.sum += x - self.sum2 += x ** 2 + if x_axis > self.max: + self.max = x_axis + self.sum += x_axis + self.sum2 += x_axis ** 2 self.cnt += 1 def avg(self): @@ -82,17 +82,17 @@ def var(self): return (self.sum2 / 1.0 / self.cnt / (self.unit ** 2)) - (self.avg() ** 2) def sdv(self): - v = self.var() - if v > 0: - return math.sqrt(v) + value = self.var() + if value > 0: + return math.sqrt(value) else: return 0 def __str__(self): return 'cnt=%d, avg=%f, sdv=%f' % (self.cnt, self.avg(), self.sdv()) - def __add__(self, x): - self.add(x) + def __add__(self, x_axis): + self.add(x_axis) return self #----------------------------------------------------------------------------- @@ -112,9 +112,9 @@ def make_histogram(ydata, bins=None): nbins = len(bins) hist = dict(zip(bins, [0] * nbins)) - for y in ydata: + for y_axis in ydata: for b in bins[::-1]: # in reverse order - if y > b: + if y_axis > b: hist[b] += 1 break # hist['bins'] = bins @@ -171,8 +171,8 @@ def generate_plots_for_problem(problem): # compute grade statistics grades = [pmd.studentmodule.grade for pmd in pmdset] gsv = StatVar() - for g in grades: - gsv += g + for grade in grades: + gsv += grade msg += "

Grade distribution: %s

" % gsv # generate grade histogram @@ -218,18 +218,18 @@ def generate_plots_for_problem(problem): if len(checktimes) < 2: continue ct0 = checktimes[0] - for ct in checktimes[1:]: - dt = (ct - ct0).total_seconds() / 60.0 - if dt < 20: # ignore if dt too long - dtset.append(dt) - dtsv += dt - ct0 = ct + for check_time in checktimes[1:]: + delta = (check_time - ct0).total_seconds() / 60.0 + if delta < 20: # ignore if delta too long + dtset.append(delta) + dtsv += delta + ct0 = check_time if dtsv.cnt > 2: msg += "

Time differences between checks: %s

" % dtsv bins = np.linspace(0, 1.5 * dtsv.sdv(), 30) dbar = bins[1] - bins[0] thist = make_histogram(dtset, bins) - thist_json = json.dumps(sorted(thist.items(), key=lambda(x): x[0])) + thist_json = json.dumps(sorted(thist.items(), key=lambda(x_axis): x_axis[0])) axisopts = """{ xaxes: [{ axisLabel: 'Time (min)'}], yaxes: [{position: 'left',axisLabel: 'Count'}]}""" @@ -250,10 +250,10 @@ def generate_plots_for_problem(problem): continue ydat = [] ylast = 0 - for x in xdat: - y = gset.filter(attempts=x).count() / ngset - ydat.append(y + ylast) - ylast = y + ylast + for x_axis in xdat: + y_axis = gset.filter(attempts=x_axis).count() / ngset + ydat.append(y_axis + ylast) + ylast = y_axis + ylast yset['ydat'] = ydat if len(ydat) > 3: # try to fit to logistic function if enough data points @@ -316,7 +316,7 @@ def make_psychometrics_data_update_handler(course_id, user, module_state_key): Construct and return a procedure which may be called to update the PsychometricData instance for the given StudentModule instance. """ - sm, status = StudentModule.objects.get_or_create( + student_module, status = StudentModule.objects.get_or_create( course_id=course_id, student=user, module_state_key=module_state_key, @@ -324,9 +324,9 @@ def make_psychometrics_data_update_handler(course_id, user, module_state_key): ) try: - pmd = PsychometricData.objects.using(db).get(studentmodule=sm) + pmd = PsychometricData.objects.using(db).get(studentmodule=student_module) except PsychometricData.DoesNotExist: - pmd = PsychometricData(studentmodule=sm) + pmd = PsychometricData(studentmodule=student_module) def psychometrics_data_update_handler(state): """ @@ -336,17 +336,25 @@ def psychometrics_data_update_handler(state): state = instance state (a nice, uniform way to interface - for more future psychometric feature extraction) """ try: - state = json.loads(sm.state) + state = json.loads(student_module.state) done = state['done'] except: - log.exception("Oops, failed to eval state for %s (state=%s)" % (sm, sm.state)) + log.exception( + "Oops, failed to eval state for %s (state=%s)", + student_module, + student_module.state, + ) return pmd.done = done try: pmd.attempts = state.get('attempts', 0) except: - log.exception("no attempts for %s (state=%s)" % (sm, sm.state)) + log.exception( + "no attempts for %s (state=%s)", + student_module, + student_module.state, + ) try: checktimes = eval(pmd.checktimes) # update log of attempt timestamps @@ -357,6 +365,9 @@ def psychometrics_data_update_handler(state): try: pmd.save() except: - log.exception("Error in updating psychometrics data for %s" % sm) + log.exception( + "Error in updating psychometrics data for %s", + student_module, + ) return psychometrics_data_update_handler diff --git a/lms/djangoapps/shoppingcart/processors/CyberSource.py b/lms/djangoapps/shoppingcart/processors/CyberSource.py index 0e6c12939b6d..9d1334d18767 100644 --- a/lms/djangoapps/shoppingcart/processors/CyberSource.py +++ b/lms/djangoapps/shoppingcart/processors/CyberSource.py @@ -219,9 +219,9 @@ def record_purchase(params, order): Record the purchase and run purchased_callbacks """ ccnum_str = params.get('card_accountNumber', '') - m = re.search("\d", ccnum_str) - if m: - ccnum = ccnum_str[m.start():] + match = re.search('\d', ccnum_str) + if match: + ccnum = ccnum_str[match.start():] else: ccnum = "####" diff --git a/lms/djangoapps/shoppingcart/processors/CyberSource2.py b/lms/djangoapps/shoppingcart/processors/CyberSource2.py index 37450b084e2f..9c9e09705f94 100644 --- a/lms/djangoapps/shoppingcart/processors/CyberSource2.py +++ b/lms/djangoapps/shoppingcart/processors/CyberSource2.py @@ -401,9 +401,9 @@ def _record_purchase(params, order): # Parse the string to retrieve the digits. # If we can't find any digits, use placeholder values instead. ccnum_str = params.get('req_card_number', '') - mm = re.search("\d", ccnum_str) - if mm: - ccnum = ccnum_str[mm.start():] + match = re.search('\d', ccnum_str) + if match: + ccnum = ccnum_str[match.start():] else: ccnum = "####" diff --git a/lms/djangoapps/shoppingcart/processors/tests/test_CyberSource.py b/lms/djangoapps/shoppingcart/processors/tests/test_CyberSource.py index d719e06f8988..4b1db74917d2 100644 --- a/lms/djangoapps/shoppingcart/processors/tests/test_CyberSource.py +++ b/lms/djangoapps/shoppingcart/processors/tests/test_CyberSource.py @@ -143,14 +143,14 @@ def test_get_processor_decline_html(self): """ Tests the processor decline html message """ - DECISION = 'REJECT' + decision = 'REJECT' for code, reason in REASONCODE_MAP.iteritems(): params = { - 'decision': DECISION, + 'decision': decision, 'reasonCode': code, } html = get_processor_decline_html(params) - self.assertIn(DECISION, html) + self.assertIn(decision, html) self.assertIn(reason, html) self.assertIn(code, html) self.assertIn(settings.PAYMENT_SUPPORT_EMAIL, html) diff --git a/lms/djangoapps/shoppingcart/tests/test_views.py b/lms/djangoapps/shoppingcart/tests/test_views.py index fb5606095cfb..9a54f4abb938 100644 --- a/lms/djangoapps/shoppingcart/tests/test_views.py +++ b/lms/djangoapps/shoppingcart/tests/test_views.py @@ -51,15 +51,15 @@ def mock_render_purchase_form_html(*args, **kwargs): return render_purchase_form_html(*args, **kwargs) -form_mock = Mock(side_effect=mock_render_purchase_form_html) +MOCK_FORM = Mock(side_effect=mock_render_purchase_form_html) def mock_render_to_response(*args, **kwargs): return render_to_response(*args, **kwargs) -render_mock = Mock(side_effect=mock_render_to_response) +MOCK_RENDER = Mock(side_effect=mock_render_to_response) -postpay_mock = Mock() +MOCK_POST_PAY = Mock() @patch.dict('django.conf.settings.FEATURES', {'ENABLE_PAID_COURSE_REGISTRATION': True}) @@ -155,7 +155,7 @@ def test_add_course_to_cart_anon(self): resp = self.client.post(reverse('shoppingcart.views.add_course_to_cart', args=[self.course_key.to_deprecated_string()])) self.assertEqual(resp.status_code, 403) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_billing_details(self): billing_url = reverse('billing_details') self.login_user() @@ -170,7 +170,7 @@ def test_billing_details(self): resp = self.client.get(billing_url) self.assertEqual(resp.status_code, 200) - ((template, context), _) = render_mock.call_args # pylint: disable=redefined-outer-name + ((template, context), _) = MOCK_RENDER.call_args # pylint: disable=redefined-outer-name self.assertEqual(template, 'shoppingcart/billing_details.html') # check for the default currency in the context self.assertEqual(context['currency'], 'usd') @@ -186,7 +186,7 @@ def test_billing_details(self): resp = self.client.post(billing_url, data) self.assertEqual(resp.status_code, 200) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) @override_settings(PAID_COURSE_REGISTRATION_CURRENCY=['PKR', 'Rs']) def test_billing_details_with_override_currency_settings(self): billing_url = reverse('billing_details') @@ -198,7 +198,7 @@ def test_billing_details_with_override_currency_settings(self): resp = self.client.get(billing_url) self.assertEqual(resp.status_code, 200) - ((template, context), __) = render_mock.call_args # pylint: disable=redefined-outer-name + ((template, context), __) = MOCK_RENDER.call_args # pylint: disable=redefined-outer-name self.assertEqual(template, 'shoppingcart/billing_details.html') # check for the override currency settings in the context @@ -719,8 +719,8 @@ def test_add_course_to_cart_success(self): self.assertEqual(resp.status_code, 200) self.assertTrue(PaidCourseRegistration.contained_in_order(self.cart, self.course_key)) - @patch('shoppingcart.views.render_purchase_form_html', form_mock) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_purchase_form_html', MOCK_FORM) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_show_cart(self): self.login_user() reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_key) @@ -728,13 +728,13 @@ def test_show_cart(self): resp = self.client.get(reverse('shoppingcart.views.show_cart', args=[])) self.assertEqual(resp.status_code, 200) - ((purchase_form_arg_cart,), _) = form_mock.call_args # pylint: disable=redefined-outer-name + ((purchase_form_arg_cart,), _) = MOCK_FORM.call_args # pylint: disable=redefined-outer-name purchase_form_arg_cart_items = purchase_form_arg_cart.orderitem_set.all().select_subclasses() self.assertIn(reg_item, purchase_form_arg_cart_items) self.assertIn(cert_item, purchase_form_arg_cart_items) self.assertEqual(len(purchase_form_arg_cart_items), 2) - ((template, context), _) = render_mock.call_args + ((template, context), _) = MOCK_RENDER.call_args self.assertEqual(template, 'shoppingcart/shopping_cart.html') self.assertEqual(len(context['shoppingcart_items']), 2) self.assertEqual(context['amount'], 80) @@ -743,8 +743,8 @@ def test_show_cart(self): self.assertEqual(context['currency'], 'usd') self.assertEqual(context['currency_symbol'], '$') - @patch('shoppingcart.views.render_purchase_form_html', form_mock) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_purchase_form_html', MOCK_FORM) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) @override_settings(PAID_COURSE_REGISTRATION_CURRENCY=['PKR', 'Rs']) def test_show_cart_with_override_currency_settings(self): self.login_user() @@ -752,11 +752,11 @@ def test_show_cart_with_override_currency_settings(self): resp = self.client.get(reverse('shoppingcart.views.show_cart', args=[])) self.assertEqual(resp.status_code, 200) - ((purchase_form_arg_cart,), _) = form_mock.call_args # pylint: disable=redefined-outer-name + ((purchase_form_arg_cart,), _) = MOCK_FORM.call_args # pylint: disable=redefined-outer-name purchase_form_arg_cart_items = purchase_form_arg_cart.orderitem_set.all().select_subclasses() self.assertIn(reg_item, purchase_form_arg_cart_items) - ((template, context), _) = render_mock.call_args + ((template, context), _) = MOCK_RENDER.call_args self.assertEqual(template, 'shoppingcart/shopping_cart.html') # check for the override currency settings in the context self.assertEqual(context['currency'], 'PKR') @@ -801,25 +801,32 @@ def test_remove_item(self, exception_log): '-1' ) - @patch('shoppingcart.views.process_postpay_callback', postpay_mock) + @patch('shoppingcart.views.process_postpay_callback', MOCK_POST_PAY) def test_postpay_callback_success(self): - postpay_mock.return_value = {'success': True, 'order': self.cart} + MOCK_POST_PAY.return_value = { + 'success': True, + 'order': self.cart, + } self.login_user() resp = self.client.post(reverse('shoppingcart.views.postpay_callback', args=[])) self.assertEqual(resp.status_code, 302) self.assertEqual(urlparse(resp.__getitem__('location')).path, reverse('shoppingcart.views.show_receipt', args=[self.cart.id])) - @patch('shoppingcart.views.process_postpay_callback', postpay_mock) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.process_postpay_callback', MOCK_POST_PAY) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_postpay_callback_failure(self): - postpay_mock.return_value = {'success': False, 'order': self.cart, 'error_html': 'ERROR_TEST!!!'} + MOCK_POST_PAY.return_value = { + 'success': False, + 'order': self.cart, + 'error_html': 'ERROR_TEST!!!', + } self.login_user() resp = self.client.post(reverse('shoppingcart.views.postpay_callback', args=[])) self.assertEqual(resp.status_code, 200) self.assertIn('ERROR_TEST!!!', resp.content) - ((template, context), _) = render_mock.call_args + ((template, context), _) = MOCK_RENDER.call_args self.assertEqual(template, 'shoppingcart/error.html') self.assertEqual(context['order'], self.cart) self.assertEqual(context['error_html'], 'ERROR_TEST!!!') @@ -959,7 +966,7 @@ def test_total_amount_of_purchased_course(self): total_amount = PaidCourseRegistration.get_total_amount_of_purchased_item(self.course_key) self.assertEqual(total_amount, 76) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_show_receipt_success_with_valid_coupon_code(self): self.add_course_to_user_cart(self.course_key) self.add_coupon(self.course_key, True, self.coupon_code) @@ -973,7 +980,7 @@ def test_show_receipt_success_with_valid_coupon_code(self): self.assertIn('FirstNameTesting123', resp.content) self.assertIn(str(self.get_discount(self.cost)), resp.content) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_reg_code_and_course_registration_scenario(self): self.add_reg_code(self.course_key) @@ -994,7 +1001,7 @@ def test_reg_code_and_course_registration_scenario(self): response = self.client.post(redeem_url) self.assertEquals(response.status_code, 200) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_reg_code_with_multiple_courses_and_checkout_scenario(self): self.add_reg_code(self.course_key) @@ -1024,7 +1031,7 @@ def test_reg_code_with_multiple_courses_and_checkout_scenario(self): resp = self.client.get(reverse('shoppingcart.views.show_receipt', args=[self.cart.id])) self.assertEqual(resp.status_code, 200) - ((template, context), _) = render_mock.call_args # pylint: disable=redefined-outer-name + ((template, context), _) = MOCK_RENDER.call_args # pylint: disable=redefined-outer-name self.assertEqual(template, 'shoppingcart/receipt.html') self.assertEqual(context['order'], self.cart) self.assertEqual(context['order'].total_cost, self.testing_cost) @@ -1040,7 +1047,7 @@ def test_reg_code_with_multiple_courses_and_checkout_scenario(self): self.assertIsNotNone(item2.course_enrollment) self.assertEqual(item2.course_enrollment.course_id, self.testing_course.id) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_show_receipt_success_with_valid_reg_code(self): self.add_course_to_user_cart(self.course_key) self.add_reg_code(self.course_key) @@ -1053,7 +1060,7 @@ def test_show_receipt_success_with_valid_reg_code(self): self.assertEqual(resp.status_code, 200) self.assertIn('0.00', resp.content) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_show_receipt_success(self): reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_key) cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor') @@ -1065,7 +1072,7 @@ def test_show_receipt_success(self): self.assertIn('FirstNameTesting123', resp.content) self.assertIn('80.00', resp.content) - ((template, context), _) = render_mock.call_args # pylint: disable=redefined-outer-name + ((template, context), _) = MOCK_RENDER.call_args # pylint: disable=redefined-outer-name self.assertEqual(template, 'shoppingcart/receipt.html') self.assertEqual(context['order'], self.cart) self.assertIn(reg_item, context['shoppingcart_items'][0]) @@ -1076,7 +1083,7 @@ def test_show_receipt_success(self): self.assertEqual(context['currency'], 'usd') @override_settings(PAID_COURSE_REGISTRATION_CURRENCY=['PKR', 'Rs']) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_show_receipt_success_with_override_currency_settings(self): reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_key) cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor') @@ -1086,7 +1093,7 @@ def test_show_receipt_success_with_override_currency_settings(self): resp = self.client.get(reverse('shoppingcart.views.show_receipt', args=[self.cart.id])) self.assertEqual(resp.status_code, 200) - ((template, context), _) = render_mock.call_args # pylint: disable=redefined-outer-name + ((template, context), _) = MOCK_RENDER.call_args # pylint: disable=redefined-outer-name self.assertEqual(template, 'shoppingcart/receipt.html') self.assertIn(reg_item, context['shoppingcart_items'][0]) self.assertIn(cert_item, context['shoppingcart_items'][1]) @@ -1095,7 +1102,7 @@ def test_show_receipt_success_with_override_currency_settings(self): self.assertEqual(context['currency_symbol'], 'Rs') self.assertEqual(context['currency'], 'PKR') - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_courseregcode_item_total_price(self): self.cart.order_type = 'business' self.cart.save() @@ -1103,7 +1110,7 @@ def test_courseregcode_item_total_price(self): self.cart.purchase(first='FirstNameTesting123', street1='StreetTesting123') self.assertEquals(CourseRegCodeItem.get_total_amount_of_purchased_item(self.course_key), 80) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_show_receipt_success_with_order_type_business(self): self.cart.order_type = 'business' self.cart.save() @@ -1130,7 +1137,7 @@ def test_show_receipt_success_with_order_type_business(self): # fetch the newly generated registration codes course_registration_codes = CourseRegistrationCode.objects.filter(order=self.cart) - ((template, context), _) = render_mock.call_args # pylint: disable=redefined-outer-name + ((template, context), _) = MOCK_RENDER.call_args # pylint: disable=redefined-outer-name self.assertEqual(template, 'shoppingcart/receipt.html') self.assertEqual(context['order'], self.cart) self.assertIn(reg_item, context['shoppingcart_items'][0]) @@ -1162,14 +1169,14 @@ def test_show_receipt_success_with_order_type_business(self): # has been expired or not resp = self.client.get(reverse('shoppingcart.views.show_receipt', args=[self.cart.id])) self.assertEqual(resp.status_code, 200) - ((template, context), _) = render_mock.call_args # pylint: disable=redefined-outer-name + ((template, context), _) = MOCK_RENDER.call_args # pylint: disable=redefined-outer-name self.assertEqual(template, 'shoppingcart/receipt.html') # now check for all the registration codes in the receipt # and one of code should be used at this point self.assertTrue(context['reg_code_info_list'][0]['is_redeemed']) self.assertFalse(context['reg_code_info_list'][1]['is_redeemed']) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_show_receipt_success_with_upgrade(self): reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_key) @@ -1179,9 +1186,9 @@ def test_show_receipt_success_with_upgrade(self): self.login_user() # When we come from the upgrade flow, we'll have a session variable showing that - s = self.client.session - s['attempting_upgrade'] = True - s.save() + session = self.client.session + session['attempting_upgrade'] = True + session.save() self.mock_tracker.emit.reset_mock() # pylint: disable=maybe-no-member resp = self.client.get(reverse('shoppingcart.views.show_receipt', args=[self.cart.id])) @@ -1194,7 +1201,7 @@ def test_show_receipt_success_with_upgrade(self): self.assertIn('FirstNameTesting123', resp.content) self.assertIn('80.00', resp.content) - ((template, context), _) = render_mock.call_args + ((template, context), _) = MOCK_RENDER.call_args # When we come from the upgrade flow, we get these context variables @@ -1215,7 +1222,7 @@ def test_show_receipt_success_with_upgrade(self): } ) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_show_receipt_success_refund(self): reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_key) cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor') @@ -1228,14 +1235,14 @@ def test_show_receipt_success_refund(self): self.assertEqual(resp.status_code, 200) self.assertIn('40.00', resp.content) - ((template, context), _tmp) = render_mock.call_args + ((template, context), _tmp) = MOCK_RENDER.call_args self.assertEqual(template, 'shoppingcart/receipt.html') self.assertEqual(context['order'], self.cart) self.assertIn(reg_item, context['shoppingcart_items'][0]) self.assertIn(cert_item, context['shoppingcart_items'][1]) self.assertTrue(context['any_refunds']) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_show_receipt_success_custom_receipt_page(self): cert_item = CertificateItem.add_to_order(self.cart, self.course_key, self.cost, 'honor') self.cart.purchase() @@ -1243,7 +1250,7 @@ def test_show_receipt_success_custom_receipt_page(self): receipt_url = reverse('shoppingcart.views.show_receipt', args=[self.cart.id]) resp = self.client.get(receipt_url) self.assertEqual(resp.status_code, 200) - ((template, _context), _tmp) = render_mock.call_args + ((template, _context), _tmp) = MOCK_RENDER.call_args self.assertEqual(template, cert_item.single_item_receipt_template) def _assert_404(self, url, use_post=False): @@ -1378,7 +1385,7 @@ def login_user(self): """ self.client.login(username=self.user.username, password="password") - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_to_check_that_cart_item_enrollment_is_closed(self): self.login_user() reg_item1 = PaidCourseRegistration.add_to_order(self.cart, self.course_key) @@ -1395,7 +1402,7 @@ def test_to_check_that_cart_item_enrollment_is_closed(self): self.assertEqual(resp.status_code, 200) self.assertIn("{course_name} has been removed because the enrollment period has closed.".format(course_name=self.testing_course.display_name), resp.content) - ((template, context), _tmp) = render_mock.call_args + ((template, context), _tmp) = MOCK_RENDER.call_args self.assertEqual(template, 'shoppingcart/shopping_cart.html') self.assertEqual(context['order'], self.cart) self.assertIn(reg_item1, context['shoppingcart_items'][0]) @@ -1788,25 +1795,25 @@ def test_report_csv_bad_method(self): response = self.client.put(reverse('payment_csv_report')) self.assertEqual(response.status_code, 400) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_report_csv_get(self): self.login_user() self.add_to_download_group(self.user) response = self.client.get(reverse('payment_csv_report')) - ((template, context), unused_kwargs) = render_mock.call_args + ((template, context), unused_kwargs) = MOCK_RENDER.call_args self.assertEqual(template, 'shoppingcart/download_report.html') self.assertFalse(context['total_count_error']) self.assertFalse(context['date_fmt_error']) self.assertIn(_("Download CSV Reports"), response.content.decode('UTF-8')) - @patch('shoppingcart.views.render_to_response', render_mock) + @patch('shoppingcart.views.render_to_response', MOCK_RENDER) def test_report_csv_bad_date(self): self.login_user() self.add_to_download_group(self.user) response = self.client.post(reverse('payment_csv_report'), {'start_date': 'BAD', 'end_date': 'BAD', 'requested_report': 'itemized_purchase_report'}) - ((template, context), unused_kwargs) = render_mock.call_args + ((template, context), unused_kwargs) = MOCK_RENDER.call_args self.assertEqual(template, 'shoppingcart/download_report.html') self.assertFalse(context['total_count_error']) self.assertTrue(context['date_fmt_error']) diff --git a/lms/djangoapps/verify_student/tests/test_views.py b/lms/djangoapps/verify_student/tests/test_views.py index 014e9db6527b..bccc11db247b 100644 --- a/lms/djangoapps/verify_student/tests/test_views.py +++ b/lms/djangoapps/verify_student/tests/test_views.py @@ -40,7 +40,7 @@ def mock_render_to_response(*args, **kwargs): return render_to_response(*args, **kwargs) -render_mock = Mock(side_effect=mock_render_to_response) +MOCK_RENDER = Mock(side_effect=mock_render_to_response) class StartView(TestCase): @@ -1367,21 +1367,21 @@ def setUp(self): self.course = CourseFactory.create(org='MITx', number='999', display_name='Robot Super Course') self.course_key = self.course.id - @patch('verify_student.views.render_to_response', render_mock) + @patch('verify_student.views.render_to_response', MOCK_RENDER) def test_reverify_get(self): url = reverse('verify_student_reverify') response = self.client.get(url) self.assertEquals(response.status_code, 200) - ((_template, context), _kwargs) = render_mock.call_args # pylint: disable=unpacking-non-sequence + ((_template, context), _kwargs) = MOCK_RENDER.call_args # pylint: disable=unpacking-non-sequence self.assertFalse(context['error']) - @patch('verify_student.views.render_to_response', render_mock) + @patch('verify_student.views.render_to_response', MOCK_RENDER) def test_reverify_post_failure(self): url = reverse('verify_student_reverify') response = self.client.post(url, {'face_image': '', 'photo_id_image': ''}) self.assertEquals(response.status_code, 200) - ((template, context), _kwargs) = render_mock.call_args # pylint: disable=unpacking-non-sequence + ((template, context), _kwargs) = MOCK_RENDER.call_args # pylint: disable=unpacking-non-sequence self.assertIn('photo_reverification', template) self.assertTrue(context['error']) @@ -1396,7 +1396,7 @@ def test_reverify_post_success(self): self.assertIsNotNone(verification_attempt) except ObjectDoesNotExist: self.fail('No verification object generated') - ((template, context), _kwargs) = render_mock.call_args # pylint: disable=unpacking-non-sequence + ((template, context), _kwargs) = MOCK_RENDER.call_args # pylint: disable=unpacking-non-sequence self.assertIn('photo_reverification', template) self.assertTrue(context['error']) @@ -1417,7 +1417,7 @@ def setUp(self): self.mock_tracker = patcher.start() self.addCleanup(patcher.stop) - @patch('verify_student.views.render_to_response', render_mock) + @patch('verify_student.views.render_to_response', MOCK_RENDER) def test_midcourse_reverify_get(self): url = reverse('verify_student_midcourse_reverify', kwargs={"course_id": self.course_key.to_deprecated_string()}) @@ -1447,7 +1447,7 @@ def test_midcourse_reverify_get(self): self.mock_tracker.emit.reset_mock() # pylint: disable=no-member self.assertEquals(response.status_code, 200) - ((_template, context), _kwargs) = render_mock.call_args # pylint: disable=unpacking-non-sequence + ((_template, context), _kwargs) = MOCK_RENDER.call_args # pylint: disable=unpacking-non-sequence self.assertFalse(context['error']) @patch.dict(settings.FEATURES, {'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING': True}) @@ -1500,7 +1500,7 @@ def test_midcourse_reverify_post_failure_expired_window(self): with self.assertRaises(ObjectDoesNotExist): SoftwareSecurePhotoVerification.objects.get(user=self.user, window=window) - @patch('verify_student.views.render_to_response', render_mock) + @patch('verify_student.views.render_to_response', MOCK_RENDER) def test_midcourse_reverify_dash(self): url = reverse('verify_student_midcourse_reverify_dash') response = self.client.get(url) @@ -1514,7 +1514,7 @@ def test_midcourse_reverify_dash(self): # enrolled in a verified course, and the window is open self.assertEquals(response.status_code, 200) - @patch('verify_student.views.render_to_response', render_mock) + @patch('verify_student.views.render_to_response', MOCK_RENDER) def test_midcourse_reverify_invalid_course_id(self): # if course id is invalid return 400 invalid_course_key = CourseLocator('edx', 'not', 'valid') diff --git a/lms/urls.py b/lms/urls.py index a3b604d756da..7a833a935de6 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -115,16 +115,20 @@ url(r'^course_modes/', include('course_modes.urls')), ) - -js_info_dict = { - 'domain': 'djangojs', - # We need to explicitly include external Django apps that are not in LOCALE_PATHS. - 'packages': ('openassessment',), -} - urlpatterns += ( # Serve catalog of localized strings to be rendered by Javascript - url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), + url( + r'^jsi18n/$', + 'django.views.i18n.javascript_catalog', + { + 'domain': 'djangojs', + # We need to explicitly include external Django apps that + # are not in LOCALE_PATHS. + 'packages': ( + 'openassessment', + ), + }, + ), ) # sysadmin dashboard, to see what courses are loaded, to delete & load courses @@ -143,13 +147,22 @@ {'template': '404.html'}, name="404"), ) -# Favicon -favicon_path = microsite.get_value('favicon_path', settings.FAVICON_PATH) -urlpatterns += (( - r'^favicon\.ico$', - 'django.views.generic.simple.redirect_to', - {'url': settings.STATIC_URL + favicon_path} -),) +urlpatterns += ( + # Favicon: give precedence to `microsite` over `settings` + ( + r'^favicon\.ico$', + 'django.views.generic.simple.redirect_to', + { + 'url': "{url_static}{path_favicon}".format( + url_static=settings.STATIC_URL, + path_favicon=microsite.get_value( + 'favicon_path', + settings.FAVICON_PATH, + ), + ), + }, + ), +) # Semi-static views only used by edX, not by themes if not settings.FEATURES["USE_CUSTOM_THEME"]: @@ -583,12 +596,8 @@ # in debug mode, allow any template to be rendered (most useful for UX reference templates) urlpatterns += url(r'^template/(?P