From 52dd883a3c51757dbabd89a77f46aea5889c6712 Mon Sep 17 00:00:00 2001 From: Eugene Dyudyunov Date: Fri, 13 May 2022 15:48:42 +0300 Subject: [PATCH] refactor: delete now unused FutureCourseWaffleFlag (#30367) Remove temporary FutureCourseWaffleFlag class; Update ora2 and edx-toggles to versions cleaned from the LegacyWaffle* classes; Replace `override_flag`s with `override_waffle_flag`; Replace `override_switch`s with `override_waffle_switch` (where it's possible). --- .../contentstore/tests/test_contentstore.py | 36 +++++------ .../contentstore/views/tests/test_videos.py | 5 +- lms/djangoapps/commerce/tests/test_utils.py | 3 + lms/djangoapps/course_api/tests/test_views.py | 10 +-- lms/djangoapps/courseware/tests/test_about.py | 15 ++--- .../courseware/tests/test_date_summary.py | 16 ++--- .../courseware/tests/test_video_mongo.py | 33 +++++----- lms/djangoapps/teams/toggles.py | 2 +- .../verify_student/tests/test_views.py | 3 + .../schedules/tests/test_resolvers.py | 17 +++-- .../djangoapps/waffle_utils/__future__.py | 18 ------ .../waffle_utils/tests/test_init.py | 64 ++++--------------- requirements/edx/base.in | 2 +- requirements/edx/base.txt | 4 +- requirements/edx/development.txt | 4 +- requirements/edx/testing.txt | 4 +- 16 files changed, 93 insertions(+), 143 deletions(-) delete mode 100644 openedx/core/djangoapps/waffle_utils/__future__.py diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index 03855403a9..3f89bbe450 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -16,6 +16,7 @@ from django.conf import settings from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user from django.test import TestCase from django.test.utils import override_settings +from edx_toggles.toggles.testutils import override_waffle_switch from edxval.api import create_video, get_videos_for_course from fs.osfs import OSFS from lxml import etree @@ -23,7 +24,21 @@ from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import AssetKey, CourseKey, UsageKey from opaque_keys.edx.locations import CourseLocator from path import Path as path -from waffle.testutils import override_switch +from xmodule.capa_module import ProblemBlock +from xmodule.contentstore.content import StaticContent +from xmodule.contentstore.django import contentstore +from xmodule.contentstore.utils import empty_asset_trashcan, restore_asset_from_trashcan +from xmodule.course_module import CourseBlock, Textbook +from xmodule.exceptions import InvalidVersionError +from xmodule.modulestore import ModuleStoreEnum +from xmodule.modulestore.django import modulestore +from xmodule.modulestore.exceptions import ItemNotFoundError +from xmodule.modulestore.inheritance import own_metadata +from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls +from xmodule.modulestore.xml_exporter import export_course_to_xml +from xmodule.modulestore.xml_importer import import_course_from_xml, perform_xlint +from xmodule.seq_module import SequenceBlock +from xmodule.video_module import VideoBlock from cms.djangoapps.contentstore.config import waffle from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient, CourseTestCase, get_url, parse_json @@ -36,21 +51,6 @@ from common.djangoapps.student.models import CourseEnrollment from common.djangoapps.student.roles import CourseCreatorRole, CourseInstructorRole from openedx.core.djangoapps.django_comment_common.utils import are_permissions_roles_seeded from openedx.core.lib.tempdir import mkdtemp_clean -from xmodule.capa_module import ProblemBlock # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.contentstore.content import StaticContent # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.contentstore.django import contentstore # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.contentstore.utils import empty_asset_trashcan, restore_asset_from_trashcan # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.course_module import CourseBlock, Textbook # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.exceptions import InvalidVersionError # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore.exceptions import ItemNotFoundError # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore.inheritance import own_metadata # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore.xml_exporter import export_course_to_xml # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore.xml_importer import import_course_from_xml, perform_xlint # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.seq_module import SequenceBlock # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.video_module import VideoBlock # lint-amnesty, pylint: disable=wrong-import-order TEST_DATA_CONTENTSTORE = copy.deepcopy(settings.CONTENTSTORE) TEST_DATA_CONTENTSTORE['DOC_STORE_CONFIG']['db'] = 'test_xcontent_%s' % uuid4().hex @@ -1055,7 +1055,7 @@ class MiscCourseTests(ContentStoreTestCase): resp = self.client.get_html('/c4x/InvalidOrg/InvalidCourse/asset/invalid.png') self.assertEqual(resp.status_code, 404) - @override_switch(waffle.ENABLE_ACCESSIBILITY_POLICY_PAGE.name, active=False) + @override_waffle_switch(waffle.ENABLE_ACCESSIBILITY_POLICY_PAGE, active=False) def test_disabled_accessibility_page(self): """ Test that accessibility page returns 404 when waffle switch is disabled @@ -2189,7 +2189,7 @@ class EntryPageTestCase(TestCase): # Logout redirects. self._test_page("/logout", 200) - @override_switch(waffle.ENABLE_ACCESSIBILITY_POLICY_PAGE.name, active=True) + @override_waffle_switch(waffle.ENABLE_ACCESSIBILITY_POLICY_PAGE, active=True) def test_accessibility(self): self._test_page('/accessibility') diff --git a/cms/djangoapps/contentstore/views/tests/test_videos.py b/cms/djangoapps/contentstore/views/tests/test_videos.py index 5b116094df..d07cdb56d3 100644 --- a/cms/djangoapps/contentstore/views/tests/test_videos.py +++ b/cms/djangoapps/contentstore/views/tests/test_videos.py @@ -26,7 +26,6 @@ from edxval.api import ( get_transcript_preferences, get_video_info ) -from waffle.testutils import override_flag from cms.djangoapps.contentstore.models import VideoUploadConfig from cms.djangoapps.contentstore.tests.utils import CourseTestCase @@ -541,7 +540,7 @@ class VideosHandlerTestCase(VideoUploadTestMixin, VideoUploadPostTestsMixin, Cou @override_settings(AWS_ACCESS_KEY_ID='test_key_id', AWS_SECRET_ACCESS_KEY='test_secret', AWS_SECURITY_TOKEN='token') @patch('boto.s3.key.Key') @patch('boto.s3.connection.S3Connection') - @override_flag(ENABLE_DEVSTACK_VIDEO_UPLOADS.name, active=True) + @override_waffle_flag(ENABLE_DEVSTACK_VIDEO_UPLOADS, active=True) def test_devstack_upload_connection(self, mock_conn, mock_key): files = [{'file_name': 'first.mp4', 'content_type': 'video/mp4'}] mock_key_instances = [ @@ -647,7 +646,7 @@ class VideosHandlerTestCase(VideoUploadTestMixin, VideoUploadPostTestsMixin, Cou expected_args = ('course_video_upload_token', self.test_token) with patch.object(WaffleFlagCourseOverrideModel, 'override_value', return_value=data['course_override']): - with override_flag(DEPRECATE_YOUTUBE.name, active=data['global_waffle']): + with override_waffle_flag(DEPRECATE_YOUTUBE, active=data['global_waffle']): response = self.client.post( self.url, json.dumps({'files': [file_data]}), diff --git a/lms/djangoapps/commerce/tests/test_utils.py b/lms/djangoapps/commerce/tests/test_utils.py index 80d80e3d2c..2b6a2d2f74 100644 --- a/lms/djangoapps/commerce/tests/test_utils.py +++ b/lms/djangoapps/commerce/tests/test_utils.py @@ -74,6 +74,9 @@ class EcommerceServiceTests(TestCase): is_not_enabled = EcommerceService().is_enabled(self.user) assert not is_not_enabled + # TODO: replace override_switch with override_waffle_switch when the + # DISABLE_ACCOUNT_ACTIVATION_REQUIREMENT_SWITCH will be defined as actual WaffleSwitch. Now + # we have only switch name defined in the settings @override_switch(settings.DISABLE_ACCOUNT_ACTIVATION_REQUIREMENT_SWITCH, active=True) def test_is_enabled_activation_requirement_disabled(self): """Verify that is_enabled() returns True when ecomm checkout is enabled. """ diff --git a/lms/djangoapps/course_api/tests/test_views.py b/lms/djangoapps/course_api/tests/test_views.py index 1606418bd2..eea5e4da07 100644 --- a/lms/djangoapps/course_api/tests/test_views.py +++ b/lms/djangoapps/course_api/tests/test_views.py @@ -5,19 +5,20 @@ Tests for Course API views. from datetime import datetime from hashlib import md5 from unittest import TestCase -import pytest + import ddt +import pytest from django.core.exceptions import ImproperlyConfigured from django.test import RequestFactory from django.test.utils import override_settings from django.urls import reverse from edx_django_utils.cache import RequestCache +from edx_toggles.toggles.testutils import override_waffle_switch from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.locator import LibraryLocator from search.tests.test_course_discovery import DemoCourse from search.tests.tests import TEST_INDEX_NAME from search.tests.utils import SearcherMixin -from waffle.testutils import override_switch from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory @@ -26,6 +27,7 @@ from common.djangoapps.course_modes.tests.factories import CourseModeFactory from common.djangoapps.student.auth import add_users from common.djangoapps.student.roles import CourseInstructorRole, CourseStaffRole from common.djangoapps.student.tests.factories import AdminFactory +from lms.djangoapps.course_api import USE_RATE_LIMIT_2_FOR_COURSE_LIST_API, USE_RATE_LIMIT_10_FOR_COURSE_LIST_API from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES from openedx.core.lib.api.view_utils import LazySequence from openedx.features.content_type_gating.models import ContentTypeGatingConfig @@ -138,14 +140,14 @@ class CourseListViewTestCase(CourseApiTestViewMixin, SharedModuleStoreTestCase): @ddt.data(('staff', False, 10), ('user', False, 2), ('unknown', True, None)) @ddt.unpack - @override_switch('course_list_api_rate_limit.rate_limit_2', active=True) + @override_waffle_switch(USE_RATE_LIMIT_2_FOR_COURSE_LIST_API, active=True) def test_throttle_rate_2(self, user_scope, throws_exception, expected_rate): """ Make sure throttle rate 2 is set correctly for different user scopes. """ self.assert_throttle_configured_correctly(user_scope, throws_exception, expected_rate) @ddt.data(('staff', False, 20), ('user', False, 10), ('unknown', True, None)) @ddt.unpack - @override_switch('course_list_api_rate_limit.rate_limit_10', active=True) + @override_waffle_switch(USE_RATE_LIMIT_10_FOR_COURSE_LIST_API, active=True) def test_throttle_rate_20(self, user_scope, throws_exception, expected_rate): """ Make sure throttle rate 20 is set correctly for different user scopes. """ self.assert_throttle_configured_correctly(user_scope, throws_exception, expected_rate) diff --git a/lms/djangoapps/courseware/tests/test_about.py b/lms/djangoapps/courseware/tests/test_about.py index cbe59e042c..bb02a59122 100644 --- a/lms/djangoapps/courseware/tests/test_about.py +++ b/lms/djangoapps/courseware/tests/test_about.py @@ -4,23 +4,22 @@ Test the about xblock import datetime - from unittest import mock from unittest.mock import patch + import ddt import pytz from django.conf import settings from django.test.utils import override_settings from django.urls import reverse -from edx_toggles.toggles.testutils import override_waffle_flag +from edx_toggles.toggles.testutils import override_waffle_flag, override_waffle_switch from milestones.tests.utils import MilestonesTestCaseMixin -from waffle.testutils import override_switch from xmodule.course_module import ( CATALOG_VISIBILITY_ABOUT, CATALOG_VISIBILITY_NONE, COURSE_VISIBILITY_PRIVATE, COURSE_VISIBILITY_PUBLIC, - COURSE_VISIBILITY_PUBLIC_OUTLINE + COURSE_VISIBILITY_PUBLIC_OUTLINE, ) from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory @@ -28,12 +27,12 @@ from xmodule.modulestore.tests.utils import TEST_DATA_DIR from xmodule.modulestore.xml_importer import import_course_from_xml from common.djangoapps.course_modes.models import CourseMode -from openedx.core.djangoapps.models.course_details import CourseDetails -from openedx.features.course_experience import COURSE_ENABLE_UNENROLLED_ACCESS_FLAG, course_home_url -from openedx.features.course_experience.waffle import ENABLE_COURSE_ABOUT_SIDEBAR_HTML from common.djangoapps.student.tests.factories import CourseEnrollmentAllowedFactory, UserFactory from common.djangoapps.track.tests import EventTrackingTestCase from common.djangoapps.util.milestones_helpers import get_prerequisite_courses_display, set_prerequisite_courses +from openedx.core.djangoapps.models.course_details import CourseDetails +from openedx.features.course_experience import COURSE_ENABLE_UNENROLLED_ACCESS_FLAG, course_home_url +from openedx.features.course_experience.waffle import ENABLE_COURSE_ABOUT_SIDEBAR_HTML from .helpers import LoginEnrollmentTestCase @@ -396,7 +395,7 @@ class AboutSidebarHTMLTestCase(SharedModuleStoreTestCase): ) @ddt.unpack def test_html_sidebar_enabled(self, itemfactory_display_name, itemfactory_data, waffle_switch_value): - with override_switch(ENABLE_COURSE_ABOUT_SIDEBAR_HTML.name, active=waffle_switch_value): + with override_waffle_switch(ENABLE_COURSE_ABOUT_SIDEBAR_HTML, active=waffle_switch_value): if itemfactory_display_name: ItemFactory.create( category="about", diff --git a/lms/djangoapps/courseware/tests/test_date_summary.py b/lms/djangoapps/courseware/tests/test_date_summary.py index 741a02bea4..b428859c17 100644 --- a/lms/djangoapps/courseware/tests/test_date_summary.py +++ b/lms/djangoapps/courseware/tests/test_date_summary.py @@ -7,11 +7,10 @@ from unittest.mock import patch import crum import ddt -import waffle # lint-amnesty, pylint: disable=invalid-django-waffle-import from django.conf import settings from django.test import RequestFactory from django.urls import reverse -from edx_toggles.toggles.testutils import override_waffle_flag +from edx_toggles.toggles.testutils import override_waffle_flag, override_waffle_switch from freezegun import freeze_time from pytz import utc from xmodule.modulestore import ModuleStoreEnum @@ -20,6 +19,8 @@ from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from common.djangoapps.course_modes.models import CourseMode from common.djangoapps.course_modes.tests.factories import CourseModeFactory +from common.djangoapps.student.tests.factories import TEST_PASSWORD, CourseEnrollmentFactory, UserFactory +from lms.djangoapps.certificates.config import AUTO_CERTIFICATE_GENERATION from lms.djangoapps.commerce.models import CommerceConfiguration from lms.djangoapps.courseware.courses import get_course_date_blocks from lms.djangoapps.courseware.date_summary import ( @@ -30,12 +31,12 @@ from lms.djangoapps.courseware.date_summary import ( CourseStartDate, TodaysDate, VerificationDeadlineDate, - VerifiedUpgradeDeadlineDate + VerifiedUpgradeDeadlineDate, ) from lms.djangoapps.courseware.models import ( CourseDynamicUpgradeDeadlineConfiguration, DynamicUpgradeDeadlineConfiguration, - OrgDynamicUpgradeDeadlineConfiguration + OrgDynamicUpgradeDeadlineConfiguration, ) from lms.djangoapps.verify_student.models import VerificationDeadline from lms.djangoapps.verify_student.services import IDVerificationService @@ -45,7 +46,6 @@ from openedx.core.djangoapps.content.course_overviews.tests.factories import Cou from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration from openedx.features.course_duration_limits.models import CourseDurationLimitConfig from openedx.features.course_experience import RELATIVE_DATES_FLAG -from common.djangoapps.student.tests.factories import TEST_PASSWORD, CourseEnrollmentFactory, UserFactory @ddt.ddt @@ -477,7 +477,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): assert block.link == f'{configuration.basket_checkout_page}?sku={sku}' ## CertificateAvailableDate - @waffle.testutils.override_switch('certificates.auto_certificate_generation', True) + @override_waffle_switch(AUTO_CERTIFICATE_GENERATION, True) def test_no_certificate_available_date(self): course = create_course_run(days_till_start=-1) user = create_user() @@ -487,7 +487,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): assert not block.is_allowed ## CertificateAvailableDate - @waffle.testutils.override_switch('certificates.auto_certificate_generation', True) + @override_waffle_switch(AUTO_CERTIFICATE_GENERATION, True) def test_no_certificate_available_date_for_self_paced(self): course = create_self_paced_course_run() verified_user = create_user() @@ -521,7 +521,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): assert not block.is_allowed assert block.date is not None - @waffle.testutils.override_switch('certificates.auto_certificate_generation', True) + @override_waffle_switch(AUTO_CERTIFICATE_GENERATION, True) def test_certificate_available_date_defined(self): course = create_course_run() audit_user = create_user() diff --git a/lms/djangoapps/courseware/tests/test_video_mongo.py b/lms/djangoapps/courseware/tests/test_video_mongo.py index 764d60ed4a..129471f92e 100644 --- a/lms/djangoapps/courseware/tests/test_video_mongo.py +++ b/lms/djangoapps/courseware/tests/test_video_mongo.py @@ -7,15 +7,17 @@ import json import shutil from collections import OrderedDict from tempfile import mkdtemp -from uuid import uuid4 from unittest.mock import MagicMock, Mock, patch -import pytest +from uuid import uuid4 + import ddt +import pytest from django.conf import settings from django.core.files import File from django.core.files.base import ContentFile from django.test import TestCase from django.test.utils import override_settings +from edx_toggles.toggles.testutils import override_waffle_flag from edxval.api import ( ValCannotCreateError, ValVideoNotFoundError, @@ -25,31 +27,30 @@ from edxval.api import ( create_video_transcript, get_video_info, get_video_transcript, - get_video_transcript_data + get_video_transcript_data, ) from edxval.utils import create_file_in_fs from fs.osfs import OSFS from fs.path import combine from lxml import etree from path import Path as path -from waffle.testutils import override_flag +from xmodule.contentstore.content import StaticContent +from xmodule.exceptions import NotFoundError +from xmodule.modulestore import ModuleStoreEnum +from xmodule.modulestore.inheritance import own_metadata +from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_MODULESTORE, TEST_DATA_SPLIT_MODULESTORE +from xmodule.tests.test_import import DummySystem +from xmodule.tests.test_video import VideoBlockTestBase +from xmodule.video_module import VideoBlock, bumper_utils, video_utils +from xmodule.video_module.transcripts_utils import Transcript, save_to_store, subs_filename +from xmodule.video_module.video_module import EXPORT_IMPORT_COURSE_DIR, EXPORT_IMPORT_STATIC_DIR +from xmodule.x_module import PUBLIC_VIEW, STUDENT_VIEW from common.djangoapps.xblock_django.constants import ATTR_KEY_REQUEST_COUNTRY_CODE from lms.djangoapps.courseware.tests.helpers import get_context_dict_from_string from openedx.core.djangoapps.video_pipeline.config.waffle import DEPRECATE_YOUTUBE from openedx.core.djangoapps.waffle_utils.models import WaffleFlagCourseOverrideModel from openedx.core.djangolib.testing.utils import CacheIsolationTestCase -from xmodule.contentstore.content import StaticContent # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.exceptions import NotFoundError # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore.inheritance import own_metadata # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_MODULESTORE, TEST_DATA_SPLIT_MODULESTORE # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.tests.test_import import DummySystem # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.tests.test_video import VideoBlockTestBase # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.video_module import VideoBlock, bumper_utils, video_utils # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.video_module.transcripts_utils import Transcript, save_to_store, subs_filename # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.video_module.video_module import EXPORT_IMPORT_COURSE_DIR, EXPORT_IMPORT_STATIC_DIR # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.x_module import PUBLIC_VIEW, STUDENT_VIEW # lint-amnesty, pylint: disable=wrong-import-order from .test_video_handlers import BaseTestVideoXBlock, TestVideo from .test_video_xml import SOURCE_XML @@ -1178,7 +1179,7 @@ class TestGetHtmlMethod(BaseTestVideoXBlock): data['youtube'] ) with patch.object(WaffleFlagCourseOverrideModel, 'override_value', return_value=data['course_override']): - with override_flag(DEPRECATE_YOUTUBE.name, active=data['waffle_enabled']): + with override_waffle_flag(DEPRECATE_YOUTUBE, active=data['waffle_enabled']): self.initialize_block(data=video_xml, metadata=metadata) context = self.item_descriptor.render(STUDENT_VIEW).content assert '"prioritizeHls": {}'.format(data['result']) in context diff --git a/lms/djangoapps/teams/toggles.py b/lms/djangoapps/teams/toggles.py index 54d492b210..f8cc5ace55 100644 --- a/lms/djangoapps/teams/toggles.py +++ b/lms/djangoapps/teams/toggles.py @@ -34,7 +34,7 @@ def are_team_submissions_enabled(course_key): ): return True - # TODO: this behaviour differs from edx-ora2, where the LegacyWaffleSwitch overrides the setting. + # TODO: this behaviour differs from edx-ora2, where the WaffleSwitch overrides the setting. # https://github.com/edx/edx-ora2/blob/ac502d8301cb987c9885aaefbaeddaf456c13fb9/openassessment/xblock/config_mixin.py#L96 if TEAM_SUBMISSIONS_FEATURE.is_enabled(): diff --git a/lms/djangoapps/verify_student/tests/test_views.py b/lms/djangoapps/verify_student/tests/test_views.py index d65881d2e9..c5809ec91b 100644 --- a/lms/djangoapps/verify_student/tests/test_views.py +++ b/lms/djangoapps/verify_student/tests/test_views.py @@ -624,6 +624,9 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin, Tes PayAndVerifyView.WEBCAM_REQ, ]) + # TODO: replace override_switch with override_waffle_switch when the + # DISABLE_ACCOUNT_ACTIVATION_REQUIREMENT_SWITCH will be defined as actual WaffleSwitch. Now + # we have only switch name defined in the settings @override_switch(settings.DISABLE_ACCOUNT_ACTIVATION_REQUIREMENT_SWITCH, active=True) @ddt.data("verify_student_start_flow", "verify_student_begin_flow") def test_disable_account_activation_requirement_flag_active(self, payment_flow): diff --git a/openedx/core/djangoapps/schedules/tests/test_resolvers.py b/openedx/core/djangoapps/schedules/tests/test_resolvers.py index 4e177491f4..83b98e5b76 100644 --- a/openedx/core/djangoapps/schedules/tests/test_resolvers.py +++ b/openedx/core/djangoapps/schedules/tests/test_resolvers.py @@ -12,26 +12,29 @@ import pytz from django.test import TestCase from django.test.client import RequestFactory from django.test.utils import override_settings +from edx_toggles.toggles.testutils import override_waffle_switch from testfixtures import LogCapture -from waffle.testutils import override_switch +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from common.djangoapps.student.models import CourseEnrollment from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory from lms.djangoapps.experiments.testutils import override_experiment_waffle_flag from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory -from openedx.core.djangoapps.schedules.config import _EXTERNAL_COURSE_UPDATES_FLAG +from openedx.core.djangoapps.schedules.config import ( + _EXTERNAL_COURSE_UPDATES_FLAG, + COURSE_UPDATE_SHOW_UNSUBSCRIBE_WAFFLE_SWITCH, +) from openedx.core.djangoapps.schedules.models import Schedule from openedx.core.djangoapps.schedules.resolvers import ( LOG, BinnedSchedulesBaseResolver, CourseNextSectionUpdate, - CourseUpdateResolver + CourseUpdateResolver, ) from openedx.core.djangoapps.schedules.tests.factories import ScheduleConfigFactory from openedx.core.djangoapps.site_configuration.tests.factories import SiteConfigurationFactory, SiteFactory from openedx.core.djangolib.testing.utils import CacheIsolationMixin, skip_unless_lms -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory # lint-amnesty, pylint: disable=wrong-import-order class SchedulesResolverTestMixin(CacheIsolationMixin): @@ -183,7 +186,7 @@ class TestCourseUpdateResolver(SchedulesResolverTestMixin, ModuleStoreTestCase): } assert schedules == [(self.user, None, expected_context)] - @override_switch('schedules.course_update_show_unsubscribe', True) + @override_waffle_switch(COURSE_UPDATE_SHOW_UNSUBSCRIBE_WAFFLE_SWITCH, True) def test_schedule_context_show_unsubscribe(self): resolver = self.create_resolver() schedules = list(resolver.schedules_for_bin()) @@ -274,7 +277,7 @@ class TestCourseNextSectionUpdateResolver(SchedulesResolverTestMixin, ModuleStor } assert schedules == [(self.user, None, expected_context)] - @override_switch('schedules.course_update_show_unsubscribe', True) + @override_waffle_switch(COURSE_UPDATE_SHOW_UNSUBSCRIBE_WAFFLE_SWITCH, True) def test_schedule_context_show_unsubscribe(self): resolver = self.create_resolver() schedules = list(resolver.get_schedules()) diff --git a/openedx/core/djangoapps/waffle_utils/__future__.py b/openedx/core/djangoapps/waffle_utils/__future__.py deleted file mode 100644 index 38497ab5b0..0000000000 --- a/openedx/core/djangoapps/waffle_utils/__future__.py +++ /dev/null @@ -1,18 +0,0 @@ -""" -Temporary module to switch from the LegacyWaffle* classes. -""" -from edx_django_utils.monitoring import set_custom_attribute - -from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag - - -class FutureCourseWaffleFlag(CourseWaffleFlag): - """ - Temporary class to support ORA transition to the modern CourseWaffleFlag. - """ - def __init__(self, name, module_name, log_prefix=""): - super().__init__(name, module_name=module_name, log_prefix=log_prefix) - set_custom_attribute( - "deprecated_legacy_waffle_class", - f"{self.__class__.__module__}.{self.__class__.__name__}[{self.name}]" - ) diff --git a/openedx/core/djangoapps/waffle_utils/tests/test_init.py b/openedx/core/djangoapps/waffle_utils/tests/test_init.py index aa0925d68b..57f3176737 100644 --- a/openedx/core/djangoapps/waffle_utils/tests/test_init.py +++ b/openedx/core/djangoapps/waffle_utils/tests/test_init.py @@ -9,11 +9,10 @@ import crum import ddt from django.test.client import RequestFactory from edx_django_utils.cache import RequestCache +from edx_toggles.toggles.testutils import override_waffle_flag from opaque_keys.edx.keys import CourseKey -from waffle.testutils import override_flag from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag -from openedx.core.djangoapps.waffle_utils.__future__ import FutureCourseWaffleFlag from openedx.core.djangoapps.waffle_utils.models import WaffleFlagCourseOverrideModel, WaffleFlagOrgOverrideModel from openedx.core.djangolib.testing.utils import CacheIsolationTestCase @@ -54,8 +53,8 @@ class TestCourseWaffleFlag(CacheIsolationTestCase): """ Tests various combinations of a flag being set in waffle and overridden for a course. """ - with patch.object(WaffleFlagCourseOverrideModel, 'override_value', return_value=course_override): - with override_flag(self.NAMESPACED_FLAG_NAME, active=waffle_enabled): + with override_waffle_flag(self.TEST_COURSE_FLAG, active=waffle_enabled): + with patch.object(WaffleFlagCourseOverrideModel, 'override_value', return_value=course_override): # check twice to test that the result is properly cached assert self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_KEY) == result assert self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_KEY) == result @@ -65,52 +64,11 @@ class TestCourseWaffleFlag(CacheIsolationTestCase): self.NAMESPACED_FLAG_NAME, self.TEST_COURSE_KEY ) - - # check flag for a second course - if course_override == WaffleFlagCourseOverrideModel.ALL_CHOICES.unset: - # When course override wasn't set for the first course, the second course will get the same - # cached value from waffle. + # Check flag for a second course. + # This should be the same cached value as for overriden flag. assert self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_2_KEY) == waffle_enabled - else: - # When course override was set for the first course, it should not apply to the second - # course which should get the default value of False. - assert self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_2_KEY) is False - - @ddt.data( - (False, WaffleFlagCourseOverrideModel.ALL_CHOICES.on, True), - (True, WaffleFlagCourseOverrideModel.ALL_CHOICES.off, False), - (True, WaffleFlagCourseOverrideModel.ALL_CHOICES.unset, True), - (False, WaffleFlagCourseOverrideModel.ALL_CHOICES.unset, False), - ) - @ddt.unpack - def test_future_course_waffle_flag(self, waffle_enabled, course_override, result): - """ - Tests various combinations of a __future__ flag being set in waffle and overridden for a course. - """ - test_future_course_flag = FutureCourseWaffleFlag( - self.NAMESPACED_FLAG_NAME, __name__ - ) - with patch.object(WaffleFlagCourseOverrideModel, 'override_value', return_value=course_override): - with override_flag(self.NAMESPACED_FLAG_NAME, active=waffle_enabled): - # check twice to test that the result is properly cached - assert test_future_course_flag.is_enabled(self.TEST_COURSE_KEY) == result - assert test_future_course_flag.is_enabled(self.TEST_COURSE_KEY) == result - # result is cached, so override check should happen only once - # pylint: disable=no-member - WaffleFlagCourseOverrideModel.override_value.assert_called_once_with( - self.NAMESPACED_FLAG_NAME, - self.TEST_COURSE_KEY - ) - - # check flag for a second course - if course_override == WaffleFlagCourseOverrideModel.ALL_CHOICES.unset: - # When course override wasn't set for the first course, the second course will get the same - # cached value from waffle. - assert test_future_course_flag.is_enabled(self.TEST_COURSE_2_KEY) == waffle_enabled - else: - # When course override was set for the first course, it should not apply to the second - # course which should get the default value of False. - assert test_future_course_flag.is_enabled(self.TEST_COURSE_2_KEY) is False + # Check the default value for the second course after the cache was restored + assert self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_2_KEY) is False @ddt.data( (False, WaffleFlagOrgOverrideModel.ALL_CHOICES.unset, False), @@ -140,7 +98,7 @@ class TestCourseWaffleFlag(CacheIsolationTestCase): enabled=True ) # Both course keys should match the org-level override. - with override_flag(self.NAMESPACED_FLAG_NAME, active=waffle_enabled): + with override_waffle_flag(self.TEST_COURSE_FLAG, active=waffle_enabled): assert self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_KEY) == is_enabled assert self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_2_KEY) == is_enabled @@ -170,7 +128,7 @@ class TestCourseWaffleFlag(CacheIsolationTestCase): enabled=True ) # Org doesn't match the course key, so should never be enabled. - with override_flag(self.NAMESPACED_FLAG_NAME, active=waffle_enabled): + with override_waffle_flag(self.TEST_COURSE_FLAG, active=waffle_enabled): assert self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_3_KEY) == is_enabled @ddt.data( @@ -226,7 +184,7 @@ class TestCourseWaffleFlag(CacheIsolationTestCase): note='', enabled=True ) - with override_flag(self.NAMESPACED_FLAG_NAME, active=waffle_enabled): + with override_waffle_flag(self.TEST_COURSE_FLAG, active=waffle_enabled): assert self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_KEY) == is_enabled def test_undefined_waffle_flag(self): @@ -265,5 +223,5 @@ class TestCourseWaffleFlag(CacheIsolationTestCase): crum.set_current_request(None) test_course_flag = CourseWaffleFlag(self.NAMESPACED_FLAG_NAME, __name__) - with override_flag(self.NAMESPACED_FLAG_NAME, active=True): + with override_waffle_flag(self.TEST_COURSE_FLAG, active=True): assert test_course_flag.is_enabled(self.TEST_COURSE_KEY) is True diff --git a/requirements/edx/base.in b/requirements/edx/base.in index e8a2551097..5e55fc7c08 100644 --- a/requirements/edx/base.in +++ b/requirements/edx/base.in @@ -121,7 +121,7 @@ oauthlib # OAuth specification support for authentica openedx-calc # Library supporting mathematical calculations for Open edX openedx-events # Open edX Events from Hooks Extension Framework (OEP-50) openedx-filters # Open edX Filters from Hooks Extension Framework (OEP-50) -ora2>=4.3.0 +ora2>=4.4.0 piexif # Exif image metadata manipulation, used in the profile_images app Pillow # Image manipulation library; used for course assets, profile images, invoice PDFs, etc. py2neo # Driver for converting Python modulestore structures to Neo4j's schema (for Coursegraph). diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index b6bba4c76d..0350462c65 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -523,7 +523,7 @@ edx-submissions==3.5.1 # ora2 edx-tincan-py35==1.0.0 # via edx-enterprise -edx-toggles==4.3.1 +edx-toggles==5.0.0 # via # -r requirements/edx/base.in # edx-completion @@ -737,7 +737,7 @@ openedx-filters==0.6.2 # via # -r requirements/edx/base.in # lti-consumer-xblock -ora2==4.3.0 +ora2==4.4.0 # via -r requirements/edx/base.in packaging==21.3 # via diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index 2518fa09c6..4aae51721e 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -646,7 +646,7 @@ edx-tincan-py35==1.0.0 # via # -r requirements/edx/testing.txt # edx-enterprise -edx-toggles==4.3.1 +edx-toggles==5.0.0 # via # -r requirements/edx/testing.txt # edx-completion @@ -966,7 +966,7 @@ openedx-filters==0.6.2 # via # -r requirements/edx/testing.txt # lti-consumer-xblock -ora2==4.3.0 +ora2==4.4.0 # via -r requirements/edx/testing.txt packaging==21.3 # via diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index b16ea1c428..9bc50891fa 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -628,7 +628,7 @@ edx-tincan-py35==1.0.0 # via # -r requirements/edx/base.txt # edx-enterprise -edx-toggles==4.3.1 +edx-toggles==5.0.0 # via # -r requirements/edx/base.txt # edx-completion @@ -917,7 +917,7 @@ openedx-filters==0.6.2 # via # -r requirements/edx/base.txt # lti-consumer-xblock -ora2==4.3.0 +ora2==4.4.0 # via -r requirements/edx/base.txt packaging==21.3 # via