Merge remote-tracking branch 'origin/release' into dj18-release-merge

Conflicts:
	common/djangoapps/util/testing.py
	lms/djangoapps/instructor/views/api.py
	lms/djangoapps/teams/tests/test_views.py
	openedx/core/djangoapps/programs/models.py
	openedx/core/djangoapps/user_api/accounts/tests/test_views.py
	requirements/edx/github.txt
This commit is contained in:
muhammad-ammar
2015-11-18 17:53:44 +05:00
556 changed files with 5078 additions and 38377 deletions

View File

@@ -1,2 +0,0 @@
""" module init will register signal handlers """
import contentstore.signals

View File

@@ -15,7 +15,7 @@ config.readfp(config_file)
def doc_url(request=None): # pylint: disable=unused-argument
"""
This function is added in the list of TEMPLATE_CONTEXT_PROCESSORS, which is a django setting for
This function is added in the list of TEMPLATES 'context_processors' OPTION, which is a django setting for
a tuple of callables that take a request object as their argument and return a dictionary of items
to be merged into the RequestContext.

View File

@@ -7,7 +7,7 @@ import re
from six import add_metaclass
from django.conf import settings
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext as _
from django.core.urlresolvers import resolve
from contentstore.utils import course_image_url
@@ -350,7 +350,7 @@ class CoursewareSearchIndexer(SearchIndexerBase):
'category': 'courseware_index'
}
UNNAMED_MODULE_NAME = _("(Unnamed)")
UNNAMED_MODULE_NAME = ugettext_lazy("(Unnamed)")
@classmethod
def normalize_structure_key(cls, structure_key):
@@ -417,7 +417,7 @@ class CoursewareSearchIndexer(SearchIndexerBase):
while parent is not None:
path_component_name = parent.display_name
if not path_component_name:
path_component_name = cls.UNNAMED_MODULE_NAME
path_component_name = unicode(cls.UNNAMED_MODULE_NAME)
location_path.append(path_component_name)
parent = parent.get_parent()
location_path.reverse()

View File

@@ -14,18 +14,19 @@ class Command(BaseCommand):
|commit|: optional argument. If not provided, will not run task.
'''
def handle(self, *args, **options):
if len(args) not in {1, 2}:
raise CommandError("delete_orphans requires one or more arguments: <course_id> |commit|")
def add_arguments(self, parser):
parser.add_argument('course_id')
parser.add_argument('--commit', action='store')
def handle(self, *args, **options):
try:
course_key = CourseKey.from_string(args[0])
course_key = CourseKey.from_string(options['course_id'])
except InvalidKeyError:
raise CommandError("Invalid course key.")
commit = False
if len(args) == 2:
commit = args[1] == 'commit'
if options['commit']:
commit = options['commit'] == 'commit'
if commit:
print 'Deleting orphans from the course:'

View File

@@ -18,23 +18,24 @@ class Command(BaseCommand):
"""
help = 'Export the specified data directory into the default ModuleStore'
def handle(self, *args, **options):
"Execute the command"
if len(args) != 2:
raise CommandError("export requires two arguments: <course id> <output path>")
def add_arguments(self, parser):
parser.add_argument('course_id')
parser.add_argument('output_path')
def handle(self, *args, **options):
"""Execute the command"""
try:
course_key = CourseKey.from_string(args[0])
course_key = CourseKey.from_string(options['course_id'])
except InvalidKeyError:
try:
course_key = SlashSeparatedCourseKey.from_deprecated_string(args[0])
course_key = SlashSeparatedCourseKey.from_deprecated_string(options['course_id'])
except InvalidKeyError:
raise CommandError("Invalid course_key: '%s'. " % args[0])
raise CommandError("Invalid course_key: '%s'." % options['course_id'])
if not modulestore().get_course(course_key):
raise CommandError("Course with %s key not found." % args[0])
raise CommandError("Course with %s key not found." % options['course_id'])
output_path = args[1]
output_path = options['output_path']
print "Exporting course id = {0} to {1}".format(course_key, output_path)

View File

@@ -13,12 +13,14 @@ class Command(BaseCommand):
"""Fix a course's item not found errors"""
help = "Fix a course's ItemNotFound errors"
def handle(self, *args, **options):
"Execute the command"
if len(args) != 1:
raise CommandError("requires 1 argument: <course_id>")
def add_arguments(self, parser):
parser.add_argument('course_id')
course_key = CourseKey.from_string(args[0])
def handle(self, *args, **options):
"""Execute the command"""
course_id = options.get('course_id', None)
course_key = CourseKey.from_string(course_id)
# for now only support on split mongo
# pylint: disable=protected-access
owning_store = modulestore()._get_modulestore_for_courselike(course_key)

View File

@@ -1,8 +1,9 @@
"""
Script for importing courseware from XML format
"""
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError, make_option
from django.core.management.base import BaseCommand, CommandError
from django_comment_common.utils import (seed_permissions_roles,
are_permissions_roles_seeded)
from xmodule.modulestore.xml_importer import import_course_from_xml

View File

@@ -1,7 +1,7 @@
"""Tests running the delete_orphan command"""
import ddt
from django.core.management import call_command
from django.core.management import call_command, CommandError
from contentstore.tests.test_orphan import TestOrphanBase
from xmodule.modulestore.tests.factories import CourseFactory
@@ -14,6 +14,13 @@ class TestDeleteOrphan(TestOrphanBase):
Tests for running the delete_orphan management command.
Inherits from TestOrphan in order to use its setUp method.
"""
def test_no_args(self):
"""
Test delete_orphans command with no arguments
"""
with self.assertRaisesRegexp(CommandError, 'Error: too few arguments'):
call_command('delete_orphans')
@ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo)
def test_delete_orphans_no_commit(self, default_store):
"""
@@ -35,7 +42,7 @@ class TestDeleteOrphan(TestOrphanBase):
"""
course = self.create_course_with_orphans(default_store)
call_command('delete_orphans', unicode(course.id), 'commit')
call_command('delete_orphans', unicode(course.id), commit='commit')
# make sure this module wasn't deleted
self.assertTrue(self.store.has_item(course.id.make_usage_key('html', 'multi_parent_html')))
@@ -59,7 +66,7 @@ class TestDeleteOrphan(TestOrphanBase):
# call delete orphans, specifying the published branch
# of the course
call_command('delete_orphans', unicode(published_branch), 'commit')
call_command('delete_orphans', unicode(published_branch), commit='commit')
# now all orphans should be deleted
self.assertOrphanCount(course.id, 0)

View File

@@ -24,11 +24,9 @@ class TestArgParsingCourseExport(unittest.TestCase):
"""
Test export command with no arguments
"""
errstring = "export requires two arguments: <course id> <output path>"
with self.assertRaises(SystemExit) as ex:
with self.assertRaisesRegexp(CommandError, errstring):
call_command('export')
self.assertEqual(ex.exception.code, 1)
errstring = "Error: too few arguments"
with self.assertRaisesRegexp(CommandError, errstring):
call_command('export')
@ddt.ddt
@@ -59,11 +57,9 @@ class TestCourseExport(ModuleStoreTestCase):
"Could not find course in {}".format(store)
)
# Test `export` management command with invalid course_id
errstring = "Invalid course_key 'InvalidCourseID'."
with self.assertRaises(SystemExit) as ex:
with self.assertRaisesRegexp(CommandError, errstring):
call_command('export', "InvalidCourseID", self.temp_dir_1)
self.assertEqual(ex.exception.code, 1)
errstring = "Invalid course_key: 'InvalidCourseID'."
with self.assertRaisesRegexp(CommandError, errstring):
call_command('export', "InvalidCourseID", self.temp_dir_1)
# Test `export` management command with correct course_id
for output_dir in [self.temp_dir_1, self.temp_dir_2]:
@@ -74,7 +70,5 @@ class TestCourseExport(ModuleStoreTestCase):
Test export command with a valid course key that doesn't exist
"""
errstring = "Course with x/y/z key not found."
with self.assertRaises(SystemExit) as ex:
with self.assertRaisesRegexp(CommandError, errstring):
call_command('export', "x/y/z", self.temp_dir_1)
self.assertEqual(ex.exception.code, 1)
with self.assertRaisesRegexp(CommandError, errstring):
call_command('export', "x/y/z", self.temp_dir_1)

View File

@@ -2,7 +2,7 @@
Tests for the fix_not_found management command
"""
from django.core.management import call_command
from django.core.management import CommandError, call_command
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
@@ -12,12 +12,19 @@ class TestFixNotFound(ModuleStoreTestCase):
"""
Tests for the fix_not_found management command
"""
def test_no_args(self):
"""
Test fix_not_found command with no arguments
"""
with self.assertRaisesRegexp(CommandError, "Error: too few arguments"):
call_command('fix_not_found')
def test_fix_not_found_non_split(self):
"""
The management command doesn't work on non split courses
"""
course = CourseFactory.create(default_store=ModuleStoreEnum.Type.mongo)
with self.assertRaises(SystemExit):
with self.assertRaisesRegexp(CommandError, "The owning modulestore does not support this command."):
call_command("fix_not_found", unicode(course.id))
def test_fix_not_found(self):

View File

@@ -56,57 +56,33 @@ class TestGitExport(CourseTestCase):
Test that the command interface works. Ignore stderr for clean
test output.
"""
with self.assertRaises(SystemExit) as ex:
with self.assertRaisesRegexp(CommandError, 'This script requires.*'):
call_command('git_export', 'blah', 'blah', 'blah',
stderr=StringIO.StringIO())
self.assertEqual(ex.exception.code, 1)
with self.assertRaisesRegexp(CommandError, 'This script requires.*'):
call_command('git_export', 'blah', 'blah', 'blah', stderr=StringIO.StringIO())
with self.assertRaises(SystemExit) as ex:
with self.assertRaisesRegexp(CommandError, 'This script requires.*'):
call_command('git_export', stderr=StringIO.StringIO())
self.assertEqual(ex.exception.code, 1)
with self.assertRaisesRegexp(CommandError, 'This script requires.*'):
call_command('git_export', stderr=StringIO.StringIO())
# Send bad url to get course not exported
with self.assertRaises(SystemExit) as ex:
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.URL_BAD)):
call_command('git_export', 'foo/bar/baz', 'silly',
stderr=StringIO.StringIO())
self.assertEqual(ex.exception.code, 1)
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.URL_BAD)):
call_command('git_export', 'foo/bar/baz', 'silly', stderr=StringIO.StringIO())
# Send bad course_id to get course not exported
with self.assertRaises(SystemExit) as ex:
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.BAD_COURSE)):
call_command('git_export', 'foo/bar:baz', 'silly',
stderr=StringIO.StringIO())
self.assertEqual(ex.exception.code, 1)
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.BAD_COURSE)):
call_command('git_export', 'foo/bar:baz', 'silly', stderr=StringIO.StringIO())
def test_error_output(self):
"""
Verify that error output is actually resolved as the correct string
"""
output = StringIO.StringIO()
with self.assertRaises(SystemExit):
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.BAD_COURSE)):
call_command(
'git_export', 'foo/bar:baz', 'silly',
stdout=output, stderr=output
)
self.assertIn('Bad course location provided', output.getvalue())
output.close()
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.BAD_COURSE)):
call_command(
'git_export', 'foo/bar:baz', 'silly'
)
output = StringIO.StringIO()
with self.assertRaises(SystemExit):
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.URL_BAD)):
call_command(
'git_export', 'foo/bar/baz', 'silly',
stdout=output, stderr=output
)
self.assertIn(
'Non writable git url provided. Expecting something like:'
' git@github.com:mitocw/edx4edx_lite.git',
output.getvalue()
)
output.close()
with self.assertRaisesRegexp(CommandError, unicode(GitExportError.URL_BAD)):
call_command(
'git_export', 'foo/bar/baz', 'silly'
)
def test_bad_git_url(self):
"""

View File

@@ -6,7 +6,6 @@ import mock
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from common.test.utils import nostderr
from xmodule.modulestore.tests.factories import CourseFactory, LibraryFactory
from contentstore.management.commands.reindex_course import Command as ReindexCommand
@@ -48,36 +47,30 @@ class TestReindexCourse(ModuleStoreTestCase):
def test_given_no_arguments_raises_command_error(self):
""" Test that raises CommandError for incorrect arguments """
with self.assertRaises(SystemExit), nostderr():
with self.assertRaisesRegexp(CommandError, ".* requires one or more arguments .*"):
call_command('reindex_course')
with self.assertRaisesRegexp(CommandError, ".* requires one or more arguments.*"):
call_command('reindex_course')
@ddt.data('qwerty', 'invalid_key', 'xblock-v1:qwe+rty')
@ddt.data('qwerty', 'invalid_key', 'xblockv1:qwerty')
def test_given_invalid_course_key_raises_not_found(self, invalid_key):
""" Test that raises InvalidKeyError for invalid keys """
errstring = "Invalid course_key: '%s'." % invalid_key
with self.assertRaises(SystemExit) as ex:
with self.assertRaisesRegexp(CommandError, errstring):
call_command('reindex_course', invalid_key)
self.assertEqual(ex.exception.code, 1)
err_string = "Invalid course_key: '{0}'".format(invalid_key)
with self.assertRaisesRegexp(CommandError, err_string):
call_command('reindex_course', invalid_key)
def test_given_library_key_raises_command_error(self):
""" Test that raises CommandError if library key is passed """
with self.assertRaises(SystemExit), nostderr():
with self.assertRaisesRegexp(SearchIndexingError, ".* is not a course key"):
call_command('reindex_course', unicode(self._get_lib_key(self.first_lib)))
with self.assertRaisesRegexp(CommandError, ".* is not a course key"):
call_command('reindex_course', unicode(self._get_lib_key(self.first_lib)))
with self.assertRaises(SystemExit), nostderr():
with self.assertRaisesRegexp(SearchIndexingError, ".* is not a course key"):
call_command('reindex_course', unicode(self._get_lib_key(self.second_lib)))
with self.assertRaisesRegexp(CommandError, ".* is not a course key"):
call_command('reindex_course', unicode(self._get_lib_key(self.second_lib)))
with self.assertRaises(SystemExit), nostderr():
with self.assertRaisesRegexp(SearchIndexingError, ".* is not a course key"):
call_command(
'reindex_course',
unicode(self.second_course.id),
unicode(self._get_lib_key(self.first_lib))
)
with self.assertRaisesRegexp(CommandError, ".* is not a course key"):
call_command(
'reindex_course',
unicode(self.second_course.id),
unicode(self._get_lib_key(self.first_lib))
)
def test_given_id_list_indexes_courses(self):
""" Test that reindexes courses when given single course key or a list of course keys """

View File

@@ -6,7 +6,6 @@ import mock
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from common.test.utils import nostderr
from xmodule.modulestore.tests.factories import CourseFactory, LibraryFactory
from opaque_keys import InvalidKeyError
@@ -50,9 +49,8 @@ class TestReindexLibrary(ModuleStoreTestCase):
def test_given_no_arguments_raises_command_error(self):
""" Test that raises CommandError for incorrect arguments """
with self.assertRaises(SystemExit), nostderr():
with self.assertRaisesRegexp(CommandError, ".* requires one or more arguments .*"):
call_command('reindex_library')
with self.assertRaisesRegexp(CommandError, ".* requires one or more arguments.*"):
call_command('reindex_library')
@ddt.data('qwerty', 'invalid_key', 'xblock-v1:qwe+rty')
def test_given_invalid_lib_key_raises_not_found(self, invalid_key):
@@ -62,21 +60,18 @@ class TestReindexLibrary(ModuleStoreTestCase):
def test_given_course_key_raises_command_error(self):
""" Test that raises CommandError if course key is passed """
with self.assertRaises(SystemExit), nostderr():
with self.assertRaisesRegexp(CommandError, ".* is not a library key"):
call_command('reindex_library', unicode(self.first_course.id))
with self.assertRaisesRegexp(CommandError, ".* is not a library key"):
call_command('reindex_library', unicode(self.first_course.id))
with self.assertRaises(SystemExit), nostderr():
with self.assertRaisesRegexp(CommandError, ".* is not a library key"):
call_command('reindex_library', unicode(self.second_course.id))
with self.assertRaisesRegexp(CommandError, ".* is not a library key"):
call_command('reindex_library', unicode(self.second_course.id))
with self.assertRaises(SystemExit), nostderr():
with self.assertRaisesRegexp(CommandError, ".* is not a library key"):
call_command(
'reindex_library',
unicode(self.second_course.id),
unicode(self._get_lib_key(self.first_lib))
)
with self.assertRaisesRegexp(CommandError, ".* is not a library key"):
call_command(
'reindex_library',
unicode(self.second_course.id),
unicode(self._get_lib_key(self.first_lib))
)
def test_given_id_list_indexes_libraries(self):
""" Test that reindexes libraries when given single library key or a list of library keys """

View File

@@ -1,80 +1,43 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
from django.conf import settings
class Migration(SchemaMigration):
class Migration(migrations.Migration):
def forwards(self, orm):
# Adding model 'VideoUploadConfig'
db.create_table('contentstore_videouploadconfig', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('change_date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
('changed_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, on_delete=models.PROTECT)),
('enabled', self.gf('django.db.models.fields.BooleanField')(default=False)),
('profile_whitelist', self.gf('django.db.models.fields.TextField')(blank=True)),
('status_whitelist', self.gf('django.db.models.fields.TextField')(blank=True)),
))
db.send_create_signal('contentstore', ['VideoUploadConfig'])
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
if not db.dry_run:
orm.VideoUploadConfig.objects.create(
profile_whitelist="desktop_mp4,desktop_webm,mobile_low,youtube",
status_whitelist="Uploading,In Progress,Complete,Failed,Invalid Token,Unknown"
)
def backwards(self, orm):
# Deleting model 'VideoUploadConfig'
db.delete_table('contentstore_videouploadconfig')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contentstore.videouploadconfig': {
'Meta': {'object_name': 'VideoUploadConfig'},
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'profile_whitelist': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'status_whitelist': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['contentstore']
operations = [
migrations.CreateModel(
name='PushNotificationConfig',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')),
('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')),
],
options={
'ordering': ('-change_date',),
'abstract': False,
},
),
migrations.CreateModel(
name='VideoUploadConfig',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')),
('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
('profile_whitelist', models.TextField(help_text=b'A comma-separated list of names of profiles to include in video encoding downloads.', blank=True)),
('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')),
],
options={
'ordering': ('-change_date',),
'abstract': False,
},
),
]

View File

@@ -1,69 +0,0 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Deleting field 'VideoUploadConfig.status_whitelist'
db.delete_column('contentstore_videouploadconfig', 'status_whitelist')
def backwards(self, orm):
# Adding field 'VideoUploadConfig.status_whitelist'
db.add_column('contentstore_videouploadconfig', 'status_whitelist',
self.gf('django.db.models.fields.TextField')(default='', blank=True),
keep_default=False)
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contentstore.videouploadconfig': {
'Meta': {'object_name': 'VideoUploadConfig'},
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'profile_whitelist': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['contentstore']

View File

@@ -1,80 +0,0 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'PushNotificationConfig'
db.create_table('contentstore_pushnotificationconfig', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('change_date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
('changed_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, on_delete=models.PROTECT)),
('enabled', self.gf('django.db.models.fields.BooleanField')(default=False)),
))
db.send_create_signal('contentstore', ['PushNotificationConfig'])
def backwards(self, orm):
# Deleting model 'PushNotificationConfig'
db.delete_table('contentstore_pushnotificationconfig')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contentstore.pushnotificationconfig': {
'Meta': {'object_name': 'PushNotificationConfig'},
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'contentstore.videouploadconfig': {
'Meta': {'object_name': 'VideoUploadConfig'},
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'profile_whitelist': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['contentstore']

View File

@@ -0,0 +1,2 @@
""" will register signal handlers, moved out of __init__.py to ensure correct loading order post Django 1.7 """
from . import signals # pylint: disable=unused-import

View File

@@ -187,7 +187,7 @@ def _get_entrance_exam(request, course_key): # pylint: disable=W0613
exam_descriptor = modulestore().get_item(exam_key)
return HttpResponse(
escape_json_dumps({'locator': unicode(exam_descriptor.location)}),
status=200, mimetype='application/json')
status=200, content_type='application/json')
except ItemNotFoundError:
return HttpResponse(status=404)

View File

@@ -301,7 +301,7 @@ def xblock_view_handler(request, usage_key_string, view_name):
hashed_resources = OrderedDict()
for resource in fragment.resources:
hashed_resources[hash_resource(resource)] = resource
hashed_resources[hash_resource(resource)] = resource._asdict()
return JsonResponse({
'html': fragment.content,

View File

@@ -38,7 +38,7 @@ from .session_kv_store import SessionKeyValueStore
from .helpers import render_from_lms
from contentstore.views.access import get_user_role
from cms.djangoapps.xblock_config.models import StudioConfig
from xblock_config.models import StudioConfig
__all__ = ['preview_handler']

View File

@@ -610,12 +610,12 @@ class TestCourseReIndex(CourseTestCase):
response = non_staff_client.get(index_url, {}, HTTP_ACCEPT='application/json')
self.assertEqual(response.status_code, 403)
def test_content_type_none(self):
def test_empty_content_type(self):
"""
Test json content type is set if none is selected
Test json content type is set if '' is selected
"""
index_url = reverse_course_url('course_search_index_handler', self.course.id)
response = self.client.get(index_url, {}, CONTENT_TYPE=None)
response = self.client.get(index_url, {}, CONTENT_TYPE='')
# A course with the default release date should display as "Unscheduled"
self.assertIn(self.SUCCESSFUL_RESPONSE, response.content)

View File

@@ -17,7 +17,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from contentstore.views.preview import get_preview_fragment, _preview_module_system
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.tests.test_asides import AsideTestType
from cms.djangoapps.xblock_config.models import StudioConfig
from xblock_config.models import StudioConfig
from xmodule.modulestore.django import modulestore