INCR-433 python3 compatibility
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
from django.contrib import admin
|
||||
"""
|
||||
Admin view for courseware.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
from config_models.admin import ConfigurationModelAdmin, KeyedConfigurationModelAdmin
|
||||
from django.contrib import admin
|
||||
|
||||
from courseware import models
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@ This is meant to simplify the process of sending user preferences (espec. time_z
|
||||
to the templates without having to append every view file.
|
||||
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import six
|
||||
|
||||
from openedx.core.djangoapps.user_api.errors import UserAPIInternalError, UserNotFound
|
||||
from openedx.core.djangoapps.user_api.preferences.api import get_user_preferences
|
||||
from openedx.core.lib.cache_utils import get_cache
|
||||
@@ -39,7 +43,7 @@ def user_timezone_locale_prefs(request):
|
||||
else:
|
||||
user_prefs = {
|
||||
key: user_preferences.get(pref_name, None)
|
||||
for key, pref_name in RETRIEVABLE_PREFERENCES.iteritems()
|
||||
for key, pref_name in six.iteritems(RETRIEVABLE_PREFERENCES)
|
||||
}
|
||||
|
||||
cached_value.update(user_prefs)
|
||||
|
||||
@@ -2,15 +2,18 @@
|
||||
Platform plugins to support a verified upgrade tool.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import datetime
|
||||
|
||||
import pytz
|
||||
from crum import get_current_request
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from course_modes.models import CourseMode
|
||||
from courseware.date_summary import verified_upgrade_deadline_link
|
||||
from openedx.features.course_experience.course_tools import CourseTool
|
||||
from student.models import CourseEnrollment
|
||||
from courseware.date_summary import verified_upgrade_deadline_link
|
||||
|
||||
|
||||
class VerifiedUpgradeTool(CourseTool):
|
||||
|
||||
@@ -2,45 +2,49 @@
|
||||
Functions for accessing and displaying courses within the
|
||||
courseware.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
from collections import defaultdict
|
||||
from datetime import datetime
|
||||
|
||||
import branding
|
||||
import pytz
|
||||
import six
|
||||
from crum import get_current_request
|
||||
from openedx.features.course_duration_limits.access import AuditExpiredError
|
||||
from django.conf import settings
|
||||
from django.db.models import Prefetch
|
||||
from django.http import Http404, QueryDict
|
||||
from django.urls import reverse
|
||||
from fs.errors import ResourceNotFound
|
||||
from opaque_keys.edx.keys import UsageKey
|
||||
from path import Path as path
|
||||
from six import text_type
|
||||
|
||||
import branding
|
||||
from course_modes.models import CourseMode
|
||||
from courseware.access import has_access
|
||||
from courseware.access_response import StartDateError, MilestoneAccessError
|
||||
from courseware.access_response import MilestoneAccessError, StartDateError
|
||||
from courseware.date_summary import (
|
||||
CertificateAvailableDate,
|
||||
CourseEndDate,
|
||||
CourseStartDate,
|
||||
TodaysDate,
|
||||
VerificationDeadlineDate,
|
||||
VerifiedUpgradeDeadlineDate,
|
||||
CertificateAvailableDate
|
||||
VerifiedUpgradeDeadlineDate
|
||||
)
|
||||
from courseware.masquerade import check_content_start_date_for_masquerade_user
|
||||
from courseware.model_data import FieldDataCache
|
||||
from courseware.module_render import get_module
|
||||
from course_modes.models import CourseMode
|
||||
from django.conf import settings
|
||||
from django.db.models import Prefetch
|
||||
from django.urls import reverse
|
||||
from django.http import Http404, QueryDict
|
||||
from edxmako.shortcuts import render_to_string
|
||||
from fs.errors import ResourceNotFound
|
||||
from lms.djangoapps.certificates import api as certs_api
|
||||
from lms.djangoapps.courseware.courseware_access_exception import CoursewareAccessException
|
||||
from lms.djangoapps.courseware.exceptions import CourseAccessRedirect
|
||||
from opaque_keys.edx.keys import UsageKey
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangoapps.enrollments.api import get_course_enrollment_details
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.lib.api.view_utils import LazySequence
|
||||
from openedx.features.course_duration_limits.access import AuditExpiredError
|
||||
from openedx.features.course_experience import COURSE_ENABLE_UNENROLLED_ACCESS_FLAG
|
||||
from path import Path as path
|
||||
from six import text_type
|
||||
from static_replace import replace_static_urls
|
||||
from student.models import CourseEnrollment
|
||||
from survey.utils import is_survey_required_and_unanswered
|
||||
@@ -81,7 +85,7 @@ def get_course_by_id(course_key, depth=0):
|
||||
if course:
|
||||
return course
|
||||
else:
|
||||
raise Http404(u"Course not found: {}.".format(unicode(course_key)))
|
||||
raise Http404(u"Course not found: {}.".format(six.text_type(course_key)))
|
||||
|
||||
|
||||
def get_course_with_access(user, action, course_key, depth=0, check_if_enrolled=False, check_survey_complete=True):
|
||||
@@ -175,12 +179,12 @@ def check_course_access(course, user, action, check_if_enrolled=False, check_sur
|
||||
if check_if_enrolled:
|
||||
# If the user is not enrolled, redirect them to the about page
|
||||
if not CourseEnrollment.is_enrolled(user, course.id):
|
||||
raise CourseAccessRedirect(reverse('about_course', args=[unicode(course.id)]))
|
||||
raise CourseAccessRedirect(reverse('about_course', args=[six.text_type(course.id)]))
|
||||
|
||||
# Redirect if the user must answer a survey before entering the course.
|
||||
if check_survey_complete and action == 'load':
|
||||
if is_survey_required_and_unanswered(user, course):
|
||||
raise CourseAccessRedirect(reverse('course_survey', args=[unicode(course.id)]))
|
||||
raise CourseAccessRedirect(reverse('course_survey', args=[six.text_type(course.id)]))
|
||||
|
||||
|
||||
def can_self_enroll_in_course(course_key):
|
||||
@@ -205,7 +209,7 @@ def course_open_for_self_enrollment(course_key):
|
||||
return False
|
||||
|
||||
# Check the enrollment start and end dates.
|
||||
course_details = get_course_enrollment_details(unicode(course_key))
|
||||
course_details = get_course_enrollment_details(six.text_type(course_key))
|
||||
now = datetime.now().replace(tzinfo=pytz.UTC)
|
||||
start = course_details['enrollment_start']
|
||||
end = course_details['enrollment_end']
|
||||
@@ -379,7 +383,7 @@ def get_course_info_section(request, user, course, section_key):
|
||||
html = render_to_string('courseware/error-message.html', None)
|
||||
log.exception(
|
||||
u"Error rendering course_id=%s, section_key=%s",
|
||||
unicode(course.id), section_key
|
||||
six.text_type(course.id), section_key
|
||||
)
|
||||
|
||||
return html
|
||||
@@ -524,7 +528,7 @@ def get_cms_course_link(course, page='course'):
|
||||
"""
|
||||
# This is fragile, but unfortunately the problem is that within the LMS we
|
||||
# can't use the reverse calls from the CMS
|
||||
return u"//{}/{}/{}".format(settings.CMS_BASE, page, unicode(course.id))
|
||||
return u"//{}/{}/{}".format(settings.CMS_BASE, page, six.text_type(course.id))
|
||||
|
||||
|
||||
def get_cms_block_link(block, page):
|
||||
@@ -571,7 +575,7 @@ def get_problems_in_section(section):
|
||||
for vertical in subsection.get_children():
|
||||
for component in vertical.get_children():
|
||||
if component.location.block_type == 'problem' and getattr(component, 'has_score', False):
|
||||
problem_descriptors[unicode(component.location)] = component
|
||||
problem_descriptors[six.text_type(component.location)] = component
|
||||
|
||||
return problem_descriptors
|
||||
|
||||
@@ -643,7 +647,7 @@ def get_course_chapter_ids(course_key):
|
||||
except Exception: # pylint: disable=broad-except
|
||||
log.exception('Failed to retrieve course from modulestore.')
|
||||
return []
|
||||
return [unicode(chapter_key) for chapter_key in chapter_keys if chapter_key.block_type == 'chapter']
|
||||
return [six.text_type(chapter_key) for chapter_key in chapter_keys if chapter_key.block_type == 'chapter']
|
||||
|
||||
|
||||
def allow_public_access(course, visibilities):
|
||||
|
||||
@@ -3,17 +3,19 @@ This module provides date summary blocks for the Course Info
|
||||
page. Each block gives information about a particular
|
||||
course-run-specific date which will be displayed to the user.
|
||||
"""
|
||||
import crum
|
||||
from __future__ import absolute_import
|
||||
|
||||
import datetime
|
||||
|
||||
import crum
|
||||
from babel.dates import format_timedelta
|
||||
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from django.utils.formats import date_format
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import get_language, to_locale, ugettext_lazy
|
||||
from django.utils.translation import get_language, to_locale
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy
|
||||
from lazy import lazy
|
||||
from pytz import utc
|
||||
|
||||
@@ -23,7 +25,7 @@ from lms.djangoapps.verify_student.models import VerificationDeadline
|
||||
from lms.djangoapps.verify_student.services import IDVerificationService
|
||||
from openedx.core.djangoapps.certificates.api import can_show_certificate_available_date_field
|
||||
from openedx.core.djangolib.markup import HTML, Text
|
||||
from openedx.features.course_experience import CourseHomeMessages, UPGRADE_DEADLINE_MESSAGE
|
||||
from openedx.features.course_experience import UPGRADE_DEADLINE_MESSAGE, CourseHomeMessages
|
||||
from student.models import CourseEnrollment
|
||||
|
||||
from .context_processor import user_timezone_locale_prefs
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../../../../../cms/djangoapps/contentstore/management/commands/import.py
|
||||
78
lms/djangoapps/courseware/management/commands/import.py
Normal file
78
lms/djangoapps/courseware/management/commands/import.py
Normal file
@@ -0,0 +1,78 @@
|
||||
"""
|
||||
Script for importing courseware from XML format
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from openedx.core.djangoapps.django_comment_common.utils import are_permissions_roles_seeded, seed_permissions_roles
|
||||
from xmodule.contentstore.django import contentstore
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.xml_importer import import_course_from_xml
|
||||
from xmodule.util.sandboxing import DEFAULT_PYTHON_LIB_FILENAME
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""
|
||||
Import the specified data directory into the default ModuleStore
|
||||
"""
|
||||
help = 'Import the specified data directory into the default ModuleStore.'
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('data_directory')
|
||||
parser.add_argument('course_dirs',
|
||||
nargs='*',
|
||||
metavar='course_dir')
|
||||
parser.add_argument('--nostatic',
|
||||
action='store_true',
|
||||
help='Skip import of static content')
|
||||
parser.add_argument('--nopythonlib',
|
||||
action='store_true',
|
||||
help=(
|
||||
'Skip import of course python library if it exists '
|
||||
'(NOTE: If the static content import is not skipped, the python library '
|
||||
'will be imported and this flag will be ignored)'
|
||||
))
|
||||
parser.add_argument('--python-lib-filename',
|
||||
default=DEFAULT_PYTHON_LIB_FILENAME,
|
||||
help='Filename of the course code library (if it exists)')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
data_dir = options['data_directory']
|
||||
source_dirs = options['course_dirs']
|
||||
if not source_dirs:
|
||||
source_dirs = None
|
||||
do_import_static = not options.get('nostatic', False)
|
||||
# If the static content is not skipped, the python lib should be imported regardless
|
||||
# of the 'nopythonlib' flag.
|
||||
do_import_python_lib = do_import_static or not options.get('nopythonlib', False)
|
||||
python_lib_filename = options.get('python_lib_filename')
|
||||
|
||||
output = (
|
||||
u"Importing...\n"
|
||||
u" data_dir={data}, source_dirs={courses}\n"
|
||||
u" Importing static content? {import_static}\n"
|
||||
u" Importing python lib? {import_python_lib}"
|
||||
).format(
|
||||
data=data_dir,
|
||||
courses=source_dirs,
|
||||
import_static=do_import_static,
|
||||
import_python_lib=do_import_python_lib
|
||||
)
|
||||
self.stdout.write(output)
|
||||
mstore = modulestore()
|
||||
|
||||
course_items = import_course_from_xml(
|
||||
mstore, ModuleStoreEnum.UserID.mgmt_command, data_dir, source_dirs, load_error_modules=False,
|
||||
static_content_store=contentstore(), verbose=True,
|
||||
do_import_static=do_import_static, do_import_python_lib=do_import_python_lib,
|
||||
create_if_not_present=True,
|
||||
python_lib_filename=python_lib_filename,
|
||||
)
|
||||
|
||||
for course in course_items:
|
||||
course_id = course.id
|
||||
if not are_permissions_roles_seeded(course_id):
|
||||
self.stdout.write(u'Seeding forum roles for course {0}\n'.format(course_id))
|
||||
seed_permissions_roles(course_id)
|
||||
@@ -2,6 +2,8 @@
|
||||
Middleware for the courseware app
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.shortcuts import redirect
|
||||
|
||||
from lms.djangoapps.courseware.exceptions import Redirect
|
||||
|
||||
@@ -12,9 +12,12 @@ file and check it in at the same time as your model changes. To do that,
|
||||
ASSUMPTIONS: modules have unique IDs, even across different module_types
|
||||
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import itertools
|
||||
import logging
|
||||
|
||||
import six
|
||||
from config_models.models import ConfigurationModel
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
@@ -22,11 +25,11 @@ from django.db import models
|
||||
from django.db.models.signals import post_save
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from model_utils.models import TimeStampedModel
|
||||
from opaque_keys.edx.django.models import BlockTypeKeyField, CourseKeyField, UsageKeyField
|
||||
from six import text_type
|
||||
from six.moves import range
|
||||
|
||||
import coursewarehistoryextended
|
||||
from opaque_keys.edx.django.models import BlockTypeKeyField, CourseKeyField, UsageKeyField
|
||||
|
||||
from openedx.core.djangolib.markup import HTML
|
||||
|
||||
log = logging.getLogger("edx.courseware")
|
||||
@@ -37,7 +40,7 @@ def chunks(items, chunk_size):
|
||||
Yields the values from items in chunks of size chunk_size
|
||||
"""
|
||||
items = list(items)
|
||||
return (items[i:i + chunk_size] for i in xrange(0, len(items), chunk_size))
|
||||
return (items[i:i + chunk_size] for i in range(0, len(items), chunk_size))
|
||||
|
||||
|
||||
class ChunkingManager(models.Manager):
|
||||
@@ -67,7 +70,7 @@ class ChunkingManager(models.Manager):
|
||||
"""
|
||||
chunk_size = kwargs.pop('chunk_size', 500)
|
||||
res = itertools.chain.from_iterable(
|
||||
self.filter(**dict([(chunk_field, chunk)] + kwargs.items()))
|
||||
self.filter(**dict([(chunk_field, chunk)] + list(kwargs.items())))
|
||||
for chunk in chunks(items, chunk_size)
|
||||
)
|
||||
return res
|
||||
@@ -151,7 +154,7 @@ class StudentModule(models.Model):
|
||||
},)
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(repr(self))
|
||||
return six.text_type(repr(self))
|
||||
|
||||
@classmethod
|
||||
def get_state_by_params(cls, course_id, module_state_keys, student_id=None):
|
||||
@@ -245,7 +248,7 @@ class StudentModuleHistory(BaseStudentModuleHistory):
|
||||
student_module = models.ForeignKey(StudentModule, db_index=True, db_constraint=False, on_delete=models.CASCADE)
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(repr(self))
|
||||
return six.text_type(repr(self))
|
||||
|
||||
def save_history(sender, instance, **kwargs): # pylint: disable=no-self-argument, unused-argument
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user