def create_video(video_data): """ Called on to create Video objects in the database create_video is used to create Video objects whose children are EncodedVideo objects which are linked to Profile objects. This is an alternative to the HTTP requests so it can be used internally. The VideoSerializer is used to deserialize this object. If there are duplicate profile_names, the entire creation will be rejected. If the profile is not found in the database, the video will not be created. Args: data (dict): { url: api url to the video edx_video_id: ID of the video duration: Length of video in seconds client_video_id: client ID of video encoded_video: a list of EncodedVideo dicts url: url of the video file_size: size of the video in bytes profile: ID of the profile courses: Courses associated with this video } """ serializer = VideoSerializer(data=video_data) if serializer.is_valid(): serializer.save() return video_data.get("edx_video_id") else: raise ValCannotCreateError(serializer.errors)
def _get_videos_for_filter(video_filter, sort_field=None, sort_dir=SortDirection.asc, pagination_conf=None): """ Returns a generator expression that contains the videos found, sorted by the given field and direction, with ties broken by edx_video_id to ensure a total order. """ videos = Video.objects.filter(**video_filter) paginator_context = {} if sort_field: # Refining by edx_video_id ensures a total order videos = videos.order_by(sort_field.value, "edx_video_id") if sort_dir == SortDirection.desc: videos = videos.reverse() if pagination_conf: videos_per_page = pagination_conf.get('videos_per_page') paginator = Paginator(videos, videos_per_page) videos = paginator.page(pagination_conf.get('page_number')) paginator_context = { 'current_page': videos.number, 'total_pages': videos.paginator.num_pages, 'items_on_one_page': videos_per_page } return (VideoSerializer(video).data for video in videos), paginator_context
def test_encoded_video_set_output(self): """ Tests for basic structure of EncodedVideoSetSerializer """ video = Video.objects.create(**constants.VIDEO_DICT_FISH) EncodedVideo.objects.create( video=video, profile=Profile.objects.get(profile_name="desktop"), **constants.ENCODED_VIDEO_DICT_DESKTOP ) EncodedVideo.objects.create( video=video, profile=Profile.objects.get(profile_name="mobile"), **constants.ENCODED_VIDEO_DICT_MOBILE ) EncodedVideo.objects.create( video=video, profile=Profile.objects.get(profile_name="hls"), **constants.ENCODED_VIDEO_DICT_HLS ) result = VideoSerializer(video).data # Check for 3 EncodedVideo entries self.assertEqual(len(result.get("encoded_videos")), 3) # Check for original Video data matching_dict = {k: v for k, v in result.items() if k in constants.VIDEO_DICT_FISH} assert constants.VIDEO_DICT_FISH == matching_dict
def test_invalid_edx_video_id(self): """ Test the Video model regex validation for edx_video_id field """ serializer = VideoSerializer(data=constants.VIDEO_DICT_INVALID_ID) self.assertFalse(serializer.is_valid()) message = serializer.errors.get("edx_video_id")[0] self.assertEqual(message, u"edx_video_id has invalid characters")
def test_non_latin_serialization(self): """ Tests if the serializers can accept non-latin chars """ # TODO not the best test. Need to understand what result we want self.assertIsInstance( VideoSerializer( Video.objects.get(edx_video_id=constants. VIDEO_DICT_NON_LATIN_ID["edx_video_id"])), VideoSerializer)
def test_wrong_input_type(self): """ Tests an non dict input in the VideoSerializer """ data = "hello" serializer = VideoSerializer(data=data) self.assertFalse(serializer.is_valid()) self.assertEqual( serializer.errors.get("non_field_errors")[0], "Invalid data. Expected a dictionary, but got str.")
def test_negative_fields_for_video_serializer(self): """ Tests negative inputs for VideoSerializer Tests negative inputs for duration in model Video """ serializer = VideoSerializer( data=constants.VIDEO_DICT_NEGATIVE_DURATION) self.assertFalse(serializer.is_valid()) self.assertEqual( serializer.errors.get('duration')[0], u"Ensure this value is greater than or equal to 0.")
def test_no_profile_validation(self): """ Tests when there are no profiles to validation when deserializing """ data = dict(encoded_videos=[constants.ENCODED_VIDEO_DICT_MOBILE], **constants.VIDEO_DICT_FISH) serializer = VideoSerializer(data=data) self.assertFalse(serializer.is_valid()) self.assertEqual(serializer.errors.get("encoded_videos"), [{ "profile": ["This field is required."] }])
def get_video_info(edx_video_id): """ Retrieves all encoded videos of a video found with given video edx_video_id Args: edx_video_id (str): id for video content. Returns: (dict): Deserialized Video Object with related field EncodedVideo Returns all the Video object fields, and it's related EncodedVideo objects in a list. { url: api url to the video edx_video_id: ID of the video status: Status of the video as a string duration: Length of video in seconds client_video_id: client ID of video encoded_video: a list of EncodedVideo dicts url: url of the video file_size: size of the video in bytes profile: ID of the profile subtitles: a list of Subtitle dicts fmt: file format (SRT or SJSON) language: language code content_url: url of file url: api url to subtitle } Raises: ValVideoNotFoundError: Raised if video doesn't exist ValInternalError: Raised for unknown errors Example: Given one EncodedVideo with edx_video_id "example" >>> get_video_info("example") Returns (dict): { 'url' : '/edxval/videos/example', 'edx_video_id': u'example', 'duration': 111.0, 'client_video_id': u'The example video', 'encoded_videos': [ { 'url': u'http://www.example.com', 'file_size': 25556, 'bitrate': 9600, 'profile': u'mobile' } ] } """ return VideoSerializer(_get_video(edx_video_id)).data
def _get_videos_for_filter(video_filter, sort_field=None, sort_dir=SortDirection.asc): """ Returns a generator expression that contains the videos found, sorted by the given field and direction, with ties broken by edx_video_id to ensure a total order. """ videos = Video.objects.filter(**video_filter) if sort_field: # Refining by edx_video_id ensures a total order videos = videos.order_by(sort_field.value, "edx_video_id") if sort_dir == SortDirection.desc: videos = videos.reverse() return (VideoSerializer(video).data for video in videos)
def test_invalid_course_id(self): serializer = VideoSerializer( data={ "edx_video_id": "dummy", "client_video_id": "dummy", "duration": 0, "status": "dummy", "encoded_videos": [], "courses": ["x" * 300], }) self.assertFalse(serializer.is_valid()) self.assertEqual( serializer.errors, { "courses": ["Ensure this value has at most 255 characters (it has 300)."] })
def test_encoded_video_set_output(self): """ Tests for basic structure of EncodedVideoSetSerializer """ video = Video.objects.create(**constants.VIDEO_DICT_FISH) EncodedVideo.objects.create( video=video, profile=Profile.objects.get(profile_name="desktop"), **constants.ENCODED_VIDEO_DICT_DESKTOP) EncodedVideo.objects.create( video=video, profile=Profile.objects.get(profile_name="mobile"), **constants.ENCODED_VIDEO_DICT_MOBILE) result = VideoSerializer(video).data # pylint: disable=E1101 # Check for 2 EncodedVideo entries self.assertEqual(len(result.get("encoded_videos")), 2) # Check for original Video data self.assertDictContainsSubset(constants.VIDEO_DICT_FISH, result)
def update_video(video_data): """ Called on to update Video objects in the database update_video is used to update Video objects by the given edx_video_id in the video_data. Args: video_data (dict): { url: api url to the video edx_video_id: ID of the video duration: Length of video in seconds client_video_id: client ID of video encoded_video: a list of EncodedVideo dicts url: url of the video file_size: size of the video in bytes profile: ID of the profile courses: Courses associated with this video } Raises: Raises ValVideoNotFoundError if the video cannot be retrieved. Raises ValCannotUpdateError if the video cannot be updated. Returns the successfully updated Video object """ try: video = _get_video(video_data.get("edx_video_id")) except Video.DoesNotExist: error_message = u"Video not found when trying to update video with edx_video_id: {0}".format( video_data.get("edx_video_id")) raise ValVideoNotFoundError(error_message) serializer = VideoSerializer(video, data=video_data) if serializer.is_valid(): serializer.save() return video_data.get("edx_video_id") else: raise ValCannotUpdateError(serializer.errors)