From 0872732cf005de2712b55da45ad5195da7747c54 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Mon, 23 Nov 2015 09:37:24 -0500 Subject: [PATCH] Fix pylint C7630 (literal used as attribute) violations There's no need to use a string literal in setattr, delattr, or the two-argument form of getattr. --- .../contentstore/views/entrance_exam.py | 4 ++-- .../tests/test_middleware.py | 13 +++++-------- common/djangoapps/student/roles.py | 2 +- common/djangoapps/student/views.py | 2 +- common/djangoapps/terrain/setup_prereqs.py | 2 +- common/djangoapps/third_party_auth/pipeline.py | 2 +- common/djangoapps/util/url.py | 2 +- common/djangoapps/xblock_django/user_service.py | 5 ++++- common/lib/xmodule/xmodule/course_module.py | 2 +- .../xmodule/xmodule/modulestore/mongo/draft.py | 2 +- .../split_mongo/caching_descriptor_system.py | 8 ++++---- .../modulestore/split_mongo/split_draft.py | 5 +++-- .../modulestore/tests/test_contentstore.py | 12 ++++++------ .../xmodule/xmodule/modulestore/xml_importer.py | 2 +- .../lib/xmodule/xmodule/tests/test_services.py | 8 ++++---- .../xmodule/xmodule/video_module/bumper_utils.py | 2 +- lms/djangoapps/courseware/features/lti.py | 4 ++-- lms/djangoapps/courseware/module_render.py | 2 +- .../courseware/tests/test_module_render.py | 5 +++-- .../commands/tests/test_git_add_course.py | 2 +- lms/djangoapps/dashboard/tests/test_sysadmin.py | 16 ++++++++-------- .../instructor/paidcourse_enrollment_report.py | 6 +++--- lms/djangoapps/instructor/views/api.py | 2 +- .../instructor/views/instructor_dashboard.py | 2 +- .../instructor/views/instructor_task_helpers.py | 2 +- lms/djangoapps/instructor_analytics/basic.py | 15 ++++++++------- .../instructor_analytics/tests/test_basic.py | 2 +- lms/djangoapps/oauth2_handler/handlers.py | 2 +- lms/djangoapps/shoppingcart/models.py | 12 +++++++----- lms/djangoapps/shoppingcart/tests/test_views.py | 8 ++++---- lms/djangoapps/shoppingcart/views.py | 14 +++++++------- lms/lib/xblock/test/test_mixin.py | 2 +- openedx/core/djangoapps/credit/tasks.py | 2 +- scripts/all-tests.sh | 2 +- 34 files changed, 89 insertions(+), 84 deletions(-) diff --git a/cms/djangoapps/contentstore/views/entrance_exam.py b/cms/djangoapps/contentstore/views/entrance_exam.py index 400ce362d3..21be96119e 100644 --- a/cms/djangoapps/contentstore/views/entrance_exam.py +++ b/cms/djangoapps/contentstore/views/entrance_exam.py @@ -177,7 +177,7 @@ def _get_entrance_exam(request, course_key): # pylint: disable=W0613 course = modulestore().get_course(course_key) if course is None: return HttpResponse(status=400) - if not getattr(course, 'entrance_exam_id'): + if not course.entrance_exam_id: return HttpResponse(status=404) try: exam_key = UsageKey.from_string(course.entrance_exam_id) @@ -228,7 +228,7 @@ def _delete_entrance_exam(request, course_key): # Reset the entrance exam flags on the course # Reload the course so we have the latest state course = store.get_course(course_key) - if getattr(course, 'entrance_exam_id'): + if course.entrance_exam_id: metadata = { 'entrance_exam_enabled': False, 'entrance_exam_minimum_score_pct': None, diff --git a/common/djangoapps/microsite_configuration/tests/test_middleware.py b/common/djangoapps/microsite_configuration/tests/test_middleware.py index 771ce6f4bb..c68636dcc8 100644 --- a/common/djangoapps/microsite_configuration/tests/test_middleware.py +++ b/common/djangoapps/microsite_configuration/tests/test_middleware.py @@ -36,10 +36,9 @@ class MicroSiteSessionCookieTests(TestCase): """ Tests that non-microsite behaves according to default behavior """ - response = self.client.get('/') - self.assertNotIn('test_microsite.localhost', str(getattr(response, 'cookies')['sessionid'])) - self.assertNotIn('Domain', str(getattr(response, 'cookies')['sessionid'])) + self.assertNotIn('test_microsite.localhost', str(response.cookies['sessionid'])) # pylint: disable=no-member + self.assertNotIn('Domain', str(response.cookies['sessionid'])) # pylint: disable=no-member def test_session_cookie_domain(self): """ @@ -47,9 +46,8 @@ class MicroSiteSessionCookieTests(TestCase): is the one specially overridden in configuration, in this case in test.py """ - response = self.client.get('/', HTTP_HOST=settings.MICROSITE_TEST_HOSTNAME) - self.assertIn('test_microsite.localhost', str(getattr(response, 'cookies')['sessionid'])) + self.assertIn('test_microsite.localhost', str(response.cookies['sessionid'])) # pylint: disable=no-member @patch.dict("django.conf.settings.MICROSITE_CONFIGURATION", {'test_microsite': {'SESSION_COOKIE_DOMAIN': None}}) def test_microsite_none_cookie_domain(self): @@ -57,7 +55,6 @@ class MicroSiteSessionCookieTests(TestCase): Tests to make sure that a Microsite that specifies None for 'SESSION_COOKIE_DOMAIN' does not set a domain on the session cookie """ - response = self.client.get('/', HTTP_HOST=settings.MICROSITE_TEST_HOSTNAME) - self.assertNotIn('test_microsite.localhost', str(getattr(response, 'cookies')['sessionid'])) - self.assertNotIn('Domain', str(getattr(response, 'cookies')['sessionid'])) + self.assertNotIn('test_microsite.localhost', str(response.cookies['sessionid'])) # pylint: disable=no-member + self.assertNotIn('Domain', str(response.cookies['sessionid'])) # pylint: disable=no-member diff --git a/common/djangoapps/student/roles.py b/common/djangoapps/student/roles.py index e60300c191..c8b8796420 100644 --- a/common/djangoapps/student/roles.py +++ b/common/djangoapps/student/roles.py @@ -27,7 +27,7 @@ def register_access_role(cls): """ try: - role_name = getattr(cls, 'ROLE') + role_name = cls.ROLE REGISTERED_ACCESS_ROLES[role_name] = cls except AttributeError: log.exception(u"Unable to register Access Role with attribute 'ROLE'.") diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 725b9b501e..f3383015e9 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -500,7 +500,7 @@ def is_course_blocked(request, redeemed_registration_codes, course_key): # we have to check only for the invoice generated registration codes # that their invoice is valid or not if redeemed_registration.invoice_item: - if not getattr(redeemed_registration.invoice_item.invoice, 'is_valid'): + if not redeemed_registration.invoice_item.invoice.is_valid: blocked = True # disabling email notifications for unpaid registration courses Optout.objects.get_or_create(user=request.user, course_id=course_key) diff --git a/common/djangoapps/terrain/setup_prereqs.py b/common/djangoapps/terrain/setup_prereqs.py index 90337c3867..90386af90c 100644 --- a/common/djangoapps/terrain/setup_prereqs.py +++ b/common/djangoapps/terrain/setup_prereqs.py @@ -43,7 +43,7 @@ def start_video_server(): video_source_dir = '{}/data/video'.format(settings.TEST_ROOT) video_server = VideoSourceHttpService(port_num=settings.VIDEO_SOURCE_PORT) video_server.config['root_dir'] = video_source_dir - setattr(world, 'video_source', video_server) + world.video_source = video_server @after.all # pylint: disable=no-member diff --git a/common/djangoapps/third_party_auth/pipeline.py b/common/djangoapps/third_party_auth/pipeline.py index 59865b419b..02b9f72a9a 100644 --- a/common/djangoapps/third_party_auth/pipeline.py +++ b/common/djangoapps/third_party_auth/pipeline.py @@ -589,7 +589,7 @@ def login_analytics(strategy, auth_entry, *args, **kwargs): { 'category': "conversion", 'label': None, - 'provider': getattr(kwargs['backend'], 'name') + 'provider': kwargs['backend'].name }, context={ 'ip': tracking_context.get('ip'), diff --git a/common/djangoapps/util/url.py b/common/djangoapps/util/url.py index 25250eb2d5..a5deda2b4e 100644 --- a/common/djangoapps/util/url.py +++ b/common/djangoapps/util/url.py @@ -18,5 +18,5 @@ def reload_django_url_config(): if urlconf and urlconf in sys.modules: reload(sys.modules[urlconf]) reloaded = import_module(urlconf) - reloaded_urls = getattr(reloaded, 'urlpatterns') + reloaded_urls = reloaded.urlpatterns set_urlconf(tuple(reloaded_urls)) diff --git a/common/djangoapps/xblock_django/user_service.py b/common/djangoapps/xblock_django/user_service.py index c09e518578..3adb5cb65b 100644 --- a/common/djangoapps/xblock_django/user_service.py +++ b/common/djangoapps/xblock_django/user_service.py @@ -59,7 +59,10 @@ class DjangoXBlockUserService(UserService): if django_user is not None and django_user.is_authenticated(): # This full_name is dependent on edx-platform's profile implementation - full_name = getattr(django_user.profile, 'name') if hasattr(django_user, 'profile') else None + if hasattr(django_user, 'profile'): + full_name = django_user.profile.name + else: + full_name = None xblock_user.full_name = full_name xblock_user.emails = [django_user.email] xblock_user.opt_attrs[ATTR_KEY_IS_AUTHENTICATED] = True diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py index 19b85a36a1..770f2d6d46 100644 --- a/common/lib/xmodule/xmodule/course_module.py +++ b/common/lib/xmodule/xmodule/course_module.py @@ -977,7 +977,7 @@ class CourseDescriptor(CourseFields, SequenceDescriptor, LicenseMixin): # Then remove show_timezone so that if the user clears out the due_date_display_format, # they get the default date display. self.due_date_display_format = "DATE_TIME" - delattr(self, 'show_timezone') + del self.show_timezone # NOTE: relies on the modulestore to call set_grading_policy() right after # init. (Modulestore is in charge of figuring out where to load the policy from) diff --git a/common/lib/xmodule/xmodule/modulestore/mongo/draft.py b/common/lib/xmodule/xmodule/modulestore/mongo/draft.py index b75a337e63..d1ee46412a 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongo/draft.py +++ b/common/lib/xmodule/xmodule/modulestore/mongo/draft.py @@ -32,7 +32,7 @@ def wrap_draft(item): Sets `item.is_draft` to `True` if the item is DRAFT, and `False` otherwise. Sets the item's location to the non-draft location in either case. """ - setattr(item, 'is_draft', item.location.revision == MongoRevisionKey.draft) + item.is_draft = (item.location.revision == MongoRevisionKey.draft) item.location = item.location.replace(revision=MongoRevisionKey.published) return item diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/caching_descriptor_system.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/caching_descriptor_system.py index f8f1dbe54e..d5e1bbdea9 100644 --- a/common/lib/xmodule/xmodule/modulestore/split_mongo/caching_descriptor_system.py +++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/caching_descriptor_system.py @@ -281,9 +281,9 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin): self._compute_subtree_edited_internal( block_data, xblock.location.course_key ) - setattr(xblock, '_subtree_edited_by', block_data.edit_info._subtree_edited_by) + xblock._subtree_edited_by = block_data.edit_info._subtree_edited_by - return getattr(xblock, '_subtree_edited_by') + return xblock._subtree_edited_by @contract(xblock='XBlock') def get_subtree_edited_on(self, xblock): @@ -297,9 +297,9 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin): self._compute_subtree_edited_internal( block_data, xblock.location.course_key ) - setattr(xblock, '_subtree_edited_on', block_data.edit_info._subtree_edited_on) + xblock._subtree_edited_on = block_data.edit_info._subtree_edited_on - return getattr(xblock, '_subtree_edited_on') + return xblock._subtree_edited_on def get_published_by(self, xblock): """ diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py index bdd4696106..8f2554eab1 100644 --- a/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py +++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py @@ -552,8 +552,9 @@ class DraftVersioningModuleStore(SplitMongoModuleStore, ModuleStoreDraftAndPubli """ published_block = self._get_head(xblock, ModuleStoreEnum.BranchName.published) if published_block is not None: - setattr(xblock, '_published_by', published_block.edit_info.edited_by) - setattr(xblock, '_published_on', published_block.edit_info.edited_on) + # pylint: disable=protected-access + xblock._published_by = published_block.edit_info.edited_by + xblock._published_on = published_block.edit_info.edited_on @contract(asset_key='AssetKey') def find_asset_metadata(self, asset_key, **kwargs): diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_contentstore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_contentstore.py index 667eaa5bf6..5735d89f20 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_contentstore.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_contentstore.py @@ -42,13 +42,13 @@ class TestContentstore(unittest.TestCase): Restores deprecated values """ if cls.asset_deprecated is not None: - setattr(AssetLocator, 'deprecated', cls.asset_deprecated) + AssetLocator.deprecated = cls.asset_deprecated else: - delattr(AssetLocator, 'deprecated') + del AssetLocator.deprecated if cls.ssck_deprecated is not None: - setattr(CourseLocator, 'deprecated', cls.ssck_deprecated) + CourseLocator.deprecated = cls.ssck_deprecated else: - delattr(CourseLocator, 'deprecated') + del CourseLocator.deprecated return super(TestContentstore, cls).tearDownClass() def set_up_assets(self, deprecated): @@ -60,8 +60,8 @@ class TestContentstore(unittest.TestCase): self.contentstore = MongoContentStore(HOST, DB, port=PORT) self.addCleanup(self.contentstore._drop_database) # pylint: disable=protected-access - setattr(AssetLocator, 'deprecated', deprecated) - setattr(CourseLocator, 'deprecated', deprecated) + AssetLocator.deprecated = deprecated + CourseLocator.deprecated = deprecated self.course1_key = CourseLocator('test', 'asset_test', '2014_07') self.course2_key = CourseLocator('test', 'asset_test2', '2014_07') diff --git a/common/lib/xmodule/xmodule/modulestore/xml_importer.py b/common/lib/xmodule/xmodule/modulestore/xml_importer.py index 6791d10af1..8ef58dbea6 100644 --- a/common/lib/xmodule/xmodule/modulestore/xml_importer.py +++ b/common/lib/xmodule/xmodule/modulestore/xml_importer.py @@ -961,7 +961,7 @@ def create_xml_attributes(module, xml): xml_attrs[attr] = val # now cache it on module where it's expected - setattr(module, 'xml_attributes', xml_attrs) + module.xml_attributes = xml_attrs def validate_no_non_editable_metadata(module_store, course_id, category): diff --git a/common/lib/xmodule/xmodule/tests/test_services.py b/common/lib/xmodule/xmodule/tests/test_services.py index 59c49fbb03..c8dfd89639 100644 --- a/common/lib/xmodule/xmodule/tests/test_services.py +++ b/common/lib/xmodule/xmodule/tests/test_services.py @@ -52,20 +52,20 @@ class TestSettingsService(TestCase): @override_settings(XBLOCK_SETTINGS={xblock_setting_key2: {'b': 1}}) def test_get_returns_none_or_default_if_bucket_not_found(self): """ Test if settings service returns default if setting not found """ - self.assertEqual(getattr(settings, 'XBLOCK_SETTINGS'), {self.xblock_setting_key2: {'b': 1}}) + self.assertEqual(settings.XBLOCK_SETTINGS, {self.xblock_setting_key2: {'b': 1}}) self.assertEqual(self.settings_service.get_settings_bucket(self.xblock_mock), {}) self.assertEqual(self.settings_service.get_settings_bucket(self.xblock_mock, 123), 123) @override_settings(XBLOCK_SETTINGS={xblock_setting_key1: 42}) def test_get_returns_correct_value(self): """ Test if settings service returns correct bucket """ - self.assertEqual(getattr(settings, 'XBLOCK_SETTINGS'), {self.xblock_setting_key1: 42}) + self.assertEqual(settings.XBLOCK_SETTINGS, {self.xblock_setting_key1: 42}) self.assertEqual(self.settings_service.get_settings_bucket(self.xblock_mock), 42) @override_settings(XBLOCK_SETTINGS={xblock_setting_key2: "I'm a setting"}) def test_get_respects_block_settings_key(self): """ Test if settings service respects block_settings_key value """ - self.assertEqual(getattr(settings, 'XBLOCK_SETTINGS'), {self.xblock_setting_key2: "I'm a setting"}) + self.assertEqual(settings.XBLOCK_SETTINGS, {self.xblock_setting_key2: "I'm a setting"}) self.xblock_mock.block_settings_key = self.xblock_setting_key2 self.assertEqual(self.settings_service.get_settings_bucket(self.xblock_mock), "I'm a setting") @@ -74,5 +74,5 @@ class TestSettingsService(TestCase): """ Test if settings service uses class name if block_settings_key attribute does not exist """ mixologist = Mixologist([]) block = mixologist.mix(_DummyBlock) - self.assertEqual(getattr(settings, 'XBLOCK_SETTINGS'), {"_DummyBlock": [1, 2, 3]}) + self.assertEqual(settings.XBLOCK_SETTINGS, {"_DummyBlock": [1, 2, 3]}) self.assertEqual(self.settings_service.get_settings_bucket(block), [1, 2, 3]) diff --git a/common/lib/xmodule/xmodule/video_module/bumper_utils.py b/common/lib/xmodule/xmodule/video_module/bumper_utils.py index 0bb914d280..6ef996e3b8 100644 --- a/common/lib/xmodule/xmodule/video_module/bumper_utils.py +++ b/common/lib/xmodule/xmodule/video_module/bumper_utils.py @@ -49,7 +49,7 @@ def is_bumper_enabled(video): utc_now = datetime.utcnow().replace(tzinfo=pytz.utc) periodicity = settings.FEATURES.get('SHOW_BUMPER_PERIODICITY', 0) has_viewed = any([ - getattr(video, 'bumper_do_not_show_again'), + video.bumper_do_not_show_again, (bumper_last_view_date and bumper_last_view_date + timedelta(seconds=periodicity) > utc_now) ]) is_studio = getattr(video.system, "is_author_mode", False) diff --git a/lms/djangoapps/courseware/features/lti.py b/lms/djangoapps/courseware/features/lti.py index 75f9950e94..fcefc44f64 100644 --- a/lms/djangoapps/courseware/features/lti.py +++ b/lms/djangoapps/courseware/features/lti.py @@ -181,10 +181,10 @@ def add_correct_lti_to_course(_step, fields): metadata=metadata, ) - setattr(world.scenario_dict['LTI'], 'TEST_BASE_PATH', '{host}:{port}'.format( + world.scenario_dict['LTI'].TEST_BASE_PATH = '{host}:{port}'.format( host=world.browser.host, port=world.browser.port, - )) + ) visit_scenario_item('LTI') diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index e6bcad933d..2302ab5dba 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -769,7 +769,7 @@ def get_module_system_for_user(user, student_data, # TODO # pylint: disable=to system.set(u'user_is_staff', user_is_staff) system.set(u'user_is_admin', bool(has_access(user, u'staff', 'global'))) system.set(u'user_is_beta_tester', CourseBetaTesterRole(course_id).has_user(user)) - system.set(u'days_early_for_beta', getattr(descriptor, 'days_early_for_beta')) + system.set(u'days_early_for_beta', descriptor.days_early_for_beta) # make an ErrorDescriptor -- assuming that the descriptor's system is ok if has_access(user, u'staff', descriptor.location, course_id): diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index 24462b4a55..ab271768de 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -1871,8 +1871,9 @@ class LMSXBlockServiceBindingTest(ModuleStoreTestCase): course=self.course ) - self.assertFalse(getattr(runtime, u'user_is_beta_tester')) - self.assertEqual(getattr(runtime, u'days_early_for_beta'), 5) + # pylint: disable=no-member + self.assertFalse(runtime.user_is_beta_tester) + self.assertEqual(runtime.days_early_for_beta, 5) class PureXBlockWithChildren(PureXBlock): diff --git a/lms/djangoapps/dashboard/management/commands/tests/test_git_add_course.py b/lms/djangoapps/dashboard/management/commands/tests/test_git_add_course.py index d2da5a1417..80438aed11 100644 --- a/lms/djangoapps/dashboard/management/commands/tests/test_git_add_course.py +++ b/lms/djangoapps/dashboard/management/commands/tests/test_git_add_course.py @@ -46,7 +46,7 @@ class TestGitAddCourse(ModuleStoreTestCase): TEST_COURSE = 'MITx/edx4edx/edx4edx' TEST_BRANCH = 'testing_do_not_delete' TEST_BRANCH_COURSE = SlashSeparatedCourseKey('MITx', 'edx4edx_branch', 'edx4edx') - GIT_REPO_DIR = getattr(settings, 'GIT_REPO_DIR') + GIT_REPO_DIR = settings.GIT_REPO_DIR def assertCommandFailureRegexp(self, regex, *args): """ diff --git a/lms/djangoapps/dashboard/tests/test_sysadmin.py b/lms/djangoapps/dashboard/tests/test_sysadmin.py index 7f08e35906..ee0355cf68 100644 --- a/lms/djangoapps/dashboard/tests/test_sysadmin.py +++ b/lms/djangoapps/dashboard/tests/test_sysadmin.py @@ -442,8 +442,8 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase): self._setstaff_login() - if os.path.isdir(getattr(settings, 'GIT_REPO_DIR')): - shutil.rmtree(getattr(settings, 'GIT_REPO_DIR')) + if os.path.isdir(settings.GIT_REPO_DIR): + shutil.rmtree(settings.GIT_REPO_DIR) # Create git loaded course response = self._add_edx4edx() @@ -457,7 +457,7 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase): """ self._setstaff_login() - self._mkdir(getattr(settings, 'GIT_REPO_DIR')) + self._mkdir(settings.GIT_REPO_DIR) def_ms = modulestore() self.assertFalse('xml' == def_ms.get_modulestore_type(None)) @@ -485,7 +485,7 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase): """, re.VERBOSE) self._setstaff_login() - self._mkdir(getattr(settings, 'GIT_REPO_DIR')) + self._mkdir(settings.GIT_REPO_DIR) # Make sure we don't have any git hashes on the page response = self.client.get(reverse('sysadmin_courses')) @@ -501,7 +501,7 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase): """ self._setstaff_login() - self._mkdir(getattr(settings, 'GIT_REPO_DIR')) + self._mkdir(settings.GIT_REPO_DIR) self._add_edx4edx() response = self.client.get(reverse('gitlogs')) @@ -534,7 +534,7 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase): tz_format = DEFAULT_DATE_TIME_FORMAT self._setstaff_login() - self._mkdir(getattr(settings, 'GIT_REPO_DIR')) + self._mkdir(settings.GIT_REPO_DIR) self._add_edx4edx() date = CourseImportLog.objects.first().created.replace(tzinfo=UTC) @@ -564,7 +564,7 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase): """ self._setstaff_login() - self._mkdir(getattr(settings, 'GIT_REPO_DIR')) + self._mkdir(settings.GIT_REPO_DIR) self._add_edx4edx() @@ -623,7 +623,7 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase): Ensure course team users are allowed to access only their own course. """ - self._mkdir(getattr(settings, 'GIT_REPO_DIR')) + self._mkdir(settings.GIT_REPO_DIR) self._setstaff_login() self._add_edx4edx() diff --git a/lms/djangoapps/instructor/paidcourse_enrollment_report.py b/lms/djangoapps/instructor/paidcourse_enrollment_report.py index f011ee67df..1d627f6f05 100644 --- a/lms/djangoapps/instructor/paidcourse_enrollment_report.py +++ b/lms/djangoapps/instructor/paidcourse_enrollment_report.py @@ -111,12 +111,12 @@ class PaidCourseEnrollmentReportProvider(BaseAbstractEnrollmentReportProvider): if registration_code_redemption is not None: registration_code = registration_code_redemption.registration_code registration_code_used = registration_code.code - if getattr(registration_code, 'invoice_item_id'): + if registration_code.invoice_item_id: list_price, payment_amount, payment_status, transaction_reference_number =\ self._get_invoice_data(registration_code_redemption) coupon_codes_used = 'N/A' - elif getattr(registration_code_redemption.registration_code, 'order_id'): + elif registration_code_redemption.registration_code.order_id: list_price, payment_amount, coupon_codes_used, payment_status, transaction_reference_number = \ self._get_order_data(registration_code_redemption, course_id) @@ -168,7 +168,7 @@ class PaidCourseEnrollmentReportProvider(BaseAbstractEnrollmentReportProvider): Returns the Invoice data """ registration_code = registration_code_redemption.registration_code - list_price = getattr(registration_code.invoice_item, 'unit_price') + list_price = registration_code.invoice_item.unit_price total_amount = registration_code_redemption.registration_code.invoice.total_amount qty = registration_code_redemption.registration_code.invoice_item.qty payment_amount = total_amount / qty diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index f2df7db524..d8bd396ff5 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -914,7 +914,7 @@ def get_problem_responses(request, course_id): try: problem_key = UsageKey.from_string(problem_location) # Are we dealing with an "old-style" problem location? - run = getattr(problem_key, 'run') + run = problem_key.run if not run: problem_key = course_key.make_usage_key_from_deprecated_string(problem_location) if problem_key.course_key != course_key: diff --git a/lms/djangoapps/instructor/views/instructor_dashboard.py b/lms/djangoapps/instructor/views/instructor_dashboard.py index 57cfa01b80..7207a536f8 100644 --- a/lms/djangoapps/instructor/views/instructor_dashboard.py +++ b/lms/djangoapps/instructor/views/instructor_dashboard.py @@ -352,7 +352,7 @@ def set_course_mode_price(request, course_id): CourseModesArchive.objects.create( course_id=course_id, mode_slug='honor', mode_display_name='Honor Code Certificate', - min_price=getattr(course_honor_mode[0], 'min_price'), currency=getattr(course_honor_mode[0], 'currency'), + min_price=course_honor_mode[0].min_price, currency=course_honor_mode[0].currency, expiration_datetime=datetime.datetime.now(pytz.utc), expiration_date=datetime.date.today() ) course_honor_mode.update( diff --git a/lms/djangoapps/instructor/views/instructor_task_helpers.py b/lms/djangoapps/instructor/views/instructor_task_helpers.py index 11d0e5e399..0b61ee2634 100644 --- a/lms/djangoapps/instructor/views/instructor_task_helpers.py +++ b/lms/djangoapps/instructor/views/instructor_task_helpers.py @@ -58,7 +58,7 @@ def extract_email_features(email_task): email_feature_dict = { 'created': get_default_time_display(email.created), 'sent_to': task_input_information['to_option'], - 'requester': str(getattr(email_task, 'requester')), + 'requester': str(email_task.requester), } features = ['subject', 'html_message', 'id'] email_info = {feature: unicode(getattr(email, feature)) for feature in features} diff --git a/lms/djangoapps/instructor_analytics/basic.py b/lms/djangoapps/instructor_analytics/basic.py index 3e9ebfe044..f6fa04d895 100644 --- a/lms/djangoapps/instructor_analytics/basic.py +++ b/lms/djangoapps/instructor_analytics/basic.py @@ -80,8 +80,8 @@ def sale_order_record_features(course_id, features): sale_order_dict = dict((feature, getattr(purchased_course.order, feature)) for feature in sale_order_features) - quantity = int(getattr(purchased_course, 'qty')) - unit_cost = float(getattr(purchased_course, 'unit_cost')) + quantity = int(purchased_course.qty) + unit_cost = float(purchased_course.unit_cost) sale_order_dict.update({"quantity": quantity}) sale_order_dict.update({"total_amount": quantity * unit_cost}) @@ -147,7 +147,7 @@ def sale_record_features(course_id, features): total_used_codes = RegistrationCodeRedemption.objects.filter( registration_code__in=sale.courseregistrationcode_set.all() ).count() - sale_dict.update({"invoice_number": getattr(invoice, 'id')}) + sale_dict.update({"invoice_number": invoice.id}) sale_dict.update({"total_codes": sale.courseregistrationcode_set.all().count()}) sale_dict.update({'total_used_codes': total_used_codes}) @@ -379,7 +379,7 @@ def list_problem_responses(course_key, problem_location): """ problem_key = UsageKey.from_string(problem_location) # Are we dealing with an "old-style" problem location? - run = getattr(problem_key, 'run') + run = problem_key.run if not run: problem_key = course_key.make_usage_key_from_deprecated_string(problem_location) if problem_key.course_key != course_key: @@ -420,7 +420,7 @@ def course_registration_features(features, registration_codes, csv_type): course_registration_dict = dict((feature, getattr(registration_code, feature)) for feature in registration_features) course_registration_dict['company_name'] = None if registration_code.invoice_item: - course_registration_dict['company_name'] = getattr(registration_code.invoice_item.invoice, 'company_name') + course_registration_dict['company_name'] = registration_code.invoice_item.invoice.company_name course_registration_dict['redeemed_by'] = None if registration_code.invoice_item: sale_invoice = registration_code.invoice_item.invoice @@ -439,8 +439,9 @@ def course_registration_features(features, registration_codes, csv_type): # They have not been redeemed yet if csv_type is not None: try: - redeemed_by = getattr(registration_code.registrationcoderedemption_set.get(registration_code=registration_code), 'redeemed_by') - course_registration_dict['redeemed_by'] = getattr(redeemed_by, 'email') + redemption_set = registration_code.registrationcoderedemption_set + redeemed_by = redemption_set.get(registration_code=registration_code).redeemed_by + course_registration_dict['redeemed_by'] = redeemed_by.email except ObjectDoesNotExist: pass diff --git a/lms/djangoapps/instructor_analytics/tests/test_basic.py b/lms/djangoapps/instructor_analytics/tests/test_basic.py index 307a3eaaaf..736c91091b 100644 --- a/lms/djangoapps/instructor_analytics/tests/test_basic.py +++ b/lms/djangoapps/instructor_analytics/tests/test_basic.py @@ -473,7 +473,7 @@ class TestCourseRegistrationCodeAnalyticsBasic(ModuleStoreTestCase): self.assertIn( course_registration['company_name'], [ - getattr(registration_code.invoice_item.invoice, 'company_name') + registration_code.invoice_item.invoice.company_name for registration_code in registration_codes ] ) diff --git a/lms/djangoapps/oauth2_handler/handlers.py b/lms/djangoapps/oauth2_handler/handlers.py index cab2ec5337..38f246b688 100644 --- a/lms/djangoapps/oauth2_handler/handlers.py +++ b/lms/djangoapps/oauth2_handler/handlers.py @@ -73,7 +73,7 @@ class ProfileHandler(object): # If the user has no language specified, return the default one. if not language: - language = getattr(settings, 'LANGUAGE_CODE') + language = settings.LANGUAGE_CODE return language diff --git a/lms/djangoapps/shoppingcart/models.py b/lms/djangoapps/shoppingcart/models.py index 68c96a8f94..65d718df21 100644 --- a/lms/djangoapps/shoppingcart/models.py +++ b/lms/djangoapps/shoppingcart/models.py @@ -333,7 +333,7 @@ class Order(models.Model): csv_writer.writerow(['Course Name', 'Registration Code', 'URL']) for item in orderitems: course_id = item.course_id - course = get_course_by_id(getattr(item, 'course_id'), depth=0) + course = get_course_by_id(item.course_id, depth=0) registration_codes = CourseRegistrationCode.objects.filter(course_id=course_id, order=self) course_info.append((course.display_name, ' (' + course.start_datetime_text() + '-' + course.end_datetime_text() + ')')) for registration_code in registration_codes: @@ -347,7 +347,7 @@ class Order(models.Model): """ send confirmation e-mail """ - recipient_list = [(self.user.username, getattr(self.user, 'email'), 'user')] # pylint: disable=no-member + recipient_list = [(self.user.username, self.user.email, 'user')] # pylint: disable=no-member if self.company_contact_email: recipient_list.append((self.company_contact_name, self.company_contact_email, 'company_contact')) joined_course_names = "" @@ -385,7 +385,9 @@ class Order(models.Model): 'course_names': ", ".join([course_info[0] for course_info in courses_info]), 'dashboard_url': dashboard_url, 'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1], - 'order_placed_by': '{username} ({email})'.format(username=self.user.username, email=getattr(self.user, 'email')), # pylint: disable=no-member + 'order_placed_by': '{username} ({email})'.format( + username=self.user.username, email=self.user.email + ), 'has_billing_info': settings.FEATURES['STORE_BILLING_INFO'], 'platform_name': microsite.get_value('platform_name', settings.PLATFORM_NAME), 'payment_support_email': microsite.get_value('payment_support_email', settings.PAYMENT_SUPPORT_EMAIL), @@ -1364,7 +1366,7 @@ class CouponRedemption(models.Model): If an item removed from shopping cart then we will remove the corresponding redemption info of coupon code """ - order_item_course_id = getattr(item, 'course_id') + order_item_course_id = item.course_id try: # Try to remove redemption information of coupon code, If exist. coupon_redemption = cls.objects.get( @@ -1417,7 +1419,7 @@ class CouponRedemption(models.Model): raise MultipleCouponsNotAllowedException for item in cart_items: - if getattr(item, 'course_id'): + if item.course_id: if item.course_id == coupon.course_id: coupon_redemption = cls(order=order, user=order.user, coupon=coupon) coupon_redemption.save() diff --git a/lms/djangoapps/shoppingcart/tests/test_views.py b/lms/djangoapps/shoppingcart/tests/test_views.py index d914e65c27..459c763ecc 100644 --- a/lms/djangoapps/shoppingcart/tests/test_views.py +++ b/lms/djangoapps/shoppingcart/tests/test_views.py @@ -531,9 +531,9 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): get_coupon = Coupon.objects.get(id=1) request = HttpRequest() request.user = admin - setattr(request, 'session', 'session') + request.session = 'session' messages = FallbackStorage(request) - setattr(request, '_messages', messages) + request._messages = messages # pylint: disable=protected-access coupon_admin = SoftDeleteCouponAdmin(Coupon, AdminSite()) test_query_set = coupon_admin.queryset(request) test_actions = coupon_admin.get_actions(request) @@ -1546,7 +1546,7 @@ class ShoppingcartViewsClosedEnrollment(ModuleStoreTestCase): resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code}) self.assertEqual(resp.status_code, 200) - coupon_redemption = CouponRedemption.objects.filter(coupon__course_id=getattr(expired_course_item, 'course_id'), + coupon_redemption = CouponRedemption.objects.filter(coupon__course_id=expired_course_item.course_id, order=expired_course_item.order_id) self.assertEqual(coupon_redemption.count(), 1) # testing_course enrollment is closed but the course is in the cart @@ -1557,7 +1557,7 @@ class ShoppingcartViewsClosedEnrollment(ModuleStoreTestCase): self.assertIn("{course_name} has been removed because the enrollment period has closed.".format(course_name=self.testing_course.display_name), resp.content) # now the redemption entry should be deleted from the table. - coupon_redemption = CouponRedemption.objects.filter(coupon__course_id=getattr(expired_course_item, 'course_id'), + coupon_redemption = CouponRedemption.objects.filter(coupon__course_id=expired_course_item.course_id, order=expired_course_item.order_id) self.assertEqual(coupon_redemption.count(), 0) ((template, context), _tmp) = render_mock.call_args diff --git a/lms/djangoapps/shoppingcart/views.py b/lms/djangoapps/shoppingcart/views.py index 4c87b4df44..06ded6ebe6 100644 --- a/lms/djangoapps/shoppingcart/views.py +++ b/lms/djangoapps/shoppingcart/views.py @@ -319,7 +319,7 @@ def register_code_redemption(request, registration_code): if request.method == "GET": reg_code_is_valid, reg_code_already_redeemed, course_registration = get_reg_code_validity(registration_code, request, limiter) - course = get_course_by_id(getattr(course_registration, 'course_id'), depth=0) + course = get_course_by_id(course_registration.course_id, depth=0) # Restrict the user from enrolling based on country access rules embargo_redirect = embargo_api.redirect_if_blocked( @@ -341,7 +341,7 @@ def register_code_redemption(request, registration_code): elif request.method == "POST": reg_code_is_valid, reg_code_already_redeemed, course_registration = get_reg_code_validity(registration_code, request, limiter) - course = get_course_by_id(getattr(course_registration, 'course_id'), depth=0) + course = get_course_by_id(course_registration.course_id, depth=0) # Restrict the user from enrolling based on country access rules embargo_redirect = embargo_api.redirect_if_blocked( @@ -700,7 +700,7 @@ def billing_details(request): cart = Order.get_cart_for_user(request.user) cart_items = cart.orderitem_set.all().select_subclasses() - if getattr(cart, 'order_type') != OrderTypes.BUSINESS: + if cart.order_type != OrderTypes.BUSINESS: raise Http404('Page not found!') if request.method == "GET": @@ -845,7 +845,7 @@ def _show_receipt_json(order): 'unit_cost': item.unit_cost, 'line_cost': item.line_cost, 'line_desc': item.line_desc, - 'course_key': unicode(getattr(item, 'course_id')) + 'course_key': unicode(item.course_id) } for item in OrderItem.objects.filter(order=order).select_subclasses() ] @@ -868,7 +868,7 @@ def _show_receipt_html(request, order): shoppingcart_items = [] course_names_list = [] for order_item in order_items: - course_key = getattr(order_item, 'course_id') + course_key = order_item.course_id if course_key: course = get_course_by_id(course_key, depth=0) shoppingcart_items.append((order_item, course)) @@ -878,12 +878,12 @@ def _show_receipt_html(request, order): any_refunds = any(i.status == "refunded" for i in order_items) receipt_template = 'shoppingcart/receipt.html' __, instructions = order.generate_receipt_instructions() - order_type = getattr(order, 'order_type') + order_type = order.order_type recipient_list = [] total_registration_codes = None reg_code_info_list = [] - recipient_list.append(getattr(order.user, 'email')) + recipient_list.append(order.user.email) if order_type == OrderTypes.BUSINESS: if order.company_contact_email: recipient_list.append(order.company_contact_email) diff --git a/lms/lib/xblock/test/test_mixin.py b/lms/lib/xblock/test/test_mixin.py index cebf7d7a8e..64360c4a5f 100644 --- a/lms/lib/xblock/test/test_mixin.py +++ b/lms/lib/xblock/test/test_mixin.py @@ -243,7 +243,7 @@ def ddt_named(parent, child): Helper to get more readable dynamically-generated test names from ddt. """ args = RenamedTuple([parent, child]) - setattr(args, '__name__', 'parent_{}_child_{}'.format(parent, child)) + args.__name__ = 'parent_{}_child_{}'.format(parent, child) # pylint: disable=attribute-defined-outside-init return args diff --git a/openedx/core/djangoapps/credit/tasks.py b/openedx/core/djangoapps/credit/tasks.py index 1c0ba2468d..654aaee98f 100644 --- a/openedx/core/djangoapps/credit/tasks.py +++ b/openedx/core/djangoapps/credit/tasks.py @@ -106,7 +106,7 @@ def _get_min_grade_requirement(course_key): "name": "grade", "display_name": "Minimum Grade", "criteria": { - "min_grade": getattr(course, "minimum_grade_credit") + "min_grade": course.minimum_grade_credit }, } ] diff --git a/scripts/all-tests.sh b/scripts/all-tests.sh index b0c49f4c63..a84f288f78 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=5650 +export PYLINT_THRESHOLD=5555 export JSHINT_THRESHOLD=9080 doCheckVars() {