Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
037ef3be
Commit
037ef3be
authored
Jun 04, 2015
by
Nimisha Asthagiri
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Video module support for student_view_json.
parent
65e330e8
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
196 additions
and
4 deletions
+196
-4
common/lib/xmodule/xmodule/video_module/video_handlers.py
+2
-1
common/lib/xmodule/xmodule/video_module/video_module.py
+78
-2
lms/djangoapps/courseware/tests/test_video_mongo.py
+116
-1
No files found.
common/lib/xmodule/xmodule/video_module/video_handlers.py
View file @
037ef3be
...
@@ -250,9 +250,10 @@ class VideoStudentViewHandlers(object):
...
@@ -250,9 +250,10 @@ class VideoStudentViewHandlers(object):
response
.
content_type
=
Transcript
.
mime_types
[
'sjson'
]
response
.
content_type
=
Transcript
.
mime_types
[
'sjson'
]
elif
dispatch
==
'download'
:
elif
dispatch
==
'download'
:
lang
=
request
.
GET
.
get
(
'lang'
,
None
)
try
:
try
:
transcript_content
,
transcript_filename
,
transcript_mime_type
=
self
.
get_transcript
(
transcript_content
,
transcript_filename
,
transcript_mime_type
=
self
.
get_transcript
(
transcripts
,
transcript_format
=
self
.
transcript_download_format
transcripts
,
transcript_format
=
self
.
transcript_download_format
,
lang
=
lang
)
)
except
(
NotFoundError
,
ValueError
,
KeyError
,
UnicodeDecodeError
):
except
(
NotFoundError
,
ValueError
,
KeyError
,
UnicodeDecodeError
):
log
.
debug
(
"Video@download exception"
)
log
.
debug
(
"Video@download exception"
)
...
...
common/lib/xmodule/xmodule/video_module/video_module.py
View file @
037ef3be
...
@@ -20,12 +20,12 @@ import logging
...
@@ -20,12 +20,12 @@ import logging
import
random
import
random
from
collections
import
OrderedDict
from
collections
import
OrderedDict
from
operator
import
itemgetter
from
operator
import
itemgetter
from
lxml
import
etree
from
lxml
import
etree
from
pkg_resources
import
resource_string
from
pkg_resources
import
resource_string
from
django.conf
import
settings
from
django.conf
import
settings
from
openedx.core.lib.cache_utils
import
memoize_in_request_cache
from
xblock.core
import
XBlock
from
xblock.core
import
XBlock
from
xblock.fields
import
ScopeIds
from
xblock.fields
import
ScopeIds
from
xblock.runtime
import
KvsFieldData
from
xblock.runtime
import
KvsFieldData
...
@@ -329,6 +329,7 @@ class VideoModule(VideoFields, VideoTranscriptsMixin, VideoStudentViewHandlers,
...
@@ -329,6 +329,7 @@ class VideoModule(VideoFields, VideoTranscriptsMixin, VideoStudentViewHandlers,
return
self
.
system
.
render_template
(
'video.html'
,
context
)
return
self
.
system
.
render_template
(
'video.html'
,
context
)
@XBlock.wants
(
"request_cache"
)
@XBlock.wants
(
"settings"
)
@XBlock.wants
(
"settings"
)
class
VideoDescriptor
(
VideoFields
,
VideoTranscriptsMixin
,
VideoStudioViewHandlers
,
class
VideoDescriptor
(
VideoFields
,
VideoTranscriptsMixin
,
VideoStudioViewHandlers
,
TabsEditingDescriptor
,
EmptyDataRawDescriptor
):
TabsEditingDescriptor
,
EmptyDataRawDescriptor
):
...
@@ -722,7 +723,7 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
...
@@ -722,7 +723,7 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
if
self
.
sub
:
if
self
.
sub
:
_update_transcript_for_index
()
_update_transcript_for_index
()
#
c
heck to see if there are transcripts in other languages besides default transcript
#
C
heck to see if there are transcripts in other languages besides default transcript
if
self
.
transcripts
:
if
self
.
transcripts
:
for
language
in
self
.
transcripts
.
keys
():
for
language
in
self
.
transcripts
.
keys
():
_update_transcript_for_index
(
language
)
_update_transcript_for_index
(
language
)
...
@@ -734,3 +735,78 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
...
@@ -734,3 +735,78 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
xblock_body
[
"content_type"
]
=
"Video"
xblock_body
[
"content_type"
]
=
"Video"
return
xblock_body
return
xblock_body
@property
def
request_cache
(
self
):
"""
Returns the request_cache from the runtime.
"""
return
self
.
runtime
.
service
(
self
,
"request_cache"
)
@memoize_in_request_cache
(
'request_cache'
)
def
get_cached_val_data_for_course
(
self
,
video_profile_names
,
course_id
):
"""
Returns the VAL data for the requested video profiles for the given course.
"""
return
edxval_api
.
get_video_info_for_course_and_profiles
(
unicode
(
course_id
),
video_profile_names
)
def
student_view_json
(
self
,
context
):
"""
Returns a JSON representation of the student_view of this XModule.
The contract of the JSON content is between the caller and the particular XModule.
"""
# Honor only_on_web
if
self
.
only_on_web
:
return
{
"only_on_web"
:
True
}
encoded_videos
=
{}
val_video_data
=
{}
# Check in VAL data first if edx_video_id exists
if
self
.
edx_video_id
:
video_profile_names
=
context
.
get
(
"profiles"
,
[])
# get and cache bulk VAL data for course
val_course_data
=
self
.
get_cached_val_data_for_course
(
video_profile_names
,
self
.
location
.
course_key
)
val_video_data
=
val_course_data
.
get
(
self
.
edx_video_id
,
{})
# Get the encoded videos if data from VAL is found
if
val_video_data
:
encoded_videos
=
val_video_data
.
get
(
'profiles'
,
{})
# If information for this edx_video_id is not found in the bulk course data, make a
# separate request for this individual edx_video_id, unless cache misses are disabled.
# This is useful/required for videos that don't have a course designated, such as the introductory video
# that is shared across many courses. However, this results in a separate database request so watch
# out for any performance hit if many such videos exist in a course. Set the 'allow_cache_miss' parameter
# to False to disable this fall back.
elif
context
.
get
(
"allow_cache_miss"
,
"True"
)
.
lower
()
==
"true"
:
try
:
val_video_data
=
edxval_api
.
get_video_info
(
self
.
edx_video_id
)
# Unfortunately, the VAL API is inconsistent in how it returns the encodings, so remap here.
for
enc_vid
in
val_video_data
.
pop
(
'encoded_videos'
):
encoded_videos
[
enc_vid
[
'profile'
]]
=
{
key
:
enc_vid
[
key
]
for
key
in
[
"url"
,
"file_size"
]}
except
edxval_api
.
ValVideoNotFoundError
:
pass
# Fall back to other video URLs in the video module if not found in VAL
if
not
encoded_videos
:
video_url
=
self
.
html5_sources
[
0
]
if
self
.
html5_sources
else
self
.
source
if
video_url
:
encoded_videos
[
"fallback"
]
=
{
"url"
:
video_url
,
"file_size"
:
0
,
# File size is unknown for fallback URLs
}
transcripts_info
=
self
.
get_transcripts_info
()
transcripts
=
{
lang
:
self
.
runtime
.
handler_url
(
self
,
'transcript'
,
'download'
,
query
=
"lang="
+
lang
,
thirdparty
=
True
)
for
lang
in
self
.
available_translations
(
transcripts_info
,
verify_assets
=
False
)
}
return
{
"only_on_web"
:
self
.
only_on_web
,
"duration"
:
val_video_data
.
get
(
'duration'
,
None
),
"transcripts"
:
transcripts
,
"encoded_videos"
:
encoded_videos
,
}
lms/djangoapps/courseware/tests/test_video_mongo.py
View file @
037ef3be
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
"""Video xmodule tests in mongo."""
"""Video xmodule tests in mongo."""
import
ddt
import
itertools
import
json
import
json
from
collections
import
OrderedDict
from
collections
import
OrderedDict
...
@@ -13,7 +15,7 @@ from django.test.utils import override_settings
...
@@ -13,7 +15,7 @@ from django.test.utils import override_settings
from
xmodule.video_module
import
VideoDescriptor
,
bumper_utils
,
video_utils
from
xmodule.video_module
import
VideoDescriptor
,
bumper_utils
,
video_utils
from
xmodule.x_module
import
STUDENT_VIEW
from
xmodule.x_module
import
STUDENT_VIEW
from
xmodule.tests.test_video
import
VideoDescriptorTestBase
from
xmodule.tests.test_video
import
VideoDescriptorTestBase
,
instantiate_descriptor
from
xmodule.tests.test_import
import
DummySystem
from
xmodule.tests.test_import
import
DummySystem
from
edxval.api
import
(
from
edxval.api
import
(
...
@@ -861,6 +863,119 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
...
@@ -861,6 +863,119 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
self
.
assertFalse
(
self
.
item_descriptor
.
download_video
)
self
.
assertFalse
(
self
.
item_descriptor
.
download_video
)
@ddt.ddt
class
TestVideoDescriptorStudentViewJson
(
TestCase
):
"""
Tests for the student_view_json method on VideoDescriptor.
"""
TEST_DURATION
=
111.0
TEST_PROFILE
=
"mobile"
TEST_SOURCE_URL
=
"http://www.example.com/source.mp4"
TEST_LANGUAGE
=
"ge"
TEST_ENCODED_VIDEO
=
{
'profile'
:
TEST_PROFILE
,
'bitrate'
:
333
,
'url'
:
'http://example.com/video'
,
'file_size'
:
222
,
}
TEST_EDX_VIDEO_ID
=
'test_edx_video_id'
def
setUp
(
self
):
super
(
TestVideoDescriptorStudentViewJson
,
self
)
.
setUp
()
sample_xml
=
(
"<video display_name='Test Video'> "
+
"<source src='"
+
self
.
TEST_SOURCE_URL
+
"'/> "
+
"<transcript language='"
+
self
.
TEST_LANGUAGE
+
"' src='german_translation.srt' /> "
+
"</video>"
)
self
.
transcript_url
=
"transcript_url"
self
.
video
=
instantiate_descriptor
(
data
=
sample_xml
)
self
.
video
.
runtime
.
handler_url
=
Mock
(
return_value
=
self
.
transcript_url
)
def
setup_val_video
(
self
,
associate_course_in_val
=
False
):
"""
Creates a video entry in VAL.
Arguments:
associate_course - If True, associates the test course with the video in VAL.
"""
create_profile
(
'mobile'
)
create_video
({
'edx_video_id'
:
self
.
TEST_EDX_VIDEO_ID
,
'client_video_id'
:
'test_client_video_id'
,
'duration'
:
self
.
TEST_DURATION
,
'status'
:
'dummy'
,
'encoded_videos'
:
[
self
.
TEST_ENCODED_VIDEO
],
'courses'
:
[
self
.
video
.
location
.
course_key
]
if
associate_course_in_val
else
[],
})
self
.
val_video
=
get_video_info
(
self
.
TEST_EDX_VIDEO_ID
)
# pylint: disable=attribute-defined-outside-init
def
get_result
(
self
,
allow_cache_miss
=
True
):
"""
Returns the result from calling the video's student_view_json method.
Arguments:
allow_cache_miss is passed in the context to the student_view_json method.
"""
context
=
{
"profiles"
:
[
self
.
TEST_PROFILE
],
"allow_cache_miss"
:
"True"
if
allow_cache_miss
else
"False"
}
return
self
.
video
.
student_view_json
(
context
)
def
verify_result_with_fallback_url
(
self
,
result
):
"""
Verifies the result is as expected when returning "fallback" video data (not from VAL).
"""
self
.
assertDictEqual
(
result
,
{
"only_on_web"
:
False
,
"duration"
:
None
,
"transcripts"
:
{
self
.
TEST_LANGUAGE
:
self
.
transcript_url
},
"encoded_videos"
:
{
"fallback"
:
{
"url"
:
self
.
TEST_SOURCE_URL
,
"file_size"
:
0
}},
}
)
def
verify_result_with_val_profile
(
self
,
result
):
"""
Verifies the result is as expected when returning video data from VAL.
"""
self
.
assertDictContainsSubset
(
result
.
pop
(
"encoded_videos"
)[
self
.
TEST_PROFILE
],
self
.
TEST_ENCODED_VIDEO
,
)
self
.
assertDictEqual
(
result
,
{
"only_on_web"
:
False
,
"duration"
:
self
.
TEST_DURATION
,
"transcripts"
:
{
self
.
TEST_LANGUAGE
:
self
.
transcript_url
},
}
)
def
test_only_on_web
(
self
):
self
.
video
.
only_on_web
=
True
result
=
self
.
get_result
()
self
.
assertDictEqual
(
result
,
{
"only_on_web"
:
True
})
def
test_no_edx_video_id
(
self
):
result
=
self
.
get_result
()
self
.
verify_result_with_fallback_url
(
result
)
@ddt.data
(
*
itertools
.
product
([
True
,
False
],
[
True
,
False
],
[
True
,
False
])
)
@ddt.unpack
def
test_with_edx_video_id
(
self
,
allow_cache_miss
,
video_exists_in_val
,
associate_course_in_val
):
self
.
video
.
edx_video_id
=
self
.
TEST_EDX_VIDEO_ID
if
video_exists_in_val
:
self
.
setup_val_video
(
associate_course_in_val
)
result
=
self
.
get_result
(
allow_cache_miss
)
if
video_exists_in_val
and
(
associate_course_in_val
or
allow_cache_miss
):
self
.
verify_result_with_val_profile
(
result
)
else
:
self
.
verify_result_with_fallback_url
(
result
)
@attr
(
'shard_1'
)
@attr
(
'shard_1'
)
class
VideoDescriptorTest
(
TestCase
,
VideoDescriptorTestBase
):
class
VideoDescriptorTest
(
TestCase
,
VideoDescriptorTestBase
):
"""
"""
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment