diff --git a/openedx/core/djangoapps/content/course_overviews/admin.py b/openedx/core/djangoapps/content/course_overviews/admin.py index 7cf362b898..45d5ad5939 100644 --- a/openedx/core/djangoapps/content/course_overviews/admin.py +++ b/openedx/core/djangoapps/content/course_overviews/admin.py @@ -3,9 +3,11 @@ Django admin page for CourseOverviews, the basic metadata about a course that is used in user dashboard queries and other places where you need info like name, and start dates, but don't actually need to crawl into course content. """ -from django.contrib import admin +from __future__ import absolute_import from config_models.admin import ConfigurationModelAdmin +from django.contrib import admin + from .models import CourseOverview, CourseOverviewImageConfig, CourseOverviewImageSet diff --git a/openedx/core/djangoapps/content/course_overviews/apps.py b/openedx/core/djangoapps/content/course_overviews/apps.py index 8640e17ddc..c95bf3a9d2 100644 --- a/openedx/core/djangoapps/content/course_overviews/apps.py +++ b/openedx/core/djangoapps/content/course_overviews/apps.py @@ -1,6 +1,8 @@ """ Configuration for course_overviews Django app """ +from __future__ import absolute_import + from django.apps import AppConfig diff --git a/openedx/core/djangoapps/content/course_overviews/management/commands/generate_course_overview.py b/openedx/core/djangoapps/content/course_overviews/management/commands/generate_course_overview.py index fee26c9019..52d49ce65f 100644 --- a/openedx/core/djangoapps/content/course_overviews/management/commands/generate_course_overview.py +++ b/openedx/core/djangoapps/content/course_overviews/management/commands/generate_course_overview.py @@ -2,10 +2,12 @@ Command to load course overviews. """ +from __future__ import absolute_import + import logging +import six from django.core.management.base import BaseCommand, CommandError - from opaque_keys import InvalidKeyError from openedx.core.djangoapps.content.course_overviews.tasks import ( @@ -15,7 +17,6 @@ from openedx.core.djangoapps.content.course_overviews.tasks import ( enqueue_async_course_overview_update_tasks ) - log = logging.getLogger(__name__) @@ -73,4 +74,4 @@ class Command(BaseCommand): **kwargs ) except InvalidKeyError as exc: - raise CommandError(u'Invalid Course Key: ' + unicode(exc)) + raise CommandError(u'Invalid Course Key: ' + six.text_type(exc)) diff --git a/openedx/core/djangoapps/content/course_overviews/management/commands/simulate_publish.py b/openedx/core/djangoapps/content/course_overviews/management/commands/simulate_publish.py index 048ec400eb..3d65b295c6 100644 --- a/openedx/core/djangoapps/content/course_overviews/management/commands/simulate_publish.py +++ b/openedx/core/djangoapps/content/course_overviews/management/commands/simulate_publish.py @@ -11,21 +11,22 @@ This management command will emit the SignalHandler.course_published signal for some subset of courses and signal listeners, and then rely on existing listener behavior to trigger the necessary data updates. """ -from __future__ import print_function +from __future__ import absolute_import, print_function + import copy import logging import os +import sys import textwrap import time -import sys +import six from django.core.management.base import BaseCommand from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey from lms.djangoapps.ccx.tasks import course_published_handler as ccx_receiver_fn -from xmodule.modulestore.django import modulestore, SignalHandler - +from xmodule.modulestore.django import SignalHandler, modulestore log = logging.getLogger('simulate_publish') @@ -253,7 +254,7 @@ class Command(BaseCommand): log.info("No courses specified, reading all courses from modulestore...") course_keys = sorted( (course.id for course in modulestore().get_course_summaries()), - key=unicode # Different types of CourseKeys can't be compared without this. + key=six.text_type # Different types of CourseKeys can't be compared without this. ) log.info(u"%d courses read from modulestore.", len(course_keys)) diff --git a/openedx/core/djangoapps/content/course_overviews/management/commands/tests/test_generate_course_overview.py b/openedx/core/djangoapps/content/course_overviews/management/commands/tests/test_generate_course_overview.py index 735f117535..4495cd4bb3 100644 --- a/openedx/core/djangoapps/content/course_overviews/management/commands/tests/test_generate_course_overview.py +++ b/openedx/core/djangoapps/content/course_overviews/management/commands/tests/test_generate_course_overview.py @@ -1,12 +1,14 @@ """ Tests that the generate_course_overview management command actually generates course overviews. """ +from __future__ import absolute_import + +import six from django.core.management.base import CommandError from mock import patch from openedx.core.djangoapps.content.course_overviews.management.commands import generate_course_overview from openedx.core.djangoapps.content.course_overviews.models import CourseOverview - from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory @@ -57,7 +59,7 @@ class TestGenerateCourseOverview(ModuleStoreTestCase): Test that a specified course is loaded into course overviews. """ self._assert_courses_not_in_overview(self.course_key_1, self.course_key_2) - self.command.handle(unicode(self.course_key_1), all_courses=False) + self.command.handle(six.text_type(self.course_key_1), all_courses=False) self._assert_courses_in_overview(self.course_key_1) self._assert_courses_not_in_overview(self.course_key_2) @@ -72,8 +74,8 @@ class TestGenerateCourseOverview(ModuleStoreTestCase): self.store.update_item(course, self.user.id) # force_update course_key_1, but not course_key_2 - self.command.handle(unicode(self.course_key_1), all_courses=False, force_update=True) - self.command.handle(unicode(self.course_key_2), all_courses=False, force_update=False) + self.command.handle(six.text_type(self.course_key_1), all_courses=False, force_update=True) + self.command.handle(six.text_type(self.course_key_2), all_courses=False, force_update=False) self.assertEquals(CourseOverview.get_from_id(self.course_key_1).display_name, updated_course_name) self.assertNotEquals(CourseOverview.get_from_id(self.course_key_2).display_name, updated_course_name) @@ -106,7 +108,7 @@ class TestGenerateCourseOverview(ModuleStoreTestCase): called_kwargs = mock_async_task.apply_async.call_args_list[0][1] self.assertEquals( - sorted([unicode(self.course_key_1), unicode(self.course_key_2)]), + sorted([six.text_type(self.course_key_1), six.text_type(self.course_key_2)]), sorted(called_kwargs.pop('args')) ) self.assertEquals({ diff --git a/openedx/core/djangoapps/content/course_overviews/management/commands/tests/test_simulate_publish.py b/openedx/core/djangoapps/content/course_overviews/management/commands/tests/test_simulate_publish.py index 459db8ef56..134000e5f0 100644 --- a/openedx/core/djangoapps/content/course_overviews/management/commands/tests/test_simulate_publish.py +++ b/openedx/core/djangoapps/content/course_overviews/management/commands/tests/test_simulate_publish.py @@ -1,12 +1,14 @@ """ Tests the simulate_publish management command. """ -from openedx.core.djangoapps.content.course_overviews.management.commands.simulate_publish import ( - Command, name_from_fn -) -from openedx.core.djangoapps.content.course_overviews.models import CourseOverview -import openedx.core.djangoapps.content.course_overviews.signals +from __future__ import absolute_import + +import six + import lms.djangoapps.ccx.tasks +import openedx.core.djangoapps.content.course_overviews.signals +from openedx.core.djangoapps.content.course_overviews.management.commands.simulate_publish import Command, name_from_fn +from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import SwitchedSignal from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase @@ -103,7 +105,7 @@ class TestSimulatePublish(SharedModuleStoreTestCase): """Test sending only to specific courses.""" self.command.handle( **self.options( - courses=[unicode(self.course_key_1), unicode(self.course_key_2)] + courses=[six.text_type(self.course_key_1), six.text_type(self.course_key_2)] ) ) self.assertIn(self.course_key_1, self.received_1) diff --git a/openedx/core/djangoapps/content/course_overviews/models.py b/openedx/core/djangoapps/content/course_overviews/models.py index 722f665588..16514274e4 100644 --- a/openedx/core/djangoapps/content/course_overviews/models.py +++ b/openedx/core/djangoapps/content/course_overviews/models.py @@ -1,29 +1,31 @@ """ Declaration of CourseOverview model """ +from __future__ import absolute_import + import json import logging -from urlparse import urlparse, urlunparse +import six +from ccx_keys.locator import CCXLocator +from config_models.models import ConfigurationModel from django.conf import settings from django.db import models, transaction -from django.db.models.fields import BooleanField, DateTimeField, DecimalField, TextField, FloatField, IntegerField +from django.db.models.fields import BooleanField, DateTimeField, DecimalField, FloatField, IntegerField, TextField from django.db.utils import IntegrityError from django.template import defaultfilters - -from ccx_keys.locator import CCXLocator from model_utils.models import TimeStampedModel from opaque_keys.edx.django.models import CourseKeyField, UsageKeyField -from six import text_type +from six import text_type # pylint: disable=ungrouped-imports +from six.moves.urllib.parse import urlparse, urlunparse # pylint: disable=import-error -from config_models.models import ConfigurationModel from lms.djangoapps.discussion import django_comment_client from openedx.core.djangoapps.catalog.models import CatalogIntegration from openedx.core.djangoapps.lang_pref.api import get_closest_released_language from openedx.core.djangoapps.models.course_details import CourseDetails from static_replace.models import AssetBaseUrlConfig -from xmodule import course_metadata_utils, block_metadata_utils -from xmodule.course_module import CourseDescriptor, DEFAULT_START_DATE +from xmodule import block_metadata_utils, course_metadata_utils +from xmodule.course_module import DEFAULT_START_DATE, CourseDescriptor from xmodule.error_module import ErrorDescriptor from xmodule.modulestore.django import modulestore @@ -149,10 +151,10 @@ class CourseOverview(TimeStampedModel): course_overview = cls.objects.filter(id=course.id) if course_overview.exists(): - log.info(u'Updating course overview for %s.', unicode(course.id)) + log.info(u'Updating course overview for %s.', six.text_type(course.id)) course_overview = course_overview.first() else: - log.info(u'Creating course overview for %s.', unicode(course.id)) + log.info(u'Creating course overview for %s.', six.text_type(course.id)) course_overview = cls() course_overview.version = cls.VERSION @@ -260,8 +262,8 @@ class CourseOverview(TimeStampedModel): elif course is not None: raise IOError( u"Error while loading course {} from the module store: {}", - unicode(course_id), - course.error_msg if isinstance(course, ErrorDescriptor) else unicode(course) + six.text_type(course_id), + course.error_msg if isinstance(course, ErrorDescriptor) else six.text_type(course) ) else: raise cls.DoesNotExist() @@ -554,7 +556,7 @@ class CourseOverview(TimeStampedModel): except Exception as ex: # pylint: disable=broad-except log.exception( u'An error occurred while generating course overview for %s: %s', - unicode(course_key), + six.text_type(course_key), text_type(ex), ) @@ -703,7 +705,7 @@ class CourseOverview(TimeStampedModel): def __unicode__(self): """Represent ourselves with the course key.""" - return unicode(self.id) + return six.text_type(self.id) class CourseOverviewTab(models.Model): diff --git a/openedx/core/djangoapps/content/course_overviews/signals.py b/openedx/core/djangoapps/content/course_overviews/signals.py index f80d92a777..d8110da05f 100644 --- a/openedx/core/djangoapps/content/course_overviews/signals.py +++ b/openedx/core/djangoapps/content/course_overviews/signals.py @@ -1,14 +1,17 @@ """ Signal handler for invalidating cached course overviews """ +from __future__ import absolute_import + import logging from django.dispatch import Signal from django.dispatch.dispatcher import receiver -from .models import CourseOverview from xmodule.modulestore.django import SignalHandler +from .models import CourseOverview + LOG = logging.getLogger(__name__) diff --git a/openedx/core/djangoapps/content/course_overviews/tasks.py b/openedx/core/djangoapps/content/course_overviews/tasks.py index d813670600..dc98073da0 100644 --- a/openedx/core/djangoapps/content/course_overviews/tasks.py +++ b/openedx/core/djangoapps/content/course_overviews/tasks.py @@ -1,14 +1,16 @@ +from __future__ import absolute_import + import logging +import six from celery import task from celery_utils.persist_on_failure import LoggedPersistOnFailureTask from django.conf import settings - from opaque_keys.edx.keys import CourseKey -from xmodule.modulestore.django import modulestore +from six.moves import range # pylint: disable=ungrouped-imports from openedx.core.djangoapps.content.course_overviews.models import CourseOverview - +from xmodule.modulestore.django import modulestore log = logging.getLogger(__name__) @@ -21,7 +23,7 @@ DEFAULT_FORCE_UPDATE = False def chunks(sequence, chunk_size): - return (sequence[index: index + chunk_size] for index in xrange(0, len(sequence), chunk_size)) + return (sequence[index: index + chunk_size] for index in range(0, len(sequence), chunk_size)) def _task_options(routing_key): @@ -46,7 +48,7 @@ def enqueue_async_course_overview_update_tasks( course_keys = [CourseKey.from_string(id) for id in course_ids] for course_key_group in chunks(course_keys, chunk_size): - course_key_strings = [unicode(key) for key in course_key_group] + course_key_strings = [six.text_type(key) for key in course_key_group] options = _task_options(routing_key) async_course_overview_update.apply_async( diff --git a/openedx/core/djangoapps/content/course_overviews/tests/factories.py b/openedx/core/djangoapps/content/course_overviews/tests/factories.py index 4b3a9bd370..e898ff2b02 100644 --- a/openedx/core/djangoapps/content/course_overviews/tests/factories.py +++ b/openedx/core/djangoapps/content/course_overviews/tests/factories.py @@ -1,10 +1,12 @@ +from __future__ import absolute_import + import json import factory from factory.django import DjangoModelFactory +from opaque_keys.edx.locator import CourseLocator from ..models import CourseOverview -from opaque_keys.edx.locator import CourseLocator class CourseOverviewFactory(DjangoModelFactory): diff --git a/openedx/core/djangoapps/content/course_overviews/tests/test_course_overviews.py b/openedx/core/djangoapps/content/course_overviews/tests/test_course_overviews.py index 20c738ceaa..722d1fe7e6 100644 --- a/openedx/core/djangoapps/content/course_overviews/tests/test_course_overviews.py +++ b/openedx/core/djangoapps/content/course_overviews/tests/test_course_overviews.py @@ -1,19 +1,23 @@ """ Tests for course_overviews app. """ -from cStringIO import StringIO +from __future__ import absolute_import + import datetime -import ddt import itertools import math +from cStringIO import StringIO + +import ddt import mock import pytz - +import six from django.conf import settings from django.db.utils import IntegrityError from django.test.utils import override_settings from django.utils import timezone from PIL import Image +from six.moves import range # pylint: disable=ungrouped-imports from lms.djangoapps.certificates.api import get_active_web_certificate from openedx.core.djangoapps.catalog.tests.mixins import CatalogIntegrationMixin @@ -23,13 +27,13 @@ from openedx.core.djangolib.testing.utils import CacheIsolationTestCase from openedx.core.lib.courses import course_image_url from static_replace.models import AssetBaseUrlConfig from xmodule.assetstore.assetmgr import AssetManager -from xmodule.contentstore.django import contentstore from xmodule.contentstore.content import StaticContent +from xmodule.contentstore.django import contentstore from xmodule.course_metadata_utils import DEFAULT_START_DATE from xmodule.course_module import ( - CATALOG_VISIBILITY_CATALOG_AND_ABOUT, CATALOG_VISIBILITY_ABOUT, - CATALOG_VISIBILITY_NONE, + CATALOG_VISIBILITY_CATALOG_AND_ABOUT, + CATALOG_VISIBILITY_NONE ) from xmodule.error_module import ErrorDescriptor from xmodule.modulestore import ModuleStoreEnum @@ -37,7 +41,7 @@ from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, check_mongo_calls_range -from ..models import CourseOverview, CourseOverviewImageSet, CourseOverviewImageConfig +from ..models import CourseOverview, CourseOverviewImageConfig, CourseOverviewImageSet from .factories import CourseOverviewFactory @@ -472,7 +476,7 @@ class CourseOverviewTestCase(CatalogIntegrationMixin, ModuleStoreTestCase, Cache org_courses = [] # list of lists of courses for index in range(3): org_courses.append([ - CourseFactory.create(org='test_org_' + unicode(index), emit_signals=True) + CourseFactory.create(org='test_org_' + six.text_type(index), emit_signals=True) for __ in range(3) ]) diff --git a/openedx/core/djangoapps/content/course_overviews/tests/test_signals.py b/openedx/core/djangoapps/content/course_overviews/tests/test_signals.py index e7993800bd..16011898f6 100644 --- a/openedx/core/djangoapps/content/course_overviews/tests/test_signals.py +++ b/openedx/core/djangoapps/content/course_overviews/tests/test_signals.py @@ -1,4 +1,7 @@ +from __future__ import absolute_import + import datetime + import ddt from mock import patch diff --git a/openedx/core/djangoapps/content/course_overviews/tests/test_tasks.py b/openedx/core/djangoapps/content/course_overviews/tests/test_tasks.py index 78d4a63002..615d437822 100644 --- a/openedx/core/djangoapps/content/course_overviews/tests/test_tasks.py +++ b/openedx/core/djangoapps/content/course_overviews/tests/test_tasks.py @@ -1,4 +1,7 @@ +from __future__ import absolute_import + import mock +import six from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase @@ -30,7 +33,7 @@ class BatchedAsyncCourseOverviewUpdateTests(ModuleStoreTestCase): @mock.patch('openedx.core.djangoapps.content.course_overviews.models.CourseOverview.update_select_courses') def test_enqueue_specific_courses_in_two_batches(self, mock_update_courses): enqueue_async_course_overview_update_tasks( - course_ids=[unicode(self.course_1.id), unicode(self.course_2.id)], + course_ids=[six.text_type(self.course_1.id), six.text_type(self.course_2.id)], force_update=True, chunk_size=1, all_courses=False