示例#1
0
    def test_existing_video(self, course_id):
        xml = self.make_import_xml(
            video_dict={
                "client_video_id": "new_client_video_id",
                "duration": 0,
            },
            encoded_video_dicts=[
                constants.ENCODED_VIDEO_DICT_FISH_DESKTOP,
                {
                    "url": "http://example.com/new_url",
                    "file_size": 2733256,
                    "bitrate": 1597804,
                    "profile": "mobile",
                },
            ])
        api.import_from_xml(xml, constants.VIDEO_DICT_FISH["edx_video_id"],
                            course_id)

        video = Video.objects.get(
            edx_video_id=constants.VIDEO_DICT_FISH["edx_video_id"])
        self.assert_video_matches_dict(video, constants.VIDEO_DICT_FISH)
        self.assert_encoded_video_matches_dict(
            video.encoded_videos.get(
                profile__profile_name=constants.PROFILE_MOBILE),
            constants.ENCODED_VIDEO_DICT_MOBILE)
        self.assertFalse(
            video.encoded_videos.filter(
                profile__profile_name=constants.PROFILE_DESKTOP).exists())
        self.assertTrue(video.courses.filter(course_id=course_id).exists())
示例#2
0
 def test_existing_video_with_invalid_course_id(self):
     xml = self.make_import_xml(video_dict=constants.VIDEO_DICT_FISH)
     with self.assertRaises(ValCannotCreateError):
         api.import_from_xml(
             xml,
             edx_video_id=constants.VIDEO_DICT_FISH["edx_video_id"],
             course_id="x" * 300)
示例#3
0
    def test_new_video_minimal(self):
        edx_video_id = "test_edx_video_id"

        xml = self.make_import_xml(video_dict={"client_video_id": "dummy", "duration": "0"})
        api.import_from_xml(xml, edx_video_id)

        video = Video.objects.get(edx_video_id=edx_video_id)
        self.assertFalse(video.encoded_videos.all().exists())
        self.assertFalse(video.courses.all().exists())
示例#4
0
    def test_new_video_minimal(self):
        edx_video_id = "test_edx_video_id"

        xml = self.make_import_xml(video_dict={
            "client_video_id": "dummy",
            "duration": "0",
        })
        api.import_from_xml(xml, edx_video_id)

        video = Video.objects.get(edx_video_id=edx_video_id)
        self.assertFalse(video.encoded_videos.all().exists())
        self.assertFalse(video.courses.all().exists())
示例#5
0
    def test_new_video_full(self):
        new_course_id = "new_course_id"

        xml = self.make_import_xml(
            video_dict=constants.VIDEO_DICT_STAR, encoded_video_dicts=[constants.ENCODED_VIDEO_DICT_STAR]
        )
        api.import_from_xml(xml, constants.VIDEO_DICT_STAR["edx_video_id"], new_course_id)

        video = Video.objects.get(edx_video_id=constants.VIDEO_DICT_STAR["edx_video_id"])
        self.assert_video_matches_dict(video, constants.VIDEO_DICT_STAR)
        self.assert_encoded_video_matches_dict(
            video.encoded_videos.get(profile__profile_name=constants.PROFILE_MOBILE), constants.ENCODED_VIDEO_DICT_STAR
        )
        video.courses.get(course_id=new_course_id)
示例#6
0
    def test_new_video_full(self):
        new_course_id = "new_course_id"

        xml = self.make_import_xml(
            video_dict=constants.VIDEO_DICT_STAR,
            encoded_video_dicts=[constants.ENCODED_VIDEO_DICT_STAR]
        )
        api.import_from_xml(xml, constants.VIDEO_DICT_STAR["edx_video_id"], new_course_id)

        video = Video.objects.get(edx_video_id=constants.VIDEO_DICT_STAR["edx_video_id"])
        self.assert_video_matches_dict(video, constants.VIDEO_DICT_STAR)
        self.assert_encoded_video_matches_dict(
            video.encoded_videos.get(profile__profile_name=constants.PROFILE_MOBILE),
            constants.ENCODED_VIDEO_DICT_STAR
        )
        video.courses.get(course_id=new_course_id)
示例#7
0
    def test_existing_video(self, course_id):
        xml = self.make_import_xml(
            video_dict={"client_video_id": "new_client_video_id", "duration": 0},
            encoded_video_dicts=[
                constants.ENCODED_VIDEO_DICT_FISH_DESKTOP,
                {"url": "http://example.com/new_url", "file_size": 2733256, "bitrate": 1597804, "profile": "mobile"},
            ],
        )
        api.import_from_xml(xml, constants.VIDEO_DICT_FISH["edx_video_id"], course_id)

        video = Video.objects.get(edx_video_id=constants.VIDEO_DICT_FISH["edx_video_id"])
        self.assert_video_matches_dict(video, constants.VIDEO_DICT_FISH)
        self.assert_encoded_video_matches_dict(
            video.encoded_videos.get(profile__profile_name=constants.PROFILE_MOBILE),
            constants.ENCODED_VIDEO_DICT_MOBILE,
        )
        self.assertFalse(video.encoded_videos.filter(profile__profile_name=constants.PROFILE_DESKTOP).exists())
        self.assertTrue(video.courses.filter(course_id=course_id).exists())
示例#8
0
    def test_unknown_profile(self):
        profile = "unknown_profile"
        xml = self.make_import_xml(
            video_dict=constants.VIDEO_DICT_STAR,
            encoded_video_dicts=[
                constants.ENCODED_VIDEO_DICT_STAR,
                {
                    "url": "http://example.com/dummy",
                    "file_size": -1,  # Invalid data in an unknown profile is ignored
                    "bitrate": 0,
                    "profile": profile,
                }
            ]
        )
        api.import_from_xml(xml, constants.VIDEO_DICT_STAR["edx_video_id"])

        video = Video.objects.get(edx_video_id=constants.VIDEO_DICT_STAR["edx_video_id"])
        self.assertFalse(video.encoded_videos.filter(profile__profile_name=profile).exists())
示例#9
0
    def test_unknown_profile(self):
        profile = "unknown_profile"
        xml = self.make_import_xml(
            video_dict=constants.VIDEO_DICT_STAR,
            encoded_video_dicts=[
                constants.ENCODED_VIDEO_DICT_STAR,
                {
                    "url": "http://example.com/dummy",
                    "file_size": -1,  # Invalid data in an unknown profile is ignored
                    "bitrate": 0,
                    "profile": profile,
                },
            ],
        )
        api.import_from_xml(xml, constants.VIDEO_DICT_STAR["edx_video_id"])

        video = Video.objects.get(edx_video_id=constants.VIDEO_DICT_STAR["edx_video_id"])
        self.assertFalse(video.encoded_videos.filter(profile__profile_name=profile).exists())
示例#10
0
    def import_video_info_into_val(self, xml, course_id):
        """
        Import parsed video info from `xml` into edxval.

        Arguments:
            xml (lxml object): xml representation of video to be imported
            course_id (str): course id
        """
        if self.edx_video_id is not None:
            edx_video_id = self.edx_video_id.strip()

        video_asset_elem = xml.find('video_asset')
        if edxval_api and video_asset_elem is not None:
            # Always pass the edx_video_id, Whether the video is internal or external
            # In case of external, we only need to import transcripts and for that
            # purpose video id is already present in the xml
            edxval_api.import_from_xml(video_asset_elem,
                                       edx_video_id,
                                       course_id=course_id)
示例#11
0
    def import_video_info_into_val(self, xml, course_id):
        """
        Import parsed video info from `xml` into edxval.

        Arguments:
            xml (lxml object): xml representation of video to be imported
            course_id (str): course id
        """
        if self.edx_video_id is not None:
            edx_video_id = self.edx_video_id.strip()

        video_asset_elem = xml.find('video_asset')
        if edxval_api and video_asset_elem is not None:
            # Always pass the edx_video_id, Whether the video is internal or external
            # In case of external, we only need to import transcripts and for that
            # purpose video id is already present in the xml
            edxval_api.import_from_xml(
                video_asset_elem,
                edx_video_id,
                course_id=course_id
            )
示例#12
0
    def import_video_info_into_val(self, xml, resource_fs, course_id):
        """
        Import parsed video info from `xml` into edxval.

        Arguments:
            xml (lxml object): xml representation of video to be imported.
            resource_fs (OSFS): Import file system.
            course_id (str): course id
        """
        edx_video_id = clean_video_id(self.edx_video_id)

        # Create video_asset is not already present.
        video_asset_elem = xml.find('video_asset')
        if video_asset_elem is None:
            video_asset_elem = etree.Element('video_asset')

        # This will be a dict containing the list of names of the external transcripts.
        # Example:
        # {
        #     'en': ['The_Flash.srt', 'Harry_Potter.srt'],
        #     'es': ['Green_Arrow.srt']
        # }
        external_transcripts = defaultdict(list)

        # Add trancript from self.sub and self.youtube_id_1_0 fields.
        external_transcripts['en'] = [
            subs_filename(transcript, 'en')
            for transcript in [self.sub, self.youtube_id_1_0] if transcript
        ]

        for language_code, transcript in self.transcripts.items():
            external_transcripts[language_code].append(transcript)

        if edxval_api:
            edx_video_id = edxval_api.import_from_xml(
                video_asset_elem,
                edx_video_id,
                resource_fs,
                EXPORT_IMPORT_STATIC_DIR,
                external_transcripts,
                course_id=course_id
            )
        return edx_video_id
示例#13
0
    def _parse_video_xml(cls, xml, id_generator=None):
        """
        Parse video fields out of xml_data. The fields are set if they are
        present in the XML.

        Arguments:
            id_generator is used to generate course-specific urls and identifiers
        """
        field_data = {}

        # Convert between key types for certain attributes --
        # necessary for backwards compatibility.
        conversions = {
            # example: 'start_time': cls._example_convert_start_time
        }

        # Convert between key names for certain attributes --
        # necessary for backwards compatibility.
        compat_keys = {
            'from': 'start_time',
            'to': 'end_time'
        }
        sources = xml.findall('source')
        if sources:
            field_data['html5_sources'] = [ele.get('src') for ele in sources]

        track = xml.find('track')
        if track is not None:
            field_data['track'] = track.get('src')

        handout = xml.find('handout')
        if handout is not None:
            field_data['handout'] = handout.get('src')

        transcripts = xml.findall('transcript')
        if transcripts:
            field_data['transcripts'] = {tr.get('language'): tr.get('src') for tr in transcripts}

        for attr, value in xml.items():
            if attr in compat_keys:
                attr = compat_keys[attr]
            if attr in cls.metadata_to_strip + ('url_name', 'name'):
                continue
            if attr == 'youtube':
                speeds = cls._parse_youtube(value)
                for speed, youtube_id in speeds.items():
                    # should have made these youtube_id_1_00 for
                    # cleanliness, but hindsight doesn't need glasses
                    normalized_speed = speed[:-1] if speed.endswith('0') else speed
                    # If the user has specified html5 sources, make sure we don't use the default video
                    if youtube_id != '' or 'html5_sources' in field_data:
                        field_data['youtube_id_{0}'.format(normalized_speed.replace('.', '_'))] = youtube_id
            elif attr in conversions:
                field_data[attr] = conversions[attr](value)
            elif attr not in cls.fields:
                field_data.setdefault('xml_attributes', {})[attr] = value
            else:
                # We export values with json.dumps (well, except for Strings, but
                # for about a month we did it for Strings also).
                field_data[attr] = deserialize_field(cls.fields[attr], value)

        course_id = getattr(id_generator, 'target_course_id', None)
        # Update the handout location with current course_id
        if 'handout' in field_data.keys() and course_id:
            handout_location = StaticContent.get_location_from_path(field_data['handout'])
            if isinstance(handout_location, AssetLocator):
                handout_new_location = StaticContent.compute_location(course_id, handout_location.path)
                field_data['handout'] = StaticContent.serialize_asset_key_with_slash(handout_new_location)

        # For backwards compatibility: Add `source` if XML doesn't have `download_video`
        # attribute.
        if 'download_video' not in field_data and sources:
            field_data['source'] = field_data['html5_sources'][0]

        # For backwards compatibility: if XML doesn't have `download_track` attribute,
        # it means that it is an old format. So, if `track` has some value,
        # `download_track` needs to have value `True`.
        if 'download_track' not in field_data and track is not None:
            field_data['download_track'] = True

        video_asset_elem = xml.find('video_asset')
        if (
                edxval_api and
                video_asset_elem is not None and
                'edx_video_id' in field_data
        ):
            # Allow ValCannotCreateError to escape
            edxval_api.import_from_xml(
                video_asset_elem,
                field_data['edx_video_id'],
                course_id=course_id
            )

        # load license if it exists
        field_data = LicenseMixin.parse_license_from_xml(field_data, xml)

        return field_data
示例#14
0
    def _parse_video_xml(cls, xml, id_generator=None):
        """
        Parse video fields out of xml_data. The fields are set if they are
        present in the XML.

        Arguments:
            id_generator is used to generate course-specific urls and identifiers
        """
        field_data = {}

        # Convert between key types for certain attributes --
        # necessary for backwards compatibility.
        conversions = {
            # example: 'start_time': cls._example_convert_start_time
        }

        # Convert between key names for certain attributes --
        # necessary for backwards compatibility.
        compat_keys = {"from": "start_time", "to": "end_time"}
        sources = xml.findall("source")
        if sources:
            field_data["html5_sources"] = [ele.get("src") for ele in sources]

        track = xml.find("track")
        if track is not None:
            field_data["track"] = track.get("src")

        handout = xml.find("handout")
        if handout is not None:
            field_data["handout"] = handout.get("src")

        transcripts = xml.findall("transcript")
        if transcripts:
            field_data["transcripts"] = {tr.get("language"): tr.get("src") for tr in transcripts}

        for attr, value in xml.items():
            if attr in compat_keys:
                attr = compat_keys[attr]
            if attr in cls.metadata_to_strip + ("url_name", "name"):
                continue
            if attr == "youtube":
                speeds = cls._parse_youtube(value)
                for speed, youtube_id in speeds.items():
                    # should have made these youtube_id_1_00 for
                    # cleanliness, but hindsight doesn't need glasses
                    normalized_speed = speed[:-1] if speed.endswith("0") else speed
                    # If the user has specified html5 sources, make sure we don't use the default video
                    if youtube_id != "" or "html5_sources" in field_data:
                        field_data["youtube_id_{0}".format(normalized_speed.replace(".", "_"))] = youtube_id
            elif attr in conversions:
                field_data[attr] = conversions[attr](value)
            elif attr not in cls.fields:
                field_data.setdefault("xml_attributes", {})[attr] = value
            else:
                # We export values with json.dumps (well, except for Strings, but
                # for about a month we did it for Strings also).
                field_data[attr] = deserialize_field(cls.fields[attr], value)

        # For backwards compatibility: Add `source` if XML doesn't have `download_video`
        # attribute.
        if "download_video" not in field_data and sources:
            field_data["source"] = field_data["html5_sources"][0]

        # For backwards compatibility: if XML doesn't have `download_track` attribute,
        # it means that it is an old format. So, if `track` has some value,
        # `download_track` needs to have value `True`.
        if "download_track" not in field_data and track is not None:
            field_data["download_track"] = True

        video_asset_elem = xml.find("video_asset")
        if edxval_api and video_asset_elem is not None and "edx_video_id" in field_data:
            # Allow ValCannotCreateError to escape
            edxval_api.import_from_xml(
                video_asset_elem, field_data["edx_video_id"], course_id=getattr(id_generator, "target_course_id", None)
            )

        # load license if it exists
        field_data = LicenseMixin.parse_license_from_xml(field_data, xml)

        return field_data
示例#15
0
 def test_existing_video_with_invalid_course_id(self):
     xml = self.make_import_xml(video_dict=constants.VIDEO_DICT_FISH)
     with self.assertRaises(ValCannotCreateError):
         api.import_from_xml(xml, edx_video_id=constants.VIDEO_DICT_FISH["edx_video_id"], course_id="x" * 300)
示例#16
0
 def assert_invalid_import(self, xml, course_id=None):
     edx_video_id = "test_edx_video_id"
     with self.assertRaises(ValCannotCreateError):
         api.import_from_xml(xml, edx_video_id, course_id)
     self.assertFalse(
         Video.objects.filter(edx_video_id=edx_video_id).exists())
示例#17
0
 def assert_invalid_import(self, xml, course_id=None):
     edx_video_id = "test_edx_video_id"
     with self.assertRaises(ValCannotCreateError):
         api.import_from_xml(xml, edx_video_id, course_id)
     self.assertFalse(Video.objects.filter(edx_video_id=edx_video_id).exists())