ran python-modernize and isort on files mentioned in INCR-332

changes made to comply with pylint

refactored the code to comply with PEP8

further changes made to comply with quality

changes made as suggested
This commit is contained in:
aarif
2019-07-09 14:33:48 +05:00
committed by root
parent 16c7227c07
commit b20eb309ff
10 changed files with 112 additions and 69 deletions

View File

@@ -1,24 +1,23 @@
"""Views for assets"""
from __future__ import absolute_import
import json
import logging
import math
from functools import partial
import re
from functools import partial
import six
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.http import HttpResponseBadRequest, HttpResponseNotFound
from django.utils.translation import ugettext as _
from django.views.decorators.csrf import ensure_csrf_cookie
from django.views.decorators.http import require_POST, require_http_methods
from django.views.decorators.http import require_http_methods, require_POST
from opaque_keys.edx.keys import AssetKey, CourseKey
from pymongo import ASCENDING, DESCENDING
from six import text_type
from xmodule.contentstore.content import StaticContent
from xmodule.contentstore.django import contentstore
from xmodule.exceptions import NotFoundError
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError
from contentstore.utils import reverse_course_url
from contentstore.views.exception import AssetNotFoundException, AssetSizeTooLargeException
@@ -27,6 +26,11 @@ from openedx.core.djangoapps.contentserver.caching import del_cached_content
from student.auth import has_course_author_access
from util.date_utils import get_default_time_display
from util.json_request import JsonResponse
from xmodule.contentstore.content import StaticContent
from xmodule.contentstore.django import contentstore
from xmodule.exceptions import NotFoundError
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError
__all__ = ['assets_handler']
@@ -186,6 +190,7 @@ def _get_requested_attribute(request, attribute):
def _get_error_if_invalid_parameters(requested_filter):
"""Function for returning error messages on filters"""
requested_file_types = _get_requested_file_types_from_requested_filter(requested_filter)
invalid_filters = []
@@ -295,6 +300,7 @@ def _get_sort_type_and_direction(request_options):
def _get_mongo_sort_from_requested_sort(requested_sort):
"""Function returns sorts dataset based on the key provided"""
if requested_sort == 'date_added':
sort = 'uploadDate'
elif requested_sort == 'display_name':
@@ -320,6 +326,7 @@ def _get_first_asset_index(current_page, page_size):
def _get_assets_for_page(course_key, options):
"""returns course content for given course and options"""
current_page = options['current_page']
page_size = options['page_size']
sort = options['sort']
@@ -331,10 +338,12 @@ def _get_assets_for_page(course_key, options):
def _update_options_to_requery_final_page(query_options, total_asset_count):
"""sets current_page value based on asset count and page_size"""
query_options['current_page'] = int(math.floor((total_asset_count - 1) / query_options['page_size']))
def _get_assets_in_json_format(assets, course_key):
"""returns assets information in JSON Format"""
assets_in_json_format = []
for asset in assets:
thumbnail_asset_key = _get_thumbnail_asset_key(asset, course_key)
@@ -355,6 +364,7 @@ def _get_assets_in_json_format(assets, course_key):
def update_course_run_asset(course_key, upload_file):
"""returns contents of the uploaded file"""
course_exists_response = _get_error_if_course_does_not_exist(course_key)
if course_exists_response is not None:
@@ -388,6 +398,7 @@ def update_course_run_asset(course_key, upload_file):
@ensure_csrf_cookie
@login_required
def _upload_asset(request, course_key):
"""uploads the file in request and returns JSON response"""
course_exists_error = _get_error_if_course_does_not_exist(course_key)
if course_exists_error is not None:
@@ -442,11 +453,13 @@ def _get_file_metadata_as_dictionary(upload_file):
def get_file_size(upload_file):
"""returns the size of the uploaded file"""
# can be used for mocking test file sizes.
return upload_file.size
def _check_file_size_is_too_large(file_metadata):
"""verifies whether file size is greater than allowed file size"""
upload_file_size = file_metadata['upload_file_size']
maximum_file_size_in_megabytes = settings.MAX_ASSET_UPLOAD_FILE_SIZE_IN_MB
maximum_file_size_in_bytes = maximum_file_size_in_megabytes * 1000 ** 2
@@ -455,6 +468,8 @@ def _check_file_size_is_too_large(file_metadata):
def _get_file_too_large_error_message(filename):
"""returns formatted error message for large files"""
return _(
u'File {filename} exceeds maximum size of '
u'{maximum_size_in_megabytes} MB.'
@@ -465,6 +480,7 @@ def _get_file_too_large_error_message(filename):
def _get_file_content_and_path(file_metadata, course_key):
"""returns contents of the uploaded file and path for temporary uploaded file"""
content_location = StaticContent.compute_location(course_key, file_metadata['filename'])
upload_file = file_metadata['upload_file']
@@ -483,10 +499,12 @@ def _get_file_content_and_path(file_metadata, course_key):
def _check_thumbnail_uploaded(thumbnail_content):
"""returns whether thumbnail is None"""
return thumbnail_content is not None
def _get_thumbnail_asset_key(asset, course_key):
"""returns thumbnail asset key"""
# note, due to the schema change we may not have a 'thumbnail_location' in the result set
thumbnail_location = asset.get('thumbnail_location', None)
thumbnail_asset_key = None
@@ -501,12 +519,12 @@ def _get_thumbnail_asset_key(asset, course_key):
@login_required
@ensure_csrf_cookie
def _update_asset(request, course_key, asset_key):
'''
"""
restful CRUD operations for a course asset.
Currently only DELETE, POST, and PUT methods are implemented.
asset_path_encoding: the odd /c4x/org/course/category/name repr of the asset (used by Backbone as the id)
'''
"""
if request.method == 'DELETE':
try:
delete_asset(course_key, asset_key)
@@ -530,10 +548,12 @@ def _update_asset(request, course_key, asset_key):
def _save_content_to_trash(content):
"""saves the content to trash"""
contentstore('trashcan').save(content)
def delete_asset(course_key, asset_key):
"""deletes the cached content based on asset key"""
content = _check_existence_and_get_asset_content(asset_key)
_save_content_to_trash(content)
@@ -583,5 +603,5 @@ def _get_asset_json(display_name, content_type, date, location, thumbnail_locati
'thumbnail': StaticContent.serialize_asset_key_with_slash(thumbnail_location) if thumbnail_location else None,
'locked': locked,
# needed for Backbone delete/update.
'id': unicode(location)
'id': six.text_type(location)
}

View File

@@ -4,6 +4,8 @@ These views will NOT be shown on production: trying to access them will result
in a 404 error.
"""
# pylint: disable=unused-argument
from __future__ import absolute_import
from edxmako.shortcuts import render_to_response

View File

@@ -3,8 +3,11 @@ This views handles exporting the course xml to a git repository if
the giturl attribute is set.
"""
from __future__ import absolute_import
import logging
import six
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.utils.translation import ugettext as _
@@ -46,7 +49,7 @@ def export_git(request, course_key_string):
msg = _('Course successfully exported to git repository')
except git_export_utils.GitExportError as ex:
failed = True
msg = unicode(ex)
msg = six.text_type(ex)
return render_to_response('export_git.html', {
'context_course': course_module,

View File

@@ -2,6 +2,8 @@
These views handle all actions in Studio related to import and exporting of
courses
"""
from __future__ import absolute_import
import base64
import json
import logging
@@ -42,10 +44,8 @@ __all__ = [
'export_handler', 'export_output_handler', 'export_status_handler',
]
log = logging.getLogger(__name__)
# Regex to capture Content-Range header ranges.
CONTENT_RE = re.compile(r"(?P<start>\d{1,11})-(?P<stop>\d{1,11})/(?P<end>\d{1,11})")
@@ -147,7 +147,7 @@ def _write_chunk(request, courselike_key):
try:
matches = CONTENT_RE.search(request.META["HTTP_CONTENT_RANGE"])
content_range = matches.groupdict()
except KeyError: # Single chunk
except KeyError: # Single chunk
# no Content-Range header, so make one that will work
content_range = {'start': 0, 'stop': 1, 'end': 2}
@@ -179,7 +179,7 @@ def _write_chunk(request, courselike_key):
elif size > int(content_range['stop']) and size == int(content_range['end']):
return JsonResponse({'ImportStatus': 1})
with open(temp_filepath, mode) as temp_file:
with open(temp_filepath, mode) as temp_file: # pylint: disable=W6005
for chunk in request.FILES['course-data'].chunks():
temp_file.write(chunk)
@@ -199,7 +199,7 @@ def _write_chunk(request, courselike_key):
})
log.info(u"Course import %s: Upload complete", courselike_key)
with open(temp_filepath, 'rb') as local_file:
with open(temp_filepath, 'rb') as local_file: # pylint: disable=W6005
django_file = File(local_file)
storage_path = course_import_export_storage.save(u'olx_import/' + filename, django_file)
import_olx.delay(
@@ -386,7 +386,7 @@ def export_status_handler(request, course_key_string):
elif task_status.state in (UserTaskStatus.FAILED, UserTaskStatus.CANCELED):
status = max(-(task_status.completed_steps + 1), -2)
errors = UserTaskArtifact.objects.filter(status=task_status, name='Error')
if len(errors):
if errors:
error = errors[0].text
try:
error = json.loads(error)

View File

@@ -1,18 +1,19 @@
"""
Public views
"""
from __future__ import absolute_import
from django.conf import settings
from django.template.context_processors import csrf
from django.urls import reverse
from django.utils.http import urlquote_plus
from django.shortcuts import redirect
from django.template.context_processors import csrf
from django.utils.http import urlquote_plus
from django.views.decorators.clickjacking import xframe_options_deny
from django.views.decorators.csrf import ensure_csrf_cookie
from waffle.decorators import waffle_switch
from contentstore.config import waffle
from edxmako.shortcuts import render_to_response
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from waffle.decorators import waffle_switch
from contentstore.config import waffle
__all__ = ['signup', 'login_page', 'login_redirect_to_lms', 'howitworks', 'accessibility']

View File

@@ -1,9 +1,12 @@
"""
Unit tests for the gating feature in Studio
"""
from __future__ import absolute_import
import json
import ddt
import six
from mock import patch
from contentstore.tests.utils import CourseTestCase
@@ -86,12 +89,13 @@ class TestSubsectionGating(CourseTestCase):
self.client.ajax_post(
self.seq2_url,
data={'prereqUsageKey': unicode(self.seq1.location), 'prereqMinScore': '100', 'prereqMinCompletion': '100'}
data={'prereqUsageKey': six.text_type(self.seq1.location), 'prereqMinScore': '100',
'prereqMinCompletion': '100'}
)
mock_set_required_content.assert_called_with(
self.course.id,
self.seq2.location,
unicode(self.seq1.location),
six.text_type(self.seq1.location),
'100',
'100'
)
@@ -128,17 +132,17 @@ class TestSubsectionGating(CourseTestCase):
mock_is_prereq, mock_get_required_content, mock_get_prereqs
):
mock_is_prereq.return_value = True
mock_get_required_content.return_value = unicode(self.seq1.location), min_score, min_completion
mock_get_required_content.return_value = six.text_type(self.seq1.location), min_score, min_completion
mock_get_prereqs.return_value = [
{'namespace': '{}{}'.format(unicode(self.seq1.location), GATING_NAMESPACE_QUALIFIER)},
{'namespace': '{}{}'.format(unicode(self.seq2.location), GATING_NAMESPACE_QUALIFIER)}
{'namespace': '{}{}'.format(six.text_type(self.seq1.location), GATING_NAMESPACE_QUALIFIER)},
{'namespace': '{}{}'.format(six.text_type(self.seq2.location), GATING_NAMESPACE_QUALIFIER)}
]
resp = json.loads(self.client.get_json(self.seq2_url).content)
mock_is_prereq.assert_called_with(self.course.id, self.seq2.location)
mock_get_required_content.assert_called_with(self.course.id, self.seq2.location)
mock_get_prereqs.assert_called_with(self.course.id)
self.assertTrue(resp['is_prereq'])
self.assertEqual(resp['prereq'], unicode(self.seq1.location))
self.assertEqual(resp['prereq'], six.text_type(self.seq1.location))
self.assertEqual(resp['prereq_min_score'], min_score)
self.assertEqual(resp['prereq_min_completion'], min_completion)
self.assertEqual(resp['visibility_state'], VisibilityState.gated)

View File

@@ -3,6 +3,8 @@
"""
Course Header Menu Tests.
"""
from __future__ import absolute_import
from django.conf import settings
from django.test.utils import override_settings

View File

@@ -1,5 +1,7 @@
""" Tests for tab functions (just primitive). """
from __future__ import absolute_import
import json
from contentstore.tests.utils import CourseTestCase

View File

@@ -1,3 +1,7 @@
"""Views for users"""
from __future__ import absolute_import
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied
@@ -41,7 +45,8 @@ def course_team_handler(request, course_key_string=None, email=None):
html: return html page for managing course team
json: return json representation of a particular course team member (email is required).
POST or PUT
json: modify the permissions for a particular course team member (email is required, as well as role in the payload).
json: modify the permissions for a particular course team member (email is required, as well as role in the
payload).
DELETE:
json: remove a particular course team member from the course team (email is required).
"""
@@ -111,7 +116,7 @@ def _course_team_user(request, course_key, email):
try:
user = User.objects.get(email=email)
except Exception:
except Exception: # pylint: disable=broad-except
msg = {
"error": _(u"Could not find user by email address '{email}'.").format(email=email),
}

View File

@@ -1,21 +1,23 @@
"""
Views related to the video upload feature
"""
from __future__ import absolute_import
import csv
import json
import logging
from contextlib import closing
from datetime import datetime, timedelta
from pytz import UTC
from uuid import uuid4
import rfc6266_parser
import six
from boto import s3
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
from django.http import HttpResponse, HttpResponseNotFound
from django.urls import reverse
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_noop
from django.views.decorators.http import require_GET, require_http_methods, require_POST
@@ -25,26 +27,27 @@ from edxval.api import (
create_or_update_transcript_preferences,
create_video,
get_3rd_party_transcription_plans,
get_available_transcript_languages,
get_transcript_credentials_state_for_org,
get_transcript_preferences,
get_videos_for_course,
remove_transcript_preferences,
remove_video_for_course,
update_video_image,
update_video_status,
get_available_transcript_languages
update_video_status
)
from opaque_keys.edx.keys import CourseKey
from xmodule.video_module.transcripts_utils import Transcript
from pytz import UTC
from contentstore.models import VideoUploadConfig
from contentstore.utils import reverse_course_url
from contentstore.video_utils import validate_video_image
from edxmako.shortcuts import render_to_response
from openedx.core.djangoapps.video_config.models import VideoTranscriptEnabledFlag
from openedx.core.djangoapps.video_pipeline.config.waffle import waffle_flags, DEPRECATE_YOUTUBE
from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag, WaffleSwitchNamespace, WaffleFlagNamespace
from openedx.core.djangoapps.video_pipeline.config.waffle import DEPRECATE_YOUTUBE, waffle_flags
from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag, WaffleFlagNamespace, WaffleSwitchNamespace
from util.json_request import JsonResponse, expect_json
from xmodule.video_module.transcripts_utils import Transcript
from .course import get_course_and_check_access
@@ -156,6 +159,7 @@ class StatusDisplayStrings(object):
@staticmethod
def get(val_status):
"""Map a VAL status string to a localized display string"""
# pylint: disable=translation-of-non-string
return _(StatusDisplayStrings._STATUS_MAP.get(val_status, StatusDisplayStrings._UNKNOWN))
@@ -204,6 +208,7 @@ def videos_handler(request, course_key_string, edx_video_id=None):
@login_required
@require_POST
def video_images_handler(request, course_key_string, edx_video_id=None):
"""Function to handle image files"""
# respond with a 404 if image upload is not enabled.
if not WAFFLE_SWITCHES.is_enabled(VIDEO_IMAGE_UPLOAD_ENABLED):
@@ -246,7 +251,7 @@ def validate_transcript_preferences(provider, cielo24_fidelity, cielo24_turnarou
# validate transcription providers
transcription_plans = get_3rd_party_transcription_plans()
if provider in transcription_plans.keys():
if provider in list(transcription_plans.keys()):
# Further validations for providers
if provider == TranscriptProvider.CIELO24:
@@ -265,7 +270,7 @@ def validate_transcript_preferences(provider, cielo24_fidelity, cielo24_turnarou
error = u'Unsupported source language {}.'.format(video_source_language)
return error, preferences
if not len(preferred_languages) or not (set(preferred_languages) <= set(supported_languages.keys())):
if not preferred_languages or not set(preferred_languages) <= set(supported_languages.keys()):
error = u'Invalid languages {}.'.format(preferred_languages)
return error, preferences
@@ -287,12 +292,12 @@ def validate_transcript_preferences(provider, cielo24_fidelity, cielo24_turnarou
# Validate transcription languages
valid_translations_map = transcription_plans[provider]['translations']
if video_source_language not in valid_translations_map.keys():
if video_source_language not in list(valid_translations_map.keys()):
error = u'Unsupported source language {}.'.format(video_source_language)
return error, preferences
valid_target_languages = valid_translations_map[video_source_language]
if not len(preferred_languages) or not (set(preferred_languages) <= set(valid_target_languages)):
if not preferred_languages or not set(preferred_languages) <= set(valid_target_languages):
error = u'Invalid languages {}.'.format(preferred_languages)
return error, preferences
@@ -448,10 +453,10 @@ def _get_and_validate_course(course_key_string, user):
course = get_course_and_check_access(course_key, user)
if (
settings.FEATURES["ENABLE_VIDEO_UPLOAD_PIPELINE"] and
getattr(settings, "VIDEO_UPLOAD_PIPELINE", None) and
course and
course.video_pipeline_configured
settings.FEATURES["ENABLE_VIDEO_UPLOAD_PIPELINE"] and
getattr(settings, "VIDEO_UPLOAD_PIPELINE", None) and
course and
course.video_pipeline_configured
):
return course
else:
@@ -496,7 +501,7 @@ def _get_videos(course, pagination_conf=None):
Retrieves the list of videos from VAL corresponding to this course.
"""
videos, pagination_context = get_videos_for_course(
unicode(course.id),
six.text_type(course.id),
VideoSortField.created,
SortDirection.desc,
pagination_conf
@@ -538,7 +543,7 @@ def _get_index_videos(course, pagination_conf=None):
"""
Returns the information about each video upload required for the video list
"""
course_id = unicode(course.id)
course_id = six.text_type(course.id)
attrs = [
'edx_video_id', 'client_video_id', 'created', 'duration',
'status', 'courses', 'transcripts', 'transcription_status',
@@ -551,16 +556,15 @@ def _get_index_videos(course, pagination_conf=None):
values = {}
for attr in attrs:
if attr == 'courses':
course = filter(lambda c: course_id in c, video['courses'])
(__, values['course_video_image_url']), = course[0].items()
course = [c for c in video['courses'] if course_id in c]
(__, values['course_video_image_url']), = list(course[0].items())
else:
values[attr] = video[attr]
return values
videos, pagination_context = _get_videos(course, pagination_conf)
return [
_get_values(video) for video in videos
], pagination_context
return [_get_values(video) for video in videos], pagination_context
def get_all_transcript_languages():
@@ -580,7 +584,7 @@ def get_all_transcript_languages():
all_languages_dict = dict(settings.ALL_LANGUAGES, **third_party_transcription_languages)
# Return combined system settings and 3rd party transcript languages.
all_languages = []
for key, value in sorted(all_languages_dict.iteritems(), key=lambda k_v: k_v[1]):
for key, value in sorted(six.iteritems(all_languages_dict), key=lambda k_v: k_v[1]):
all_languages.append({
'language_code': key,
'language_text': value
@@ -596,13 +600,13 @@ def videos_index_html(course, pagination_conf=None):
previous_uploads, pagination_context = _get_index_videos(course, pagination_conf)
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)),
'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': VIDEO_SUPPORTED_FILE_FORMATS.keys(),
'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),
@@ -619,7 +623,7 @@ def videos_index_html(course, pagination_conf=None):
'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)),
'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
@@ -629,15 +633,15 @@ def videos_index_html(course, pagination_conf=None):
context['video_transcript_settings'].update({
'transcript_preferences_handler_url': reverse_course_url(
'transcript_preferences_handler',
unicode(course.id)
six.text_type(course.id)
),
'transcript_credentials_handler_url': reverse_course_url(
'transcript_credentials_handler',
unicode(course.id)
six.text_type(course.id)
),
'transcription_plans': get_3rd_party_transcription_plans(),
})
context['active_transcript_preferences'] = get_transcript_preferences(unicode(course.id))
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)
@@ -687,13 +691,13 @@ def videos_post(course, request):
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']
'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']
file['content_type'] not in list(VIDEO_SUPPORTED_FILE_FORMATS.values())
for file in data['files']
):
error = "Request 'files' entry contain unsupported content_type"
@@ -713,12 +717,12 @@ def videos_post(course, request):
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())
edx_video_id = six.text_type(uuid4())
key = storage_service_key(bucket, file_name=edx_video_id)
metadata_list = [
('client_video_id', file_name),
('course_key', unicode(course.id)),
('course_key', six.text_type(course.id)),
]
deprecate_youtube = waffle_flags()[DEPRECATE_YOUTUBE]
@@ -731,7 +735,7 @@ def videos_post(course, request):
is_video_transcript_enabled = VideoTranscriptEnabledFlag.feature_enabled(course.id)
if is_video_transcript_enabled:
transcript_preferences = get_transcript_preferences(unicode(course.id))
transcript_preferences = get_transcript_preferences(six.text_type(course.id))
if transcript_preferences is not None:
metadata_list.append(('transcript_preferences', json.dumps(transcript_preferences)))
@@ -750,7 +754,7 @@ def videos_post(course, request):
'client_video_id': file_name,
'duration': 0,
'encoded_videos': [],
'courses': [unicode(course.id)]
'courses': [six.text_type(course.id)]
})
resp_files.append({'file_name': file_name, 'upload_url': upload_url, 'edx_video_id': edx_video_id})