Ejemplo n.º 1
0
    def handle_ajax(self, dispatch, data):
        accepted_keys = [
            'speed', 'saved_video_position', 'transcript_language',
            'transcript_download_format', 'youtube_is_available'
        ]

        conversions = {
            'speed': json.loads,
            'saved_video_position': lambda v: RelativeTime.isotime_to_timedelta(v),
            'youtube_is_available': json.loads,
        }

        if dispatch == 'save_user_state':
            for key in data:
                if hasattr(self, key) and key in accepted_keys:
                    if key in conversions:
                        value = conversions[key](data[key])
                    else:
                        value = data[key]

                    setattr(self, key, value)

                    if key == 'speed':
                        self.global_speed = self.speed

            return json.dumps({'success': True})

        log.debug(u"GET {0}".format(data))
        log.debug(u"DISPATCH {0}".format(dispatch))

        raise NotFoundError('Unexpected dispatch type')
Ejemplo n.º 2
0
    def handle_ajax(self, dispatch, data):
        accepted_keys = [
            'speed',
            'saved_video_position',
            'transcript_language',
            'transcript_download_format',
        ]

        conversions = {
            'speed': json.loads,
            'saved_video_position':
            lambda v: RelativeTime.isotime_to_timedelta(v),
        }

        if dispatch == 'save_user_state':
            for key in data:
                if hasattr(self, key) and key in accepted_keys:
                    if key in conversions:
                        value = conversions[key](data[key])
                    else:
                        value = data[key]

                    setattr(self, key, value)

                    if key == 'speed':
                        self.global_speed = self.speed

            return json.dumps({'success': True})

        log.debug(u"GET {0}".format(data))
        log.debug(u"DISPATCH {0}".format(dispatch))

        raise NotFoundError('Unexpected dispatch type')
Ejemplo n.º 3
0
class RelativeTimeTest(unittest.TestCase):

    delta = RelativeTime()

    def test_from_json(self):
        self.assertEqual(
            RelativeTimeTest.delta.from_json('0:05:07'),
            datetime.timedelta(seconds=307)
        )

        self.assertEqual(
            RelativeTimeTest.delta.from_json(100.0),
            datetime.timedelta(seconds=100)
        )
        self.assertEqual(
            RelativeTimeTest.delta.from_json(None),
            datetime.timedelta(seconds=0)
        )

        with self.assertRaises(TypeError):
            RelativeTimeTest.delta.from_json(1234)  # int

        with self.assertRaises(ValueError):
            RelativeTimeTest.delta.from_json("77:77:77")

    def test_to_json(self):
        self.assertEqual(
            "01:02:03",
            RelativeTimeTest.delta.to_json(datetime.timedelta(seconds=3723))
        )
        self.assertEqual(
            "00:00:00",
            RelativeTimeTest.delta.to_json(None)
        )
        self.assertEqual(
            "00:01:40",
            RelativeTimeTest.delta.to_json(100.0)
        )

        with self.assertRaisesRegexp(ValueError, "RelativeTime max value is 23:59:59=86400.0 seconds, but 90000.0 seconds is passed"):
            RelativeTimeTest.delta.to_json(datetime.timedelta(seconds=90000))

        with self.assertRaises(TypeError):
            RelativeTimeTest.delta.to_json("123")

    def test_str(self):
        self.assertEqual(
            "01:02:03",
            RelativeTimeTest.delta.to_json(datetime.timedelta(seconds=3723))
        )
        self.assertEqual(
            "11:02:03",
            RelativeTimeTest.delta.to_json(datetime.timedelta(seconds=39723))
        )
Ejemplo n.º 4
0
class RelativeTimeTest(unittest.TestCase):  # lint-amnesty, pylint: disable=missing-class-docstring

    delta = RelativeTime()

    def test_from_json(self):
        self.assertEqual(RelativeTimeTest.delta.from_json('0:05:07'),
                         datetime.timedelta(seconds=307))

        self.assertEqual(RelativeTimeTest.delta.from_json(100.0),
                         datetime.timedelta(seconds=100))
        self.assertEqual(RelativeTimeTest.delta.from_json(None),
                         datetime.timedelta(seconds=0))

        with self.assertRaises(TypeError):
            RelativeTimeTest.delta.from_json(1234)  # int

        with self.assertRaises(ValueError):
            RelativeTimeTest.delta.from_json("77:77:77")

    def test_enforce_type(self):
        self.assertEqual(RelativeTimeTest.delta.enforce_type(None), None)
        self.assertEqual(
            RelativeTimeTest.delta.enforce_type(
                datetime.timedelta(days=1, seconds=46799)),
            datetime.timedelta(days=1, seconds=46799))
        self.assertEqual(RelativeTimeTest.delta.enforce_type('0:05:07'),
                         datetime.timedelta(seconds=307))
        with self.assertRaises(TypeError):
            RelativeTimeTest.delta.enforce_type([1])

    def test_to_json(self):
        self.assertEqual(
            "01:02:03",
            RelativeTimeTest.delta.to_json(datetime.timedelta(seconds=3723)))
        self.assertEqual("00:00:00", RelativeTimeTest.delta.to_json(None))
        self.assertEqual("00:01:40", RelativeTimeTest.delta.to_json(100.0))

        error_msg = "RelativeTime max value is 23:59:59=86400.0 seconds, but 90000.0 seconds is passed"
        with self.assertRaisesRegex(ValueError, error_msg):
            RelativeTimeTest.delta.to_json(datetime.timedelta(seconds=90000))

        with self.assertRaises(TypeError):
            RelativeTimeTest.delta.to_json("123")

    def test_str(self):
        self.assertEqual(
            "01:02:03",
            RelativeTimeTest.delta.to_json(datetime.timedelta(seconds=3723)))
        self.assertEqual(
            "11:02:03",
            RelativeTimeTest.delta.to_json(datetime.timedelta(seconds=39723)))
Ejemplo n.º 5
0
    def handle_ajax(self, dispatch, data):
        accepted_keys = ['speed', 'saved_video_position', 'transcript_language']
        if dispatch == 'save_user_state':

            for key in data:
                if hasattr(self, key) and key in accepted_keys:
                    if key == 'saved_video_position':
                        relative_position = RelativeTime.isotime_to_timedelta(data[key])
                        self.saved_video_position = relative_position
                    else:
                        setattr(self, key, json.loads(data[key]))
                    if key == 'speed':
                        self.global_speed = self.speed

            return json.dumps({'success': True})

        log.debug(u"GET {0}".format(data))
        log.debug(u"DISPATCH {0}".format(dispatch))

        raise NotFoundError('Unexpected dispatch type')
Ejemplo n.º 6
0
    def handle_ajax(self, dispatch, data):
        accepted_keys = ["speed", "saved_video_position"]

        if dispatch == "save_user_state":
            for key in data:
                if hasattr(self, key) and key in accepted_keys:
                    if key == "saved_video_position":
                        relative_position = RelativeTime.isotime_to_timedelta(data[key])
                        self.saved_video_position = relative_position
                    else:
                        setattr(self, key, json.loads(data[key]))
                    if key == "speed":
                        self.global_speed = self.speed

            log.debug(u"Test.")

            return json.dumps({"success": True})

        log.debug(u"GET {0}".format(data))
        log.debug(u"DISPATCH {0}".format(dispatch))

        raise NotFoundError("Unexpected dispatch type")
Ejemplo n.º 7
0
class VideoFields(object):
    """Fields for `VideoModule` and `VideoDescriptor`."""
    display_name = String(
        help=_("The name students see. This name appears in the course ribbon and as a header for the video."),
        display_name=_("Component Display Name"),
        default="Video",
        scope=Scope.settings
    )

    saved_video_position = RelativeTime(
        help=_("Current position in the video."),
        scope=Scope.user_state,
        default=datetime.timedelta(seconds=0)
    )
    # TODO: This should be moved to Scope.content, but this will
    # require data migration to support the old video module.
    youtube_id_1_0 = String(
        help=_("Optional, for older browsers: the YouTube ID for the normal speed video."),
        display_name=_("YouTube ID"),
        scope=Scope.settings,
        default="3_yD_cEKoCk"
    )
    youtube_id_0_75 = String(
        help=_("Optional, for older browsers: the YouTube ID for the .75x speed video."),
        display_name=_("YouTube ID for .75x speed"),
        scope=Scope.settings,
        default=""
    )
    youtube_id_1_25 = String(
        help=_("Optional, for older browsers: the YouTube ID for the 1.25x speed video."),
        display_name=_("YouTube ID for 1.25x speed"),
        scope=Scope.settings,
        default=""
    )
    youtube_id_1_5 = String(
        help=_("Optional, for older browsers: the YouTube ID for the 1.5x speed video."),
        display_name=_("YouTube ID for 1.5x speed"),
        scope=Scope.settings,
        default=""
    )
    start_time = RelativeTime(  # datetime.timedelta object
        help=_(
            "Time you want the video to start if you don't want the entire video to play. "
            "Not supported in the native mobile app: the full video file will play. "
            "Formatted as HH:MM:SS. The maximum value is 23:59:59."
        ),
        display_name=_("Video Start Time"),
        scope=Scope.settings,
        default=datetime.timedelta(seconds=0)
    )
    end_time = RelativeTime(  # datetime.timedelta object
        help=_(
            "Time you want the video to stop if you don't want the entire video to play. "
            "Not supported in the native mobile app: the full video file will play. "
            "Formatted as HH:MM:SS. The maximum value is 23:59:59."
        ),
        display_name=_("Video Stop Time"),
        scope=Scope.settings,
        default=datetime.timedelta(seconds=0)
    )
    #front-end code of video player checks logical validity of (start_time, end_time) pair.

    # `source` is deprecated field and should not be used in future.
    # `download_video` is used instead.
    source = String(
        help=_("The external URL to download the video."),
        display_name=_("Download Video"),
        scope=Scope.settings,
        default=""
    )
    download_video = Boolean(
        help=_("Allow students to download versions of this video in different formats if they cannot use the edX video player or do not have access to YouTube. You must add at least one non-YouTube URL in the Video File URLs field."),  # pylint: disable=line-too-long
        display_name=_("Video Download Allowed"),
        scope=Scope.settings,
        default=False
    )
    html5_sources = List(
        help=_("The URL or URLs where you've posted non-YouTube versions of the video. Each URL must end in .mpeg, .mp4, .ogg, or .webm and cannot be a YouTube URL. (For browser compatibility, we strongly recommend .mp4 and .webm format.) Students will be able to view the first listed video that's compatible with the student's computer. To allow students to download these videos, set Video Download Allowed to True."),  # pylint: disable=line-too-long
        display_name=_("Video File URLs"),
        scope=Scope.settings,
    )
    track = String(
        help=_("By default, students can download an .srt or .txt transcript when you set Download Transcript Allowed to True. If you want to provide a downloadable transcript in a different format, we recommend that you upload a handout by using the Upload a Handout field. If this isn't possible, you can post a transcript file on the Files & Uploads page or on the Internet, and then add the URL for the transcript here. Students see a link to download that transcript below the video."),  # pylint: disable=line-too-long
        display_name=_("Downloadable Transcript URL"),
        scope=Scope.settings,
        default=''
    )
    download_track = Boolean(
        help=_("Allow students to download the timed transcript. A link to download the file appears below the video. By default, the transcript is an .srt or .txt file. If you want to provide the transcript for download in a different format, upload a file by using the Upload Handout field."),  # pylint: disable=line-too-long
        display_name=_("Download Transcript Allowed"),
        scope=Scope.settings,
        default=False
    )
    sub = String(
        help=_("The default transcript for the video, from the Default Timed Transcript field on the Basic tab. This transcript should be in English. You don't have to change this setting."),  # pylint: disable=line-too-long
        display_name=_("Default Timed Transcript"),
        scope=Scope.settings,
        default=""
    )
    show_captions = Boolean(
        help=_("Specify whether the transcripts appear with the video by default."),
        display_name=_("Show Transcript"),
        scope=Scope.settings,
        default=True
    )
    # Data format: {'de': 'german_translation', 'uk': 'ukrainian_translation'}
    transcripts = Dict(
        help=_("Add transcripts in different languages. Click below to specify a language and upload an .srt transcript file for that language."),  # pylint: disable=line-too-long
        display_name=_("Transcript Languages"),
        scope=Scope.settings,
        default={}
    )
    transcript_language = String(
        help=_("Preferred language for transcript."),
        display_name=_("Preferred language for transcript"),
        scope=Scope.preferences,
        default="en"
    )
    transcript_download_format = String(
        help=_("Transcript file format to download by user."),
        scope=Scope.preferences,
        values=[
            # Translators: This is a type of file used for captioning in the video player.
            {"display_name": _("SubRip (.srt) file"), "value": "srt"},
            {"display_name": _("Text (.txt) file"), "value": "txt"}
        ],
        default='srt',
    )
    speed = Float(
        help=_("The last speed that the user specified for the video."),
        scope=Scope.user_state
    )
    global_speed = Float(
        help=_("The default speed for the video."),
        scope=Scope.preferences,
        default=1.0
    )
    youtube_is_available = Boolean(
        help=_("Specify whether YouTube is available for the user."),
        scope=Scope.user_info,
        default=True
    )
    handout = String(
        help=_("Upload a handout to accompany this video. Students can download the handout by clicking Download Handout under the video."),  # pylint: disable=line-too-long
        display_name=_("Upload Handout"),
        scope=Scope.settings,
    )
    only_on_web = Boolean(
        help=_(
            "Specify whether access to this video is limited to browsers only, or if it can be "
            "accessed from other applications including mobile apps."
        ),
        display_name=_("Video Available on Web Only"),
        scope=Scope.settings,
        default=False
    )
    edx_video_id = String(
        help=_("If you were assigned a Video ID by edX for the video to play in this component, enter the ID here. In this case, do not enter values in the Default Video URL, the Video File URLs, and the YouTube ID fields. If you were not assigned a Video ID, enter values in those other fields and ignore this field."),  # pylint: disable=line-too-long
        display_name=_("Video ID"),
        scope=Scope.settings,
        default="",
    )
    bumper_last_view_date = DateTime(
        display_name=_("Date of the last view of the bumper"),
        scope=Scope.preferences,
    )
    bumper_do_not_show_again = Boolean(
        display_name=_("Do not show bumper again"),
        scope=Scope.preferences,
        default=False,
    )
Ejemplo n.º 8
0
class VideoFields(object):
    """Fields for `VideoModule` and `VideoDescriptor`."""
    display_name = String(display_name="Display Name",
                          help="Display name for this module.",
                          default="Video",
                          scope=Scope.settings)
    saved_video_position = RelativeTime(help="Current position in the video",
                                        scope=Scope.user_state,
                                        default=datetime.timedelta(seconds=0))
    # TODO: This should be moved to Scope.content, but this will
    # require data migration to support the old video module.
    youtube_id_1_0 = String(
        help="This is the Youtube ID reference for the normal speed video.",
        display_name="Youtube ID",
        scope=Scope.settings,
        default="OEoXaMPEzfM")
    youtube_id_0_75 = String(
        help=
        "Optional, for older browsers: the Youtube ID for the .75x speed video.",
        display_name="Youtube ID for .75x speed",
        scope=Scope.settings,
        default="")
    youtube_id_1_25 = String(
        help=
        "Optional, for older browsers: the Youtube ID for the 1.25x speed video.",
        display_name="Youtube ID for 1.25x speed",
        scope=Scope.settings,
        default="")
    youtube_id_1_5 = String(
        help=
        "Optional, for older browsers: the Youtube ID for the 1.5x speed video.",
        display_name="Youtube ID for 1.5x speed",
        scope=Scope.settings,
        default="")
    start_time = RelativeTime(  # datetime.timedelta object
        help="Start time for the video (HH:MM:SS). Max value is 23:59:59.",
        display_name="Start Time",
        scope=Scope.settings,
        default=datetime.timedelta(seconds=0))
    end_time = RelativeTime(  # datetime.timedelta object
        help="End time for the video (HH:MM:SS). Max value is 23:59:59.",
        display_name="End Time",
        scope=Scope.settings,
        default=datetime.timedelta(seconds=0))
    #front-end code of video player checks logical validity of (start_time, end_time) pair.

    # `source` is deprecated field and should not be used in future.
    # `download_video` is used instead.
    source = String(help="The external URL to download the video.",
                    display_name="Download Video",
                    scope=Scope.settings,
                    default="")
    download_video = Boolean(
        help=
        "Show a link beneath the video to allow students to download the video. Note: You must add at least one video source below.",
        display_name="Video Download Allowed",
        scope=Scope.settings,
        default=False)
    html5_sources = List(
        help=
        "A list of filenames to be used with HTML5 video. The first supported filetype will be displayed.",
        display_name="Video Sources",
        scope=Scope.settings,
    )
    track = String(
        help=
        "The external URL to download the timed transcript track. This appears as a link beneath the video.",
        display_name="Download Transcript",
        scope=Scope.settings,
        default='')
    download_track = Boolean(
        help=
        "Show a link beneath the video to allow students to download the transcript. Note: You must add a link to the HTML5 Transcript field above.",
        display_name="Transcript Download Allowed",
        scope=Scope.settings,
        default=False)
    sub = String(
        help="The name of the timed transcript track (for non-Youtube videos).",
        display_name="Transcript (primary)",
        scope=Scope.settings,
        default="")
    show_captions = Boolean(
        help="This controls whether or not captions are shown by default.",
        display_name="Transcript Display",
        scope=Scope.settings,
        default=True)
    # Data format: {'de': 'german_translation', 'uk': 'ukrainian_translation'}
    transcripts = Dict(help="Add additional transcripts in other languages",
                       display_name="Transcript Translations",
                       scope=Scope.settings,
                       default={})
    transcript_language = String(
        help="Preferred language for transcript",
        display_name="Preferred language for transcript",
        scope=Scope.preferences,
        default="en")
    transcript_download_format = String(
        help="Transcript file format to download by user.",
        scope=Scope.preferences,
        values=[{
            "display_name": "SubRip (.srt) file",
            "value": "srt"
        }, {
            "display_name": "Text (.txt) file",
            "value": "txt"
        }],
        default='srt',
    )
    speed = Float(
        help="The last speed that was explicitly set by user for the video.",
        scope=Scope.user_state,
    )
    global_speed = Float(
        help=
        "Default speed in cases when speed wasn't explicitly for specific video",
        scope=Scope.preferences,
        default=1.0)
Ejemplo n.º 9
0
class VideoFields(object):
    """Fields for `VideoModule` and `VideoDescriptor`."""
    display_name = String(display_name="Display Name",
                          help="Display name for this module.",
                          default="Video",
                          scope=Scope.settings)
    position = Integer(help="Current position in the video",
                       scope=Scope.user_state,
                       default=0)
    show_captions = Boolean(
        help="This controls whether or not captions are shown by default.",
        display_name="Show Transcript",
        scope=Scope.settings,
        default=True)
    # TODO: This should be moved to Scope.content, but this will
    # require data migration to support the old video module.
    youtube_id_1_0 = String(
        help="This is the Youtube ID reference for the normal speed video.",
        display_name="Youtube ID",
        scope=Scope.settings,
        default="OEoXaMPEzfM")
    youtube_id_0_75 = String(
        help=
        "Optional, for older browsers: the Youtube ID for the .75x speed video.",
        display_name="Youtube ID for .75x speed",
        scope=Scope.settings,
        default="")
    youtube_id_1_25 = String(
        help=
        "Optional, for older browsers: the Youtube ID for the 1.25x speed video.",
        display_name="Youtube ID for 1.25x speed",
        scope=Scope.settings,
        default="")
    youtube_id_1_5 = String(
        help=
        "Optional, for older browsers: the Youtube ID for the 1.5x speed video.",
        display_name="Youtube ID for 1.5x speed",
        scope=Scope.settings,
        default="")
    start_time = RelativeTime(  # datetime.timedelta object
        help="Start time for the video (HH:MM:SS). Max value is 23:59:59.",
        display_name="Start Time",
        scope=Scope.settings,
        default=datetime.timedelta(seconds=0))
    end_time = RelativeTime(  # datetime.timedelta object
        help="End time for the video (HH:MM:SS). Max value is 23:59:59.",
        display_name="End Time",
        scope=Scope.settings,
        default=datetime.timedelta(seconds=0))
    #front-end code of video player checks logical validity of (start_time, end_time) pair.

    source = String(
        help=
        "The external URL to download the video. This appears as a link beneath the video.",
        display_name="Download Video",
        scope=Scope.settings,
        default="")
    html5_sources = List(
        help=
        "A list of filenames to be used with HTML5 video. The first supported filetype will be displayed.",
        display_name="Video Sources",
        scope=Scope.settings,
    )
    track = String(
        help=
        "The external URL to download the timed transcript track. This appears as a link beneath the video.",
        display_name="Download Transcript",
        scope=Scope.settings,
        default="")
    sub = String(
        help="The name of the timed transcript track (for non-Youtube videos).",
        display_name="HTML5 Transcript",
        scope=Scope.settings,
        default="")
Ejemplo n.º 10
0
class VideoFields(object):
    """Fields for `VideoModule` and `VideoDescriptor`."""
    display_name = String(display_name="显示名称",
                          help="显示模块名称",
                          default="Video",
                          scope=Scope.settings)
    saved_video_position = RelativeTime(help="Current position in the video",
                                        scope=Scope.user_state,
                                        default=datetime.timedelta(seconds=0))
    # TODO: This should be moved to Scope.content, but this will
    # require data migration to support the old video module.
    youtube_id_1_0 = String(help="这是正常的视频播放速度",
                            display_name="Video ID",
                            scope=Scope.settings,
                            default="OEoXaMPEzfM")
    youtube_id_0_75 = String(help="可选项,对于旧的浏览器:播放速度为正常的0.75。",
                             display_name=".75x speed",
                             scope=Scope.settings,
                             default="")
    youtube_id_1_25 = String(help="可选项,对于旧的浏览器:播放速度为正常的1.25倍。",
                             display_name="1.25x speed",
                             scope=Scope.settings,
                             default="")
    youtube_id_1_5 = String(help="可选项,对于旧的浏览器:播放速度为正常的1.5倍.",
                            display_name="1.5x speed",
                            scope=Scope.settings,
                            default="")
    start_time = RelativeTime(  # datetime.timedelta object
        help="视频的开始时间 (HH:MM:SS).最大值为 23:59:59",
        display_name="开始时间",
        scope=Scope.settings,
        default=datetime.timedelta(seconds=0))
    end_time = RelativeTime(  # datetime.timedelta object
        help="视频的结束时间 (HH:MM:SS).最大值为 23:59:59",
        display_name="结束时间",
        scope=Scope.settings,
        default=datetime.timedelta(seconds=0))
    #front-end code of video player checks logical validity of (start_time, end_time) pair.

    # `source` is deprecated field and should not be used in future.
    # `download_video` is used instead.
    source = String(help="视频外部链接下载地址",
                    display_name="视频下载",
                    scope=Scope.settings,
                    default="")
    download_video = Boolean(help="显示视频下方的链接,让学生下载的视频。注意:您必须在下面添加至少一个视频源.",
                             display_name="允许下载视频",
                             scope=Scope.settings,
                             default=False)
    html5_sources = List(
        help="文件名要与HTML5视频使用的清单。第一个支持的文件类型就会显示出来。",
        display_name="视频资源",
        scope=Scope.settings,
    )
    track = String(help="外部URL下载时记录跟踪,如下显示的视频连接。",
                   display_name="下载记录",
                   scope=Scope.settings,
                   default='')
    download_track = Boolean(help="显示视频下方的链接,让学生下载视频。注意:您必须添加一个HTML5的链接记录。",
                             display_name="允许下载记录",
                             scope=Scope.settings,
                             default=False)
    sub = String(help="跟踪记录的名称.",
                 display_name="记录(初级)",
                 scope=Scope.settings,
                 default="")
    show_captions = Boolean(help="这种控制标题是否被默认显示。",
                            display_name="显示记录",
                            scope=Scope.settings,
                            default=True)
    # Data format: {'de': 'german_translation', 'uk': 'ukrainian_translation'}
    transcripts = Dict(help="用其他语言添加翻译译文",
                       display_name="翻译记录",
                       scope=Scope.settings,
                       default={})
    transcript_language = String(
        help="Preferred language for transcript",
        display_name="Preferred language for transcript",
        scope=Scope.preferences,
        default="en")
    speed = Float(
        help="The last speed that was explicitly set by user for the video.",
        scope=Scope.user_state,
    )
    global_speed = Float(
        help=
        "Default speed in cases when speed wasn't explicitly for specific video",
        scope=Scope.preferences,
        default=1.0)