def test_remove_transcript_preferences_not_found(self): """ Test that transcript handler works correctly even when no preferences are found. """ course_id = 'course-v1:dummy+course+id' # Verify transcript preferences do not exist preferences = get_transcript_preferences(course_id) self.assertIsNone(preferences) response = self.client.delete(self.get_url_for_course_key(course_id), content_type='application/json') self.assertEqual(response.status_code, 204) # Verify transcript preferences do not exist preferences = get_transcript_preferences(course_id) self.assertIsNone(preferences)
def videos_index_html(course): """ Returns an HTML page to display previous video uploads and allow new ones """ is_video_transcript_enabled = VideoTranscriptEnabledFlag.feature_enabled( course.id) context = { 'context_course': course, 'image_upload_url': reverse_course_url('video_images_handler', unicode(course.id)), 'video_handler_url': reverse_course_url('videos_handler', unicode(course.id)), 'encodings_download_url': reverse_course_url('video_encodings_download', unicode(course.id)), 'default_video_image_url': _get_default_video_image_url(), 'previous_uploads': _get_index_videos(course), 'concurrent_upload_limit': settings.VIDEO_UPLOAD_PIPELINE.get('CONCURRENT_UPLOAD_LIMIT', 0), 'video_supported_file_formats': VIDEO_SUPPORTED_FILE_FORMATS.keys(), 'video_upload_max_file_size': VIDEO_UPLOAD_MAX_FILE_SIZE_GB, 'video_image_settings': { 'video_image_upload_enabled': WAFFLE_SWITCHES.is_enabled(VIDEO_IMAGE_UPLOAD_ENABLED), 'max_size': settings.VIDEO_IMAGE_SETTINGS['VIDEO_IMAGE_MAX_BYTES'], 'min_size': settings.VIDEO_IMAGE_SETTINGS['VIDEO_IMAGE_MIN_BYTES'], 'max_width': settings.VIDEO_IMAGE_MAX_WIDTH, 'max_height': settings.VIDEO_IMAGE_MAX_HEIGHT, 'supported_file_formats': settings.VIDEO_IMAGE_SUPPORTED_FILE_FORMATS }, 'is_video_transcript_enabled': is_video_transcript_enabled, 'video_transcript_settings': None, 'active_transcript_preferences': None } if is_video_transcript_enabled: context['video_transcript_settings'] = { 'transcript_preferences_handler_url': reverse_course_url('transcript_preferences_handler', unicode(course.id)), 'transcription_plans': get_3rd_party_transcription_plans(), } context['active_transcript_preferences'] = get_transcript_preferences( unicode(course.id)) return render_to_response('videos_index.html', context)
def test_remove_transcript_preferences_not_found(self): """ Test that transcript handler works correctly even when no preferences are found. """ course_id = 'course-v1:dummy+course+id' # Verify transcript preferences do not exist preferences = get_transcript_preferences(course_id) self.assertIsNone(preferences) response = self.client.delete( self.get_url_for_course_key(course_id), content_type='application/json' ) self.assertEqual(response.status_code, 204) # Verify transcript preferences do not exist preferences = get_transcript_preferences(course_id) self.assertIsNone(preferences)
def videos_index_html(course, pagination_conf=None): """ Returns an HTML page to display previous video uploads and allow new ones """ is_video_transcript_enabled = VideoTranscriptEnabledFlag.feature_enabled(course.id) previous_uploads, pagination_context = _get_index_videos(course, pagination_conf) context = { 'context_course': course, 'image_upload_url': reverse_course_url('video_images_handler', six.text_type(course.id)), 'video_handler_url': reverse_course_url('videos_handler', six.text_type(course.id)), 'encodings_download_url': reverse_course_url('video_encodings_download', six.text_type(course.id)), 'default_video_image_url': _get_default_video_image_url(), 'previous_uploads': previous_uploads, 'concurrent_upload_limit': settings.VIDEO_UPLOAD_PIPELINE.get('CONCURRENT_UPLOAD_LIMIT', 0), 'video_supported_file_formats': list(VIDEO_SUPPORTED_FILE_FORMATS.keys()), 'video_upload_max_file_size': VIDEO_UPLOAD_MAX_FILE_SIZE_GB, 'video_image_settings': { 'video_image_upload_enabled': WAFFLE_SWITCHES.is_enabled(VIDEO_IMAGE_UPLOAD_ENABLED), 'max_size': settings.VIDEO_IMAGE_SETTINGS['VIDEO_IMAGE_MAX_BYTES'], 'min_size': settings.VIDEO_IMAGE_SETTINGS['VIDEO_IMAGE_MIN_BYTES'], 'max_width': settings.VIDEO_IMAGE_MAX_WIDTH, 'max_height': settings.VIDEO_IMAGE_MAX_HEIGHT, 'supported_file_formats': settings.VIDEO_IMAGE_SUPPORTED_FILE_FORMATS }, 'is_video_transcript_enabled': is_video_transcript_enabled, 'active_transcript_preferences': None, 'transcript_credentials': None, 'transcript_available_languages': get_all_transcript_languages(), 'video_transcript_settings': { 'transcript_download_handler_url': reverse('transcript_download_handler'), 'transcript_upload_handler_url': reverse('transcript_upload_handler'), 'transcript_delete_handler_url': reverse_course_url('transcript_delete_handler', six.text_type(course.id)), 'trancript_download_file_format': Transcript.SRT }, 'pagination_context': pagination_context } if is_video_transcript_enabled: context['video_transcript_settings'].update({ 'transcript_preferences_handler_url': reverse_course_url( 'transcript_preferences_handler', six.text_type(course.id) ), 'transcript_credentials_handler_url': reverse_course_url( 'transcript_credentials_handler', six.text_type(course.id) ), 'transcription_plans': get_3rd_party_transcription_plans(), }) context['active_transcript_preferences'] = get_transcript_preferences(six.text_type(course.id)) # Cached state for transcript providers' credentials (org-specific) context['transcript_credentials'] = get_transcript_credentials_state_for_org(course.id.org) return render_to_response('videos_index.html', context)
def videos_index_html(course): """ Returns an HTML page to display previous video uploads and allow new ones """ is_video_transcript_enabled = VideoTranscriptEnabledFlag.feature_enabled(course.id) context = { 'context_course': course, 'image_upload_url': reverse_course_url('video_images_handler', unicode(course.id)), 'video_handler_url': reverse_course_url('videos_handler', unicode(course.id)), 'encodings_download_url': reverse_course_url('video_encodings_download', unicode(course.id)), 'default_video_image_url': _get_default_video_image_url(), 'previous_uploads': _get_index_videos(course), 'concurrent_upload_limit': settings.VIDEO_UPLOAD_PIPELINE.get('CONCURRENT_UPLOAD_LIMIT', 0), 'video_supported_file_formats': VIDEO_SUPPORTED_FILE_FORMATS.keys(), 'video_upload_max_file_size': VIDEO_UPLOAD_MAX_FILE_SIZE_GB, 'video_image_settings': { 'video_image_upload_enabled': WAFFLE_SWITCHES.is_enabled(VIDEO_IMAGE_UPLOAD_ENABLED), 'max_size': settings.VIDEO_IMAGE_SETTINGS['VIDEO_IMAGE_MAX_BYTES'], 'min_size': settings.VIDEO_IMAGE_SETTINGS['VIDEO_IMAGE_MIN_BYTES'], 'max_width': settings.VIDEO_IMAGE_MAX_WIDTH, 'max_height': settings.VIDEO_IMAGE_MAX_HEIGHT, 'supported_file_formats': settings.VIDEO_IMAGE_SUPPORTED_FILE_FORMATS }, 'is_video_transcript_enabled': is_video_transcript_enabled, 'active_transcript_preferences': None, 'transcript_credentials': None, 'transcript_available_languages': get_all_transcript_languages(), 'video_transcript_settings': { 'transcript_download_handler_url': reverse('transcript_download_handler'), 'transcript_upload_handler_url': reverse('transcript_upload_handler'), 'transcript_delete_handler_url': reverse_course_url('transcript_delete_handler', unicode(course.id)), 'trancript_download_file_format': Transcript.SRT } } if is_video_transcript_enabled: context['video_transcript_settings'].update({ 'transcript_preferences_handler_url': reverse_course_url( 'transcript_preferences_handler', unicode(course.id) ), 'transcript_credentials_handler_url': reverse_course_url( 'transcript_credentials_handler', unicode(course.id) ), 'transcription_plans': get_3rd_party_transcription_plans(), }) context['active_transcript_preferences'] = get_transcript_preferences(unicode(course.id)) # Cached state for transcript providers' credentials (org-specific) context['transcript_credentials'] = get_transcript_credentials_state_for_org(course.id.org) return render_to_response('videos_index.html', context)
def test_remove_transcript_preferences(self): """ Test that transcript handler removes transcript preferences correctly. """ # First add course wide transcript preferences. preferences = create_or_update_transcript_preferences( unicode(self.course.id)) # Verify transcript preferences exist self.assertIsNotNone(preferences) response = self.client.delete(self.get_url_for_course_key( self.course.id), content_type='application/json') self.assertEqual(response.status_code, 204) # Verify transcript preferences no loger exist preferences = get_transcript_preferences(unicode(self.course.id)) self.assertIsNone(preferences)
def test_remove_transcript_preferences(self): """ Test that transcript handler removes transcript preferences correctly. """ # First add course wide transcript preferences. preferences = create_or_update_transcript_preferences(unicode(self.course.id)) # Verify transcript preferences exist self.assertIsNotNone(preferences) response = self.client.delete( self.get_url_for_course_key(self.course.id), content_type='application/json' ) self.assertEqual(response.status_code, 204) # Verify transcript preferences no loger exist preferences = get_transcript_preferences(unicode(self.course.id)) self.assertIsNone(preferences)
def videos_post(course, request): """ Input (JSON): { "files": [{ "file_name": "video.mp4", "content_type": "video/mp4" }] } Returns (JSON): { "files": [{ "file_name": "video.mp4", "upload_url": "http://example.com/put_video" }] } The returned array corresponds exactly to the input array. """ error = None data = request.json if 'files' not in data: error = "Request object is not JSON or does not contain 'files'" elif any( 'file_name' not in file or 'content_type' not in file for file in data['files'] ): error = "Request 'files' entry does not contain 'file_name' and 'content_type'" elif any( file['content_type'] not in VIDEO_SUPPORTED_FILE_FORMATS.values() for file in data['files'] ): error = "Request 'files' entry contain unsupported content_type" if error: return JsonResponse({'error': error}, status=400) bucket = storage_service_bucket() req_files = data['files'] resp_files = [] for req_file in req_files: file_name = req_file['file_name'] try: file_name.encode('ascii') except UnicodeEncodeError: error_msg = u'The file name for %s must contain only ASCII characters.' % file_name return JsonResponse({'error': error_msg}, status=400) edx_video_id = unicode(uuid4()) key = storage_service_key(bucket, file_name=edx_video_id) metadata_list = [ ('client_video_id', file_name), ('course_key', unicode(course.id)), ] deprecate_youtube = waffle_flags()[DEPRECATE_YOUTUBE] course_video_upload_token = course.video_upload_pipeline.get('course_video_upload_token') # Only include `course_video_upload_token` if youtube has not been deprecated # for this course. if not deprecate_youtube.is_enabled(course.id) and course_video_upload_token: metadata_list.append(('course_video_upload_token', course_video_upload_token)) is_video_transcript_enabled = VideoTranscriptEnabledFlag.feature_enabled(course.id) if is_video_transcript_enabled: transcript_preferences = get_transcript_preferences(unicode(course.id)) if transcript_preferences is not None: metadata_list.append(('transcript_preferences', json.dumps(transcript_preferences))) for metadata_name, value in metadata_list: key.set_metadata(metadata_name, value) upload_url = key.generate_url( KEY_EXPIRATION_IN_SECONDS, 'PUT', headers={'Content-Type': req_file['content_type']} ) # persist edx_video_id in VAL create_video({ 'edx_video_id': edx_video_id, 'status': 'upload', 'client_video_id': file_name, 'duration': 0, 'encoded_videos': [], 'courses': [unicode(course.id)] }) resp_files.append({'file_name': file_name, 'upload_url': upload_url, 'edx_video_id': edx_video_id}) return JsonResponse({'files': resp_files}, status=200)
def videos_post(course, request): """ Input (JSON): { "files": [{ "file_name": "video.mp4", "content_type": "video/mp4" }] } Returns (JSON): { "files": [{ "file_name": "video.mp4", "upload_url": "http://example.com/put_video" }] } The returned array corresponds exactly to the input array. """ error = None data = request.json if 'files' not in data: error = "Request object is not JSON or does not contain 'files'" elif any( 'file_name' not in file or 'content_type' not in file for file in data['files'] ): error = "Request 'files' entry does not contain 'file_name' and 'content_type'" elif any( file['content_type'] not in VIDEO_SUPPORTED_FILE_FORMATS.values() for file in data['files'] ): error = "Request 'files' entry contain unsupported content_type" if error: return JsonResponse({'error': error}, status=400) req_files = data['files'] resp_files = [] for req_file in req_files: file_name = req_file['file_name'] try: file_name.encode('ascii') except UnicodeEncodeError: error_msg = 'The file name for %s must contain only ASCII characters.' % file_name return JsonResponse({'error': error_msg}, status=400) edx_video_id = unicode(uuid4()) metadata_list = [ ('client_video_id', file_name), ('course_key', unicode(course.id)), ] # Only include `course_video_upload_token` if its set, as it won't be required if video uploads # are enabled by default. course_video_upload_token = course.video_upload_pipeline.get('course_video_upload_token') if course_video_upload_token: metadata_list.append(('course_video_upload_token', course_video_upload_token)) is_video_transcript_enabled = VideoTranscriptEnabledFlag.feature_enabled(course.id) if is_video_transcript_enabled: transcript_preferences = get_transcript_preferences(unicode(course.id)) if transcript_preferences is not None: metadata_list.append(('transcript_preferences', json.dumps(transcript_preferences))) upload_url = settings.VIDEO_UPLOAD_PREAUTH_URL+edx_video_id # persist edx_video_id in VAL create_video({ 'edx_video_id': edx_video_id, 'status': 'upload', 'client_video_id': file_name, 'duration': 0, 'encoded_videos': [], 'courses': [unicode(course.id)] }) resp_files.append({'file_name': file_name, 'upload_url': upload_url, 'edx_video_id': edx_video_id}) return JsonResponse({'files': resp_files}, status=200)
def videos_post(course, request): """ Input (JSON): { "files": [{ "file_name": "video.mp4", "content_type": "video/mp4" }] } Returns (JSON): { "files": [{ "file_name": "video.mp4", "upload_url": "http://example.com/put_video" }] } The returned array corresponds exactly to the input array. """ error = None data = request.json if 'files' not in data: error = "Request object is not JSON or does not contain 'files'" elif any( 'file_name' not in file or 'content_type' not in file for file in data['files'] ): error = "Request 'files' entry does not contain 'file_name' and 'content_type'" elif any( file['content_type'] not in VIDEO_SUPPORTED_FILE_FORMATS.values() for file in data['files'] ): error = "Request 'files' entry contain unsupported content_type" if error: return JsonResponse({'error': error}, status=400) bucket = storage_service_bucket() req_files = data['files'] resp_files = [] for req_file in req_files: file_name = req_file['file_name'] try: file_name.encode('ascii') except UnicodeEncodeError: error_msg = 'The file name for %s must contain only ASCII characters.' % file_name return JsonResponse({'error': error_msg}, status=400) edx_video_id = unicode(uuid4()) key = storage_service_key(bucket, file_name=edx_video_id) metadata_list = [ ('client_video_id', file_name), ('course_key', unicode(course.id)), ] # Only include `course_video_upload_token` if its set, as it won't be required if video uploads # are enabled by default. course_video_upload_token = course.video_upload_pipeline.get('course_video_upload_token') if course_video_upload_token: metadata_list.append(('course_video_upload_token', course_video_upload_token)) is_video_transcript_enabled = VideoTranscriptEnabledFlag.feature_enabled(course.id) if is_video_transcript_enabled: transcript_preferences = get_transcript_preferences(unicode(course.id)) if transcript_preferences is not None: metadata_list.append(('transcript_preferences', json.dumps(transcript_preferences))) for metadata_name, value in metadata_list: key.set_metadata(metadata_name, value) upload_url = key.generate_url( KEY_EXPIRATION_IN_SECONDS, 'PUT', headers={'Content-Type': req_file['content_type']} ) # persist edx_video_id in VAL create_video({ 'edx_video_id': edx_video_id, 'status': 'upload', 'client_video_id': file_name, 'duration': 0, 'encoded_videos': [], 'courses': [unicode(course.id)] }) resp_files.append({'file_name': file_name, 'upload_url': upload_url, 'edx_video_id': edx_video_id}) return JsonResponse({'files': resp_files}, status=200)