Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
name: ${{ matrix.shard_name }}(py=${{ matrix.python-version }},dj=${{ matrix.django-version }},mongo=${{ matrix.mongo-version }})
runs-on: ${{ matrix.os-version }}
strategy:
fail-fast: false
matrix:
python-version:
- "3.11"
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/cms_user_tasks/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ def test_email_sent_with_olx_validations_with_default_config(self):
msg = mail.outbox[0]

# Verify olx validation is not enabled out of the box.
self.assertFalse(settings.FEATURES.get('ENABLE_COURSE_OLX_VALIDATION'))
self.assertFalse(settings.ENABLE_COURSE_OLX_VALIDATION)
self.assertEqual(len(mail.outbox), 1)
self.assert_msg_subject(msg)
self.assert_msg_body_fragments(msg, body_fragments)
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/courseware_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def indexing_is_enabled():
"""
Checks to see if the indexing feature is enabled
"""
return settings.FEATURES.get('ENABLE_COURSEWARE_INDEX', False)
return settings.ENABLE_COURSEWARE_INDEX


class SearchIndexingError(Exception):
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/exams.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def register_exams(course_key):
Likewise, if formerly registered exams are not included in the payload they will
be marked inactive by the exam service.
"""
if not settings.FEATURES.get('ENABLE_SPECIAL_EXAMS') or not exams_ida_enabled(course_key):
if not settings.ENABLE_SPECIAL_EXAMS or not exams_ida_enabled(course_key):
# if feature is not enabled then do a quick exit
return

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def handle(self, *args, **options): # pylint: disable=too-many-statements
all_courses = modulestore().get_courses()

inclusion_date = datetime.strptime(
settings.FEATURES.get('COURSEWARE_SEARCH_INCLUSION_DATE', '2020-01-01'),
settings.COURSEWARE_SEARCH_INCLUSION_DATE or '2020-01-01',
'%Y-%m-%d'
)

Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/proctoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def register_special_exams(course_key):
subsystem. Likewise, if formerly registered exams are unmarked, then those
registered exams are marked as inactive
"""
if not settings.FEATURES.get('ENABLE_SPECIAL_EXAMS'):
if not settings.ENABLE_SPECIAL_EXAMS:
# if feature is not enabled then do a quick exit
return

Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/rest_api/v1/views/grading.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def get(self, request: Request, course_id: str):
self.permission_denied(request)

with modulestore().bulk_operations(course_key):
credit_eligibility_enabled = settings.FEATURES.get("ENABLE_CREDIT_ELIGIBILITY", False)
credit_eligibility_enabled = settings.ENABLE_CREDIT_ELIGIBILITY
show_credit_eligibility = is_credit_course(course_key) and credit_eligibility_enabled

grading_context = get_course_grading(course_key)
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/rest_api/v1/views/home.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def get(self, request: Request):
),
'studio_name': settings.STUDIO_NAME,
'studio_short_name': settings.STUDIO_SHORT_NAME,
'studio_request_email': settings.FEATURES.get('STUDIO_REQUEST_EMAIL', ''),
'studio_request_email': settings.STUDIO_REQUEST_EMAIL,
'tech_support_email': settings.TECH_SUPPORT_EMAIL,
'platform_name': settings.PLATFORM_NAME,
'user_is_active': request.user.is_active,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ def get(self, request: Request, course_id: str) -> Response:

course_block = modulestore().get_course(course_key)
advanced_dict = CourseMetadata.fetch(course_block)
if settings.FEATURES.get('DISABLE_MOBILE_COURSE_AVAILABLE', False):
if settings.DISABLE_MOBILE_COURSE_AVAILABLE:
advanced_dict.get('mobile_available')['deprecated'] = True

proctoring_errors = CourseMetadata.validate_proctoring_settings(course_block, advanced_dict, request.user)
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/rest_api/v1/views/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def get(self, request: Request, course_id: str):
'course_display_name': course_block.display_name,
'course_display_name_with_default': course_block.display_name_with_default,
'platform_name': settings.PLATFORM_NAME,
'licensing_enabled': settings.FEATURES.get("LICENSING", False),
'licensing_enabled': settings.LICENSING,
})

serializer = CourseSettingsSerializer(settings_context)
Expand Down
6 changes: 3 additions & 3 deletions cms/djangoapps/contentstore/tests/test_course_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ def test_marketing_site_fetch(self):
self.assertNotContains(response, "Course Banner Image")
self.assertNotContains(response, "Course Video Thumbnail Image")

@unittest.skipUnless(settings.FEATURES.get('ENTRANCE_EXAMS', False), True)
@unittest.skipUnless(settings.ENTRANCE_EXAMS, True)
def test_entrance_exam_created_updated_and_deleted_successfully(self):
"""
This tests both of the entrance exam settings and the `any_unfulfilled_milestones` helper.
Expand Down Expand Up @@ -503,7 +503,7 @@ def test_entrance_exam_created_updated_and_deleted_successfully(self):
self.assertFalse(milestones_helpers.any_unfulfilled_milestones(self.course.id, self.user.id),
msg='The entrance exam should not be required anymore')

@unittest.skipUnless(settings.FEATURES.get('ENTRANCE_EXAMS', False), True)
@unittest.skipUnless(settings.ENTRANCE_EXAMS, True)
def test_entrance_exam_store_default_min_score(self):
"""
test that creating an entrance exam should store the default value, if key missing in json request
Expand Down Expand Up @@ -557,7 +557,7 @@ def test_entrance_exam_store_default_min_score(self):
self.assertTrue(course.entrance_exam_enabled)
self.assertEqual(course.entrance_exam_minimum_score_pct, .5)

@unittest.skipUnless(settings.FEATURES.get('ENTRANCE_EXAMS', False), True)
@unittest.skipUnless(settings.ENTRANCE_EXAMS, True)
@mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_PREREQUISITE_COURSES': True})
def test_entrance_after_changing_other_setting(self):
"""
Expand Down
22 changes: 5 additions & 17 deletions cms/djangoapps/contentstore/toggles.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""
CMS feature toggles.
"""
from django.conf import settings
from edx_toggles.toggles import SettingToggle, WaffleFlag

from openedx.core.djangoapps.content.search import api as search_api
from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag

Expand Down Expand Up @@ -409,25 +411,11 @@ def default_enable_flexible_peer_openassessments(course_key):
return DEFAULT_ENABLE_FLEXIBLE_PEER_OPENASSESSMENTS.is_enabled(course_key)


# .. toggle_name: ENABLE_CONTENT_LIBRARIES
# .. toggle_implementation: SettingToggle
# .. toggle_default: True
# .. toggle_description: Enables use of the legacy and v2 libraries waffle flags.
# Note that legacy content libraries are only supported in courses using split mongo.
# .. toggle_use_cases: open_edx
# .. toggle_creation_date: 2015-03-06
# .. toggle_target_removal_date: 2025-04-09
# .. toggle_warning: This flag is deprecated in Sumac, and will be removed in favor of the disable_legacy_libraries and
# disable_new_libraries waffle flags.
ENABLE_CONTENT_LIBRARIES = SettingToggle(
"ENABLE_CONTENT_LIBRARIES", default=True, module_name=__name__
)

# .. toggle_name: contentstore.new_studio_mfe.disable_legacy_libraries
# .. toggle_implementation: WaffleFlag
# .. toggle_default: False
# .. toggle_description: Hides legacy (v1) Libraries tab in Authoring MFE.
# This toggle interacts with ENABLE_CONTENT_LIBRARIES toggle: if this is disabled, then legacy libraries are also
# This toggle interacts with ENABLE_CONTENT_LIBRARIES setting: if this is disabled, then legacy libraries are also
# disabled.
# .. toggle_use_cases: open_edx
# .. toggle_creation_date: 2024-10-02
Expand All @@ -446,7 +434,7 @@ def libraries_v1_enabled():
Returns a boolean if Libraries V2 is enabled in the new Studio Home.
"""
return (
ENABLE_CONTENT_LIBRARIES.is_enabled() and
settings.ENABLE_CONTENT_LIBRARIES and
not DISABLE_LEGACY_LIBRARIES.is_enabled()
)

Expand Down Expand Up @@ -476,7 +464,7 @@ def libraries_v2_enabled():
Requires the ENABLE_CONTENT_LIBRARIES feature flag to be enabled, plus Meilisearch.
"""
return (
ENABLE_CONTENT_LIBRARIES.is_enabled() and
settings.ENABLE_CONTENT_LIBRARIES and
search_api.is_meilisearch_enabled() and
not DISABLE_NEW_LIBRARIES.is_enabled()
)
Expand Down
28 changes: 14 additions & 14 deletions cms/djangoapps/contentstore/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ def course_import_olx_validation_is_enabled():
"""
Check if course olx validation is enabled on course import.
"""
return settings.FEATURES.get('ENABLE_COURSE_OLX_VALIDATION', False)
return settings.ENABLE_COURSE_OLX_VALIDATION


# pylint: disable=invalid-name
Expand Down Expand Up @@ -1409,33 +1409,33 @@ def get_course_settings(request, course_key, course_block):

from .views.course import get_courses_accessible_to_user, _process_courses_list

credit_eligibility_enabled = settings.FEATURES.get('ENABLE_CREDIT_ELIGIBILITY', False)
credit_eligibility_enabled = settings.ENABLE_CREDIT_ELIGIBILITY
upload_asset_url = reverse_course_url('assets_handler', course_key)

# see if the ORG of this course can be attributed to a defined configuration . In that case, the
# course about page should be editable in Studio
publisher_enabled = configuration_helpers.get_value_for_org(
course_block.location.org,
'ENABLE_PUBLISHER',
settings.FEATURES.get('ENABLE_PUBLISHER', False)
settings.ENABLE_PUBLISHER
)
marketing_enabled = configuration_helpers.get_value_for_org(
course_block.location.org,
'ENABLE_MKTG_SITE',
settings.FEATURES.get('ENABLE_MKTG_SITE', False)
settings.ENABLE_MKTG_SITE
)
enable_extended_course_details = configuration_helpers.get_value_for_org(
course_block.location.org,
'ENABLE_EXTENDED_COURSE_DETAILS',
settings.FEATURES.get('ENABLE_EXTENDED_COURSE_DETAILS', False)
settings.ENABLE_EXTENDED_COURSE_DETAILS
)

about_page_editable = not publisher_enabled
enrollment_end_editable = GlobalStaff().has_user(request.user) or not publisher_enabled
short_description_editable = configuration_helpers.get_value_for_org(
course_block.location.org,
'EDITABLE_SHORT_DESCRIPTION',
settings.FEATURES.get('EDITABLE_SHORT_DESCRIPTION', True)
settings.EDITABLE_SHORT_DESCRIPTION
)
sidebar_html_enabled = ENABLE_COURSE_ABOUT_SIDEBAR_HTML.is_enabled()

Expand Down Expand Up @@ -1623,9 +1623,9 @@ def get_library_context(request, request_is_json=False):
'user': request.user,
'request_course_creator_url': reverse('request_course_creator'),
'course_creator_status': _get_course_creator_status(request.user),
'allow_unicode_course_id': settings.FEATURES.get('ALLOW_UNICODE_COURSE_ID', False),
'allow_unicode_course_id': settings.ALLOW_UNICODE_COURSE_ID,
'archived_courses': True,
'allow_course_reruns': settings.FEATURES.get('ALLOW_COURSE_RERUNS', True),
'allow_course_reruns': settings.ALLOW_COURSE_RERUNS,
'rerun_creator_status': GlobalStaff().has_user(request.user),
'split_studio_home': split_library_view_on_dashboard(),
'active_tab': 'libraries',
Expand Down Expand Up @@ -1670,7 +1670,7 @@ def format_in_process_course_view(uca):
}

courses_iter, in_process_course_actions = get_courses_accessible_to_user(request)
split_archived = settings.FEATURES.get('ENABLE_SEPARATE_ARCHIVED_COURSES', False)
split_archived = settings.ENABLE_SEPARATE_ARCHIVED_COURSES
active_courses, archived_courses = _process_courses_list(courses_iter, in_process_course_actions, split_archived)
in_process_course_actions = [format_in_process_course_view(uca) for uca in in_process_course_actions]
return active_courses, archived_courses, in_process_course_actions
Expand Down Expand Up @@ -1763,8 +1763,8 @@ def get_home_context(request, no_course=False):
'request_course_creator_url': reverse('request_course_creator'),
'course_creator_status': _get_course_creator_status(user),
'rerun_creator_status': GlobalStaff().has_user(user),
'allow_unicode_course_id': settings.FEATURES.get('ALLOW_UNICODE_COURSE_ID', False),
'allow_course_reruns': settings.FEATURES.get('ALLOW_COURSE_RERUNS', True),
'allow_unicode_course_id': settings.ALLOW_UNICODE_COURSE_ID,
'allow_course_reruns': settings.ALLOW_COURSE_RERUNS,
'active_tab': 'courses',
'allowed_organizations': get_allowed_organizations(user),
'allowed_organizations_for_libraries': get_allowed_organizations_for_libraries(user),
Expand All @@ -1788,7 +1788,7 @@ def get_course_rerun_context(course_key, course_block, user):
'display_name': course_block.display_name,
'user': user,
'course_creator_status': _get_course_creator_status(user),
'allow_unicode_course_id': settings.FEATURES.get('ALLOW_UNICODE_COURSE_ID', False)
'allow_unicode_course_id': settings.ALLOW_UNICODE_COURSE_ID
}

return course_rerun_context
Expand Down Expand Up @@ -1910,7 +1910,7 @@ def _get_course_index_context(request, course_key, course_block):

lms_link = get_lms_link_for_item(course_block.location)
reindex_link = None
if settings.FEATURES.get('ENABLE_COURSEWARE_INDEX', False):
if settings.ENABLE_COURSEWARE_INDEX:
if GlobalStaff().has_user(request.user):
reindex_link = f"/course/{str(course_key)}/search_reindex"
sections = course_block.get_children()
Expand All @@ -1936,7 +1936,7 @@ def _get_course_index_context(request, course_key, course_block):
frontend_app_publisher_url = configuration_helpers.get_value_for_org(
course_block.location.org,
'FRONTEND_APP_PUBLISHER_URL',
settings.FEATURES.get('FRONTEND_APP_PUBLISHER_URL', False)
settings.FRONTEND_APP_PUBLISHER_URL
)
# gather any errors in the currently stored proctoring settings.
advanced_dict = CourseMetadata.fetch(course_block)
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/video_storage_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ def _get_and_validate_course(course_key_string, user):
course = get_course_and_check_access(course_key, user)

if (
settings.FEATURES["ENABLE_VIDEO_UPLOAD_PIPELINE"] and
settings.ENABLE_VIDEO_UPLOAD_PIPELINE and
getattr(settings, "VIDEO_UPLOAD_PIPELINE", None) and
course and
course.video_pipeline_configured
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/views/certificate_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def is_activated(course):
"""
is_active = False
certificates = []
if settings.FEATURES.get('CERTIFICATES_HTML_VIEW', False):
if settings.CERTIFICATES_HTML_VIEW:
certificates = CertificateManager.get_certificates(course)
# we are assuming only one certificate in certificates collection.
for certificate in certificates:
Expand Down
18 changes: 9 additions & 9 deletions cms/djangoapps/contentstore/views/course.py
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,7 @@ def _create_or_rerun_course(request):
raise PermissionDenied()

# allow/disable unicode characters in course_id according to settings
if not settings.FEATURES.get('ALLOW_UNICODE_COURSE_ID'):
if not settings.ALLOW_UNICODE_COURSE_ID:
if _has_non_ascii_characters(org) or _has_non_ascii_characters(course) or _has_non_ascii_characters(run):
return JsonResponse(
{'error': _('Special characters not allowed in organization, course number, and course run.')},
Expand Down Expand Up @@ -1285,7 +1285,7 @@ def advanced_settings_handler(request, course_key_string):
course_block = get_course_and_check_access(course_key, request.user)

advanced_dict = CourseMetadata.fetch(course_block)
if settings.FEATURES.get('DISABLE_MOBILE_COURSE_AVAILABLE', False):
if settings.DISABLE_MOBILE_COURSE_AVAILABLE:
advanced_dict.get('mobile_available')['deprecated'] = True

if 'text/html' in request.META.get('HTTP_ACCEPT', '') and request.method == 'GET':
Expand All @@ -1294,7 +1294,7 @@ def advanced_settings_handler(request, course_key_string):
publisher_enabled = configuration_helpers.get_value_for_org(
course_block.location.org,
'ENABLE_PUBLISHER',
settings.FEATURES.get('ENABLE_PUBLISHER', False)
settings.ENABLE_PUBLISHER
)
# gather any errors in the currently stored proctoring settings.
proctoring_errors = CourseMetadata.validate_proctoring_settings(course_block, advanced_dict, request.user)
Expand Down Expand Up @@ -1803,9 +1803,9 @@ def _get_course_creator_status(user):

if user.is_staff:
course_creator_status = 'granted'
elif settings.FEATURES.get('DISABLE_COURSE_CREATION', False):
elif settings.DISABLE_COURSE_CREATION:
course_creator_status = 'disallowed_for_this_site'
elif settings.FEATURES.get('ENABLE_CREATOR_GROUP', False):
elif settings.ENABLE_CREATOR_GROUP:
course_creator_status = get_course_creator_status(user)
if course_creator_status is None:
# User not grandfathered in as an existing user, has not previously visited the dashboard page.
Expand All @@ -1822,7 +1822,7 @@ def get_allowed_organizations(user):
"""
Helper method for returning the list of organizations for which the user is allowed to create courses.
"""
if settings.FEATURES.get('ENABLE_CREATOR_GROUP', False):
if settings.ENABLE_CREATOR_GROUP:
return get_organizations(user)
else:
return []
Expand All @@ -1837,12 +1837,12 @@ def get_allowed_organizations_for_libraries(user):
# This allows org-level staff to create libraries. We should re-evaluate
# whether this is necessary and try to normalize course and library creation
# authorization behavior.
if settings.FEATURES.get('ENABLE_ORGANIZATION_STAFF_ACCESS_FOR_CONTENT_LIBRARIES', False):
if settings.ENABLE_ORGANIZATION_STAFF_ACCESS_FOR_CONTENT_LIBRARIES:
organizations_set.update(get_organizations_for_non_course_creators(user))

# This allows people in the course creator group for an org to create
# libraries, which mimics course behavior.
if settings.FEATURES.get('ENABLE_CREATOR_GROUP', False):
if settings.ENABLE_CREATOR_GROUP:
organizations_set.update(get_organizations(user))

return sorted(organizations_set)
Expand All @@ -1852,7 +1852,7 @@ def user_can_create_organizations(user):
"""
Returns True if the user can create organizations.
"""
return user.is_staff or not settings.FEATURES.get('ENABLE_CREATOR_GROUP', False)
return user.is_staff or not settings.ENABLE_CREATOR_GROUP


def get_organizations_for_non_course_creators(user):
Expand Down
6 changes: 3 additions & 3 deletions cms/djangoapps/contentstore/views/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def _user_can_create_library_for_org(user, org=None):
return False
elif user.is_staff:
return True
elif settings.FEATURES.get('ENABLE_CREATOR_GROUP', False):
elif settings.ENABLE_CREATOR_GROUP:
org_filter_params = {}
if org:
org_filter_params['org'] = org
Expand All @@ -93,8 +93,8 @@ def _user_can_create_library_for_org(user, org=None):
return is_course_creator or has_org_staff_role or has_course_staff_role or has_course_admin_role
else:
# EDUCATOR-1924: DISABLE_LIBRARY_CREATION overrides DISABLE_COURSE_CREATION, if present.
disable_library_creation = settings.FEATURES.get('DISABLE_LIBRARY_CREATION', None)
disable_course_creation = settings.FEATURES.get('DISABLE_COURSE_CREATION', False)
disable_library_creation = settings.DISABLE_LIBRARY_CREATION
disable_course_creation = settings.DISABLE_COURSE_CREATION
if disable_library_creation is not None:
return not disable_library_creation
else:
Expand Down
2 changes: 1 addition & 1 deletion cms/djangoapps/contentstore/views/preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def _prepare_runtime_for_preview(request, block):
]

mako_service = MakoService(namespace_prefix='lms.')
if settings.FEATURES.get("LICENSING", False):
if settings.LICENSING:
# stick the license wrapper in front
wrappers.insert(0, partial(wrap_with_license, mako_service=mako_service))

Expand Down
Loading
Loading