diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py
index 30756d8d20..4083954f77 100644
--- a/common/djangoapps/student/views.py
+++ b/common/djangoapps/student/views.py
@@ -133,6 +133,9 @@ AUDIT_LOG = logging.getLogger("audit")
ReverifyInfo = namedtuple('ReverifyInfo', 'course_id course_name course_number date status display') # pylint: disable=invalid-name
SETTING_CHANGE_INITIATED = 'edx.user.settings.change_initiated'
+# Disable this warning because it doesn't make sense to completely refactor tests to appease Pylint
+# pylint: disable=logging-format-interpolation
+
def csrf_token(context):
"""A csrf token that can be included in a form."""
@@ -296,12 +299,13 @@ def _cert_info(user, course_overview, cert_status, course_mode): # pylint: disa
default_status = 'processing'
- default_info = {'status': default_status,
- 'show_disabled_download_button': False,
- 'show_download_url': False,
- 'show_survey_button': False,
- 'can_unenroll': True
- }
+ default_info = {
+ 'status': default_status,
+ 'show_disabled_download_button': False,
+ 'show_download_url': False,
+ 'show_survey_button': False,
+ 'can_unenroll': True,
+ }
if cert_status is None:
return default_info
@@ -500,9 +504,14 @@ def is_course_blocked(request, redeemed_registration_codes, course_key):
u"User %s (%s) opted out of receiving emails from course %s",
request.user.username,
request.user.email,
- course_key
+ course_key,
+ )
+ track.views.server_track(
+ request,
+ "change-email1-settings",
+ {"receive_emails": "no", "course": course_key.to_deprecated_string()},
+ page='dashboard',
)
- track.views.server_track(request, "change-email1-settings", {"receive_emails": "no", "course": course_key.to_deprecated_string()}, page='dashboard')
break
return blocked
@@ -725,7 +734,7 @@ def _create_recent_enrollment_message(course_enrollments, course_modes): # pyli
recently_enrolled_courses = _get_recently_enrolled_courses(course_enrollments)
if recently_enrolled_courses:
- messages = [
+ enroll_messages = [
{
"course_id": enrollment.course_overview.id,
"course_name": enrollment.course_overview.display_name,
@@ -738,7 +747,7 @@ def _create_recent_enrollment_message(course_enrollments, course_modes): # pyli
return render_to_string(
'enrollment/course_enrollment_message.html',
- {'course_enrollment_messages': messages, 'platform_name': platform_name}
+ {'course_enrollment_messages': enroll_messages, 'platform_name': platform_name}
)
@@ -777,7 +786,11 @@ def _allow_donation(course_modes, course_id, enrollment):
"""
donations_enabled = DonationConfiguration.current().enabled
- return donations_enabled and enrollment.mode in course_modes[course_id] and course_modes[course_id][enrollment.mode].min_price == 0
+ return (
+ donations_enabled and
+ enrollment.mode in course_modes[course_id] and
+ course_modes[course_id][enrollment.mode].min_price == 0
+ )
def _update_email_opt_in(request, org):
@@ -1011,7 +1024,7 @@ def change_enrollment(request, check_access=True):
enroll_mode = CourseMode.auto_enroll_mode(course_id, available_modes)
if enroll_mode:
CourseEnrollment.enroll(user, course_id, check_access=check_access, mode=enroll_mode)
- except Exception:
+ except Exception: # pylint: disable=broad-except
return HttpResponseBadRequest(_("Could not enroll"))
# If we have more than one course mode or professional ed is enabled,
@@ -1073,32 +1086,43 @@ def login_user(request, error=""): # pylint: disable=too-many-statements,unused
third_party_auth_successful = True
except User.DoesNotExist:
AUDIT_LOG.warning(
- u'Login failed - user with username {username} has no social auth with backend_name {backend_name}'.format(
- username=username, backend_name=backend_name))
- return HttpResponse(
- _("You've successfully logged into your {provider_name} account, but this account isn't linked with an {platform_name} account yet.").format(
- platform_name=platform_name, provider_name=requested_provider.name
- )
- + "
" +
- _("Use your {platform_name} username and password to log into {platform_name} below, "
- "and then link your {platform_name} account with {provider_name} from your dashboard.").format(
- platform_name=platform_name, provider_name=requested_provider.name
- )
- + "
" +
- _("If you don't have an {platform_name} account yet, "
- "click Register at the top of the page.").format(
- platform_name=platform_name),
- content_type="text/plain",
- status=403
+ u"Login failed - user with username {username} has no social auth "
+ "with backend_name {backend_name}".format(
+ username=username, backend_name=backend_name)
)
+ message = _(
+ "You've successfully logged into your {provider_name} account, "
+ "but this account isn't linked with an {platform_name} account yet."
+ ).format(
+ platform_name=platform_name,
+ provider_name=requested_provider.name,
+ )
+ message += "
"
+ message += _(
+ "Use your {platform_name} username and password to log into {platform_name} below, "
+ "and then link your {platform_name} account with {provider_name} from your dashboard."
+ ).format(
+ platform_name=platform_name,
+ provider_name=requested_provider.name,
+ )
+ message += "
"
+ message += _(
+ "If you don't have an {platform_name} account yet, "
+ "click Register at the top of the page."
+ ).format(
+ platform_name=platform_name
+ )
+
+ return HttpResponse(message, content_type="text/plain", status=403)
else:
if 'email' not in request.POST or 'password' not in request.POST:
return JsonResponse({
"success": False,
- "value": _('There was an error receiving your login information. Please email us.'), # TODO: User error message
- }) # TODO: this should be status code 400 # pylint: disable=fixme
+ # TODO: User error message
+ "value": _('There was an error receiving your login information. Please email us.'),
+ }) # TODO: this should be status code 400
email = request.POST['email']
password = request.POST['password']
@@ -1129,9 +1153,11 @@ def login_user(request, error=""): # pylint: disable=too-many-statements,unused
user_found_by_email_lookup = user
if user_found_by_email_lookup and LoginFailures.is_feature_enabled():
if LoginFailures.is_user_locked_out(user_found_by_email_lookup):
+ lockout_message = _('This account has been temporarily locked due '
+ 'to excessive login failures. Try again later.')
return JsonResponse({
"success": False,
- "value": _('This account has been temporarily locked due to excessive login failures. Try again later.'),
+ "value": lockout_message,
}) # TODO: this should be status code 429 # pylint: disable=fixme
# see if the user must reset his/her password due to any policy settings
@@ -1239,7 +1265,8 @@ def login_user(request, error=""): # pylint: disable=too-many-statements,unused
AUDIT_LOG.warning(u"Login failed - Account not active for user {0}, resending activation".format(username))
reactivation_email_for_user(user)
- not_activated_msg = _("This account has not been activated. We have sent another activation message. Please check your email for the activation instructions.")
+ not_activated_msg = _("This account has not been activated. We have sent another activation "
+ "message. Please check your email for the activation instructions.")
return JsonResponse({
"success": False,
"value": not_activated_msg,
@@ -1608,7 +1635,7 @@ def create_account_with_params(request, params):
if settings.FEATURES.get('ENABLE_DISCUSSION_EMAIL_DIGEST'):
try:
enable_notifications(user)
- except Exception:
+ except Exception: # pylint: disable=broad-except
log.exception("Enable discussion notifications failed for user {id}.".format(id=user.id))
dog_stats_api.increment("common.student.account_created")
@@ -2010,9 +2037,9 @@ def password_reset(request):
def password_reset_confirm_wrapper(
- request,
- uidb36=None,
- token=None,
+ request,
+ uidb36=None,
+ token=None,
):
""" A wrapper around django.contrib.auth.views.password_reset_confirm.
Needed because we want to set the user as active at this step.
@@ -2046,6 +2073,8 @@ def password_reset_confirm_wrapper(
num_distinct = settings.ADVANCED_SECURITY_CONFIG['MIN_DIFFERENT_STAFF_PASSWORDS_BEFORE_REUSE']
else:
num_distinct = settings.ADVANCED_SECURITY_CONFIG['MIN_DIFFERENT_STUDENT_PASSWORDS_BEFORE_REUSE']
+ # Because of how ngettext is, splitting the following into shorter lines would be ugly.
+ # pylint: disable=line-too-long
err_msg = ungettext(
"You are re-using a password that you have used recently. You must have {num} distinct password before reusing a previous password.",
"You are re-using a password that you have used recently. You must have {num} distinct passwords before reusing a previous password.",
@@ -2055,6 +2084,8 @@ def password_reset_confirm_wrapper(
# also, check to see if passwords are getting reset too frequent
if PasswordHistory.is_password_reset_too_soon(user):
num_days = settings.ADVANCED_SECURITY_CONFIG['MIN_TIME_IN_DAYS_BETWEEN_ALLOWED_RESETS']
+ # Because of how ngettext is, splitting the following into shorter lines would be ugly.
+ # pylint: disable=line-too-long
err_msg = ungettext(
"You are resetting passwords too frequently. Due to security policies, {num} day must elapse between password resets.",
"You are resetting passwords too frequently. Due to security policies, {num} days must elapse between password resets.",
@@ -2287,18 +2318,28 @@ def change_email_settings(request):
u"User %s (%s) opted in to receive emails from course %s",
user.username,
user.email,
- course_id
+ course_id,
+ )
+ track.views.server_track(
+ request,
+ "change-email-settings",
+ {"receive_emails": "yes", "course": course_id},
+ page='dashboard',
)
- track.views.server_track(request, "change-email-settings", {"receive_emails": "yes", "course": course_id}, page='dashboard')
else:
Optout.objects.get_or_create(user=user, course_id=course_key)
log.info(
u"User %s (%s) opted out of receiving emails from course %s",
user.username,
user.email,
- course_id
+ course_id,
+ )
+ track.views.server_track(
+ request,
+ "change-email-settings",
+ {"receive_emails": "no", "course": course_id},
+ page='dashboard',
)
- track.views.server_track(request, "change-email-settings", {"receive_emails": "no", "course": course_id}, page='dashboard')
return JsonResponse({"success": True})
diff --git a/common/lib/capa/capa/responsetypes.py b/common/lib/capa/capa/responsetypes.py
index 2609bdd047..14f5069a0b 100644
--- a/common/lib/capa/capa/responsetypes.py
+++ b/common/lib/capa/capa/responsetypes.py
@@ -7,7 +7,8 @@ of a variety of types.
Used by capa_problem.py
"""
-
+# TODO: Refactor this code and fix this issue.
+# pylint: disable=attribute-defined-outside-init
# standard library imports
import abc
import cgi
@@ -541,7 +542,7 @@ class LoncapaResponse(object):
# If we can't do that, create the
and set the message
# as the text of the
- except:
+ except Exception: # pylint: disable=broad-except
response_msg_div = etree.Element('div')
response_msg_div.text = str(response_msg)
@@ -1225,7 +1226,6 @@ class MultipleChoiceResponse(LoncapaResponse):
i = 0
for response in self.xml.xpath("choicegroup"):
# Is Masking enabled? -- check for shuffle or answer-pool features
- ans_str = response.get("answer-pool")
# Masking (self._has_mask) is off, to be re-enabled with a future PR.
rtype = response.get('type')
if rtype not in ["MultipleChoice"]:
@@ -1240,12 +1240,15 @@ class MultipleChoiceResponse(LoncapaResponse):
i += 1
# If using the masked name, e.g. mask_0, save the regular name
# to support unmasking later (for the logs).
- if self.has_mask():
- mask_name = "mask_" + str(mask_ids.pop())
- self._mask_dict[mask_name] = name
- choice.set("name", mask_name)
- else:
- choice.set("name", name)
+ # Masking is currently disabled so this code is commented, as
+ # the variable `mask_ids` is not defined. (the feature appears to not be fully implemented)
+ # The original work for masking was done by Nick Parlante as part of the OLI Hinting feature.
+ # if self.has_mask():
+ # mask_name = "mask_" + str(mask_ids.pop())
+ # self._mask_dict[mask_name] = name
+ # choice.set("name", mask_name)
+ # else:
+ choice.set("name", name)
def late_transforms(self, problem):
"""
@@ -1338,12 +1341,13 @@ class MultipleChoiceResponse(LoncapaResponse):
Given a masked name, e.g. mask_2, returns the regular name, e.g. choice_0.
Fails with LoncapaProblemError if called on a response that is not masking.
"""
- if not self.has_mask():
- _ = self.capa_system.i18n.ugettext
- # Translators: 'unmask_name' is a method name and should not be translated.
- msg = _("unmask_name called on response that is not masked")
- raise LoncapaProblemError(msg)
- return self._mask_dict[name]
+ # if not self.has_mask():
+ # _ = self.capa_system.i18n.ugettext
+ # # Translators: 'unmask_name' is a method name and should not be translated.
+ # msg = "unmask_name called on response that is not masked"
+ # raise LoncapaProblemError(msg)
+ # return self._mask_dict[name] # TODO: this is not defined
+ raise NotImplementedError()
def unmask_order(self):
"""
@@ -1750,7 +1754,9 @@ class NumericalResponse(LoncapaResponse):
student_float = evaluator({}, {}, student_answer)
except UndefinedVariable as undef_var:
raise StudentInputError(
- _(u"You may not use variables ({bad_variables}) in numerical problems.").format(bad_variables=undef_var.message)
+ _(u"You may not use variables ({bad_variables}) in numerical problems.").format(
+ bad_variables=undef_var.message,
+ )
)
except ValueError as val_err:
if 'factorial' in val_err.message:
@@ -1802,13 +1808,17 @@ class NumericalResponse(LoncapaResponse):
for inclusion, answer in zip(self.inclusion, self.answer_range):
boundary = self.get_staff_ans(answer)
if boundary.imag != 0:
- # Translators: This is an error message for a math problem. If the instructor provided a boundary
- # (end limit) for a variable that is a complex number (a + bi), this message displays.
- raise StudentInputError(_("There was a problem with the staff answer to this problem: complex boundary."))
+ raise StudentInputError(
+ # Translators: This is an error message for a math problem. If the instructor provided a
+ # boundary (end limit) for a variable that is a complex number (a + bi), this message displays.
+ _("There was a problem with the staff answer to this problem: complex boundary.")
+ )
if isnan(boundary):
- # Translators: This is an error message for a math problem. If the instructor did not provide
- # a boundary (end limit) for a variable, this message displays.
- raise StudentInputError(_("There was a problem with the staff answer to this problem: empty boundary."))
+ raise StudentInputError(
+ # Translators: This is an error message for a math problem. If the instructor did not
+ # provide a boundary (end limit) for a variable, this message displays.
+ _("There was a problem with the staff answer to this problem: empty boundary.")
+ )
boundaries.append(boundary.real)
if compare_with_tolerance(
student_float,
@@ -2164,7 +2174,8 @@ class StringResponse(LoncapaResponse):
def get_answers(self):
_ = self.capa_system.i18n.ugettext
- # Translators: Separator used in StringResponse to display multiple answers. Example: "Answer: Answer_1 or Answer_2 or Answer_3".
+ # Translators: Separator used in StringResponse to display multiple answers.
+ # Example: "Answer: Answer_1 or Answer_2 or Answer_3".
separator = u' {} '.format(_('or'))
return {self.answer_id: separator.join(self.correct_answer)}
@@ -2280,7 +2291,9 @@ class CustomResponse(LoncapaResponse):
submission = [student_answers[k] for k in idset]
except Exception as err:
msg = u"[courseware.capa.responsetypes.customresponse] {message}\n idset = {idset}, error = {err}".format(
- message=_("error getting student answer from {student_answers}").format(student_answers=student_answers),
+ message=_("error getting student answer from {student_answers}").format(
+ student_answers=student_answers,
+ ),
idset=idset,
err=err
)
@@ -2392,20 +2405,20 @@ class CustomResponse(LoncapaResponse):
random_seed=self.context['seed'],
unsafely=self.capa_system.can_execute_unsafe_code(),
)
- except Exception as err:
+ except Exception as err: # pylint: disable=broad-except
self._handle_exec_exception(err)
else:
# self.code is not a string; it's a function we created earlier.
# this is an interface to the Tutor2 check functions
- fn = self.code
+ tutor_cfn = self.code
answer_given = submission[0] if (len(idset) == 1) else submission
kwnames = self.xml.get("cfn_extra_args", "").split()
kwargs = {n: self.context.get(n) for n in kwnames}
log.debug(" submission = %s", submission)
try:
- ret = fn(self.expect, answer_given, **kwargs)
+ ret = tutor_cfn(self.expect, answer_given, **kwargs)
except Exception as err: # pylint: disable=broad-except
self._handle_exec_exception(err)
log.debug(
@@ -2928,15 +2941,17 @@ class CodeResponse(LoncapaResponse):
# Next, we need to check that the contents of the external grader message is safe for the LMS.
# 1) Make sure that the message is valid XML (proper opening/closing tags)
- # 2) If it is not valid XML, make sure it is valid HTML. Note: html5lib parser will try to repair any broken HTML
- # For example: will become .
+ # 2) If it is not valid XML, make sure it is valid HTML.
+ # Note: html5lib parser will try to repair any broken HTML
+ # For example: will become .
msg = score_result['msg']
try:
etree.fromstring(msg)
except etree.XMLSyntaxError as _err:
# If `html` contains attrs with no values, like `controls` in ,
- # XML parser will raise exception, so wee fallback to html5parser, which will set empty "" values for such attrs.
+ # XML parser will raise exception, so wee fallback to html5parser,
+ # which will set empty "" values for such attrs.
try:
parsed = html5lib.parseFragment(msg, treebuilder='lxml', namespaceHTMLElements=False)
except ValueError:
@@ -3612,11 +3627,13 @@ class AnnotationResponse(LoncapaResponse):
def _find_options(self, inputfield):
"""Returns an array of dicts where each dict represents an option. """
elements = inputfield.findall('./options/option')
- return [{
+ return [
+ {
'id': index,
'description': option.text,
'choice': option.get('choice')
- } for (index, option) in enumerate(elements)]
+ } for (index, option) in enumerate(elements)
+ ]
def _find_option_with_choice(self, inputfield, choice):
"""Returns the option with the given choice value, otherwise None. """
@@ -3663,10 +3680,11 @@ class ChoiceTextResponse(LoncapaResponse):
human_name = _('Checkboxes With Text Input')
tags = ['choicetextresponse']
max_inputfields = 1
- allowed_inputfields = ['choicetextgroup',
- 'checkboxtextgroup',
- 'radiotextgroup'
- ]
+ allowed_inputfields = [
+ 'choicetextgroup',
+ 'checkboxtextgroup',
+ 'radiotextgroup',
+ ]
def __init__(self, *args, **kwargs):
self.correct_inputs = {}
@@ -3771,9 +3789,8 @@ class ChoiceTextResponse(LoncapaResponse):
"""
- for index, choice in enumerate(
- self.xml.xpath('//*[@id=$id]//choice', id=self.xml.get('id'))
- ):
+ choices = self.xml.xpath('//*[@id=$id]//choice', id=self.xml.get('id'))
+ for index, choice in enumerate(choices):
# Set the name attribute for
# "bc" is appended at the end to indicate that this is a
# binary choice as opposed to a numtolerance_input, this convention
diff --git a/common/lib/chem/chem/tests.py b/common/lib/chem/chem/tests.py
index 4087016e41..75a044c7ee 100644
--- a/common/lib/chem/chem/tests.py
+++ b/common/lib/chem/chem/tests.py
@@ -9,16 +9,17 @@ from .chemcalc import (
chemical_equations_equal,
)
-import miller
+import chem.miller
-local_debug = None
+LOCAL_DEBUG = None
-def log(s, output_type=None):
- if local_debug:
- print s
+def log(msg, output_type=None):
+ """Logging function for tests"""
+ if LOCAL_DEBUG:
+ print msg
if output_type == 'html':
- f.write(s + '\n \n')
+ f.write(msg + '\n \n')
class Test_Compare_Equations(unittest.TestCase):
@@ -132,10 +133,6 @@ class Test_Compare_Expressions(unittest.TestCase):
self.assertFalse(compare_chemical_expression(
"H2O(s) + CO2", "H2O+CO2"))
- def test_compare_phases_not_ignored_explicitly(self):
- self.assertTrue(compare_chemical_expression(
- "H2O(s) + CO2", "H2O(s)+CO2", ignore_state=False))
-
# all in one cases
def test_complex_additivity(self):
self.assertTrue(compare_chemical_expression(
@@ -223,247 +220,250 @@ class Test_Divide_Expressions(unittest.TestCase):
class Test_Render_Equations(unittest.TestCase):
-
+ """
+ Tests to validate the HTML rendering of plaintext (input) equations
+ """
+ # pylint: disable=line-too-long
def test_render1(self):
- s = "H2O + CO2"
- out = render_to_html(s)
+ test_string = "H2O + CO2"
+ out = render_to_html(test_string)
correct = u'H2O+CO2'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
def test_render_uncorrect_reaction(self):
- s = "O2C + OH2"
- out = render_to_html(s)
+ test_string = "O2C + OH2"
+ out = render_to_html(test_string)
correct = u'O2C+OH2'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
def test_render2(self):
- s = "CO2 + H2O + Fe(OH)3"
- out = render_to_html(s)
+ test_string = "CO2 + H2O + Fe(OH)3"
+ out = render_to_html(test_string)
correct = u'CO2+H2O+Fe(OH)3'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
def test_render3(self):
- s = "3H2O + 2CO2"
- out = render_to_html(s)
+ test_string = "3H2O + 2CO2"
+ out = render_to_html(test_string)
correct = u'3H2O+2CO2'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
def test_render4(self):
- s = "H^+ + OH^-"
- out = render_to_html(s)
+ test_string = "H^+ + OH^-"
+ out = render_to_html(test_string)
correct = u'H++OH-'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
def test_render5(self):
- s = "Fe(OH)^2- + (OH)^-"
- out = render_to_html(s)
+ test_string = "Fe(OH)^2- + (OH)^-"
+ out = render_to_html(test_string)
correct = u'Fe(OH)2-+(OH)-'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
def test_render6(self):
- s = "7/2H^+ + 3/5OH^-"
- out = render_to_html(s)
+ test_string = "7/2H^+ + 3/5OH^-"
+ out = render_to_html(test_string)
correct = u'7⁄2H++3⁄5OH-'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
def test_render7(self):
- s = "5(H1H212)^70010- + 2H2O + 7/2HCl + H2O"
- out = render_to_html(s)
+ test_string = "5(H1H212)^70010- + 2H2O + 7/2HCl + H2O"
+ out = render_to_html(test_string)
correct = u'5(H1H212)70010-+2H2O+7⁄2HCl+H2O'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
def test_render8(self):
- s = "H2O(s) + CO2"
- out = render_to_html(s)
+ test_string = "H2O(s) + CO2"
+ out = render_to_html(test_string)
correct = u'H2O(s)+CO2'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
def test_render9(self):
- s = "5[Ni(NH3)4]^2+ + 5/2SO4^2-"
- out = render_to_html(s)
+ test_string = "5[Ni(NH3)4]^2+ + 5/2SO4^2-"
+ out = render_to_html(test_string)
correct = u'5[Ni(NH3)4]2++5⁄2SO42-'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
def test_render_error(self):
- s = "5.2H20"
- out = render_to_html(s)
+ test_string = "5.2H20"
+ out = render_to_html(test_string)
correct = u'5.2H20'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
def test_render_simple_brackets(self):
- s = "(Ar)"
- out = render_to_html(s)
+ test_string = "(Ar)"
+ out = render_to_html(test_string)
correct = u'(Ar)'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
def test_render_eq1(self):
- s = "H^+ + OH^- -> H2O"
- out = render_to_html(s)
+ test_string = "H^+ + OH^- -> H2O"
+ out = render_to_html(test_string)
correct = u'H++OH-\u2192H2O'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
def test_render_eq2(self):
- s = "H^+ + OH^- <-> H2O"
- out = render_to_html(s)
+ test_string = "H^+ + OH^- <-> H2O"
+ out = render_to_html(test_string)
correct = u'H++OH-\u2194H2O'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
def test_render_eq3(self):
- s = "H^+ + OH^- <= H2O" # unsupported arrow
- out = render_to_html(s)
+ test_string = "H^+ + OH^- <= H2O" # unsupported arrow
+ out = render_to_html(test_string)
correct = u'H^+ + OH^- <= H2O'
log(out + ' ------- ' + correct, 'html')
self.assertEqual(out, correct)
class Test_Crystallography_Miller(unittest.TestCase):
- ''' Tests for crystallography grade function.'''
-
+ """Tests for crystallography grade function."""
+ # pylint: disable=line-too-long
def test_empty_points(self):
user_input = '{"lattice": "bcc", "points": []}'
- self.assertFalse(miller.grade(user_input, {'miller': '(2,2,2)', 'lattice': 'bcc'}))
+ self.assertFalse(chem.miller.grade(user_input, {'miller': '(2,2,2)', 'lattice': 'bcc'}))
def test_only_one_point(self):
user_input = '{"lattice": "bcc", "points": [["0.50", "0.00", "0.00"]]}'
- self.assertFalse(miller.grade(user_input, {'miller': '(2,2,2)', 'lattice': 'bcc'}))
+ self.assertFalse(chem.miller.grade(user_input, {'miller': '(2,2,2)', 'lattice': 'bcc'}))
def test_only_two_points(self):
user_input = '{"lattice": "bcc", "points": [["0.50", "0.00", "0.00"], ["0.00", "0.50", "0.00"]]}'
- self.assertFalse(miller.grade(user_input, {'miller': '(2,2,2)', 'lattice': 'bcc'}))
+ self.assertFalse(chem.miller.grade(user_input, {'miller': '(2,2,2)', 'lattice': 'bcc'}))
def test_1(self):
user_input = '{"lattice": "bcc", "points": [["0.50", "0.00", "0.00"], ["0.00", "0.50", "0.00"], ["0.00", "0.00", "0.50"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(2,2,2)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(2,2,2)', 'lattice': 'bcc'}))
def test_2(self):
user_input = '{"lattice": "bcc", "points": [["1.00", "0.00", "0.00"], ["0.00", "1.00", "0.00"], ["0.00", "0.00", "1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(1,1,1)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(1,1,1)', 'lattice': 'bcc'}))
def test_3(self):
user_input = '{"lattice": "bcc", "points": [["1.00", "0.50", "1.00"], ["1.00", "1.00", "0.50"], ["0.50", "1.00", "1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(2,2,2)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(2,2,2)', 'lattice': 'bcc'}))
def test_4(self):
user_input = '{"lattice": "bcc", "points": [["0.33", "1.00", "0.00"], ["0.00", "0.664", "0.00"], ["0.00", "1.00", "0.33"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(-3, 3, -3)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(-3, 3, -3)', 'lattice': 'bcc'}))
def test_5(self):
""" return true only in case points coordinates are exact.
But if they transform to closest 0.05 value it is not true"""
user_input = '{"lattice": "bcc", "points": [["0.33", "1.00", "0.00"], ["0.00", "0.33", "0.00"], ["0.00", "1.00", "0.33"]]}'
- self.assertFalse(miller.grade(user_input, {'miller': '(-6,3,-6)', 'lattice': 'bcc'}))
+ self.assertFalse(chem.miller.grade(user_input, {'miller': '(-6,3,-6)', 'lattice': 'bcc'}))
def test_6(self):
user_input = '{"lattice": "bcc", "points": [["0.00", "0.25", "0.00"], ["0.25", "0.00", "0.00"], ["0.00", "0.00", "0.25"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(4,4,4)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(4,4,4)', 'lattice': 'bcc'}))
def test_7(self): # goes throug origin
user_input = '{"lattice": "bcc", "points": [["0.00", "1.00", "0.00"], ["1.00", "0.00", "0.00"], ["0.50", "1.00", "0.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(0,0,-1)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(0,0,-1)', 'lattice': 'bcc'}))
def test_8(self):
user_input = '{"lattice": "bcc", "points": [["0.00", "1.00", "0.50"], ["1.00", "0.00", "0.50"], ["0.50", "1.00", "0.50"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(0,0,2)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(0,0,2)', 'lattice': 'bcc'}))
def test_9(self):
user_input = '{"lattice": "bcc", "points": [["1.00", "0.00", "1.00"], ["0.00", "1.00", "1.00"], ["1.00", "0.00", "0.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(1,1,0)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(1,1,0)', 'lattice': 'bcc'}))
def test_10(self):
user_input = '{"lattice": "bcc", "points": [["1.00", "0.00", "1.00"], ["0.00", "0.00", "0.00"], ["0.00", "1.00", "1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(1,1,-1)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(1,1,-1)', 'lattice': 'bcc'}))
def test_11(self):
user_input = '{"lattice": "bcc", "points": [["1.00", "0.00", "0.50"], ["1.00", "1.00", "0.00"], ["0.00", "1.00", "0.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(0,1,2)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(0,1,2)', 'lattice': 'bcc'}))
def test_12(self):
user_input = '{"lattice": "bcc", "points": [["1.00", "0.00", "0.50"], ["0.00", "0.00", "0.50"], ["1.00", "1.00", "1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(0,1,-2)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(0,1,-2)', 'lattice': 'bcc'}))
def test_13(self):
user_input = '{"lattice": "bcc", "points": [["0.50", "0.00", "0.00"], ["0.50", "1.00", "0.00"], ["0.00", "0.00", "1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(2,0,1)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(2,0,1)', 'lattice': 'bcc'}))
def test_14(self):
user_input = '{"lattice": "bcc", "points": [["0.00", "0.00", "0.00"], ["0.00", "0.00", "1.00"], ["0.50", "1.00", "0.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(2,-1,0)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(2,-1,0)', 'lattice': 'bcc'}))
def test_15(self):
user_input = '{"lattice": "bcc", "points": [["0.00", "0.00", "0.00"], ["1.00", "1.00", "0.00"], ["0.00", "1.00", "1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(1,-1,1)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(1,-1,1)', 'lattice': 'bcc'}))
def test_16(self):
user_input = '{"lattice": "bcc", "points": [["1.00", "0.00", "0.00"], ["0.00", "1.00", "0.00"], ["1.00", "1.00", "1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(1,1,-1)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(1,1,-1)', 'lattice': 'bcc'}))
def test_17(self):
user_input = '{"lattice": "bcc", "points": [["0.00", "0.00", "0.00"], ["1.00", "0.00", "1.00"], ["1.00", "1.00", "0.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(-1,1,1)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(-1,1,1)', 'lattice': 'bcc'}))
def test_18(self):
user_input = '{"lattice": "bcc", "points": [["0.00", "0.00", "0.00"], ["1.00", "1.00", "0.00"], ["0.00", "1.00", "1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(1,-1,1)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(1,-1,1)', 'lattice': 'bcc'}))
def test_19(self):
user_input = '{"lattice": "bcc", "points": [["0.00", "0.00", "0.00"], ["1.00", "1.00", "0.00"], ["0.00", "0.00", "1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(-1,1,0)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(-1,1,0)', 'lattice': 'bcc'}))
def test_20(self):
user_input = '{"lattice": "bcc", "points": [["1.00", "0.00", "0.00"], ["1.00", "1.00", "0.00"], ["0.00", "0.00", "1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(1,0,1)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(1,0,1)', 'lattice': 'bcc'}))
def test_21(self):
user_input = '{"lattice": "bcc", "points": [["0.00", "0.00", "0.00"], ["0.00", "1.00", "0.00"], ["1.00", "0.00", "1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(-1,0,1)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(-1,0,1)', 'lattice': 'bcc'}))
def test_22(self):
user_input = '{"lattice": "bcc", "points": [["0.00", "1.00", "0.00"], ["1.00", "1.00", "0.00"], ["0.00", "0.00", "1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(0,1,1)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(0,1,1)', 'lattice': 'bcc'}))
def test_23(self):
user_input = '{"lattice": "bcc", "points": [["0.00", "0.00", "0.00"], ["1.00", "0.00", "0.00"], ["1.00", "1.00", "1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(0,-1,1)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(0,-1,1)', 'lattice': 'bcc'}))
def test_24(self):
user_input = '{"lattice": "bcc", "points": [["0.66", "0.00", "0.00"], ["0.00", "0.66", "0.00"], ["0.00", "0.00", "0.66"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(3,3,3)', 'lattice': 'bcc'}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(3,3,3)', 'lattice': 'bcc'}))
def test_25(self):
user_input = u'{"lattice":"","points":[["0.00","0.00","0.01"],["1.00","1.00","0.01"],["0.00","1.00","1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(1,-1,1)', 'lattice': ''}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(1,-1,1)', 'lattice': ''}))
def test_26(self):
user_input = u'{"lattice":"","points":[["0.00","0.01","0.00"],["1.00","0.00","0.00"],["0.00","0.00","1.00"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(0,-1,0)', 'lattice': ''}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(0,-1,0)', 'lattice': ''}))
def test_27(self):
""" rounding to 0.35"""
user_input = u'{"lattice":"","points":[["0.33","0.00","0.00"],["0.00","0.33","0.00"],["0.00","0.00","0.33"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(3,3,3)', 'lattice': ''}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(3,3,3)', 'lattice': ''}))
def test_28(self):
""" rounding to 0.30"""
user_input = u'{"lattice":"","points":[["0.30","0.00","0.00"],["0.00","0.30","0.00"],["0.00","0.00","0.30"]]}'
- self.assertTrue(miller.grade(user_input, {'miller': '(10,10,10)', 'lattice': ''}))
+ self.assertTrue(chem.miller.grade(user_input, {'miller': '(10,10,10)', 'lattice': ''}))
def test_wrong_lattice(self):
user_input = '{"lattice": "bcc", "points": [["0.00", "0.00", "0.00"], ["1.00", "0.00", "0.00"], ["1.00", "1.00", "1.00"]]}'
- self.assertFalse(miller.grade(user_input, {'miller': '(3,3,3)', 'lattice': 'fcc'}))
+ self.assertFalse(chem.miller.grade(user_input, {'miller': '(3,3,3)', 'lattice': 'fcc'}))
def suite():
@@ -478,7 +478,7 @@ def suite():
return unittest.TestSuite(suites)
if __name__ == "__main__":
- local_debug = True
+ LOCAL_DEBUG = True
with codecs.open('render.html', 'w', encoding='utf-8') as f:
unittest.TextTestRunner(verbosity=2).run(suite())
# open render.html to look at rendered equations
diff --git a/common/test/acceptance/pages/studio/overview.py b/common/test/acceptance/pages/studio/overview.py
index 160b1f1d1c..14c6b1b0d8 100644
--- a/common/test/acceptance/pages/studio/overview.py
+++ b/common/test/acceptance/pages/studio/overview.py
@@ -20,6 +20,9 @@ class CourseOutlineItem(object):
"""
A mixin class for any :class:`PageObject` shown in a course outline.
"""
+ # Note there are a few pylint disable=no-member occurances in this class, because
+ # it was written assuming it is going to be a mixin to a PageObject and will have functions
+ # such as self.wait_for_ajax, which doesn't exist on a generic `object`.
BODY_SELECTOR = None
EDIT_BUTTON_SELECTOR = '.xblock-field-value-edit'
NAME_SELECTOR = '.item-title'
@@ -33,7 +36,7 @@ class CourseOutlineItem(object):
# Check for the existence of a locator so that errors when navigating to the course outline page don't show up
# as errors in the repr method instead.
try:
- return "{}(, {!r})".format(self.__class__.__name__, self.locator)
+ return "{}(, {!r})".format(self.__class__.__name__, self.locator) # pylint: disable=no-member
except AttributeError:
return "{}()".format(self.__class__.__name__)
@@ -43,6 +46,7 @@ class CourseOutlineItem(object):
"""
# If the item doesn't have a body selector or locator, then it can't be bounded
# This happens in the context of the CourseOutlinePage
+ # pylint: disable=no-member
if self.BODY_SELECTOR and hasattr(self, 'locator'):
return '{}[data-locator="{}"] {}'.format(
self.BODY_SELECTOR,
@@ -57,7 +61,7 @@ class CourseOutlineItem(object):
"""
Returns the display name of this object.
"""
- name_element = self.q(css=self._bounded_selector(self.NAME_SELECTOR)).first
+ name_element = self.q(css=self._bounded_selector(self.NAME_SELECTOR)).first # pylint: disable=no-member
if name_element:
return name_element.text[0]
else:
@@ -68,14 +72,14 @@ class CourseOutlineItem(object):
"""
Returns True if the item has a status message, False otherwise.
"""
- return self.q(css=self._bounded_selector(self.STATUS_MESSAGE_SELECTOR)).first.visible
+ return self.q(css=self._bounded_selector(self.STATUS_MESSAGE_SELECTOR)).first.visible # pylint: disable=no-member
@property
def status_message(self):
"""
Returns the status message of this item.
"""
- return self.q(css=self._bounded_selector(self.STATUS_MESSAGE_SELECTOR)).text[0]
+ return self.q(css=self._bounded_selector(self.STATUS_MESSAGE_SELECTOR)).text[0] # pylint: disable=no-member
@property
def has_staff_lock_warning(self):
@@ -85,13 +89,13 @@ class CourseOutlineItem(object):
@property
def is_staff_only(self):
""" Returns True if the visiblity state of this item is staff only (has a black sidebar) """
- return "is-staff-only" in self.q(css=self._bounded_selector(''))[0].get_attribute("class")
+ return "is-staff-only" in self.q(css=self._bounded_selector(''))[0].get_attribute("class") # pylint: disable=no-member
def edit_name(self):
"""
Puts the item's name into editable form.
"""
- self.q(css=self._bounded_selector(self.EDIT_BUTTON_SELECTOR)).first.click()
+ self.q(css=self._bounded_selector(self.EDIT_BUTTON_SELECTOR)).first.click() # pylint: disable=no-member
def enter_name(self, new_name):
"""
@@ -105,12 +109,13 @@ class CourseOutlineItem(object):
"""
self.edit_name()
set_input_value_and_save(self, self._bounded_selector(self.NAME_INPUT_SELECTOR), new_name)
- self.wait_for_ajax()
+ self.wait_for_ajax() # pylint: disable=no-member
def finalize_name(self):
"""
Presses ENTER, saving the value of the display name for this item.
"""
+ # pylint: disable=no-member
self.q(css=self._bounded_selector(self.NAME_INPUT_SELECTOR)).results[0].send_keys(Keys.ENTER)
self.wait_for_ajax()
@@ -126,29 +131,42 @@ class CourseOutlineItem(object):
"""
Return whether this outline item's display name is in its editable form.
"""
+ # pylint: disable=no-member
return "is-editing" in self.q(
css=self._bounded_selector(self.NAME_FIELD_WRAPPER_SELECTOR)
)[0].get_attribute("class")
def edit(self):
- self.q(css=self._bounded_selector(self.CONFIGURATION_BUTTON_SELECTOR)).first.click()
+ """
+ Puts the item into editable form.
+ """
+ self.q(css=self._bounded_selector(self.CONFIGURATION_BUTTON_SELECTOR)).first.click() # pylint: disable=no-member
modal = CourseOutlineModal(self)
- EmptyPromise(lambda: modal.is_shown(), 'Modal is shown.')
+ EmptyPromise(lambda: modal.is_shown(), 'Modal is shown.') # pylint: disable=unnecessary-lambda
return modal
@property
def release_date(self):
- element = self.q(css=self._bounded_selector(".status-release-value"))
+ """
+ Returns the release date from the page. Date is "mm/dd/yyyy" string.
+ """
+ element = self.q(css=self._bounded_selector(".status-release-value")) # pylint: disable=no-member
return element.first.text[0] if element.present else None
@property
def due_date(self):
- element = self.q(css=self._bounded_selector(".status-grading-date"))
+ """
+ Returns the due date from the page. Date is "mm/dd/yyyy" string.
+ """
+ element = self.q(css=self._bounded_selector(".status-grading-date")) # pylint: disable=no-member
return element.first.text[0] if element.present else None
@property
def policy(self):
- element = self.q(css=self._bounded_selector(".status-grading-value"))
+ """
+ Select the grading format with `value` in the drop-down list.
+ """
+ element = self.q(css=self._bounded_selector(".status-grading-value")) # pylint: disable=no-member
return element.first.text[0] if element.present else None
def publish(self):
@@ -157,7 +175,7 @@ class CourseOutlineItem(object):
"""
click_css(self, self._bounded_selector('.action-publish'), require_notification=False)
modal = CourseOutlineModal(self)
- EmptyPromise(lambda: modal.is_shown(), 'Modal is shown.')
+ EmptyPromise(lambda: modal.is_shown(), 'Modal is shown.') # pylint: disable=unnecessary-lambda
modal.publish()
@property
@@ -165,7 +183,7 @@ class CourseOutlineItem(object):
"""
Returns the link for publishing a unit.
"""
- return self.q(css=self._bounded_selector('.action-publish')).first
+ return self.q(css=self._bounded_selector('.action-publish')).first # pylint: disable=no-member
class CourseOutlineContainer(CourseOutlineItem):
@@ -186,6 +204,7 @@ class CourseOutlineContainer(CourseOutlineItem):
if not child_class:
child_class = self.CHILD_CLASS
+ # pylint: disable=no-member
return child_class(
self.browser,
self.q(css=child_class.BODY_SELECTOR).filter(
@@ -200,6 +219,7 @@ class CourseOutlineContainer(CourseOutlineItem):
"""
if not child_class:
child_class = self.CHILD_CLASS
+ # pylint: disable=no-member
return self.q(css=self._bounded_selector(child_class.BODY_SELECTOR)).map(
lambda el: child_class(self.browser, el.get_attribute('data-locator'))).results
@@ -227,10 +247,13 @@ class CourseOutlineContainer(CourseOutlineItem):
"""
Toggle the expansion of this subsection.
"""
-
+ # pylint: disable=no-member
self.browser.execute_script("jQuery.fx.off = true;")
def subsection_expanded():
+ """
+ Returns whether or not this subsection is expanded.
+ """
add_button = self.q(css=self._bounded_selector(self.ADD_BUTTON_SELECTOR)).first.results
return add_button and add_button[0].is_displayed()
@@ -253,7 +276,7 @@ class CourseOutlineContainer(CourseOutlineItem):
"""
Return whether this outline item is currently collapsed.
"""
- return "is-collapsed" in self.q(css=self._bounded_selector('')).first.attrs("class")[0]
+ return "is-collapsed" in self.q(css=self._bounded_selector('')).first.attrs("class")[0] # pylint: disable=no-member
class CourseOutlineChild(PageObject, CourseOutlineItem):
@@ -742,6 +765,9 @@ class CourseOutlinePage(CoursePage, CourseOutlineContainer):
class CourseOutlineModal(object):
+ """
+ Page object specifically for a modal window on the course outline page.
+ """
MODAL_SELECTOR = ".wrapper-modal-window"
def __init__(self, page):
@@ -754,26 +780,47 @@ class CourseOutlineModal(object):
return " ".join([self.MODAL_SELECTOR, selector])
def is_shown(self):
+ """
+ Return whether or not the modal defined by self.MODAL_SELECTOR is shown.
+ """
return self.page.q(css=self.MODAL_SELECTOR).present
def find_css(self, selector):
+ """
+ Find the given css selector on the page.
+ """
return self.page.q(css=self._bounded_selector(selector))
def click(self, selector, index=0):
+ """
+ Perform a Click action on the given selector.
+ """
self.find_css(selector).nth(index).click()
def save(self):
+ """
+ Click the save action button, and wait for the ajax call to return.
+ """
self.click(".action-save")
self.page.wait_for_ajax()
def publish(self):
+ """
+ Click the publish action button, and wait for the ajax call to return.
+ """
self.click(".action-publish")
self.page.wait_for_ajax()
def cancel(self):
+ """
+ Click the cancel action button.
+ """
self.click(".action-cancel")
def has_release_date(self):
+ """
+ Check if the input box for the release date exists in the subsection's settings window
+ """
return self.find_css("#start_date").present
def has_release_time(self):
@@ -783,6 +830,9 @@ class CourseOutlineModal(object):
return self.find_css("#start_time").present
def has_due_date(self):
+ """
+ Check if the input box for the due date exists in the subsection's settings window
+ """
return self.find_css("#due_date").present
def has_due_time(self):
@@ -792,6 +842,9 @@ class CourseOutlineModal(object):
return self.find_css("#due_time").present
def has_policy(self):
+ """
+ Check if the input for the grading policy is present.
+ """
return self.find_css("#grading_type").present
def set_date(self, property_name, input_selector, date):
@@ -806,7 +859,7 @@ class CourseOutlineModal(object):
current_month, current_year = datetime.datetime.today().month, datetime.datetime.today().year
date_diff = 12 * (year - current_year) + month - current_month
selector = "a.ui-datepicker-{}".format('next' if date_diff > 0 else 'prev')
- for i in xrange(abs(date_diff)):
+ for __ in xrange(abs(date_diff)):
self.page.q(css=selector).click()
self.page.q(css="a.ui-state-default").nth(day - 1).click() # set day
self.page.wait_for_element_invisibility("#ui-datepicker-div", "datepicker should be closed")
@@ -826,12 +879,15 @@ class CourseOutlineModal(object):
@property
def release_date(self):
+ """
+ Returns the unit's release date. Date is "mm/dd/yyyy" string.
+ """
return self.find_css("#start_date").first.attrs('value')[0]
@release_date.setter
def release_date(self, date):
"""
- Date is "mm/dd/yyyy" string.
+ Sets the unit's release date to `date`. Date is "mm/dd/yyyy" string.
"""
self.set_date('release_date', "#start_date", date)
@@ -851,12 +907,15 @@ class CourseOutlineModal(object):
@property
def due_date(self):
+ """
+ Returns the due date from the page. Date is "mm/dd/yyyy" string.
+ """
return self.find_css("#due_date").first.attrs('value')[0]
@due_date.setter
def due_date(self, date):
"""
- Date is "mm/dd/yyyy" string.
+ Sets the due date for the unit. Date is "mm/dd/yyyy" string.
"""
self.set_date('due_date', "#due_date", date)
diff --git a/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_video.py b/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_video.py
index b378fa5ac4..37cf2d4033 100755
--- a/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_video.py
+++ b/lms/djangoapps/course_wiki/plugins/markdownedx/mdx_video.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
-
+# TODO: Is this file still used? If so it should be refactored and tests added.
+# pylint: disable=line-too-long, invalid-name
"""
Embeds web videos using URLs. For instance, if a URL to an youtube video is
found in the text submitted to markdown and it isn't enclosed in parenthesis
@@ -132,8 +133,8 @@ try:
# Markdown 2.1.0 changed from 2.0.3. We try importing the new version first,
# but import the 2.0.3 version if it fails
from markdown.util import etree
-except: # pylint: disable=bare-except
- from markdown import etree
+except ImportError:
+ from markdown import etree # pylint: disable=no-name-in-module
version = "0.1.6"
@@ -164,7 +165,8 @@ class VideoExtension(markdown.Extension):
for key, value in configs:
self.setConfig(key, value)
- def add_inline(self, md, name, klass, re):
+ def add_inline(self, md, name, klass, re): # pylint: disable=invalid-name
+ """Adds the inline link"""
pattern = klass(re)
pattern.md = md
pattern.ext = self
@@ -192,6 +194,7 @@ class VideoExtension(markdown.Extension):
class Bliptv(markdown.inlinepatterns.Pattern):
def handleMatch(self, m):
url = 'http://blip.tv/scripts/flash/showplayer.swf?file=http://blip.tv/file/get/%s' % m.group('bliptvfile')
+ # pylint: disable=no-member
width = self.ext.config['bliptv_width'][0]
height = self.ext.config['bliptv_height'][0]
return flash_object(url, width, height)
@@ -200,6 +203,7 @@ class Bliptv(markdown.inlinepatterns.Pattern):
class Dailymotion(markdown.inlinepatterns.Pattern):
def handleMatch(self, m):
url = 'http://www.dailymotion.com/swf/%s' % m.group('dailymotionid').split('/')[-1]
+ # pylint: disable=no-member
width = self.ext.config['dailymotion_width'][0]
height = self.ext.config['dailymotion_height'][0]
return flash_object(url, width, height)
@@ -209,6 +213,7 @@ class Gametrailers(markdown.inlinepatterns.Pattern):
def handleMatch(self, m):
url = 'http://www.gametrailers.com/remote_wrap.php?mid=%s' % \
m.group('gametrailersid').split('/')[-1]
+ # pylint: disable=no-member
width = self.ext.config['gametrailers_width'][0]
height = self.ext.config['gametrailers_height'][0]
return flash_object(url, width, height)
@@ -217,6 +222,7 @@ class Gametrailers(markdown.inlinepatterns.Pattern):
class Metacafe(markdown.inlinepatterns.Pattern):
def handleMatch(self, m):
url = 'http://www.metacafe.com/fplayer/%s.swf' % m.group('metacafeid')
+ # pylint: disable=no-member
width = self.ext.config['metacafe_width'][0]
height = self.ext.config['metacafe_height'][0]
return flash_object(url, width, height)
@@ -225,6 +231,7 @@ class Metacafe(markdown.inlinepatterns.Pattern):
class Veoh(markdown.inlinepatterns.Pattern):
def handleMatch(self, m):
url = 'http://www.veoh.com/videodetails2.swf?permalinkId=%s' % m.group('veohid')
+ # pylint: disable=no-member
width = self.ext.config['veoh_width'][0]
height = self.ext.config['veoh_height'][0]
return flash_object(url, width, height)
@@ -233,6 +240,7 @@ class Veoh(markdown.inlinepatterns.Pattern):
class Vimeo(markdown.inlinepatterns.Pattern):
def handleMatch(self, m):
url = 'http://vimeo.com/moogaloop.swf?clip_id=%s&server=vimeo.com' % m.group('vimeoid')
+ # pylint: disable=no-member
width = self.ext.config['vimeo_width'][0]
height = self.ext.config['vimeo_height'][0]
return flash_object(url, width, height)
@@ -241,6 +249,7 @@ class Vimeo(markdown.inlinepatterns.Pattern):
class Yahoo(markdown.inlinepatterns.Pattern):
def handleMatch(self, m):
url = "http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.40"
+ # pylint: disable=no-member
width = self.ext.config['yahoo_width'][0]
height = self.ext.config['yahoo_height'][0]
obj = flash_object(url, width, height)
@@ -255,6 +264,7 @@ class Yahoo(markdown.inlinepatterns.Pattern):
class Youtube(markdown.inlinepatterns.Pattern):
def handleMatch(self, m):
url = 'http://www.youtube.com/v/%s' % m.group('youtubeargs')
+ # pylint: disable=no-member
width = self.ext.config['youtube_width'][0]
height = self.ext.config['youtube_height'][0]
return flash_object(url, width, height)
diff --git a/lms/djangoapps/instructor_task/tasks.py b/lms/djangoapps/instructor_task/tasks.py
index 7898f4b30f..a5ac19e5a5 100644
--- a/lms/djangoapps/instructor_task/tasks.py
+++ b/lms/djangoapps/instructor_task/tasks.py
@@ -51,7 +51,7 @@ from instructor_task.tasks_helper import (
TASK_LOG = logging.getLogger('edx.celery.task')
-@task(base=BaseInstructorTask)
+@task(base=BaseInstructorTask) # pylint: disable=not-callable
def rescore_problem(entry_id, xmodule_instance_args):
"""Rescores a problem in a course, for all students or one specific student.
@@ -82,7 +82,7 @@ def rescore_problem(entry_id, xmodule_instance_args):
return run_main_task(entry_id, visit_fcn, action_name)
-@task(base=BaseInstructorTask)
+@task(base=BaseInstructorTask) # pylint: disable=not-callable
def reset_problem_attempts(entry_id, xmodule_instance_args):
"""Resets problem attempts to zero for a particular problem for all students in a course.
@@ -104,7 +104,7 @@ def reset_problem_attempts(entry_id, xmodule_instance_args):
return run_main_task(entry_id, visit_fcn, action_name)
-@task(base=BaseInstructorTask)
+@task(base=BaseInstructorTask) # pylint: disable=not-callable
def delete_problem_state(entry_id, xmodule_instance_args):
"""Deletes problem state entirely for all students on a particular problem in a course.
@@ -126,7 +126,7 @@ def delete_problem_state(entry_id, xmodule_instance_args):
return run_main_task(entry_id, visit_fcn, action_name)
-@task(base=BaseInstructorTask)
+@task(base=BaseInstructorTask) # pylint: disable=not-callable
def send_bulk_course_email(entry_id, _xmodule_instance_args):
"""Sends emails to recipients enrolled in a course.
@@ -147,7 +147,7 @@ def send_bulk_course_email(entry_id, _xmodule_instance_args):
return run_main_task(entry_id, visit_fcn, action_name)
-@task(base=BaseInstructorTask, routing_key=settings.GRADES_DOWNLOAD_ROUTING_KEY)
+@task(base=BaseInstructorTask, routing_key=settings.GRADES_DOWNLOAD_ROUTING_KEY) # pylint: disable=not-callable
def calculate_problem_responses_csv(entry_id, xmodule_instance_args):
"""
Compute student answers to a given problem and upload the CSV to
@@ -159,7 +159,7 @@ def calculate_problem_responses_csv(entry_id, xmodule_instance_args):
return run_main_task(entry_id, task_fn, action_name)
-@task(base=BaseInstructorTask, routing_key=settings.GRADES_DOWNLOAD_ROUTING_KEY)
+@task(base=BaseInstructorTask, routing_key=settings.GRADES_DOWNLOAD_ROUTING_KEY) # pylint: disable=not-callable
def calculate_grades_csv(entry_id, xmodule_instance_args):
"""
Grade a course and push the results to an S3 bucket for download.
@@ -175,7 +175,7 @@ def calculate_grades_csv(entry_id, xmodule_instance_args):
return run_main_task(entry_id, task_fn, action_name)
-@task(base=BaseInstructorTask, routing_key=settings.GRADES_DOWNLOAD_ROUTING_KEY)
+@task(base=BaseInstructorTask, routing_key=settings.GRADES_DOWNLOAD_ROUTING_KEY) # pylint: disable=not-callable
def calculate_problem_grade_report(entry_id, xmodule_instance_args):
"""
Generate a CSV for a course containing all students' problem
@@ -192,7 +192,7 @@ def calculate_problem_grade_report(entry_id, xmodule_instance_args):
return run_main_task(entry_id, task_fn, action_name)
-@task(base=BaseInstructorTask, routing_key=settings.GRADES_DOWNLOAD_ROUTING_KEY)
+@task(base=BaseInstructorTask, routing_key=settings.GRADES_DOWNLOAD_ROUTING_KEY) # pylint: disable=not-callable
def calculate_students_features_csv(entry_id, xmodule_instance_args):
"""
Compute student profile information for a course and upload the
@@ -204,7 +204,7 @@ def calculate_students_features_csv(entry_id, xmodule_instance_args):
return run_main_task(entry_id, task_fn, action_name)
-@task(base=BaseInstructorTask)
+@task(base=BaseInstructorTask) # pylint: disable=not-callable
def enrollment_report_features_csv(entry_id, xmodule_instance_args):
"""
Compute student profile information for a course and upload the
@@ -216,7 +216,7 @@ def enrollment_report_features_csv(entry_id, xmodule_instance_args):
return run_main_task(entry_id, task_fn, action_name)
-@task(base=BaseInstructorTask)
+@task(base=BaseInstructorTask) # pylint: disable=not-callable
def exec_summary_report_csv(entry_id, xmodule_instance_args):
"""
Compute executive summary report for a course and upload the
@@ -228,7 +228,7 @@ def exec_summary_report_csv(entry_id, xmodule_instance_args):
return run_main_task(entry_id, task_fn, action_name)
-@task(base=BaseInstructorTask)
+@task(base=BaseInstructorTask) # pylint: disable=not-callable
def course_survey_report_csv(entry_id, xmodule_instance_args):
"""
Compute the survey report for a course and upload the
@@ -240,7 +240,7 @@ def course_survey_report_csv(entry_id, xmodule_instance_args):
return run_main_task(entry_id, task_fn, action_name)
-@task(base=BaseInstructorTask)
+@task(base=BaseInstructorTask) # pylint: disable=not-callable
def proctored_exam_results_csv(entry_id, xmodule_instance_args):
"""
Compute proctored exam results report for a course and upload the
@@ -251,7 +251,7 @@ def proctored_exam_results_csv(entry_id, xmodule_instance_args):
return run_main_task(entry_id, task_fn, action_name)
-@task(base=BaseInstructorTask, routing_key=settings.GRADES_DOWNLOAD_ROUTING_KEY)
+@task(base=BaseInstructorTask, routing_key=settings.GRADES_DOWNLOAD_ROUTING_KEY) # pylint: disable=not-callable
def calculate_may_enroll_csv(entry_id, xmodule_instance_args):
"""
Compute information about invited students who have not enrolled
@@ -264,7 +264,7 @@ def calculate_may_enroll_csv(entry_id, xmodule_instance_args):
return run_main_task(entry_id, task_fn, action_name)
-@task(base=BaseInstructorTask, routing_key=settings.GRADES_DOWNLOAD_ROUTING_KEY)
+@task(base=BaseInstructorTask, routing_key=settings.GRADES_DOWNLOAD_ROUTING_KEY) # pylint: disable=not-callable
def generate_certificates(entry_id, xmodule_instance_args):
"""
Grade students and generate certificates.
@@ -280,7 +280,7 @@ def generate_certificates(entry_id, xmodule_instance_args):
return run_main_task(entry_id, task_fn, action_name)
-@task(base=BaseInstructorTask)
+@task(base=BaseInstructorTask) # pylint: disable=not-callable
def cohort_students(entry_id, xmodule_instance_args):
"""
Cohort students in bulk, and upload the results.
diff --git a/scripts/all-tests.sh b/scripts/all-tests.sh
index ed0d3e04fa..c0f49ca21f 100755
--- a/scripts/all-tests.sh
+++ b/scripts/all-tests.sh
@@ -11,7 +11,7 @@ set -e
###############################################################################
# Violations thresholds for failing the build
-export PYLINT_THRESHOLD=4999
+export PYLINT_THRESHOLD=4700
export JSHINT_THRESHOLD=9080
doCheckVars() {