PLAT-1873 to_deprecated_string() cleanup part 1

This commit is contained in:
Jeremy Bowman
2018-01-05 16:27:51 -05:00
parent 2580a76016
commit d3d6272d8f
63 changed files with 386 additions and 306 deletions

View File

@@ -19,6 +19,7 @@ from django.utils.translation import get_language, to_locale
from django.views.generic.base import View
from ipware.ip import get_ip
from opaque_keys.edx.keys import CourseKey
from six import text_type
from course_modes.models import CourseMode
from courseware.access import has_access
@@ -138,7 +139,7 @@ class ChooseModeView(View):
CourseMode.is_credit_mode(mode) for mode
in CourseMode.modes_for_course(course_key, only_selectable=False)
)
course_id = course_key.to_deprecated_string()
course_id = text_type(course_key)
context = {
"course_modes_choose_url": reverse(
"course_modes_choose",

View File

@@ -10,6 +10,7 @@ from django.dispatch import receiver
from django.utils.translation import ugettext_noop
from openedx.core.djangoapps.xmodule_django.models import CourseKeyField, NoneToEmptyManager
from six import text_type
from student.models import CourseEnrollment
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError
@@ -74,7 +75,7 @@ class Role(models.Model):
def __unicode__(self):
# pylint: disable=no-member
return self.name + " for " + (self.course_id.to_deprecated_string() if self.course_id else "all courses")
return self.name + " for " + (text_type(self.course_id) if self.course_id else "all courses")
# TODO the name of this method is a little bit confusing,
# since it's one-off and doesn't handle inheritance later

View File

@@ -8,6 +8,7 @@ from django.conf import settings
from xmodule.contentstore.content import StaticContent
from opaque_keys.edx.locator import AssetLocator
from six import text_type
log = logging.getLogger(__name__)
XBLOCK_STATIC_RESOURCE_PREFIX = '/static/xblock'
@@ -83,7 +84,7 @@ def replace_course_urls(text, course_key):
returns: text with the links replaced
"""
course_id = course_key.to_deprecated_string()
course_id = text_type(course_key)
def replace_course_url(match):
quote = match.group('quote')

View File

@@ -43,6 +43,7 @@ from eventtracking import tracker
from model_utils.models import TimeStampedModel
from opaque_keys.edx.keys import CourseKey
from pytz import UTC
from six import text_type
from slumber.exceptions import HttpClientError, HttpServerError
import dogstats_wrapper as dog_stats_api
@@ -1219,7 +1220,7 @@ class CourseEnrollment(models.Model):
assert isinstance(self.course_id, CourseKey)
data = {
'user_id': self.user.id,
'course_id': self.course_id.to_deprecated_string(),
'course_id': text_type(self.course_id),
'mode': self.mode,
}
@@ -1230,7 +1231,7 @@ class CourseEnrollment(models.Model):
tracking_context = tracker.get_tracker().resolve_context()
analytics.track(self.user_id, event_name, {
'category': 'conversion',
'label': self.course_id.to_deprecated_string(),
'label': text_type(self.course_id),
'org': self.course_id.org,
'course': self.course_id.course,
'run': self.course_id.run,
@@ -1303,14 +1304,14 @@ class CourseEnrollment(models.Model):
log.warning(
u"User %s failed to enroll in course %s because enrollment is closed",
user.username,
course_key.to_deprecated_string()
text_type(course_key)
)
raise EnrollmentClosedError
if cls.objects.is_course_full(course):
log.warning(
u"Course %s has reached its maximum enrollment of %d learners. User %s failed to enroll.",
course_key.to_deprecated_string(),
text_type(course_key),
course.max_student_enrollments_allowed,
user.username,
)
@@ -1319,7 +1320,7 @@ class CourseEnrollment(models.Model):
log.warning(
u"User %s attempted to enroll in %s, but they were already enrolled",
user.username,
course_key.to_deprecated_string()
text_type(course_key)
)
if check_access:
raise AlreadyEnrolledError

View File

@@ -14,6 +14,7 @@ from django.test import TestCase
from django.test.client import Client
from django.test.utils import override_settings
from mock import patch
from six import text_type
from social_django.models import UserSocialAuth
from openedx.core.djangoapps.external_auth.models import ExternalAuthMap
@@ -498,7 +499,7 @@ class ExternalAuthShibTest(ModuleStoreTestCase):
Tests the redirects when visiting course-specific URL with @login_required.
Should vary by course depending on its enrollment_domain
"""
TARGET_URL = reverse('courseware', args=[self.course.id.to_deprecated_string()]) # pylint: disable=invalid-name
TARGET_URL = reverse('courseware', args=[text_type(self.course.id)]) # pylint: disable=invalid-name
noshib_response = self.client.get(TARGET_URL, follow=True, HTTP_ACCEPT="text/html")
self.assertEqual(noshib_response.redirect_chain[-1],
(expected_redirect_url('/login?next={url}'.format(url=TARGET_URL)), 302))
@@ -506,7 +507,7 @@ class ExternalAuthShibTest(ModuleStoreTestCase):
.format(platform_name=settings.PLATFORM_NAME)))
self.assertEqual(noshib_response.status_code, 200)
TARGET_URL_SHIB = reverse('courseware', args=[self.shib_course.id.to_deprecated_string()]) # pylint: disable=invalid-name
TARGET_URL_SHIB = reverse('courseware', args=[text_type(self.shib_course.id)]) # pylint: disable=invalid-name
shib_response = self.client.get(**{'path': TARGET_URL_SHIB,
'follow': True,
'REMOTE_USER': self.extauth.external_id,

View File

@@ -21,6 +21,7 @@ from nose.plugins.attrib import attr
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locations import CourseLocator
from pyquery import PyQuery as pq
from six import text_type
import shoppingcart # pylint: disable=import-error
from bulk_email.models import Optout # pylint: disable=import-error
@@ -442,11 +443,11 @@ class DashboardTest(ModuleStoreTestCase):
self.assertEqual(len(optout_object), 1)
# Direct link to course redirect to user dashboard
self.client.get(reverse('courseware', kwargs={"course_id": self.course.id.to_deprecated_string()}))
self.client.get(reverse('courseware', kwargs={"course_id": text_type(self.course.id)}))
log_warning.assert_called_with(
u'User %s cannot access the course %s because payment has not yet been received',
self.user,
unicode(self.course.id),
text_type(self.course.id),
)
# Now re-validating the invoice
@@ -711,7 +712,7 @@ class EnrollmentEventTestMixin(EventTestMixin):
self.mock_tracker.emit.assert_called_once_with( # pylint: disable=maybe-no-member
'edx.course.enrollment.mode_changed',
{
'course_id': course_key.to_deprecated_string(),
'course_id': text_type(course_key),
'user_id': user.pk,
'mode': mode
}
@@ -723,7 +724,7 @@ class EnrollmentEventTestMixin(EventTestMixin):
self.mock_tracker.emit.assert_called_once_with( # pylint: disable=maybe-no-member
'edx.course.enrollment.activated',
{
'course_id': course_key.to_deprecated_string(),
'course_id': text_type(course_key),
'user_id': user.pk,
'mode': CourseMode.DEFAULT_MODE_SLUG
}
@@ -735,7 +736,7 @@ class EnrollmentEventTestMixin(EventTestMixin):
self.mock_tracker.emit.assert_called_once_with( # pylint: disable=maybe-no-member
'edx.course.enrollment.deactivated',
{
'course_id': course_key.to_deprecated_string(),
'course_id': text_type(course_key),
'user_id': user.pk,
'mode': CourseMode.DEFAULT_MODE_SLUG
}
@@ -942,7 +943,7 @@ class ChangeEnrollmentViewTest(ModuleStoreTestCase):
""" Enroll a student in a course. """
response = self.client.post(
reverse('change_enrollment'), {
'course_id': course.id.to_deprecated_string(),
'course_id': text_type(course.id),
'enrollment_action': 'enroll'
}
)

View File

@@ -45,6 +45,7 @@ from provider.oauth2.models import Client
from pytz import UTC
from ratelimitbackend.exceptions import RateLimitException
from requests import HTTPError
from six import text_type
from social_core.backends import oauth as social_oauth
from social_core.exceptions import AuthAlreadyAssociated, AuthException
from social_django import utils as social_utils
@@ -609,7 +610,7 @@ def is_course_blocked(request, redeemed_registration_codes, course_key):
track.views.server_track(
request,
"change-email1-settings",
{"receive_emails": "no", "course": course_key.to_deprecated_string()},
{"receive_emails": "no", "course": text_type(course_key)},
page='dashboard',
)
break

View File

@@ -3,6 +3,7 @@ import logging
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from six import text_type
from util.request import COURSE_REGEX
@@ -51,6 +52,6 @@ def course_context_from_course_id(course_id):
# TODO: Make this accept any CourseKey, and serialize it using .to_string
assert isinstance(course_id, CourseKey)
return {
'course_id': course_id.to_deprecated_string(),
'course_id': text_type(course_id),
'org_id': course_id.org,
}

View File

@@ -34,6 +34,7 @@ from lxml.html.soupparser import fromstring as fromstring_bs # uses Beautiful S
from pyparsing import ParseException
from pytz import UTC
from shapely.geometry import MultiPoint, Point
from six import text_type
import capa.safe_exec as safe_exec
import capa.xqueue_interface as xqueue_interface
@@ -368,7 +369,7 @@ class LoncapaResponse(object):
# self.runtime.track_function('get_demand_hint', event_info)
# This this "feedback hint" event
event_info = dict()
event_info['module_id'] = self.capa_module.location.to_deprecated_string()
event_info['module_id'] = text_type(self.capa_module.location)
event_info['problem_part_id'] = self.id
event_info['trigger_type'] = 'single' # maybe be overwritten by log_extra
event_info['hint_label'] = label

View File

@@ -6,6 +6,7 @@ import os
import os.path
import fs.osfs
import six
from capa.capa_problem import LoncapaProblem, LoncapaSystem
from capa.inputtypes import Status
@@ -84,8 +85,17 @@ def mock_capa_module():
"""
capa response types needs just two things from the capa_module: location and track_function.
"""
def mock_location_text(self):
"""
Mock implementation of __unicode__ or __str__ for the module's location.
"""
return u'i4x://Foo/bar/mock/abc'
capa_module = Mock()
capa_module.location.to_deprecated_string.return_value = 'i4x://Foo/bar/mock/abc'
if six.PY2:
capa_module.location.__unicode__ = mock_location_text
else:
capa_module.location.__str__ = mock_location_text
# The following comes into existence by virtue of being called
# capa_module.runtime.track_function
return capa_module

View File

@@ -52,7 +52,7 @@ class TextInputHintsTest(HintTest):
self.get_hint(u'1_3_1', u'Blue')
self.problem.capa_module.runtime.track_function.assert_called_with(
'edx.problem.hint.feedback_displayed',
{'module_id': 'i4x://Foo/bar/mock/abc',
{'module_id': u'i4x://Foo/bar/mock/abc',
'problem_part_id': '1_2',
'trigger_type': 'single',
'hint_label': u'Correct:',
@@ -225,7 +225,7 @@ class NumericInputHintsTest(HintTest):
self.get_hint(u'1_2_1', u'1.141')
self.problem.capa_module.runtime.track_function.assert_called_with(
'edx.problem.hint.feedback_displayed',
{'module_id': 'i4x://Foo/bar/mock/abc', 'problem_part_id': '1_1', 'trigger_type': 'single',
{'module_id': u'i4x://Foo/bar/mock/abc', 'problem_part_id': '1_1', 'trigger_type': 'single',
'hint_label': u'Nice',
'correctness': True,
'student_answer': [u'1.141'],
@@ -364,7 +364,7 @@ class CheckboxHintsTestTracking(HintTest):
self.problem.capa_module.runtime.track_function.assert_called_with(
'edx.problem.hint.feedback_displayed',
{'hint_label': u'Incorrect:',
'module_id': 'i4x://Foo/bar/mock/abc',
'module_id': u'i4x://Foo/bar/mock/abc',
'problem_part_id': '1_1',
'choice_all': ['choice_0', 'choice_1', 'choice_2'],
'correctness': False,
@@ -427,7 +427,7 @@ class MultpleChoiceHintsTest(HintTest):
self.get_hint(u'1_3_1', u'choice_2')
self.problem.capa_module.runtime.track_function.assert_called_with(
'edx.problem.hint.feedback_displayed',
{'module_id': 'i4x://Foo/bar/mock/abc', 'problem_part_id': '1_2', 'trigger_type': 'single',
{'module_id': u'i4x://Foo/bar/mock/abc', 'problem_part_id': '1_2', 'trigger_type': 'single',
'student_answer': [u'choice_2'], 'correctness': False, 'question_type': 'multiplechoiceresponse',
'hint_label': 'OOPS', 'hints': [{'text': 'Apple is a fruit.'}]}
)
@@ -467,7 +467,7 @@ class MultpleChoiceHintsWithHtmlTest(HintTest):
self.get_hint(u'1_2_1', u'choice_0')
self.problem.capa_module.runtime.track_function.assert_called_with(
'edx.problem.hint.feedback_displayed',
{'module_id': 'i4x://Foo/bar/mock/abc', 'problem_part_id': '1_1', 'trigger_type': 'single',
{'module_id': u'i4x://Foo/bar/mock/abc', 'problem_part_id': '1_1', 'trigger_type': 'single',
'student_answer': [u'choice_0'], 'correctness': False, 'question_type': 'multiplechoiceresponse',
'hint_label': 'Incorrect:', 'hints': [{'text': 'Mushroom <img src="#" ale="#"/>is a fungus, not a fruit.'}]}
)
@@ -500,7 +500,7 @@ class DropdownHintsTest(HintTest):
self.get_hint(u'1_3_1', u'FACES')
self.problem.capa_module.runtime.track_function.assert_called_with(
'edx.problem.hint.feedback_displayed',
{'module_id': 'i4x://Foo/bar/mock/abc', 'problem_part_id': '1_2', 'trigger_type': 'single',
{'module_id': u'i4x://Foo/bar/mock/abc', 'problem_part_id': '1_2', 'trigger_type': 'single',
'student_answer': [u'FACES'], 'correctness': True, 'question_type': 'optionresponse',
'hint_label': 'Correct:', 'hints': [{'text': 'With lots of makeup, doncha know?'}]}
)

View File

@@ -19,6 +19,7 @@ except ImportError:
dog_stats_api = None
from pytz import utc
from django.utils.encoding import smart_text
from six import text_type
from capa.capa_problem import LoncapaProblem, LoncapaSystem
from capa.inputtypes import Status
@@ -246,7 +247,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
# Need the problem location in openendedresponse to send out. Adding
# it to the system here seems like the least clunky way to get it
# there.
self.runtime.set('location', self.location.to_deprecated_string())
self.runtime.set('location', text_type(self.location))
try:
# TODO (vshnayder): move as much as possible of this work and error
@@ -264,7 +265,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
except Exception as err: # pylint: disable=broad-except
msg = u'cannot create LoncapaProblem {loc}: {err}'.format(
loc=self.location.to_deprecated_string(), err=err)
loc=text_type(self.location), err=err)
# TODO (vshnayder): do modules need error handlers too?
# We shouldn't be switching on DEBUG.
if self.runtime.DEBUG:
@@ -286,7 +287,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
problem_text = (
u'<problem><text><span class="inline-error">'
u'Problem {url} has an error:</span>{msg}</text></problem>'.format(
url=self.location.to_deprecated_string(),
url=text_type(self.location),
msg=msg,
)
)
@@ -429,7 +430,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
return self.runtime.render_template('problem_ajax.html', {
'element_id': self.location.html_id(),
'id': self.location.to_deprecated_string(),
'id': text_type(self.location),
'ajax_url': self.runtime.ajax_url,
'current_score': curr_score,
'total_possible': total_possible,
@@ -550,7 +551,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
msg = (
u'[courseware.capa.capa_module] <font size="+1" color="red">'
u'Failed to generate HTML for problem {url}</font>'.format(
url=cgi.escape(self.location.to_deprecated_string()))
url=cgi.escape(text_type(self.location)))
)
msg += u'<p>Error:</p><p><pre>{msg}</pre></p>'.format(msg=cgi.escape(err.message))
msg += u'<p><pre>{tb}</pre></p>'.format(tb=cgi.escape(traceback.format_exc()))
@@ -661,7 +662,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
# Log this demand-hint request. Note that this only logs the last hint requested (although now
# all previously shown hints are still displayed).
event_info = dict()
event_info['module_id'] = self.location.to_deprecated_string()
event_info['module_id'] = text_type(self.location)
event_info['hint_index'] = hint_index
event_info['hint_len'] = len(demand_hints)
event_info['hint_text'] = get_inner_html_from_xpath(demand_hints[hint_index])
@@ -723,7 +724,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
context = {
'problem': content,
'id': self.location.to_deprecated_string(),
'id': text_type(self.location),
'short_id': self.location.html_id(),
'submit_button': submit_button,
'submit_button_submitting': submit_button_submitting,
@@ -1005,7 +1006,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
(and also screen reader text).
"""
event_info = dict()
event_info['problem_id'] = self.location.to_deprecated_string()
event_info['problem_id'] = text_type(self.location)
self.track_function_unmask('showanswer', event_info)
if not self.answer_available():
raise NotFoundError('Answer is not available')
@@ -1159,7 +1160,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
"""
event_info = dict()
event_info['state'] = self.lcp.get_state()
event_info['problem_id'] = self.location.to_deprecated_string()
event_info['problem_id'] = text_type(self.location)
self.lcp.has_saved_answers = False
answers = self.make_dict_of_responses(data)
@@ -1475,7 +1476,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
"""
event_info = dict()
event_info['state'] = self.lcp.get_state()
event_info['problem_id'] = self.location.to_deprecated_string()
event_info['problem_id'] = text_type(self.location)
answers = self.make_dict_of_responses(data)
event_info['answers'] = answers
@@ -1535,7 +1536,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
"""
event_info = dict()
event_info['old_state'] = self.lcp.get_state()
event_info['problem_id'] = self.location.to_deprecated_string()
event_info['problem_id'] = text_type(self.location)
_ = self.runtime.service(self, "i18n").ugettext
if self.closed():
@@ -1600,7 +1601,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
Returns the error messages for exceptions occurring while performing
the rescoring, rather than throwing them.
"""
event_info = {'state': self.lcp.get_state(), 'problem_id': self.location.to_deprecated_string()}
event_info = {'state': self.lcp.get_state(), 'problem_id': text_type(self.location)}
_ = self.runtime.service(self, "i18n").ugettext

View File

@@ -8,6 +8,7 @@ import logging
from lazy import lazy
from lxml import etree
from pkg_resources import resource_string
from six import text_type
from opaque_keys.edx.locator import BlockUsageLocator
from xblock.fields import ReferenceList, Scope, String
@@ -338,12 +339,12 @@ class ConditionalDescriptor(ConditionalFields, SequenceDescriptor, StudioEditabl
if self.show_tag_list:
show_str = u'<{tag_name} sources="{sources}" />'.format(
tag_name='show', sources=';'.join(location.to_deprecated_string() for location in self.show_tag_list))
tag_name='show', sources=';'.join(text_type(location) for location in self.show_tag_list))
xml_object.append(etree.fromstring(show_str))
# Overwrite the original sources attribute with the value from sources_list, as
# Locations may have been changed to Locators.
stringified_sources_list = map(lambda loc: loc.to_deprecated_string(), self.sources_list)
stringified_sources_list = map(lambda loc: text_type(loc), self.sources_list)
self.xml_attributes['sources'] = ';'.join(stringified_sources_list)
self.xml_attributes[self.conditional_attr] = self.conditional_value
self.xml_attributes['message'] = self.conditional_message

View File

@@ -13,6 +13,7 @@ from lazy import lazy
from lxml import etree
from opaque_keys.edx.locator import LibraryLocator
from pkg_resources import resource_string
from six import text_type
from webob import Response
from xblock.core import XBlock
from xblock.fields import Integer, List, Scope, String
@@ -326,7 +327,7 @@ class LibraryContentModule(LibraryContentFields, XModule, StudioEditableModule):
rendered_child = displayable.render(STUDENT_VIEW, child_context)
fragment.add_frag_resources(rendered_child)
contents.append({
'id': displayable.location.to_deprecated_string(),
'id': text_type(displayable.location),
'content': rendered_child.content,
})

View File

@@ -66,6 +66,7 @@ from pytz import UTC
from lxml import etree
from oauthlib.oauth1.rfc5849 import signature
from pkg_resources import resource_string
from six import text_type
from webob import Response
from xblock.core import List, Scope, String, XBlock
from xblock.fields import Boolean, Float
@@ -532,7 +533,7 @@ class LTIModule(LTIFields, LTI20ModuleMixin, XModule):
context_id is an opaque identifier that uniquely identifies the context (e.g., a course)
that contains the link being launched.
"""
return self.course_id.to_deprecated_string()
return text_type(self.course_id)
@property
def role(self):
@@ -557,8 +558,8 @@ class LTIModule(LTIFields, LTI20ModuleMixin, XModule):
"""
client = oauthlib.oauth1.Client(
client_key=unicode(client_key),
client_secret=unicode(client_secret)
client_key=text_type(client_key),
client_secret=text_type(client_secret)
)
# Must have parameters for correct signing from LTI:

View File

@@ -11,6 +11,7 @@ from datetime import datetime
from lxml import etree
from pkg_resources import resource_string
from pytz import UTC
from six import text_type
from xblock.completable import XBlockCompletionMode
from xblock.core import XBlock
from xblock.fields import Boolean, Integer, List, Scope, String
@@ -311,7 +312,7 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
params = {
'items': self._render_student_view_for_items(context, display_items, fragment),
'element_id': self.location.html_id(),
'item_id': self.location.to_deprecated_string(),
'item_id': text_type(self.location),
'position': self.position,
'tag': self.location.category,
'ajax_url': self.system.ajax_url,
@@ -391,7 +392,7 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
'content': rendered_item.content,
'page_title': getattr(item, 'tooltip_title', ''),
'type': item_type,
'id': usage_id.to_deprecated_string(),
'id': text_type(usage_id),
'bookmarked': is_bookmarked,
'path': " > ".join(display_names + [item.display_name_with_default]),
}

View File

@@ -16,6 +16,7 @@ from xmodule.validation import StudioValidation, StudioValidationMessage
from xmodule.modulestore.inheritance import UserPartitionList
from lxml import etree
from six import text_type
from xblock.core import XBlock
from xblock.fields import Scope, Integer, String, ReferenceValueDict
@@ -225,7 +226,7 @@ class SplitTestModule(SplitTestFields, XModule, StudioEditableModule):
updated_group_id = [g_id for g_id, loc in self.group_id_to_child.items() if loc == child_location][0]
inactive_contents.append({
'group_name': _(u'{group_name} (inactive)').format(group_name=group_name),
'id': child.location.to_deprecated_string(),
'id': text_type(child.location),
'content': rendered_child.content,
'group_id': updated_group_id,
})
@@ -233,7 +234,7 @@ class SplitTestModule(SplitTestFields, XModule, StudioEditableModule):
active_contents.append({
'group_name': group_name,
'id': child.location.to_deprecated_string(),
'id': text_type(child.location),
'content': rendered_child.content,
'group_id': updated_group_id,
})
@@ -332,7 +333,7 @@ class SplitTestModule(SplitTestFields, XModule, StudioEditableModule):
Record in the tracking logs which child was rendered
"""
# TODO: use publish instead, when publish is wired to the tracking logs
self.system.track_function('xblock.split_test.child_render', {'child_id': self.child.scope_ids.usage_id.to_deprecated_string()})
self.system.track_function('xblock.split_test.child_render', {'child_id': text_type(self.child.scope_ids.usage_id)})
return Response()
def get_icon_class(self):
@@ -394,7 +395,7 @@ class SplitTestDescriptor(SplitTestFields, SequenceDescriptor, StudioEditableDes
renderable_groups = {}
# json.dumps doesn't know how to handle Location objects
for group in self.group_id_to_child:
renderable_groups[group] = self.group_id_to_child[group].to_deprecated_string()
renderable_groups[group] = text_type(self.group_id_to_child[group])
xml_object.set('group_id_to_child', json.dumps(renderable_groups))
xml_object.set('user_partition_id', str(self.user_partition_id))
for child in self.get_children():

View File

@@ -5,6 +5,7 @@ import logging
from abc import ABCMeta
from django.core.files.storage import get_storage_class
from six import text_type
from xblock.fields import List
from openedx.core.lib.api.plugins import PluginError
@@ -266,7 +267,7 @@ class TabFragmentViewMixin(object):
# If not, then use the generic course tab URL
def link_func(course, reverse_func):
""" Returns a function that returns the course tab's URL. """
return reverse_func("course_tab_view", args=[course.id.to_deprecated_string(), self.type])
return reverse_func("course_tab_view", args=[text_type(course.id), self.type])
return link_func
@@ -304,7 +305,7 @@ class StaticTab(CourseTab):
def __init__(self, tab_dict=None, name=None, url_slug=None):
def link_func(course, reverse_func):
""" Returns a function that returns the static tab's URL. """
return reverse_func(self.type, args=[course.id.to_deprecated_string(), self.url_slug])
return reverse_func(self.type, args=[text_type(course.id), self.url_slug])
self.url_slug = tab_dict.get('url_slug') if tab_dict else url_slug
@@ -612,7 +613,7 @@ def course_reverse_func_from_name_func(reverse_name_func):
"""
return lambda course, reverse_url_func: reverse_url_func(
reverse_name_func(course),
args=[course.id.to_deprecated_string()]
args=[text_type(course.id)]
)

View File

@@ -17,6 +17,7 @@ import ddt
from django.utils.encoding import smart_text
from lxml import etree
from mock import Mock, patch, DEFAULT
import six
import webob
from webob.multidict import MultiDict
@@ -1533,10 +1534,19 @@ class CapaModuleTest(unittest.TestCase):
self.assertFalse(result['should_enable_next_hint'])
def test_demand_hint_logging(self):
def mock_location_text(self):
"""
Mock implementation of __unicode__ or __str__ for the module's location.
"""
return u'i4x://edX/capa_test/problem/meh'
module = CapaFactory.create(xml=self.demand_xml)
# Re-mock the module_id to a fixed string, so we can check the logging
module.location = Mock(module.location)
module.location.to_deprecated_string.return_value = 'i4x://edX/capa_test/problem/meh'
if six.PY2:
module.location.__unicode__ = mock_location_text
else:
module.location.__str__ = mock_location_text
with patch.object(module.runtime, 'publish') as mock_track_function:
module.get_problem_html()