diff --git a/a11y_tests/mixins.py b/a11y_tests/mixins.py index fe7269c64..555e138d0 100644 --- a/a11y_tests/mixins.py +++ b/a11y_tests/mixins.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import - from acceptance_tests.mixins import AnalyticsApiClientMixin, LoginMixin @@ -10,6 +8,6 @@ class CoursePageTestsMixin(LoginMixin, AnalyticsApiClientMixin): page = None def setUp(self): - super(CoursePageTestsMixin, self).setUp() + super().setUp() self.api_date_format = self.analytics_api_client.DATE_FORMAT self.api_datetime_format = self.analytics_api_client.DATETIME_FORMAT diff --git a/a11y_tests/pages.py b/a11y_tests/pages.py index 3e7dc24b7..a923d58bd 100644 --- a/a11y_tests/pages.py +++ b/a11y_tests/pages.py @@ -2,7 +2,6 @@ Tests for course analytics pages """ -from __future__ import absolute_import from bok_choy.page_object import PageObject @@ -16,13 +15,13 @@ class CoursePage(PageObject): def __init__(self, browser, course_id=None): # Create the path self.course_id = course_id or TEST_COURSE_ID - path = 'courses/{}'.format(self.course_id) + path = f'courses/{self.course_id}' self.server_url = DASHBOARD_SERVER_URL - self.page_url = '{0}/{1}'.format(self.server_url, path) + self.page_url = f'{self.server_url}/{path}' # Call the constructor and setup the URL - super(CoursePage, self).__init__(browser) + super().__init__(browser) def is_browser_on_page(self): return self.browser.current_url == self.page_url @@ -36,13 +35,13 @@ class CourseEnrollmentDemographicsPage(CoursePage): demographic = None def __init__(self, browser, course_id=None): - super(CourseEnrollmentDemographicsPage, self).__init__(browser, course_id) - self.page_url += '/enrollment/demographics/{0}/'.format(self.demographic) + super().__init__(browser, course_id) + self.page_url += f'/enrollment/demographics/{self.demographic}/' def is_browser_on_page(self): return ( - super(CourseEnrollmentDemographicsPage, self).is_browser_on_page() - and 'Enrollment Demographics by {0}'.format(self.demographic.title()) + super().is_browser_on_page() + and f'Enrollment Demographics by {self.demographic.title()}' in self.browser.title ) diff --git a/a11y_tests/test_course_enrollment_demographics_axs.py b/a11y_tests/test_course_enrollment_demographics_axs.py index a3d8a0169..ada860ca5 100644 --- a/a11y_tests/test_course_enrollment_demographics_axs.py +++ b/a11y_tests/test_course_enrollment_demographics_axs.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import - from bok_choy.promise import EmptyPromise from bok_choy.web_app_test import WebAppTest @@ -15,7 +13,7 @@ class CourseEnrollmentDemographicsAgeTests(CoursePageTestsMixin, WebAppTest): """ def setUp(self): - super(CourseEnrollmentDemographicsAgeTests, self).setUp() + super().setUp() self.page = CourseEnrollmentDemographicsAgePage(self.browser) def test_a11y(self): diff --git a/acceptance_tests/__init__.py b/acceptance_tests/__init__.py index 38232a097..7e9415c20 100644 --- a/acceptance_tests/__init__.py +++ b/acceptance_tests/__init__.py @@ -1,5 +1,3 @@ - - import locale import os @@ -7,7 +5,7 @@ def str2bool(s): - return str(s).lower() in (u"yes", u"true", u"t", u"1") + return str(s).lower() in ("yes", "true", "t", "1") # Dashboard settings @@ -40,27 +38,27 @@ def str2bool(s): if ENABLE_OAUTH_TESTS and not (LMS_HOSTNAME and LMS_USERNAME and LMS_PASSWORD): raise Exception('LMS settings must be set in order to test OAuth.') -TEST_COURSE_ID = os.environ.get('TEST_COURSE_ID', u'edX/DemoX/Demo_Course') +TEST_COURSE_ID = os.environ.get('TEST_COURSE_ID', 'edX/DemoX/Demo_Course') TEST_ASSIGNMENT_TYPE = os.environ.get('TEST_ASSIGNMENT_TYPE', 'Homework') -TEST_ASSIGNMENT_ID = os.environ.get('TEST_ASSIGNMENT_ID', u'i4x://edX/DemoX/sequential/basic_questions') +TEST_ASSIGNMENT_ID = os.environ.get('TEST_ASSIGNMENT_ID', 'i4x://edX/DemoX/sequential/basic_questions') TEST_GRADED_PROBLEM_ID = os.environ.get('TEST_GRADED_PROBLEM_ID', - u'i4x://edX/DemoX/problem/a0effb954cca4759994f1ac9e9434bf4') + 'i4x://edX/DemoX/problem/a0effb954cca4759994f1ac9e9434bf4') TEST_GRADED_PROBLEM_PART_ID = os.environ.get('TEST_GRADED_PROBLEM_PART_ID', - u'i4x-edX-DemoX-problem-a0effb954cca4759994f1ac9e9434bf4_2_1') + 'i4x-edX-DemoX-problem-a0effb954cca4759994f1ac9e9434bf4_2_1') TEST_UNGRADED_SECTION_ID = os.environ.get('TEST_UNGRADED_SECTION_ID', - u'i4x://edX/DemoX/chapter/interactive_demonstrations') + 'i4x://edX/DemoX/chapter/interactive_demonstrations') TEST_UNGRADED_SUBSECTION_ID = os.environ.get('TEST_UNGRADED_SUBSECTION_ID', - u'i4x://edX/DemoX/sequential/19a30717eff543078a5d94ae9d6c18a5') + 'i4x://edX/DemoX/sequential/19a30717eff543078a5d94ae9d6c18a5') TEST_UNGRADED_PROBLEM_ID = os.environ.get('TEST_UNGRADED_PROBLEM_ID', - u'i4x://edX/DemoX/problem/303034da25524878a2e66fb57c91cf85') + 'i4x://edX/DemoX/problem/303034da25524878a2e66fb57c91cf85') TEST_UNGRADED_PROBLEM_PART_ID = os.environ.get('TEST_UNGRADED_PROBLEM_PART_ID', - u'i4x-edX-DemoX-problem-303034da25524878a2e66fb57c91cf85_2_1') + 'i4x-edX-DemoX-problem-303034da25524878a2e66fb57c91cf85_2_1') TEST_VIDEO_SECTION_ID = os.environ.get('TEST_VIDEO_SECTION_ID', - u'i4x://edX/DemoX/chapter/interactive_demonstrations') + 'i4x://edX/DemoX/chapter/interactive_demonstrations') TEST_VIDEO_SUBSECTION_ID = os.environ.get('TEST_VIDEO_SUBSECTION_ID', - u'i4x://edX/DemoX/sequential/19a30717eff543078a5d94ae9d6c18a5') + 'i4x://edX/DemoX/sequential/19a30717eff543078a5d94ae9d6c18a5') TEST_VIDEO_ID = os.environ.get('TEST_VIDEO_ID', - u'i4x://edX/DemoX/video/7e9b434e6de3435ab99bd3fb25bde807') + 'i4x://edX/DemoX/video/7e9b434e6de3435ab99bd3fb25bde807') DOC_BASE_URL = os.environ.get('DOC_BASE_URL', 'http://edx-insights.readthedocs.org/en/latest') diff --git a/acceptance_tests/course_validation/__init__.py b/acceptance_tests/course_validation/__init__.py index 8809c47ef..b1b2293c7 100644 --- a/acceptance_tests/course_validation/__init__.py +++ b/acceptance_tests/course_validation/__init__.py @@ -1,5 +1,3 @@ - - import os from acceptance_tests import str2bool diff --git a/acceptance_tests/course_validation/report_generators.py b/acceptance_tests/course_validation/report_generators.py index 6ff5d6050..ac7a7bd9b 100644 --- a/acceptance_tests/course_validation/report_generators.py +++ b/acceptance_tests/course_validation/report_generators.py @@ -1,5 +1,3 @@ - - import datetime import logging import traceback @@ -50,11 +48,11 @@ def get_http_status_and_load_time(self, url): def build_course_path(self, path): path = path.strip('/') - return '/courses/{}/{}/'.format(self.course_id, path) + return f'/courses/{self.course_id}/{path}/' def get_dashboard_url(self, path): path = path.strip('/') - return '{}/{}/'.format(DASHBOARD_SERVER_URL, path) + return f'{DASHBOARD_SERVER_URL}/{path}/' def generate_report(self): """ @@ -283,7 +281,7 @@ class CoursePerformanceScreenshotReporter(CoursePerformanceReportGenerator): REPORT_NAME = 'course_performance_screenshot' def __init__(self, course_id, http_cookies=None): - super(CoursePerformanceScreenshotReporter, self).__init__(course_id, http_cookies) + super().__init__(course_id, http_cookies) self.driver = webdriver.Firefox() def _take_screenshot(self, url_path): @@ -310,9 +308,9 @@ def _login(self): if BASIC_AUTH_CREDENTIALS: username = BASIC_AUTH_CREDENTIALS[0] password = BASIC_AUTH_CREDENTIALS[1] - url = url.replace('://', '://{}:{}@'.format(username, password)) + url = url.replace('://', f'://{username}:{password}@') - self.driver.get('{}/login'.format(url)) + self.driver.get(f'{url}/login') self.driver.find_element_by_id('login-email').send_keys(LMS_USERNAME) self.driver.find_element_by_id('login-password').send_keys(LMS_PASSWORD) self.driver.find_element_by_css_selector('button.login-button').click() diff --git a/acceptance_tests/course_validation/report_runner.py b/acceptance_tests/course_validation/report_runner.py index b3d2e1212..c9ff9ea9c 100755 --- a/acceptance_tests/course_validation/report_runner.py +++ b/acceptance_tests/course_validation/report_runner.py @@ -20,7 +20,6 @@ """ import datetime -import io import json import logging import time @@ -64,7 +63,7 @@ def _setup_logging(): msg_format = '%(asctime)s - %(levelname)s - %(message)s' logging.basicConfig( - filename='{}-course_report.log'.format(TIMESTAMP), + filename=f'{TIMESTAMP}-course_report.log', format=msg_format, level=level) @@ -126,7 +125,7 @@ def login(http_client): if ENABLE_AUTO_AUTH: logger.info('Logging into dashboard with auto auth...') - response = http_client.get('{}/test/auto_auth/'.format(DASHBOARD_SERVER_URL)) + response = http_client.get(f'{DASHBOARD_SERVER_URL}/test/auto_auth/') if response.status_code == 200: logger.info('Login succeeded.') @@ -140,8 +139,8 @@ def login(http_client): if BASIC_AUTH_CREDENTIALS: http_client.auth = BASIC_AUTH_CREDENTIALS - lms_login = '{}/login'.format(LMS_URL) - lms_login_ajax = '{}/login_ajax'.format(LMS_URL) + lms_login = f'{LMS_URL}/login' + lms_login_ajax = f'{LMS_URL}/login_ajax' # Make a call to the login page to get cookies (esp. CSRF token) http_client.get(lms_login) @@ -175,7 +174,7 @@ def get_courses(): filename = 'courses.json' try: - with io.open(filename, 'r', encoding='utf-8') as f: + with open(filename, 'r', encoding='utf-8') as f: courses = json.load(f) except Exception as e: # pylint: disable=broad-except logger.warning('Failed to read courses from file: %s', e) @@ -188,7 +187,7 @@ def get_courses(): courses = [course['id'] for course in courses] courses.sort(key=lambda course: course.lower()) - with io.open(filename, 'w', encoding='utf-8') as f: + with open(filename, 'w', encoding='utf-8') as f: f.write(str(json.dumps(courses, ensure_ascii=False))) logger.info('Retrieved %s courses.', len(courses)) @@ -212,7 +211,7 @@ def main(): # Create the mappings mappings_file = join(dirname(abspath(__file__)), 'mappings.json') - with io.open(mappings_file, 'r', encoding='utf-8') as f: + with open(mappings_file, 'r', encoding='utf-8') as f: mappings = json.load(f) for doc_type, body in mappings.items(): diff --git a/acceptance_tests/mixins.py b/acceptance_tests/mixins.py index 23f477f7e..a6538340c 100644 --- a/acceptance_tests/mixins.py +++ b/acceptance_tests/mixins.py @@ -1,5 +1,3 @@ - - import datetime import locale from unittest import skip @@ -36,7 +34,7 @@ class AnalyticsApiClientMixin: analytics_api_client = None def setUp(self): - super(AnalyticsApiClientMixin, self).setUp() + super().setUp() api_url = API_SERVER_URL auth_token = API_AUTH_TOKEN @@ -47,7 +45,7 @@ class CourseApiMixin: course_api_client = None def setUp(self): - super(CourseApiMixin, self).setUp() + super().setUp() if ENABLE_COURSE_API: self.course_api_client = CourseStructureApiClient(COURSE_API_URL, COURSE_API_KEY, 5) @@ -120,7 +118,7 @@ def assertTable(self, table_selector, columns, download_selector=None): # check the headings self.assertTableColumnHeadingsEqual(table_selector, columns) - rows = self.page.browser.find_elements_by_css_selector('{} tbody tr'.format(table_selector)) + rows = self.page.browser.find_elements_by_css_selector(f'{table_selector} tbody tr') self.assertGreater(len(rows), 0) if download_selector is not None: @@ -150,30 +148,30 @@ def _test_footer(self): self.assertTrue(element.present) def test_page(self): - super(FooterMixin, self).test_page() + super().test_page() self._test_footer() class FooterLegalMixin(FooterMixin): def _test_footer(self): - super(FooterLegalMixin, self)._test_footer() + super()._test_footer() # Verify the terms of service link is present selector = self.footer_selector + " a[data-role=tos]" element = self.page.q(css=selector) self.assertTrue(element.present) - self.assertEqual(element.text[0], u'Terms of Service') + self.assertEqual(element.text[0], 'Terms of Service') # Verify the privacy policy link is present selector = self.footer_selector + " a[data-role=privacy-policy]" element = self.page.q(css=selector) self.assertTrue(element.present) - self.assertEqual(element.text[0], u'Privacy Policy') + self.assertEqual(element.text[0], 'Privacy Policy') class FooterFeedbackMixin(FooterMixin): def _test_footer(self): - super(FooterFeedbackMixin, self)._test_footer() + super()._test_footer() # check that we have an email self.assertValidFeedbackLink(self.footer_selector + " a[class=feedback-email]") @@ -238,7 +236,7 @@ def test_page(self): class LoginMixin: def setUp(self): - super(LoginMixin, self).setUp() + super().setUp() self.lms_login_page = LMSLoginPage(self.browser) def login(self): @@ -248,7 +246,7 @@ def login(self): self.login_with_lms() def login_with_auto_auth(self): - url = '{}/test/auto_auth/'.format(DASHBOARD_SERVER_URL) + url = f'{DASHBOARD_SERVER_URL}/test/auto_auth/' self.browser.get(url) def login_with_lms(self): @@ -261,7 +259,7 @@ def login_with_lms(self): class LogoutMixin: def logout(self): - url = '{}/logout/'.format(DASHBOARD_SERVER_URL) + url = f'{DASHBOARD_SERVER_URL}/logout/' self.browser.get(url) @@ -270,7 +268,7 @@ class ContextSensitiveHelpMixin: @property def help_url(self): - return '{0}/{1}'.format(DOC_BASE_URL, self.help_path) + return f'{DOC_BASE_URL}/{self.help_path}' def test_page(self): # Validate the help link @@ -292,7 +290,7 @@ def _test_soapbox_messages(self): self.assertTrue(SOAPBOX_SINGLE_PAGE_MESSAGE in element.text) def test_page(self): - super(SoapboxMessagesMixin, self).test_page() + super().test_page() self._test_soapbox_messages() @@ -330,7 +328,7 @@ def assertSummaryPointValueEquals(self, data_selector, value): if len(value) > MAX_SUMMARY_POINT_VALUE_LENGTH: value = value[:(MAX_SUMMARY_POINT_VALUE_LENGTH - 1)] + '…' - element = self.page.q(css="div[{0}] .summary-point-number".format(data_selector)) + element = self.page.q(css=f"div[{data_selector}] .summary-point-number") self.assertTrue(element.present) self.assertEqual(element.text[0], value) @@ -342,7 +340,7 @@ def assertSummaryTooltipEquals(self, data_selector, tip_text): data_selector (String): Attribute selector (ex. data-stat-type=current_enrollment) tip_text (String): expected text """ - help_selector = "div[{0}] .summary-point-help".format(data_selector) + help_selector = f"div[{data_selector}] .summary-point-help" element = self.page.q(css=help_selector) self.assertTrue(element.present) @@ -371,7 +369,7 @@ class CoursePageTestsMixin(AnalyticsApiClientMixin, FooterLegalMixin, FooterFeed page = None def setUp(self): - super(CoursePageTestsMixin, self).setUp() + super().setUp() self.api_date_format = self.analytics_api_client.DATE_FORMAT self.api_datetime_format = self.analytics_api_client.DATETIME_FORMAT @@ -391,7 +389,7 @@ def format_last_updated_date_and_time(self, d): def build_display_percentage(self, count, total, zero_percent_default='0.0%'): if total and count: percent = count / float(total) * 100.0 - return '{:.1f}%'.format(percent) if percent >= 1.0 else '< 1%' + return f'{percent:.1f}%' if percent >= 1.0 else '< 1%' return zero_percent_default def _get_data_update_message(self): @@ -415,7 +413,7 @@ def test_page(self): pass, execution of this parent method will leave the browser on the page being tested. :return: """ - super(CoursePageTestsMixin, self).test_page() + super().test_page() self._test_data_update_message() self._test_course_home_nav() @@ -430,7 +428,7 @@ class CourseDemographicsPageTestsMixin(CoursePageTestsMixin): demographic_data = None def test_page(self): - super(CourseDemographicsPageTestsMixin, self).test_page() + super().test_page() self._test_data_information_message() self._test_chart() self._test_table() @@ -443,7 +441,7 @@ def _test_chart(self): def _test_table(self): self.assertTable(self.table_section_selector, self.table_columns, self.table_download_selector) - rows = self.page.browser.find_elements_by_css_selector('{} tbody tr'.format(self.table_section_selector)) + rows = self.page.browser.find_elements_by_css_selector(f'{self.table_section_selector} tbody tr') self.assertGreater(len(rows), 0) sum_count = 0.0 if self.demographic_data and 'count' in self.demographic_data[0]: diff --git a/acceptance_tests/pages.py b/acceptance_tests/pages.py index 6e5d2b896..13e94be73 100644 --- a/acceptance_tests/pages.py +++ b/acceptance_tests/pages.py @@ -36,10 +36,10 @@ def url(self): return self.page_url def __init__(self, browser, path=None): - super(DashboardPage, self).__init__(browser) + super().__init__(browser) path = path or self.path self.server_url = DASHBOARD_SERVER_URL - self.page_url = '{0}/{1}'.format(self.server_url, path) + self.page_url = f'{self.server_url}/{path}' class LandingPage(DashboardPage): @@ -53,10 +53,10 @@ class CoursePage(DashboardPage): def __init__(self, browser, course_id=None): # Create the path self.course_id = course_id or TEST_COURSE_ID - path = 'courses/{}'.format(self.course_id) + path = f'courses/{self.course_id}' # Call the constructor and setup the URL - super(CoursePage, self).__init__(browser, path) + super().__init__(browser, path) def is_browser_on_page(self): return self.browser.current_url == self.page_url @@ -64,20 +64,20 @@ def is_browser_on_page(self): class CourseHomePage(CoursePage): def __init__(self, browser, course_id=None): - super(CourseHomePage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.page_url += '/' def is_browser_on_page(self): - return super(CourseHomePage, self).is_browser_on_page() and self.browser.title.startswith('Course Home') + return super().is_browser_on_page() and self.browser.title.startswith('Course Home') class CourseEnrollmentActivityPage(CoursePage): def __init__(self, browser, course_id=None): - super(CourseEnrollmentActivityPage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.page_url += '/enrollment/activity/' def is_browser_on_page(self): - return super(CourseEnrollmentActivityPage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ 'Enrollment Activity' in self.browser.title @@ -87,9 +87,9 @@ def url(self): protocol = 'https' if LMS_SSL_ENABLED else 'http' if BASIC_AUTH_USERNAME and BASIC_AUTH_PASSWORD: - return '{0}://{1}:{2}@{3}/login'.format(protocol, BASIC_AUTH_USERNAME, BASIC_AUTH_PASSWORD, LMS_HOSTNAME) + return f'{protocol}://{BASIC_AUTH_USERNAME}:{BASIC_AUTH_PASSWORD}@{LMS_HOSTNAME}/login' - return '{0}://{1}/login'.format(protocol, LMS_HOSTNAME) + return f'{protocol}://{LMS_HOSTNAME}/login' def is_browser_on_page(self): return self.browser.title.startswith('Log into') @@ -117,12 +117,12 @@ class CourseEnrollmentDemographicsPage(CoursePage): demographic = None def __init__(self, browser, course_id=None): - super(CourseEnrollmentDemographicsPage, self).__init__(browser, course_id) - self.page_url += '/enrollment/demographics/{0}/'.format(self.demographic) + super().__init__(browser, course_id) + self.page_url += f'/enrollment/demographics/{self.demographic}/' def is_browser_on_page(self): - return super(CourseEnrollmentDemographicsPage, self).is_browser_on_page() and \ - 'Enrollment Demographics by {0}'.format(self.demographic.title()) in self.browser.title + return super().is_browser_on_page() and \ + f'Enrollment Demographics by {self.demographic.title()}' in self.browser.title class CourseEnrollmentDemographicsAgePage(CourseEnrollmentDemographicsPage): @@ -139,61 +139,61 @@ class CourseEnrollmentDemographicsEducationPage(CourseEnrollmentDemographicsPage class CourseEnrollmentGeographyPage(CoursePage): def __init__(self, browser, course_id=None): - super(CourseEnrollmentGeographyPage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.page_url += '/enrollment/geography/' def is_browser_on_page(self): - return super(CourseEnrollmentGeographyPage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ 'Enrollment Geography' in self.browser.title class CourseEngagementContentPage(CoursePage): def __init__(self, browser, course_id=None): - super(CourseEngagementContentPage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.page_url += '/engagement/content/' def is_browser_on_page(self): - return super(CourseEngagementContentPage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ 'Engagement Content' in self.browser.title class CourseEngagementVideosContentPage(CoursePage): def __init__(self, browser, course_id=None): - super(CourseEngagementVideosContentPage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.page_url += '/engagement/videos/' def is_browser_on_page(self): - return super(CourseEngagementVideosContentPage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ 'Engagement Videos' in self.browser.title class CourseEngagementVideoSectionPage(CoursePage): def __init__(self, browser, course_id=None, section_id=None): - super(CourseEngagementVideoSectionPage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.section_id = section_id or TEST_VIDEO_SECTION_ID - self.page_url += '/engagement/videos/sections/{}/'.format(self.section_id) + self.page_url += f'/engagement/videos/sections/{self.section_id}/' def is_browser_on_page(self): - return super(CourseEngagementVideoSectionPage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ 'Engagement Videos' in self.browser.title class CourseEngagementVideoSubsectionPage(CoursePage): def __init__(self, browser, course_id=None, section_id=None, subsection_id=None): - super(CourseEngagementVideoSubsectionPage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.section_id = section_id or TEST_VIDEO_SECTION_ID self.subsection_id = subsection_id or TEST_VIDEO_SUBSECTION_ID self.page_url += '/engagement/videos/sections/{}/subsections/{}/'.format( self.section_id, self.subsection_id) def is_browser_on_page(self): - return super(CourseEngagementVideoSubsectionPage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ 'Engagement Videos' in self.browser.title class CourseEngagementVideoTimelinePage(CoursePage): def __init__(self, browser, course_id=None, section_id=None, subsection_id=None, video_id=None): - super(CourseEngagementVideoTimelinePage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.section_id = section_id or TEST_VIDEO_SECTION_ID self.subsection_id = subsection_id or TEST_VIDEO_SUBSECTION_ID self.video_id = video_id or TEST_VIDEO_ID @@ -201,7 +201,7 @@ def __init__(self, browser, course_id=None, section_id=None, subsection_id=None, self.section_id, self.subsection_id, self.video_id) def is_browser_on_page(self): - return super(CourseEngagementVideoTimelinePage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ 'Engagement Videos' in self.browser.title @@ -214,41 +214,41 @@ def is_browser_on_page(self): class CoursePerformanceUngradedContentPage(CoursePage): def __init__(self, browser, course_id=None): - super(CoursePerformanceUngradedContentPage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.page_url += '/performance/ungraded_content/' def is_browser_on_page(self): - return super(CoursePerformanceUngradedContentPage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ 'Ungraded Problems' in self.browser.title class CoursePerformanceUngradedSectionPage(CoursePage): def __init__(self, browser, course_id=None, section_id=None): - super(CoursePerformanceUngradedSectionPage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.section_id = section_id or TEST_UNGRADED_SECTION_ID - self.page_url += '/performance/ungraded_content/sections/{}/'.format(self.section_id) + self.page_url += f'/performance/ungraded_content/sections/{self.section_id}/' def is_browser_on_page(self): - return super(CoursePerformanceUngradedSectionPage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ 'Ungraded Problems' in self.browser.title class CoursePerformanceUngradedSubsectionPage(CoursePage): def __init__(self, browser, course_id=None, section_id=None, subsection_id=None): - super(CoursePerformanceUngradedSubsectionPage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.section_id = section_id or TEST_UNGRADED_SECTION_ID self.subsection_id = subsection_id or TEST_UNGRADED_SUBSECTION_ID self.page_url += '/performance/ungraded_content/sections/{}/subsections/{}/'.format( self.section_id, self.subsection_id) def is_browser_on_page(self): - return super(CoursePerformanceUngradedSubsectionPage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ 'Ungraded Problems' in self.browser.title class CoursePerformanceUngradedAnswerDistributionPage(CoursePage): def __init__(self, browser, course_id=None, section_id=None, subsection_id=None, problem_id=None, part_id=None): - super(CoursePerformanceUngradedAnswerDistributionPage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.section_id = section_id or TEST_UNGRADED_SECTION_ID self.subsection_id = subsection_id or TEST_UNGRADED_SUBSECTION_ID self.problem_id = problem_id or TEST_UNGRADED_PROBLEM_ID @@ -258,45 +258,45 @@ def __init__(self, browser, course_id=None, section_id=None, subsection_id=None, self.problem_id, self.part_id) def is_browser_on_page(self): - return super(CoursePerformanceUngradedAnswerDistributionPage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ self.browser.title.startswith('Performance: Problem Submissions') class CoursePerformanceGradedContentPage(CoursePage): def __init__(self, browser, course_id=None): - super(CoursePerformanceGradedContentPage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.page_url += '/performance/graded_content/' def is_browser_on_page(self): - return super(CoursePerformanceGradedContentPage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ 'Graded Content' in self.browser.title class CoursePerformanceGradedContentByTypePage(CoursePage): def __init__(self, browser, course_id=None, assignment_type=None): - super(CoursePerformanceGradedContentByTypePage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.assignment_type = assignment_type or TEST_ASSIGNMENT_TYPE - self.page_url += '/performance/graded_content/{}/'.format(self.assignment_type) + self.page_url += f'/performance/graded_content/{self.assignment_type}/' def is_browser_on_page(self): - return super(CoursePerformanceGradedContentByTypePage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ self.assignment_type in self.browser.title class CoursePerformanceAssignmentPage(CoursePage): def __init__(self, browser, course_id=None, assignment_id=None): - super(CoursePerformanceAssignmentPage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.assignment_id = assignment_id or TEST_ASSIGNMENT_ID - self.page_url += '/performance/graded_content/assignments/{}/'.format(self.assignment_id) + self.page_url += f'/performance/graded_content/assignments/{self.assignment_id}/' def is_browser_on_page(self): - return super(CoursePerformanceAssignmentPage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ 'Graded Content' in self.browser.title class CoursePerformanceAnswerDistributionPage(CoursePage): def __init__(self, browser, course_id=None, assignment_id=None, problem_id=None, part_id=None): - super(CoursePerformanceAnswerDistributionPage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.assignment_id = assignment_id or TEST_ASSIGNMENT_ID self.problem_id = problem_id or TEST_GRADED_PROBLEM_ID self.part_id = part_id or TEST_GRADED_PROBLEM_PART_ID @@ -304,17 +304,17 @@ def __init__(self, browser, course_id=None, assignment_id=None, problem_id=None, self.assignment_id, self.problem_id, self.part_id) def is_browser_on_page(self): - return super(CoursePerformanceAnswerDistributionPage, self).is_browser_on_page() and \ + return super().is_browser_on_page() and \ self.browser.title.startswith('Performance: Problem Submissions') class CourseLearnersPage(CoursePage): def __init__(self, browser, course_id=None): - super(CourseLearnersPage, self).__init__(browser, course_id) + super().__init__(browser, course_id) self.page_url += '/learners/' def is_browser_on_page(self): - return super(CourseLearnersPage, self).is_browser_on_page() \ + return super().is_browser_on_page() \ and self.browser.title.startswith('Learners') @@ -323,8 +323,8 @@ class ErrorPage(DashboardPage): error_title = None def __init__(self, browser): - self.path = self.path or '{}/'.format(self.error_code) - super(ErrorPage, self).__init__(browser) + self.path = self.path or f'{self.error_code}/' + super().__init__(browser) def is_browser_on_page(self): element = self.q(css='.error-title') @@ -333,19 +333,19 @@ def is_browser_on_page(self): class ServerErrorPage(ErrorPage): error_code = 500 - error_title = u'An Error Occurred' + error_title = 'An Error Occurred' class NotFoundErrorPage(ErrorPage): error_code = 404 - error_title = u'Page Not Found' + error_title = 'Page Not Found' class AccessDeniedErrorPage(ErrorPage): error_code = 403 - error_title = u'Access Denied' + error_title = 'Access Denied' class ServiceUnavailableErrorPage(ErrorPage): error_code = 503 - error_title = u"We're having trouble loading this page. Please try again in a minute." + error_title = "We're having trouble loading this page. Please try again in a minute." diff --git a/acceptance_tests/test_auth.py b/acceptance_tests/test_auth.py index 5ef83c9bb..90c163fbb 100644 --- a/acceptance_tests/test_auth.py +++ b/acceptance_tests/test_auth.py @@ -1,5 +1,3 @@ - - from unittest import skipUnless from bok_choy.web_app_test import WebAppTest @@ -15,7 +13,7 @@ def setUp(self): """ Instantiate the page objects. """ - super(OAuth2FlowTests, self).setUp() + super().setUp() self.insights_login_page = LoginPage(self.browser) diff --git a/acceptance_tests/test_course_detail.py b/acceptance_tests/test_course_detail.py index 2ba980148..38a8ff930 100644 --- a/acceptance_tests/test_course_detail.py +++ b/acceptance_tests/test_course_detail.py @@ -1,5 +1,3 @@ - - from bok_choy.web_app_test import WebAppTest from acceptance_tests import ENABLE_COURSE_API @@ -12,12 +10,12 @@ # pylint: disable=abstract-method class CourseHomeTests(CoursePageTestsMixin, WebAppTest): def setUp(self): - super(CourseHomeTests, self).setUp() + super().setUp() self.page = CourseHomePage(self.browser) self.course = self.analytics_api_client.courses(self.page.course_id) def test_page(self): - super(CourseHomeTests, self).test_page() + super().test_page() self._test_table() def _test_data_update_message(self): @@ -29,7 +27,7 @@ def _view_to_href(self, view): Generates a URL path from the specified view name. """ return '/' + view.replace('_', '/') \ - .replace('courses:', 'courses/{}/'.format(self.page.course_id)) \ + .replace('courses:', f'courses/{self.page.course_id}/') \ .replace(':', '/') + '/' def _test_table(self): @@ -134,7 +132,7 @@ def _test_table(self): self.assertEqual(title.text, row['title']) expected = self._view_to_href(row['view']) actual = title.find_element_by_css_selector('a').get_attribute('href') - self.assertTrue(actual.endswith(expected), '{} should end with {}'.format(actual, expected)) + self.assertTrue(actual.endswith(expected), f'{actual} should end with {expected}') # Check the breadcrumbs breadcrumbs = element.find_element_by_css_selector('.breadcrumbs') diff --git a/acceptance_tests/test_course_engagement.py b/acceptance_tests/test_course_engagement.py index 168b7435e..ca7e1c096 100644 --- a/acceptance_tests/test_course_engagement.py +++ b/acceptance_tests/test_course_engagement.py @@ -1,5 +1,3 @@ - - import datetime from unittest import skipUnless @@ -30,7 +28,7 @@ class CourseEngagementPageTestsMixin(CoursePageTestsMixin): chart_selector = None def test_page(self): - super(CourseEngagementPageTestsMixin, self).test_page() + super().test_page() self._test_chart() self._test_table() @@ -54,12 +52,12 @@ def setUp(self): """ Instantiate the page object. """ - super(CourseEngagementContentTests, self).setUp() + super().setUp() self.page = CourseEngagementContentPage(self.browser) self.course = self.analytics_api_client.courses(self.page.course_id) def test_page(self): - super(CourseEngagementContentTests, self).test_page() + super().test_page() self._test_engagement_metrics() def _get_data_update_message(self): @@ -76,13 +74,13 @@ def _test_engagement_metrics(self): # Verify the activity values activity_types = [at.ANY, at.ATTEMPTED_PROBLEM, at.PLAYED_VIDEO] expected_tooltips = { - at.ANY: u'Learners who visited at least one page in the course content.', - at.ATTEMPTED_PROBLEM: u'Learners who submitted an answer for a standard problem. ' - u'Not all problem types are included.', - at.PLAYED_VIDEO: u'Learners who played one or more videos.' + at.ANY: 'Learners who visited at least one page in the course content.', + at.ATTEMPTED_PROBLEM: 'Learners who submitted an answer for a standard problem. ' + 'Not all problem types are included.', + at.PLAYED_VIDEO: 'Learners who played one or more videos.' } for activity_type in activity_types: - data_selector = 'data-activity-type={0}'.format(activity_type) + data_selector = f'data-activity-type={activity_type}' self.assertSummaryPointValueEquals(data_selector, self.format_number(recent_activity[activity_type])) self.assertSummaryTooltipEquals(data_selector, expected_tooltips[activity_type]) @@ -98,10 +96,10 @@ def _test_table(self): table_selector = 'div[data-role=engagement-table] table' - headings = [u'Week Ending', u'Active Learners', u'Watched a Video', u'Tried a Problem'] + headings = ['Week Ending', 'Active Learners', 'Watched a Video', 'Tried a Problem'] if ENABLE_FORUM_POSTS: - headings.append(u'Participated in Discussions') - headings.append(u'Percent of Current Learners') + headings.append('Participated in Discussions') + headings.append('Percent of Current Learners') self.assertTableColumnHeadingsEqual(table_selector, headings) @@ -134,13 +132,13 @@ def _test_table(self): class CourseEngagementVideoMixin(CourseEngagementPageTestsMixin): help_path = 'engagement/Engagement_Video.html' chart_selector = '#chart-view' - expected_table_heading = u'Video Views' + expected_table_heading = 'Video Views' expected_heading = None expected_tooltip = None expected_table_columns = None def test_page(self): - super(CourseEngagementVideoMixin, self).test_page() + super().test_page() self._test_heading_question() def _get_data_update_message(self): @@ -160,7 +158,7 @@ def _test_table(self): self.assertTableColumnHeadingsEqual('div[data-role="data-table"]', self.expected_table_columns) def _test_chart(self): - super(CourseEngagementVideoMixin, self)._test_chart() + super()._test_chart() container_selector = '.analytics-chart-container' element = self.page.q(css=container_selector + ' i') self.assertEqual(element[0].get_attribute('data-original-title'), self.expected_tooltip) @@ -172,63 +170,63 @@ def _test_heading_question(self): @skipUnless(ENABLE_COURSE_API, 'Course API must be enabled to test the video pages.') class CourseEngagementVideoContentTests(CourseEngagementVideoMixin, WebAppTest): - expected_heading = u'How did learners interact with course videos?' - expected_tooltip = u'Each bar shows the average number of complete and incomplete views for videos in that ' \ - u'section. Click on bars with low totals or a high incomplete rate to drill down and ' \ - u'understand why.' - expected_table_columns = [u'Order', u'Section Name', u'Videos', u'Average Complete Views', - u'Average Incomplete Views', u'Completion Percentage'] + expected_heading = 'How did learners interact with course videos?' + expected_tooltip = 'Each bar shows the average number of complete and incomplete views for videos in that ' \ + 'section. Click on bars with low totals or a high incomplete rate to drill down and ' \ + 'understand why.' + expected_table_columns = ['Order', 'Section Name', 'Videos', 'Average Complete Views', + 'Average Incomplete Views', 'Completion Percentage'] def setUp(self): - super(CourseEngagementVideoContentTests, self).setUp() + super().setUp() self.page = CourseEngagementVideosContentPage(self.browser) self.course = self.analytics_api_client.courses(self.page.course_id) @skipUnless(ENABLE_COURSE_API, 'Course API must be enabled to test the video pages.') class CourseEngagementVideoSectionTests(CourseEngagementVideoMixin, WebAppTest): - expected_heading = u'How did learners interact with videos in this section?' - expected_tooltip = u'Each bar shows the average number of complete and incomplete views for videos in that ' \ - u'subsection. Click on bars with low totals or a high incomplete rate to drill down and ' \ - u'understand why.' - expected_table_columns = [u'Order', u'Subsection Name', u'Videos', u'Average Complete Views', - u'Average Incomplete Views', u'Completion Percentage'] + expected_heading = 'How did learners interact with videos in this section?' + expected_tooltip = 'Each bar shows the average number of complete and incomplete views for videos in that ' \ + 'subsection. Click on bars with low totals or a high incomplete rate to drill down and ' \ + 'understand why.' + expected_table_columns = ['Order', 'Subsection Name', 'Videos', 'Average Complete Views', + 'Average Incomplete Views', 'Completion Percentage'] def setUp(self): - super(CourseEngagementVideoSectionTests, self).setUp() + super().setUp() self.page = CourseEngagementVideoSectionPage(self.browser) self.course = self.analytics_api_client.courses(self.page.course_id) @skipUnless(ENABLE_COURSE_API, 'Course API must be enabled to test the video pages.') class CourseEngagementVideoSubsectionTests(CourseEngagementVideoMixin, WebAppTest): - expected_heading = u'How did learners interact with videos in this subsection?' - expected_tooltip = u'Each bar shows the counts of complete and incomplete views for that video. ' \ - u'Click to understand where learners drop off and which parts they replay.' - expected_table_columns = [u'Order', u'Video Name', u'Complete Views', u'Incomplete Views', - u'Completion Percentage'] + expected_heading = 'How did learners interact with videos in this subsection?' + expected_tooltip = 'Each bar shows the counts of complete and incomplete views for that video. ' \ + 'Click to understand where learners drop off and which parts they replay.' + expected_table_columns = ['Order', 'Video Name', 'Complete Views', 'Incomplete Views', + 'Completion Percentage'] def setUp(self): - super(CourseEngagementVideoSubsectionTests, self).setUp() + super().setUp() self.page = CourseEngagementVideoSubsectionPage(self.browser) self.course = self.analytics_api_client.courses(self.page.course_id) @skipUnless(ENABLE_COURSE_API, 'Course API must be enabled to test the video pages.') class CourseEngagementVideoTimelineTests(CourseEngagementVideoMixin, WebAppTest): - expected_heading = u'What were the viewing patterns for this video?' - expected_tooltip = u'The number of learners who watched each segment of the video, and the ' \ - u'number of replays for each segment.' - expected_table_columns = [u'Time', u'Unique Viewers', u'Replays'] - expected_table_heading = u'Total Video Views' + expected_heading = 'What were the viewing patterns for this video?' + expected_tooltip = 'The number of learners who watched each segment of the video, and the ' \ + 'number of replays for each segment.' + expected_table_columns = ['Time', 'Unique Viewers', 'Replays'] + expected_table_heading = 'Total Video Views' def setUp(self): - super(CourseEngagementVideoTimelineTests, self).setUp() + super().setUp() self.page = CourseEngagementVideoTimelinePage(self.browser) self.course = self.analytics_api_client.courses(self.page.course_id) def test_page(self): - super(CourseEngagementVideoTimelineTests, self).test_page() + super().test_page() self._test_metrics() if ENABLE_VIDEO_PREVIEW: self._test_video_preview() @@ -272,6 +270,6 @@ def _test_metrics(self): ] for expected in expected_metrics: - data_selector = 'data-type={0}'.format(expected['data_type']) + data_selector = 'data-type={}'.format(expected['data_type']) self.assertSummaryPointValueEquals(data_selector, expected['metric_value']) self.assertSummaryTooltipEquals(data_selector, expected['tooltip']) diff --git a/acceptance_tests/test_course_enrollment.py b/acceptance_tests/test_course_enrollment.py index 091ca02f5..572cc480d 100644 --- a/acceptance_tests/test_course_enrollment.py +++ b/acceptance_tests/test_course_enrollment.py @@ -1,5 +1,3 @@ - - import datetime from collections import OrderedDict @@ -23,7 +21,7 @@ class CourseEnrollmentActivityTests(CoursePageTestsMixin, WebAppTest): help_path = 'enrollment/Enrollment_Activity.html' def setUp(self): - super(CourseEnrollmentActivityTests, self).setUp() + super().setUp() self.page = CourseEnrollmentActivityPage(self.browser) self.course = self.analytics_api_client.courses(self.page.course_id) @@ -36,7 +34,7 @@ def get_enrollment_data(self): return self.course.enrollment('mode', start_date=None, end_date=end_date_string) def test_page(self): - super(CourseEnrollmentActivityTests, self).test_page() + super().test_page() self._test_enrollment_metrics_and_graph() self._test_enrollment_trend_table() @@ -68,13 +66,13 @@ def _test_enrollment_metrics_and_graph(self): enrollment = enrollment_data[-1]['count'] # Verify the current enrollment metric tile. - tooltip = u'Learners currently enrolled in the course.' + tooltip = 'Learners currently enrolled in the course.' self.assertMetricTileValid('current_enrollment', enrollment, tooltip) # Verify the total enrollment change metric tile. i = 7 enrollment = enrollment - enrollment_data[-(i + 1)]['count'] - tooltip = u'Net difference in current enrollment in the last week.' + tooltip = 'Net difference in current enrollment in the last week.' self.assertMetricTileValid('enrollment_change_last_%s_days' % i, enrollment, tooltip) valid_modes = self._get_valid_enrollment_modes(enrollment_data) @@ -82,7 +80,7 @@ def _test_enrollment_metrics_and_graph(self): if enrollment_modes.VERIFIED in valid_modes: # Verify the verified enrollment metric tile. verified_enrollment = enrollment_data[-1][enrollment_modes.VERIFIED] - tooltip = u'Number of currently enrolled learners pursuing a verified certificate of achievement.' + tooltip = 'Number of currently enrolled learners pursuing a verified certificate of achievement.' self.assertMetricTileValid('verified_enrollment', verified_enrollment, tooltip) # Verify *something* rendered where the graph should be. We cannot easily verify what rendered @@ -133,14 +131,14 @@ class CourseEnrollmentGeographyTests(CoursePageTestsMixin, WebAppTest): help_path = 'enrollment/Enrollment_Geography.html' def setUp(self): - super(CourseEnrollmentGeographyTests, self).setUp() + super().setUp() self.page = CourseEnrollmentGeographyPage(self.browser) self.course = self.analytics_api_client.courses(self.page.course_id) self.enrollment_data = sorted(self.course.enrollment(demographics.LOCATION), key=lambda item: item['count'], reverse=True) def test_page(self): - super(CourseEnrollmentGeographyTests, self).test_page() + super().test_page() self._test_enrollment_country_map() self._test_enrollment_country_table() self._test_metrics() @@ -178,7 +176,7 @@ def _test_enrollment_country_table(self): self.assertTable(table_section_selector, ['Country or Region', 'Percent', 'Current Enrollment'], 'a[data-role=enrollment-location-csv]') - rows = self.page.browser.find_elements_by_css_selector('{} tbody tr'.format(table_section_selector)) + rows = self.page.browser.find_elements_by_css_selector(f'{table_section_selector} tbody tr') sum_count = float(sum([datum['count'] for datum in self.enrollment_data])) for i, row in enumerate(rows): @@ -189,10 +187,10 @@ def _test_enrollment_country_table(self): country_name = enrollment['country']['name'] if country_name == UNKNOWN_COUNTRY_CODE: - country_name = u'Unknown Country' + country_name = 'Unknown Country' # FIXME: because django-countries is different between dashboard and api elif country_name == 'United States': - country_name = u'United States of America' + country_name = 'United States of America' expected = [country_name, expected_percent_display, self.format_number(enrollment['count'])] actual = [columns[0].text, columns[1].text, columns[2].text] @@ -209,5 +207,5 @@ def _test_metrics(self): country = enrollment_data[i]['country']['name'] # FIXME: because django-countries is different between dashboard and api if country == 'United States': - country = u'United Sta...' - self.assertSummaryPointValueEquals('data-stat-type=top-country-{0}'.format((i + 1)), country) + country = 'United Sta...' + self.assertSummaryPointValueEquals('data-stat-type=top-country-{}'.format(i + 1), country) diff --git a/acceptance_tests/test_course_enrollment_demographics.py b/acceptance_tests/test_course_enrollment_demographics.py index 3669b46b7..21a69870a 100644 --- a/acceptance_tests/test_course_enrollment_demographics.py +++ b/acceptance_tests/test_course_enrollment_demographics.py @@ -1,5 +1,3 @@ - - import datetime from analyticsclient.constants import demographics @@ -24,7 +22,7 @@ class CourseEnrollmentDemographicsAgeTests(CourseDemographicsPageTestsMixin, Web table_columns = ['Age', 'Number of Learners', 'Percent of Total'] def setUp(self): - super(CourseEnrollmentDemographicsAgeTests, self).setUp() + super().setUp() self.page = CourseEnrollmentDemographicsAgePage(self.browser) self.course = self.analytics_api_client.courses(self.page.course_id) @@ -35,7 +33,7 @@ def setUp(self): self.demographic_data_without_none = [datum for datum in self.demographic_data if datum['birth_year']] def test_page(self): - super(CourseEnrollmentDemographicsAgeTests, self).test_page() + super().test_page() self._test_metrics() def _calculate_median_age(self, current_year): @@ -121,7 +119,7 @@ class CourseEnrollmentDemographicsGenderTests(CourseDemographicsPageTestsMixin, table_columns = ['Date', 'Current Enrollment', 'Female', 'Male', 'Other', 'Not Reported'] def setUp(self): - super(CourseEnrollmentDemographicsGenderTests, self).setUp() + super().setUp() self.page = CourseEnrollmentDemographicsGenderPage(self.browser) self.course = self.analytics_api_client.courses(self.page.course_id) @@ -171,14 +169,14 @@ class CourseEnrollmentDemographicsEducationTests(CourseDemographicsPageTestsMixi table_columns = ['Educational Background', 'Number of Learners'] def setUp(self): - super(CourseEnrollmentDemographicsEducationTests, self).setUp() + super().setUp() self.page = CourseEnrollmentDemographicsEducationPage(self.browser) self.course = self.analytics_api_client.courses(self.page.course_id) self.demographic_data = sorted(self.course.enrollment(self.demographic_type), key=lambda item: item['count'], reverse=True) def test_page(self): - super(CourseEnrollmentDemographicsEducationTests, self).test_page() + super().test_page() self._test_metrics() def _test_metrics(self): diff --git a/acceptance_tests/test_course_index.py b/acceptance_tests/test_course_index.py index 1aa6bbde7..552f3f0b1 100644 --- a/acceptance_tests/test_course_index.py +++ b/acceptance_tests/test_course_index.py @@ -1,5 +1,3 @@ - - import requests from bok_choy.promise import EmptyPromise from bok_choy.web_app_test import WebAppTest @@ -23,13 +21,13 @@ class CourseIndexTests(AnalyticsApiClientMixin, AnalyticsDashboardWebAppTestMixi test_skip_link_url = False def setUp(self): - super(CourseIndexTests, self).setUp() + super().setUp() self.page = CourseIndexPage(self.browser) self.maxDiff = None self.course_summaries = self.analytics_api_client.course_summaries() def test_page(self): - super(CourseIndexTests, self).test_page() + super().test_page() self._test_course_list() self._test_search() self._test_clear_input() @@ -70,7 +68,7 @@ def _test_course_list(self): course_links = self.page.q(css='.course-list .course-name-cell a').attrs('href') for link, course_id in zip(course_links, course_ids): - self.assertTrue(link.endswith(u'/courses/{}'.format(course_id.text))) + self.assertTrue(link.endswith(f'/courses/{course_id.text}')) def _test_search(self): """ @@ -297,7 +295,7 @@ def _test_download_csv(self): # Steal the cookies from the logged-in firefox browser and use them in a python-initiated request kwargs = dict() - session_id = [{i['name']: i['value']} for i in self.browser.get_cookies() if i['name'] == u'sessionid'] + session_id = [{i['name']: i['value']} for i in self.browser.get_cookies() if i['name'] == 'sessionid'] if session_id: kwargs.update({ 'cookies': session_id[0] @@ -320,14 +318,14 @@ def _test_summary_metrics(self): count_change_i_days = course_summaries[0]['count_change_%s_days' % i] verified_enrollment = course_summaries[0]['enrollment_modes']['verified']['count'] - tooltip = u'Current enrollments across all of your courses.' + tooltip = 'Current enrollments across all of your courses.' self.assertMetricTileValid('current_enrollment', current_enrollment, tooltip) - tooltip = u'Total enrollments across all of your courses.' + tooltip = 'Total enrollments across all of your courses.' self.assertMetricTileValid('total_enrollment', total_enrollment, tooltip) - tooltip = u'Total change in enrollment last week across all of your courses.' + tooltip = 'Total change in enrollment last week across all of your courses.' self.assertMetricTileValid('enrollment_change_%s_days' % i, count_change_i_days, tooltip) - tooltip = u'Verified enrollments across all of your courses.' + tooltip = 'Verified enrollments across all of your courses.' self.assertMetricTileValid('verified_enrollment', verified_enrollment, tooltip) diff --git a/acceptance_tests/test_course_learners.py b/acceptance_tests/test_course_learners.py index f577cf3c3..61385ccd1 100644 --- a/acceptance_tests/test_course_learners.py +++ b/acceptance_tests/test_course_learners.py @@ -1,5 +1,3 @@ - - from unittest import skipUnless from bok_choy.web_app_test import WebAppTest @@ -15,7 +13,7 @@ class CourseLearnersTests(CoursePageTestsMixin, WebAppTest): help_path = 'learners/Learner_Activity.html' def setUp(self): - super(CourseLearnersTests, self).setUp() + super().setUp() self.page = CourseLearnersPage(self.browser) def _test_data_update_message(self): diff --git a/acceptance_tests/test_course_performance.py b/acceptance_tests/test_course_performance.py index b422bc987..bf7632789 100644 --- a/acceptance_tests/test_course_performance.py +++ b/acceptance_tests/test_course_performance.py @@ -1,5 +1,3 @@ - - import datetime from unittest import skipUnless @@ -28,7 +26,7 @@ class CoursePerformancePageTestsMixin(CoursePageTestsMixin): table_selector = 'div[data-role="data-table"]' def test_page(self): - super(CoursePerformancePageTestsMixin, self).test_page() + super().test_page() self._test_chart() self._test_table() @@ -83,7 +81,7 @@ def _get_sections(self): def _find_child_block(self, blocks, child_id): for block in blocks: - if block[u'id'] == child_id: + if block['id'] == child_id: return block return None @@ -145,7 +143,7 @@ def get_expected_row(self, index, block): class CoursePerformanceAveragedTableMixin(CoursePerformancePageTestsMixin): def get_expected_row(self, index, block): - row = super(CoursePerformanceAveragedTableMixin, self).get_expected_row(index, block) + row = super().get_expected_row(index, block) num_modules_denominator = float(block.get('num_modules', 1)) row += [ str(self._format_number_or_hyphen(block.get('num_modules', 0))), @@ -173,7 +171,7 @@ def get_expected_row(self, index, block): class CoursePerformanceModuleTableMixin(CoursePerformancePageTestsMixin): def get_expected_row(self, index, block): - row = super(CoursePerformanceModuleTableMixin, self).get_expected_row(index, block) + row = super().get_expected_row(index, block) row += [ str(self._format_number_or_hyphen(block['correct_submissions'])), str(self._format_number_or_hyphen( @@ -205,12 +203,12 @@ def _get_grading_policy(self): for item in policy: weight = item['weight'] - item['weight_as_percentage'] = u'{:.0f}%'.format(weight * 100) + item['weight_as_percentage'] = '{:.0f}%'.format(weight * 100) return policy def setUp(self): - super(CoursePerformanceGradedContentTests, self).setUp() + super().setUp() self.page = CoursePerformanceGradedContentPage(self.browser) self.grading_policy = self._get_grading_policy() @@ -226,7 +224,7 @@ def _test_chart(self): # Verify the URL to view the assignments is correct. actual = element.find_element_by_css_selector('a').get_attribute('href') - expected = u'{}{}/'.format(self.page.page_url, assignment_type) + expected = f'{self.page.page_url}{assignment_type}/' self.assertEqual(actual, expected) # Verify the displayed weight @@ -254,7 +252,7 @@ class CoursePerformanceGradedContentByTypeTests(CoursePerformanceAveragedTableMi """ def setUp(self): - super(CoursePerformanceGradedContentByTypeTests, self).setUp() + super().setUp() self.page = CoursePerformanceGradedContentByTypePage(self.browser) self.assignment_type = self.page.assignment_type self.course = self.analytics_api_client.courses(self.page.course_id) @@ -262,9 +260,9 @@ def setUp(self): def _test_table(self): self.assertTableColumnHeadingsEqual(self.table_selector, - [u'Order', u'Assignment Name', u'Problems', - u'Average Correct', u'Average Incorrect', - u'Average Submissions Per Problem', u'Percentage Correct']) + ['Order', 'Assignment Name', 'Problems', + 'Average Correct', 'Average Incorrect', + 'Average Submissions Per Problem', 'Percentage Correct']) self.assertBlockRows(self.assignments) @@ -277,13 +275,13 @@ class CoursePerformanceAssignmentTests(CoursePerformanceModuleTableMixin, WebApp def _get_assignment(self): assignments = self._get_assignments() for assignment in assignments: - if assignment[u'id'] == self.assignment_id: + if assignment['id'] == self.assignment_id: return assignment raise AttributeError('Assignment not found!') def setUp(self): - super(CoursePerformanceAssignmentTests, self).setUp() + super().setUp() self.page = CoursePerformanceAssignmentPage(self.browser) self.assignment_id = self.page.assignment_id self.course = self.analytics_api_client.courses(self.page.course_id) @@ -292,7 +290,7 @@ def setUp(self): def _test_table(self): # Check the column headings self.assertTableColumnHeadingsEqual(self.table_selector, [ - u'Order', u'Problem Name', u'Correct', u'Incorrect', u'Total', u'Percentage Correct']) + 'Order', 'Problem Name', 'Correct', 'Incorrect', 'Total', 'Percentage Correct']) self.assertBlockRows(self.assignment['children']) @@ -303,7 +301,7 @@ class CoursePerformanceAnswerDistributionMixin(CoursePerformancePageTestsMixin): answer_distribution = None def setUp(self): - super(CoursePerformanceAnswerDistributionMixin, self).setUp() + super().setUp() self.page = self.get_page() self.course = self.analytics_api_client.courses(self.page.course_id) self.module = self.analytics_api_client.modules(self.page.course_id, self.page.problem_id) @@ -315,13 +313,13 @@ def get_page(self): raise NotImplementedError def test_page(self): - super(CoursePerformanceAnswerDistributionMixin, self).test_page() + super().test_page() self._test_heading_question() self._test_problem_description() def _test_heading_question(self): element = self.page.q(css='.section-heading') - self.assertEqual(element.text[0], u'How did learners answer this problem?') + self.assertEqual(element.text[0], 'How did learners answer this problem?') def _test_problem_description(self): section_selector = '.module-description' @@ -353,7 +351,7 @@ def _test_table(self): self.assertTable(table_section_selector, ['Answer', 'Correct', 'Submission Count'], 'a[data-role=performance-csv]') - rows = self.page.browser.find_elements_by_css_selector('{} tbody tr'.format(table_section_selector)) + rows = self.page.browser.find_elements_by_css_selector(f'{table_section_selector} tbody tr') value_field = 'answer_value' @@ -365,10 +363,10 @@ def _test_table(self): for col in columns: actual.append(col.text) - expected = [answer[value_field] if answer[value_field] else u'(empty)'] - correct = u'-' + expected = [answer[value_field] if answer[value_field] else '(empty)'] + correct = '-' if answer['correct']: - correct = u'Correct' + correct = 'Correct' expected.append(correct) expected.append(self.format_number(answer['last_response_count'])) @@ -394,16 +392,16 @@ def get_page(self): class CoursePerformanceUngradedContentTests(CoursePerformanceAveragedTableMixin, WebAppTest): def setUp(self): - super(CoursePerformanceUngradedContentTests, self).setUp() + super().setUp() self.page = CoursePerformanceUngradedContentPage(self.browser) self.course = self.analytics_api_client.courses(self.page.course_id) self.sections = self._get_sections() def _test_table(self): self.assertTableColumnHeadingsEqual(self.table_selector, - [u'Order', u'Section Name', u'Problems', u'Average Correct', - u'Average Incorrect', u'Average Submissions Per Problem', - u'Percentage Correct']) + ['Order', 'Section Name', 'Problems', 'Average Correct', + 'Average Incorrect', 'Average Submissions Per Problem', + 'Percentage Correct']) self.assertBlockRows(self.sections) @@ -411,16 +409,16 @@ def _test_table(self): class CoursePerformanceUngradedSectionTests(CoursePerformanceAveragedTableMixin, WebAppTest): def setUp(self): - super(CoursePerformanceUngradedSectionTests, self).setUp() + super().setUp() self.page = CoursePerformanceUngradedSectionPage(self.browser) self.course = self.analytics_api_client.courses(self.page.course_id) self.section = self._find_child_block(self._get_sections(), self.page.section_id) def _test_table(self): self.assertTableColumnHeadingsEqual(self.table_selector, - [u'Order', u'Subsection Name', u'Problems', u'Average Correct', - u'Average Incorrect', u'Average Submissions Per Problem', - u'Percentage Correct']) + ['Order', 'Subsection Name', 'Problems', 'Average Correct', + 'Average Incorrect', 'Average Submissions Per Problem', + 'Percentage Correct']) self.assertBlockRows(self.section['children']) @@ -428,13 +426,13 @@ def _test_table(self): class CoursePerformanceUngradedSubsectionTests(CoursePerformanceModuleTableMixin, WebAppTest): def setUp(self): - super(CoursePerformanceUngradedSubsectionTests, self).setUp() + super().setUp() self.page = CoursePerformanceUngradedSubsectionPage(self.browser) self.course = self.analytics_api_client.courses(self.page.course_id) subsections = self._find_child_block(self._get_sections(), self.page.section_id)['children'] self.problems = self._find_child_block(subsections, self.page.subsection_id)['children'] def _test_table(self): - self.assertTableColumnHeadingsEqual(self.table_selector, [u'Order', u'Problem Name', u'Correct', - u'Incorrect', u'Total', u'Percentage Correct']) + self.assertTableColumnHeadingsEqual(self.table_selector, ['Order', 'Problem Name', 'Correct', + 'Incorrect', 'Total', 'Percentage Correct']) self.assertBlockRows(self.problems) diff --git a/acceptance_tests/test_error_pages.py b/acceptance_tests/test_error_pages.py index adb602814..c61aee0ca 100644 --- a/acceptance_tests/test_error_pages.py +++ b/acceptance_tests/test_error_pages.py @@ -1,5 +1,3 @@ - - from unittest import skipUnless from bok_choy.web_app_test import WebAppTest @@ -30,11 +28,11 @@ def test_valid_pages(self): page.visit() # Check the title - expected = u'{0} | {1} {2}'.format(page.error_title, PLATFORM_NAME, APPLICATION_NAME) + expected = f'{page.error_title} | {PLATFORM_NAME} {APPLICATION_NAME}' self.assertEqual(expected, self.browser.title) # Check the support link element = page.q(css='a[data-role=support-email]') self.assertTrue(element.present) href = element.attrs('href')[0] - self.assertEqual(href, 'mailto:{}'.format(SUPPORT_EMAIL)) + self.assertEqual(href, f'mailto:{SUPPORT_EMAIL}') diff --git a/acceptance_tests/test_landing.py b/acceptance_tests/test_landing.py index 3990a549a..015e71d86 100644 --- a/acceptance_tests/test_landing.py +++ b/acceptance_tests/test_landing.py @@ -1,5 +1,3 @@ - - from bok_choy.web_app_test import WebAppTest from acceptance_tests import ( @@ -21,11 +19,11 @@ class LandingTests(PageTestMixin, LoginMixin, LogoutMixin, FooterLegalMixin, WebAppTest): def setUp(self): - super(LandingTests, self).setUp() + super().setUp() self.page = LandingPage(self.browser) def test_page(self): - super(LandingTests, self).test_page() + super().test_page() # landing page will not be viewable by logged in users self.assertFalse(self.page.is_browser_on_page()) @@ -77,7 +75,7 @@ def _test_audience_messages(self): self.assertTrue(action_link_elements.present) self.assertEqual(len(action_link_elements), num_actions) - expected_links = [OPEN_SOURCE_URL, RESEARCH_URL, 'mailto:{}'.format(SUPPORT_EMAIL)] + expected_links = [OPEN_SOURCE_URL, RESEARCH_URL, f'mailto:{SUPPORT_EMAIL}'] for i in range(num_actions): self.assertEqual(header_elements[i].text, expected_headers[i]) self.assertEqual(action_link_elements.attrs('href')[i], expected_links[i]) diff --git a/acceptance_tests/test_status.py b/acceptance_tests/test_status.py index 79a2bda59..3b9a631d6 100644 --- a/acceptance_tests/test_status.py +++ b/acceptance_tests/test_status.py @@ -1,5 +1,3 @@ - - from unittest import TestCase import requests @@ -8,10 +6,10 @@ class StatusTests(TestCase): - POSITIVE_STATUS = u'OK' + POSITIVE_STATUS = 'OK' def test_health(self): - response = requests.get('{}/health'.format(DASHBOARD_SERVER_URL)) + response = requests.get(f'{DASHBOARD_SERVER_URL}/health') self.assertEqual(response.status_code, 200) @@ -24,6 +22,6 @@ def test_health(self): self.assertDictEqual(response.json(), expected_status) def test_status(self): - response = requests.get('{}/status'.format(DASHBOARD_SERVER_URL)) + response = requests.get(f'{DASHBOARD_SERVER_URL}/status') self.assertEqual(response.status_code, 200) diff --git a/analytics_dashboard/help/middleware.py b/analytics_dashboard/help/middleware.py index ea98e84c5..427a727ef 100644 --- a/analytics_dashboard/help/middleware.py +++ b/analytics_dashboard/help/middleware.py @@ -1,5 +1,3 @@ - - from django.utils.deprecation import MiddlewareMixin from rest_framework.response import Response diff --git a/analytics_dashboard/help/tests.py b/analytics_dashboard/help/tests.py index 4aa99d85d..b0b7035cd 100644 --- a/analytics_dashboard/help/tests.py +++ b/analytics_dashboard/help/tests.py @@ -1,5 +1,3 @@ - - from django import http from django.template.response import TemplateResponse from django.test import TestCase @@ -12,7 +10,7 @@ def build_doc_url(path): - return '{0}/{1}'.format(DOC_BASE_URL, path) + return f'{DOC_BASE_URL}/{path}' DOC_INDEX = build_doc_url('index.html') diff --git a/analytics_dashboard/help/utils.py b/analytics_dashboard/help/utils.py index 1b9c9c407..bc8cbb432 100644 --- a/analytics_dashboard/help/utils.py +++ b/analytics_dashboard/help/utils.py @@ -1,5 +1,3 @@ - - import logging import configparser diff --git a/analytics_dashboard/help/views.py b/analytics_dashboard/help/views.py index cf4c6c269..d6e23adcd 100644 --- a/analytics_dashboard/help/views.py +++ b/analytics_dashboard/help/views.py @@ -1,5 +1,3 @@ - - from analytics_dashboard.help import HELP_CONTEXT_TOKEN_NAME @@ -11,6 +9,6 @@ class ContextSensitiveHelpMixin: help_token = None def get_context_data(self, **kwargs): - context = super(ContextSensitiveHelpMixin, self).get_context_data(**kwargs) + context = super().get_context_data(**kwargs) context[HELP_CONTEXT_TOKEN_NAME] = self.help_token return context diff --git a/analytics_dashboard/learner_analytics_api/urls.py b/analytics_dashboard/learner_analytics_api/urls.py index 57a87b963..7eea709a1 100644 --- a/analytics_dashboard/learner_analytics_api/urls.py +++ b/analytics_dashboard/learner_analytics_api/urls.py @@ -1,5 +1,3 @@ - - from django.conf.urls import include, url app_name = 'learner_analytics_api' diff --git a/analytics_dashboard/learner_analytics_api/v0/clients.py b/analytics_dashboard/learner_analytics_api/v0/clients.py index 33b626d00..6faf21e8a 100644 --- a/analytics_dashboard/learner_analytics_api/v0/clients.py +++ b/analytics_dashboard/learner_analytics_api/v0/clients.py @@ -1,5 +1,3 @@ - - import requests from django.conf import settings from slumber import API, Resource, exceptions, serialize @@ -11,7 +9,7 @@ def __init__(self, token): self.token = token def __call__(self, r): - r.headers['Authorization'] = 'Token {}'.format(self.token) + r.headers['Authorization'] = f'Token {self.token}' return r @@ -40,7 +38,7 @@ def _request(self, *args, **kwargs): # Doesn't hide 400s and 500s, however timeouts will still # raise a requests.exceptions.ConnectTimeout. try: - response = super(LearnerApiResource, self)._request(*args, **kwargs) + response = super()._request(*args, **kwargs) except exceptions.SlumberHttpBaseException as e: response = e.response return response @@ -65,7 +63,7 @@ def __init__(self, timeout=5, serializer_type='json'): TextSerializer(), ] ) - super(LearnerAPIClient, self).__init__( + super().__init__( settings.DATA_API_URL, session=session, auth=TokenAuth(settings.DATA_API_AUTH_TOKEN), diff --git a/analytics_dashboard/learner_analytics_api/v0/permissions.py b/analytics_dashboard/learner_analytics_api/v0/permissions.py index 82e15b3e9..2ead0767d 100644 --- a/analytics_dashboard/learner_analytics_api/v0/permissions.py +++ b/analytics_dashboard/learner_analytics_api/v0/permissions.py @@ -1,5 +1,3 @@ - - import logging from rest_framework.permissions import BasePermission diff --git a/analytics_dashboard/learner_analytics_api/v0/tests/test_views.py b/analytics_dashboard/learner_analytics_api/v0/tests/test_views.py index 77cfd3b6d..3d3691bb0 100644 --- a/analytics_dashboard/learner_analytics_api/v0/tests/test_views.py +++ b/analytics_dashboard/learner_analytics_api/v0/tests/test_views.py @@ -1,5 +1,3 @@ - - import json import unittest.mock as mock diff --git a/analytics_dashboard/learner_analytics_api/v0/urls.py b/analytics_dashboard/learner_analytics_api/v0/urls.py index 2b0c3d1c3..890e1af72 100644 --- a/analytics_dashboard/learner_analytics_api/v0/urls.py +++ b/analytics_dashboard/learner_analytics_api/v0/urls.py @@ -1,5 +1,3 @@ - - from django.conf import settings from django.conf.urls import url @@ -9,13 +7,13 @@ app_name = 'v0' urlpatterns = [ - url(r'^learners/{}/$'.format(USERNAME_PATTERN), views.LearnerDetailView.as_view(), name='LearnerDetail'), + url(fr'^learners/{USERNAME_PATTERN}/$', views.LearnerDetailView.as_view(), name='LearnerDetail'), url(r'^learners/$', views.LearnerListView.as_view(), name='LearnerList'), url(r'^learners.csv$', views.LearnerListCSV.as_view(), name='LearnerListCSV'), - url(r'^engagement_timelines/{}/$'.format(USERNAME_PATTERN), + url(fr'^engagement_timelines/{USERNAME_PATTERN}/$', views.EngagementTimelinesView.as_view(), name='EngagementTimeline'), - url(r'^course_learner_metadata/{}/$'.format(settings.COURSE_ID_PATTERN), + url(fr'^course_learner_metadata/{settings.COURSE_ID_PATTERN}/$', views.CourseLearnerMetadataView.as_view(), name='CourseMetadata'), ] diff --git a/analytics_dashboard/learner_analytics_api/v0/views.py b/analytics_dashboard/learner_analytics_api/v0/views.py index e1b08cdac..d1a3ee9e2 100644 --- a/analytics_dashboard/learner_analytics_api/v0/views.py +++ b/analytics_dashboard/learner_analytics_api/v0/views.py @@ -1,5 +1,3 @@ - - from requests.exceptions import ConnectTimeout from rest_framework.exceptions import PermissionDenied from rest_framework.generics import RetrieveAPIView @@ -23,7 +21,7 @@ class BaseLearnerApiView(RetrieveAPIView): include_headers = False def __init__(self, *args, **kwargs): - super(BaseLearnerApiView, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.client = LearnerAPIClient(serializer_type=self.serializer_type) def get_queryset(self): @@ -74,7 +72,7 @@ def handle_exception(self, exc): data={'developer_message': 'Learner Analytics API timed out.', 'error_code': 'analytics_api_timeout'}, status=504 ) - return super(BaseLearnerApiView, self).handle_exception(exc) + return super().handle_exception(exc) class DownloadLearnerApiViewMixin: @@ -94,7 +92,7 @@ def get_api_response(self, request, **kwargs): """ request.META['Accept'] = self.content_type request.accepted_renderer = TextRenderer() - return super(DownloadLearnerApiViewMixin, self).get_api_response(request, **kwargs) + return super().get_api_response(request, **kwargs) class NotFoundLearnerApiViewMixin: @@ -115,7 +113,7 @@ def handle_exception(self, exc): data={'developer_message': self.not_found_developer_message, 'error_code': self.not_found_error_code}, status=404 ) - return super(NotFoundLearnerApiViewMixin, self).handle_exception(exc) + return super().handle_exception(exc) class LearnerDetailView(NotFoundLearnerApiViewMixin, BaseLearnerApiView): @@ -127,7 +125,7 @@ class LearnerDetailView(NotFoundLearnerApiViewMixin, BaseLearnerApiView): @property def not_found_developer_message(self): message = 'Learner {} not found'.format(self.kwargs.get('username', '')) - message += 'for course {}.'.format(self.course_id) if self.course_id else '.' + message += f'for course {self.course_id}.' if self.course_id else '.' return message def get_api_response(self, request, username, **kwargs): @@ -159,7 +157,7 @@ class EngagementTimelinesView(NotFoundLearnerApiViewMixin, BaseLearnerApiView): @property def not_found_developer_message(self): message = 'Learner {} engagement timeline not found'.format(self.kwargs.get('username', '')) - message += 'for course {}.'.format(self.course_id) if self.course_id else '.' + message += f'for course {self.course_id}.' if self.course_id else '.' return message def get_api_response(self, request, username, **kwargs): diff --git a/analytics_dashboard/settings/base.py b/analytics_dashboard/settings/base.py index dd72db99b..3853e224a 100644 --- a/analytics_dashboard/settings/base.py +++ b/analytics_dashboard/settings/base.py @@ -1,5 +1,3 @@ - - import os from os.path import abspath, basename, dirname, join, normpath from sys import path @@ -311,7 +309,7 @@ ########## DOCUMENTATION LINKS -- These values should be overridden for production deployments. DOCUMENTATION_LOAD_ERROR_URL = 'http://127.0.0.1/en/latest/Reference.html#error-conditions' # evaluated again at the end of production setting after DOCUMENTATION_LOAD_ERROR_URL has been set -DOCUMENTATION_LOAD_ERROR_MESSAGE = 'Read more.'.format(error_documentation_link=DOCUMENTATION_LOAD_ERROR_URL) +DOCUMENTATION_LOAD_ERROR_MESSAGE = f'Read more.' ########## END DOCUMENTATION LINKS @@ -386,7 +384,7 @@ # The application and platform display names to be used in templates, emails, etc. PLATFORM_NAME = 'edx' APPLICATION_NAME = 'Insights' -FULL_APPLICATION_NAME = '{0} {1}'.format(PLATFORM_NAME, APPLICATION_NAME) +FULL_APPLICATION_NAME = f'{PLATFORM_NAME} {APPLICATION_NAME}' ########## DOCS/HELP CONFIGURATION diff --git a/analytics_dashboard/settings/dev.py b/analytics_dashboard/settings/dev.py index c05b8acc3..a30a0d575 100644 --- a/analytics_dashboard/settings/dev.py +++ b/analytics_dashboard/settings/dev.py @@ -50,7 +50,7 @@ ########## BRANDING PLATFORM_NAME = 'Open edX' APPLICATION_NAME = 'Insights' -FULL_APPLICATION_NAME = '{0} {1}'.format(PLATFORM_NAME, APPLICATION_NAME) +FULL_APPLICATION_NAME = f'{PLATFORM_NAME} {APPLICATION_NAME}' ########## END BRANDING diff --git a/analytics_dashboard/settings/production.py b/analytics_dashboard/settings/production.py index c7f1e80be..a196c1d69 100644 --- a/analytics_dashboard/settings/production.py +++ b/analytics_dashboard/settings/production.py @@ -25,7 +25,7 @@ DATABASES['default'][override] = value # Re-declare the full application name in case the components have been overridden. -FULL_APPLICATION_NAME = u'{0} {1}'.format(PLATFORM_NAME, APPLICATION_NAME) +FULL_APPLICATION_NAME = f'{PLATFORM_NAME} {APPLICATION_NAME}' # Depends on DOCUMENTATION_LOAD_ERROR_URL, so evaluate at the end DOCUMENTATION_LOAD_ERROR_MESSAGE = 'This data may not be available for your course. ' \ diff --git a/analytics_dashboard/settings/test.py b/analytics_dashboard/settings/test.py index 02fa80f5a..d326d126c 100644 --- a/analytics_dashboard/settings/test.py +++ b/analytics_dashboard/settings/test.py @@ -1,5 +1,3 @@ - - from analytics_dashboard.settings.base import * from analytics_dashboard.settings.logger import get_logger_config diff --git a/analytics_dashboard/settings/yaml_config.py b/analytics_dashboard/settings/yaml_config.py index 564292323..18dad9e3b 100644 --- a/analytics_dashboard/settings/yaml_config.py +++ b/analytics_dashboard/settings/yaml_config.py @@ -1,5 +1,3 @@ - - from os import environ import yaml diff --git a/common/clients.py b/common/clients.py index b505249e6..2da994dab 100644 --- a/common/clients.py +++ b/common/clients.py @@ -1,5 +1,3 @@ - - import logging from edx_rest_api_client.client import EdxRestApiClient @@ -19,7 +17,7 @@ class CourseStructureApiClient(EdxRestApiClient): DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ" def __init__(self, url, access_token, timeout): - super(CourseStructureApiClient, self).__init__(url, jwt=access_token, timeout=timeout) + super().__init__(url, jwt=access_token, timeout=timeout) @property def all_courses(self): diff --git a/common/course_structure.py b/common/course_structure.py index a58352d75..ff29d8e8b 100644 --- a/common/course_structure.py +++ b/common/course_structure.py @@ -1,5 +1,3 @@ - - class CourseStructure: @staticmethod def _filter_children(blocks, key, require_format=False, **kwargs): @@ -15,9 +13,9 @@ def _filter_children(blocks, key, require_format=False, **kwargs): """ block = blocks[key] - block_type = kwargs.pop(u'block_type', None) + block_type = kwargs.pop('block_type', None) if block_type: - kwargs[u'type'] = block_type + kwargs['type'] = block_type matched = True for name, value in kwargs.items(): @@ -27,14 +25,14 @@ def _filter_children(blocks, key, require_format=False, **kwargs): if matched: if require_format: - if u'format' in block and block[u'format']: + if 'format' in block and block['format']: return [block] else: return [block] children = [] - if u'children' in block: - for child in block[u'children']: + if 'children' in block: + for child in block['children']: children += CourseStructure._filter_children(blocks, child, require_format=require_format, **kwargs) return children @@ -45,8 +43,8 @@ def course_structure_to_assignments(structure, graded=None, assignment_type=None Returns the assignments and nested problems from the given course structure. """ - blocks = structure[u'blocks'] - root = blocks[structure[u'root']] + blocks = structure['blocks'] + root = blocks[structure['root']] # Break down the course structure into assignments and nested problems, returning only the data # we absolutely need. @@ -57,13 +55,13 @@ def course_structure_to_assignments(structure, graded=None, assignment_type=None } if assignment_type: - kwargs[u'format'] = assignment_type + kwargs['format'] = assignment_type - filtered = CourseStructure._filter_children(blocks, root[u'id'], require_format=True, **kwargs) + filtered = CourseStructure._filter_children(blocks, root['id'], require_format=True, **kwargs) for assignment in filtered: - filtered_children = CourseStructure._filter_children(blocks, assignment[u'id'], graded=graded, - block_type=u'problem', require_format=False) + filtered_children = CourseStructure._filter_children(blocks, assignment['id'], graded=graded, + block_type='problem', require_format=False) problems = [] for problem in filtered_children: problems.append({ @@ -87,10 +85,10 @@ def course_structure_to_sections(structure, child_block_type, graded=None): within 'children' attributes. """ - blocks = structure[u'blocks'] - root = blocks[structure[u'root']] - sections = CourseStructure._build_sections(blocks, root[u'id'], - graded, [u'chapter', u'sequential', str(child_block_type)]) + blocks = structure['blocks'] + root = blocks[structure['root']] + sections = CourseStructure._build_sections(blocks, root['id'], + graded, ['chapter', 'sequential', str(child_block_type)]) return sections @staticmethod @@ -110,7 +108,7 @@ def _build_sections(blocks, section_id, graded, block_types): **filter_kwargs) for section in structure_sections: - children = CourseStructure._build_sections(blocks, section[u'id'], graded, block_types) + children = CourseStructure._build_sections(blocks, section['id'], graded, block_types) sections.append({ 'id': section['id'], 'name': section['display_name'], diff --git a/common/tests/course_fixtures.py b/common/tests/course_fixtures.py index 82f609f69..580a16a1e 100644 --- a/common/tests/course_fixtures.py +++ b/common/tests/course_fixtures.py @@ -1,4 +1,3 @@ - import uuid @@ -79,7 +78,7 @@ def id(self): class CourseFixture(CourseStructureAPIFixtureMixin): """Represents a course as returned by the Course Structure API.""" def __init__(self, *args, **kwargs): - super(CourseFixture, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self._type = 'course' self.org = kwargs.get('org', 'test_org') self.course = kwargs.get('course', 'test_course') @@ -101,7 +100,7 @@ class ChapterFixture(CourseStructureAPIFixtureMixin): """Represents a chapter as returned by the Course Structure API.""" def __init__(self, *args, **kwargs): - super(ChapterFixture, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self._type = 'chapter' @@ -109,7 +108,7 @@ class SequentialFixture(CourseStructureAPIFixtureMixin): """Represents a sequential as returned by the Course Structure API.""" def __init__(self, *args, **kwargs): - super(SequentialFixture, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.graded = kwargs.get('graded', False) self._assignment_type = kwargs.get('assignment_type') self._type = 'sequential' @@ -119,7 +118,7 @@ class VerticalFixture(CourseStructureAPIFixtureMixin): """Represents a vertical as returned by the Course Structure API.""" def __init__(self, *args, **kwargs): - super(VerticalFixture, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self._type = 'vertical' @@ -127,5 +126,5 @@ class VideoFixture(CourseStructureAPIFixtureMixin): """Represents a video as returned by the Course Structure API.""" def __init__(self, *args, **kwargs): - super(VideoFixture, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self._type = 'video' diff --git a/common/tests/factories.py b/common/tests/factories.py index dff6396f6..937301a21 100644 --- a/common/tests/factories.py +++ b/common/tests/factories.py @@ -1,5 +1,3 @@ - - import copy import uuid @@ -74,7 +72,7 @@ def _generate_subsection_children(self, assignment_type, display_name, problem_i """ Overwrite if you want other subsection types (e.g. videos) """ problem = self._generate_block('problem', assignment_type, - '{} Problem {}'.format(display_name, problem_index), + f'{display_name} Problem {problem_index}', graded) self._structure['blocks'][problem['id']] = problem return problem @@ -102,7 +100,7 @@ def _generate_structure(self): assignment_type = gp['assignment_type'] for assignment_index in range(1, count + 1): - display_name = '{} {}'.format(assignment_type, assignment_index) + display_name = f'{assignment_type} {assignment_index}' graded_children = [] # Generate the graded children diff --git a/common/tests/test_course_structure.py b/common/tests/test_course_structure.py index 4c230a332..6dd4c1153 100644 --- a/common/tests/test_course_structure.py +++ b/common/tests/test_course_structure.py @@ -1,5 +1,3 @@ - - from unittest import TestCase from common.course_structure import CourseStructure diff --git a/docs/en_us/dashboard/source/conf.py b/docs/en_us/dashboard/source/conf.py index 0b13ba035..5b1615d6e 100644 --- a/docs/en_us/dashboard/source/conf.py +++ b/docs/en_us/dashboard/source/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # import datetime