Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-val
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-val
Commits
727e643d
Unverified
Commit
727e643d
authored
Jan 26, 2018
by
M. Rehan
Committed by
GitHub
Jan 26, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #117 from edx/mrehan/transcript-foreign-key
Make Video an explicit foreign key in VideoTranscript model
parents
7d5c04df
eee4c2f0
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
207 additions
and
260 deletions
+207
-260
edxval/admin.py
+1
-1
edxval/api.py
+17
-32
edxval/migrations/0010_add_video_as_foreign_key.py
+31
-0
edxval/models.py
+9
-17
edxval/serializers.py
+7
-1
edxval/tests/constants.py
+0
-8
edxval/tests/test_api.py
+135
-198
edxval/tests/test_views.py
+7
-3
No files found.
edxval/admin.py
View file @
727e643d
...
@@ -69,7 +69,7 @@ class CourseVideoAdmin(admin.ModelAdmin):
...
@@ -69,7 +69,7 @@ class CourseVideoAdmin(admin.ModelAdmin):
class
VideoTranscriptAdmin
(
admin
.
ModelAdmin
):
class
VideoTranscriptAdmin
(
admin
.
ModelAdmin
):
list_display
=
(
'video
_id
'
,
'language_code'
,
'provider'
,
'file_format'
)
list_display
=
(
'video'
,
'language_code'
,
'provider'
,
'file_format'
)
model
=
VideoTranscript
model
=
VideoTranscript
...
...
edxval/api.py
View file @
727e643d
...
@@ -192,7 +192,7 @@ def is_transcript_available(video_id, language_code=None):
...
@@ -192,7 +192,7 @@ def is_transcript_available(video_id, language_code=None):
video_id: it can be an edx_video_id or an external_id extracted from external sources in a video component.
video_id: it can be an edx_video_id or an external_id extracted from external sources in a video component.
language_code: it will the language code of the requested transcript.
language_code: it will the language code of the requested transcript.
"""
"""
filter_attrs
=
{
'video_id'
:
video_id
}
filter_attrs
=
{
'video_
_edx_video_
id'
:
video_id
}
if
language_code
:
if
language_code
:
filter_attrs
[
'language_code'
]
=
language_code
filter_attrs
[
'language_code'
]
=
language_code
...
@@ -200,22 +200,6 @@ def is_transcript_available(video_id, language_code=None):
...
@@ -200,22 +200,6 @@ def is_transcript_available(video_id, language_code=None):
return
transcript_set
.
exists
()
return
transcript_set
.
exists
()
def
get_video_transcripts
(
video_id
):
"""
Get a video's transcripts
Arguments:
video_id: it can be an edx_video_id or an external_id extracted from external sources in a video component.
"""
transcripts_set
=
VideoTranscript
.
objects
.
filter
(
video_id
=
video_id
)
transcripts
=
[]
if
transcripts_set
.
exists
():
transcripts
=
TranscriptSerializer
(
transcripts_set
,
many
=
True
)
.
data
return
transcripts
def
get_video_transcript
(
video_id
,
language_code
):
def
get_video_transcript
(
video_id
,
language_code
):
"""
"""
Get video transcript info
Get video transcript info
...
@@ -245,7 +229,7 @@ def get_video_transcript_data(video_ids, language_code):
...
@@ -245,7 +229,7 @@ def get_video_transcript_data(video_ids, language_code):
transcript_data
=
None
transcript_data
=
None
for
video_id
in
video_ids
:
for
video_id
in
video_ids
:
try
:
try
:
video_transcript
=
VideoTranscript
.
objects
.
get
(
video_id
=
video_id
,
language_code
=
language_code
)
video_transcript
=
VideoTranscript
.
objects
.
get
(
video_
_edx_video_
id
=
video_id
,
language_code
=
language_code
)
transcript_data
=
dict
(
transcript_data
=
dict
(
file_name
=
video_transcript
.
filename
,
file_name
=
video_transcript
.
filename
,
content
=
video_transcript
.
transcript
.
file
.
read
()
content
=
video_transcript
.
transcript
.
file
.
read
()
...
@@ -276,7 +260,7 @@ def get_available_transcript_languages(video_ids):
...
@@ -276,7 +260,7 @@ def get_available_transcript_languages(video_ids):
A list containing unique transcript language codes for the video ids.
A list containing unique transcript language codes for the video ids.
"""
"""
available_languages
=
VideoTranscript
.
objects
.
filter
(
available_languages
=
VideoTranscript
.
objects
.
filter
(
video_id__in
=
video_ids
video_
_edx_video_
id__in
=
video_ids
)
.
values_list
(
)
.
values_list
(
'language_code'
,
flat
=
True
'language_code'
,
flat
=
True
)
)
...
@@ -324,7 +308,12 @@ def create_or_update_video_transcript(video_id, language_code, metadata, file_da
...
@@ -324,7 +308,12 @@ def create_or_update_video_transcript(video_id, language_code, metadata, file_da
if
provider
and
provider
not
in
dict
(
TranscriptProviderType
.
CHOICES
)
.
keys
():
if
provider
and
provider
not
in
dict
(
TranscriptProviderType
.
CHOICES
)
.
keys
():
raise
InvalidTranscriptProvider
(
'{} transcript provider is not supported'
.
format
(
provider
))
raise
InvalidTranscriptProvider
(
'{} transcript provider is not supported'
.
format
(
provider
))
video_transcript
,
__
=
VideoTranscript
.
create_or_update
(
video_id
,
language_code
,
metadata
,
file_data
)
try
:
# Video should be present in edxval in order to attach transcripts to it.
video
=
Video
.
objects
.
get
(
edx_video_id
=
video_id
)
video_transcript
,
__
=
VideoTranscript
.
create_or_update
(
video
,
language_code
,
metadata
,
file_data
)
except
Video
.
DoesNotExist
:
return
None
return
video_transcript
.
url
()
return
video_transcript
.
url
()
...
@@ -338,7 +327,7 @@ def delete_video_transcript(video_id, language_code):
...
@@ -338,7 +327,7 @@ def delete_video_transcript(video_id, language_code):
language_code: language code of a video transcript
language_code: language code of a video transcript
"""
"""
try
:
try
:
video_transcript
=
VideoTranscript
.
objects
.
get
(
video_id
=
video_id
,
language_code
=
language_code
)
video_transcript
=
VideoTranscript
.
objects
.
get
(
video_
_edx_video_
id
=
video_id
,
language_code
=
language_code
)
# delete the actual transcript file from storage
# delete the actual transcript file from storage
video_transcript
.
transcript
.
delete
()
video_transcript
.
transcript
.
delete
()
# delete the record from db
# delete the record from db
...
@@ -775,10 +764,9 @@ def export_to_xml(video_ids, course_id=None, external=False):
...
@@ -775,10 +764,9 @@ def export_to_xml(video_ids, course_id=None, external=False):
Raises:
Raises:
ValVideoNotFoundError: if the video does not exist
ValVideoNotFoundError: if the video does not exist
"""
"""
#
val does not store external videos, so construct transcripts information only.
#
TODO: This will be removed as a part of EDUCATOR-1789
if
external
:
if
external
:
video_el
=
Element
(
'video_asset'
)
return
Element
(
'video_asset'
)
return
create_transcripts_xml
(
video_ids
,
video_el
)
# for an internal video, first video id must be edx_video_id
# for an internal video, first video id must be edx_video_id
video_id
=
video_ids
[
0
]
video_id
=
video_ids
[
0
]
...
@@ -824,7 +812,7 @@ def create_transcripts_xml(video_ids, video_el):
...
@@ -824,7 +812,7 @@ def create_transcripts_xml(video_ids, video_el):
Returns:
Returns:
lxml Element object with transcripts information
lxml Element object with transcripts information
"""
"""
video_transcripts
=
VideoTranscript
.
objects
.
filter
(
video_
id__in
=
video_ids
)
video_transcripts
=
VideoTranscript
.
objects
.
filter
(
video_
_edx_video_id__in
=
video_ids
)
.
order_by
(
'language_code'
)
# create transcripts node only when we have transcripts for a video
# create transcripts node only when we have transcripts for a video
if
video_transcripts
.
exists
():
if
video_transcripts
.
exists
():
transcripts_el
=
SubElement
(
video_el
,
'transcripts'
)
transcripts_el
=
SubElement
(
video_el
,
'transcripts'
)
...
@@ -836,7 +824,7 @@ def create_transcripts_xml(video_ids, video_el):
...
@@ -836,7 +824,7 @@ def create_transcripts_xml(video_ids, video_el):
transcripts_el
,
transcripts_el
,
'transcript'
,
'transcript'
,
{
{
'video_id'
:
video_transcript
.
video_id
,
'video_id'
:
video_transcript
.
video
.
edx_video
_id
,
'file_name'
:
video_transcript
.
transcript
.
name
,
'file_name'
:
video_transcript
.
transcript
.
name
,
'language_code'
:
video_transcript
.
language_code
,
'language_code'
:
video_transcript
.
language_code
,
'file_format'
:
video_transcript
.
file_format
,
'file_format'
:
video_transcript
.
file_format
,
...
@@ -866,9 +854,9 @@ def import_from_xml(xml, edx_video_id, course_id=None):
...
@@ -866,9 +854,9 @@ def import_from_xml(xml, edx_video_id, course_id=None):
if
xml
.
tag
!=
'video_asset'
:
if
xml
.
tag
!=
'video_asset'
:
raise
ValCannotCreateError
(
'Invalid XML'
)
raise
ValCannotCreateError
(
'Invalid XML'
)
#
if edx_video_id does not exist then create video transcripts only
#
TODO this will be moved as a part of EDUCATOR-2173
if
not
edx_video_id
:
if
not
edx_video_id
:
return
create_transcript_objects
(
xml
)
return
# If video with edx_video_id already exists, associate it with the given course_id.
# If video with edx_video_id already exists, associate it with the given course_id.
try
:
try
:
...
@@ -885,9 +873,6 @@ def import_from_xml(xml, edx_video_id, course_id=None):
...
@@ -885,9 +873,6 @@ def import_from_xml(xml, edx_video_id, course_id=None):
if
image_file_name
:
if
image_file_name
:
VideoImage
.
create_or_update
(
course_video
,
image_file_name
)
VideoImage
.
create_or_update
(
course_video
,
image_file_name
)
# import transcripts
create_transcript_objects
(
xml
)
return
return
except
ValidationError
as
err
:
except
ValidationError
as
err
:
logger
.
exception
(
err
.
message
)
logger
.
exception
(
err
.
message
)
...
@@ -934,7 +919,7 @@ def create_transcript_objects(xml):
...
@@ -934,7 +919,7 @@ def create_transcript_objects(xml):
"""
"""
for
transcript
in
xml
.
findall
(
'.//transcripts/transcript'
):
for
transcript
in
xml
.
findall
(
'.//transcripts/transcript'
):
try
:
try
:
VideoTranscript
.
create_or_update
(
create_or_update_video_transcript
(
transcript
.
attrib
[
'video_id'
],
transcript
.
attrib
[
'video_id'
],
transcript
.
attrib
[
'language_code'
],
transcript
.
attrib
[
'language_code'
],
metadata
=
dict
(
metadata
=
dict
(
...
...
edxval/migrations/0010_add_video_as_foreign_key.py
0 → 100644
View file @
727e643d
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'edxval'
,
'0009_auto_20171127_0406'
),
]
operations
=
[
migrations
.
AlterUniqueTogether
(
name
=
'videotranscript'
,
unique_together
=
set
([(
'language_code'
,)]),
),
migrations
.
RemoveField
(
model_name
=
'videotranscript'
,
name
=
'video_id'
,
),
migrations
.
AddField
(
model_name
=
'videotranscript'
,
name
=
'video'
,
field
=
models
.
ForeignKey
(
related_name
=
'video_transcripts'
,
to
=
'edxval.Video'
,
null
=
True
),
),
migrations
.
AlterUniqueTogether
(
name
=
'videotranscript'
,
unique_together
=
set
([(
'video'
,
'language_code'
)]),
),
]
edxval/models.py
View file @
727e643d
...
@@ -404,7 +404,7 @@ class VideoTranscript(TimeStampedModel):
...
@@ -404,7 +404,7 @@ class VideoTranscript(TimeStampedModel):
"""
"""
Transcript for a video
Transcript for a video
"""
"""
video
_id
=
models
.
CharField
(
max_length
=
255
,
help_text
=
'It can be an edx_video_id or an external video id'
)
video
=
models
.
ForeignKey
(
Video
,
related_name
=
'video_transcripts'
,
null
=
True
)
transcript
=
CustomizableFileField
()
transcript
=
CustomizableFileField
()
language_code
=
models
.
CharField
(
max_length
=
50
,
db_index
=
True
)
language_code
=
models
.
CharField
(
max_length
=
50
,
db_index
=
True
)
provider
=
models
.
CharField
(
provider
=
models
.
CharField
(
...
@@ -415,27 +415,19 @@ class VideoTranscript(TimeStampedModel):
...
@@ -415,27 +415,19 @@ class VideoTranscript(TimeStampedModel):
file_format
=
models
.
CharField
(
max_length
=
20
,
db_index
=
True
,
choices
=
TranscriptFormat
.
CHOICES
)
file_format
=
models
.
CharField
(
max_length
=
20
,
db_index
=
True
,
choices
=
TranscriptFormat
.
CHOICES
)
class
Meta
:
class
Meta
:
unique_together
=
(
'video
_id
'
,
'language_code'
)
unique_together
=
(
'video'
,
'language_code'
)
@property
@property
def
filename
(
self
):
def
filename
(
self
):
"""
"""
Returns readable filename for a transcript
Returns readable filename for a transcript
"""
"""
try
:
client_id
,
__
=
os
.
path
.
splitext
(
self
.
video
.
client_video_id
)
video
=
Video
.
objects
.
get
(
edx_video_id
=
self
.
video_id
)
client_id
,
__
=
os
.
path
.
splitext
(
video
.
client_video_id
)
file_name
=
u'{name}-{language}.{format}'
.
format
(
file_name
=
u'{name}-{language}.{format}'
.
format
(
name
=
client_id
,
name
=
client_id
,
language
=
self
.
language_code
,
language
=
self
.
language_code
,
format
=
self
.
file_format
format
=
self
.
file_format
)
)
except
Video
.
DoesNotExist
:
file_name
=
u'{name}-{language}.{format}'
.
format
(
name
=
self
.
video_id
,
language
=
self
.
language_code
,
format
=
self
.
file_format
)
return
file_name
return
file_name
...
@@ -449,19 +441,19 @@ class VideoTranscript(TimeStampedModel):
...
@@ -449,19 +441,19 @@ class VideoTranscript(TimeStampedModel):
language_code(unicode): language of the requested transcript
language_code(unicode): language of the requested transcript
"""
"""
try
:
try
:
transcript
=
cls
.
objects
.
get
(
video_id
=
video_id
,
language_code
=
language_code
)
transcript
=
cls
.
objects
.
get
(
video_
_edx_video_
id
=
video_id
,
language_code
=
language_code
)
except
cls
.
DoesNotExist
:
except
cls
.
DoesNotExist
:
transcript
=
None
transcript
=
None
return
transcript
return
transcript
@classmethod
@classmethod
def
create_or_update
(
cls
,
video
_id
,
language_code
,
metadata
,
file_data
=
None
):
def
create_or_update
(
cls
,
video
,
language_code
,
metadata
,
file_data
=
None
):
"""
"""
Create or update Transcript object.
Create or update Transcript object.
Arguments:
Arguments:
video
_id (str): unique id for a video
video
(Video): Video for which transcript is going to be saved.
language_code (str): language code for (to be created/updated) transcript
language_code (str): language code for (to be created/updated) transcript
metadata (dict): A dict containing (to be overwritten) properties
metadata (dict): A dict containing (to be overwritten) properties
file_data (InMemoryUploadedFile): File data to be saved
file_data (InMemoryUploadedFile): File data to be saved
...
@@ -469,7 +461,7 @@ class VideoTranscript(TimeStampedModel):
...
@@ -469,7 +461,7 @@ class VideoTranscript(TimeStampedModel):
Returns:
Returns:
Returns a tuple of (video_transcript, created).
Returns a tuple of (video_transcript, created).
"""
"""
video_transcript
,
created
=
cls
.
objects
.
get_or_create
(
video
_id
=
video_id
,
language_code
=
language_code
)
video_transcript
,
created
=
cls
.
objects
.
get_or_create
(
video
=
video
,
language_code
=
language_code
)
for
prop
,
value
in
metadata
.
iteritems
():
for
prop
,
value
in
metadata
.
iteritems
():
if
prop
in
[
'language_code'
,
'file_format'
,
'provider'
]:
if
prop
in
[
'language_code'
,
'file_format'
,
'provider'
]:
...
@@ -489,7 +481,7 @@ class VideoTranscript(TimeStampedModel):
...
@@ -489,7 +481,7 @@ class VideoTranscript(TimeStampedModel):
try
:
try
:
video_transcript
.
transcript
.
save
(
file_name
,
transcript_file_data
)
video_transcript
.
transcript
.
save
(
file_name
,
transcript_file_data
)
except
Exception
:
except
Exception
:
logger
.
exception
(
'VAL: Transcript save failed to storage for video_id [
%
s]'
,
video_id
)
logger
.
exception
(
'VAL: Transcript save failed to storage for video_id [
%
s]'
,
video
.
edx_video
_id
)
raise
raise
video_transcript
.
save
()
video_transcript
.
save
()
...
@@ -503,7 +495,7 @@ class VideoTranscript(TimeStampedModel):
...
@@ -503,7 +495,7 @@ class VideoTranscript(TimeStampedModel):
return
storage
.
url
(
self
.
transcript
.
name
)
return
storage
.
url
(
self
.
transcript
.
name
)
def
__unicode__
(
self
):
def
__unicode__
(
self
):
return
u'{lang} Transcript for {video}'
.
format
(
lang
=
self
.
language_code
,
video
=
self
.
video_id
)
return
u'{lang} Transcript for {video}'
.
format
(
lang
=
self
.
language_code
,
video
=
self
.
video
.
edx_video
_id
)
class
Cielo24Turnaround
(
object
):
class
Cielo24Turnaround
(
object
):
...
...
edxval/serializers.py
View file @
727e643d
...
@@ -57,11 +57,17 @@ class TranscriptSerializer(serializers.ModelSerializer):
...
@@ -57,11 +57,17 @@ class TranscriptSerializer(serializers.ModelSerializer):
"""
"""
class
Meta
:
# pylint: disable=C1001, C0111
class
Meta
:
# pylint: disable=C1001, C0111
model
=
VideoTranscript
model
=
VideoTranscript
lookup_field
=
'video_id'
fields
=
(
'video_id'
,
'url'
,
'language_code'
,
'provider'
,
'file_format'
)
fields
=
(
'video_id'
,
'url'
,
'language_code'
,
'provider'
,
'file_format'
)
video_id
=
serializers
.
SerializerMethodField
()
url
=
serializers
.
SerializerMethodField
()
url
=
serializers
.
SerializerMethodField
()
def
get_video_id
(
self
,
transcript
):
"""
Returns an edx video ID for the related video.
"""
return
transcript
.
video
.
edx_video_id
def
get_url
(
self
,
transcript
):
def
get_url
(
self
,
transcript
):
"""
"""
Retrieves the transcript url.
Retrieves the transcript url.
...
...
edxval/tests/constants.py
View file @
727e643d
...
@@ -378,14 +378,6 @@ VIDEO_TRANSCRIPT_3PLAY = dict(
...
@@ -378,14 +378,6 @@ VIDEO_TRANSCRIPT_3PLAY = dict(
file_format
=
TranscriptFormat
.
SJSON
,
file_format
=
TranscriptFormat
.
SJSON
,
)
)
VIDEO_TRANSCRIPT_CUSTOM
=
dict
(
video_id
=
'external_video_id'
,
language_code
=
'de'
,
transcript
=
'wow.srt'
,
provider
=
TranscriptProviderType
.
CUSTOM
,
file_format
=
TranscriptFormat
.
SRT
,
)
TRANSCRIPT_PREFERENCES_CIELO24
=
dict
(
TRANSCRIPT_PREFERENCES_CIELO24
=
dict
(
course_id
=
'edX/DemoX/Demo_Course'
,
course_id
=
'edX/DemoX/Demo_Course'
,
provider
=
TranscriptProviderType
.
CIELO24
,
provider
=
TranscriptProviderType
.
CIELO24
,
...
...
edxval/tests/test_api.py
View file @
727e643d
...
@@ -4,7 +4,6 @@ Tests for the API for Video Abstraction Layer
...
@@ -4,7 +4,6 @@ Tests for the API for Video Abstraction Layer
"""
"""
import
json
import
json
import
os
import
os
import
tempfile
import
mock
import
mock
from
ddt
import
data
,
ddt
,
unpack
from
ddt
import
data
,
ddt
,
unpack
...
@@ -908,16 +907,13 @@ class ExportTest(TestCase):
...
@@ -908,16 +907,13 @@ class ExportTest(TestCase):
**
constants
.
ENCODED_VIDEO_DICT_HLS
**
constants
.
ENCODED_VIDEO_DICT_HLS
)
)
# create external video transcripts
VideoTranscript
.
objects
.
create
(
**
constants
.
VIDEO_TRANSCRIPT_CUSTOM
)
video_transcript
=
dict
(
constants
.
VIDEO_TRANSCRIPT_CUSTOM
,
language_code
=
u'ar'
)
VideoTranscript
.
objects
.
create
(
**
video_transcript
)
video_transcript
=
dict
(
constants
.
VIDEO_TRANSCRIPT_CUSTOM
,
video_id
=
u'external_video_id2'
,
language_code
=
u'fr'
)
VideoTranscript
.
objects
.
create
(
**
video_transcript
)
# create internal video transcripts
# create internal video transcripts
VideoTranscript
.
objects
.
create
(
**
constants
.
VIDEO_TRANSCRIPT_CIELO24
)
transcript_data
=
dict
(
constants
.
VIDEO_TRANSCRIPT_CIELO24
,
video
=
video
)
VideoTranscript
.
objects
.
create
(
**
constants
.
VIDEO_TRANSCRIPT_3PLAY
)
transcript_data
.
pop
(
'video_id'
)
VideoTranscript
.
objects
.
create
(
**
transcript_data
)
transcript_data
=
dict
(
constants
.
VIDEO_TRANSCRIPT_3PLAY
,
video
=
video
)
transcript_data
.
pop
(
'video_id'
)
VideoTranscript
.
objects
.
create
(
**
transcript_data
)
def
assert_xml_equal
(
self
,
left
,
right
):
def
assert_xml_equal
(
self
,
left
,
right
):
"""
"""
...
@@ -949,8 +945,8 @@ class ExportTest(TestCase):
...
@@ -949,8 +945,8 @@ class ExportTest(TestCase):
)
)
@data
(
@data
(
{
'course_id'
:
None
,
'image'
:
''
},
{
'course_id'
:
None
,
'image'
:
''
},
{
'course_id'
:
'test-course'
,
'image'
:
'image.jpg'
},
{
'course_id'
:
'test-course'
,
'image'
:
'image.jpg'
},
)
)
@unpack
@unpack
def
test_basic
(
self
,
course_id
,
image
):
def
test_basic
(
self
,
course_id
,
image
):
...
@@ -960,8 +956,8 @@ class ExportTest(TestCase):
...
@@ -960,8 +956,8 @@ class ExportTest(TestCase):
<encoded_video url="http://www.meowmagic.com" file_size="33" bitrate="44" profile="desktop"/>
<encoded_video url="http://www.meowmagic.com" file_size="33" bitrate="44" profile="desktop"/>
<encoded_video url="https://www.tmnt.com/tmnt101.m3u8" file_size="100" bitrate="0" profile="hls"/>
<encoded_video url="https://www.tmnt.com/tmnt101.m3u8" file_size="100" bitrate="0" profile="hls"/>
<transcripts>
<transcripts>
<transcript file_format="sjson" file_name="edxval/tests/data/wow.sjson" language_code="de" provider="3PlayMedia" video_id="
super-soaker
"/>
<transcript file_format="sjson" file_name="edxval/tests/data/wow.sjson" language_code="de" provider="3PlayMedia" video_id="
{video_id}
"/>
<transcript file_format="srt" file_name="wow.srt" language_code="en" provider="Cielo24" video_id="
super-soaker
" />
<transcript file_format="srt" file_name="wow.srt" language_code="en" provider="Cielo24" video_id="
{video_id}
" />
</transcripts>
</transcripts>
</video_asset>
</video_asset>
"""
.
format
(
image
=
image
,
video_id
=
constants
.
VIDEO_DICT_FISH
[
'edx_video_id'
]))
"""
.
format
(
image
=
image
,
video_id
=
constants
.
VIDEO_DICT_FISH
[
'edx_video_id'
]))
...
@@ -975,26 +971,6 @@ class ExportTest(TestCase):
...
@@ -975,26 +971,6 @@ class ExportTest(TestCase):
with
self
.
assertRaises
(
ValVideoNotFoundError
):
with
self
.
assertRaises
(
ValVideoNotFoundError
):
api
.
export_to_xml
([
"unknown_video"
])
api
.
export_to_xml
([
"unknown_video"
])
def
test_external_video_transcript
(
self
):
"""
Verify that transcript export for multiple external videos is working as expected.
"""
video_ids
=
[
'missing'
,
'external_video_id'
,
'missing2'
,
'external_video_id2'
]
expected
=
self
.
parse_xml
(
"""
<video_asset>
<transcripts>
<transcript file_format="srt" file_name="wow.srt" language_code="ar" provider="Custom" video_id="external_video_id"/>
<transcript file_format="srt" file_name="wow.srt" language_code="de" provider="Custom" video_id="external_video_id"/>
<transcript file_format="srt" file_name="wow.srt" language_code="fr" provider="Custom" video_id="external_video_id2"/>
</transcripts>
</video_asset>
"""
.
format
(
video_id
=
''
))
self
.
assert_xml_equal
(
api
.
export_to_xml
(
video_ids
,
external
=
True
),
expected
)
def
test_with_multiple_video_ids
(
self
):
def
test_with_multiple_video_ids
(
self
):
"""
"""
Verify that transcript export with multiple video ids is working as expected.
Verify that transcript export with multiple video ids is working as expected.
...
@@ -1006,8 +982,7 @@ class ExportTest(TestCase):
...
@@ -1006,8 +982,7 @@ class ExportTest(TestCase):
<encoded_video bitrate="44" file_size="33" profile="desktop" url="http://www.meowmagic.com" />
<encoded_video bitrate="44" file_size="33" profile="desktop" url="http://www.meowmagic.com" />
<encoded_video bitrate="0" file_size="100" profile="hls" url="https://www.tmnt.com/tmnt101.m3u8" />
<encoded_video bitrate="0" file_size="100" profile="hls" url="https://www.tmnt.com/tmnt101.m3u8" />
<transcripts>
<transcripts>
<transcript file_format="srt" file_name="wow.srt" language_code="ar" provider="Custom" video_id="external_video_id" />
<transcript file_format="sjson" file_name="edxval/tests/data/wow.sjson" language_code="de" provider="3PlayMedia" video_id="super-soaker"/>
<transcript file_format="srt" file_name="wow.srt" language_code="de" provider="Custom" video_id="external_video_id"/>
<transcript file_format="srt" file_name="wow.srt" language_code="en" provider="Cielo24" video_id="super-soaker" />
<transcript file_format="srt" file_name="wow.srt" language_code="en" provider="Cielo24" video_id="super-soaker" />
</transcripts>
</transcripts>
</video_asset>
</video_asset>
...
@@ -1115,7 +1090,7 @@ class ImportTest(TestCase):
...
@@ -1115,7 +1090,7 @@ class ImportTest(TestCase):
Compare `received` with `expected` and assert if not equal
Compare `received` with `expected` and assert if not equal
"""
"""
# Verify total number of expected transcripts for a video
# Verify total number of expected transcripts for a video
video_transcripts
=
VideoTranscript
.
objects
.
filter
(
video_id
=
video_id
)
video_transcripts
=
VideoTranscript
.
objects
.
filter
(
video_
_edx_video_
id
=
video_id
)
self
.
assertEqual
(
video_transcripts
.
count
(),
len
(
expected_transcripts
))
self
.
assertEqual
(
video_transcripts
.
count
(),
len
(
expected_transcripts
))
# Verify data for each transcript
# Verify data for each transcript
...
@@ -1125,7 +1100,7 @@ class ImportTest(TestCase):
...
@@ -1125,7 +1100,7 @@ class ImportTest(TestCase):
# get the imported transcript and rename `url` key
# get the imported transcript and rename `url` key
received
=
api
.
TranscriptSerializer
(
received
=
api
.
TranscriptSerializer
(
VideoTranscript
.
objects
.
get
(
video_id
=
video_id
,
language_code
=
language_code
)
VideoTranscript
.
objects
.
get
(
video_
_edx_video_
id
=
video_id
,
language_code
=
language_code
)
)
.
data
)
.
data
received
[
'name'
]
=
received
.
pop
(
'url'
)
received
[
'name'
]
=
received
.
pop
(
'url'
)
...
@@ -1143,7 +1118,7 @@ class ImportTest(TestCase):
...
@@ -1143,7 +1118,7 @@ class ImportTest(TestCase):
# there must not be any transcript before import
# there must not be any transcript before import
with
self
.
assertRaises
(
VideoTranscript
.
DoesNotExist
):
with
self
.
assertRaises
(
VideoTranscript
.
DoesNotExist
):
VideoTranscript
.
objects
.
get
(
video_id
=
constants
.
VIDEO_DICT_STAR
[
'edx_video_id'
])
VideoTranscript
.
objects
.
get
(
video_
_edx_video_
id
=
constants
.
VIDEO_DICT_STAR
[
'edx_video_id'
])
api
.
import_from_xml
(
xml
,
constants
.
VIDEO_DICT_STAR
[
'edx_video_id'
],
new_course_id
)
api
.
import_from_xml
(
xml
,
constants
.
VIDEO_DICT_STAR
[
'edx_video_id'
],
new_course_id
)
...
@@ -1209,7 +1184,7 @@ class ImportTest(TestCase):
...
@@ -1209,7 +1184,7 @@ class ImportTest(TestCase):
# there must not be any transcript before import
# there must not be any transcript before import
with
self
.
assertRaises
(
VideoTranscript
.
DoesNotExist
):
with
self
.
assertRaises
(
VideoTranscript
.
DoesNotExist
):
VideoTranscript
.
objects
.
get
(
video_id
=
constants
.
VIDEO_DICT_FISH
[
"edx_video_id"
])
VideoTranscript
.
objects
.
get
(
video_
_edx_video_
id
=
constants
.
VIDEO_DICT_FISH
[
"edx_video_id"
])
api
.
import_from_xml
(
xml
,
constants
.
VIDEO_DICT_FISH
[
"edx_video_id"
],
course_id
)
api
.
import_from_xml
(
xml
,
constants
.
VIDEO_DICT_FISH
[
"edx_video_id"
],
course_id
)
...
@@ -1228,7 +1203,7 @@ class ImportTest(TestCase):
...
@@ -1228,7 +1203,7 @@ class ImportTest(TestCase):
self
.
assert_transcripts
(
self
.
assert_transcripts
(
constants
.
VIDEO_DICT_FISH
[
"edx_video_id"
],
constants
.
VIDEO_DICT_FISH
[
"edx_video_id"
],
[
transcript_data
]
[]
)
)
def
test_existing_video_with_invalid_course_id
(
self
):
def
test_existing_video_with_invalid_course_id
(
self
):
...
@@ -1290,26 +1265,6 @@ class ImportTest(TestCase):
...
@@ -1290,26 +1265,6 @@ class ImportTest(TestCase):
xml
=
self
.
make_import_xml
(
video_dict
=
constants
.
VIDEO_DICT_FISH
)
xml
=
self
.
make_import_xml
(
video_dict
=
constants
.
VIDEO_DICT_FISH
)
self
.
assert_invalid_import
(
xml
,
"x"
*
300
)
self
.
assert_invalid_import
(
xml
,
"x"
*
300
)
def
test_external_video_transcript
(
self
):
"""
Verify that transcript import for external video working as expected.
"""
external_video_id
=
'little-star'
xml
=
etree
.
fromstring
(
"""
<video_asset>
<transcripts>
<transcript file_name="wow.srt" language_code="en" file_format="srt" provider='Cielo24' video_id="{video_id}"/>
<transcript file_name="edxval/tests/data/wow.sjson" language_code="de" file_format="sjson" provider='3PlayMedia' video_id="{video_id}"/>
</transcripts>
</video_asset>
"""
.
format
(
video_id
=
external_video_id
))
with
self
.
assertRaises
(
VideoTranscript
.
DoesNotExist
):
VideoTranscript
.
objects
.
get
(
video_id
=
external_video_id
)
api
.
import_from_xml
(
xml
,
''
)
self
.
assert_transcripts
(
external_video_id
,
[
self
.
transcript_data1
,
self
.
transcript_data2
])
def
test_external_no_video_transcript
(
self
):
def
test_external_no_video_transcript
(
self
):
"""
"""
Verify that transcript import for external video working as expected when there is no transcript.
Verify that transcript import for external video working as expected when there is no transcript.
...
@@ -1325,7 +1280,7 @@ class ImportTest(TestCase):
...
@@ -1325,7 +1280,7 @@ class ImportTest(TestCase):
"""
"""
Verify that video transcript import working as expected if transcript xml data is missing.
Verify that video transcript import working as expected if transcript xml data is missing.
"""
"""
video_id
=
'
little-sta
r'
video_id
=
'
super-soake
r'
transcript_xml
=
'<transcript file_name="wow.srt" language_code="en" file_format="srt" provider="Cielo24"/>'
transcript_xml
=
'<transcript file_name="wow.srt" language_code="en" file_format="srt" provider="Cielo24"/>'
xml
=
etree
.
fromstring
(
"""
xml
=
etree
.
fromstring
(
"""
<video_asset>
<video_asset>
...
@@ -1338,7 +1293,7 @@ class ImportTest(TestCase):
...
@@ -1338,7 +1293,7 @@ class ImportTest(TestCase):
# there should be no video transcript before import
# there should be no video transcript before import
with
self
.
assertRaises
(
VideoTranscript
.
DoesNotExist
):
with
self
.
assertRaises
(
VideoTranscript
.
DoesNotExist
):
VideoTranscript
.
objects
.
get
(
video_id
=
video_id
)
VideoTranscript
.
objects
.
get
(
video_
_edx_video_
id
=
video_id
)
api
.
create_transcript_objects
(
xml
)
api
.
create_transcript_objects
(
xml
)
...
@@ -1347,7 +1302,7 @@ class ImportTest(TestCase):
...
@@ -1347,7 +1302,7 @@ class ImportTest(TestCase):
transcript_xml
transcript_xml
)
)
self
.
assert_transcripts
(
video_id
,
[
self
.
transcript_data
2
])
self
.
assert_transcripts
(
video_id
,
[
self
.
transcript_data
3
])
class
GetCourseVideoRemoveTest
(
TestCase
):
class
GetCourseVideoRemoveTest
(
TestCase
):
...
@@ -1676,60 +1631,94 @@ class TranscriptTest(TestCase):
...
@@ -1676,60 +1631,94 @@ class TranscriptTest(TestCase):
"""
"""
Creates video and video transcript objects.
Creates video and video transcript objects.
"""
"""
self
.
video1
=
Video
.
objects
.
create
(
**
constants
.
VIDEO_DICT_FISH
)
self
.
edx_video_id1
=
self
.
video1
.
edx_video_id
self
.
video2
=
Video
.
objects
.
create
(
**
constants
.
VIDEO_DICT_DIFFERENT_ID_FISH
)
self
.
edx_video_id2
=
self
.
video2
.
edx_video_id
self
.
transcript_data1
=
dict
(
constants
.
VIDEO_TRANSCRIPT_CIELO24
)
self
.
transcript_data1
[
'name'
]
=
self
.
transcript_data1
.
pop
(
'transcript'
)
self
.
transcript_data2
=
dict
(
constants
.
VIDEO_TRANSCRIPT_3PLAY
)
self
.
transcript_data2
[
'name'
]
=
self
.
transcript_data2
.
pop
(
'transcript'
)
self
.
transcript1
=
VideoTranscript
.
objects
.
create
(
**
constants
.
VIDEO_TRANSCRIPT_CIELO24
)
self
.
transcript2
=
VideoTranscript
.
objects
.
create
(
**
constants
.
VIDEO_TRANSCRIPT_3PLAY
)
self
.
video_id
=
'0987654321'
self
.
arrow_transcript_path
=
'edxval/tests/data/The_Arrow.srt'
self
.
flash_transcript_path
=
'edxval/tests/data/The_Flash.srt'
self
.
flash_transcript_path
=
'edxval/tests/data/The_Flash.srt'
self
.
transcript_url
=
api
.
create_or_update_video_transcript
(
self
.
arrow_transcript_path
=
'edxval/tests/data/The_Arrow.srt'
self
.
video_id
,
'ur'
,
# Set up a video (video_id -> super-soaker) with 'en' and 'fr' transcripts.
metadata
=
{
'file_format'
:
TranscriptFormat
.
SRT
},
video_and_transcripts
=
self
.
setup_video_with_transcripts
(
file_data
=
File
(
open
(
self
.
arrow_transcript_path
))
video_data
=
constants
.
VIDEO_DICT_FISH
,
transcripts_data
=
[
{
'language_code'
:
'en'
,
'provider'
:
TranscriptProviderType
.
THREE_PLAY_MEDIA
,
'file_name'
:
None
,
'file_format'
:
TranscriptFormat
.
SRT
,
'file_data'
:
File
(
open
(
self
.
flash_transcript_path
))
},
{
'language_code'
:
'fr'
,
'provider'
:
TranscriptProviderType
.
CIELO24
,
'file_name'
:
None
,
'file_format'
:
TranscriptFormat
.
SRT
,
'file_data'
:
ContentFile
(
FILE_DATA
)
}
]
)
)
self
.
video1
=
video_and_transcripts
[
'video'
]
self
.
v1_transcript1
=
video_and_transcripts
[
'transcripts'
][
'en'
]
self
.
v1_transcript2
=
video_and_transcripts
[
'transcripts'
][
'fr'
]
# create a temporary transcript file
# Set up another video (video_id -> medium-soaker) with 'de' and 'zh' transcripts.
_
,
self
.
transcript_file
=
tempfile
.
mkstemp
(
video_and_transcripts
=
self
.
setup_video_with_transcripts
(
suffix
=
'.srt'
,
video_data
=
constants
.
VIDEO_DICT_DIFFERENT_ID_FISH
,
dir
=
'edxval/tests/data/'
transcripts_data
=
[
{
'language_code'
:
'de'
,
'provider'
:
TranscriptProviderType
.
CUSTOM
,
'file_name'
:
None
,
'file_format'
:
TranscriptFormat
.
SRT
,
'file_data'
:
File
(
open
(
self
.
arrow_transcript_path
))
},
{
'language_code'
:
'zh'
,
'provider'
:
TranscriptProviderType
.
CUSTOM
,
'file_name'
:
'non/existent/transcript/path'
,
'file_format'
:
TranscriptFormat
.
SRT
,
'file_data'
:
None
}
]
)
)
with
open
(
self
.
transcript_file
,
'w'
)
as
outfile
:
self
.
video2
=
video_and_transcripts
[
'video'
]
outfile
.
write
(
FILE_DATA
)
self
.
v2_transcript1
=
video_and_transcripts
[
'transcripts'
][
'de'
]
self
.
v2_transcript2
=
video_and_transcripts
[
'transcripts'
][
'zh'
]
self
.
transcript3
=
VideoTranscript
.
objects
.
create
(
def
setup_video_with_transcripts
(
self
,
video_data
,
transcripts_data
):
video_id
=
'super-soaker'
,
"""
language_code
=
'fr'
,
Setup a video with transcripts and returns them
transcript
=
self
.
transcript_file
,
"""
provider
=
TranscriptProviderType
.
THREE_PLAY_MEDIA
,
result
=
dict
(
video
=
None
,
transcripts
=
{})
file_format
=
TranscriptFormat
.
SRT
,
result
[
'video'
]
=
Video
.
objects
.
create
(
**
video_data
)
for
transcript_data
in
transcripts_data
:
language_code
=
transcript_data
[
'language_code'
]
transcript
,
__
=
VideoTranscript
.
create_or_update
(
video
=
result
[
'video'
],
language_code
=
language_code
,
metadata
=
{
'file_name'
:
transcript_data
[
'file_name'
],
'file_format'
:
transcript_data
[
'file_format'
],
'provider'
:
transcript_data
[
'provider'
]
},
file_data
=
transcript_data
[
'file_data'
]
)
)
result
[
'transcripts'
][
language_code
]
=
transcript
return
result
def
tearDown
(
self
):
def
tearDown
(
self
):
"""
"""
Reverse the setup
Reverse the setup
"""
"""
# Remove the temporary transcript file
# Remove the transcript files
if
os
.
path
.
exists
(
self
.
transcript_file
):
self
.
v1_transcript1
.
transcript
.
delete
()
os
.
remove
(
self
.
transcript_file
)
self
.
v1_transcript2
.
transcript
.
delete
()
self
.
v2_transcript1
.
transcript
.
delete
()
@data
(
@data
(
{
'video_id'
:
'super-soaker'
,
'language_code'
:
'en'
,
'expected_availability'
:
True
},
{
'video_id'
:
'super-soaker'
,
'language_code'
:
'en'
,
'expected_availability'
:
True
},
{
'video_id'
:
'super-soaker'
,
'language_code'
:
None
,
'expected_availability'
:
True
},
{
'video_id'
:
'super-soaker'
,
'language_code'
:
None
,
'expected_availability'
:
True
},
{
'video_id'
:
'super123'
,
'language_code'
:
'en'
,
'expected_availability'
:
False
},
{
'video_id'
:
'super123'
,
'language_code'
:
'en'
,
'expected_availability'
:
False
},
{
'video_id'
:
'super-soaker'
,
'language_code'
:
'ro'
,
'expected_availability'
:
False
},
{
'video_id'
:
'super-soaker'
,
'language_code'
:
'ro'
,
'expected_availability'
:
False
},
{
'video_id'
:
'medium-soaker'
,
'language_code'
:
'de'
,
'expected_availability'
:
True
},
)
)
@unpack
@unpack
def
test_is_transcript_available
(
self
,
video_id
,
language_code
,
expected_availability
):
def
test_is_transcript_available
(
self
,
video_id
,
language_code
,
expected_availability
):
...
@@ -1754,13 +1743,13 @@ class TranscriptTest(TestCase):
...
@@ -1754,13 +1743,13 @@ class TranscriptTest(TestCase):
"""
"""
Verify that `get_video_transcript` works as expected if transcript is found.
Verify that `get_video_transcript` works as expected if transcript is found.
"""
"""
transcript
=
api
.
get_video_transcript
(
u'
0987654321'
,
u'u
r'
)
transcript
=
api
.
get_video_transcript
(
u'
super-soaker'
,
u'f
r'
)
expectation
=
{
expectation
=
{
'video_id'
:
u'
0987654321
'
,
'video_id'
:
u'
super-soaker
'
,
'url'
:
self
.
transcript_url
,
'url'
:
self
.
v1_transcript2
.
url
()
,
'file_format'
:
TranscriptFormat
.
SRT
,
'file_format'
:
TranscriptFormat
.
SRT
,
'provider'
:
TranscriptProviderType
.
C
USTOM
,
'provider'
:
TranscriptProviderType
.
C
IELO24
,
'language_code'
:
u'
u
r'
'language_code'
:
u'
f
r'
}
}
self
.
assertDictEqual
(
transcript
,
expectation
)
self
.
assertDictEqual
(
transcript
,
expectation
)
...
@@ -1770,17 +1759,17 @@ class TranscriptTest(TestCase):
...
@@ -1770,17 +1759,17 @@ class TranscriptTest(TestCase):
Verify that `get_video_transcript_data` logs and raises an exception.
Verify that `get_video_transcript_data` logs and raises an exception.
"""
"""
with
self
.
assertRaises
(
IOError
):
with
self
.
assertRaises
(
IOError
):
api
.
get_video_transcript_data
(
video_ids
=
[
'
super-soaker'
],
language_code
=
u'en
'
)
api
.
get_video_transcript_data
(
video_ids
=
[
'
medium-soaker'
],
language_code
=
u'zh
'
)
mock_logger
.
exception
.
assert_called_with
(
mock_logger
.
exception
.
assert_called_with
(
'[edx-val] Error while retrieving transcript for video=
%
s -- language_code=
%
s'
,
'[edx-val] Error while retrieving transcript for video=
%
s -- language_code=
%
s'
,
'
super
-soaker'
,
'
medium
-soaker'
,
'
en
'
,
'
zh
'
,
)
)
@data
(
@data
(
{
'video_ids'
:
[
'non-existant-video'
,
'another-non-existant-id'
],
'language_code'
:
'en'
,
'result'
:
None
},
{
'video_ids'
:
[
'non-existant-video'
,
'another-non-existant-id'
],
'language_code'
:
'en'
,
'result'
:
None
},
{
'video_ids'
:
[
'non-existant-video'
,
'
0987654321'
],
'language_code'
:
'en
'
,
'result'
:
None
},
{
'video_ids'
:
[
'non-existant-video'
,
'
super-soaker'
],
'language_code'
:
'zh
'
,
'result'
:
None
},
)
)
@unpack
@unpack
def
test_get_video_transcript_data_not_found
(
self
,
video_ids
,
language_code
,
result
):
def
test_get_video_transcript_data_not_found
(
self
,
video_ids
,
language_code
,
result
):
...
@@ -1791,11 +1780,11 @@ class TranscriptTest(TestCase):
...
@@ -1791,11 +1780,11 @@ class TranscriptTest(TestCase):
self
.
assertEqual
(
transcript
,
result
)
self
.
assertEqual
(
transcript
,
result
)
@data
(
@data
(
(
'
de'
,
'Shallow Swordfish-de.sjson'
,
'edxval/tests/data/wow.sjson
'
),
(
'
super-soaker'
,
'en'
,
'Shallow Swordfish-en.srt'
,
'edxval/tests/data/The_Flash.srt
'
),
(
'
ur'
,
'0987654321-ur
.srt'
,
'edxval/tests/data/The_Arrow.srt'
)
(
'
medium-soaker'
,
'de'
,
'Shallow Swordfish-de
.srt'
,
'edxval/tests/data/The_Arrow.srt'
)
)
)
@unpack
@unpack
def
test_get_video_transcript_data
(
self
,
language_code
,
expected_file_name
,
expected_transcript_path
):
def
test_get_video_transcript_data
(
self
,
video_id
,
language_code
,
expected_file_name
,
expected_transcript_path
):
"""
"""
Verify that `get_video_transcript_data` api function works as expected.
Verify that `get_video_transcript_data` api function works as expected.
"""
"""
...
@@ -1804,75 +1793,17 @@ class TranscriptTest(TestCase):
...
@@ -1804,75 +1793,17 @@ class TranscriptTest(TestCase):
'content'
:
File
(
open
(
expected_transcript_path
))
.
read
()
'content'
:
File
(
open
(
expected_transcript_path
))
.
read
()
}
}
transcript
=
api
.
get_video_transcript_data
(
transcript
=
api
.
get_video_transcript_data
(
video_ids
=
[
'super-soaker'
,
'0987654321'
],
video_ids
=
[
video_id
,
'0987654321'
],
language_code
=
language_code
language_code
=
language_code
)
)
self
.
assertDictEqual
(
transcript
,
expected_transcript
)
self
.
assertDictEqual
(
transcript
,
expected_transcript
)
@data
(
def
test_get_video_transcript_url
(
self
):
{
'video_id'
:
'super-soaker'
,
'result'
:
True
},
{
'video_id'
:
'super-soaker1'
,
'result'
:
False
},
)
@unpack
def
test_get_video_transcripts
(
self
,
video_id
,
result
):
"""
Verify that `get_video_transcripts` api function works as expected.
"""
transcripts
=
api
.
get_video_transcripts
(
video_id
)
if
result
:
self
.
assertEqual
(
len
(
transcripts
),
3
)
for
transcript
,
transcript_data
in
zip
(
transcripts
,
[
self
.
transcript_data2
,
self
.
transcript_data1
]):
transcript_data
[
'url'
]
=
transcript_data
.
pop
(
'name'
)
self
.
assertEqual
(
transcript
,
transcript_data
)
else
:
self
.
assertEqual
(
transcripts
,
[])
def
test_create_video_transcript
(
self
):
"""
Verify that `create_or_update_video_transcript` api function creates transcript if there is no already.
"""
transcript_data
=
dict
(
self
.
transcript_data1
)
transcript_data
[
'language_code'
]
=
'ur'
with
self
.
assertRaises
(
VideoTranscript
.
DoesNotExist
):
VideoTranscript
.
objects
.
get
(
video_id
=
transcript_data
[
'video_id'
],
language_code
=
transcript_data
[
'language_code'
]
)
transcript_url
=
api
.
create_or_update_video_transcript
(
video_id
=
transcript_data
[
'video_id'
],
language_code
=
transcript_data
[
'language_code'
],
metadata
=
dict
(
file_name
=
transcript_data
[
'name'
],
file_format
=
transcript_data
[
'file_format'
],
provider
=
transcript_data
[
'provider'
]
)
)
self
.
assertEqual
(
transcript_url
,
transcript_data
[
'name'
])
expected_transcript
=
api
.
get_video_transcript
(
video_id
=
transcript_data
[
'video_id'
],
language_code
=
transcript_data
[
'language_code'
]
)
transcript_data
[
'url'
]
=
transcript_data
.
pop
(
'name'
)
self
.
assertEqual
(
transcript_data
,
expected_transcript
)
@data
(
{
'language_code'
:
'ur'
,
'has_url'
:
True
},
{
'language_code'
:
'xyz'
,
'has_url'
:
False
},
)
@unpack
def
test_get_video_transcript_url
(
self
,
language_code
,
has_url
):
"""
"""
Verify that `get_video_transcript_url` api function works as expected.
Verify that `get_video_transcript_url` api function works as expected.
"""
"""
transcript_url
=
api
.
get_video_transcript_url
(
self
.
video_id
,
language_code
)
transcript_url
=
api
.
get_video_transcript_url
(
'super-soaker'
,
'fr'
)
if
has_url
:
self
.
assertEqual
(
transcript_url
,
self
.
v1_transcript2
.
url
())
self
.
assertEqual
(
self
.
transcript_url
,
transcript_url
)
else
:
self
.
assertIsNone
(
transcript_url
)
@data
(
@data
(
{
{
...
@@ -1895,12 +1826,13 @@ class TranscriptTest(TestCase):
...
@@ -1895,12 +1826,13 @@ class TranscriptTest(TestCase):
"""
"""
Verify that `create_or_update_video_transcript` api function updates existing transcript as expected.
Verify that `create_or_update_video_transcript` api function updates existing transcript as expected.
"""
"""
video_transcript
=
VideoTranscript
.
objects
.
get
(
video_id
=
self
.
video_id
,
language_code
=
'ur'
)
edx_video_id
=
'super-soaker'
video_transcript
=
VideoTranscript
.
objects
.
get
(
video__edx_video_id
=
edx_video_id
,
language_code
=
'en'
)
self
.
assertIsNotNone
(
video_transcript
)
self
.
assertIsNotNone
(
video_transcript
)
transcript_url
=
api
.
create_or_update_video_transcript
(
transcript_url
=
api
.
create_or_update_video_transcript
(
video_id
=
self
.
video_id
,
video_id
=
edx_
video_id
,
language_code
=
'
ur
'
,
language_code
=
'
en
'
,
metadata
=
dict
(
metadata
=
dict
(
provider
=
provider
,
provider
=
provider
,
language_code
=
language_code
,
language_code
=
language_code
,
...
@@ -1912,10 +1844,10 @@ class TranscriptTest(TestCase):
...
@@ -1912,10 +1844,10 @@ class TranscriptTest(TestCase):
# Now, Querying Video Transcript with previous/old language code leads to DoesNotExist
# Now, Querying Video Transcript with previous/old language code leads to DoesNotExist
with
self
.
assertRaises
(
VideoTranscript
.
DoesNotExist
):
with
self
.
assertRaises
(
VideoTranscript
.
DoesNotExist
):
VideoTranscript
.
objects
.
get
(
video_
id
=
self
.
video_id
,
language_code
=
'ur
'
)
VideoTranscript
.
objects
.
get
(
video_
_edx_video_id
=
edx_video_id
,
language_code
=
'en
'
)
# Assert the updates to the transcript object
# Assert the updates to the transcript object
video_transcript
=
VideoTranscript
.
objects
.
get
(
video_
id
=
self
.
video_id
,
language_code
=
language_code
)
video_transcript
=
VideoTranscript
.
objects
.
get
(
video_
_edx_video_id
=
edx_
video_id
,
language_code
=
language_code
)
self
.
assertEqual
(
transcript_url
,
video_transcript
.
url
())
self
.
assertEqual
(
transcript_url
,
video_transcript
.
url
())
self
.
assertEqual
(
video_transcript
.
file_format
,
file_format
)
self
.
assertEqual
(
video_transcript
.
file_format
,
file_format
)
self
.
assertEqual
(
video_transcript
.
provider
,
provider
)
self
.
assertEqual
(
video_transcript
.
provider
,
provider
)
...
@@ -1931,12 +1863,14 @@ class TranscriptTest(TestCase):
...
@@ -1931,12 +1863,14 @@ class TranscriptTest(TestCase):
@data
(
@data
(
{
{
'video_id'
:
'super-soaker'
,
'file_format'
:
'123'
,
'file_format'
:
'123'
,
'provider'
:
TranscriptProviderType
.
CIELO24
,
'provider'
:
TranscriptProviderType
.
CIELO24
,
'exception'
:
InvalidTranscriptFormat
,
'exception'
:
InvalidTranscriptFormat
,
'exception_message'
:
'123 transcript format is not supported'
,
'exception_message'
:
'123 transcript format is not supported'
,
},
},
{
{
'video_id'
:
'medium-soaker'
,
'file_format'
:
TranscriptFormat
.
SRT
,
'file_format'
:
TranscriptFormat
.
SRT
,
'provider'
:
123
,
'provider'
:
123
,
'exception'
:
InvalidTranscriptProvider
,
'exception'
:
InvalidTranscriptProvider
,
...
@@ -1944,12 +1878,12 @@ class TranscriptTest(TestCase):
...
@@ -1944,12 +1878,12 @@ class TranscriptTest(TestCase):
},
},
)
)
@unpack
@unpack
def
test_create_or_update_video_exceptions
(
self
,
file_format
,
provider
,
exception
,
exception_message
):
def
test_create_or_update_video_exceptions
(
self
,
video_id
,
file_format
,
provider
,
exception
,
exception_message
):
"""
"""
Verify that `create_or_update_video_transcript` api function raise exceptions on invalid values.
Verify that `create_or_update_video_transcript` api function raise exceptions on invalid values.
"""
"""
with
self
.
assertRaises
(
exception
)
as
transcript_exception
:
with
self
.
assertRaises
(
exception
)
as
transcript_exception
:
api
.
create_or_update_video_transcript
(
self
.
video_id
,
'ur'
,
metadata
=
{
api
.
create_or_update_video_transcript
(
video_id
,
'ur'
,
metadata
=
{
'provider'
:
provider
,
'provider'
:
provider
,
'file_format'
:
file_format
'file_format'
:
file_format
})
})
...
@@ -1960,21 +1894,22 @@ class TranscriptTest(TestCase):
...
@@ -1960,21 +1894,22 @@ class TranscriptTest(TestCase):
"""
"""
Test video transcript deletion works as expected.
Test video transcript deletion works as expected.
"""
"""
edx_video_id
=
'super-soaker'
# get an existing video transcript
# get an existing video transcript
video_transcript
=
VideoTranscript
.
objects
.
get
(
video_
id
=
self
.
video_id
,
language_code
=
'ur
'
)
video_transcript
=
VideoTranscript
.
objects
.
get
(
video_
_edx_video_id
=
edx_video_id
,
language_code
=
'en
'
)
existing_transcript_url
=
video_transcript
.
transcript
.
name
existing_transcript_url
=
video_transcript
.
url
()
# This will replace the transcript for an existing video and delete the existing transcript
# This will replace the transcript for an existing video and delete the existing transcript
new_transcript_url
=
api
.
create_or_update_video_transcript
(
new_transcript_url
=
api
.
create_or_update_video_transcript
(
video_id
=
self
.
video_id
,
video_id
=
edx_
video_id
,
language_code
=
'
ur
'
,
language_code
=
'
en
'
,
metadata
=
dict
(
provider
=
TranscriptProviderType
.
CIELO24
),
metadata
=
dict
(
provider
=
TranscriptProviderType
.
CIELO24
),
file_data
=
ContentFile
(
FILE_DATA
)
file_data
=
ContentFile
(
FILE_DATA
)
)
)
# Verify that new transcript is set to video
# Verify that new transcript is set to video
video_transcript
=
VideoTranscript
.
objects
.
get
(
video_
id
=
self
.
video_id
,
language_code
=
'ur
'
)
video_transcript
=
VideoTranscript
.
objects
.
get
(
video_
_edx_video_id
=
edx_video_id
,
language_code
=
'en
'
)
self
.
assertEqual
(
video_transcript
.
transcript
.
name
,
new_transcript_url
)
self
.
assertEqual
(
video_transcript
.
url
()
,
new_transcript_url
)
# verify that new data is written correctly
# verify that new data is written correctly
with
open
(
video_transcript
.
transcript
.
name
)
as
saved_transcript
:
with
open
(
video_transcript
.
transcript
.
name
)
as
saved_transcript
:
...
@@ -1990,28 +1925,30 @@ class TranscriptTest(TestCase):
...
@@ -1990,28 +1925,30 @@ class TranscriptTest(TestCase):
"""
"""
Verify that `get_available_transcript_languages` works as expected.
Verify that `get_available_transcript_languages` works as expected.
"""
"""
dupe_lang_video_id
=
'duplicate_lang_video'
# `super-soaker` has got 'en' and 'fr' transcripts
VideoTranscript
.
objects
.
create
(
**
dict
(
constants
.
VIDEO_TRANSCRIPT_CIELO24
,
video_id
=
dupe_lang_video_id
))
# `super-soaker` has got 'en' and 'de' transcripts
# `self.video_id` has got 'ur' transcript
# `duplicate_lang_video` has got 'en' transcript
# `non_existent_video_id` that does not have transcript
# `non_existent_video_id` that does not have transcript
video_ids
=
[
'super-soaker'
,
self
.
video_id
,
dupe_lang_video_id
,
'non_existent_video_id'
]
video_ids
=
[
'super-soaker'
,
'non_existent_video_id'
]
transcript_languages
=
api
.
get_available_transcript_languages
(
video_ids
=
video_ids
)
transcript_languages
=
api
.
get_available_transcript_languages
(
video_ids
=
video_ids
)
self
.
assertItemsEqual
(
transcript_languages
,
[
'
de'
,
'en'
,
'ur
'
,
'fr'
])
self
.
assertItemsEqual
(
transcript_languages
,
[
'
en
'
,
'fr'
])
def
test_delete_video_transcript
(
self
):
def
test_delete_video_transcript
(
self
):
"""
"""
Verify that `delete_video_transcript` works as expected.
Verify that `delete_video_transcript` works as expected.
"""
"""
query_filter
=
{
query_filter
=
{
'video_id'
:
'super-soaker'
,
'video_
_edx_video_
id'
:
'super-soaker'
,
'language_code'
:
'fr'
'language_code'
:
'fr'
}
}
self
.
assertEqual
(
VideoTranscript
.
objects
.
filter
(
**
query_filter
)
.
count
(),
1
)
self
.
assertEqual
(
VideoTranscript
.
objects
.
filter
(
**
query_filter
)
.
count
(),
1
)
api
.
delete_video_transcript
(
**
query_filter
)
# current transcript path
self
.
assertFalse
(
os
.
path
.
exists
(
self
.
transcript_file
))
transcript_path
=
self
.
v1_transcript2
.
transcript
.
name
api
.
delete_video_transcript
(
video_id
=
query_filter
[
'video__edx_video_id'
],
language_code
=
query_filter
[
'language_code'
]
)
# assert that the transcript does not exist on the path anymore.
self
.
assertFalse
(
os
.
path
.
exists
(
transcript_path
))
self
.
assertEqual
(
VideoTranscript
.
objects
.
filter
(
**
query_filter
)
.
count
(),
0
)
self
.
assertEqual
(
VideoTranscript
.
objects
.
filter
(
**
query_filter
)
.
count
(),
0
)
...
...
edxval/tests/test_views.py
View file @
727e643d
...
@@ -3,7 +3,6 @@
...
@@ -3,7 +3,6 @@
Tests for Video Abstraction Layer views
Tests for Video Abstraction Layer views
"""
"""
import
json
import
json
import
unittest
from
ddt
import
data
,
ddt
,
unpack
from
ddt
import
data
,
ddt
,
unpack
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
...
@@ -821,13 +820,18 @@ class VideoTranscriptViewTest(APIAuthTestCase):
...
@@ -821,13 +820,18 @@ class VideoTranscriptViewTest(APIAuthTestCase):
serialized_data
=
TranscriptSerializer
(
VideoTranscript
.
objects
.
first
())
.
data
serialized_data
=
TranscriptSerializer
(
VideoTranscript
.
objects
.
first
())
.
data
post_transcript_data
[
'url'
]
=
post_transcript_data
.
pop
(
'name'
)
post_transcript_data
[
'url'
]
=
post_transcript_data
.
pop
(
'name'
)
self
.
assertEqual
(
serialized_data
,
post_transcript_data
)
self
.
assert
Dict
Equal
(
serialized_data
,
post_transcript_data
)
def
test_update_existing_transcript
(
self
):
def
test_update_existing_transcript
(
self
):
"""
"""
Tests updating existing transcript works as expected.
Tests updating existing transcript works as expected.
"""
"""
VideoTranscript
.
objects
.
create
(
**
self
.
transcript_data
)
VideoTranscript
.
objects
.
create
(
video
=
self
.
video
,
language_code
=
self
.
transcript_data
[
'language_code'
],
file_format
=
self
.
transcript_data
[
'file_format'
],
provider
=
self
.
transcript_data
[
'provider'
],
)
post_transcript_data
=
dict
(
self
.
transcript_data
)
post_transcript_data
=
dict
(
self
.
transcript_data
)
post_transcript_data
[
'name'
]
=
post_transcript_data
.
pop
(
'transcript'
)
post_transcript_data
[
'name'
]
=
post_transcript_data
.
pop
(
'transcript'
)
...
...
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