Merge pull request #19749 from edx/unicode8
fix unicode strings in openedx/ part 1
This commit is contained in:
@@ -56,14 +56,14 @@ def _get_variables_from_context(context, tag_name):
|
||||
|
||||
if request is None:
|
||||
raise template.VariableDoesNotExist(
|
||||
'The {0} template tag requires a "request" to be present in the template context. Consider using '
|
||||
'"emulate_http_request" if you are rendering the template in a celery task.'.format(tag_name)
|
||||
u'The {0} template tag requires a "request" to be present in the template context. Consider using '
|
||||
u'"emulate_http_request" if you are rendering the template in a celery task.'.format(tag_name)
|
||||
)
|
||||
|
||||
message = context.get('message')
|
||||
if message is None:
|
||||
raise template.VariableDoesNotExist(
|
||||
'The {0} template tag requires a "message" to be present in the template context.'.format(tag_name)
|
||||
u'The {0} template tag requires a "message" to be present in the template context.'.format(tag_name)
|
||||
)
|
||||
|
||||
return request.site, request.user, message
|
||||
@@ -87,7 +87,7 @@ def google_analytics_tracking_pixel(context):
|
||||
image_url = _get_google_analytics_tracking_url(context)
|
||||
if image_url is not None:
|
||||
return mark_safe(
|
||||
HTML('<img src="{0}" alt="" role="presentation" aria-hidden="true" />').format(HTML(image_url))
|
||||
HTML(u'<img src="{0}" alt="" role="presentation" aria-hidden="true" />').format(HTML(image_url))
|
||||
)
|
||||
else:
|
||||
return ''
|
||||
|
||||
@@ -6,6 +6,7 @@ from django.urls import reverse
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from openedx.core.djangoapps.api_admin.models import ApiAccessConfig, ApiAccessRequest
|
||||
from openedx.core.djangolib.markup import HTML, Text
|
||||
|
||||
|
||||
@admin.register(ApiAccessRequest)
|
||||
@@ -30,10 +31,10 @@ class ApiAccessRequestAdmin(admin.ModelAdmin):
|
||||
)
|
||||
},),
|
||||
('Status', {
|
||||
'description': _(
|
||||
'Once you have approved this request, go to {catalog_admin_url} to set up a catalog for this user.'
|
||||
).format(
|
||||
catalog_admin_url='<a href="{0}">{0}</a>'.format(reverse('api_admin:catalog-search'))
|
||||
'description': Text(_(
|
||||
u'Once you have approved this request, go to {catalog_admin_url} to set up a catalog for this user.'
|
||||
)).format(
|
||||
catalog_admin_url=HTML(u'<a href="{0}">{0}</a>').format(reverse('api_admin:catalog-search'))
|
||||
),
|
||||
'fields': ('status',),
|
||||
}),
|
||||
|
||||
@@ -68,7 +68,7 @@ class ViewersField(forms.Field):
|
||||
nonexistent_users.append(username)
|
||||
if nonexistent_users:
|
||||
raise forms.ValidationError(
|
||||
_('The following users do not exist: {usernames}.').format(usernames=nonexistent_users)
|
||||
_(u'The following users do not exist: {usernames}.').format(usernames=nonexistent_users)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -106,13 +106,13 @@ class ApiAccessRequest(TimeStampedModel):
|
||||
|
||||
def approve(self):
|
||||
"""Approve this request."""
|
||||
log.info('Approving API request from user [%s].', self.user.id)
|
||||
log.info(u'Approving API request from user [%s].', self.user.id)
|
||||
self.status = self.APPROVED
|
||||
self.save()
|
||||
|
||||
def deny(self):
|
||||
"""Deny this request."""
|
||||
log.info('Denying API request from user [%s].', self.user.id)
|
||||
log.info(u'Denying API request from user [%s].', self.user.id)
|
||||
self.status = self.DENIED
|
||||
self.save()
|
||||
|
||||
@@ -161,14 +161,14 @@ def _send_new_pending_email(instance):
|
||||
message = render_to_string('api_admin/api_access_request_email_new_request.txt', context)
|
||||
try:
|
||||
send_mail(
|
||||
_('API access request from {company}').format(company=instance.company_name),
|
||||
_(u'API access request from {company}').format(company=instance.company_name),
|
||||
message,
|
||||
settings.API_ACCESS_FROM_EMAIL,
|
||||
[settings.API_ACCESS_MANAGER_EMAIL],
|
||||
fail_silently=False
|
||||
)
|
||||
except SMTPException:
|
||||
log.exception('Error sending API user notification email for request [%s].', instance.id)
|
||||
log.exception(u'Error sending API user notification email for request [%s].', instance.id)
|
||||
|
||||
|
||||
def _send_decision_email(instance):
|
||||
@@ -204,7 +204,7 @@ def _send_decision_email(instance):
|
||||
)
|
||||
instance.contacted = True
|
||||
except SMTPException:
|
||||
log.exception('Error sending API user notification email for request [%s].', instance.id)
|
||||
log.exception(u'Error sending API user notification email for request [%s].', instance.id)
|
||||
|
||||
|
||||
class Catalog(models.Model):
|
||||
|
||||
@@ -33,7 +33,7 @@ class ViewersWidgetTest(TestCase):
|
||||
"""
|
||||
dummy_string_value = 'staff, verified'
|
||||
input_field_name = 'viewers'
|
||||
expected_widget_html = '<input type="text" name="{input_field_name}" value="{serialized_value}" />'.format(
|
||||
expected_widget_html = u'<input type="text" name="{input_field_name}" value="{serialized_value}" />'.format(
|
||||
input_field_name=input_field_name,
|
||||
serialized_value=dummy_string_value,
|
||||
)
|
||||
|
||||
@@ -143,7 +143,7 @@ class ApiAccessRequestSignalTests(TestCase):
|
||||
|
||||
# Verify that initial save logs email errors properly
|
||||
mock_model_log_exception.assert_called_once_with(
|
||||
'Error sending API user notification email for request [%s].', self.api_access_request.id
|
||||
u'Error sending API user notification email for request [%s].', self.api_access_request.id
|
||||
)
|
||||
# Verify object saved
|
||||
self.assertIsNotNone(self.api_access_request.id)
|
||||
@@ -153,7 +153,7 @@ class ApiAccessRequestSignalTests(TestCase):
|
||||
self.api_access_request.approve()
|
||||
# Verify that updating request status logs email errors properly
|
||||
mock_model_log_exception.assert_called_once_with(
|
||||
'Error sending API user notification email for request [%s].', self.api_access_request.id
|
||||
u'Error sending API user notification email for request [%s].', self.api_access_request.id
|
||||
)
|
||||
# Verify object saved
|
||||
self.assertEqual(self.api_access_request.status, ApiAccessRequest.APPROVED)
|
||||
|
||||
@@ -9,6 +9,7 @@ from django.utils.html import format_html
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangolib.markup import HTML, Text
|
||||
|
||||
|
||||
class TermsOfServiceCheckboxInput(CheckboxInput):
|
||||
@@ -27,15 +28,15 @@ class TermsOfServiceCheckboxInput(CheckboxInput):
|
||||
|
||||
# Translators: link_start and link_end are HTML tags for a link to the terms of service.
|
||||
# platform_name is the name of this Open edX installation.
|
||||
label = _(
|
||||
'I, and my organization, accept the {link_start}{platform_name} API Terms of Service{link_end}.'
|
||||
).format(
|
||||
label = Text(_(
|
||||
u'I, and my organization, accept the {link_start}{platform_name} API Terms of Service{link_end}.'
|
||||
)).format(
|
||||
platform_name=configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME),
|
||||
link_start='<a href="{url}" target="_blank">'.format(url=reverse('api_admin:api-tos')),
|
||||
link_end='</a>',
|
||||
link_start=HTML(u'<a href="{url}" target="_blank">').format(url=reverse('api_admin:api-tos')),
|
||||
link_end=HTML('</a>'),
|
||||
)
|
||||
|
||||
html = u'<input{{}} /> <label class="tos-checkbox-label" for="{id}">{label}</label>'.format(
|
||||
html = HTML(u'<input{{}} /> <label class="tos-checkbox-label" for="{id}">{label}</label>').format(
|
||||
id=final_attrs['id'],
|
||||
label=label
|
||||
)
|
||||
|
||||
@@ -36,7 +36,7 @@ class AccessTokenExchangeForm(ScopeMixin, OAuthForm):
|
||||
raise OAuthValidationError(
|
||||
{
|
||||
"error": "invalid_request",
|
||||
"error_description": "{} is required".format(field_name),
|
||||
"error_description": u"{} is required".format(field_name),
|
||||
}
|
||||
)
|
||||
return field_val
|
||||
@@ -62,7 +62,7 @@ class AccessTokenExchangeForm(ScopeMixin, OAuthForm):
|
||||
raise OAuthValidationError(
|
||||
{
|
||||
"error": "invalid_request",
|
||||
"error_description": "{} is not a supported provider".format(backend.name),
|
||||
"error_description": u"{} is not a supported provider".format(backend.name),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -75,7 +75,7 @@ class AccessTokenExchangeForm(ScopeMixin, OAuthForm):
|
||||
raise OAuthValidationError(
|
||||
{
|
||||
"error": "invalid_client",
|
||||
"error_description": "{} is not a valid client_id".format(client_id),
|
||||
"error_description": u"{} is not a valid client_id".format(client_id),
|
||||
}
|
||||
)
|
||||
if client.client_type not in [provider.constants.PUBLIC, Application.CLIENT_PUBLIC]:
|
||||
@@ -84,7 +84,7 @@ class AccessTokenExchangeForm(ScopeMixin, OAuthForm):
|
||||
# invalid_client isn't really the right code, but this mirrors
|
||||
# https://github.com/edx/django-oauth2-provider/blob/edx/provider/oauth2/forms.py#L331
|
||||
"error": "invalid_client",
|
||||
"error_description": "{} is not a public client".format(client_id),
|
||||
"error_description": u"{} is not a public client".format(client_id),
|
||||
}
|
||||
)
|
||||
self.cleaned_data["client"] = client
|
||||
|
||||
@@ -181,7 +181,7 @@ class TestLoginWithAccessTokenView(TestCase):
|
||||
Calls the login_with_access_token endpoint and verifies the response given the expected values.
|
||||
"""
|
||||
url = reverse("login_with_access_token")
|
||||
response = self.client.post(url, HTTP_AUTHORIZATION="Bearer {0}".format(access_token))
|
||||
response = self.client.post(url, HTTP_AUTHORIZATION=b"Bearer {0}".format(access_token))
|
||||
self.assertEqual(response.status_code, expected_status_code)
|
||||
if expected_cookie_name:
|
||||
self.assertIn(expected_cookie_name, response.cookies)
|
||||
|
||||
@@ -61,7 +61,7 @@ class AccessTokenExchangeTestMixin(ThirdPartyOAuthTestMixin):
|
||||
for field in ["access_token", "client_id"]:
|
||||
data = dict(self.data)
|
||||
del data[field]
|
||||
self._assert_error(data, "invalid_request", "{} is required".format(field))
|
||||
self._assert_error(data, "invalid_request", u"{} is required".format(field))
|
||||
|
||||
def test_invalid_client(self):
|
||||
self.data["client_id"] = "nonexistent_client"
|
||||
@@ -77,7 +77,7 @@ class AccessTokenExchangeTestMixin(ThirdPartyOAuthTestMixin):
|
||||
self._assert_error(
|
||||
self.data,
|
||||
"invalid_client",
|
||||
"{}_confidential is not a public client".format(self.client_id),
|
||||
u"{}_confidential is not a public client".format(self.client_id),
|
||||
)
|
||||
|
||||
def test_inactive_user(self):
|
||||
|
||||
@@ -152,7 +152,7 @@ def update_xblocks_cache(course_id):
|
||||
# Ideally we'd like to accept a CourseLocator; however, CourseLocator is not JSON-serializable (by default) so
|
||||
# Celery's delayed tasks fail to start. For this reason, callers should pass the course key as a Unicode string.
|
||||
if not isinstance(course_id, basestring):
|
||||
raise ValueError('course_id must be a string. {} is not acceptable.'.format(type(course_id)))
|
||||
raise ValueError(u'course_id must be a string. {} is not acceptable.'.format(type(course_id)))
|
||||
|
||||
course_key = CourseKey.from_string(course_id)
|
||||
log.info(u'Starting XBlockCaches update for course_key: %s', course_id)
|
||||
|
||||
@@ -107,7 +107,7 @@ class CacheBackedAuthenticationMiddleware(AuthenticationMiddleware):
|
||||
request.user = User.get_cached(session_user_id)
|
||||
if request.user.id != session_user_id:
|
||||
log.error(
|
||||
"CacheBackedAuthenticationMiddleware cached user '%s' does not match requested user '%s'.",
|
||||
u"CacheBackedAuthenticationMiddleware cached user '%s' does not match requested user '%s'.",
|
||||
request.user.id,
|
||||
session_user_id,
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ class Command(BaseCommand):
|
||||
user = User.objects.get(username=username)
|
||||
except User.DoesNotExist:
|
||||
logger.exception(
|
||||
'Failed to create API client. Service user {username} does not exist.'.format(username=username)
|
||||
u'Failed to create API client. Service user {username} does not exist.'.format(username=username)
|
||||
)
|
||||
raise
|
||||
|
||||
@@ -49,7 +49,7 @@ class Command(BaseCommand):
|
||||
for site in Site.objects.all():
|
||||
site_config = getattr(site, 'configuration', None)
|
||||
if site_config is None or not site_config.get_value('COURSE_CATALOG_API_URL'):
|
||||
logger.info('Skipping site {domain}. No configuration.'.format(domain=site.domain))
|
||||
logger.info(u'Skipping site {domain}. No configuration.'.format(domain=site.domain))
|
||||
cache.set(SITE_PROGRAM_UUIDS_CACHE_KEY_TPL.format(domain=site.domain), [], None)
|
||||
cache.set(SITE_PATHWAY_IDS_CACHE_KEY_TPL.format(domain=site.domain), [], None)
|
||||
continue
|
||||
@@ -67,26 +67,26 @@ class Command(BaseCommand):
|
||||
programs.update(new_programs)
|
||||
pathways.update(new_pathways)
|
||||
|
||||
logger.info('Caching UUIDs for {total} programs for site {site_name}.'.format(
|
||||
logger.info(u'Caching UUIDs for {total} programs for site {site_name}.'.format(
|
||||
total=len(uuids),
|
||||
site_name=site.domain,
|
||||
))
|
||||
cache.set(SITE_PROGRAM_UUIDS_CACHE_KEY_TPL.format(domain=site.domain), uuids, None)
|
||||
|
||||
pathway_ids = new_pathways.keys()
|
||||
logger.info('Caching ids for {total} pathways for site {site_name}.'.format(
|
||||
logger.info(u'Caching ids for {total} pathways for site {site_name}.'.format(
|
||||
total=len(pathway_ids),
|
||||
site_name=site.domain,
|
||||
))
|
||||
cache.set(SITE_PATHWAY_IDS_CACHE_KEY_TPL.format(domain=site.domain), pathway_ids, None)
|
||||
|
||||
successful_programs = len(programs)
|
||||
logger.info('Caching details for {successful_programs} programs.'.format(
|
||||
logger.info(u'Caching details for {successful_programs} programs.'.format(
|
||||
successful_programs=successful_programs))
|
||||
cache.set_many(programs, None)
|
||||
|
||||
successful_pathways = len(pathways)
|
||||
logger.info('Caching details for {successful_pathways} pathways.'.format(
|
||||
logger.info(u'Caching details for {successful_pathways} pathways.'.format(
|
||||
successful_pathways=successful_pathways))
|
||||
cache.set_many(pathways, None)
|
||||
|
||||
@@ -105,13 +105,13 @@ class Command(BaseCommand):
|
||||
'uuids_only': 1,
|
||||
}
|
||||
|
||||
logger.info('Requesting program UUIDs for {domain}.'.format(domain=site.domain))
|
||||
logger.info(u'Requesting program UUIDs for {domain}.'.format(domain=site.domain))
|
||||
uuids = client.programs.get(**querystring)
|
||||
except: # pylint: disable=bare-except
|
||||
logger.exception('Failed to retrieve program UUIDs for site: {domain}.'.format(domain=site.domain))
|
||||
logger.exception(u'Failed to retrieve program UUIDs for site: {domain}.'.format(domain=site.domain))
|
||||
failure = True
|
||||
|
||||
logger.info('Received {total} UUIDs for site {domain}'.format(
|
||||
logger.info(u'Received {total} UUIDs for site {domain}'.format(
|
||||
total=len(uuids),
|
||||
domain=site.domain
|
||||
))
|
||||
@@ -123,13 +123,13 @@ class Command(BaseCommand):
|
||||
for uuid in uuids:
|
||||
try:
|
||||
cache_key = PROGRAM_CACHE_KEY_TPL.format(uuid=uuid)
|
||||
logger.info('Requesting details for program {uuid}.'.format(uuid=uuid))
|
||||
logger.info(u'Requesting details for program {uuid}.'.format(uuid=uuid))
|
||||
program = client.programs(uuid).get(exclude_utm=1)
|
||||
# pathways get added in process_pathways
|
||||
program['pathway_ids'] = []
|
||||
programs[cache_key] = program
|
||||
except: # pylint: disable=bare-except
|
||||
logger.exception('Failed to retrieve details for program {uuid}.'.format(uuid=uuid))
|
||||
logger.exception(u'Failed to retrieve details for program {uuid}.'.format(uuid=uuid))
|
||||
failure = True
|
||||
continue
|
||||
return programs, failure
|
||||
@@ -140,7 +140,7 @@ class Command(BaseCommand):
|
||||
"""
|
||||
pathways = []
|
||||
failure = False
|
||||
logger.info('Requesting pathways for {domain}.'.format(domain=site.domain))
|
||||
logger.info(u'Requesting pathways for {domain}.'.format(domain=site.domain))
|
||||
try:
|
||||
next_page = 1
|
||||
while next_page:
|
||||
@@ -150,11 +150,11 @@ class Command(BaseCommand):
|
||||
|
||||
except: # pylint: disable=bare-except
|
||||
logger.exception(
|
||||
msg='Failed to retrieve pathways for site: {domain}.'.format(domain=site.domain),
|
||||
msg=u'Failed to retrieve pathways for site: {domain}.'.format(domain=site.domain),
|
||||
)
|
||||
failure = True
|
||||
|
||||
logger.info('Received {total} pathways for site {domain}'.format(
|
||||
logger.info(u'Received {total} pathways for site {domain}'.format(
|
||||
total=len(pathways),
|
||||
domain=site.domain
|
||||
))
|
||||
@@ -185,6 +185,6 @@ class Command(BaseCommand):
|
||||
del pathway['programs']
|
||||
pathway['program_uuids'] = uuids
|
||||
except: # pylint: disable=bare-except
|
||||
logger.exception('Failed to process pathways for {domain}'.format(domain=site.domain))
|
||||
logger.exception(u'Failed to process pathways for {domain}'.format(domain=site.domain))
|
||||
failure = True
|
||||
return processed_pathways, programs, failure
|
||||
|
||||
@@ -65,10 +65,10 @@ class Command(BaseCommand):
|
||||
page_size=page_size
|
||||
)
|
||||
except Exception as err:
|
||||
raise CommandError('Error creating CatalogIntegration: {}'.format(err))
|
||||
raise CommandError(u'Error creating CatalogIntegration: {}'.format(err))
|
||||
|
||||
self.stdout.write(self.style.SUCCESS(
|
||||
'Successfully created CatalogIntegration enabled={} url={} service_username={}').format(
|
||||
u'Successfully created CatalogIntegration enabled={} url={} service_username={}').format(
|
||||
catalog_integration.enabled,
|
||||
catalog_integration.internal_api_url,
|
||||
catalog_integration.service_username
|
||||
|
||||
@@ -42,7 +42,7 @@ class Command(BaseCommand):
|
||||
num_runs_found_in_course_overview += 1
|
||||
except CourseOverview.DoesNotExist:
|
||||
log.info(
|
||||
'[sync_course_runs] course overview record not found for course run: %s',
|
||||
u'[sync_course_runs] course overview record not found for course run: %s',
|
||||
unicode(course_key),
|
||||
)
|
||||
continue
|
||||
@@ -60,10 +60,10 @@ class Command(BaseCommand):
|
||||
|
||||
log.info(
|
||||
'[sync_course_runs] '
|
||||
'course runs found in catalog: %d, '
|
||||
'course runs found in course overview: %d, '
|
||||
'course runs not found in course overview: %d, '
|
||||
'course overviews updated: %d',
|
||||
u'course runs found in catalog: %d, '
|
||||
u'course runs found in course overview: %d, '
|
||||
u'course runs not found in course overview: %d, '
|
||||
u'course overviews updated: %d',
|
||||
num_runs_found_in_catalog,
|
||||
num_runs_found_in_course_overview,
|
||||
num_runs_found_in_catalog - num_runs_found_in_course_overview,
|
||||
|
||||
@@ -74,7 +74,7 @@ class TestSyncCourseRunsCommand(ModuleStoreTestCase):
|
||||
call_command('sync_course_runs')
|
||||
|
||||
mock_log_info.assert_any_call(
|
||||
'[sync_course_runs] course overview record not found for course run: %s',
|
||||
u'[sync_course_runs] course overview record not found for course run: %s',
|
||||
nonexistent_course_run['key'],
|
||||
)
|
||||
updated_marketing_url = CourseOverview.objects.get(id=self.course.id).marketing_url
|
||||
@@ -88,8 +88,8 @@ class TestSyncCourseRunsCommand(ModuleStoreTestCase):
|
||||
def _assert_logs(num_updates):
|
||||
mock_log_info.assert_any_call('[sync_course_runs] Fetching course runs from catalog service.')
|
||||
mock_log_info.assert_any_call(
|
||||
'[sync_course_runs] course runs found in catalog: %d, course runs found in course overview: %d,'
|
||||
' course runs not found in course overview: %d, course overviews updated: %d',
|
||||
u'[sync_course_runs] course runs found in catalog: %d, course runs found in course overview: %d,'
|
||||
u' course runs not found in course overview: %d, course overviews updated: %d',
|
||||
3,
|
||||
1,
|
||||
2,
|
||||
|
||||
@@ -74,7 +74,7 @@ class TestGetPrograms(CacheIsolationTestCase):
|
||||
# empty list and log a warning.
|
||||
self.assertEqual(get_programs(self.site), [])
|
||||
mock_warning.assert_called_once_with(
|
||||
'Failed to get program UUIDs from the cache for site {}.'.format(self.site.domain)
|
||||
u'Failed to get program UUIDs from the cache for site {}.'.format(self.site.domain)
|
||||
)
|
||||
mock_warning.reset_mock()
|
||||
|
||||
@@ -95,7 +95,7 @@ class TestGetPrograms(CacheIsolationTestCase):
|
||||
)
|
||||
mock_info.assert_called_with('Failed to get details for 1 programs. Retrying.')
|
||||
mock_warning.assert_called_with(
|
||||
'Failed to get details for program {uuid} from the cache.'.format(uuid=programs[2]['uuid'])
|
||||
u'Failed to get details for program {uuid} from the cache.'.format(uuid=programs[2]['uuid'])
|
||||
)
|
||||
mock_warning.reset_mock()
|
||||
|
||||
@@ -169,7 +169,7 @@ class TestGetPrograms(CacheIsolationTestCase):
|
||||
|
||||
self.assertEqual(get_programs(self.site, uuid=expected_uuid), None)
|
||||
mock_warning.assert_called_once_with(
|
||||
'Failed to get details for program {uuid} from the cache.'.format(uuid=expected_uuid)
|
||||
u'Failed to get details for program {uuid} from the cache.'.format(uuid=expected_uuid)
|
||||
)
|
||||
mock_warning.reset_mock()
|
||||
|
||||
@@ -226,7 +226,7 @@ class TestGetPathways(CacheIsolationTestCase):
|
||||
)
|
||||
mock_info.assert_called_with('Failed to get details for 1 pathways. Retrying.')
|
||||
mock_warning.assert_called_with(
|
||||
'Failed to get details for credit pathway {id} from the cache.'.format(id=pathways[2]['id'])
|
||||
u'Failed to get details for credit pathway {id} from the cache.'.format(id=pathways[2]['id'])
|
||||
)
|
||||
mock_warning.reset_mock()
|
||||
|
||||
@@ -300,7 +300,7 @@ class TestGetPathways(CacheIsolationTestCase):
|
||||
|
||||
self.assertEqual(get_pathways(self.site, pathway_id=expected_id), None)
|
||||
mock_warning.assert_called_once_with(
|
||||
'Failed to get details for credit pathway {id} from the cache.'.format(id=expected_id)
|
||||
u'Failed to get details for credit pathway {id} from the cache.'.format(id=expected_id)
|
||||
)
|
||||
mock_warning.reset_mock()
|
||||
|
||||
@@ -433,7 +433,7 @@ class TestGetCourseRuns(CatalogIntegrationMixin, TestCase):
|
||||
|
||||
data = get_course_runs()
|
||||
mock_log_error.any_call(
|
||||
'Catalog service user with username [%s] does not exist. Course runs will not be retrieved.',
|
||||
u'Catalog service user with username [%s] does not exist. Course runs will not be retrieved.',
|
||||
catalog_integration.service_username,
|
||||
)
|
||||
self.assertFalse(mock_get_edx_api_data.called)
|
||||
|
||||
@@ -58,8 +58,8 @@ def check_catalog_integration_and_get_user(error_message_field):
|
||||
user = catalog_integration.get_service_user()
|
||||
except ObjectDoesNotExist:
|
||||
logger.error(
|
||||
'Catalog service user with username [{username}] does not exist. '
|
||||
'{field} will not be retrieved.'.format(
|
||||
u'Catalog service user with username [{username}] does not exist. '
|
||||
u'{field} will not be retrieved.'.format(
|
||||
username=catalog_integration.service_username,
|
||||
field=error_message_field,
|
||||
)
|
||||
@@ -68,7 +68,7 @@ def check_catalog_integration_and_get_user(error_message_field):
|
||||
return user, catalog_integration
|
||||
else:
|
||||
logger.error(
|
||||
'Unable to retrieve details about {field} because Catalog Integration is not enabled'.format(
|
||||
u'Unable to retrieve details about {field} because Catalog Integration is not enabled'.format(
|
||||
field=error_message_field,
|
||||
)
|
||||
)
|
||||
@@ -90,7 +90,7 @@ def get_programs(site, uuid=None):
|
||||
list of dict, representing programs.
|
||||
dict, if a specific program is requested.
|
||||
"""
|
||||
missing_details_msg_tpl = 'Failed to get details for program {uuid} from the cache.'
|
||||
missing_details_msg_tpl = u'Failed to get details for program {uuid} from the cache.'
|
||||
|
||||
if uuid:
|
||||
program = cache.get(PROGRAM_CACHE_KEY_TPL.format(uuid=uuid))
|
||||
@@ -100,7 +100,7 @@ def get_programs(site, uuid=None):
|
||||
return program
|
||||
uuids = cache.get(SITE_PROGRAM_UUIDS_CACHE_KEY_TPL.format(domain=site.domain), [])
|
||||
if not uuids:
|
||||
logger.warning('Failed to get program UUIDs from the cache for site {}.'.format(site.domain))
|
||||
logger.warning(u'Failed to get program UUIDs from the cache for site {}.'.format(site.domain))
|
||||
|
||||
programs = cache.get_many([PROGRAM_CACHE_KEY_TPL.format(uuid=uuid) for uuid in uuids])
|
||||
programs = list(programs.values())
|
||||
@@ -116,7 +116,7 @@ def get_programs(site, uuid=None):
|
||||
missing_uuids = set(uuids) - set(program['uuid'] for program in programs)
|
||||
if missing_uuids:
|
||||
logger.info(
|
||||
'Failed to get details for {count} programs. Retrying.'.format(count=len(missing_uuids))
|
||||
u'Failed to get details for {count} programs. Retrying.'.format(count=len(missing_uuids))
|
||||
)
|
||||
|
||||
retried_programs = cache.get_many([PROGRAM_CACHE_KEY_TPL.format(uuid=uuid) for uuid in missing_uuids])
|
||||
@@ -171,7 +171,7 @@ def get_pathways(site, pathway_id=None):
|
||||
list of dict, representing pathways.
|
||||
dict, if a specific pathway is requested.
|
||||
"""
|
||||
missing_details_msg_tpl = 'Failed to get details for credit pathway {id} from the cache.'
|
||||
missing_details_msg_tpl = u'Failed to get details for credit pathway {id} from the cache.'
|
||||
|
||||
if pathway_id:
|
||||
pathway = cache.get(PATHWAY_CACHE_KEY_TPL.format(id=pathway_id))
|
||||
@@ -197,7 +197,7 @@ def get_pathways(site, pathway_id=None):
|
||||
missing_ids = set(pathway_ids) - set(pathway['id'] for pathway in pathways)
|
||||
if missing_ids:
|
||||
logger.info(
|
||||
'Failed to get details for {count} pathways. Retrying.'.format(count=len(missing_ids))
|
||||
u'Failed to get details for {count} pathways. Retrying.'.format(count=len(missing_ids))
|
||||
)
|
||||
|
||||
retried_pathways = cache.get_many(
|
||||
@@ -240,8 +240,8 @@ def format_price(price, symbol='$', code='USD'):
|
||||
:return: A formatted price string, i.e. '$10 USD', '$10.52 USD'.
|
||||
"""
|
||||
if int(price) == price:
|
||||
return '{}{} {}'.format(symbol, int(price), code)
|
||||
return '{}{:0.2f} {}'.format(symbol, price, code)
|
||||
return u'{}{} {}'.format(symbol, int(price), code)
|
||||
return u'{}{:0.2f} {}'.format(symbol, price, code)
|
||||
|
||||
|
||||
def get_localized_price_text(price, request):
|
||||
@@ -506,7 +506,7 @@ def get_course_run_details(course_run_key, fields):
|
||||
"""
|
||||
course_run_details = dict()
|
||||
user, catalog_integration = check_catalog_integration_and_get_user(
|
||||
error_message_field='Data for course_run {}'.format(course_run_key)
|
||||
error_message_field=u'Data for course_run {}'.format(course_run_key)
|
||||
)
|
||||
if user:
|
||||
api = create_catalog_api_client(user)
|
||||
|
||||
@@ -90,17 +90,17 @@ def course_info_to_ccxcon(course_key):
|
||||
try:
|
||||
course = get_course_by_id(course_key)
|
||||
except Http404:
|
||||
log.error('Master Course with key "%s" not found', unicode(course_key))
|
||||
log.error(u'Master Course with key "%s" not found', unicode(course_key))
|
||||
return
|
||||
if not course.enable_ccx:
|
||||
log.debug('ccx not enabled for course key "%s"', unicode(course_key))
|
||||
log.debug(u'ccx not enabled for course key "%s"', unicode(course_key))
|
||||
return
|
||||
if not course.ccx_connector:
|
||||
log.debug('ccx connector not defined for course key "%s"', unicode(course_key))
|
||||
log.debug(u'ccx connector not defined for course key "%s"', unicode(course_key))
|
||||
return
|
||||
if not is_valid_url(course.ccx_connector):
|
||||
log.error(
|
||||
'ccx connector URL "%s" for course key "%s" is not a valid URL.',
|
||||
u'ccx connector URL "%s" for course key "%s" is not a valid URL.',
|
||||
course.ccx_connector, unicode(course_key)
|
||||
)
|
||||
return
|
||||
@@ -108,7 +108,7 @@ def course_info_to_ccxcon(course_key):
|
||||
try:
|
||||
ccxcon = CCXCon.objects.get(url=course.ccx_connector)
|
||||
except CCXCon.DoesNotExist:
|
||||
log.error('ccx connector Oauth credentials not configured for URL "%s".', course.ccx_connector)
|
||||
log.error(u'ccx connector Oauth credentials not configured for URL "%s".', course.ccx_connector)
|
||||
return
|
||||
|
||||
# get an oauth client with a valid token
|
||||
@@ -147,11 +147,11 @@ def course_info_to_ccxcon(course_key):
|
||||
)
|
||||
|
||||
if resp.status_code >= 500:
|
||||
raise CCXConnServerError('Server returned error Status: %s, Content: %s', resp.status_code, resp.content)
|
||||
raise CCXConnServerError(u'Server returned error Status: %s, Content: %s', resp.status_code, resp.content)
|
||||
if resp.status_code >= 400:
|
||||
log.error("Error creating course on ccxcon. Status: %s, Content: %s", resp.status_code, resp.content)
|
||||
log.error(u"Error creating course on ccxcon. Status: %s, Content: %s", resp.status_code, resp.content)
|
||||
# this API performs a POST request both for POST and PATCH, but the POST returns 201 and the PATCH returns 200
|
||||
elif resp.status_code != HTTP_200_OK and resp.status_code != HTTP_201_CREATED:
|
||||
log.error('Server returned unexpected status code %s', resp.status_code)
|
||||
log.error(u'Server returned unexpected status code %s', resp.status_code)
|
||||
else:
|
||||
log.debug('Request successful. Status: %s, Content: %s', resp.status_code, resp.content)
|
||||
log.debug(u'Request successful. Status: %s, Content: %s', resp.status_code, resp.content)
|
||||
|
||||
@@ -25,9 +25,9 @@ def update_ccxcon(course_id, cur_retry=0):
|
||||
course_key = CourseKey.from_string(course_id)
|
||||
try:
|
||||
api.course_info_to_ccxcon(course_key)
|
||||
log.info('Course update to CCXCon returned no errors. Course key: %s', course_id)
|
||||
log.info(u'Course update to CCXCon returned no errors. Course key: %s', course_id)
|
||||
except (ConnectionError, HTTPError, RequestException, TooManyRedirects, api.CCXConnServerError) as exp:
|
||||
log.error('Course update to CCXCon failed for course_id %s with error: %s', course_id, exp)
|
||||
log.error(u'Course update to CCXCon failed for course_id %s with error: %s', course_id, exp)
|
||||
# in case the maximum amount of retries has not been reached,
|
||||
# insert another task delayed exponentially up to 5 retries
|
||||
if cur_retry < 5:
|
||||
@@ -35,4 +35,4 @@ def update_ccxcon(course_id, cur_retry=0):
|
||||
kwargs={'course_id': course_id, 'cur_retry': cur_retry + 1},
|
||||
countdown=10 ** cur_retry # number of seconds the task should be delayed
|
||||
)
|
||||
log.info('Requeued celery task for course key %s ; retry # %s', course_id, cur_retry + 1)
|
||||
log.info(u'Requeued celery task for course key %s ; retry # %s', course_id, cur_retry + 1)
|
||||
|
||||
@@ -300,7 +300,7 @@ class FieldData(object):
|
||||
try:
|
||||
return self.fields[field_name]
|
||||
except KeyError:
|
||||
raise AttributeError("Field {0} does not exist".format(field_name))
|
||||
raise AttributeError(u"Field {0} does not exist".format(field_name))
|
||||
|
||||
def __setattr__(self, field_name, field_value):
|
||||
if self._is_own_field(field_name):
|
||||
@@ -747,7 +747,7 @@ class BlockStructureBlockData(BlockStructure):
|
||||
its current version number.
|
||||
"""
|
||||
if transformer.WRITE_VERSION == 0:
|
||||
raise TransformerException('Version attributes are not set on transformer {0}.', transformer.name())
|
||||
raise TransformerException(u'Version attributes are not set on transformer {0}.', transformer.name())
|
||||
self.set_transformer_data(transformer, TRANSFORMER_VERSION_KEY, transformer.WRITE_VERSION)
|
||||
|
||||
def _get_or_create_block(self, usage_key):
|
||||
|
||||
@@ -38,5 +38,5 @@ class BlockStructureNotFound(BlockStructureException):
|
||||
"""
|
||||
def __init__(self, root_block_usage_key):
|
||||
super(BlockStructureNotFound, self).__init__(
|
||||
'Block structure not found; data_usage_key: {}'.format(root_block_usage_key)
|
||||
u'Block structure not found; data_usage_key: {}'.format(root_block_usage_key)
|
||||
)
|
||||
|
||||
@@ -68,7 +68,7 @@ class BlockStructureManager(object):
|
||||
# as part of the transformation.
|
||||
if starting_block_usage_key not in block_structure:
|
||||
raise UsageKeyNotInBlockStructure(
|
||||
"The requested usage_key '{0}' is not found in the block_structure with root '{1}'",
|
||||
u"The requested usage_key '{0}' is not found in the block_structure with root '{1}'",
|
||||
unicode(starting_block_usage_key),
|
||||
unicode(self.root_block_usage_key),
|
||||
)
|
||||
|
||||
@@ -109,7 +109,7 @@ class BlockStructureStore(object):
|
||||
bs_model = self._get_model(root_block_usage_key)
|
||||
self._cache.delete(self._encode_root_cache_key(bs_model))
|
||||
bs_model.delete()
|
||||
logger.info("BlockStructure: Deleted from cache and store; %s.", bs_model)
|
||||
logger.info(u"BlockStructure: Deleted from cache and store; %s.", bs_model)
|
||||
|
||||
def is_up_to_date(self, root_block_usage_key, modulestore):
|
||||
"""
|
||||
@@ -158,7 +158,7 @@ class BlockStructureStore(object):
|
||||
"""
|
||||
cache_key = self._encode_root_cache_key(bs_model)
|
||||
self._cache.set(cache_key, serialized_data, timeout=config.cache_timeout_in_seconds())
|
||||
logger.info("BlockStructure: Added to cache; %s, size: %d", bs_model, len(serialized_data))
|
||||
logger.info(u"BlockStructure: Added to cache; %s, size: %d", bs_model, len(serialized_data))
|
||||
|
||||
def _get_from_cache(self, bs_model):
|
||||
"""
|
||||
@@ -171,7 +171,7 @@ class BlockStructureStore(object):
|
||||
serialized_data = self._cache.get(cache_key)
|
||||
|
||||
if not serialized_data:
|
||||
logger.info("BlockStructure: Not found in cache; %s.", bs_model)
|
||||
logger.info(u"BlockStructure: Not found in cache; %s.", bs_model)
|
||||
raise BlockStructureNotFound(bs_model.data_usage_key)
|
||||
return serialized_data
|
||||
|
||||
|
||||
@@ -102,18 +102,18 @@ def _call_and_retry_if_needed(self, api_method, **kwargs):
|
||||
except NO_RETRY_TASKS:
|
||||
# Known unrecoverable errors
|
||||
log.exception(
|
||||
"BlockStructure: %s encountered unrecoverable error in course %s, task_id %s",
|
||||
u"BlockStructure: %s encountered unrecoverable error in course %s, task_id %s",
|
||||
self.__name__,
|
||||
kwargs.get('course_id'),
|
||||
self.request.id,
|
||||
)
|
||||
raise
|
||||
except RETRY_TASKS as exc:
|
||||
log.exception("%s encountered expected error, retrying.", self.__name__)
|
||||
log.exception(u"%s encountered expected error, retrying.", self.__name__)
|
||||
raise self.retry(kwargs=kwargs, exc=exc)
|
||||
except Exception as exc:
|
||||
log.exception(
|
||||
"BlockStructure: %s encountered unknown error in course %s, task_id %s. Retry #%d",
|
||||
u"BlockStructure: %s encountered unknown error in course %s, task_id %s. Retry #%d",
|
||||
self.__name__,
|
||||
kwargs.get('course_id'),
|
||||
self.request.id,
|
||||
|
||||
@@ -303,7 +303,7 @@ class ChildrenMapTestMixin(object):
|
||||
self.assertEqual(
|
||||
self.block_key_factory(block_key) in block_structure,
|
||||
block_key not in missing_blocks,
|
||||
'Expected presence in block_structure for block_key {} to match absence in missing_blocks.'.format(
|
||||
u'Expected presence in block_structure for block_key {} to match absence in missing_blocks.'.format(
|
||||
unicode(block_key)
|
||||
),
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ class TestBlockStructureStore(UsageKeyFactoryMixin, ChildrenMapTestMixin, CacheI
|
||||
self.block_key_factory(0),
|
||||
transformer,
|
||||
key='test',
|
||||
value='{} val'.format(transformer.name()),
|
||||
value=u'{} val'.format(transformer.name()),
|
||||
)
|
||||
|
||||
@ddt.data(True, False)
|
||||
|
||||
@@ -60,7 +60,7 @@ class BlockStructureTransformers(object):
|
||||
unregistered_transformers = TransformerRegistry.find_unregistered(transformers)
|
||||
if unregistered_transformers:
|
||||
raise TransformerException(
|
||||
"The following requested transformers are not registered: {}".format(unregistered_transformers)
|
||||
u"The following requested transformers are not registered: {}".format(unregistered_transformers)
|
||||
)
|
||||
|
||||
for transformer in transformers:
|
||||
@@ -100,7 +100,7 @@ class BlockStructureTransformers(object):
|
||||
|
||||
if outdated_transformers:
|
||||
raise TransformerDataIncompatible(
|
||||
"Collected Block Structure data for the following transformers is outdated: '%s'.",
|
||||
u"Collected Block Structure data for the following transformers is outdated: '%s'.",
|
||||
[(transformer.name(), transformer.READ_VERSION) for transformer in outdated_transformers],
|
||||
)
|
||||
return True
|
||||
|
||||
@@ -162,7 +162,7 @@ class Command(BaseCommand):
|
||||
return self.print_show_receivers()
|
||||
|
||||
log.info(
|
||||
"simulate_publish starting, dry-run=%s, delay=%d seconds",
|
||||
u"simulate_publish starting, dry-run=%s, delay=%d seconds",
|
||||
options['dry_run'],
|
||||
options['delay']
|
||||
)
|
||||
@@ -172,8 +172,8 @@ class Command(BaseCommand):
|
||||
log.info("Forcing simulate_publish to run in LMS process.")
|
||||
else:
|
||||
log.fatal(
|
||||
"simulate_publish should be run as a CMS (Studio) " +
|
||||
"command, not %s (override with --force-lms).",
|
||||
u"simulate_publish should be run as a CMS (Studio) " +
|
||||
u"command, not %s (override with --force-lms).", # pylint: disable=unicode-format-string
|
||||
os.environ.get('SERVICE_VARIANT')
|
||||
)
|
||||
sys.exit(1)
|
||||
@@ -193,7 +193,7 @@ class Command(BaseCommand):
|
||||
# actual work of emitting signals.
|
||||
for i, course_key in enumerate(course_keys, start=1):
|
||||
log.info(
|
||||
"Emitting course_published signal (%d of %d) for course %s",
|
||||
u"Emitting course_published signal (%d of %d) for course %s",
|
||||
i, len(course_keys), course_key
|
||||
)
|
||||
if options['delay']:
|
||||
@@ -214,19 +214,19 @@ class Command(BaseCommand):
|
||||
unknown_receiver_names = set(receiver_names) - all_receiver_names
|
||||
if unknown_receiver_names:
|
||||
log.fatal(
|
||||
"The following receivers were specified but not recognized: %s",
|
||||
", ".join(sorted(unknown_receiver_names))
|
||||
u"The following receivers were specified but not recognized: %s",
|
||||
u", ".join(sorted(unknown_receiver_names))
|
||||
)
|
||||
log.fatal("Known receivers: %s", ", ".join(sorted(all_receiver_names)))
|
||||
log.fatal(u"Known receivers: %s", ", ".join(sorted(all_receiver_names)))
|
||||
sys.exit(1)
|
||||
log.info("%d receivers specified: %s", len(receiver_names), ", ".join(receiver_names))
|
||||
log.info(u"%d receivers specified: %s", len(receiver_names), ", ".join(receiver_names))
|
||||
receiver_names_set = set(receiver_names)
|
||||
for receiver_fn in get_receiver_fns():
|
||||
if receiver_fn == ccx_receiver_fn and not skip_ccx:
|
||||
continue
|
||||
fn_name = name_from_fn(receiver_fn)
|
||||
if fn_name not in receiver_names_set:
|
||||
log.info("Disconnecting %s", fn_name)
|
||||
log.info(u"Disconnecting %s", fn_name)
|
||||
self.course_published_signal.disconnect(receiver_fn)
|
||||
|
||||
def get_course_keys(self, courses):
|
||||
@@ -242,12 +242,12 @@ class Command(BaseCommand):
|
||||
# Use specific courses if specified, but fall back to all courses.
|
||||
course_keys = []
|
||||
if courses:
|
||||
log.info("%d courses specified: %s", len(courses), ", ".join(courses))
|
||||
log.info(u"%d courses specified: %s", len(courses), ", ".join(courses))
|
||||
for course_id in courses:
|
||||
try:
|
||||
course_keys.append(CourseKey.from_string(course_id))
|
||||
except InvalidKeyError:
|
||||
log.fatal("%s is not a parseable CourseKey", course_id)
|
||||
log.fatal(u"%s is not a parseable CourseKey", course_id)
|
||||
sys.exit(1)
|
||||
else:
|
||||
log.info("No courses specified, reading all courses from modulestore...")
|
||||
@@ -255,7 +255,7 @@ class Command(BaseCommand):
|
||||
(course.id for course in modulestore().get_course_summaries()),
|
||||
key=unicode # Different types of CourseKeys can't be compared without this.
|
||||
)
|
||||
log.info("%d courses read from modulestore.", len(course_keys))
|
||||
log.info(u"%d courses read from modulestore.", len(course_keys))
|
||||
|
||||
return course_keys
|
||||
|
||||
@@ -284,7 +284,7 @@ class Command(BaseCommand):
|
||||
for course_key in course_keys[:COURSES_TO_SHOW]:
|
||||
print(" ", course_key)
|
||||
if len(course_keys) > COURSES_TO_SHOW:
|
||||
print(" (+ {} more)".format(len(course_keys) - COURSES_TO_SHOW))
|
||||
print(u" (+ {} more)".format(len(course_keys) - COURSES_TO_SHOW))
|
||||
|
||||
|
||||
def get_receiver_names():
|
||||
|
||||
@@ -147,10 +147,10 @@ class CourseOverview(TimeStampedModel):
|
||||
|
||||
course_overview = cls.objects.filter(id=course.id)
|
||||
if course_overview.exists():
|
||||
log.info('Updating course overview for %s.', unicode(course.id))
|
||||
log.info(u'Updating course overview for %s.', unicode(course.id))
|
||||
course_overview = course_overview.first()
|
||||
else:
|
||||
log.info('Creating course overview for %s.', unicode(course.id))
|
||||
log.info(u'Creating course overview for %s.', unicode(course.id))
|
||||
course_overview = cls()
|
||||
|
||||
course_overview.version = cls.VERSION
|
||||
@@ -249,7 +249,7 @@ class CourseOverview(TimeStampedModel):
|
||||
pass
|
||||
except Exception:
|
||||
log.exception(
|
||||
"CourseOverview for course %s failed!",
|
||||
u"CourseOverview for course %s failed!",
|
||||
course_id,
|
||||
)
|
||||
raise
|
||||
@@ -257,7 +257,7 @@ class CourseOverview(TimeStampedModel):
|
||||
return course_overview
|
||||
elif course is not None:
|
||||
raise IOError(
|
||||
"Error while loading course {} from the module store: {}",
|
||||
u"Error while loading course {} from the module store: {}",
|
||||
unicode(course_id),
|
||||
course.error_msg if isinstance(course, ErrorDescriptor) else unicode(course)
|
||||
)
|
||||
@@ -541,8 +541,8 @@ class CourseOverview(TimeStampedModel):
|
||||
whether the requested CourseOverview objects should be
|
||||
forcefully updated (i.e., re-synched with the modulestore).
|
||||
"""
|
||||
log.info('Generating course overview for %d courses.', len(course_keys))
|
||||
log.debug('Generating course overview(s) for the following courses: %s', course_keys)
|
||||
log.info(u'Generating course overview for %d courses.', len(course_keys))
|
||||
log.debug(u'Generating course overview(s) for the following courses: %s', course_keys)
|
||||
|
||||
action = CourseOverview.load_from_module_store if force_update else CourseOverview.get_from_id
|
||||
|
||||
@@ -551,7 +551,7 @@ class CourseOverview(TimeStampedModel):
|
||||
action(course_key)
|
||||
except Exception as ex: # pylint: disable=broad-except
|
||||
log.exception(
|
||||
'An error occurred while generating course overview for %s: %s',
|
||||
u'An error occurred while generating course overview for %s: %s',
|
||||
unicode(course_key),
|
||||
text_type(ex),
|
||||
)
|
||||
@@ -818,7 +818,7 @@ class CourseOverviewImageSet(TimeStampedModel):
|
||||
image_set.large_url = create_course_image_thumbnail(course, config.large)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
log.exception(
|
||||
"Could not create thumbnail for course %s with image %s (small=%s), (large=%s)",
|
||||
u"Could not create thumbnail for course %s with image %s (small=%s), (large=%s)",
|
||||
course.id,
|
||||
course.course_image,
|
||||
config.small,
|
||||
|
||||
@@ -63,7 +63,7 @@ def _log_start_date_change(previous_course_overview, updated_course_overview):
|
||||
new_start_str = 'None'
|
||||
if updated_course_overview.start is not None:
|
||||
new_start_str = updated_course_overview.start.isoformat()
|
||||
LOG.info('Course start date changed: course={0} previous={1} new={2}'.format(
|
||||
LOG.info(u'Course start date changed: course={0} previous={1} new={2}'.format(
|
||||
updated_course_overview.id,
|
||||
previous_start_str,
|
||||
new_start_str,
|
||||
|
||||
@@ -511,7 +511,7 @@ class CourseOverviewTestCase(CatalogIntegrationMixin, ModuleStoreTestCase, Cache
|
||||
CourseOverview.get_all_courses(filter_=filter_)
|
||||
},
|
||||
expected_courses,
|
||||
"testing CourseOverview.get_all_courses with filter_={}"
|
||||
u"testing CourseOverview.get_all_courses with filter_={}"
|
||||
.format(filter_),
|
||||
)
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ from .models import CourseAssetCacheTtlConfig, CdnUserAgentsConfig
|
||||
# TODO: Soon as we have a reasonable way to serialize/deserialize AssetKeys, we need
|
||||
# to change this file so instead of using course_id_partial, we're just using asset keys
|
||||
|
||||
HTTP_DATE_FORMAT = "%a, %d %b %Y %H:%M:%S GMT"
|
||||
HTTP_DATE_FORMAT = u"%a, %d %b %Y %H:%M:%S GMT"
|
||||
|
||||
|
||||
class StaticContentServer(object):
|
||||
@@ -152,7 +152,7 @@ class StaticContentServer(object):
|
||||
if 0 <= first <= last < content.length:
|
||||
# If the byte range is satisfiable
|
||||
response = HttpResponse(content.stream_data_in_range(first, last))
|
||||
response['Content-Range'] = 'bytes {first}-{last}/{length}'.format(
|
||||
response['Content-Range'] = b'bytes {first}-{last}/{length}'.format(
|
||||
first=first, last=last, length=content.length
|
||||
)
|
||||
response['Content-Length'] = str(last - first + 1)
|
||||
@@ -207,7 +207,7 @@ class StaticContentServer(object):
|
||||
newrelic.agent.add_custom_parameter('contentserver.cacheable', True)
|
||||
|
||||
response['Expires'] = StaticContentServer.get_expiration_value(datetime.datetime.utcnow(), cache_ttl)
|
||||
response['Cache-Control'] = "public, max-age={ttl}, s-maxage={ttl}".format(ttl=cache_ttl)
|
||||
response['Cache-Control'] = b"public, max-age={ttl}, s-maxage={ttl}".format(ttl=cache_ttl)
|
||||
elif is_locked:
|
||||
if newrelic:
|
||||
newrelic.agent.add_custom_parameter('contentserver.cacheable', False)
|
||||
|
||||
@@ -217,7 +217,7 @@ class ContentStoreToyCourseTest(SharedModuleStoreTestCase):
|
||||
self.assertEqual(resp.status_code, 206) # HTTP_206_PARTIAL_CONTENT
|
||||
self.assertEqual(
|
||||
resp['Content-Range'],
|
||||
'bytes {first}-{last}/{length}'.format(
|
||||
b'bytes {first}-{last}/{length}'.format(
|
||||
first=0, last=self.length_unlocked - 1,
|
||||
length=self.length_unlocked
|
||||
)
|
||||
@@ -236,7 +236,7 @@ class ContentStoreToyCourseTest(SharedModuleStoreTestCase):
|
||||
first=first_byte, last=last_byte))
|
||||
|
||||
self.assertEqual(resp.status_code, 206) # HTTP_206_PARTIAL_CONTENT
|
||||
self.assertEqual(resp['Content-Range'], 'bytes {first}-{last}/{length}'.format(
|
||||
self.assertEqual(resp['Content-Range'], b'bytes {first}-{last}/{length}'.format(
|
||||
first=first_byte, last=last_byte, length=self.length_unlocked))
|
||||
self.assertEqual(resp['Content-Length'], str(last_byte - first_byte + 1))
|
||||
|
||||
@@ -246,7 +246,7 @@ class ContentStoreToyCourseTest(SharedModuleStoreTestCase):
|
||||
"""
|
||||
first_byte = self.length_unlocked / 4
|
||||
last_byte = self.length_unlocked / 2
|
||||
resp = self.client.get(self.url_unlocked, HTTP_RANGE='bytes={first}-{last}, -100'.format(
|
||||
resp = self.client.get(self.url_unlocked, HTTP_RANGE=b'bytes={first}-{last}, -100'.format(
|
||||
first=first_byte, last=last_byte))
|
||||
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
@@ -139,7 +139,7 @@ class CsrfCrossDomainCookieMiddleware(object):
|
||||
secure=True
|
||||
)
|
||||
log.debug(
|
||||
"Set cross-domain CSRF cookie '%s' for domain '%s'",
|
||||
u"Set cross-domain CSRF cookie '%s' for domain '%s'",
|
||||
settings.CROSS_DOMAIN_CSRF_COOKIE_NAME,
|
||||
settings.CROSS_DOMAIN_CSRF_COOKIE_DOMAIN
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@ class XDomainProxyConfiguration(ConfigurationModel):
|
||||
whitelist = models.fields.TextField(
|
||||
help_text=_(
|
||||
u"List of domains that are allowed to make cross-domain "
|
||||
u"requests to this site. Please list each domain on its own line."
|
||||
"requests to this site. Please list each domain on its own line."
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -263,7 +263,7 @@ class TestCsrfCrossDomainCookieMiddleware(TestCase):
|
||||
self.assertIn(self.COOKIE_NAME, response.cookies)
|
||||
cookie_header = str(response.cookies[self.COOKIE_NAME])
|
||||
|
||||
expected = 'Set-Cookie: {name}={value}; Domain={domain};'.format(
|
||||
expected = b'Set-Cookie: {name}={value}; Domain={domain};'.format(
|
||||
name=self.COOKIE_NAME,
|
||||
value=self.COOKIE_VALUE,
|
||||
domain=self.COOKIE_DOMAIN
|
||||
|
||||
@@ -264,7 +264,7 @@ def get_cohort(user, course_key, assign=True, use_cached=False):
|
||||
# create the same row in one of the cohort model entries:
|
||||
# CourseCohort, CohortMembership.
|
||||
log.info(
|
||||
"HANDLING_INTEGRITY_ERROR: IntegrityError encountered for course '%s' and user '%s': %s",
|
||||
u"HANDLING_INTEGRITY_ERROR: IntegrityError encountered for course '%s' and user '%s': %s",
|
||||
course_key, user.id, unicode(integrity_error)
|
||||
)
|
||||
return get_cohort(user, course_key, assign, use_cached)
|
||||
@@ -377,7 +377,7 @@ def add_cohort(course_key, name, assignment_type):
|
||||
Add a cohort to a course. Raises ValueError if a cohort of the same name already
|
||||
exists.
|
||||
"""
|
||||
log.debug("Adding cohort %s to %s", name, course_key)
|
||||
log.debug(u"Adding cohort %s to %s", name, course_key)
|
||||
if is_cohort_exists(course_key, name):
|
||||
raise ValueError(_("You cannot create two cohorts with the same name"))
|
||||
|
||||
@@ -426,7 +426,7 @@ def remove_user_from_cohort(cohort, username_or_email):
|
||||
membership.delete()
|
||||
COHORT_MEMBERSHIP_UPDATED.send(sender=None, user=user, course_key=course_key)
|
||||
except CohortMembership.DoesNotExist:
|
||||
raise ValueError("User {} was not present in cohort {}".format(username_or_email, cohort))
|
||||
raise ValueError(u"User {} was not present in cohort {}".format(username_or_email, cohort))
|
||||
|
||||
|
||||
def add_user_to_cohort(cohort, username_or_email_or_user):
|
||||
|
||||
@@ -107,7 +107,7 @@ class CohortMembership(models.Model):
|
||||
membership.course_user_group.users.add(user)
|
||||
previous_cohort = None
|
||||
elif membership.course_user_group == cohort:
|
||||
raise ValueError("User {user_name} already present in cohort {cohort_name}".format(
|
||||
raise ValueError(u"User {user_name} already present in cohort {cohort_name}".format(
|
||||
user_name=user.username,
|
||||
cohort_name=cohort.name))
|
||||
else:
|
||||
@@ -122,8 +122,7 @@ class CohortMembership(models.Model):
|
||||
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
||||
self.full_clean(validate_unique=False)
|
||||
|
||||
log.info("Saving CohortMembership for user '%s' in '%s'", self.user.id, self.course_id)
|
||||
|
||||
log.info(u"Saving CohortMembership for user '%s' in '%s'", self.user.id, self.course_id)
|
||||
return super(CohortMembership, self).save(force_insert=force_insert,
|
||||
force_update=force_update,
|
||||
using=using,
|
||||
|
||||
@@ -61,7 +61,7 @@ class CohortPartitionScheme(object):
|
||||
# one it means the mapping is invalid. the previous state of the
|
||||
# partition configuration may have been modified.
|
||||
log.warn(
|
||||
"partition mismatch in CohortPartitionScheme: %r",
|
||||
u"partition mismatch in CohortPartitionScheme: %r",
|
||||
{
|
||||
"requested_partition_id": user_partition.id,
|
||||
"found_partition_id": partition_id,
|
||||
@@ -79,7 +79,7 @@ class CohortPartitionScheme(object):
|
||||
# it means the mapping is invalid. the previous state of the
|
||||
# partition configuration may have been modified.
|
||||
log.warn(
|
||||
"group not found in CohortPartitionScheme: %r",
|
||||
u"group not found in CohortPartitionScheme: %r",
|
||||
{
|
||||
"requested_partition_id": user_partition.id,
|
||||
"requested_group_id": group_id,
|
||||
|
||||
@@ -14,7 +14,7 @@ class CohortUsersAPISerializer(serializers.ModelSerializer):
|
||||
|
||||
def get_full_name(self, model):
|
||||
"""Return the full name of the user."""
|
||||
return '{} {}'.format(model.first_name, model.last_name)
|
||||
return u'{} {}'.format(model.first_name, model.last_name)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
|
||||
@@ -308,7 +308,7 @@ class TestCohortApi(SharedModuleStoreTestCase):
|
||||
expected_results = [{
|
||||
'username': user.username,
|
||||
'email': user.email,
|
||||
'name': '{} {}'.format(user.first_name, user.last_name)
|
||||
'name': u'{} {}'.format(user.first_name, user.last_name)
|
||||
} for user in users]
|
||||
assert results == expected_results
|
||||
|
||||
|
||||
@@ -1057,7 +1057,7 @@ class AddUsersToCohortTestCase(CohortViewsTestCase):
|
||||
"""
|
||||
unknown = "unknown_user"
|
||||
response_dict = self.request_add_users_to_cohort(
|
||||
" {} {}\t{}, \r\n{}".format(
|
||||
u" {} {}\t{}, \r\n{}".format(
|
||||
unknown,
|
||||
self.cohort1_users[0].username,
|
||||
self.cohort2_users[0].username,
|
||||
@@ -1194,7 +1194,7 @@ class RemoveUserFromCohortTestCase(CohortViewsTestCase):
|
||||
username,
|
||||
response_dict,
|
||||
cohort,
|
||||
expected_error_msg='No user \'{0}\''.format(username)
|
||||
expected_error_msg=u'No user \'{0}\''.format(username)
|
||||
)
|
||||
|
||||
def test_can_remove_user_not_in_cohort(self):
|
||||
|
||||
@@ -270,7 +270,7 @@ def users_in_cohort(request, course_key_string, cohort_id):
|
||||
|
||||
user_info = [{'username': u.username,
|
||||
'email': u.email,
|
||||
'name': '{0} {1}'.format(u.first_name, u.last_name)}
|
||||
'name': u'{0} {1}'.format(u.first_name, u.last_name)}
|
||||
for u in users]
|
||||
|
||||
return json_http_response({'success': True,
|
||||
@@ -307,7 +307,7 @@ def add_users_to_cohort(request, course_key_string, cohort_id):
|
||||
try:
|
||||
cohort = cohorts.get_cohort_by_id(course_key, cohort_id)
|
||||
except CourseUserGroup.DoesNotExist:
|
||||
raise Http404("Cohort (ID {cohort_id}) not found for {course_key_string}".format(
|
||||
raise Http404(u"Cohort (ID {cohort_id}) not found for {course_key_string}".format(
|
||||
cohort_id=cohort_id,
|
||||
course_key_string=course_key_string
|
||||
))
|
||||
@@ -378,7 +378,7 @@ def remove_user_from_cohort(request, course_key_string, cohort_id):
|
||||
api.remove_user_from_cohort(course_key, username)
|
||||
except User.DoesNotExist:
|
||||
log.debug('no user')
|
||||
return json_http_response({'success': False, 'msg': "No user '{0}'".format(username)})
|
||||
return json_http_response({'success': False, 'msg': u"No user '{0}'".format(username)})
|
||||
|
||||
return json_http_response({'success': True})
|
||||
|
||||
@@ -667,7 +667,7 @@ class CohortUsers(DeveloperErrorViewMixin, APIPermissions):
|
||||
try:
|
||||
cohort = cohorts.get_cohort_by_id(course_key, cohort_id)
|
||||
except CourseUserGroup.DoesNotExist:
|
||||
msg = 'Cohort (ID {cohort_id}) not found for {course_key_string}'.format(
|
||||
msg = u'Cohort (ID {cohort_id}) not found for {course_key_string}'.format(
|
||||
cohort_id=cohort_id,
|
||||
course_key_string=course_key_string
|
||||
)
|
||||
|
||||
@@ -163,7 +163,7 @@ class Command(BaseCommand):
|
||||
options = self.get_args_from_database()
|
||||
|
||||
log.info(
|
||||
"notify_credentials starting, dry-run=%s, site=%s, delay=%d seconds",
|
||||
u"notify_credentials starting, dry-run=%s, site=%s, delay=%d seconds",
|
||||
options['dry_run'],
|
||||
options['site'],
|
||||
options['delay']
|
||||
@@ -175,8 +175,7 @@ class Command(BaseCommand):
|
||||
try:
|
||||
site_config = SiteConfiguration.objects.get(site__domain=options['site']) if options['site'] else None
|
||||
except SiteConfiguration.DoesNotExist:
|
||||
log.error('No site configuration found for site %s', options['site'])
|
||||
|
||||
log.error(u'No site configuration found for site %s', options['site'])
|
||||
if options['courses']:
|
||||
course_keys = self.get_course_keys(options['courses'])
|
||||
cert_filter_args['course_id__in'] = course_keys
|
||||
@@ -214,11 +213,11 @@ class Command(BaseCommand):
|
||||
# First, do certs
|
||||
for i, cert in paged_query(certs, delay, page_size):
|
||||
if site_config and not site_config.has_org(cert.course_id.org):
|
||||
log.info("Skipping credential changes %d for certificate %s", i, certstr(cert))
|
||||
log.info(u"Skipping credential changes %d for certificate %s", i, certstr(cert))
|
||||
continue
|
||||
|
||||
log.info(
|
||||
"Handling credential changes %d for certificate %s",
|
||||
u"Handling credential changes %d for certificate %s",
|
||||
i, certstr(cert),
|
||||
)
|
||||
|
||||
@@ -236,11 +235,11 @@ class Command(BaseCommand):
|
||||
# Then do grades
|
||||
for i, grade in paged_query(grades, delay, page_size):
|
||||
if site_config and not site_config.has_org(grade.course_id.org):
|
||||
log.info("Skipping grade changes %d for grade %s", i, gradestr(grade))
|
||||
log.info(u"Skipping grade changes %d for grade %s", i, gradestr(grade))
|
||||
continue
|
||||
|
||||
log.info(
|
||||
"Handling grade changes %d for grade %s",
|
||||
u"Handling grade changes %d for grade %s",
|
||||
i, gradestr(grade),
|
||||
)
|
||||
|
||||
@@ -267,12 +266,12 @@ class Command(BaseCommand):
|
||||
"""
|
||||
# Use specific courses if specified, but fall back to all courses.
|
||||
course_keys = []
|
||||
log.info("%d courses specified: %s", len(courses), ", ".join(courses))
|
||||
log.info(u"%d courses specified: %s", len(courses), ", ".join(courses))
|
||||
for course_id in courses:
|
||||
try:
|
||||
course_keys.append(CourseKey.from_string(course_id))
|
||||
except InvalidKeyError:
|
||||
log.fatal("%s is not a parseable CourseKey", course_id)
|
||||
log.fatal(u"%s is not a parseable CourseKey", course_id)
|
||||
sys.exit(1)
|
||||
|
||||
return course_keys
|
||||
@@ -286,10 +285,10 @@ class Command(BaseCommand):
|
||||
for cert in certs[:ITEMS_TO_SHOW]:
|
||||
print(" ", certstr(cert))
|
||||
if certs.count() > ITEMS_TO_SHOW:
|
||||
print(" (+ {} more)".format(certs.count() - ITEMS_TO_SHOW))
|
||||
print(u" (+ {} more)".format(certs.count() - ITEMS_TO_SHOW))
|
||||
|
||||
print(grades.count(), "Grades:")
|
||||
for grade in grades[:ITEMS_TO_SHOW]:
|
||||
print(" ", gradestr(grade))
|
||||
if grades.count() > ITEMS_TO_SHOW:
|
||||
print(" (+ {} more)".format(grades.count() - ITEMS_TO_SHOW))
|
||||
print(u" (+ {} more)".format(grades.count() - ITEMS_TO_SHOW))
|
||||
|
||||
@@ -46,7 +46,7 @@ def send_grade_if_interesting(user, course_run_key, mode, status, letter_grade,
|
||||
""" Checks if grade is interesting to Credentials and schedules a Celery task if so. """
|
||||
|
||||
if verbose:
|
||||
msg = "Starting send_grade_if_interesting with params: "\
|
||||
msg = u"Starting send_grade_if_interesting with params: "\
|
||||
"user [{username}], "\
|
||||
"course_run_key [{key}], "\
|
||||
"mode [{mode}], "\
|
||||
@@ -74,7 +74,7 @@ def send_grade_if_interesting(user, course_run_key, mode, status, letter_grade,
|
||||
if not helpers.get_value_for_org(course_run_key.org, 'ENABLE_LEARNER_RECORDS', True):
|
||||
if verbose:
|
||||
log.info(
|
||||
"Skipping send grade: ENABLE_LEARNER_RECORDS False for org [{org}]".format(
|
||||
u"Skipping send grade: ENABLE_LEARNER_RECORDS False for org [{org}]".format(
|
||||
org=course_run_key.org
|
||||
)
|
||||
)
|
||||
@@ -90,7 +90,7 @@ def send_grade_if_interesting(user, course_run_key, mode, status, letter_grade,
|
||||
# We only care about grades for which there is a certificate.
|
||||
if verbose:
|
||||
log.info(
|
||||
"Skipping send grade: no cert for user [{username}] & course_id [{course_id}]".format(
|
||||
u"Skipping send grade: no cert for user [{username}] & course_id [{course_id}]".format(
|
||||
username=getattr(user, 'username', None),
|
||||
course_id=str(course_run_key)
|
||||
)
|
||||
@@ -103,7 +103,7 @@ def send_grade_if_interesting(user, course_run_key, mode, status, letter_grade,
|
||||
if mode not in INTERESTING_MODES or status not in INTERESTING_STATUSES:
|
||||
if verbose:
|
||||
log.info(
|
||||
"Skipping send grade: mode/status uninteresting for mode [{mode}] & status [{status}]".format(
|
||||
u"Skipping send grade: mode/status uninteresting for mode [{mode}] & status [{status}]".format(
|
||||
mode=mode,
|
||||
status=status
|
||||
)
|
||||
@@ -115,7 +115,7 @@ def send_grade_if_interesting(user, course_run_key, mode, status, letter_grade,
|
||||
if not is_course_run_in_a_program(course_run_key):
|
||||
if verbose:
|
||||
log.info(
|
||||
"Skipping send grade: course run not in a program. [{course_id}]".format(course_id=str(course_run_key))
|
||||
u"Skipping send grade: course run not in a program. [{course_id}]".format(course_id=str(course_run_key))
|
||||
)
|
||||
return
|
||||
|
||||
@@ -125,7 +125,7 @@ def send_grade_if_interesting(user, course_run_key, mode, status, letter_grade,
|
||||
if grade is None:
|
||||
if verbose:
|
||||
log.info(
|
||||
"Skipping send grade: No grade found for user [{username}] & course_id [{course_id}]".format(
|
||||
u"Skipping send grade: No grade found for user [{username}] & course_id [{course_id}]".format(
|
||||
username=getattr(user, 'username', None),
|
||||
course_id=str(course_run_key)
|
||||
)
|
||||
|
||||
@@ -27,7 +27,7 @@ MAX_RETRIES = 11
|
||||
@task(bind=True, ignore_result=True, routing_key=ROUTING_KEY)
|
||||
def send_grade_to_credentials(self, username, course_run_key, verified, letter_grade, percent_grade):
|
||||
""" Celery task to notify the Credentials IDA of a grade change via POST. """
|
||||
logger.info('Running task send_grade_to_credentials for username %s and course %s', username, course_run_key)
|
||||
logger.info(u'Running task send_grade_to_credentials for username %s and course %s', username, course_run_key)
|
||||
|
||||
countdown = 2 ** self.request.retries
|
||||
course_key = CourseKey.from_string(course_run_key)
|
||||
@@ -46,8 +46,8 @@ def send_grade_to_credentials(self, username, course_run_key, verified, letter_g
|
||||
'verified': verified,
|
||||
})
|
||||
|
||||
logger.info('Sent grade for course %s to user %s', course_run_key, username)
|
||||
logger.info(u'Sent grade for course %s to user %s', course_run_key, username)
|
||||
|
||||
except Exception as exc:
|
||||
logger.exception('Failed to send grade for course %s to user %s', course_run_key, username)
|
||||
logger.exception(u'Failed to send grade for course %s to user %s', course_run_key, username)
|
||||
raise self.retry(exc=exc, countdown=countdown, max_retries=MAX_RETRIES)
|
||||
|
||||
@@ -264,8 +264,8 @@ def create_credit_request(course_key, provider_id, username):
|
||||
final_grade = unicode(final_grade)
|
||||
|
||||
except (CreditRequirementStatus.DoesNotExist, TypeError, KeyError):
|
||||
msg = 'Could not retrieve final grade from the credit eligibility table for ' \
|
||||
'user [{user_id}] in course [{course_key}].'.format(user_id=user.id, course_key=course_key)
|
||||
msg = u'Could not retrieve final grade from the credit eligibility table for ' \
|
||||
u'user [{user_id}] in course [{course_key}].'.format(user_id=user.id, course_key=course_key)
|
||||
log.exception(msg)
|
||||
raise UserIsNotEligible(msg)
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ from eventtracking import tracker
|
||||
from openedx.core.djangoapps.commerce.utils import ecommerce_api_client
|
||||
from openedx.core.djangoapps.credit.models import CreditConfig, CreditProvider
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangolib.markup import HTML
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -36,7 +37,7 @@ def send_credit_notifications(username, course_key):
|
||||
try:
|
||||
user = User.objects.get(username=username)
|
||||
except User.DoesNotExist:
|
||||
log.error('No user with %s exist', username)
|
||||
log.error(u'No user with %s exist', username)
|
||||
return
|
||||
|
||||
course = modulestore().get_course(course_key, depth=0)
|
||||
@@ -150,7 +151,7 @@ def with_inline_css(html_without_css):
|
||||
import pynliner
|
||||
|
||||
# insert style tag in the html and run pyliner.
|
||||
html_with_inline_css = pynliner.fromString('<style>' + css_content + '</style>' + html_without_css)
|
||||
html_with_inline_css = pynliner.fromString(HTML('<style>{}</style>{}').format(css_content, html_without_css))
|
||||
return html_with_inline_css
|
||||
|
||||
return html_without_css
|
||||
@@ -167,7 +168,7 @@ def attach_image(img_dict, filename):
|
||||
if img_path:
|
||||
with open(img_path, 'rb') as img:
|
||||
msg_image = MIMEImage(img.read(), name=os.path.basename(img_path))
|
||||
msg_image.add_header('Content-ID', '<{}>'.format(img_dict['cid']))
|
||||
msg_image.add_header('Content-ID', b'<{}>'.format(img_dict['cid'])) # xss-lint: disable=python-wrap-html
|
||||
msg_image.add_header("Content-Disposition", "inline", filename=filename)
|
||||
return msg_image
|
||||
|
||||
@@ -223,11 +224,11 @@ def get_credit_provider_display_names(course_key):
|
||||
user = User.objects.get(username=settings.ECOMMERCE_SERVICE_WORKER_USERNAME)
|
||||
response = ecommerce_api_client(user).courses(course_id).get(include_products=1)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
log.exception("Failed to receive data from the ecommerce course API for Course ID '%s'.", course_id)
|
||||
log.exception(u"Failed to receive data from the ecommerce course API for Course ID '%s'.", course_id)
|
||||
return provider_names
|
||||
|
||||
if not response:
|
||||
log.info("No Course information found from ecommerce API for Course ID '%s'.", course_id)
|
||||
log.info(u"No Course information found from ecommerce API for Course ID '%s'.", course_id)
|
||||
return provider_names
|
||||
|
||||
provider_ids = []
|
||||
@@ -265,14 +266,14 @@ def make_providers_strings(providers):
|
||||
|
||||
elif len(providers) == 2:
|
||||
# Translators: The join of two university names (e.g., Harvard and MIT).
|
||||
providers_string = _("{first_provider} and {second_provider}").format(
|
||||
providers_string = _(u"{first_provider} and {second_provider}").format(
|
||||
first_provider=providers[0],
|
||||
second_provider=providers[1]
|
||||
)
|
||||
else:
|
||||
# Translators: The join of three or more university names. The first of these formatting strings
|
||||
# represents a comma-separated list of names (e.g., MIT, Harvard, Dartmouth).
|
||||
providers_string = _("{first_providers}, and {last_provider}").format(
|
||||
providers_string = _(u"{first_providers}, and {last_provider}").format(
|
||||
first_providers=u", ".join(providers[:-1]),
|
||||
last_provider=providers[-1]
|
||||
)
|
||||
|
||||
@@ -133,10 +133,10 @@ class CreditService(object):
|
||||
# table. This will be to help debug any issues that might
|
||||
# arise in production
|
||||
log_msg = (
|
||||
'set_credit_requirement_status was called with '
|
||||
'user_id={user_id}, course_key_or_id={course_key_or_id} '
|
||||
'req_namespace={req_namespace}, req_name={req_name}, '
|
||||
'status={status}, reason={reason}'.format(
|
||||
u'set_credit_requirement_status was called with '
|
||||
u'user_id={user_id}, course_key_or_id={course_key_or_id} '
|
||||
u'req_namespace={req_namespace}, req_name={req_name}, '
|
||||
u'status={status}, reason={reason}'.format(
|
||||
user_id=user_id,
|
||||
course_key_or_id=course_key_or_id,
|
||||
req_namespace=req_namespace,
|
||||
@@ -189,9 +189,9 @@ class CreditService(object):
|
||||
# table. This will be to help debug any issues that might
|
||||
# arise in production
|
||||
log_msg = (
|
||||
'remove_credit_requirement_status was called with '
|
||||
'user_id={user_id}, course_key_or_id={course_key_or_id} '
|
||||
'req_namespace={req_namespace}, req_name={req_name}, '.format(
|
||||
u'remove_credit_requirement_status was called with '
|
||||
u'user_id={user_id}, course_key_or_id={course_key_or_id} '
|
||||
u'req_namespace={req_namespace}, req_name={req_name}, '.format(
|
||||
user_id=user_id,
|
||||
course_key_or_id=course_key_or_id,
|
||||
req_namespace=req_namespace,
|
||||
|
||||
@@ -36,10 +36,10 @@ def update_credit_course_requirements(course_id):
|
||||
requirements = _get_course_credit_requirements(course_key)
|
||||
set_credit_requirements(course_key, requirements)
|
||||
except (InvalidKeyError, ItemNotFoundError, InvalidCreditRequirements) as exc:
|
||||
LOGGER.error('Error on adding the requirements for course %s - %s', course_id, unicode(exc))
|
||||
LOGGER.error(u'Error on adding the requirements for course %s - %s', course_id, unicode(exc))
|
||||
raise update_credit_course_requirements.retry(args=[course_id], exc=exc)
|
||||
else:
|
||||
LOGGER.info('Requirements added for course %s', course_id)
|
||||
LOGGER.info(u'Requirements added for course %s', course_id)
|
||||
|
||||
|
||||
def _get_course_credit_requirements(course_key):
|
||||
@@ -95,7 +95,7 @@ def _get_min_grade_requirement(course_key):
|
||||
}
|
||||
]
|
||||
except AttributeError:
|
||||
LOGGER.error("The course %s does not has minimum_grade_credit attribute", unicode(course.id))
|
||||
LOGGER.error(u"The course %s does not has minimum_grade_credit attribute", unicode(course.id))
|
||||
else:
|
||||
return []
|
||||
|
||||
@@ -127,7 +127,7 @@ def _get_proctoring_requirements(course_key):
|
||||
usage_key = UsageKey.from_string(exam['content_id'])
|
||||
proctor_block = modulestore().get_item(usage_key)
|
||||
except (InvalidKeyError, ItemNotFoundError):
|
||||
LOGGER.info("Invalid content_id '%s' for proctored block '%s'", exam['content_id'], exam['exam_name'])
|
||||
LOGGER.info(u"Invalid content_id '%s' for proctored block '%s'", exam['content_id'], exam['exam_name'])
|
||||
proctor_block = None
|
||||
|
||||
if proctor_block:
|
||||
@@ -142,7 +142,7 @@ def _get_proctoring_requirements(course_key):
|
||||
|
||||
if requirements:
|
||||
log_msg = (
|
||||
'Registering the following as \'proctored_exam\' credit requirements: {log_msg}'.format(
|
||||
u'Registering the following as \'proctored_exam\' credit requirements: {log_msg}'.format(
|
||||
log_msg=requirements
|
||||
)
|
||||
)
|
||||
|
||||
@@ -699,7 +699,7 @@ class CreditRequirementApiTests(CreditApiTestBase):
|
||||
# strip enclosing angle brackets from 'logo_image' cache 'Content-ID'
|
||||
image_id = email_image.get('Content-ID', '')[1:-1]
|
||||
self.assertIsNotNone(image_id)
|
||||
self.assertIn(image_id, html_content_first)
|
||||
self.assertIn(image_id, html_content_first.decode('utf-8'))
|
||||
self.assertIn(
|
||||
'credit from Hogwarts School of Witchcraft and Wizardry for',
|
||||
html_content_first
|
||||
@@ -729,7 +729,7 @@ class CreditRequirementApiTests(CreditApiTestBase):
|
||||
# logo image is used
|
||||
email_payload_second = mail.outbox[1].attachments[0]._payload # pylint: disable=protected-access
|
||||
html_content_second = email_payload_second[0]._payload[1]._payload # pylint: disable=protected-access
|
||||
self.assertIn(image_id, html_content_second)
|
||||
self.assertIn(image_id, html_content_second.decode('utf-8'))
|
||||
|
||||
# The user should remain eligible even if the requirement status is later changed
|
||||
api.set_credit_requirement_status(
|
||||
@@ -1125,7 +1125,7 @@ class CreditProviderIntegrationApiTests(CreditApiTestBase):
|
||||
# Simulate users who registered accounts before the country field was introduced.
|
||||
# We need to manipulate the database directly because the country Django field
|
||||
# coerces None values to empty strings.
|
||||
query = "UPDATE auth_userprofile SET country = NULL WHERE id = %s"
|
||||
query = u"UPDATE auth_userprofile SET country = NULL WHERE id = %s"
|
||||
connection.cursor().execute(query, [str(self.user.profile.id)])
|
||||
|
||||
# Request should include an empty country field
|
||||
|
||||
@@ -228,7 +228,7 @@ class DarkLangMiddlewareTests(CacheIsolationTestCase):
|
||||
|
||||
self.assertAcceptEquals(
|
||||
'es-419;q=1.0',
|
||||
self.process_middleware_request(accept='{};q=1.0, pt;q=0.5'.format(latin_america_code))
|
||||
self.process_middleware_request(accept=b'{};q=1.0, pt;q=0.5'.format(latin_america_code))
|
||||
)
|
||||
|
||||
def assert_session_lang_equals(self, value, session):
|
||||
|
||||
@@ -94,7 +94,7 @@ class PreviewLanguageFragmentView(EdxFragmentView):
|
||||
set_user_preference(request.user, DARK_LANGUAGE_KEY, preview_language)
|
||||
PageLevelMessages.register_success_message(
|
||||
request,
|
||||
_('Language set to {preview_language}').format(
|
||||
_(u'Language set to {preview_language}').format(
|
||||
preview_language=preview_language
|
||||
)
|
||||
)
|
||||
|
||||
@@ -53,4 +53,4 @@ def show_reference_template(request, template):
|
||||
|
||||
return render_to_response(template, context)
|
||||
except TemplateDoesNotExist:
|
||||
return HttpResponseNotFound('Missing template {template}'.format(template=bleach.clean(template, strip=True)))
|
||||
return HttpResponseNotFound(u'Missing template {template}'.format(template=bleach.clean(template, strip=True)))
|
||||
|
||||
@@ -85,7 +85,7 @@ class IPFilterForm(forms.ModelForm):
|
||||
if not self._is_valid_ip(address):
|
||||
error_addresses.append(address)
|
||||
if error_addresses:
|
||||
msg = 'Invalid IP Address(es): {0}'.format(error_addresses)
|
||||
msg = u'Invalid IP Address(es): {0}'.format(error_addresses)
|
||||
msg += ' Please fix the error(s) and try again.'
|
||||
raise forms.ValidationError(msg)
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ class RestrictedCourse(models.Model):
|
||||
default=False,
|
||||
help_text=ugettext_lazy(
|
||||
u"Allow users who enrolled in an allowed country "
|
||||
u"to access restricted courses from excluded countries."
|
||||
"to access restricted courses from excluded countries."
|
||||
)
|
||||
)
|
||||
|
||||
@@ -525,7 +525,7 @@ class CountryAccessRule(models.Model):
|
||||
"""Invalidate the cache. """
|
||||
cache_key = cls.CACHE_KEY.format(course_key=course_key)
|
||||
cache.delete(cache_key)
|
||||
log.info("Invalidated country access list for course %s", course_key)
|
||||
log.info(u"Invalidated country access list for course %s", course_key)
|
||||
|
||||
class Meta(object):
|
||||
"""a course can be added with either black or white list. """
|
||||
|
||||
@@ -156,7 +156,7 @@ class EmbargoCheckAccessApiTests(ModuleStoreTestCase):
|
||||
# exception when the embargo middleware treated the value as a string.
|
||||
# In order to simulate this behavior, we can't simply set `profile.country = None`.
|
||||
# (because when we save it, it will set the database field to an empty string instead of NULL)
|
||||
query = "UPDATE auth_userprofile SET country = NULL WHERE id = %s"
|
||||
query = u"UPDATE auth_userprofile SET country = NULL WHERE id = %s"
|
||||
connection.cursor().execute(query, [str(self.user.profile.id)])
|
||||
|
||||
# Verify that we can check the user's access without error
|
||||
|
||||
@@ -45,7 +45,7 @@ class DjangoOpenIDStore(OpenIDStore):
|
||||
def storeAssociation(self, server_url, assoc):
|
||||
key = get_url_key(server_url)
|
||||
|
||||
log.info('storeAssociation {0}'.format(key))
|
||||
log.info(u'storeAssociation {0}'.format(key))
|
||||
|
||||
associations = cache.get(key, {})
|
||||
associations[assoc.handle] = assoc
|
||||
@@ -55,7 +55,7 @@ class DjangoOpenIDStore(OpenIDStore):
|
||||
def getAssociation(self, server_url, handle=None):
|
||||
key = get_url_key(server_url)
|
||||
|
||||
log.info('getAssociation {0}'.format(key))
|
||||
log.info(u'getAssociation {0}'.format(key))
|
||||
|
||||
associations = cache.get(key, {})
|
||||
|
||||
@@ -84,7 +84,7 @@ class DjangoOpenIDStore(OpenIDStore):
|
||||
def removeAssociation(self, server_url, handle):
|
||||
key = get_url_key(server_url)
|
||||
|
||||
log.info('removeAssociation {0}'.format(key))
|
||||
log.info(u'removeAssociation {0}'.format(key))
|
||||
|
||||
associations = cache.get(key, {})
|
||||
|
||||
@@ -105,7 +105,7 @@ class DjangoOpenIDStore(OpenIDStore):
|
||||
def useNonce(self, server_url, timestamp, salt):
|
||||
key = get_nonce_key(server_url, timestamp, salt)
|
||||
|
||||
log.info('useNonce {0}'.format(key))
|
||||
log.info(u'useNonce {0}'.format(key))
|
||||
|
||||
if abs(timestamp - time.time()) > nonce.SKEW:
|
||||
return False
|
||||
|
||||
@@ -100,7 +100,7 @@ class OpenIdProviderTest(TestCase):
|
||||
resp = self.client.post(url)
|
||||
code = 200
|
||||
self.assertEqual(resp.status_code, code,
|
||||
"got code {0} for url '{1}'. Expected code {2}"
|
||||
u"got code {0} for url '{1}'. Expected code {2}"
|
||||
.format(resp.status_code, url, code))
|
||||
|
||||
@skipUnless(settings.FEATURES.get('AUTH_USE_OPENID') and
|
||||
@@ -129,7 +129,7 @@ class OpenIdProviderTest(TestCase):
|
||||
resp = self.client.post(url)
|
||||
code = 200
|
||||
self.assertEqual(resp.status_code, code,
|
||||
"got code {0} for url '{1}'. Expected code {2}"
|
||||
u"got code {0} for url '{1}'. Expected code {2}"
|
||||
.format(resp.status_code, url, code))
|
||||
for expected_input in (
|
||||
'<input name="openid.ns" type="hidden" value="http://specs.openid.net/auth/2.0" />',
|
||||
@@ -216,7 +216,7 @@ class OpenIdProviderTest(TestCase):
|
||||
|
||||
code = expected_code
|
||||
self.assertEqual(resp.status_code, code,
|
||||
"got code {0} for url '{1}'. Expected code {2}"
|
||||
u"got code {0} for url '{1}'. Expected code {2}"
|
||||
.format(resp.status_code, url, code))
|
||||
|
||||
@skipUnless(settings.FEATURES.get('AUTH_USE_OPENID') and
|
||||
@@ -454,7 +454,7 @@ class OpenIdProviderLiveServerTest(LiveServerTestCase):
|
||||
resp = self.client.post(url)
|
||||
code = 200
|
||||
self.assertEqual(resp.status_code, code,
|
||||
"got code {0} for url '{1}'. Expected code {2}"
|
||||
u"got code {0} for url '{1}'. Expected code {2}"
|
||||
.format(resp.status_code, url, code))
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -222,7 +222,7 @@ class ShibSPTest(CacheIsolationTestCase):
|
||||
"""
|
||||
inactive_user = UserFactory.create(email='inactive@stanford.edu')
|
||||
if not log_user_string:
|
||||
log_user_string = "user.id: {}".format(inactive_user.id)
|
||||
log_user_string = u"user.id: {}".format(inactive_user.id)
|
||||
inactive_user.is_active = False
|
||||
inactive_user.save()
|
||||
request = self.request_factory.get('/shib-login')
|
||||
|
||||
@@ -45,7 +45,7 @@ class SSLClientTest(ModuleStoreTestCase):
|
||||
Tests SSL Authentication code sections of external_auth
|
||||
"""
|
||||
|
||||
AUTH_DN = '/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}'
|
||||
AUTH_DN = b'/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}'
|
||||
USER_NAME = 'test_user_ssl'
|
||||
USER_EMAIL = 'test_user_ssl@EDX.ORG'
|
||||
MOCK_URL = '/'
|
||||
@@ -98,7 +98,7 @@ class SSLClientTest(ModuleStoreTestCase):
|
||||
try:
|
||||
ExternalAuthMap.objects.get(external_id=self.USER_EMAIL)
|
||||
except ExternalAuthMap.DoesNotExist, ex:
|
||||
self.fail('User did not get properly added to external auth map, exception was {0}'.format(str(ex)))
|
||||
self.fail(u'User did not get properly added to external auth map, exception was {0}'.format(str(ex)))
|
||||
|
||||
with self.assertRaises(User.DoesNotExist):
|
||||
User.objects.get(email=self.USER_EMAIL)
|
||||
@@ -117,7 +117,7 @@ class SSLClientTest(ModuleStoreTestCase):
|
||||
try:
|
||||
ExternalAuthMap.objects.get(external_id=self.USER_EMAIL)
|
||||
except ExternalAuthMap.DoesNotExist, ex:
|
||||
self.fail('User did not get properly added to external auth map, exception was {0}'.format(str(ex)))
|
||||
self.fail(u'User did not get properly added to external auth map, exception was {0}'.format(str(ex)))
|
||||
|
||||
with self.assertRaises(User.DoesNotExist):
|
||||
User.objects.get(email=self.USER_EMAIL)
|
||||
@@ -136,11 +136,11 @@ class SSLClientTest(ModuleStoreTestCase):
|
||||
try:
|
||||
ExternalAuthMap.objects.get(external_id=self.USER_EMAIL)
|
||||
except ExternalAuthMap.DoesNotExist, ex:
|
||||
self.fail('User did not get properly added to external auth map, exception was {0}'.format(str(ex)))
|
||||
self.fail(u'User did not get properly added to external auth map, exception was {0}'.format(str(ex)))
|
||||
try:
|
||||
User.objects.get(email=self.USER_EMAIL)
|
||||
except ExternalAuthMap.DoesNotExist, ex:
|
||||
self.fail('User did not get properly added to internal users, exception was {0}'.format(str(ex)))
|
||||
self.fail(u'User did not get properly added to internal users, exception was {0}'.format(str(ex)))
|
||||
|
||||
@skip_unless_cms
|
||||
@override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP)
|
||||
@@ -162,11 +162,11 @@ class SSLClientTest(ModuleStoreTestCase):
|
||||
try:
|
||||
ExternalAuthMap.objects.get(external_id=self.USER_EMAIL)
|
||||
except ExternalAuthMap.DoesNotExist, ex:
|
||||
self.fail('User did not get properly added to external auth map, exception was {0}'.format(str(ex)))
|
||||
self.fail(u'User did not get properly added to external auth map, exception was {0}'.format(str(ex)))
|
||||
try:
|
||||
User.objects.get(email=self.USER_EMAIL)
|
||||
except ExternalAuthMap.DoesNotExist, ex:
|
||||
self.fail('User did not get properly added to internal users, exception was {0}'.format(str(ex)))
|
||||
self.fail(u'User did not get properly added to internal users, exception was {0}'.format(str(ex)))
|
||||
|
||||
@skip_unless_lms
|
||||
@override_settings(FEATURES=FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP)
|
||||
@@ -323,11 +323,11 @@ class SSLClientTest(ModuleStoreTestCase):
|
||||
try:
|
||||
ExternalAuthMap.objects.get(external_id=self.USER_EMAIL)
|
||||
except ExternalAuthMap.DoesNotExist, ex:
|
||||
self.fail('User did not get properly added to external auth map, exception was {0}'.format(str(ex)))
|
||||
self.fail(u'User did not get properly added to external auth map, exception was {0}'.format(str(ex)))
|
||||
try:
|
||||
User.objects.get(email=self.USER_EMAIL)
|
||||
except ExternalAuthMap.DoesNotExist, ex:
|
||||
self.fail('User did not get properly added to internal users, exception was {0}'.format(str(ex)))
|
||||
self.fail(u'User did not get properly added to internal users, exception was {0}'.format(str(ex)))
|
||||
self.assertEqual(1, len(ExternalAuthMap.objects.all()))
|
||||
|
||||
self.assertTrue(self.mock.called)
|
||||
|
||||
@@ -97,12 +97,12 @@ def openid_login_complete(request,
|
||||
oid_backend = openid_auth.OpenIDBackend()
|
||||
details = oid_backend._extract_user_details(openid_response) # pylint: disable=protected-access
|
||||
|
||||
log.debug('openid success, details=%s', details)
|
||||
log.debug(u'openid success, details=%s', details)
|
||||
|
||||
url = getattr(settings, 'OPENID_SSO_SERVER_URL', None)
|
||||
external_domain = "{0}{1}".format(OPENID_DOMAIN_PREFIX, url)
|
||||
fullname = '%s %s' % (details.get('first_name', ''),
|
||||
details.get('last_name', ''))
|
||||
external_domain = u"{0}{1}".format(OPENID_DOMAIN_PREFIX, url)
|
||||
fullname = u'%s %s' % (details.get('first_name', ''),
|
||||
details.get('last_name', ''))
|
||||
|
||||
return _external_login_or_signup(
|
||||
request,
|
||||
@@ -174,9 +174,9 @@ def _external_login_or_signup(request,
|
||||
# otherwise, there must have been an error, b/c we've already linked a user with these external
|
||||
# creds
|
||||
failure_msg = _(
|
||||
"You have already created an account using "
|
||||
"an external login like WebAuth or Shibboleth. "
|
||||
"Please contact {tech_support_email} for support."
|
||||
u"You have already created an account using "
|
||||
u"an external login like WebAuth or Shibboleth. "
|
||||
"Please contact {tech_support_email} for support." # pylint: disable=unicode-format-string
|
||||
).format(
|
||||
tech_support_email=get_value('email_from_address', settings.TECH_SUPPORT_EMAIL),
|
||||
)
|
||||
|
||||
@@ -43,4 +43,4 @@ class CountryMiddleware(object):
|
||||
country_code = pygeoip.GeoIP(settings.GEOIP_PATH).country_code_by_addr(new_ip_address)
|
||||
request.session['country_code'] = country_code
|
||||
request.session['ip_address'] = new_ip_address
|
||||
log.debug('Country code for IP: %s is set to %s', new_ip_address, country_code)
|
||||
log.debug(u'Country code for IP: %s is set to %s', new_ip_address, country_code)
|
||||
|
||||
@@ -30,8 +30,7 @@ def runchecks(include_extended=False):
|
||||
'message': message
|
||||
}
|
||||
except ImportError as e:
|
||||
raise ImproperlyConfigured('Error importing module %s: "%s"' % (module, e))
|
||||
raise ImproperlyConfigured(u'Error importing module %s: "%s"' % (module, e))
|
||||
except AttributeError:
|
||||
raise ImproperlyConfigured('Module "%s" does not define a "%s" callable' % (module, attr))
|
||||
|
||||
raise ImproperlyConfigured(u'Module "%s" does not define a "%s" callable' % (module, attr))
|
||||
return response_dict
|
||||
|
||||
@@ -8,6 +8,7 @@ from django.conf import settings
|
||||
|
||||
from xmodule.fields import Date
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
from openedx.core.djangolib.markup import HTML
|
||||
from openedx.core.lib.courses import course_image_url
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
@@ -80,7 +81,7 @@ class CourseDetails(object):
|
||||
Retrieve an attribute from a course's "about" info
|
||||
"""
|
||||
if attribute not in ABOUT_ATTRIBUTES + ['video']:
|
||||
raise ValueError("'{0}' is not a valid course about attribute.".format(attribute))
|
||||
raise ValueError(u"'{0}' is not a valid course about attribute.".format(attribute))
|
||||
|
||||
usage_key = course_key.make_usage_key('about', attribute)
|
||||
try:
|
||||
@@ -332,8 +333,7 @@ class CourseDetails(object):
|
||||
result = None
|
||||
if video_key:
|
||||
result = (
|
||||
'<iframe title="YouTube Video" width="560" height="315" src="//www.youtube.com/embed/' +
|
||||
video_key +
|
||||
'?rel=0" frameborder="0" allowfullscreen=""></iframe>'
|
||||
HTML(u'<iframe title="YouTube Video" width="560" height="315" src="//www.youtube.com/embed/{}?rel=0" '
|
||||
'frameborder="0" allowfullscreen=""></iframe>').format(video_key)
|
||||
)
|
||||
return result
|
||||
|
||||
@@ -61,12 +61,12 @@ class EdxClearExpiredTokensTests(TestCase):
|
||||
(
|
||||
LOGGER_NAME,
|
||||
'INFO',
|
||||
'Cleaning {} rows from {} table'.format(0, RefreshToken.__name__)
|
||||
u'Cleaning {} rows from {} table'.format(0, RefreshToken.__name__)
|
||||
),
|
||||
(
|
||||
LOGGER_NAME,
|
||||
'INFO',
|
||||
'Cleaning {} rows from {} table'.format(0, AccessToken.__name__),
|
||||
u'Cleaning {} rows from {} table'.format(0, AccessToken.__name__),
|
||||
),
|
||||
(
|
||||
LOGGER_NAME,
|
||||
|
||||
@@ -62,7 +62,7 @@ class AccessTokenLoginMixin(object):
|
||||
|
||||
return self.client.post(
|
||||
self.login_with_access_token_url,
|
||||
HTTP_AUTHORIZATION="Bearer {0}".format(access_token if access_token else self.access_token)
|
||||
HTTP_AUTHORIZATION=b"Bearer {0}".format(access_token if access_token else self.access_token)
|
||||
)
|
||||
|
||||
def _assert_access_token_is_valid(self, access_token=None):
|
||||
@@ -464,7 +464,7 @@ class TestAuthorizationView(_DispatchingViewTestCase):
|
||||
# is the application name specified?
|
||||
self.assertContains(
|
||||
response,
|
||||
"Authorize {name}".format(name=self.dot_app.name)
|
||||
u"Authorize {name}".format(name=self.dot_app.name)
|
||||
)
|
||||
|
||||
# are the cancel and allow buttons on the page?
|
||||
|
||||
@@ -56,5 +56,5 @@ class PasswordPolicyConfig(AppConfig):
|
||||
if isinstance(deadline, six.string_types):
|
||||
config[setting] = parse_date(deadline)
|
||||
except (ValueError, OverflowError):
|
||||
log.exception("Could not parse %s password policy rollout value of '%s'.", setting, deadline)
|
||||
log.exception(u"Could not parse %s password policy rollout value of '%s'.", setting, deadline)
|
||||
config[setting] = None
|
||||
|
||||
@@ -72,7 +72,7 @@ def enforce_compliance_on_login(user, password):
|
||||
if now >= deadline:
|
||||
raise NonCompliantPasswordException(
|
||||
HTML(_(
|
||||
'{strong_tag_open}We recently changed our password requirements{strong_tag_close}{break_line_tag}'
|
||||
u'{strong_tag_open}We recently changed our password requirements{strong_tag_close}{break_line_tag}'
|
||||
'Your current password does not meet the new security requirements. We just sent a password-reset '
|
||||
'message to the email address associated with this account. Thank you for helping us keep your data '
|
||||
'safe.'
|
||||
@@ -85,17 +85,17 @@ def enforce_compliance_on_login(user, password):
|
||||
else:
|
||||
raise NonCompliantPasswordWarning(
|
||||
HTML(_(
|
||||
'{strong_tag_open}Required Action: Please update your password{strong_tag_close}{break_line_tag}'
|
||||
'As of {deadline}, {platform_name} will require all learners to have complex passwords. Your current '
|
||||
'password does not meet these requirements. To reset your password, go to to '
|
||||
'{anchor_tag_open}Account Settings{anchor_tag_close}.'
|
||||
u'{strong_tag_open}Required Action: Please update your password{strong_tag_close}{break_line_tag}'
|
||||
u'As of {deadline}, {platform_name} will require all learners to have complex passwords. Your current '
|
||||
u'password does not meet these requirements. To reset your password, go to to '
|
||||
u'{anchor_tag_open}Account Settings{anchor_tag_close}.'
|
||||
)).format(
|
||||
strong_tag_open=HTML('<strong>'),
|
||||
strong_tag_close=HTML('</strong>'),
|
||||
break_line_tag=HTML('<br/>'),
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
deadline=strftime_localized(deadline, DEFAULT_SHORT_DATE_FORMAT),
|
||||
anchor_tag_open=HTML('<a href="{account_settings_url}">').format(
|
||||
anchor_tag_open=HTML(u'<a href="{account_settings_url}">').format(
|
||||
account_settings_url=settings.LMS_ROOT_URL + "/account/settings"
|
||||
),
|
||||
anchor_tag_close=HTML('</a>')
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# pylint: disable=unicode-format-string
|
||||
"""
|
||||
Defines the URL routes for this app.
|
||||
|
||||
@@ -5,6 +6,7 @@ NOTE: These views are deprecated. These routes are superseded by
|
||||
``/api/user/v1/accounts/{username}/image``, found in
|
||||
``openedx.core.djangoapps.user_api.urls``.
|
||||
"""
|
||||
# pylint: enable=unicode-format-string
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf.urls import url
|
||||
|
||||
@@ -27,8 +27,8 @@ from .images import IMAGE_TYPES, create_profile_images, remove_profile_images, v
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
LOG_MESSAGE_CREATE = 'Generated and uploaded images %(image_names)s for user %(user_id)s'
|
||||
LOG_MESSAGE_DELETE = 'Deleted images %(image_names)s for user %(user_id)s'
|
||||
LOG_MESSAGE_CREATE = u'Generated and uploaded images %(image_names)s for user %(user_id)s'
|
||||
LOG_MESSAGE_DELETE = u'Deleted images %(image_names)s for user %(user_id)s'
|
||||
|
||||
|
||||
def _make_upload_dt():
|
||||
|
||||
@@ -44,10 +44,10 @@ class Command(BaseCommand):
|
||||
self._load_usernames()
|
||||
|
||||
if options.get('commit'):
|
||||
logger.info('Enqueuing program certification tasks for %d candidates.', len(self.usernames))
|
||||
logger.info(u'Enqueuing program certification tasks for %d candidates.', len(self.usernames))
|
||||
else:
|
||||
logger.info(
|
||||
'Found %d candidates. To enqueue program certification tasks, pass the -c or --commit flags.',
|
||||
u'Found %d candidates. To enqueue program certification tasks, pass the -c or --commit flags.',
|
||||
len(self.usernames)
|
||||
)
|
||||
return
|
||||
@@ -58,14 +58,14 @@ class Command(BaseCommand):
|
||||
award_program_certificates.delay(username)
|
||||
except: # pylint: disable=bare-except
|
||||
failed += 1
|
||||
logger.exception('Failed to enqueue task for user [%s]', username)
|
||||
logger.exception(u'Failed to enqueue task for user [%s]', username)
|
||||
else:
|
||||
succeeded += 1
|
||||
logger.debug('Successfully enqueued task for user [%s]', username)
|
||||
logger.debug(u'Successfully enqueued task for user [%s]', username)
|
||||
|
||||
logger.info(
|
||||
'Done. Successfully enqueued tasks for %d candidates. '
|
||||
'Failed to enqueue tasks for %d candidates.',
|
||||
u'Done. Successfully enqueued tasks for %d candidates. '
|
||||
u'Failed to enqueue tasks for %d candidates.',
|
||||
succeeded,
|
||||
failed
|
||||
)
|
||||
@@ -74,7 +74,7 @@ class Command(BaseCommand):
|
||||
"""Find all course runs which are part of a program."""
|
||||
programs = []
|
||||
for site in Site.objects.all():
|
||||
logger.info('Loading programs from the catalog for site %s.', site.domain)
|
||||
logger.info(u'Loading programs from the catalog for site %s.', site.domain)
|
||||
programs.extend(get_programs(site))
|
||||
|
||||
self.course_runs = self._flatten(programs)
|
||||
|
||||
@@ -44,7 +44,7 @@ def handle_course_cert_awarded(sender, user, course_key, mode, status, **kwargs)
|
||||
|
||||
# schedule background task to process
|
||||
LOGGER.debug(
|
||||
'handling COURSE_CERT_AWARDED: username=%s, course_key=%s, mode=%s, status=%s',
|
||||
u'handling COURSE_CERT_AWARDED: username=%s, course_key=%s, mode=%s, status=%s',
|
||||
user,
|
||||
course_key,
|
||||
mode,
|
||||
@@ -83,7 +83,7 @@ def handle_course_cert_changed(sender, user, course_key, mode, status, **kwargs)
|
||||
|
||||
verbose = kwargs.get('verbose', False)
|
||||
if verbose:
|
||||
msg = "Starting handle_course_cert_changed with params: "\
|
||||
msg = u"Starting handle_course_cert_changed with params: "\
|
||||
"sender [{sender}], "\
|
||||
"user [{username}], "\
|
||||
"course_key [{course_key}], "\
|
||||
@@ -112,7 +112,7 @@ def handle_course_cert_changed(sender, user, course_key, mode, status, **kwargs)
|
||||
if not helpers.get_value_for_org(course_key.org, 'ENABLE_LEARNER_RECORDS', True):
|
||||
if verbose:
|
||||
LOGGER.info(
|
||||
"Skipping send cert: ENABLE_LEARNER_RECORDS False for org [{org}]".format(
|
||||
u"Skipping send cert: ENABLE_LEARNER_RECORDS False for org [{org}]".format(
|
||||
org=course_key.org
|
||||
)
|
||||
)
|
||||
@@ -120,7 +120,7 @@ def handle_course_cert_changed(sender, user, course_key, mode, status, **kwargs)
|
||||
|
||||
# schedule background task to process
|
||||
LOGGER.debug(
|
||||
'handling COURSE_CERT_CHANGED: username=%s, course_key=%s, mode=%s, status=%s',
|
||||
u'handling COURSE_CERT_CHANGED: username=%s, course_key=%s, mode=%s, status=%s',
|
||||
user,
|
||||
course_key,
|
||||
mode,
|
||||
|
||||
@@ -124,7 +124,7 @@ def award_program_certificates(self, username):
|
||||
None
|
||||
|
||||
"""
|
||||
LOGGER.info('Running task award_program_certificates for username %s', username)
|
||||
LOGGER.info(u'Running task award_program_certificates for username %s', username)
|
||||
programs_without_certificates = configuration_helpers.get_value('programs_without_certificates', [])
|
||||
if programs_without_certificates:
|
||||
if str(programs_without_certificates[0]).lower() == "all":
|
||||
@@ -147,7 +147,7 @@ def award_program_certificates(self, username):
|
||||
try:
|
||||
student = User.objects.get(username=username)
|
||||
except User.DoesNotExist:
|
||||
LOGGER.exception('Task award_program_certificates was called with invalid username %s', username)
|
||||
LOGGER.exception(u'Task award_program_certificates was called with invalid username %s', username)
|
||||
# Don't retry for this case - just conclude the task.
|
||||
return
|
||||
completed_programs = {}
|
||||
@@ -156,7 +156,7 @@ def award_program_certificates(self, username):
|
||||
if not completed_programs:
|
||||
# No reason to continue beyond this point unless/until this
|
||||
# task gets updated to support revocation of program certs.
|
||||
LOGGER.info('Task award_program_certificates was called for user %s with no completed programs', username)
|
||||
LOGGER.info(u'Task award_program_certificates was called for user %s with no completed programs', username)
|
||||
return
|
||||
|
||||
# Determine which program certificates the user has already been awarded, if any.
|
||||
@@ -167,7 +167,7 @@ def award_program_certificates(self, username):
|
||||
awarded_and_skipped_program_uuids = list(set(existing_program_uuids + list(programs_without_certificates)))
|
||||
|
||||
except Exception as exc:
|
||||
LOGGER.exception('Failed to determine program certificates to be awarded for user %s', username)
|
||||
LOGGER.exception(u'Failed to determine program certificates to be awarded for user %s', username)
|
||||
raise self.retry(exc=exc, countdown=countdown, max_retries=MAX_RETRIES)
|
||||
|
||||
# For each completed program for which the student doesn't already have a
|
||||
@@ -192,10 +192,10 @@ def award_program_certificates(self, username):
|
||||
visible_date = completed_programs[program_uuid]
|
||||
try:
|
||||
award_program_certificate(credentials_client, username, program_uuid, visible_date)
|
||||
LOGGER.info('Awarded certificate for program %s to user %s', program_uuid, username)
|
||||
LOGGER.info(u'Awarded certificate for program %s to user %s', program_uuid, username)
|
||||
except exceptions.HttpNotFoundError:
|
||||
LOGGER.exception(
|
||||
"""Certificate for program {uuid} could not be found. Unable to award certificate to user
|
||||
u"""Certificate for program {uuid} could not be found. Unable to award certificate to user
|
||||
{username}. The program might not be configured.""".format(uuid=program_uuid, username=username)
|
||||
)
|
||||
except exceptions.HttpClientError as exc:
|
||||
@@ -206,39 +206,39 @@ def award_program_certificates(self, username):
|
||||
if exc.response.status_code == 429: # pylint: disable=no-member
|
||||
rate_limit_countdown = 60
|
||||
LOGGER.info(
|
||||
"""Rate limited. Retrying task to award certificates to user {username} in {countdown}
|
||||
u"""Rate limited. Retrying task to award certificates to user {username} in {countdown}
|
||||
seconds""".format(username=username, countdown=rate_limit_countdown)
|
||||
)
|
||||
# Retry after 60 seconds, when we should be in a new throttling window
|
||||
raise self.retry(exc=exc, countdown=rate_limit_countdown, max_retries=MAX_RETRIES)
|
||||
else:
|
||||
LOGGER.exception(
|
||||
"""Unable to award certificate to user {username} for program {uuid}. The program might not be
|
||||
u"""Unable to award certificate to user {username} for program {uuid}. The program might not be
|
||||
configured.""".format(username=username, uuid=program_uuid)
|
||||
)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# keep trying to award other certs, but retry the whole task to fix any missing entries
|
||||
LOGGER.warning('Failed to award certificate for program {uuid} to user {username}.'.format(
|
||||
LOGGER.warning(u'Failed to award certificate for program {uuid} to user {username}.'.format(
|
||||
uuid=program_uuid, username=username))
|
||||
failed_program_certificate_award_attempts.append(program_uuid)
|
||||
|
||||
if failed_program_certificate_award_attempts:
|
||||
# N.B. This logic assumes that this task is idempotent
|
||||
LOGGER.info('Retrying task to award failed certificates to user %s', username)
|
||||
LOGGER.info(u'Retrying task to award failed certificates to user %s', username)
|
||||
# The error message may change on each reattempt but will never be raised until
|
||||
# the max number of retries have been exceeded. It is unlikely that this list
|
||||
# will change by the time it reaches its maximimum number of attempts.
|
||||
exception = MaxRetriesExceededError(
|
||||
"Failed to award certificate for user {} for programs {}".format(
|
||||
u"Failed to award certificate for user {} for programs {}".format(
|
||||
username, failed_program_certificate_award_attempts))
|
||||
raise self.retry(
|
||||
exc=exception,
|
||||
countdown=countdown,
|
||||
max_retries=MAX_RETRIES)
|
||||
else:
|
||||
LOGGER.info('User %s is not eligible for any new program certificates', username)
|
||||
LOGGER.info(u'User %s is not eligible for any new program certificates', username)
|
||||
|
||||
LOGGER.info('Successfully completed the task award_program_certificates for username %s', username)
|
||||
LOGGER.info(u'Successfully completed the task award_program_certificates for username %s', username)
|
||||
|
||||
|
||||
def post_course_certificate(client, username, certificate, visible_date):
|
||||
@@ -268,7 +268,7 @@ def award_course_certificate(self, username, course_run_key):
|
||||
This task is designed to be called whenever a student GeneratedCertificate is updated.
|
||||
It can be called independently for a username and a course_run, but is invoked on each GeneratedCertificate.save.
|
||||
"""
|
||||
LOGGER.info('Running task award_course_certificate for username %s', username)
|
||||
LOGGER.info(u'Running task award_course_certificate for username %s', username)
|
||||
|
||||
countdown = 2 ** self.request.retries
|
||||
|
||||
@@ -288,7 +288,7 @@ def award_course_certificate(self, username, course_run_key):
|
||||
try:
|
||||
user = User.objects.get(username=username)
|
||||
except User.DoesNotExist:
|
||||
LOGGER.exception('Task award_course_certificate was called with invalid username %s', username)
|
||||
LOGGER.exception(u'Task award_course_certificate was called with invalid username %s', username)
|
||||
# Don't retry for this case - just conclude the task.
|
||||
return
|
||||
# Get the cert for the course key and username if it's both passing and available in professional/verified
|
||||
@@ -299,7 +299,7 @@ def award_course_certificate(self, username, course_run_key):
|
||||
)
|
||||
except GeneratedCertificate.DoesNotExist:
|
||||
LOGGER.exception(
|
||||
'Task award_course_certificate was called without Certificate found for %s to user %s',
|
||||
u'Task award_course_certificate was called without Certificate found for %s to user %s',
|
||||
course_key,
|
||||
username
|
||||
)
|
||||
@@ -309,7 +309,7 @@ def award_course_certificate(self, username, course_run_key):
|
||||
course_overview = CourseOverview.get_from_id(course_key)
|
||||
except (CourseOverview.DoesNotExist, IOError):
|
||||
LOGGER.exception(
|
||||
'Task award_course_certificate was called without course overview data for course %s',
|
||||
u'Task award_course_certificate was called without course overview data for course %s',
|
||||
course_key
|
||||
)
|
||||
return
|
||||
@@ -323,7 +323,7 @@ def award_course_certificate(self, username, course_run_key):
|
||||
visible_date = available_date_for_certificate(course_overview, certificate)
|
||||
post_course_certificate(credentials_client, username, certificate, visible_date)
|
||||
|
||||
LOGGER.info('Awarded certificate for course %s to user %s', course_key, username)
|
||||
LOGGER.info(u'Awarded certificate for course %s to user %s', course_key, username)
|
||||
except Exception as exc:
|
||||
LOGGER.exception('Failed to determine course certificates to be awarded for user %s', username)
|
||||
LOGGER.exception(u'Failed to determine course certificates to be awarded for user %s', username)
|
||||
raise self.retry(exc=exc, countdown=countdown, max_retries=MAX_RETRIES)
|
||||
|
||||
@@ -319,7 +319,7 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
|
||||
|
||||
self.assertEqual(mock_award_program_certificate.call_count, 3)
|
||||
mock_warning.assert_called_once_with(
|
||||
'Failed to award certificate for program {uuid} to user {username}.'.format(
|
||||
u'Failed to award certificate for program {uuid} to user {username}.'.format(
|
||||
uuid=1,
|
||||
username=self.student.username)
|
||||
)
|
||||
|
||||
@@ -500,7 +500,7 @@ class ProgramDataExtender(object):
|
||||
try:
|
||||
self.course_overview = CourseOverview.get_from_id(self.course_run_key)
|
||||
except CourseOverview.DoesNotExist:
|
||||
log.warning('Failed to get course overview for course run key: %s',
|
||||
log.warning(u'Failed to get course overview for course run key: %s',
|
||||
self.course_run.get('key'),
|
||||
exec_info=True)
|
||||
else:
|
||||
@@ -695,7 +695,7 @@ class ProgramDataExtender(object):
|
||||
'variant': bundle_variant
|
||||
})
|
||||
except (ConnectionError, SlumberBaseException, Timeout):
|
||||
log.exception('Failed to get discount price for following product SKUs: %s ', ', '.join(skus))
|
||||
log.exception(u'Failed to get discount price for following product SKUs: %s ', ', '.join(skus))
|
||||
self.data.update({
|
||||
'discount_data': {'is_discounted': False}
|
||||
})
|
||||
|
||||
@@ -146,12 +146,12 @@ class SafeCookieData(object):
|
||||
safe_cookie_data = SafeCookieData(*raw_cookie_components)
|
||||
except TypeError:
|
||||
raise SafeCookieError(
|
||||
"SafeCookieData BWC parse error: {0!r}.".format(safe_cookie_string)
|
||||
u"SafeCookieData BWC parse error: {0!r}.".format(safe_cookie_string)
|
||||
)
|
||||
else:
|
||||
if safe_cookie_data.version != cls.CURRENT_VERSION:
|
||||
raise SafeCookieError(
|
||||
"SafeCookieData version {0!r} is not supported. Current version is {1}.".format(
|
||||
u"SafeCookieData version {0!r} is not supported. Current version is {1}.".format(
|
||||
safe_cookie_data.version,
|
||||
cls.CURRENT_VERSION,
|
||||
))
|
||||
@@ -182,10 +182,10 @@ class SafeCookieData(object):
|
||||
unsigned_data = signing.loads(self.signature, salt=self.key_salt, max_age=settings.SESSION_COOKIE_AGE)
|
||||
if unsigned_data == self._compute_digest(user_id):
|
||||
return True
|
||||
log.error("SafeCookieData '%r' is not bound to user '%s'.", unicode(self), user_id)
|
||||
log.error(u"SafeCookieData '%r' is not bound to user '%s'.", unicode(self), user_id)
|
||||
except signing.BadSignature as sig_error:
|
||||
log.error(
|
||||
"SafeCookieData signature error for cookie data {0!r}: {1}".format( # pylint: disable=logging-format-interpolation
|
||||
u"SafeCookieData signature error for cookie data {0!r}: {1}".format( # pylint: disable=logging-format-interpolation
|
||||
unicode(self),
|
||||
text_type(sig_error),
|
||||
)
|
||||
@@ -215,7 +215,7 @@ class SafeCookieData(object):
|
||||
if not session_id or session_id == unicode(None):
|
||||
# The session ID should always be valid in the cookie.
|
||||
raise SafeCookieError(
|
||||
"SafeCookieData not created due to invalid value for session_id '{}' for user_id '{}'.".format(
|
||||
u"SafeCookieData not created due to invalid value for session_id '{}' for user_id '{}'.".format(
|
||||
session_id,
|
||||
user_id,
|
||||
))
|
||||
@@ -226,7 +226,7 @@ class SafeCookieData(object):
|
||||
# as some of the session requests are made as
|
||||
# Anonymous users.
|
||||
log.debug(
|
||||
"SafeCookieData received empty user_id '%s' for session_id '%s'.",
|
||||
u"SafeCookieData received empty user_id '%s' for session_id '%s'.",
|
||||
user_id,
|
||||
session_id,
|
||||
)
|
||||
@@ -367,14 +367,14 @@ class SafeSessionMiddleware(SessionMiddleware):
|
||||
# conditionally set the log level.
|
||||
log_func = log.debug if request.user.id is None else log.warning
|
||||
log_func(
|
||||
"SafeCookieData user at request '{0}' does not match user at response: '{1}'".format(
|
||||
u"SafeCookieData user at request '{0}' does not match user at response: '{1}'".format(
|
||||
request.safe_cookie_verified_user_id,
|
||||
request.user.id,
|
||||
),
|
||||
)
|
||||
if request.safe_cookie_verified_user_id != userid_in_session:
|
||||
log.warning(
|
||||
"SafeCookieData user at request '{0}' does not match user in session: '{1}'".format( # pylint: disable=logging-format-interpolation
|
||||
u"SafeCookieData user at request '{0}' does not match user in session: '{1}'".format( # pylint: disable=logging-format-interpolation
|
||||
request.safe_cookie_verified_user_id,
|
||||
userid_in_session,
|
||||
),
|
||||
|
||||
@@ -120,7 +120,7 @@ class TestSafeSessionsLogMixin(object):
|
||||
was not equal to user at response
|
||||
"""
|
||||
with self.assert_logged_with_message(
|
||||
"SafeCookieData user at request '{}' does not match user at response: '{}'".format(
|
||||
u"SafeCookieData user at request '{}' does not match user at response: '{}'".format(
|
||||
user_at_request, user_at_response
|
||||
),
|
||||
log_level=log_level,
|
||||
@@ -134,7 +134,7 @@ class TestSafeSessionsLogMixin(object):
|
||||
was not equal to user at session
|
||||
"""
|
||||
with self.assert_logged_with_message(
|
||||
"SafeCookieData user at request '{}' does not match user in session: '{}'".format(
|
||||
u"SafeCookieData user at request '{}' does not match user in session: '{}'".format(
|
||||
user_at_request, user_in_session
|
||||
),
|
||||
log_level='warning',
|
||||
|
||||
@@ -34,14 +34,20 @@ def _set_experience(db_name, human_name, modeladmin, request, queryset):
|
||||
).update(
|
||||
experience_type=db_name
|
||||
)
|
||||
modeladmin.message_user(request, "{} schedule(s) were changed to use the {} experience".format(rows_updated, human_name))
|
||||
modeladmin.message_user(
|
||||
request,
|
||||
u"{} schedule(s) were changed to use the {} experience".format(
|
||||
rows_updated,
|
||||
human_name,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# Generate a list of all "set_experience_to_X" actions
|
||||
experience_actions = []
|
||||
for (db_name, human_name) in models.ScheduleExperience.EXPERIENCES:
|
||||
partial = functools.partial(_set_experience, db_name, human_name)
|
||||
partial.short_description = "Convert the selected schedules to the {} experience".format(human_name)
|
||||
partial.short_description = u"Convert the selected schedules to the {} experience".format(human_name)
|
||||
partial.__name__ = "set_experience_to_{}".format(db_name)
|
||||
experience_actions.append(partial)
|
||||
|
||||
@@ -128,12 +134,12 @@ class ScheduleAdmin(admin.ModelAdmin):
|
||||
|
||||
def deactivate_schedules(self, request, queryset):
|
||||
rows_updated = queryset.update(active=False)
|
||||
self.message_user(request, "{} schedule(s) were deactivated".format(rows_updated))
|
||||
self.message_user(request, u"{} schedule(s) were deactivated".format(rows_updated))
|
||||
deactivate_schedules.short_description = "Deactivate selected schedules"
|
||||
|
||||
def activate_schedules(self, request, queryset):
|
||||
rows_updated = queryset.update(active=True)
|
||||
self.message_user(request, "{} schedule(s) were activated".format(rows_updated))
|
||||
self.message_user(request, u"{} schedule(s) were activated".format(rows_updated))
|
||||
activate_schedules.short_description = "Activate selected schedules"
|
||||
|
||||
def experience_display(self, obj):
|
||||
|
||||
@@ -66,14 +66,14 @@ def _get_course_with_highlights(course_key):
|
||||
# pylint: disable=missing-docstring
|
||||
if not COURSE_UPDATE_WAFFLE_FLAG.is_enabled(course_key):
|
||||
raise CourseUpdateDoesNotExist(
|
||||
"%s Course Update Messages waffle flag is disabled.",
|
||||
u"%s Course Update Messages waffle flag is disabled.",
|
||||
course_key,
|
||||
)
|
||||
|
||||
course_descriptor = _get_course_descriptor(course_key)
|
||||
if not course_descriptor.highlights_enabled_for_messaging:
|
||||
raise CourseUpdateDoesNotExist(
|
||||
"%s Course Update Messages are disabled.",
|
||||
u"%s Course Update Messages are disabled.",
|
||||
course_key,
|
||||
)
|
||||
|
||||
@@ -84,7 +84,7 @@ def _get_course_descriptor(course_key):
|
||||
course_descriptor = modulestore().get_course(course_key, depth=1)
|
||||
if course_descriptor is None:
|
||||
raise CourseUpdateDoesNotExist(
|
||||
"Course {} not found.".format(course_key)
|
||||
u"Course {} not found.".format(course_key)
|
||||
)
|
||||
return course_descriptor
|
||||
|
||||
@@ -116,7 +116,7 @@ def _get_highlights_for_week(sections, week_num, course_key):
|
||||
num_sections = len(sections)
|
||||
if not (1 <= week_num <= num_sections):
|
||||
raise CourseUpdateDoesNotExist(
|
||||
"Requested week {} but {} has only {} sections.".format(
|
||||
u"Requested week {} but {} has only {} sections.".format(
|
||||
week_num, course_key, num_sections
|
||||
)
|
||||
)
|
||||
|
||||
@@ -30,10 +30,10 @@ class SendEmailBaseCommand(PrefixedDebugLoggerMixin, BaseCommand):
|
||||
*[int(x) for x in options['date'].split('-')],
|
||||
tzinfo=pytz.UTC
|
||||
)
|
||||
self.log_debug('Current date = %s', current_date.isoformat())
|
||||
self.log_debug(u'Current date = %s', current_date.isoformat())
|
||||
|
||||
site = Site.objects.get(domain__iexact=options['site_domain_name'])
|
||||
self.log_debug('Running for site %s', site.domain)
|
||||
self.log_debug(u'Running for site %s', site.domain)
|
||||
|
||||
override_recipient_email = options.get('override_recipient_email')
|
||||
self.send_emails(site, current_date, override_recipient_email)
|
||||
|
||||
@@ -66,7 +66,7 @@ class Command(BaseCommand):
|
||||
start=datetime.datetime.today() - datetime.timedelta(days=30),
|
||||
end=datetime.datetime.today() + datetime.timedelta(days=30),
|
||||
number=factory.Sequence('schedules_test_course_{}'.format),
|
||||
display_name=factory.Sequence('Schedules Test Course {}'.format),
|
||||
display_name=factory.Sequence(u'Schedules Test Course {}'.format),
|
||||
)
|
||||
XMODULE_FACTORY_LOCK.disable()
|
||||
course_overview = CourseOverview.load_from_module_store(course.id)
|
||||
|
||||
@@ -111,7 +111,7 @@ class ScheduleSendEmailTestMixin(FilteredQueryCountMixin):
|
||||
|
||||
def _get_template_overrides(self):
|
||||
templates_override = deepcopy(settings.TEMPLATES)
|
||||
templates_override[0]['OPTIONS']['string_if_invalid'] = "TEMPLATE WARNING - MISSING VARIABLE [%s]"
|
||||
templates_override[0]['OPTIONS']['string_if_invalid'] = u"TEMPLATE WARNING - MISSING VARIABLE [%s]"
|
||||
return templates_override
|
||||
|
||||
def _schedule_factory(self, offset=None, **factory_kwargs):
|
||||
@@ -187,7 +187,7 @@ class ScheduleSendEmailTestMixin(FilteredQueryCountMixin):
|
||||
target_day_str = serialize(target_day)
|
||||
|
||||
for b in range(self.task.num_bins):
|
||||
LOG.debug('Checking bin %d', b)
|
||||
LOG.debug(u'Checking bin %d', b)
|
||||
expected_queries = NUM_QUERIES_SITE_SCHEDULES
|
||||
if b in bins_in_use:
|
||||
if is_first_match:
|
||||
|
||||
@@ -49,7 +49,7 @@ class TestSendCourseUpdate(ScheduleUpsellTestMixin, ScheduleSendEmailTestMixin,
|
||||
super(TestSendCourseUpdate, self).setUp()
|
||||
self.highlights_patcher = patch('openedx.core.djangoapps.schedules.resolvers.get_week_highlights')
|
||||
mock_highlights = self.highlights_patcher.start()
|
||||
mock_highlights.return_value = ['Highlight {}'.format(num + 1) for num in range(3)]
|
||||
mock_highlights.return_value = [u'Highlight {}'.format(num + 1) for num in range(3)]
|
||||
self.addCleanup(self.stop_highlights_patcher)
|
||||
|
||||
def stop_highlights_patcher(self):
|
||||
|
||||
@@ -135,13 +135,13 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
|
||||
if "read_replica" in settings.DATABASES:
|
||||
schedules = schedules.using("read_replica")
|
||||
|
||||
LOG.info('Query = %r', schedules.query.sql_with_params())
|
||||
LOG.info(u'Query = %r', schedules.query.sql_with_params())
|
||||
|
||||
with function_trace('schedule_query_set_evaluation'):
|
||||
# This will run the query and cache all of the results in memory.
|
||||
num_schedules = len(schedules)
|
||||
|
||||
LOG.info('Number of schedules = %d', num_schedules)
|
||||
LOG.info(u'Number of schedules = %d', num_schedules)
|
||||
|
||||
# This should give us a sense of the volume of data being processed by each task.
|
||||
set_custom_metric('num_schedules', num_schedules)
|
||||
@@ -352,7 +352,7 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
|
||||
week_highlights = get_week_highlights(user, enrollment.course_id, week_num)
|
||||
except CourseUpdateDoesNotExist:
|
||||
LOG.warning(
|
||||
'Weekly highlights for user {} in week {} of course {} does not exist or is disabled'.format(
|
||||
u'Weekly highlights for user {} in week {} of course {} does not exist or is disabled'.format(
|
||||
user, week_num, enrollment.course_id
|
||||
)
|
||||
)
|
||||
|
||||
@@ -39,7 +39,7 @@ def create_schedule(sender, **kwargs): # pylint: disable=unused-argument
|
||||
if schedule_details:
|
||||
log.debug(
|
||||
'Schedules: created a new schedule starting at ' +
|
||||
'%s with an upgrade deadline of %s and experience type: %s',
|
||||
u'%s with an upgrade deadline of %s and experience type: %s',
|
||||
schedule_details['content_availability_date'],
|
||||
schedule_details['upgrade_deadline'],
|
||||
ScheduleExperience.EXPERIENCES[schedule_details['experience_type']]
|
||||
@@ -47,7 +47,7 @@ def create_schedule(sender, **kwargs): # pylint: disable=unused-argument
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# We do not want to block the creation of a CourseEnrollment because of an error in creating a Schedule.
|
||||
# No Schedule is acceptable, but no CourseEnrollment is not.
|
||||
log.exception('Encountered error in creating a Schedule for CourseEnrollment for user {} in course {}'.format(
|
||||
log.exception(u'Encountered error in creating a Schedule for CourseEnrollment for user {} in course {}'.format(
|
||||
enrollment.user.id if (enrollment and enrollment.user) else None,
|
||||
enrollment.course_id if enrollment else None
|
||||
))
|
||||
|
||||
@@ -53,7 +53,7 @@ def update_course_schedules(self, **kwargs):
|
||||
)
|
||||
except Exception as exc:
|
||||
if not isinstance(exc, KNOWN_RETRY_ERRORS):
|
||||
LOG.exception("Unexpected failure: task id: %s, kwargs=%s".format(self.request.id, kwargs))
|
||||
LOG.exception(u"Unexpected failure: task id: {}, kwargs={}".format(self.request.id, kwargs))
|
||||
raise self.retry(kwargs=kwargs, exc=exc)
|
||||
|
||||
|
||||
@@ -89,11 +89,11 @@ class ScheduleMessageBaseTask(LoggedTask):
|
||||
current_date = resolvers._get_datetime_beginning_of_day(current_date)
|
||||
|
||||
if not cls.is_enqueue_enabled(site):
|
||||
cls.log_info('Message queuing disabled for site %s', site.domain)
|
||||
cls.log_info(u'Message queuing disabled for site %s', site.domain)
|
||||
return
|
||||
|
||||
target_date = current_date + datetime.timedelta(days=day_offset)
|
||||
cls.log_info('Target date = %s', target_date.isoformat())
|
||||
cls.log_info(u'Target date = %s', target_date.isoformat())
|
||||
for bin in range(cls.num_bins):
|
||||
task_args = (
|
||||
site.id,
|
||||
@@ -102,7 +102,7 @@ class ScheduleMessageBaseTask(LoggedTask):
|
||||
bin,
|
||||
override_recipient_email,
|
||||
)
|
||||
cls.log_info('Launching task with args = %r', task_args)
|
||||
cls.log_info(u'Launching task with args = %r', task_args)
|
||||
cls().apply_async(
|
||||
task_args,
|
||||
retry=False,
|
||||
@@ -205,7 +205,7 @@ def _schedule_send(msg_str, site_id, delivery_config_var, log_prefix):
|
||||
user = User.objects.get(username=msg.recipient.username)
|
||||
with emulate_http_request(site=site, user=user):
|
||||
_annonate_send_task_for_monitoring(msg)
|
||||
LOG.debug('%s: Sending message = %s', log_prefix, msg_str)
|
||||
LOG.debug(u'%s: Sending message = %s', log_prefix, msg_str)
|
||||
ace.send(msg)
|
||||
_track_message_sent(site, user, msg)
|
||||
|
||||
@@ -250,7 +250,7 @@ def _is_delivery_enabled(site, delivery_config_var, log_prefix):
|
||||
if getattr(ScheduleConfig.current(site), delivery_config_var, False):
|
||||
return True
|
||||
else:
|
||||
LOG.info('%s: Message delivery disabled for site %s', log_prefix, site.domain)
|
||||
LOG.info(u'%s: Message delivery disabled for site %s', log_prefix, site.domain)
|
||||
|
||||
|
||||
def _annotate_for_monitoring(message_type, site, bin_num, target_day_str, day_offset):
|
||||
|
||||
@@ -38,7 +38,7 @@ class TestScheduleMessageBaseTask(CacheIsolationTestCase):
|
||||
day_offset=2
|
||||
)
|
||||
patches['log_info'].assert_called_once_with(
|
||||
'Message queuing disabled for site %s', self.site.domain)
|
||||
u'Message queuing disabled for site %s', self.site.domain)
|
||||
send.apply_async.assert_not_called()
|
||||
|
||||
@ddt.data(0, 2, -3)
|
||||
@@ -59,7 +59,7 @@ class TestScheduleMessageBaseTask(CacheIsolationTestCase):
|
||||
target_date = current_date.replace(hour=0, minute=0, second=0, microsecond=0) + \
|
||||
datetime.timedelta(day_offset)
|
||||
patches['log_info'].assert_any_call(
|
||||
'Target date = %s', target_date.isoformat())
|
||||
u'Target date = %s', target_date.isoformat())
|
||||
assert send.call_count == DEFAULT_NUM_BINS
|
||||
|
||||
@ddt.data(True, False)
|
||||
|
||||
Reference in New Issue
Block a user