chore: Move waffle flags, configs (used in video block) to video service

Merge pull request #37631 from openedx/farhan/add-waffle-flags
This commit is contained in:
Muhammad Farhan Khan
2025-11-17 17:52:29 +05:00
committed by GitHub
parent f51343c871
commit a50ab7d75f
4 changed files with 79 additions and 20 deletions

View File

@@ -1201,7 +1201,9 @@ class TestGetHtmlMethod(BaseTestVideoXBlock):
'youtube': 'https://yt.com/?v=v0TFmdO4ZP0',
'desktop_mp4': 'https://mp4.com/dm.mp4'
}
with patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled') as feature_enabled:
with patch(
'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled'
) as feature_enabled:
feature_enabled.return_value = hls_feature_enabled
video_xml = '<video display_name="Video" download_video="true" edx_video_id="12345-67890">[]</video>'
self.initialize_block(data=video_xml)
@@ -1211,7 +1213,10 @@ class TestGetHtmlMethod(BaseTestVideoXBlock):
expected_val_profiles,
)
@patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True))
@patch(
'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled',
Mock(return_value=True)
)
@patch('xmodule.video_block.video_block.edxval_api.get_urls_for_profiles')
def test_get_html_hls(self, get_urls_for_profiles):
"""
@@ -1309,7 +1314,10 @@ class TestGetHtmlMethod(BaseTestVideoXBlock):
assert "'poster': 'null'" in context
@patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=False))
@patch(
'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled',
Mock(return_value=False)
)
def test_hls_primary_playback_on_toggling_hls_feature(self):
"""
Verify that `prioritize_hls` is set to `False` if `HLSPlaybackEnabledFlag` is disabled.
@@ -1356,7 +1364,10 @@ class TestGetHtmlMethod(BaseTestVideoXBlock):
'result': 'false'
},
)
@patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True))
@patch(
'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled',
Mock(return_value=True)
)
def test_deprecate_youtube_course_waffle_flag(self, data):
"""
Tests various combinations of a `prioritize_hls` flag being set in waffle and overridden for a course.
@@ -1417,7 +1428,10 @@ class TestVideoBlockInitialization(BaseTestVideoXBlock):
),
)
@ddt.unpack
@patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True))
@patch(
'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled',
Mock(return_value=True)
)
def test_val_encoding_in_context(self, val_video_encodings, video_url):
"""
Tests that the val encodings correctly override the video url when the edx video id is set and
@@ -1458,7 +1472,10 @@ class TestVideoBlockInitialization(BaseTestVideoXBlock):
),
)
@ddt.unpack
@patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True))
@patch(
'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled',
Mock(return_value=True)
)
def test_val_encoding_in_context_without_external_youtube_source(self, val_video_encodings, video_url):
"""
Tests that the val encodings correctly override the video url when the edx video id is set and

View File

@@ -12,7 +12,12 @@ from opaque_keys.edx.keys import CourseKey, UsageKey
from openedx.core.djangoapps.video_config import sharing
from organizations.api import get_course_organization
from openedx.core.djangoapps.video_config.models import (
CourseYoutubeBlockedFlag,
HLSPlaybackEnabledFlag,
)
from openedx.core.djangoapps.video_config.toggles import TRANSCRIPT_FEEDBACK
from openedx.core.djangoapps.video_pipeline.config.waffle import DEPRECATE_YOUTUBE
log = logging.getLogger(__name__)
@@ -62,3 +67,27 @@ class VideoConfigService:
context['sharing_sites_info'] = sharing_sites_info
return context
def is_transcript_feedback_enabled(self, course_id: CourseKey) -> bool:
"""
Check if transcript feedback is enabled for the course.
"""
return TRANSCRIPT_FEEDBACK.is_enabled(course_id)
def is_youtube_deprecated(self, course_id: CourseKey) -> bool:
"""
Check if YouTube is deprecated for the course.
"""
return DEPRECATE_YOUTUBE.is_enabled(course_id)
def is_youtube_blocked_for_course(self, course_id: CourseKey) -> bool:
"""
Check if YouTube is blocked for the course.
"""
return CourseYoutubeBlockedFlag.feature_enabled(course_id)
def is_hls_playback_enabled(self, course_id: CourseKey) -> bool:
"""
Check if HLS playback is enabled for the course.
"""
return HLSPlaybackEnabledFlag.feature_enabled(course_id)

View File

@@ -944,7 +944,10 @@ class VideoBlockStudentViewDataTestCase(unittest.TestCase):
student_view_data = block.student_view_data()
assert student_view_data == expected_student_view_data
@patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True))
@patch(
'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled',
Mock(return_value=True)
)
@patch('openedx.core.djangoapps.video_config.transcripts_utils.get_available_transcript_languages',
Mock(return_value=['es']))
@patch('edxval.api.get_video_info_for_course_and_profiles', Mock(return_value={}))

View File

@@ -22,6 +22,7 @@ from operator import itemgetter
from django.conf import settings
from edx_django_utils.cache import RequestCache
from lxml import etree
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locator import AssetLocator
from web_fragments.fragment import Fragment
from xblock.completable import XBlockCompletionMode
@@ -31,9 +32,6 @@ from xblock.runtime import KvsFieldData
from xblocks_contrib.video import VideoBlock as _ExtractedVideoBlock
from common.djangoapps.xblock_django.constants import ATTR_KEY_REQUEST_COUNTRY_CODE, ATTR_KEY_USER_ID
from openedx.core.djangoapps.video_config.models import HLSPlaybackEnabledFlag, CourseYoutubeBlockedFlag
from openedx.core.djangoapps.video_config.toggles import TRANSCRIPT_FEEDBACK
from openedx.core.djangoapps.video_pipeline.config.waffle import DEPRECATE_YOUTUBE
from openedx.core.lib.cache_utils import request_cached
from openedx.core.lib.license import LicenseMixin
from xmodule.contentstore.content import StaticContent
@@ -106,8 +104,8 @@ EXPORT_IMPORT_COURSE_DIR = 'course'
EXPORT_IMPORT_STATIC_DIR = 'static'
@XBlock.wants('settings', 'completion', 'i18n', 'request_cache')
@XBlock.needs('mako', 'user', 'video_config')
@XBlock.wants('settings', 'completion', 'i18n', 'request_cache', 'video_config')
@XBlock.needs('mako', 'user')
class _BuiltInVideoBlock(
VideoFields, VideoTranscriptsMixin, VideoStudioViewHandlers, VideoStudentViewHandlers,
EmptyDataRawMixin, XmlMixin, EditingMixin, XModuleToXBlockMixin,
@@ -188,18 +186,26 @@ class _BuiltInVideoBlock(
sorted_languages = OrderedDict(sorted_languages)
return track_url, transcript_language, sorted_languages
def is_hls_playback_enabled(self, course_id: CourseKey) -> bool:
"""
Check if HLS playback is enabled for the course.
"""
video_config_service = self.runtime.service(self, 'video_config')
return video_config_service.is_hls_playback_enabled(course_id) if video_config_service else False
@property
def youtube_deprecated(self):
"""
Return True if youtube is deprecated and hls as primary playback is enabled else False
"""
video_config_service = self.runtime.service(self, 'video_config')
# Return False if `hls` playback feature is disabled.
if not HLSPlaybackEnabledFlag.feature_enabled(self.location.course_key):
if not self.is_hls_playback_enabled(self.location.course_key):
return False
# check if youtube has been deprecated and hls as primary playback
# is enabled for this course
return DEPRECATE_YOUTUBE.is_enabled(self.location.course_key)
return video_config_service.is_youtube_deprecated(self.location.course_key) if video_config_service else False
def youtube_disabled_for_course(self): # lint-amnesty, pylint: disable=missing-function-docstring
if not self.location.context_key.is_course:
@@ -209,7 +215,9 @@ class _BuiltInVideoBlock(
if cache_response.is_found:
return cache_response.value
youtube_is_disabled = CourseYoutubeBlockedFlag.feature_enabled(self.location.course_key)
video_config_service = self.runtime.service(self, 'video_config')
youtube_is_disabled = video_config_service.is_youtube_blocked_for_course(
self.location.course_key) if video_config_service else False
request_cache.set(self.location.context_key, youtube_is_disabled)
return youtube_is_disabled
@@ -300,7 +308,7 @@ class _BuiltInVideoBlock(
try:
val_profiles = ["youtube", "desktop_webm", "desktop_mp4"]
if HLSPlaybackEnabledFlag.feature_enabled(self.course_id):
if self.is_hls_playback_enabled(self.course_id):
val_profiles.append('hls')
# strip edx_video_id to prevent ValVideoNotFoundError error if unwanted spaces are there. TNL-5769
@@ -499,7 +507,9 @@ class _BuiltInVideoBlock(
return False # Only courses support this feature at all (not libraries)
try:
# Video transcript feedback must be enabled in order to show the widget
feature_enabled = TRANSCRIPT_FEEDBACK.is_enabled(self.context_key)
video_config_service = self.runtime.service(self, 'video_config')
feature_enabled = video_config_service.is_transcript_feedback_enabled(
self.context_key) if video_config_service else False
except Exception as err: # pylint: disable=broad-except
log.exception(f"Error retrieving course for course ID: {self.context_key}")
return False
@@ -881,7 +891,7 @@ class _BuiltInVideoBlock(
if self.edx_video_id and edxval_api:
val_profiles = ['youtube', 'desktop_webm', 'desktop_mp4']
if HLSPlaybackEnabledFlag.feature_enabled(self.scope_ids.usage_id.context_key.for_branch(None)):
if self.is_hls_playback_enabled(self.scope_ids.usage_id.context_key.for_branch(None)):
val_profiles.append('hls')
# Get video encodings for val profiles.
@@ -1137,7 +1147,7 @@ class _BuiltInVideoBlock(
# Check in VAL data first if edx_video_id exists
if self.edx_video_id:
video_profile_names = context.get("profiles", ["mobile_low", 'desktop_mp4', 'desktop_webm', 'mobile_high'])
if HLSPlaybackEnabledFlag.feature_enabled(self.location.course_key) and 'hls' not in video_profile_names:
if self.is_hls_playback_enabled(self.location.course_key) and 'hls' not in video_profile_names:
video_profile_names.append('hls')
# get and cache bulk VAL data for course