Skip to content

Commit 3c7e50b

Browse files
committed
chore: move waffle flags, configs to video service
1 parent f51343c commit 3c7e50b

File tree

5 files changed

+119
-32
lines changed

5 files changed

+119
-32
lines changed

lms/djangoapps/courseware/tests/test_video_mongo.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,7 +1201,9 @@ def test_get_html_on_toggling_hls_feature(self, hls_feature_enabled, expected_va
12011201
'youtube': 'https://yt.com/?v=v0TFmdO4ZP0',
12021202
'desktop_mp4': 'https://mp4.com/dm.mp4'
12031203
}
1204-
with patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled') as feature_enabled:
1204+
with patch(
1205+
'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled'
1206+
) as feature_enabled:
12051207
feature_enabled.return_value = hls_feature_enabled
12061208
video_xml = '<video display_name="Video" download_video="true" edx_video_id="12345-67890">[]</video>'
12071209
self.initialize_block(data=video_xml)
@@ -1211,7 +1213,10 @@ def test_get_html_on_toggling_hls_feature(self, hls_feature_enabled, expected_va
12111213
expected_val_profiles,
12121214
)
12131215

1214-
@patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True))
1216+
@patch(
1217+
'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled',
1218+
Mock(return_value=True)
1219+
)
12151220
@patch('xmodule.video_block.video_block.edxval_api.get_urls_for_profiles')
12161221
def test_get_html_hls(self, get_urls_for_profiles):
12171222
"""
@@ -1309,7 +1314,10 @@ def test_poster_image_without_edx_video_id(self, get_course_video_image_url):
13091314

13101315
assert "'poster': 'null'" in context
13111316

1312-
@patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=False))
1317+
@patch(
1318+
'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled',
1319+
Mock(return_value=False)
1320+
)
13131321
def test_hls_primary_playback_on_toggling_hls_feature(self):
13141322
"""
13151323
Verify that `prioritize_hls` is set to `False` if `HLSPlaybackEnabledFlag` is disabled.
@@ -1356,7 +1364,10 @@ def test_hls_primary_playback_on_toggling_hls_feature(self):
13561364
'result': 'false'
13571365
},
13581366
)
1359-
@patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True))
1367+
@patch(
1368+
'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled',
1369+
Mock(return_value=True)
1370+
)
13601371
def test_deprecate_youtube_course_waffle_flag(self, data):
13611372
"""
13621373
Tests various combinations of a `prioritize_hls` flag being set in waffle and overridden for a course.
@@ -1417,7 +1428,10 @@ def setUp(self):
14171428
),
14181429
)
14191430
@ddt.unpack
1420-
@patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True))
1431+
@patch(
1432+
'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled',
1433+
Mock(return_value=True)
1434+
)
14211435
def test_val_encoding_in_context(self, val_video_encodings, video_url):
14221436
"""
14231437
Tests that the val encodings correctly override the video url when the edx video id is set and
@@ -1458,7 +1472,10 @@ def test_val_encoding_in_context(self, val_video_encodings, video_url):
14581472
),
14591473
)
14601474
@ddt.unpack
1461-
@patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True))
1475+
@patch(
1476+
'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled',
1477+
Mock(return_value=True)
1478+
)
14621479
def test_val_encoding_in_context_without_external_youtube_source(self, val_video_encodings, video_url):
14631480
"""
14641481
Tests that the val encodings correctly override the video url when the edx video id is set and

openedx/core/djangoapps/video_config/services.py

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,19 @@
88

99
import logging
1010

11-
from opaque_keys.edx.keys import CourseKey, UsageKey
12-
11+
from opaque_keys.edx.keys import (
12+
CourseKey,
13+
UsageKey,
14+
UsageKeyV2,
15+
)
1316
from openedx.core.djangoapps.video_config import sharing
1417
from organizations.api import get_course_organization
15-
18+
from openedx.core.djangoapps.video_config.models import (
19+
CourseYoutubeBlockedFlag,
20+
HLSPlaybackEnabledFlag,
21+
)
22+
from openedx.core.djangoapps.video_config.toggles import TRANSCRIPT_FEEDBACK
23+
from openedx.core.djangoapps.video_pipeline.config.waffle import DEPRECATE_YOUTUBE
1624

1725
log = logging.getLogger(__name__)
1826

@@ -62,3 +70,54 @@ def get_public_sharing_context(self, video_block, course_key: CourseKey) -> dict
6270
context['sharing_sites_info'] = sharing_sites_info
6371

6472
return context
73+
74+
def is_transcript_feedback_enabled(self, course_id: CourseKey) -> bool:
75+
"""
76+
Check if transcript feedback is enabled for the course.
77+
"""
78+
return TRANSCRIPT_FEEDBACK.is_enabled(course_id)
79+
80+
def is_youtube_deprecated(self, course_id: CourseKey) -> bool:
81+
"""
82+
Check if YouTube is deprecated for the course.
83+
"""
84+
return DEPRECATE_YOUTUBE.is_enabled(course_id)
85+
86+
def is_youtube_blocked_for_course(self, course_id: CourseKey) -> bool:
87+
"""
88+
Check if YouTube is blocked for the course.
89+
"""
90+
return CourseYoutubeBlockedFlag.feature_enabled(course_id)
91+
92+
def is_hls_playback_enabled(self, course_id: CourseKey) -> bool:
93+
"""
94+
Check if HLS playback is enabled for the course.
95+
"""
96+
return HLSPlaybackEnabledFlag.feature_enabled(course_id)
97+
98+
def add_library_static_asset(self, usage_key: UsageKeyV2, filename: str, content: bytes) -> bool:
99+
"""
100+
This method provides access to the library API for adding static assets
101+
to Learning Core components.
102+
"""
103+
# Import here to avoid circular dependency
104+
from openedx.core.djangoapps.content_libraries.api import lib_api
105+
lib_api.add_library_block_static_asset_file(
106+
usage_key,
107+
filename,
108+
content,
109+
)
110+
return True
111+
112+
def delete_library_static_asset(self, usage_key: UsageKeyV2, filename: str) -> bool:
113+
"""
114+
This method provides access to the library API for deleting static assets
115+
from Learning Core components.
116+
"""
117+
# Import here to avoid circular dependency
118+
from openedx.core.djangoapps.content_libraries.api import lib_api
119+
lib_api.delete_library_block_static_asset_file(
120+
usage_key,
121+
filename,
122+
)
123+
return True

xmodule/tests/test_video.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,10 @@ def test_student_view_data(self, field_data, expected_student_view_data):
944944
student_view_data = block.student_view_data()
945945
assert student_view_data == expected_student_view_data
946946

947-
@patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True))
947+
@patch(
948+
'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled',
949+
Mock(return_value=True)
950+
)
948951
@patch('openedx.core.djangoapps.video_config.transcripts_utils.get_available_transcript_languages',
949952
Mock(return_value=['es']))
950953
@patch('edxval.api.get_video_info_for_course_and_profiles', Mock(return_value={}))

xmodule/video_block/video_block.py

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@
3131
from xblocks_contrib.video import VideoBlock as _ExtractedVideoBlock
3232

3333
from common.djangoapps.xblock_django.constants import ATTR_KEY_REQUEST_COUNTRY_CODE, ATTR_KEY_USER_ID
34-
from openedx.core.djangoapps.video_config.models import HLSPlaybackEnabledFlag, CourseYoutubeBlockedFlag
35-
from openedx.core.djangoapps.video_config.toggles import TRANSCRIPT_FEEDBACK
36-
from openedx.core.djangoapps.video_pipeline.config.waffle import DEPRECATE_YOUTUBE
3734
from openedx.core.lib.cache_utils import request_cached
3835
from openedx.core.lib.license import LicenseMixin
3936
from xmodule.contentstore.content import StaticContent
@@ -106,8 +103,8 @@
106103
EXPORT_IMPORT_STATIC_DIR = 'static'
107104

108105

109-
@XBlock.wants('settings', 'completion', 'i18n', 'request_cache')
110-
@XBlock.needs('mako', 'user', 'video_config')
106+
@XBlock.wants('settings', 'completion', 'i18n', 'request_cache', 'video_config')
107+
@XBlock.needs('mako', 'user')
111108
class _BuiltInVideoBlock(
112109
VideoFields, VideoTranscriptsMixin, VideoStudioViewHandlers, VideoStudentViewHandlers,
113110
EmptyDataRawMixin, XmlMixin, EditingMixin, XModuleToXBlockMixin,
@@ -188,18 +185,26 @@ def get_transcripts_for_student(self, transcripts, dest_lang=None):
188185
sorted_languages = OrderedDict(sorted_languages)
189186
return track_url, transcript_language, sorted_languages
190187

188+
def is_hls_playback_enabled(self, course_id):
189+
"""
190+
Check if HLS playback is enabled for the course.
191+
"""
192+
video_config_service = self.runtime.service(self, 'video_config')
193+
return video_config_service.is_hls_playback_enabled(course_id) if video_config_service else False
194+
191195
@property
192196
def youtube_deprecated(self):
193197
"""
194198
Return True if youtube is deprecated and hls as primary playback is enabled else False
195199
"""
200+
video_config_service = self.runtime.service(self, 'video_config')
196201
# Return False if `hls` playback feature is disabled.
197-
if not HLSPlaybackEnabledFlag.feature_enabled(self.location.course_key):
202+
if video_config_service and not self.is_hls_playback_enabled(self.location.course_key):
198203
return False
199204

200205
# check if youtube has been deprecated and hls as primary playback
201206
# is enabled for this course
202-
return DEPRECATE_YOUTUBE.is_enabled(self.location.course_key)
207+
return video_config_service.is_youtube_deprecated(self.location.course_key) if video_config_service else False
203208

204209
def youtube_disabled_for_course(self): # lint-amnesty, pylint: disable=missing-function-docstring
205210
if not self.location.context_key.is_course:
@@ -209,7 +214,9 @@ def youtube_disabled_for_course(self): # lint-amnesty, pylint: disable=missing-
209214
if cache_response.is_found:
210215
return cache_response.value
211216

212-
youtube_is_disabled = CourseYoutubeBlockedFlag.feature_enabled(self.location.course_key)
217+
video_config_service = self.runtime.service(self, 'video_config')
218+
youtube_is_disabled = video_config_service.is_youtube_blocked_for_course(
219+
self.location.course_key) if video_config_service else False
213220
request_cache.set(self.location.context_key, youtube_is_disabled)
214221
return youtube_is_disabled
215222

@@ -300,7 +307,7 @@ def get_html(self, view=STUDENT_VIEW, context=None): # lint-amnesty, pylint: di
300307
try:
301308
val_profiles = ["youtube", "desktop_webm", "desktop_mp4"]
302309

303-
if HLSPlaybackEnabledFlag.feature_enabled(self.course_id):
310+
if self.is_hls_playback_enabled(self.course_id):
304311
val_profiles.append('hls')
305312

306313
# strip edx_video_id to prevent ValVideoNotFoundError error if unwanted spaces are there. TNL-5769
@@ -499,7 +506,9 @@ def is_transcript_feedback_enabled(self):
499506
return False # Only courses support this feature at all (not libraries)
500507
try:
501508
# Video transcript feedback must be enabled in order to show the widget
502-
feature_enabled = TRANSCRIPT_FEEDBACK.is_enabled(self.context_key)
509+
video_config_service = self.runtime.service(self, 'video_config')
510+
feature_enabled = video_config_service.is_transcript_feedback_enabled(
511+
self.context_key) if video_config_service else False
503512
except Exception as err: # pylint: disable=broad-except
504513
log.exception(f"Error retrieving course for course ID: {self.context_key}")
505514
return False
@@ -881,7 +890,7 @@ def get_youtube_link(video_id):
881890
if self.edx_video_id and edxval_api:
882891

883892
val_profiles = ['youtube', 'desktop_webm', 'desktop_mp4']
884-
if HLSPlaybackEnabledFlag.feature_enabled(self.scope_ids.usage_id.context_key.for_branch(None)):
893+
if self.is_hls_playback_enabled(self.scope_ids.usage_id.context_key.for_branch(None)):
885894
val_profiles.append('hls')
886895

887896
# Get video encodings for val profiles.
@@ -1137,7 +1146,7 @@ def student_view_data(self, context=None):
11371146
# Check in VAL data first if edx_video_id exists
11381147
if self.edx_video_id:
11391148
video_profile_names = context.get("profiles", ["mobile_low", 'desktop_mp4', 'desktop_webm', 'mobile_high'])
1140-
if HLSPlaybackEnabledFlag.feature_enabled(self.location.course_key) and 'hls' not in video_profile_names:
1149+
if self.is_hls_playback_enabled(self.location.course_key) and 'hls' not in video_profile_names:
11411150
video_profile_names.append('hls')
11421151

11431152
# get and cache bulk VAL data for course

xmodule/video_block/video_handlers.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
from xmodule.exceptions import NotFoundError
2222
from xmodule.fields import RelativeTime
23-
from openedx.core.djangoapps.content_libraries import api as lib_api
2423

2524
from openedx.core.djangoapps.video_config.transcripts_utils import (
2625
Transcript,
@@ -563,11 +562,9 @@ def _studio_transcript_upload(self, request):
563562
if is_library:
564563
# Save transcript as static asset in Learning Core if is a library component
565564
filename = f"static/{filename}"
566-
lib_api.add_library_block_static_asset_file(
567-
self.usage_key,
568-
filename,
569-
content,
570-
)
565+
video_config_service = self.runtime.service(self, 'video_config')
566+
if video_config_service:
567+
video_config_service.add_library_static_asset(self.usage_key, filename, content)
571568
else:
572569
sjson_subs = Transcript.convert(
573570
content=content.decode('utf-8'),
@@ -625,10 +622,12 @@ def _studio_transcript_delete(self, request):
625622
# TODO: In the future, we need a proper XBlock API
626623
# like `self.static_assets.delete(...)` instead of coding
627624
# these runtime-specific/library-specific APIs.
628-
lib_api.delete_library_block_static_asset_file(
629-
self.usage_key,
630-
f"static/{transcript_name}",
631-
)
625+
video_config_service = self.runtime.service(self, 'video_config')
626+
if video_config_service:
627+
video_config_service.delete_library_static_asset(
628+
self.usage_key,
629+
f"static/{transcript_name}"
630+
)
632631
self._save_transcript_field()
633632
else:
634633
if language == 'en':

0 commit comments

Comments
 (0)