From bc30addfb9555cea7f49149073bbd64e3b7b16c3 Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Fri, 10 Jan 2014 12:20:28 -0500 Subject: [PATCH] Unicode changes to support QRF fixing unit tests fixing merge error fixing xqueue submission issue with unicode url (trial 0.1) fixing fotmats as commented upon removing yaml file language selection Unicode changes to support QRF removed unnecessary pass in modulestore/init.py fixing merge error fixing fotmats as commented upon removing yaml file language selection fixing pep8 violations - fixing pylint violations pylint violation fixing line spaces and formats ignore pylint E1101 remove empty line fixing pylint violations pep8 violations bulk mail unicode/decode fix migration error fix pep8 just to push again more unicode/decode Final changes to comments and error messages. --- cms/djangoapps/contentstore/utils.py | 4 ++-- .../contentstore/views/component.py | 3 +-- cms/djangoapps/contentstore/views/course.py | 8 ++++--- cms/djangoapps/contentstore/views/preview.py | 2 +- cms/static/js/index.js | 4 ++-- cms/templates/unit.html | 2 +- common/djangoapps/cache_toolbox/core.py | 6 +++--- common/djangoapps/course_groups/cohorts.py | 2 +- common/djangoapps/static_replace/__init__.py | 4 ++-- common/djangoapps/student/roles.py | 17 ++++++++------- common/djangoapps/student/views.py | 8 +++---- common/lib/capa/capa/capa_problem.py | 2 +- common/lib/capa/capa/correctmap.py | 2 +- common/lib/capa/capa/xqueue_interface.py | 2 +- .../xmodule/xmodule/contentstore/content.py | 12 ++++++----- .../xmodule/xmodule/modulestore/__init__.py | 21 +++++++++++-------- .../xmodule/modulestore/loc_mapper_store.py | 19 ++++++++--------- .../xmodule/xmodule/modulestore/locator.py | 12 +++++------ .../xmodule/xmodule/modulestore/parsers.py | 7 ++++--- .../xmodule/modulestore/store_utilities.py | 6 +++--- .../xmodule/xmodule/tests/test_conditional.py | 12 +++++------ common/lib/xmodule/xmodule/x_module.py | 5 ++--- lms/djangoapps/bulk_email/tasks.py | 2 +- lms/djangoapps/courseware/access.py | 2 +- lms/djangoapps/courseware/module_render.py | 10 ++++----- lms/djangoapps/courseware/views.py | 10 ++++----- .../django_comment_client/permissions.py | 3 ++- lms/djangoapps/instructor/views/legacy.py | 4 ++-- .../open_ended_notifications.py | 10 ++++----- .../staff_grading_service.py | 6 +----- lms/lib/xblock/runtime.py | 4 ++-- 31 files changed, 107 insertions(+), 104 deletions(-) diff --git a/cms/djangoapps/contentstore/utils.py b/cms/djangoapps/contentstore/utils.py index f5b3196ccb19..fbe04186c43c 100644 --- a/cms/djangoapps/contentstore/utils.py +++ b/cms/djangoapps/contentstore/utils.py @@ -143,7 +143,7 @@ def get_lms_link_for_item(location, preview=False, course_id=None): else: lms_base = settings.LMS_BASE - lms_link = "//{lms_base}/courses/{course_id}/jump_to/{location}".format( + lms_link = u"//{lms_base}/courses/{course_id}/jump_to/{location}".format( lms_base=lms_base, course_id=course_id, location=Location(location) @@ -179,7 +179,7 @@ def get_lms_link_for_about_page(location): about_base = None if about_base is not None: - lms_link = "//{about_base_url}/courses/{course_id}/about".format( + lms_link = u"//{about_base_url}/courses/{course_id}/about".format( about_base_url=about_base, course_id=Location(location).course_id ) diff --git a/cms/djangoapps/contentstore/views/component.py b/cms/djangoapps/contentstore/views/component.py index d466bbe73238..8c1bcb7a9df4 100644 --- a/cms/djangoapps/contentstore/views/component.py +++ b/cms/djangoapps/contentstore/views/component.py @@ -267,8 +267,7 @@ def unit_handler(request, tag=None, package_id=None, branch=None, version_guid=N preview_lms_base = settings.FEATURES.get('PREVIEW_LMS_BASE') preview_lms_link = ( - '//{preview_lms_base}/courses/{org}/{course}/' - '{course_name}/courseware/{section}/{subsection}/{index}' + u'//{preview_lms_base}/courses/{org}/{course}/{course_name}/courseware/{section}/{subsection}/{index}' ).format( preview_lms_base=preview_lms_base, lms_base=settings.LMS_BASE, diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py index 89c5a33db779..e930e33c1a5e 100644 --- a/cms/djangoapps/contentstore/views/course.py +++ b/cms/djangoapps/contentstore/views/course.py @@ -251,7 +251,7 @@ def create_new_course(request): run = request.json.get('run') try: - dest_location = Location('i4x', org, number, 'course', run) + dest_location = Location(u'i4x', org, number, u'course', run) except InvalidLocationError as error: return JsonResponse({ "ErrMsg": _("Unable to create course '{name}'.\n\n{err}").format( @@ -286,8 +286,10 @@ def create_new_course(request): course_search_location = bson.son.SON({ '_id.tag': 'i4x', # cannot pass regex to Location constructor; thus this hack - '_id.org': re.compile('^{}$'.format(dest_location.org), re.IGNORECASE), - '_id.course': re.compile('^{}$'.format(dest_location.course), re.IGNORECASE), + # pylint: disable=E1101 + '_id.org': re.compile(u'^{}$'.format(dest_location.org), re.IGNORECASE | re.UNICODE), + # pylint: disable=E1101 + '_id.course': re.compile(u'^{}$'.format(dest_location.course), re.IGNORECASE | re.UNICODE), '_id.category': 'course', }) courses = modulestore().collection.find(course_search_location, fields=('_id')) diff --git a/cms/djangoapps/contentstore/views/preview.py b/cms/djangoapps/contentstore/views/preview.py index 19b351d59cb0..11bea40f9fa6 100644 --- a/cms/djangoapps/contentstore/views/preview.py +++ b/cms/djangoapps/contentstore/views/preview.py @@ -41,7 +41,7 @@ def handler_prefix(block, handler='', suffix=''): Trailing `/`s are removed from the returned url. """ return reverse('preview_handler', kwargs={ - 'usage_id': quote_slashes(str(block.scope_ids.usage_id)), + 'usage_id': quote_slashes(unicode(block.scope_ids.usage_id).encode('utf-8')), 'handler': handler, 'suffix': suffix, }).rstrip('/?') diff --git a/cms/static/js/index.js b/cms/static/js/index.js index d8a6903763c2..fff1923f4dba 100644 --- a/cms/static/js/index.js +++ b/cms/static/js/index.js @@ -84,8 +84,8 @@ require(["domReady", "jquery", "underscore", "js/utils/cancel_on_escape"], if (required) { return required; } - if (item !== encodeURIComponent(item)) { - return gettext('Please do not use any spaces or special characters in this field.'); + if (/\s/g.test(item)) { + return gettext('Please do not use any spaces in this field.'); } return ''; }; diff --git a/cms/templates/unit.html b/cms/templates/unit.html index 1151b4c5523c..04d73d8efd94 100644 --- a/cms/templates/unit.html +++ b/cms/templates/unit.html @@ -164,7 +164,7 @@

${_("Unit Settings")}

% endif ${_("with the subsection {link_start}{name}{link_end}").format( name=subsection.display_name_with_default, - link_start=''.format(url=subsection_url), + link_start=u''.format(url=subsection_url), link_end='', )}

diff --git a/common/djangoapps/cache_toolbox/core.py b/common/djangoapps/cache_toolbox/core.py index 9a7be940b894..3321f83d5ed2 100644 --- a/common/djangoapps/cache_toolbox/core.py +++ b/common/djangoapps/cache_toolbox/core.py @@ -110,12 +110,12 @@ def instance_key(model, instance_or_pk): def set_cached_content(content): - cache.set(str(content.location), content) + cache.set(unicode(content.location).encode("utf-8"), content) def get_cached_content(location): - return cache.get(str(location)) + return cache.get(unicode(location).encode("utf-8")) def del_cached_content(location): - cache.delete(str(location)) + cache.delete(unicode(location).encode("utf-8")) diff --git a/common/djangoapps/course_groups/cohorts.py b/common/djangoapps/course_groups/cohorts.py index d2c7e3a782f5..c6b93e563490 100644 --- a/common/djangoapps/course_groups/cohorts.py +++ b/common/djangoapps/course_groups/cohorts.py @@ -77,7 +77,7 @@ def is_commentable_cohorted(course_id, commentable_id): # inline discussions are cohorted by default ans = True - log.debug("is_commentable_cohorted({0}, {1}) = {2}".format(course_id, + log.debug(u"is_commentable_cohorted({0}, {1}) = {2}".format(course_id, commentable_id, ans)) return ans diff --git a/common/djangoapps/static_replace/__init__.py b/common/djangoapps/static_replace/__init__.py index a05129d86441..29dcf7455b03 100644 --- a/common/djangoapps/static_replace/__init__.py +++ b/common/djangoapps/static_replace/__init__.py @@ -19,7 +19,7 @@ def _url_replace_regex(prefix): To anyone contemplating making this more complicated: http://xkcd.com/1171/ """ - return r""" + return ur""" (?x) # flags=re.VERBOSE (?P\\?['"]) # the opening quotes (?P{prefix}) # the prefix @@ -152,7 +152,7 @@ def replace_static_url(match): return "".join([quote, url, quote]) return re.sub( - _url_replace_regex('(?:{static_url}|/static/)(?!{data_dir})'.format( + _url_replace_regex(u'(?:{static_url}|/static/)(?!{data_dir})'.format( static_url=settings.STATIC_URL, data_dir=static_asset_path or data_directory )), diff --git a/common/djangoapps/student/roles.py b/common/djangoapps/student/roles.py index daf3f6ee025b..a0783196b5de 100644 --- a/common/djangoapps/student/roles.py +++ b/common/djangoapps/student/roles.py @@ -159,30 +159,30 @@ def __init__(self, role, location, course_context=None): if isinstance(self.location, Location): try: - groupnames.append('{0}_{1}'.format(role, self.location.course_id)) + groupnames.append(u'{0}_{1}'.format(role, self.location.course_id)) course_context = self.location.course_id # course_id is valid for translation except InvalidLocationError: # will occur on old locations where location is not of category course if course_context is None: raise CourseContextRequired() else: - groupnames.append('{0}_{1}'.format(role, course_context)) + groupnames.append(u'{0}_{1}'.format(role, course_context)) try: locator = loc_mapper().translate_location_to_course_locator(course_context, self.location) - groupnames.append('{0}_{1}'.format(role, locator.package_id)) + groupnames.append(u'{0}_{1}'.format(role, locator.package_id)) except (InvalidLocationError, ItemNotFoundError): # if it's never been mapped, the auth won't be via the Locator syntax pass # least preferred legacy role_course format - groupnames.append('{0}_{1}'.format(role, self.location.course)) + groupnames.append(u'{0}_{1}'.format(role, self.location.course)) # pylint: disable=E1101, E1103 elif isinstance(self.location, CourseLocator): - groupnames.append('{0}_{1}'.format(role, self.location.package_id)) + groupnames.append(u'{0}_{1}'.format(role, self.location.package_id)) # handle old Location syntax old_location = loc_mapper().translate_locator_to_location(self.location, get_course=True) if old_location: # the slashified version of the course_id (myu/mycourse/myrun) - groupnames.append('{0}_{1}'.format(role, old_location.course_id)) + groupnames.append(u'{0}_{1}'.format(role, old_location.course_id)) # add the least desirable but sometimes occurring format. - groupnames.append('{0}_{1}'.format(role, old_location.course)) + groupnames.append(u'{0}_{1}'.format(role, old_location.course)) # pylint: disable=E1101, E1103 super(CourseRole, self).__init__(groupnames) @@ -193,12 +193,13 @@ class OrgRole(GroupBasedRole): """ def __init__(self, role, location): location = Location(location) - super(OrgRole, self).__init__(['{}_{}'.format(role, location.org)]) + super(OrgRole, self).__init__([u'{}_{}'.format(role, location.org)]) class CourseStaffRole(CourseRole): """A Staff member of a course""" ROLE = 'staff' + def __init__(self, *args, **kwargs): super(CourseStaffRole, self).__init__(self.ROLE, *args, **kwargs) diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 007b894900da..5ab43a161d87 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -353,7 +353,7 @@ def dashboard(request): course_enrollment_pairs.append((course, enrollment)) except ItemNotFoundError: - log.error("User {0} enrolled in non-existent course {1}" + log.error(u"User {0} enrolled in non-existent course {1}" .format(user.username, enrollment.course_id)) course_optouts = Optout.objects.filter(user=user).values_list('course_id', flat=True) @@ -495,9 +495,9 @@ def change_enrollment(request): org, course_num, run = course_id.split("/") dog_stats_api.increment( "common.student.enrollment", - tags=["org:{0}".format(org), - "course:{0}".format(course_num), - "run:{0}".format(run)] + tags=[u"org:{0}".format(org), + u"course:{0}".format(course_num), + u"run:{0}".format(run)] ) CourseEnrollment.enroll(user, course.id, mode=current_mode.slug) diff --git a/common/lib/capa/capa/capa_problem.py b/common/lib/capa/capa/capa_problem.py index f011b3813e22..d14af5b0d8fa 100644 --- a/common/lib/capa/capa/capa_problem.py +++ b/common/lib/capa/capa/capa_problem.py @@ -372,7 +372,7 @@ def _grade_answers(self, student_answers): # TODO: figure out where to get file submissions when rescoring. if 'filesubmission' in responder.allowed_inputfields and student_answers is None: _ = self.capa_system.i18n.ugettext - raise Exception(_("Cannot rescore problems with possible file submissions")) + raise Exception(_(u"Cannot rescore problems with possible file submissions")) # use 'student_answers' only if it is provided, and if it might contain a file # submission that would not exist in the persisted "student_answers". diff --git a/common/lib/capa/capa/correctmap.py b/common/lib/capa/capa/correctmap.py index 2ea4a35c024d..df7efee343c6 100644 --- a/common/lib/capa/capa/correctmap.py +++ b/common/lib/capa/capa/correctmap.py @@ -50,7 +50,7 @@ def set( ): if answer_id is not None: - self.cmap[str(answer_id)] = { + self.cmap[answer_id] = { 'correctness': correctness, 'npoints': npoints, 'msg': msg, diff --git a/common/lib/capa/capa/xqueue_interface.py b/common/lib/capa/capa/xqueue_interface.py index 270b696f9f40..78b9fcd008f3 100644 --- a/common/lib/capa/capa/xqueue_interface.py +++ b/common/lib/capa/capa/xqueue_interface.py @@ -62,7 +62,7 @@ class XQueueInterface(object): """ def __init__(self, url, django_auth, requests_auth=None): - self.url = url + self.url = unicode(url) self.auth = django_auth self.session = requests.Session() self.session.auth = requests_auth diff --git a/common/lib/xmodule/xmodule/contentstore/content.py b/common/lib/xmodule/xmodule/contentstore/content.py index 61ff0bc1927a..50e7f5d84842 100644 --- a/common/lib/xmodule/xmodule/contentstore/content.py +++ b/common/lib/xmodule/xmodule/contentstore/content.py @@ -34,7 +34,9 @@ def is_thumbnail(self): @staticmethod def generate_thumbnail_name(original_name): - return ('{0}' + XASSET_THUMBNAIL_TAIL_NAME).format(os.path.splitext(original_name)[0]) + return u"{name_root}{extension}".format( + name_root=os.path.splitext(original_name)[0], + extension=XASSET_THUMBNAIL_TAIL_NAME,) @staticmethod def compute_location(org, course, name, revision=None, is_thumbnail=False): @@ -64,7 +66,7 @@ def is_c4x_path(path_string): """ Returns a boolean if a path is believed to be a c4x link based on the leading element """ - return path_string.startswith('/{0}/'.format(XASSET_LOCATION_TAG)) + return path_string.startswith(u'/{0}/'.format(XASSET_LOCATION_TAG)) @staticmethod def renamespace_c4x_path(path_string, target_location): @@ -86,14 +88,14 @@ def get_static_path_from_location(location): the actual /c4x/... path which the client needs to reference static content """ if location is not None: - return "/static/{name}".format(**location.dict()) + return u"/static/{name}".format(**location.dict()) else: return None @staticmethod def get_base_url_path_for_course_assets(loc): if loc is not None: - return "/c4x/{org}/{course}/asset".format(**loc.dict()) + return u"/c4x/{org}/{course}/asset".format(**loc.dict()) @staticmethod def get_id_from_location(location): @@ -237,6 +239,6 @@ def generate_thumbnail(self, content, tempfile_path=None): except Exception, e: # log and continue as thumbnails are generally considered as optional - logging.exception("Failed to generate thumbnail for {0}. Exception: {1}".format(content.location, str(e))) + logging.exception(u"Failed to generate thumbnail for {0}. Exception: {1}".format(content.location, str(e))) return thumbnail_content, thumbnail_file_location diff --git a/common/lib/xmodule/xmodule/modulestore/__init__.py b/common/lib/xmodule/xmodule/modulestore/__init__.py index 89b8e80d15b9..5d241731a7e4 100644 --- a/common/lib/xmodule/xmodule/modulestore/__init__.py +++ b/common/lib/xmodule/xmodule/modulestore/__init__.py @@ -30,12 +30,12 @@ # TODO (cpennington): We should decide whether we want to expand the # list of valid characters in a location -INVALID_CHARS = re.compile(r"[^\w.-]") +INVALID_CHARS = re.compile(r"[^\w.%-]", re.UNICODE) # Names are allowed to have colons. -INVALID_CHARS_NAME = re.compile(r"[^\w.:-]") +INVALID_CHARS_NAME = re.compile(r"[^\w.:%-]", re.UNICODE) # html ids can contain word chars and dashes -INVALID_HTML_CHARS = re.compile(r"[^\w-]") +INVALID_HTML_CHARS = re.compile(r"[^\w-]", re.UNICODE) _LocationBase = namedtuple('LocationBase', 'tag org course category name revision') @@ -186,14 +186,14 @@ def check_list(list_): elif isinstance(location, basestring): match = URL_RE.match(location) if match is None: - log.debug("location %r doesn't match URL", location) + log.debug(u"location %r doesn't match URL", location) raise InvalidLocationError(location) groups = match.groupdict() check_dict(groups) return _LocationBase.__new__(_cls, **groups) elif isinstance(location, (list, tuple)): if len(location) not in (5, 6): - log.debug('location has wrong length') + log.debug(u'location has wrong length') raise InvalidLocationError(location) if len(location) == 5: @@ -216,9 +216,9 @@ def url(self): """ Return a string containing the URL for this location """ - url = "{0.tag}://{0.org}/{0.course}/{0.category}/{0.name}".format(self) + url = u"{0.tag}://{0.org}/{0.course}/{0.category}/{0.name}".format(self) if self.revision: - url += "@" + self.revision + url += u"@{rev}".format(rev=self.revision) # pylint: disable=E1101 return url def html_id(self): @@ -226,7 +226,7 @@ def html_id(self): Return a string with a version of the location that is safe for use in html id attributes """ - id_string = "-".join(str(v) for v in self.list() if v is not None) + id_string = u"-".join(v for v in self.list() if v is not None) return Location.clean_for_html(id_string) def dict(self): @@ -240,6 +240,9 @@ def list(self): return list(self) def __str__(self): + return str(self.url().encode("utf-8")) + + def __unicode__(self): return self.url() def __repr__(self): @@ -254,7 +257,7 @@ def course_id(self): Throws an InvalidLocationError is this location does not represent a course. """ if self.category != 'course': - raise InvalidLocationError('Cannot call course_id for {0} because it is not of category course'.format(self)) + raise InvalidLocationError(u'Cannot call course_id for {0} because it is not of category course'.format(self)) return "/".join([self.org, self.course, self.name]) diff --git a/common/lib/xmodule/xmodule/modulestore/loc_mapper_store.py b/common/lib/xmodule/xmodule/modulestore/loc_mapper_store.py index 7e00abfdace2..37853d07896a 100644 --- a/common/lib/xmodule/xmodule/modulestore/loc_mapper_store.py +++ b/common/lib/xmodule/xmodule/modulestore/loc_mapper_store.py @@ -88,9 +88,9 @@ def create_map_entry(self, course_location, package_id=None, draft_branch='draft """ if package_id is None: if course_location.category == 'course': - package_id = "{0.org}.{0.course}.{0.name}".format(course_location) + package_id = u"{0.org}.{0.course}.{0.name}".format(course_location) else: - package_id = "{0.org}.{0.course}".format(course_location) + package_id = u"{0.org}.{0.course}".format(course_location) # very like _interpret_location_id but w/o the _id location_id = self._construct_location_son( course_location.org, course_location.course, @@ -185,7 +185,6 @@ def translate_location(self, old_style_course_id, location, published=True, add_ self._cache_location_map_entry(old_style_course_id, location, published_usage, draft_usage) return result - def translate_locator_to_location(self, locator, get_course=False): """ Returns an old style Location for the given Locator if there's an appropriate entry in the @@ -331,12 +330,12 @@ def _generate_location_course_id(self, entry_id): # strip id envelope if any entry_id = entry_id.get('_id', entry_id) if entry_id.get('name', False): - return '{0[org]}/{0[course]}/{0[name]}'.format(entry_id) + return u'{0[org]}/{0[course]}/{0[name]}'.format(entry_id) elif entry_id.get('_id.org', False): # the odd format one - return '{0[_id.org]}/{0[_id.course]}'.format(entry_id) + return u'{0[_id.org]}/{0[_id.course]}'.format(entry_id) else: - return '{0[org]}/{0[course]}'.format(entry_id) + return u'{0[org]}/{0[course]}'.format(entry_id) def _construct_location_son(self, org, course, name=None): """ @@ -392,7 +391,7 @@ def _get_locator_from_cache(self, old_course_id, location, published): """ See if the location x published pair is in the cache. If so, return the mapped locator. """ - entry = self.cache.get('{}+{}'.format(old_course_id, location.url())) + entry = self.cache.get(u'{}+{}'.format(old_course_id, location.url())) if entry is not None: if published: return entry[0] @@ -424,7 +423,7 @@ def _get_course_location_from_cache(self, locator_package_id): See if the package_id is in the cache. If so, return the mapped location to the course root. """ - return self.cache.get('courseId+{}'.format(locator_package_id)) + return self.cache.get(u'courseId+{}'.format(locator_package_id)) def _cache_course_locator(self, old_course_id, published_course_locator, draft_course_locator): """ @@ -442,9 +441,9 @@ def _cache_location_map_entry(self, old_course_id, location, published_usage, dr """ setmany = {} if location.category == 'course': - setmany['courseId+{}'.format(published_usage.package_id)] = location + setmany[u'courseId+{}'.format(published_usage.package_id)] = location setmany[unicode(published_usage)] = location setmany[unicode(draft_usage)] = location - setmany['{}+{}'.format(old_course_id, location.url())] = (published_usage, draft_usage) + setmany[u'{}+{}'.format(old_course_id, location.url())] = (published_usage, draft_usage) setmany[old_course_id] = (published_usage, draft_usage) self.cache.set_many(setmany) diff --git a/common/lib/xmodule/xmodule/modulestore/locator.py b/common/lib/xmodule/xmodule/modulestore/locator.py index bde6cee83892..2b58797532bf 100644 --- a/common/lib/xmodule/xmodule/modulestore/locator.py +++ b/common/lib/xmodule/xmodule/modulestore/locator.py @@ -64,13 +64,13 @@ def __str__(self): ''' str(self) returns something like this: "mit.eecs.6002x" ''' - return unicode(self).encode('utf8') + return unicode(self).encode('utf-8') def __unicode__(self): ''' unicode(self) returns something like this: "mit.eecs.6002x" ''' - return self.url() + return unicode(self).encode('utf-8') @abstractmethod def version(self): @@ -199,12 +199,12 @@ def __unicode__(self): Return a string representing this location. """ if self.package_id: - result = self.package_id + result = unicode(self.package_id) if self.branch: result += '/' + BRANCH_PREFIX + self.branch return result elif self.version_guid: - return VERSION_PREFIX + str(self.version_guid) + return u"{prefix}{guid}".format(prefix=VERSION_PREFIX, guid=self.version_guid) else: # raise InsufficientSpecificationError("missing package_id or version_guid") return '' @@ -213,7 +213,7 @@ def url(self): """ Return a string containing the URL for this location. """ - return 'edx://' + unicode(self) + return u'edx://' + unicode(self) def _validate_args(self, url, version_guid, package_id): """ @@ -526,7 +526,7 @@ def url(self): Return a string containing the URL for this location. url(self) returns something like this: 'defx://version/519665f6223ebd6980884f2b' """ - return 'defx://' + unicode(self) + return u'defx://' + unicode(self) def version(self): """ diff --git a/common/lib/xmodule/xmodule/modulestore/parsers.py b/common/lib/xmodule/xmodule/modulestore/parsers.py index f1f49febb4c7..9d046effdb67 100644 --- a/common/lib/xmodule/xmodule/modulestore/parsers.py +++ b/common/lib/xmodule/xmodule/modulestore/parsers.py @@ -7,7 +7,8 @@ # Prefix for the version portion of a locator URL, when it is preceded by a course ID VERSION_PREFIX = r"version/" -ALLOWED_ID_CHARS = r'[a-zA-Z0-9_\-~.:]' +ALLOWED_ID_CHARS = r'[\w\-~.:]' + URL_RE_SOURCE = r""" (?Pedx://)? @@ -20,7 +21,7 @@ VERSION_PREFIX=VERSION_PREFIX, BLOCK_PREFIX=BLOCK_PREFIX ) -URL_RE = re.compile('^' + URL_RE_SOURCE + '$', re.IGNORECASE | re.VERBOSE) +URL_RE = re.compile('^' + URL_RE_SOURCE + '$', re.IGNORECASE | re.VERBOSE | re.UNICODE) def parse_url(string, tag_optional=False): @@ -54,7 +55,7 @@ def parse_url(string, tag_optional=False): return matched_dict -BLOCK_RE = re.compile(r'^' + ALLOWED_ID_CHARS + r'+$', re.IGNORECASE) +BLOCK_RE = re.compile(r'^' + ALLOWED_ID_CHARS + r'+$', re.IGNORECASE | re.UNICODE) def parse_block_ref(string): diff --git a/common/lib/xmodule/xmodule/modulestore/store_utilities.py b/common/lib/xmodule/xmodule/modulestore/store_utilities.py index a01eb5e5f1db..9408dc14fd91 100644 --- a/common/lib/xmodule/xmodule/modulestore/store_utilities.py +++ b/common/lib/xmodule/xmodule/modulestore/store_utilities.py @@ -73,13 +73,13 @@ def generic_courseware_link_substitution(match): # NOTE: ultimately link updating is not a hard requirement, so if something blows up with # the regex subsitution, log the error and continue try: - c4x_link_base = '{0}/'.format(StaticContent.get_base_url_path_for_course_assets(course_location)) + c4x_link_base = u'{0}/'.format(StaticContent.get_base_url_path_for_course_assets(course_location)) text = re.sub(_prefix_only_url_replace_regex(c4x_link_base), portable_asset_link_subtitution, text) except Exception, e: logging.warning("Error going regex subtituion %r on text = %r.\n\nError msg = %s", c4x_link_base, text, str(e)) try: - jump_to_link_base = '/courses/{org}/{course}/{run}/jump_to/i4x://{org}/{course}/'.format( + jump_to_link_base = u'/courses/{org}/{course}/{run}/jump_to/i4x://{org}/{course}/'.format( org=org, course=course, run=run ) text = re.sub(_prefix_and_category_url_replace_regex(jump_to_link_base), portable_jump_to_link_substitution, text) @@ -94,7 +94,7 @@ def generic_courseware_link_substitution(match): # if source_course_id != dest_course_id: try: - generic_courseware_link_base = '/courses/{org}/{course}/{run}/'.format( + generic_courseware_link_base = u'/courses/{org}/{course}/{run}/'.format( org=org, course=course, run=run ) text = re.sub(_prefix_only_url_replace_regex(generic_courseware_link_base), portable_asset_link_subtitution, text) diff --git a/common/lib/xmodule/xmodule/tests/test_conditional.py b/common/lib/xmodule/xmodule/tests/test_conditional.py index 74aa83073ffc..0487194dbc7d 100644 --- a/common/lib/xmodule/xmodule/tests/test_conditional.py +++ b/common/lib/xmodule/xmodule/tests/test_conditional.py @@ -129,9 +129,9 @@ def test_get_html(self): html = modules['cond_module'].render('student_view').content expected = modules['cond_module'].xmodule_runtime.render_template('conditional_ajax.html', { 'ajax_url': modules['cond_module'].xmodule_runtime.ajax_url, - 'element_id': 'i4x-edX-conditional_test-conditional-SampleConditional', - 'id': 'i4x://edX/conditional_test/conditional/SampleConditional', - 'depends': 'i4x-edX-conditional_test-problem-SampleProblem', + 'element_id': u'i4x-edX-conditional_test-conditional-SampleConditional', + 'id': u'i4x://edX/conditional_test/conditional/SampleConditional', + 'depends': u'i4x-edX-conditional_test-problem-SampleProblem', }) self.assertEquals(expected, html) @@ -225,9 +225,9 @@ def replace_urls(text, staticfiles_prefix=None, replace_prefix='/static/', cours { # Test ajax url is just usage-id / handler_name 'ajax_url': 'i4x://HarvardX/ER22x/conditional/condone/xmodule_handler', - 'element_id': 'i4x-HarvardX-ER22x-conditional-condone', - 'id': 'i4x://HarvardX/ER22x/conditional/condone', - 'depends': 'i4x-HarvardX-ER22x-problem-choiceprob' + 'element_id': u'i4x-HarvardX-ER22x-conditional-condone', + 'id': u'i4x://HarvardX/ER22x/conditional/condone', + 'depends': u'i4x-HarvardX-ER22x-problem-choiceprob' } ) self.assertEqual(html, html_expect) diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index 51d077c68607..9fe208fd0474 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -223,7 +223,7 @@ def get_children(self): try: child = self.runtime.get_block(child_loc) except ItemNotFoundError: - log.exception('Unable to load item {loc}, skipping'.format(loc=child_loc)) + log.exception(u'Unable to load item {loc}, skipping'.format(loc=child_loc)) continue self._child_instances.append(child) @@ -538,7 +538,6 @@ def templates(cls): template = yaml.safe_load(template_content) template['template_id'] = template_file templates.append(template) - return templates @classmethod @@ -546,7 +545,7 @@ def get_template_dir(cls): if getattr(cls, 'template_dir_name', None): dirname = os.path.join('templates', cls.template_dir_name) if not resource_isdir(__name__, dirname): - log.warning("No resource directory {dir} found when loading {cls_name} templates".format( + log.warning(u"No resource directory {dir} found when loading {cls_name} templates".format( dir=dirname, cls_name=cls.__name__, )) diff --git a/lms/djangoapps/bulk_email/tasks.py b/lms/djangoapps/bulk_email/tasks.py index d02045a8be23..5b07f49fa538 100644 --- a/lms/djangoapps/bulk_email/tasks.py +++ b/lms/djangoapps/bulk_email/tasks.py @@ -677,5 +677,5 @@ def _statsd_tag(course_title): """ Calculate the tag we will use for DataDog. """ - tag = "course_email:{0}".format(course_title) + tag = u"course_email:{0}".format(course_title) return tag[:200] diff --git a/lms/djangoapps/courseware/access.py b/lms/djangoapps/courseware/access.py index e5cfc85038dd..8f789915725c 100644 --- a/lms/djangoapps/courseware/access.py +++ b/lms/djangoapps/courseware/access.py @@ -343,7 +343,7 @@ def _dispatch(table, action, user, obj): action) return result - raise ValueError("Unknown action for object type '{0}': '{1}'".format( + raise ValueError(u"Unknown action for object type '{0}': '{1}'".format( type(obj), action)) diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index 51f236adc70f..207e46f63897 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -321,10 +321,10 @@ def publish(block, event, custom_user=None): org, course_num, run = course_id.split("/") tags = [ - "org:{0}".format(org), - "course:{0}".format(course_num), - "run:{0}".format(run), - "score_bucket:{0}".format(score_bucket) + u"org:{0}".format(org), + u"course:{0}".format(course_num), + u"run:{0}".format(run), + u"score_bucket:{0}".format(score_bucket) ] if grade_bucket_type is not None: @@ -443,7 +443,7 @@ def publish(block, event, custom_user=None): make_psychometrics_data_update_handler(course_id, user, descriptor.location.url()) ) - system.set('user_is_staff', has_access(user, descriptor.location, 'staff', course_id)) + system.set(u'user_is_staff', has_access(user, descriptor.location, u'staff', course_id)) # make an ErrorDescriptor -- assuming that the descriptor's system is ok if has_access(user, descriptor.location, 'staff', course_id): diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py index e60b6c5394fc..4e0e97c2bcd9 100644 --- a/lms/djangoapps/courseware/views.py +++ b/lms/djangoapps/courseware/views.py @@ -238,7 +238,7 @@ def index(request, course_id, chapter=None, section=None, registered = registered_for_course(course, user) if not registered: # TODO (vshnayder): do course instructors need to be registered to see course? - log.debug('User %s tried to view course %s but is not enrolled' % (user, course.location.url())) + log.debug(u'User {0} tried to view course {1} but is not enrolled'.format(user, course.location.url())) return redirect(reverse('about_course', args=[course.id])) masq = setup_masquerade(request, staff_access) @@ -249,8 +249,8 @@ def index(request, course_id, chapter=None, section=None, course_module = get_module_for_descriptor(user, request, course, field_data_cache, course.id) if course_module is None: - log.warning('If you see this, something went wrong: if we got this' - ' far, should have gotten a course module for this user') + log.warning(u'If you see this, something went wrong: if we got this' + u' far, should have gotten a course module for this user') return redirect(reverse('about_course', args=[course.id])) if chapter is None: @@ -424,9 +424,9 @@ def jump_to(request, course_id, location): try: (course_id, chapter, section, position) = path_to_location(modulestore(), course_id, location) except ItemNotFoundError: - raise Http404("No data at this location: {0}".format(location)) + raise Http404(u"No data at this location: {0}".format(location)) except NoPathToItem: - raise Http404("This location is not in any class: {0}".format(location)) + raise Http404(u"This location is not in any class: {0}".format(location)) # choose the appropriate view (and provide the necessary args) based on the # args provided by the redirect. diff --git a/lms/djangoapps/django_comment_client/permissions.py b/lms/djangoapps/django_comment_client/permissions.py index 3c83556a7e75..4003dfb460c5 100644 --- a/lms/djangoapps/django_comment_client/permissions.py +++ b/lms/djangoapps/django_comment_client/permissions.py @@ -15,7 +15,8 @@ def cached_has_permission(user, permission, course_id=None): Call has_permission if it's not cached. A change in a user's role or a role's permissions will only become effective after CACHE_LIFESPAN seconds. """ - key = "permission_%d_%s_%s" % (user.id, str(course_id), permission) + key = u"permission_{user_id:d}_{course_id}_{permission}".format( + user_id=user.id, course_id=course_id, permission=permission) val = CACHE.get(key, None) if val not in [True, False]: val = has_permission(user, permission, course_id=course_id) diff --git a/lms/djangoapps/instructor/views/legacy.py b/lms/djangoapps/instructor/views/legacy.py index ae740ad319a0..c671b2892251 100644 --- a/lms/djangoapps/instructor/views/legacy.py +++ b/lms/djangoapps/instructor/views/legacy.py @@ -173,7 +173,7 @@ def get_module_url(urlname): # complete the url using information about the current course: (org, course_name, _) = course_id.split("/") - return "i4x://" + org + "/" + course_name + "/" + urlname + return u"i4x://{org}/{name}/{url}".format(org=org, name=course_name, url=urlname) def get_student_from_identifier(unique_student_identifier): """Gets a student object using either an email address or username""" @@ -782,7 +782,7 @@ def get_analytics_result(analytics_name): logs and swallows errors. """ url = settings.ANALYTICS_SERVER_URL + \ - "get?aname={}&course_id={}&apikey={}".format(analytics_name, + u"get?aname={}&course_id={}&apikey={}".format(analytics_name, course_id, settings.ANALYTICS_API_KEY) try: diff --git a/lms/djangoapps/open_ended_grading/open_ended_notifications.py b/lms/djangoapps/open_ended_grading/open_ended_notifications.py index e99f51283c78..9398a119578b 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_notifications.py +++ b/lms/djangoapps/open_ended_grading/open_ended_notifications.py @@ -66,7 +66,7 @@ def staff_grading_notifications(course, user): def peer_grading_notifications(course, user): system = LmsModuleSystem( track_function=None, - get_module = None, + get_module=None, render_template=render_to_string, replace_urls=None, ) @@ -115,7 +115,7 @@ def combined_notifications(course, user): #Set up return values so that we can return them for error cases pending_grading = False img_path = "" - notifications={} + notifications = {} notification_dict = {'pending_grading': pending_grading, 'img_path': img_path, 'response': notifications} #We don't want to show anonymous users anything. @@ -126,7 +126,7 @@ def combined_notifications(course, user): system = LmsModuleSystem( static_url="/static", track_function=None, - get_module = None, + get_module=None, render_template=render_to_string, replace_urls=None, ) @@ -159,7 +159,7 @@ def combined_notifications(course, user): #Non catastrophic error, so no real action #This is a dev_facing_error log.exception( - "Problem with getting notifications from controller query service for course {0} user {1}.".format( + u"Problem with getting notifications from controller query service for course {0} user {1}.".format( course_id, student_id)) if pending_grading: @@ -185,7 +185,7 @@ def set_value_in_cache(student_id, course_id, notification_type, value): def create_key_name(student_id, course_id, notification_type): - key_name = "{prefix}{type}_{course}_{student}".format(prefix=KEY_PREFIX, type=notification_type, course=course_id, + key_name = u"{prefix}{type}_{course}_{student}".format(prefix=KEY_PREFIX, type=notification_type, course=course_id, student=student_id) return key_name diff --git a/lms/djangoapps/open_ended_grading/staff_grading_service.py b/lms/djangoapps/open_ended_grading/staff_grading_service.py index 090b36d13c32..81a2eb401c53 100644 --- a/lms/djangoapps/open_ended_grading/staff_grading_service.py +++ b/lms/djangoapps/open_ended_grading/staff_grading_service.py @@ -66,7 +66,6 @@ def get_problem_list(self, course_id, grader_id): 'min_for_ml': 10}) ]}) - def save_grade(self, course_id, grader_id, submission_id, score, feedback, skipped, rubric_scores, submission_flagged): return self.get_next(course_id, 'fake location', grader_id) @@ -81,7 +80,7 @@ def __init__(self, config): config['system'] = LmsModuleSystem( static_url='/static', track_function=None, - get_module = None, + get_module=None, render_template=render_to_string, replace_urls=None, ) @@ -93,7 +92,6 @@ def __init__(self, config): self.get_problem_list_url = self.url + '/get_problem_list/' self.get_notifications_url = self.url + "/get_notifications/" - def get_problem_list(self, course_id, grader_id): """ Get the list of problems for a given course. @@ -113,7 +111,6 @@ def get_problem_list(self, course_id, grader_id): params = {'course_id': course_id, 'grader_id': grader_id} return self.get(self.get_problem_list_url, params) - def get_next(self, course_id, location, grader_id): """ Get the next thing to grade. @@ -137,7 +134,6 @@ def get_next(self, course_id, location, grader_id): 'grader_id': grader_id}) return json.dumps(self._render_rubric(response)) - def save_grade(self, course_id, grader_id, submission_id, score, feedback, skipped, rubric_scores, submission_flagged): """ diff --git a/lms/lib/xblock/runtime.py b/lms/lib/xblock/runtime.py index cb2c0330251b..74066a6af13d 100644 --- a/lms/lib/xblock/runtime.py +++ b/lms/lib/xblock/runtime.py @@ -35,7 +35,7 @@ def quote_slashes(text): ';;'. By making the escape sequence fixed length, and escaping identifier character ';', we are able to reverse the escaping. """ - return re.sub(r'[;/]', _quote_slashes, text) + return re.sub(ur'[;/]', _quote_slashes, text) def _unquote_slashes(match): @@ -84,7 +84,7 @@ def handler_url(course_id, block, handler, suffix='', query='', thirdparty=False url = reverse(view_name, kwargs={ 'course_id': course_id, - 'usage_id': quote_slashes(str(block.scope_ids.usage_id)), + 'usage_id': quote_slashes(unicode(block.scope_ids.usage_id).encode('utf-8')), 'handler': handler, 'suffix': suffix, })