Commit 9cfd649c by Jay Zoldak

Merge pull request #2137 from abdoosh00/feature/unicode

Unicode changes to support R to L script
parents 7dbec608 bc30addf
......@@ -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
)
......
......@@ -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,
......
......@@ -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'))
......
......@@ -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('/?')
......
......@@ -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 '';
};
......
......@@ -164,7 +164,7 @@ require(["domReady!", "jquery", "js/models/module_info", "coffee/src/views/unit"
% endif
${_("with the subsection {link_start}{name}{link_end}").format(
name=subsection.display_name_with_default,
link_start='<a href="{url}">'.format(url=subsection_url),
link_start=u'<a href="{url}">'.format(url=subsection_url),
link_end='</a>',
)}
</p>
......
......@@ -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"))
......@@ -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
......
......@@ -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<quote>\\?['"]) # the opening quotes
(?P<prefix>{prefix}) # the prefix
......@@ -152,7 +152,7 @@ def replace_static_urls(text, data_directory, course_id=None, static_asset_path=
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
)),
......
......@@ -159,30 +159,30 @@ class CourseRole(GroupBasedRole):
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)
......
......@@ -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)
......
......@@ -372,7 +372,7 @@ class LoncapaProblem(object):
# 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".
......
......@@ -50,7 +50,7 @@ class CorrectMap(object):
):
if answer_id is not None:
self.cmap[str(answer_id)] = {
self.cmap[answer_id] = {
'correctness': correctness,
'npoints': npoints,
'msg': msg,
......
......@@ -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
......
......@@ -34,7 +34,9 @@ class StaticContent(object):
@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 @@ class StaticContent(object):
"""
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 @@ class StaticContent(object):
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 @@ class ContentStore(object):
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
......@@ -30,12 +30,12 @@ URL_RE = re.compile("""
# 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 @@ class Location(_LocationBase):
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 @@ class Location(_LocationBase):
"""
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 @@ class Location(_LocationBase):
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 @@ class Location(_LocationBase):
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 @@ class Location(_LocationBase):
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])
......
......@@ -88,9 +88,9 @@ class LocMapperStore(object):
"""
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 @@ class LocMapperStore(object):
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 @@ class LocMapperStore(object):
# 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 @@ class LocMapperStore(object):
"""
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 @@ class LocMapperStore(object):
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 @@ class LocMapperStore(object):
"""
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)
......@@ -64,13 +64,13 @@ class Locator(object):
'''
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 @@ class CourseLocator(Locator):
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 '<InsufficientSpecificationError: missing package_id or version_guid>'
......@@ -213,7 +213,7 @@ class CourseLocator(Locator):
"""
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 @@ class DefinitionLocator(Locator):
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):
"""
......
......@@ -7,7 +7,8 @@ BLOCK_PREFIX = r"block/"
# 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"""
(?P<tag>edx://)?
......@@ -20,7 +21,7 @@ URL_RE_SOURCE = r"""
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):
......
......@@ -73,13 +73,13 @@ def rewrite_nonportable_content_links(source_course_id, dest_course_id, text):
# 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 rewrite_nonportable_content_links(source_course_id, dest_course_id, text):
#
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)
......
......@@ -129,9 +129,9 @@ class ConditionalModuleBasicTest(unittest.TestCase):
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 @@ class ConditionalModuleXmlTest(unittest.TestCase):
{
# 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)
......
......@@ -223,7 +223,7 @@ class XModuleMixin(XBlockMixin):
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 @@ class ResourceTemplates(object):
template = yaml.safe_load(template_content)
template['template_id'] = template_file
templates.append(template)
return templates
@classmethod
......@@ -546,7 +545,7 @@ class ResourceTemplates(object):
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__,
))
......
......@@ -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]
......@@ -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))
......
......@@ -321,10 +321,10 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours
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 get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours
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):
......
......@@ -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.
......
......@@ -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)
......
......@@ -173,7 +173,7 @@ def instructor_dashboard(request, course_id):
# 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 instructor_dashboard(request, course_id):
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:
......
......@@ -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
......
......@@ -66,7 +66,6 @@ class MockStaffGradingService(object):
'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 @@ class StaffGradingService(GradingService):
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 @@ class StaffGradingService(GradingService):
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 @@ class StaffGradingService(GradingService):
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 @@ class StaffGradingService(GradingService):
'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):
"""
......
......@@ -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,
})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment