diff --git a/lms/djangoapps/courseware/migrations/0001_initial.py b/lms/djangoapps/courseware/migrations/0001_initial.py index b00a76c9e1..6bc122ddab 100644 --- a/lms/djangoapps/courseware/migrations/0001_initial.py +++ b/lms/djangoapps/courseware/migrations/0001_initial.py @@ -1,13 +1,11 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals +from __future__ import absolute_import, unicode_literals -from django.db import migrations, models -import model_utils.fields import django.utils.timezone +import model_utils.fields from django.conf import settings -from opaque_keys.edx.django.models import ( - BlockTypeKeyField, CourseKeyField, UsageKeyField -) +from django.db import migrations, models +from opaque_keys.edx.django.models import BlockTypeKeyField, CourseKeyField, UsageKeyField class Migration(migrations.Migration): diff --git a/lms/djangoapps/courseware/migrations/0005_orgdynamicupgradedeadlineconfiguration.py b/lms/djangoapps/courseware/migrations/0005_orgdynamicupgradedeadlineconfiguration.py index 2d0c7584f6..43dbdff62d 100644 --- a/lms/djangoapps/courseware/migrations/0005_orgdynamicupgradedeadlineconfiguration.py +++ b/lms/djangoapps/courseware/migrations/0005_orgdynamicupgradedeadlineconfiguration.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals +from __future__ import absolute_import, unicode_literals -from django.db import migrations, models import django.db.models.deletion from django.conf import settings +from django.db import migrations, models + import courseware.models diff --git a/lms/djangoapps/courseware/migrations/0007_remove_done_index.py b/lms/djangoapps/courseware/migrations/0007_remove_done_index.py index 9b6338dd39..2103d22d51 100644 --- a/lms/djangoapps/courseware/migrations/0007_remove_done_index.py +++ b/lms/djangoapps/courseware/migrations/0007_remove_done_index.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Generated by Django 1.11.13 on 2018-05-29 15:18 -from __future__ import unicode_literals +from __future__ import absolute_import, unicode_literals from django.db import migrations, models diff --git a/lms/djangoapps/courseware/views/index.py b/lms/djangoapps/courseware/views/index.py index d40cf593cc..53bf4d4516 100644 --- a/lms/djangoapps/courseware/views/index.py +++ b/lms/djangoapps/courseware/views/index.py @@ -4,15 +4,21 @@ View for Courseware Index # pylint: disable=attribute-defined-outside-init -import logging -import urllib +from __future__ import absolute_import +import logging + +import six +import six.moves.urllib as urllib # pylint: disable=import-error +import six.moves.urllib.error # pylint: disable=import-error +import six.moves.urllib.parse # pylint: disable=import-error +import six.moves.urllib.request # pylint: disable=import-error from django.conf import settings from django.contrib.auth.models import User from django.contrib.auth.views import redirect_to_login -from django.urls import reverse from django.http import Http404 from django.template.context_processors import csrf +from django.urls import reverse from django.utils.decorators import method_decorator from django.utils.functional import cached_property from django.utils.translation import ugettext as _ @@ -24,7 +30,6 @@ from opaque_keys.edx.keys import CourseKey from web_fragments.fragment import Fragment from edxmako.shortcuts import render_to_response, render_to_string - from lms.djangoapps.courseware.courses import allow_public_access from lms.djangoapps.courseware.exceptions import CourseAccessRedirect from lms.djangoapps.experiments.utils import get_experiment_user_metadata_context @@ -37,17 +42,19 @@ from openedx.core.djangoapps.util.user_messages import PageLevelMessages from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace from openedx.core.djangolib.markup import HTML, Text from openedx.features.course_experience import ( - COURSE_OUTLINE_PAGE_FLAG, default_course_url_name, COURSE_ENABLE_UNENROLLED_ACCESS_FLAG + COURSE_ENABLE_UNENROLLED_ACCESS_FLAG, + COURSE_OUTLINE_PAGE_FLAG, + default_course_url_name ) from openedx.features.course_experience.views.course_sock import CourseSockFragmentView from openedx.features.enterprise_support.api import data_sharing_consent_required from shoppingcart.models import CourseRegistrationCode from student.views import is_course_blocked from util.views import ensure_valid_course_key -from xmodule.modulestore.django import modulestore from xmodule.course_module import COURSE_VISIBILITY_PUBLIC +from xmodule.modulestore.django import modulestore from xmodule.x_module import PUBLIC_VIEW, STUDENT_VIEW -from .views import CourseTabView + from ..access import has_access from ..courses import check_course_access, get_course_with_access, get_current_child, get_studio_url from ..entrance_exams import ( @@ -56,12 +63,10 @@ from ..entrance_exams import ( user_can_skip_entrance_exam, user_has_passed_entrance_exam ) -from ..masquerade import ( - setup_masquerade, - check_content_start_date_for_masquerade_user -) +from ..masquerade import check_content_start_date_for_masquerade_user, setup_masquerade from ..model_data import FieldDataCache from ..module_render import get_module_for_descriptor, toc_for_course +from .views import CourseTabView log = logging.getLogger("edx.courseware.views.index") @@ -190,7 +195,7 @@ class CoursewareIndex(View): self.course.start, self.chapter.start, self.section.start) if not request.user.is_authenticated: - qs = urllib.urlencode({ + qs = six.moves.urllib.parse.urlencode({ 'course_id': self.course_key, 'enrollment_action': 'enroll', 'email_opt_in': False, @@ -231,7 +236,7 @@ class CoursewareIndex(View): reverse( 'courseware_section', kwargs={ - 'course_id': unicode(self.course_key), + 'course_id': six.text_type(self.course_key), 'chapter': self.chapter.url_name, 'section': self.section.url_name, }, @@ -269,7 +274,7 @@ class CoursewareIndex(View): log.warning( u'User %s cannot access the course %s because payment has not yet been received', self.real_user, - unicode(self.course_key), + six.text_type(self.course_key), ) raise CourseAccessRedirect(reverse('dashboard')) @@ -399,7 +404,7 @@ class CoursewareIndex(View): Also returns the table of contents for the courseware. """ course_url_name = default_course_url_name(self.course.id) - course_url = reverse(course_url_name, kwargs={'course_id': unicode(self.course.id)}) + course_url = reverse(course_url_name, kwargs={'course_id': six.text_type(self.course.id)}) courseware_context = { 'csrf': csrf(self.request)['csrf_token'], @@ -511,7 +516,7 @@ class CoursewareIndex(View): return "{url}?child={requested_child}".format( url=reverse( 'courseware_section', - args=[unicode(self.course_key), section_info['chapter_url_name'], section_info['url_name']], + args=[six.text_type(self.course_key), section_info['chapter_url_name'], section_info['url_name']], ), requested_child=requested_child, ) @@ -522,7 +527,7 @@ class CoursewareIndex(View): section_context = { 'activate_block_id': self.request.GET.get('activate_block_id'), 'requested_child': self.request.GET.get("child"), - 'progress_url': reverse('progress', kwargs={'course_id': unicode(self.course_key)}), + 'progress_url': reverse('progress', kwargs={'course_id': six.text_type(self.course_key)}), 'user_authenticated': self.request.user.is_authenticated, 'position': position, } @@ -544,10 +549,10 @@ def render_accordion(request, course, table_of_contents): context = dict( [ ('toc', table_of_contents), - ('course_id', unicode(course.id)), + ('course_id', six.text_type(course.id)), ('csrf', csrf(request)['csrf_token']), ('due_date_display_format', course.due_date_display_format), - ] + TEMPLATE_IMPORTS.items() + ] + list(TEMPLATE_IMPORTS.items()) ) return render_to_string('courseware/accordion.html', context) diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 5a0a649ffa..b215607283 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -1,13 +1,17 @@ """ Courseware views functions """ +from __future__ import absolute_import + import json import logging -import urllib from collections import OrderedDict, namedtuple from datetime import datetime import bleach +import six.moves.urllib.error # pylint: disable=import-error +import six.moves.urllib.parse # pylint: disable=import-error +import six.moves.urllib.request # pylint: disable=import-error from django.conf import settings from django.contrib.auth.decorators import login_required from django.contrib.auth.models import AnonymousUser, User @@ -21,20 +25,22 @@ from django.urls import reverse from django.utils.decorators import method_decorator from django.utils.http import urlquote_plus from django.utils.text import slugify -from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext +from django.utils.translation import ugettext_lazy as _ from django.views.decorators.cache import cache_control from django.views.decorators.clickjacking import xframe_options_exempt from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.http import require_GET, require_http_methods, require_POST from django.views.generic import View from edx_django_utils.monitoring import set_custom_metrics_for_course_key +from ipware.ip import get_ip from markupsafe import escape from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey, UsageKey from pytz import UTC from rest_framework import status from six import text_type +from web_fragments.fragment import Fragment import shoppingcart import survey.views @@ -61,7 +67,6 @@ from courseware.permissions import VIEW_COURSE_HOME from courseware.url_helpers import get_redirect_url from courseware.user_state_client import DjangoXBlockUserStateClient from edxmako.shortcuts import marketing_link, render_to_response, render_to_string -from ipware.ip import get_ip from lms.djangoapps.ccx.custom_exception import CCXLocatorValidationException from lms.djangoapps.certificates import api as certs_api from lms.djangoapps.certificates.models import CertificateStatuses @@ -91,9 +96,9 @@ from openedx.core.djangoapps.util.user_messages import PageLevelMessages from openedx.core.djangolib.markup import HTML, Text from openedx.features.course_duration_limits.access import generate_course_expired_fragment from openedx.features.course_experience import ( - UNIFIED_COURSE_TAB_FLAG, COURSE_ENABLE_UNENROLLED_ACCESS_FLAG, - course_home_url_name, + UNIFIED_COURSE_TAB_FLAG, + course_home_url_name ) from openedx.features.course_experience.course_tools import CourseToolsPluginManager from openedx.features.course_experience.views.course_dates import CourseDatesFragmentView @@ -108,7 +113,6 @@ from util.db import outer_atomic from util.milestones_helpers import get_prerequisite_courses_display from util.views import _record_feedback_in_zendesk, ensure_valid_course_key, ensure_valid_usage_key from xmodule.course_module import COURSE_VISIBILITY_PUBLIC, COURSE_VISIBILITY_PUBLIC_OUTLINE -from web_fragments.fragment import Fragment from xmodule.modulestore.django import modulestore from xmodule.modulestore.exceptions import ItemNotFoundError, NoPathToItem from xmodule.tabs import CourseTabList @@ -767,7 +771,7 @@ class EnrollStaffView(View): Either enrolls the user in course or redirects user to course about page depending upon the option (Enroll, Don't Enroll) chosen by the user. """ - _next = urllib.quote_plus(request.GET.get('next', 'info'), safe='/:?=') + _next = six.moves.urllib.parse.quote_plus(request.GET.get('next', 'info'), safe='/:?=') # pylint: disable=redundant-keyword-arg course_key = CourseKey.from_string(course_id) enroll = 'enroll' in request.POST if enroll: @@ -834,7 +838,7 @@ def course_about(request, course_id): shoppingcart.models.CourseRegCodeItem.contained_in_order(cart, course_key) reg_then_add_to_cart_link = "{reg_url}?course_id={course_id}&enrollment_action=add_to_cart".format( - reg_url=reverse('register_user'), course_id=urllib.quote(str(course_id)) + reg_url=reverse('register_user'), course_id=six.moves.urllib.parse.quote(str(course_id)) ) # If the ecommerce checkout flow is enabled and the mode of the course is @@ -1018,7 +1022,7 @@ def _progress(request, course_key, student_id): # student instead of request.user in the rest of the function. course_grade = CourseGradeFactory().read(student, course) - courseware_summary = course_grade.chapter_grades.values() + courseware_summary = list(course_grade.chapter_grades.values()) studio_url = get_studio_url(course, 'settings/grading') # checking certificate generation configuration