From 5c47a3b42536032608ef66d43b0412e01a87fe59 Mon Sep 17 00:00:00 2001 From: Ayub khan <muhammadayubkhan6@gmail.com> Date: Fri, 20 Sep 2019 18:15:54 +0500 Subject: [PATCH] BOM Project Updated __unicode__ to __str__ --- cms/djangoapps/course_creators/models.py | 4 ++- cms/djangoapps/xblock_config/models.py | 4 ++- cms/lib/xblock/tagging/models.py | 7 +++-- common/djangoapps/course_modes/models.py | 7 +++-- common/djangoapps/entitlements/models.py | 7 +++-- common/djangoapps/static_replace/models.py | 7 +++-- common/djangoapps/status/models.py | 7 +++-- common/djangoapps/student/models.py | 23 +++++++++------ common/djangoapps/track/backends/django.py | 4 ++- common/djangoapps/xblock_django/models.py | 10 +++++-- common/lib/capa/capa/capa_problem.py | 4 ++- common/lib/capa/capa/inputtypes.py | 5 ++-- common/lib/capa/capa/responsetypes.py | 6 ++-- .../xmodule/xmodule/library_root_xblock.py | 9 +++--- common/lib/xmodule/xmodule/modulestore/xml.py | 4 ++- common/lib/xmodule/xmodule/tests/__init__.py | 4 ++- common/lib/xmodule/xmodule/x_module.py | 4 ++- lms/djangoapps/badges/models.py | 13 ++++++--- lms/djangoapps/bulk_email/models.py | 19 +++++++++---- .../bulk_email/tests/test_models.py | 4 +-- lms/djangoapps/certificates/models.py | 13 ++++++--- lms/djangoapps/certificates/queue.py | 4 ++- lms/djangoapps/commerce/models.py | 4 ++- lms/djangoapps/course_goals/models.py | 4 ++- lms/djangoapps/courseware/models.py | 16 +++++++---- .../coursewarehistoryextended/models.py | 4 ++- lms/djangoapps/email_marketing/models.py | 4 ++- lms/djangoapps/grades/config/models.py | 8 ++++-- lms/djangoapps/grades/course_grade.py | 4 ++- lms/djangoapps/grades/models.py | 12 +++++--- lms/djangoapps/instructor_task/models.py | 4 ++- lms/djangoapps/instructor_task/subtasks.py | 4 ++- lms/djangoapps/mobile_api/models.py | 4 ++- lms/djangoapps/shoppingcart/models.py | 13 ++++++--- .../shoppingcart/tests/test_reports.py | 4 +-- .../shoppingcart/tests/test_views.py | 2 +- lms/djangoapps/verify_student/models.py | 7 +++-- openedx/core/djangoapps/api_admin/models.py | 6 ++-- openedx/core/djangoapps/bookmarks/models.py | 7 +++-- openedx/core/djangoapps/ccxcon/models.py | 6 ++-- .../content/block_structure/config/models.py | 4 ++- .../content/block_structure/models.py | 4 ++- .../content/block_structure/store.py | 4 ++- .../content/course_overviews/models.py | 13 ++++++--- .../djangoapps/content_libraries/models.py | 5 ++-- .../core/djangoapps/contentserver/models.py | 7 +++-- openedx/core/djangoapps/cors_csrf/models.py | 4 ++- .../core/djangoapps/course_groups/models.py | 4 ++- openedx/core/djangoapps/crawlers/models.py | 4 ++- openedx/core/djangoapps/credentials/models.py | 7 +++-- openedx/core/djangoapps/credit/models.py | 21 +++++++++----- openedx/core/djangoapps/dark_lang/models.py | 4 ++- .../django_comment_common/models.py | 6 ++-- openedx/core/djangoapps/embargo/models.py | 6 ++-- .../djangoapps/site_configuration/models.py | 11 +++++--- .../core/djangoapps/theming/helpers_dirs.py | 6 ++-- openedx/core/djangoapps/theming/models.py | 4 ++- openedx/core/djangoapps/user_api/models.py | 9 ++++-- .../core/djangoapps/video_config/models.py | 28 +++++++++++++------ .../core/djangoapps/video_pipeline/models.py | 7 +++-- .../core/djangoapps/waffle_utils/models.py | 4 ++- openedx/features/announcements/models.py | 4 ++- 62 files changed, 306 insertions(+), 142 deletions(-) diff --git a/cms/djangoapps/course_creators/models.py b/cms/djangoapps/course_creators/models.py index 998096473c5..fd80213757a 100644 --- a/cms/djangoapps/course_creators/models.py +++ b/cms/djangoapps/course_creators/models.py @@ -8,6 +8,7 @@ from django.db import models from django.db.models.signals import post_init, post_save from django.dispatch import Signal, receiver from django.utils import timezone +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ # A signal that will be sent when users should be added or removed from the creator group @@ -20,6 +21,7 @@ send_admin_notification = Signal(providing_args=["user"]) send_user_notification = Signal(providing_args=["user", "state"]) +@python_2_unicode_compatible class CourseCreator(models.Model): """ Creates the database table model. @@ -47,7 +49,7 @@ class CourseCreator(models.Model): note = models.CharField(max_length=512, blank=True, help_text=_("Optional notes about this user (for example, " "why course creation access was denied)")) - def __unicode__(self): + def __str__(self): return u"{0} | {1} [{2}]".format(self.user, self.state, self.state_changed) diff --git a/cms/djangoapps/xblock_config/models.py b/cms/djangoapps/xblock_config/models.py index 08d0f3d786f..5eac8045c9e 100644 --- a/cms/djangoapps/xblock_config/models.py +++ b/cms/djangoapps/xblock_config/models.py @@ -10,6 +10,7 @@ from __future__ import absolute_import import six from config_models.models import ConfigurationModel from django.db.models import TextField +from django.utils.encoding import python_2_unicode_compatible from opaque_keys.edx.django.models import CourseKeyField from openedx.core.lib.cache_utils import request_cached @@ -37,6 +38,7 @@ class StudioConfig(ConfigurationModel): # TODO: Move CourseEditLTIFieldsEnabledFlag to LTI XBlock as a part of EDUCATOR-121 # reference: https://openedx.atlassian.net/browse/EDUCATOR-121 +@python_2_unicode_compatible class CourseEditLTIFieldsEnabledFlag(ConfigurationModel): """ Enables the editing of "request username" and "request email" fields @@ -77,7 +79,7 @@ class CourseEditLTIFieldsEnabledFlag(ConfigurationModel): return course_specific_config.enabled if course_specific_config else False - def __unicode__(self): + def __str__(self): en = "Not " if self.enabled: en = "" diff --git a/cms/lib/xblock/tagging/models.py b/cms/lib/xblock/tagging/models.py index de1704f7f64..78b819f0a5d 100644 --- a/cms/lib/xblock/tagging/models.py +++ b/cms/lib/xblock/tagging/models.py @@ -4,8 +4,10 @@ Django Model for tags from __future__ import absolute_import from django.db import models +from django.utils.encoding import python_2_unicode_compatible +@python_2_unicode_compatible class TagCategories(models.Model): """ This model represents tag categories. @@ -21,7 +23,7 @@ class TagCategories(models.Model): verbose_name = "tag category" verbose_name_plural = "tag categories" - def __unicode__(self): + def __str__(self): return "[TagCategories] {}: {}".format(self.name, self.title) def get_values(self): @@ -31,6 +33,7 @@ class TagCategories(models.Model): return [t.value for t in TagAvailableValues.objects.filter(category=self)] +@python_2_unicode_compatible class TagAvailableValues(models.Model): """ This model represents available values for tags. @@ -45,5 +48,5 @@ class TagAvailableValues(models.Model): ordering = ('id',) verbose_name = "available tag value" - def __unicode__(self): + def __str__(self): return "[TagAvailableValues] {}: {}".format(self.category, self.value) diff --git a/common/djangoapps/course_modes/models.py b/common/djangoapps/course_modes/models.py index cc32e231687..04588a34287 100644 --- a/common/djangoapps/course_modes/models.py +++ b/common/djangoapps/course_modes/models.py @@ -14,6 +14,7 @@ from django.core.validators import validate_comma_separated_integer_list from django.db import models from django.db.models import Q from django.dispatch import receiver +from django.utils.encoding import python_2_unicode_compatible from django.utils.timezone import now from django.utils.translation import ugettext_lazy as _ from edx_django_utils.cache import RequestCache @@ -38,6 +39,7 @@ Mode = namedtuple('Mode', ]) +@python_2_unicode_compatible class CourseMode(models.Model): """ We would like to offer a course in a variety of modes. @@ -791,7 +793,7 @@ class CourseMode(models.Model): self.bulk_sku ) - def __unicode__(self): + def __str__(self): return u"{} : {}, min={}".format( self.course_id, self.mode_slug, self.min_price ) @@ -902,6 +904,7 @@ class CourseModesArchive(models.Model): expiration_datetime = models.DateTimeField(default=None, null=True, blank=True) +@python_2_unicode_compatible class CourseModeExpirationConfig(ConfigurationModel): """ Configuration for time period from end of course to auto-expire a course mode. @@ -918,6 +921,6 @@ class CourseModeExpirationConfig(ConfigurationModel): ) ) - def __unicode__(self): + def __str__(self): """ Returns the unicode date of the verification window. """ return six.text_type(self.verification_window) diff --git a/common/djangoapps/entitlements/models.py b/common/djangoapps/entitlements/models.py index 3f20ca975ca..364d43f4546 100644 --- a/common/djangoapps/entitlements/models.py +++ b/common/djangoapps/entitlements/models.py @@ -9,6 +9,7 @@ from datetime import timedelta from django.conf import settings from django.contrib.sites.models import Site from django.db import IntegrityError, models, transaction +from django.utils.encoding import python_2_unicode_compatible from django.utils.timezone import now from model_utils import Choices from model_utils.models import TimeStampedModel @@ -26,6 +27,7 @@ from util.date_utils import strftime_localized log = logging.getLogger("common.entitlements.models") +@python_2_unicode_compatible class CourseEntitlementPolicy(models.Model): """ Represents the Entitlement's policy for expiration, refunds, and regaining a used certificate @@ -138,7 +140,7 @@ class CourseEntitlementPolicy(models.Model): and not entitlement.enrollment_course_run and not entitlement.expired_at) - def __unicode__(self): + def __str__(self): return u'Course Entitlement Policy: expiration_period: {}, refund_period: {}, regain_period: {}, mode: {}'\ .format( self.expiration_period, @@ -448,6 +450,7 @@ class CourseEntitlement(TimeStampedModel): raise IntegrityError +@python_2_unicode_compatible class CourseEntitlementSupportDetail(TimeStampedModel): """ Table recording support interactions with an entitlement @@ -492,7 +495,7 @@ class CourseEntitlementSupportDetail(TimeStampedModel): on_delete=models.CASCADE, ) - def __unicode__(self): + def __str__(self): """Unicode representation of an Entitlement""" return u'Course Entitlement Support Detail: entitlement: {}, support_user: {}, reason: {}'.format( self.entitlement, diff --git a/common/djangoapps/static_replace/models.py b/common/djangoapps/static_replace/models.py index f89eea1b8e2..2012832eaf0 100644 --- a/common/djangoapps/static_replace/models.py +++ b/common/djangoapps/static_replace/models.py @@ -9,8 +9,10 @@ from six.moves import map from config_models.models import ConfigurationModel from django.db.models.fields import TextField +from django.utils.encoding import python_2_unicode_compatible +@python_2_unicode_compatible class AssetBaseUrlConfig(ConfigurationModel): """ Configuration for the base URL used for static assets. @@ -34,10 +36,11 @@ class AssetBaseUrlConfig(ConfigurationModel): def __repr__(self): return '<AssetBaseUrlConfig(base_url={})>'.format(self.get_base_url()) - def __unicode__(self): + def __str__(self): return six.text_type(repr(self)) +@python_2_unicode_compatible class AssetExcludedExtensionsConfig(ConfigurationModel): """ Configuration for the the excluded file extensions when canonicalizing static asset paths. @@ -63,5 +66,5 @@ class AssetExcludedExtensionsConfig(ConfigurationModel): def __repr__(self): return '<AssetExcludedExtensionsConfig(extensions={})>'.format(self.get_excluded_extensions()) - def __unicode__(self): + def __str__(self): return six.text_type(repr(self)) diff --git a/common/djangoapps/status/models.py b/common/djangoapps/status/models.py index fdd1ee74913..0ad62f2d122 100644 --- a/common/djangoapps/status/models.py +++ b/common/djangoapps/status/models.py @@ -10,11 +10,13 @@ from config_models.models import ConfigurationModel from django.contrib import admin from django.core.cache import cache from django.db import models +from django.utils.encoding import python_2_unicode_compatible from opaque_keys.edx.django.models import CourseKeyField from openedx.core.djangolib.markup import HTML +@python_2_unicode_compatible class GlobalStatusMessage(ConfigurationModel): """ Model that represents the current status message. @@ -51,10 +53,11 @@ class GlobalStatusMessage(ConfigurationModel): cache.set(cache_key, msg) return msg - def __unicode__(self): + def __str__(self): return "{} - {} - {}".format(self.change_date, self.enabled, self.message) +@python_2_unicode_compatible class CourseMessage(models.Model): """ Model that allows the administrator to specify banner messages for individual courses. @@ -68,7 +71,7 @@ class CourseMessage(models.Model): course_key = CourseKeyField(max_length=255, blank=True, db_index=True) message = models.TextField(blank=True, null=True) - def __unicode__(self): + def __str__(self): return six.text_type(self.course_key) diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index 9a7e521eb89..83a22d2d7e4 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -858,7 +858,7 @@ EVENT_NAME_ENROLLMENT_DEACTIVATED = 'edx.course.enrollment.deactivated' EVENT_NAME_ENROLLMENT_MODE_CHANGED = 'edx.course.enrollment.mode_changed' -@six.python_2_unicode_compatible +@python_2_unicode_compatible class LoginFailures(models.Model): """ This model will keep track of failed login attempts. @@ -1084,6 +1084,7 @@ class CourseEnrollmentManager(models.Manager): CourseEnrollmentState = namedtuple('CourseEnrollmentState', 'mode, is_active') +@python_2_unicode_compatible class CourseEnrollment(models.Model): """ Represents a Student's Enrollment record for a single Course. You should @@ -1160,7 +1161,7 @@ class CourseEnrollment(models.Model): # When the property .course_overview is accessed for the first time, this variable will be set. self._course_overview = None - def __unicode__(self): + def __str__(self): return ( "[CourseEnrollment] {}: {} ({}); active: ({})" ).format(self.user, self.course_id, self.created, self.is_active) @@ -2139,6 +2140,7 @@ class ManualEnrollmentAudit(models.Model): return cls.objects.filter(id__in=manual_enrollment_ids).update(reason="", enrolled_email=retired_email) +@python_2_unicode_compatible class CourseEnrollmentAllowed(DeletableByUserValue, models.Model): """ Table of users (specified by email address strings) who are allowed to enroll in a specified course. @@ -2166,7 +2168,7 @@ class CourseEnrollmentAllowed(DeletableByUserValue, models.Model): class Meta(object): unique_together = (('email', 'course_id'),) - def __unicode__(self): + def __str__(self): return "[CourseEnrollmentAllowed] %s: %s (%s)" % (self.email, self.course_id, self.created) @classmethod @@ -2199,6 +2201,7 @@ class CourseEnrollmentAllowed(DeletableByUserValue, models.Model): @total_ordering +@python_2_unicode_compatible class CourseAccessRole(models.Model): """ Maps users to org, courses, and roles. Used by student.roles.CourseRole and OrgRole. @@ -2244,7 +2247,7 @@ class CourseAccessRole(models.Model): """ return self._key < other._key # pylint: disable=protected-access - def __unicode__(self): + def __str__(self): return "[CourseAccessRole] user: {} role: {} org: {} course: {}".format(self.user.username, self.role, self.org, self.course_id) @@ -2576,6 +2579,7 @@ class LinkedInAddToProfileConfiguration(ConfigurationModel): ) +@python_2_unicode_compatible class EntranceExamConfiguration(models.Model): """ Represents a Student's entrance exam specific data for a single Course @@ -2595,7 +2599,7 @@ class EntranceExamConfiguration(models.Model): class Meta(object): unique_together = (('user', 'course_id'), ) - def __unicode__(self): + def __str__(self): return "[EntranceExamConfiguration] %s: %s (%s) = %s" % ( self.user, self.course_id, self.created, self.skip_entrance_exam ) @@ -2683,6 +2687,7 @@ class SocialLink(models.Model): # pylint: disable=model-missing-unicode social_link = models.CharField(max_length=100, blank=True) +@python_2_unicode_compatible class CourseEnrollmentAttribute(models.Model): """ Provide additional information about the user's enrollment. @@ -2703,7 +2708,7 @@ class CourseEnrollmentAttribute(models.Model): help_text=_("Value of the enrollment attribute") ) - def __unicode__(self): + def __str__(self): """Unicode representation of the attribute. """ return u"{namespace}:{name}, {value}".format( namespace=self.namespace, @@ -2790,6 +2795,7 @@ class EnrollmentRefundConfiguration(ConfigurationModel): self.refund_window_microseconds = int(refund_window.total_seconds() * 1000000) +@python_2_unicode_compatible class RegistrationCookieConfiguration(ConfigurationModel): """ Configuration for registration cookies. @@ -2806,7 +2812,7 @@ class RegistrationCookieConfiguration(ConfigurationModel): help_text=_("Name of the affiliate cookie") ) - def __unicode__(self): + def __str__(self): """Unicode representation of this config. """ return u"UTM: {utm_name}; AFFILIATE: {affiliate_name}".format( utm_name=self.utm_cookie_name, @@ -2858,6 +2864,7 @@ class UserAttribute(TimeStampedModel): return None +@python_2_unicode_compatible class LogoutViewConfiguration(ConfigurationModel): """ DEPRECATED: Configuration for the logout view. @@ -2865,7 +2872,7 @@ class LogoutViewConfiguration(ConfigurationModel): .. no_pii: """ - def __unicode__(self): + def __str__(self): """ Unicode representation of the instance. """ diff --git a/common/djangoapps/track/backends/django.py b/common/djangoapps/track/backends/django.py index d04103a1a45..d093004bb54 100644 --- a/common/djangoapps/track/backends/django.py +++ b/common/djangoapps/track/backends/django.py @@ -12,6 +12,7 @@ from __future__ import absolute_import import logging from django.db import models +from django.utils.encoding import python_2_unicode_compatible from track.backends import BaseBackend @@ -31,6 +32,7 @@ LOGFIELDS = [ ] +@python_2_unicode_compatible class TrackingLog(models.Model): """ Defines the fields that are stored in the tracking log database. @@ -55,7 +57,7 @@ class TrackingLog(models.Model): app_label = 'track' db_table = 'track_trackinglog' - def __unicode__(self): + def __str__(self): fmt = ( u"[{self.time}] {self.username}@{self.ip}: " u"{self.event_source}| {self.event_type} | " diff --git a/common/djangoapps/xblock_django/models.py b/common/djangoapps/xblock_django/models.py index 48d8b5b8d68..a33af2cb08d 100644 --- a/common/djangoapps/xblock_django/models.py +++ b/common/djangoapps/xblock_django/models.py @@ -7,8 +7,10 @@ from __future__ import absolute_import from config_models.models import ConfigurationModel from django.db import models from django.utils.translation import ugettext_lazy as _ +from django.utils.encoding import python_2_unicode_compatible +@python_2_unicode_compatible class XBlockConfiguration(ConfigurationModel): """ XBlock configuration used by both LMS and Studio, and not specific to a particular template. @@ -28,12 +30,13 @@ class XBlockConfiguration(ConfigurationModel): verbose_name=_('show deprecation messaging in Studio') ) - def __unicode__(self): + def __str__(self): return ( "XBlockConfiguration(name={}, enabled={}, deprecated={})" ).format(self.name, self.enabled, self.deprecated) +@python_2_unicode_compatible class XBlockStudioConfigurationFlag(ConfigurationModel): """ Enables site-wide Studio configuration for XBlocks. @@ -46,10 +49,11 @@ class XBlockStudioConfigurationFlag(ConfigurationModel): # boolean field 'enabled' inherited from parent ConfigurationModel - def __unicode__(self): + def __str__(self): return "XBlockStudioConfigurationFlag(enabled={})".format(self.enabled) +@python_2_unicode_compatible class XBlockStudioConfiguration(ConfigurationModel): """ Studio editing configuration for a specific XBlock/template combination. @@ -76,7 +80,7 @@ class XBlockStudioConfiguration(ConfigurationModel): class Meta(object): app_label = "xblock_django" - def __unicode__(self): + def __str__(self): return ( "XBlockStudioConfiguration(name={}, template={}, enabled={}, support_level={})" ).format(self.name, self.template, self.enabled, self.support_level) diff --git a/common/lib/capa/capa/capa_problem.py b/common/lib/capa/capa/capa_problem.py index 5471bc4ea26..c54d5f83b07 100644 --- a/common/lib/capa/capa/capa_problem.py +++ b/common/lib/capa/capa/capa_problem.py @@ -34,6 +34,7 @@ import capa.xqueue_interface as xqueue_interface from capa.correctmap import CorrectMap from capa.safe_exec import safe_exec from capa.util import contextualize_text, convert_files_to_filenames +from django.utils.encoding import python_2_unicode_compatible from openedx.core.djangolib.markup import HTML, Text from xmodule.stringify import stringify_children @@ -126,6 +127,7 @@ class LoncapaSystem(object): self.matlab_api_key = matlab_api_key +@python_2_unicode_compatible class LoncapaProblem(object): """ Main class for capa Problems. @@ -283,7 +285,7 @@ class LoncapaProblem(object): self.student_answers = initial_answers - def __unicode__(self): + def __str__(self): return u"LoncapaProblem ({0})".format(self.problem_id) def get_state(self): diff --git a/common/lib/capa/capa/inputtypes.py b/common/lib/capa/capa/inputtypes.py index b0e35139eac..1f3bba51dc2 100644 --- a/common/lib/capa/capa/inputtypes.py +++ b/common/lib/capa/capa/inputtypes.py @@ -58,6 +58,7 @@ from six import text_type from capa.xqueue_interface import XQUEUE_TIMEOUT from chem import chemcalc +from django.utils.encoding import python_2_unicode_compatible from openedx.core.djangolib.markup import HTML, Text from openedx.core.lib import edx_six from xmodule.stringify import stringify_children @@ -74,6 +75,7 @@ log = logging.getLogger(__name__) registry = TagRegistry() # pylint: disable=invalid-name +@python_2_unicode_compatible class Status(object): """ Problem status @@ -119,9 +121,6 @@ class Status(object): def __str__(self): return self._status - def __unicode__(self): - return self._status.decode('utf8') - def __repr__(self): return 'Status(%r)' % self._status diff --git a/common/lib/capa/capa/responsetypes.py b/common/lib/capa/capa/responsetypes.py index 12b7c6db134..b0c5829d01c 100644 --- a/common/lib/capa/capa/responsetypes.py +++ b/common/lib/capa/capa/responsetypes.py @@ -35,6 +35,7 @@ import requests import six # specific library imports from calc import UndefinedVariable, UnmatchedParenthesis, evaluator +from django.utils.encoding import python_2_unicode_compatible from lxml import etree from lxml.html.soupparser import fromstring as fromstring_bs # uses Beautiful Soup!!! FIXME? from pyparsing import ParseException @@ -108,6 +109,7 @@ class StudentInputError(Exception): # Main base class for CAPA responsetypes +@python_2_unicode_compatible class LoncapaResponse(six.with_metaclass(abc.ABCMeta, object)): """ Base class for CAPA responsetypes. Each response type (ie a capa question, @@ -130,7 +132,7 @@ class LoncapaResponse(six.with_metaclass(abc.ABCMeta, object)): condition for a hint to be displayed - render_html : render this Response as HTML (must return XHTML-compliant string) - - __unicode__ : unicode representation of this Response + - __str__ : unicode representation of this Response Each response type may also specify the following attributes: @@ -574,7 +576,7 @@ class LoncapaResponse(six.with_metaclass(abc.ABCMeta, object)): def setup_response(self): pass - def __unicode__(self): + def __str__(self): return u'LoncapaProblem Response %s' % self.xml.tag def _render_response_msg_html(self, response_msg): diff --git a/common/lib/xmodule/xmodule/library_root_xblock.py b/common/lib/xmodule/xmodule/library_root_xblock.py index 6494bc4440f..17b2c856df4 100644 --- a/common/lib/xmodule/xmodule/library_root_xblock.py +++ b/common/lib/xmodule/xmodule/library_root_xblock.py @@ -4,8 +4,9 @@ from __future__ import absolute_import import logging - import six + +from django.utils.encoding import python_2_unicode_compatible from web_fragments.fragment import Fragment from xblock.core import XBlock from xblock.fields import Boolean, List, Scope, String @@ -18,6 +19,7 @@ log = logging.getLogger(__name__) _ = lambda text: text +@python_2_unicode_compatible class LibraryRoot(XBlock): """ The LibraryRoot is the root XBlock of a content library. All other blocks in @@ -47,11 +49,8 @@ class LibraryRoot(XBlock): has_children = True has_author_view = True - def __unicode__(self): - return u"Library: {}".format(self.display_name) - def __str__(self): - return six.text_type(self).encode('utf-8') + return u"Library: {}".format(self.display_name) def author_view(self, context): """ diff --git a/common/lib/xmodule/xmodule/modulestore/xml.py b/common/lib/xmodule/xmodule/modulestore/xml.py index 0da3a4b3689..d23f4acdadf 100644 --- a/common/lib/xmodule/xmodule/modulestore/xml.py +++ b/common/lib/xmodule/xmodule/modulestore/xml.py @@ -15,6 +15,7 @@ from contextlib import contextmanager from importlib import import_module import six +from django.utils.encoding import python_2_unicode_compatible from fs.osfs import OSFS from lazy import lazy from lxml import etree @@ -302,6 +303,7 @@ class CourseImportLocationManager(CourseLocationManager): self.target_course_id = target_course_id +@python_2_unicode_compatible class XMLModuleStore(ModuleStoreReadBase): """ An XML backed ModuleStore @@ -395,7 +397,7 @@ class XMLModuleStore(ModuleStoreReadBase): course_id = self.id_from_descriptor(course_descriptor) self._course_errors[course_id] = errorlog - def __unicode__(self): + def __str__(self): ''' String representation - for debugging ''' diff --git a/common/lib/xmodule/xmodule/tests/__init__.py b/common/lib/xmodule/xmodule/tests/__init__.py index 2113f766783..739a0d883dd 100644 --- a/common/lib/xmodule/xmodule/tests/__init__.py +++ b/common/lib/xmodule/xmodule/tests/__init__.py @@ -21,6 +21,7 @@ from functools import wraps import six from django.test import TestCase +from django.utils.encoding import python_2_unicode_compatible from mock import Mock from opaque_keys.edx.keys import CourseKey from path import Path as path @@ -225,6 +226,7 @@ def map_references(value, field, actual_course_key): return value +@python_2_unicode_compatible class LazyFormat(object): """ An stringy object that delays formatting until it's put into a string context. @@ -237,7 +239,7 @@ class LazyFormat(object): self.kwargs = kwargs self._message = None - def __unicode__(self): + def __str__(self): if self._message is None: self._message = self.template.format(*self.args, **self.kwargs) return self._message diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index 26692e0d55b..26eeb4cc2aa 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -12,6 +12,7 @@ from pkg_resources import resource_exists, resource_isdir, resource_listdir, res import six import yaml from contracts import contract, new_contract +from django.utils.encoding import python_2_unicode_compatible from lazy import lazy from lxml import etree from opaque_keys.edx.asides import AsideDefinitionKeyV2, AsideUsageKeyV2 @@ -921,6 +922,7 @@ class XModuleToXBlockMixin(object): @XBlock.needs("i18n") +@python_2_unicode_compatible class XModule(XModuleToXBlockMixin, HTMLSnippet, XModuleMixin): """ Implements a generic learning module. @@ -965,7 +967,7 @@ class XModule(XModuleToXBlockMixin, HTMLSnippet, XModuleMixin): def runtime(self, value): # pylint: disable=arguments-differ self._runtime = value - def __unicode__(self): + def __str__(self): # xss-lint: disable=python-wrap-html return u'<x_module(id={0})>'.format(self.id) diff --git a/lms/djangoapps/badges/models.py b/lms/djangoapps/badges/models.py index 5e479ffe26d..da7cf2e0679 100644 --- a/lms/djangoapps/badges/models.py +++ b/lms/djangoapps/badges/models.py @@ -11,6 +11,7 @@ from django.conf import settings from django.contrib.auth.models import User from django.core.exceptions import ValidationError from django.db import models +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ from jsonfield import JSONField from lazy import lazy @@ -48,6 +49,7 @@ class CourseBadgesDisabledError(Exception): """ +@python_2_unicode_compatible class BadgeClass(models.Model): """ Specifies a badge class to be registered with a backend. @@ -64,7 +66,7 @@ class BadgeClass(models.Model): mode = models.CharField(max_length=100, default='', blank=True) image = models.ImageField(upload_to='badge_classes', validators=[validate_badge_image]) - def __unicode__(self): + def __str__(self): return HTML(u"<Badge '{slug}' for '{issuing_component}'>").format( slug=HTML(self.slug), issuing_component=HTML(self.issuing_component) ) @@ -143,6 +145,7 @@ class BadgeClass(models.Model): verbose_name_plural = "Badge Classes" +@python_2_unicode_compatible class BadgeAssertion(TimeStampedModel): """ Tracks badges on our side of the badge baking transaction @@ -156,7 +159,7 @@ class BadgeAssertion(TimeStampedModel): image_url = models.URLField() assertion_url = models.URLField() - def __unicode__(self): + def __str__(self): return HTML(u"<{username} Badge Assertion for {slug} for {issuing_component}").format( username=HTML(self.user.username), slug=HTML(self.badge_class.slug), @@ -180,6 +183,7 @@ class BadgeAssertion(TimeStampedModel): BadgeAssertion._meta.get_field('created').db_index = True +@python_2_unicode_compatible class CourseCompleteImageConfiguration(models.Model): """ Contains the icon configuration for badges for a specific course mode. @@ -207,7 +211,7 @@ class CourseCompleteImageConfiguration(models.Model): default=False, ) - def __unicode__(self): + def __str__(self): return HTML(u"<CourseCompleteImageConfiguration for '{mode}'{default}>").format( mode=HTML(self.mode), default=HTML(u" (default)") if self.default else HTML(u'') @@ -235,6 +239,7 @@ class CourseCompleteImageConfiguration(models.Model): app_label = "badges" +@python_2_unicode_compatible class CourseEventBadgesConfiguration(ConfigurationModel): """ Determines the settings for meta course awards-- such as completing a certain @@ -268,7 +273,7 @@ class CourseEventBadgesConfiguration(ConfigurationModel): ) ) - def __unicode__(self): + def __str__(self): return HTML(u"<CourseEventBadgesConfiguration ({})>").format( Text(u"Enabled") if self.enabled else Text(u"Disabled") ) diff --git a/lms/djangoapps/bulk_email/models.py b/lms/djangoapps/bulk_email/models.py index e9cf7856e73..85a3e380ced 100644 --- a/lms/djangoapps/bulk_email/models.py +++ b/lms/djangoapps/bulk_email/models.py @@ -10,6 +10,7 @@ import six from config_models.models import ConfigurationModel from django.contrib.auth.models import User from django.db import models +from django.utils.encoding import python_2_unicode_compatible from opaque_keys.edx.django.models import CourseKeyField from six import text_type from six.moves import zip @@ -60,6 +61,7 @@ EMAIL_TARGET_CHOICES = list(zip( EMAIL_TARGETS = {target[0] for target in EMAIL_TARGET_CHOICES} +@python_2_unicode_compatible class Target(models.Model): """ A way to refer to a particular group (within a course) as a "Send to:" target. @@ -79,7 +81,7 @@ class Target(models.Model): class Meta(object): app_label = "bulk_email" - def __unicode__(self): + def __str__(self): return "CourseEmail Target: {}".format(self.short_display()) def short_display(self): @@ -143,6 +145,7 @@ class Target(models.Model): raise ValueError(u"Unrecognized target type {}".format(self.target_type)) +@python_2_unicode_compatible class CohortTarget(Target): """ Subclass of Target, specifically referring to a cohort. @@ -158,7 +161,7 @@ class CohortTarget(Target): kwargs['target_type'] = SEND_TO_COHORT super(CohortTarget, self).__init__(*args, **kwargs) - def __unicode__(self): + def __str__(self): return self.short_display() def short_display(self): @@ -188,6 +191,7 @@ class CohortTarget(Target): return cohort +@python_2_unicode_compatible class CourseModeTarget(Target): """ Subclass of Target, specifically for course modes. @@ -203,7 +207,7 @@ class CourseModeTarget(Target): kwargs['target_type'] = SEND_TO_TRACK super(CourseModeTarget, self).__init__(*args, **kwargs) - def __unicode__(self): + def __str__(self): return self.short_display() def short_display(self): @@ -235,6 +239,7 @@ class CourseModeTarget(Target): ) +@python_2_unicode_compatible class CourseEmail(Email): """ Stores information for an email to a course. @@ -251,7 +256,7 @@ class CourseEmail(Email): template_name = models.CharField(null=True, max_length=255) from_addr = models.CharField(null=True, max_length=255) - def __unicode__(self): + def __str__(self): return self.subject @classmethod @@ -429,6 +434,7 @@ class CourseEmailTemplate(models.Model): return CourseEmailTemplate._render(self.html_template, htmltext, context) +@python_2_unicode_compatible class CourseAuthorization(models.Model): """ Enable the course email feature on a course-by-course basis. @@ -455,7 +461,7 @@ class CourseAuthorization(models.Model): except cls.DoesNotExist: return False - def __unicode__(self): + def __str__(self): not_en = "Not " if self.email_enabled: not_en = "" @@ -474,6 +480,7 @@ class CourseAuthorization(models.Model): # .. toggle_warnings: None # .. toggle_tickets: None # .. toggle_status: supported +@python_2_unicode_compatible class BulkEmailFlag(ConfigurationModel): """ Enables site-wide configuration for the bulk_email feature. @@ -512,7 +519,7 @@ class BulkEmailFlag(ConfigurationModel): class Meta(object): app_label = "bulk_email" - def __unicode__(self): + def __str__(self): current_model = BulkEmailFlag.current() return u"BulkEmailFlag: enabled {}, require_course_email_auth: {}".format( current_model.is_enabled(), diff --git a/lms/djangoapps/bulk_email/tests/test_models.py b/lms/djangoapps/bulk_email/tests/test_models.py index 1865a57208b..03b3f6115ca 100644 --- a/lms/djangoapps/bulk_email/tests/test_models.py +++ b/lms/djangoapps/bulk_email/tests/test_models.py @@ -288,7 +288,7 @@ class CourseAuthorizationTest(TestCase): # Now, course should be authorized self.assertTrue(is_bulk_email_feature_enabled(course_id)) self.assertEqual( - cauth.__unicode__(), + str(cauth), "Course 'abc/123/doremi': Instructor Email Enabled" ) @@ -298,7 +298,7 @@ class CourseAuthorizationTest(TestCase): # Test that course is now unauthorized self.assertFalse(is_bulk_email_feature_enabled(course_id)) self.assertEqual( - cauth.__unicode__(), + str(cauth), "Course 'abc/123/doremi': Instructor Email Not Enabled" ) diff --git a/lms/djangoapps/certificates/models.py b/lms/djangoapps/certificates/models.py index e3b355bb465..6a0737a5f7c 100644 --- a/lms/djangoapps/certificates/models.py +++ b/lms/djangoapps/certificates/models.py @@ -60,6 +60,7 @@ from django.core.exceptions import ValidationError from django.db import models, transaction from django.db.models import Count from django.dispatch import receiver +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ from model_utils import Choices from model_utils.fields import AutoCreatedField @@ -404,6 +405,7 @@ class GeneratedCertificate(models.Model): ) +@python_2_unicode_compatible class CertificateGenerationHistory(TimeStampedModel): """ Model for storing Certificate Generation History. @@ -463,11 +465,12 @@ class CertificateGenerationHistory(TimeStampedModel): class Meta(object): app_label = "certificates" - def __unicode__(self): + def __str__(self): return u"certificates %s by %s on %s for %s" % \ ("regenerated" if self.is_regeneration else "generated", self.generated_by, self.created, self.course_id) +@python_2_unicode_compatible class CertificateInvalidation(TimeStampedModel): """ Model for storing Certificate Invalidation. @@ -482,7 +485,7 @@ class CertificateInvalidation(TimeStampedModel): class Meta(object): app_label = "certificates" - def __unicode__(self): + def __str__(self): return u"Certificate %s, invalidated by %s on %s." % \ (self.generated_certificate, self.invalidated_by, self.created) @@ -1067,6 +1070,7 @@ class CertificateHtmlViewConfiguration(ConfigurationModel): return json_data +@python_2_unicode_compatible class CertificateTemplate(TimeStampedModel): """A set of custom web certificate templates. @@ -1123,7 +1127,7 @@ class CertificateTemplate(TimeStampedModel): u'Course language is determined by the first two letters of the language code.' ) - def __unicode__(self): + def __str__(self): return u'%s' % (self.name, ) class Meta(object): @@ -1147,6 +1151,7 @@ def template_assets_path(instance, filename): return name +@python_2_unicode_compatible class CertificateTemplateAsset(TimeStampedModel): """A set of assets to be used in custom web certificate templates. @@ -1183,7 +1188,7 @@ class CertificateTemplateAsset(TimeStampedModel): super(CertificateTemplateAsset, self).save(*args, **kwargs) - def __unicode__(self): + def __str__(self): return u'%s' % (self.asset.url, ) class Meta(object): diff --git a/lms/djangoapps/certificates/queue.py b/lms/djangoapps/certificates/queue.py index 78ac989b9a6..46d756d5f18 100644 --- a/lms/djangoapps/certificates/queue.py +++ b/lms/djangoapps/certificates/queue.py @@ -11,6 +11,7 @@ import six from django.conf import settings from django.test.client import RequestFactory from django.urls import reverse +from django.utils.encoding import python_2_unicode_compatible from lxml.etree import ParserError, XMLSyntaxError from requests.auth import HTTPBasicAuth @@ -31,6 +32,7 @@ from xmodule.modulestore.django import modulestore LOGGER = logging.getLogger(__name__) +@python_2_unicode_compatible class XQueueAddToQueueError(Exception): """An error occurred when adding a certificate task to the queue. """ @@ -39,7 +41,7 @@ class XQueueAddToQueueError(Exception): self.error_msg = error_msg super(XQueueAddToQueueError, self).__init__(six.text_type(self)) - def __unicode__(self): + def __str__(self): return ( u"Could not add certificate to the XQueue. " u"The error code was '{code}' and the message was '{msg}'." diff --git a/lms/djangoapps/commerce/models.py b/lms/djangoapps/commerce/models.py index bf7d907dde1..8d8fb019446 100644 --- a/lms/djangoapps/commerce/models.py +++ b/lms/djangoapps/commerce/models.py @@ -5,9 +5,11 @@ from __future__ import absolute_import from config_models.models import ConfigurationModel from django.db import models +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ +@python_2_unicode_compatible class CommerceConfiguration(ConfigurationModel): """ Commerce configuration @@ -52,7 +54,7 @@ class CommerceConfiguration(ConfigurationModel): help_text=_('Automatically approve valid refund requests, without manual processing') ) - def __unicode__(self): + def __str__(self): return "Commerce configuration" @property diff --git a/lms/djangoapps/course_goals/models.py b/lms/djangoapps/course_goals/models.py index 34866705bbe..62ea1d7c496 100644 --- a/lms/djangoapps/course_goals/models.py +++ b/lms/djangoapps/course_goals/models.py @@ -5,6 +5,7 @@ from __future__ import absolute_import from django.contrib.auth.models import User from django.db import models +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ from model_utils import Choices from opaque_keys.edx.django.models import CourseKeyField @@ -18,6 +19,7 @@ GOAL_KEY_CHOICES = Choices( ) +@python_2_unicode_compatible class CourseGoal(models.Model): """ Represents a course goal set by a user on the course home page. @@ -32,7 +34,7 @@ class CourseGoal(models.Model): course_key = CourseKeyField(max_length=255, db_index=True) goal_key = models.CharField(max_length=100, choices=GOAL_KEY_CHOICES, default=GOAL_KEY_CHOICES.unsure) - def __unicode__(self): + def __str__(self): return 'CourseGoal: {user} set goal to {goal} for course {course}'.format( user=self.user.username, goal=self.goal_key, diff --git a/lms/djangoapps/courseware/models.py b/lms/djangoapps/courseware/models.py index c25d142bfe7..0dfa1b892e5 100644 --- a/lms/djangoapps/courseware/models.py +++ b/lms/djangoapps/courseware/models.py @@ -23,6 +23,7 @@ from django.conf import settings from django.contrib.auth.models import User from django.db import models from django.db.models.signals import post_save +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ from model_utils.models import TimeStampedModel from opaque_keys.edx.django.models import BlockTypeKeyField, CourseKeyField, LearningContextKeyField, UsageKeyField @@ -77,6 +78,7 @@ class ChunkingManager(models.Manager): return res +@python_2_unicode_compatible class StudentModule(models.Model): """ Keeps student state for a particular XBlock usage and particular student. @@ -149,7 +151,7 @@ class StudentModule(models.Model): 'state': str(self.state)[:20], },) - def __unicode__(self): + def __str__(self): return six.text_type(repr(self)) @classmethod @@ -232,6 +234,7 @@ class BaseStudentModuleHistory(models.Model): return history_entries +@python_2_unicode_compatible class StudentModuleHistory(BaseStudentModuleHistory): """Keeps a complete history of state changes for a given XModule for a given Student. Right now, we restrict this to problems so that the table doesn't @@ -243,7 +246,7 @@ class StudentModuleHistory(BaseStudentModuleHistory): student_module = models.ForeignKey(StudentModule, db_index=True, db_constraint=False, on_delete=models.CASCADE) - def __unicode__(self): + def __str__(self): return six.text_type(repr(self)) def save_history(sender, instance, **kwargs): # pylint: disable=no-self-argument, unused-argument @@ -268,6 +271,7 @@ class StudentModuleHistory(BaseStudentModuleHistory): post_save.connect(save_history, sender=StudentModule) +@python_2_unicode_compatible class XBlockFieldBase(models.Model): """ Base class for all XBlock field storage. @@ -289,7 +293,7 @@ class XBlockFieldBase(models.Model): created = models.DateTimeField(auto_now_add=True, db_index=True) modified = models.DateTimeField(auto_now=True, db_index=True) - def __unicode__(self): + def __str__(self): keys = [field.name for field in self._meta.get_fields() if field.name not in ('created', 'modified')] return HTML(u'{}<{!r}').format( HTML(self.__class__.__name__), @@ -337,6 +341,7 @@ class XModuleStudentInfoField(XBlockFieldBase): student = models.ForeignKey(User, db_index=True, on_delete=models.CASCADE) +@python_2_unicode_compatible class OfflineComputedGrade(models.Model): """ Table of grades computed offline for a given user and course. @@ -355,10 +360,11 @@ class OfflineComputedGrade(models.Model): app_label = "courseware" unique_together = (('user', 'course_id'),) - def __unicode__(self): + def __str__(self): return "[OfflineComputedGrade] %s: %s (%s) = %s" % (self.user, self.course_id, self.created, self.gradeset) +@python_2_unicode_compatible class OfflineComputedGradeLog(models.Model): """ Log of when offline grades are computed. @@ -377,7 +383,7 @@ class OfflineComputedGradeLog(models.Model): seconds = models.IntegerField(default=0) # seconds elapsed for computation nstudents = models.IntegerField(default=0) - def __unicode__(self): + def __str__(self): return "[OCGLog] %s: %s" % (text_type(self.course_id), self.created) diff --git a/lms/djangoapps/coursewarehistoryextended/models.py b/lms/djangoapps/coursewarehistoryextended/models.py index 9df1277c485..b9347f8ec41 100644 --- a/lms/djangoapps/coursewarehistoryextended/models.py +++ b/lms/djangoapps/coursewarehistoryextended/models.py @@ -18,11 +18,13 @@ import six from django.db import models from django.db.models.signals import post_delete, post_save from django.dispatch import receiver +from django.utils.encoding import python_2_unicode_compatible from courseware.models import BaseStudentModuleHistory, StudentModule from courseware.fields import UnsignedBigIntAutoField +@python_2_unicode_compatible class StudentModuleHistoryExtended(BaseStudentModuleHistory): """Keeps a complete history of state changes for a given XModule for a given Student. Right now, we restrict this to problems so that the table doesn't @@ -64,5 +66,5 @@ class StudentModuleHistoryExtended(BaseStudentModuleHistory): """ StudentModuleHistoryExtended.objects.filter(student_module=instance).all().delete() - def __unicode__(self): + def __str__(self): return six.text_type(repr(self)) diff --git a/lms/djangoapps/email_marketing/models.py b/lms/djangoapps/email_marketing/models.py index 28124f321bd..1822a18bd6c 100644 --- a/lms/djangoapps/email_marketing/models.py +++ b/lms/djangoapps/email_marketing/models.py @@ -5,9 +5,11 @@ from __future__ import absolute_import from config_models.models import ConfigurationModel from django.db import models +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ +@python_2_unicode_compatible class EmailMarketingConfiguration(ConfigurationModel): """ Email marketing configuration @@ -166,6 +168,6 @@ class EmailMarketingConfiguration(ConfigurationModel): ) ) - def __unicode__(self): + def __str__(self): return u"Email marketing configuration: New user list %s, Welcome template: %s" % \ (self.sailthru_new_user_list, self.sailthru_welcome_template) diff --git a/lms/djangoapps/grades/config/models.py b/lms/djangoapps/grades/config/models.py index 34726a6eea4..bc433198c44 100644 --- a/lms/djangoapps/grades/config/models.py +++ b/lms/djangoapps/grades/config/models.py @@ -7,12 +7,15 @@ from __future__ import absolute_import from config_models.models import ConfigurationModel from django.conf import settings from django.db.models import BooleanField, IntegerField, TextField +from django.utils.encoding import python_2_unicode_compatible from opaque_keys.edx.django.models import CourseKeyField + from six import text_type from openedx.core.lib.cache_utils import request_cached +@python_2_unicode_compatible class PersistentGradesEnabledFlag(ConfigurationModel): """ Enables persistent grades across the platform. @@ -50,13 +53,14 @@ class PersistentGradesEnabledFlag(ConfigurationModel): class Meta(object): app_label = "grades" - def __unicode__(self): + def __str__(self): current_model = PersistentGradesEnabledFlag.current() return u"PersistentGradesEnabledFlag: enabled {}".format( current_model.is_enabled() ) +@python_2_unicode_compatible class CoursePersistentGradesFlag(ConfigurationModel): """ Enables persistent grades for a specific @@ -73,7 +77,7 @@ class CoursePersistentGradesFlag(ConfigurationModel): # The course that these features are attached to. course_id = CourseKeyField(max_length=255, db_index=True) - def __unicode__(self): + def __str__(self): not_en = "Not " if self.enabled: not_en = "" diff --git a/lms/djangoapps/grades/course_grade.py b/lms/djangoapps/grades/course_grade.py index 1af0421ee31..dcc5bf363b7 100644 --- a/lms/djangoapps/grades/course_grade.py +++ b/lms/djangoapps/grades/course_grade.py @@ -9,6 +9,7 @@ from collections import OrderedDict, defaultdict import six from ccx_keys.locator import CCXLocator from django.conf import settings +from django.utils.encoding import python_2_unicode_compatible from lazy import lazy from xmodule import block_metadata_utils @@ -19,6 +20,7 @@ from .subsection_grade import ZeroSubsectionGrade from .subsection_grade_factory import SubsectionGradeFactory +@python_2_unicode_compatible class CourseGradeBase(object): """ Base class for Course Grades. @@ -34,7 +36,7 @@ class CourseGradeBase(object): self.letter_grade = letter_grade or None self.force_update_subsections = force_update_subsections - def __unicode__(self): + def __str__(self): return u'Course Grade: percent: {}, letter_grade: {}, passed: {}'.format( six.text_type(self.percent), self.letter_grade, diff --git a/lms/djangoapps/grades/models.py b/lms/djangoapps/grades/models.py index 55efa8cff07..dc412594fea 100644 --- a/lms/djangoapps/grades/models.py +++ b/lms/djangoapps/grades/models.py @@ -265,6 +265,7 @@ class VisibleBlocks(models.Model): return u"visible_blocks_cache.{}.{}".format(course_key, user_id) +@python_2_unicode_compatible class PersistentSubsectionGrade(TimeStampedModel): """ A django model tracking persistent grades at the subsection level. @@ -336,7 +337,7 @@ class PersistentSubsectionGrade(TimeStampedModel): else: return self.usage_key - def __unicode__(self): + def __str__(self): """ Returns a string representation of this model. """ @@ -507,6 +508,7 @@ class PersistentSubsectionGrade(TimeStampedModel): return u"subsection_grades_cache.{}".format(course_id) +@python_2_unicode_compatible class PersistentCourseGrade(TimeStampedModel): """ A django model tracking persistent course grades. @@ -550,7 +552,7 @@ class PersistentCourseGrade(TimeStampedModel): _CACHE_NAMESPACE = u"grades.models.PersistentCourseGrade" - def __unicode__(self): + def __str__(self): """ Returns a string representation of this model. """ @@ -643,6 +645,7 @@ class PersistentCourseGrade(TimeStampedModel): events.course_grade_calculated(grade) +@python_2_unicode_compatible class PersistentSubsectionGradeOverride(models.Model): """ A django model tracking persistent grades overrides at the subsection level. @@ -677,7 +680,7 @@ class PersistentSubsectionGradeOverride(models.Model): if 'grades' in apps.app_configs: history = HistoricalRecords() - def __unicode__(self): + def __str__(self): return u', '.join([ u"{}".format(type(self).__name__), u"earned_all_override: {}".format(self.earned_all_override), @@ -763,6 +766,7 @@ class PersistentSubsectionGradeOverride(models.Model): return cleaned_data +@python_2_unicode_compatible class PersistentSubsectionGradeOverrideHistory(models.Model): """ A django model tracking persistent grades override audit records. @@ -799,7 +803,7 @@ class PersistentSubsectionGradeOverrideHistory(models.Model): comments = models.CharField(max_length=300, blank=True, null=True) created = models.DateTimeField(auto_now_add=True, db_index=True) - def __unicode__(self): + def __str__(self): """ String representation of this model. """ diff --git a/lms/djangoapps/instructor_task/models.py b/lms/djangoapps/instructor_task/models.py index 0bcfa4a2890..3efe99ba4d9 100644 --- a/lms/djangoapps/instructor_task/models.py +++ b/lms/djangoapps/instructor_task/models.py @@ -28,6 +28,7 @@ from django.conf import settings from django.contrib.auth.models import User from django.core.files.base import ContentFile from django.db import models, transaction +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext as _ from opaque_keys.edx.django.models import CourseKeyField from six import text_type @@ -42,6 +43,7 @@ PROGRESS = 'PROGRESS' TASK_INPUT_LENGTH = 10000 +@python_2_unicode_compatible class InstructorTask(models.Model): """ Stores information about background tasks that have been submitted to @@ -91,7 +93,7 @@ class InstructorTask(models.Model): 'task_output': self.task_output, },) - def __unicode__(self): + def __str__(self): return six.text_type(repr(self)) @classmethod diff --git a/lms/djangoapps/instructor_task/subtasks.py b/lms/djangoapps/instructor_task/subtasks.py index 374b9ed69e7..75ec200325e 100644 --- a/lms/djangoapps/instructor_task/subtasks.py +++ b/lms/djangoapps/instructor_task/subtasks.py @@ -15,6 +15,7 @@ import six from celery.states import READY_STATES, RETRY, SUCCESS from django.core.cache import cache from django.db import DatabaseError, transaction +from django.utils.encoding import python_2_unicode_compatible from six.moves import range, zip from util.db import outer_atomic @@ -121,6 +122,7 @@ def _generate_items_for_subtask( TASK_LOG.info(u"Number of items generated by chunking %s not equal to original total %s", num_items_queued, total_num_items) +@python_2_unicode_compatible class SubtaskStatus(object): """ Create and return a dict for tracking the status of a subtask. @@ -205,7 +207,7 @@ class SubtaskStatus(object): """Return print representation of a SubtaskStatus object.""" return 'SubtaskStatus<%r>' % (self.to_dict(),) - def __unicode__(self): + def __str__(self): """Return unicode version of a SubtaskStatus object representation.""" return six.text_type(repr(self)) diff --git a/lms/djangoapps/mobile_api/models.py b/lms/djangoapps/mobile_api/models.py index bb8c023183d..9ab57d36a0b 100644 --- a/lms/djangoapps/mobile_api/models.py +++ b/lms/djangoapps/mobile_api/models.py @@ -5,6 +5,7 @@ from __future__ import absolute_import from config_models.models import ConfigurationModel from django.db import models +from django.utils.encoding import python_2_unicode_compatible from . import utils from .mobile_platform import PLATFORM_CLASSES @@ -35,6 +36,7 @@ class MobileApiConfig(ConfigurationModel): return [profile.strip() for profile in cls.current().video_profiles.split(",") if profile] +@python_2_unicode_compatible class AppVersionConfig(models.Model): """ Configuration for mobile app versions available. @@ -64,7 +66,7 @@ class AppVersionConfig(models.Model): unique_together = ('platform', 'version',) ordering = ['-major_version', '-minor_version', '-patch_version'] - def __unicode__(self): + def __str__(self): return "{}_{}".format(self.platform, self.version) @classmethod diff --git a/lms/djangoapps/shoppingcart/models.py b/lms/djangoapps/shoppingcart/models.py index 9cf522807d8..75b9b23ca01 100644 --- a/lms/djangoapps/shoppingcart/models.py +++ b/lms/djangoapps/shoppingcart/models.py @@ -26,6 +26,7 @@ from django.db.models import Count, F, Q, Sum from django.db.models.signals import post_delete, post_save from django.dispatch import receiver from django.urls import reverse +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy from model_utils.managers import InheritanceManager @@ -827,6 +828,7 @@ class OrderItem(TimeStampedModel): self.save() +@python_2_unicode_compatible class Invoice(TimeStampedModel): """ This table capture all the information needed to support "invoicing" @@ -960,7 +962,7 @@ class Invoice(TimeStampedModel): ], } - def __unicode__(self): + def __str__(self): label = ( six.text_type(self.internal_reference) if self.internal_reference @@ -1340,6 +1342,7 @@ class RegistrationCodeRedemption(models.Model): return code_redemption +@python_2_unicode_compatible class Coupon(models.Model): """ This table contains coupon codes @@ -1359,7 +1362,7 @@ class Coupon(models.Model): is_active = models.BooleanField(default=True) expiration_date = models.DateTimeField(null=True, blank=True) - def __unicode__(self): + def __str__(self): return "[Coupon] code: {} course: {}".format(self.code, self.course_id) @property @@ -1850,6 +1853,7 @@ class CourseRegCodeItem(OrderItem): return data +@python_2_unicode_compatible class CourseRegCodeItemAnnotation(models.Model): """ A model that maps course_id to an additional annotation. This is specifically needed because when Stanford @@ -1865,10 +1869,11 @@ class CourseRegCodeItemAnnotation(models.Model): course_id = CourseKeyField(unique=True, max_length=128, db_index=True) annotation = models.TextField(null=True) - def __unicode__(self): + def __str__(self): return u"{} : {}".format(text_type(self.course_id), self.annotation) +@python_2_unicode_compatible class PaidCourseRegistrationAnnotation(models.Model): """ A model that maps course_id to an additional annotation. This is specifically needed because when Stanford @@ -1884,7 +1889,7 @@ class PaidCourseRegistrationAnnotation(models.Model): course_id = CourseKeyField(unique=True, max_length=128, db_index=True) annotation = models.TextField(null=True) - def __unicode__(self): + def __str__(self): return u"{} : {}".format(text_type(self.course_id), self.annotation) diff --git a/lms/djangoapps/shoppingcart/tests/test_reports.py b/lms/djangoapps/shoppingcart/tests/test_reports.py index 002b936926b..c9ea37f6155 100644 --- a/lms/djangoapps/shoppingcart/tests/test_reports.py +++ b/lms/djangoapps/shoppingcart/tests/test_reports.py @@ -245,12 +245,12 @@ class ItemizedPurchaseReportTest(ModuleStoreTestCase): def test_paidcourseregistrationannotation_unicode(self): """ - Fill in gap in test coverage. __unicode__ method of PaidCourseRegistrationAnnotation + Fill in gap in test coverage. __str__ method of PaidCourseRegistrationAnnotation """ self.assertEqual(text_type(self.annotation), u'{} : {}'.format(text_type(self.course_key), self.TEST_ANNOTATION)) def test_courseregcodeitemannotationannotation_unicode(self): """ - Fill in gap in test coverage. __unicode__ method of CourseRegCodeItemAnnotation + Fill in gap in test coverage. __str__ method of CourseRegCodeItemAnnotation """ self.assertEqual(text_type(self.course_reg_code_annotation), u'{} : {}'.format(text_type(self.course_key), self.TEST_ANNOTATION)) diff --git a/lms/djangoapps/shoppingcart/tests/test_views.py b/lms/djangoapps/shoppingcart/tests/test_views.py index f83aa49dafa..43dc7c01dea 100644 --- a/lms/djangoapps/shoppingcart/tests/test_views.py +++ b/lms/djangoapps/shoppingcart/tests/test_views.py @@ -592,7 +592,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): coupon = Coupon(code='TestCode', description='testing', course_id=self.course_key, percentage_discount=12, created_by=self.user, is_active=True) coupon.save() - self.assertEquals(coupon.__unicode__(), '[Coupon] code: TestCode course: MITx/999/Robot_Super_Course') + self.assertEquals(str(coupon), '[Coupon] code: TestCode course: MITx/999/Robot_Super_Course') admin = User.objects.create_user('Mark', 'admin+courses@edx.org', 'foo') admin.is_staff = True get_coupon = Coupon.objects.get(id=1) diff --git a/lms/djangoapps/verify_student/models.py b/lms/djangoapps/verify_student/models.py index 5c5377cb04b..0aabe59090e 100644 --- a/lms/djangoapps/verify_student/models.py +++ b/lms/djangoapps/verify_student/models.py @@ -28,6 +28,7 @@ from django.contrib.auth.models import User from django.core.files.base import ContentFile from django.db import models from django.urls import reverse +from django.utils.encoding import python_2_unicode_compatible from django.utils.functional import cached_property from django.utils.timezone import now from django.utils.translation import ugettext_lazy @@ -144,6 +145,7 @@ class IDVerificationAttempt(StatusModel): ) +@python_2_unicode_compatible class ManualVerification(IDVerificationAttempt): """ Each ManualVerification represents a user's verification that bypasses the need for @@ -165,7 +167,7 @@ class ManualVerification(IDVerificationAttempt): class Meta(object): app_label = 'verify_student' - def __unicode__(self): + def __str__(self): return 'ManualIDVerification for {name}, status: {status}'.format( name=self.name, status=self.status, @@ -178,6 +180,7 @@ class ManualVerification(IDVerificationAttempt): return False +@python_2_unicode_compatible class SSOVerification(IDVerificationAttempt): """ Each SSOVerification represents a Student's attempt to establish their identity @@ -215,7 +218,7 @@ class SSOVerification(IDVerificationAttempt): class Meta(object): app_label = "verify_student" - def __unicode__(self): + def __str__(self): return 'SSOIDVerification for {name}, status: {status}'.format( name=self.name, status=self.status, diff --git a/openedx/core/djangoapps/api_admin/models.py b/openedx/core/djangoapps/api_admin/models.py index f5f4bd89255..316fe00c771 100644 --- a/openedx/core/djangoapps/api_admin/models.py +++ b/openedx/core/djangoapps/api_admin/models.py @@ -26,6 +26,7 @@ from openedx.core.djangoapps.site_configuration import helpers as configuration_ log = logging.getLogger(__name__) +@python_2_unicode_compatible class ApiAccessRequest(TimeStampedModel): """ Model to track API access for a user. @@ -127,7 +128,7 @@ class ApiAccessRequest(TimeStampedModel): self.status = self.DENIED self.save() - def __unicode__(self): + def __str__(self): return u'ApiAccessRequest {website} [{status}]'.format(website=self.website, status=self.status) @@ -223,6 +224,7 @@ def _send_decision_email(instance): log.exception(u'Error sending API user notification email for request [%s].', instance.id) +@python_2_unicode_compatible class Catalog(models.Model): """ A (non-Django-managed) model for Catalogs in the course discovery service. @@ -265,5 +267,5 @@ class Catalog(models.Model): 'viewers': self.viewers, } - def __unicode__(self): + def __str__(self): return u'Catalog {name} [{query}]'.format(name=self.name, query=self.query) diff --git a/openedx/core/djangoapps/bookmarks/models.py b/openedx/core/djangoapps/bookmarks/models.py index 34493e36f28..60ce8d5f063 100644 --- a/openedx/core/djangoapps/bookmarks/models.py +++ b/openedx/core/djangoapps/bookmarks/models.py @@ -8,6 +8,7 @@ import logging import six from django.contrib.auth.models import User from django.db import models +from django.utils.encoding import python_2_unicode_compatible from jsonfield.fields import JSONField from model_utils.models import TimeStampedModel from opaque_keys.edx.django.models import CourseKeyField, UsageKeyField @@ -41,6 +42,7 @@ def parse_path_data(path_data): return path +@python_2_unicode_compatible class Bookmark(TimeStampedModel): """ Bookmarks model. @@ -60,7 +62,7 @@ class Bookmark(TimeStampedModel): """ unique_together = ('user', 'usage_key') - def __unicode__(self): + def __str__(self): return self.resource_id @classmethod @@ -191,6 +193,7 @@ class Bookmark(TimeStampedModel): return path_data +@python_2_unicode_compatible class XBlockCache(TimeStampedModel): """ XBlockCache model to store info about xblocks. @@ -206,7 +209,7 @@ class XBlockCache(TimeStampedModel): db_column='paths', default=[], help_text='All paths in course tree to the corresponding block.' ) - def __unicode__(self): + def __str__(self): return six.text_type(self.usage_key) @property diff --git a/openedx/core/djangoapps/ccxcon/models.py b/openedx/core/djangoapps/ccxcon/models.py index f240216f098..99b68fd27ad 100644 --- a/openedx/core/djangoapps/ccxcon/models.py +++ b/openedx/core/djangoapps/ccxcon/models.py @@ -4,10 +4,11 @@ Models for the ccxcon from __future__ import absolute_import -import six from django.db import models +from django.utils.encoding import python_2_unicode_compatible +@python_2_unicode_compatible class CCXCon(models.Model): """ Definition of the CCXCon model. @@ -30,6 +31,3 @@ class CCXCon(models.Model): def __str__(self): return self.title - - def __unicode__(self): - return six.text_type(self.__str__()) diff --git a/openedx/core/djangoapps/content/block_structure/config/models.py b/openedx/core/djangoapps/content/block_structure/config/models.py index ee7606d3499..2aa34d75eaa 100644 --- a/openedx/core/djangoapps/content/block_structure/config/models.py +++ b/openedx/core/djangoapps/content/block_structure/config/models.py @@ -5,8 +5,10 @@ from __future__ import absolute_import from config_models.models import ConfigurationModel from django.db.models import IntegerField +from django.utils.encoding import python_2_unicode_compatible +@python_2_unicode_compatible class BlockStructureConfiguration(ConfigurationModel): """ Configuration model for Block Structures. @@ -23,7 +25,7 @@ class BlockStructureConfiguration(ConfigurationModel): num_versions_to_keep = IntegerField(blank=True, null=True, default=DEFAULT_PRUNE_KEEP_COUNT) cache_timeout_in_seconds = IntegerField(blank=True, null=True, default=DEFAULT_CACHE_TIMEOUT_IN_SECONDS) - def __unicode__(self): + def __str__(self): return u"BlockStructureConfiguration: num_versions_to_keep: {}, cache_timeout_in_seconds: {}".format( self.num_versions_to_keep, self.cache_timeout_in_seconds, diff --git a/openedx/core/djangoapps/content/block_structure/models.py b/openedx/core/djangoapps/content/block_structure/models.py index 290f7e3d52e..f8dc317fde7 100644 --- a/openedx/core/djangoapps/content/block_structure/models.py +++ b/openedx/core/djangoapps/content/block_structure/models.py @@ -14,6 +14,7 @@ from django.conf import settings from django.core.exceptions import SuspiciousOperation from django.core.files.base import ContentFile from django.db import models, transaction +from django.utils.encoding import python_2_unicode_compatible from model_utils.models import TimeStampedModel from openedx.core.djangoapps.xmodule_django.models import UsageKeyWithRunField @@ -125,6 +126,7 @@ def _storage_error_handling(bs_model, operation, is_read_operation=False): raise +@python_2_unicode_compatible class BlockStructureModel(TimeStampedModel): """ Model for storing Block Structure information. @@ -218,7 +220,7 @@ class BlockStructureModel(TimeStampedModel): return bs_model, created - def __unicode__(self): + def __str__(self): """ Returns a string representation of this model. """ diff --git a/openedx/core/djangoapps/content/block_structure/store.py b/openedx/core/djangoapps/content/block_structure/store.py index 204ee3606a5..c6568f031f6 100644 --- a/openedx/core/djangoapps/content/block_structure/store.py +++ b/openedx/core/djangoapps/content/block_structure/store.py @@ -8,6 +8,7 @@ from logging import getLogger import six +from django.utils.encoding import python_2_unicode_compatible from openedx.core.lib.cache_utils import zpickle, zunpickle from . import config @@ -20,6 +21,7 @@ from .transformer_registry import TransformerRegistry logger = getLogger(__name__) # pylint: disable=C0103 +@python_2_unicode_compatible class StubModel(object): """ Stub model to use when storage backing is disabled. @@ -29,7 +31,7 @@ class StubModel(object): def __init__(self, root_block_usage_key): self.data_usage_key = root_block_usage_key - def __unicode__(self): + def __str__(self): return six.text_type(self.data_usage_key) def delete(self): diff --git a/openedx/core/djangoapps/content/course_overviews/models.py b/openedx/core/djangoapps/content/course_overviews/models.py index 71658cfccf9..2ffe4c1e34f 100644 --- a/openedx/core/djangoapps/content/course_overviews/models.py +++ b/openedx/core/djangoapps/content/course_overviews/models.py @@ -14,6 +14,7 @@ from django.db import models, transaction from django.db.models.fields import BooleanField, DateTimeField, DecimalField, FloatField, IntegerField, TextField from django.db.utils import IntegrityError from django.template import defaultfilters +from django.utils.encoding import python_2_unicode_compatible from model_utils.models import TimeStampedModel from opaque_keys.edx.django.models import CourseKeyField, UsageKeyField from six import text_type # pylint: disable=ungrouped-imports @@ -33,6 +34,7 @@ from xmodule.modulestore.django import modulestore log = logging.getLogger(__name__) +@python_2_unicode_compatible class CourseOverview(TimeStampedModel): """ Model for storing and caching basic information about a course. @@ -725,7 +727,7 @@ class CourseOverview(TimeStampedModel): return urlunparse((None, base_url, path, params, query, fragment)) - def __unicode__(self): + def __str__(self): """Represent ourselves with the course key.""" return six.text_type(self.id) @@ -740,6 +742,7 @@ class CourseOverviewTab(models.Model): course_overview = models.ForeignKey(CourseOverview, db_index=True, related_name="tabs", on_delete=models.CASCADE) +@python_2_unicode_compatible class CourseOverviewImageSet(TimeStampedModel): """ Model for Course overview images. Each column is an image type/size. @@ -876,12 +879,13 @@ class CourseOverviewImageSet(TimeStampedModel): # to unsaved related object 'course_overview'.") pass - def __unicode__(self): + def __str__(self): return u"CourseOverviewImageSet({}, small_url={}, large_url={})".format( self.course_overview_id, self.small_url, self.large_url ) +@python_2_unicode_compatible class CourseOverviewImageConfig(ConfigurationModel): """ This sets the size of the thumbnail images that Course Overviews will generate @@ -911,12 +915,13 @@ class CourseOverviewImageConfig(ConfigurationModel): """Tuple for large image dimensions in pixels -- (width, height)""" return (self.large_width, self.large_height) - def __unicode__(self): + def __str__(self): return u"CourseOverviewImageConfig(enabled={}, small={}, large={})".format( self.enabled, self.small, self.large ) +@python_2_unicode_compatible class SimulateCoursePublishConfig(ConfigurationModel): """ Manages configuration for a run of the simulate_publish management command. @@ -935,5 +940,5 @@ class SimulateCoursePublishConfig(ConfigurationModel): default='', ) - def __unicode__(self): + def __str__(self): return six.text_type(self.arguments) diff --git a/openedx/core/djangoapps/content_libraries/models.py b/openedx/core/djangoapps/content_libraries/models.py index f1680c18d6e..44f8f133ee9 100644 --- a/openedx/core/djangoapps/content_libraries/models.py +++ b/openedx/core/djangoapps/content_libraries/models.py @@ -5,6 +5,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera from django.contrib.auth import get_user_model from django.db import models +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ from opaque_keys.edx.locator import LibraryLocatorV2 from organizations.models import Organization @@ -25,7 +26,7 @@ class ContentLibraryManager(models.Manager): return self.get(org__short_name=library_key.org, slug=library_key.slug) -@six.python_2_unicode_compatible # pylint: disable=model-missing-unicode +@python_2_unicode_compatible class ContentLibrary(models.Model): """ A Content Library is a collection of content (XBlocks and/or static assets) @@ -84,7 +85,7 @@ class ContentLibrary(models.Model): return "ContentLibrary ({})".format(six.text_type(self.library_key)) -@six.python_2_unicode_compatible # pylint: disable=model-missing-unicode +@python_2_unicode_compatible class ContentLibraryPermission(models.Model): """ Row recording permissions for a content library diff --git a/openedx/core/djangoapps/contentserver/models.py b/openedx/core/djangoapps/contentserver/models.py index 13463ad6435..f7d30e21162 100644 --- a/openedx/core/djangoapps/contentserver/models.py +++ b/openedx/core/djangoapps/contentserver/models.py @@ -8,8 +8,10 @@ import six from config_models.models import ConfigurationModel from django.db.models.fields import PositiveIntegerField, TextField +from django.utils.encoding import python_2_unicode_compatible +@python_2_unicode_compatible class CourseAssetCacheTtlConfig(ConfigurationModel): """ Configuration for the TTL of course assets. @@ -33,10 +35,11 @@ class CourseAssetCacheTtlConfig(ConfigurationModel): def __repr__(self): return '<CourseAssetCacheTtlConfig(cache_ttl={})>'.format(self.get_cache_ttl()) - def __unicode__(self): + def __str__(self): return six.text_type(repr(self)) +@python_2_unicode_compatible class CdnUserAgentsConfig(ConfigurationModel): """ Configuration for the user agents we expect to see from CDNs. @@ -60,5 +63,5 @@ class CdnUserAgentsConfig(ConfigurationModel): def __repr__(self): return '<WhitelistedCdnConfig(cdn_user_agents={})>'.format(self.get_cdn_user_agents()) - def __unicode__(self): + def __str__(self): return six.text_type(repr(self)) diff --git a/openedx/core/djangoapps/cors_csrf/models.py b/openedx/core/djangoapps/cors_csrf/models.py index d0ec0d1b1b3..62e3dbbaa2e 100644 --- a/openedx/core/djangoapps/cors_csrf/models.py +++ b/openedx/core/djangoapps/cors_csrf/models.py @@ -3,9 +3,11 @@ from __future__ import absolute_import from config_models.models import ConfigurationModel from django.db import models +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ +@python_2_unicode_compatible class XDomainProxyConfiguration(ConfigurationModel): """ Cross-domain proxy configuration. @@ -22,5 +24,5 @@ class XDomainProxyConfiguration(ConfigurationModel): ) ) - def __unicode__(self): + def __str__(self): return "XDomainProxyConfiguration()" diff --git a/openedx/core/djangoapps/course_groups/models.py b/openedx/core/djangoapps/course_groups/models.py index 9af25a42bdf..9c43ec7379c 100644 --- a/openedx/core/djangoapps/course_groups/models.py +++ b/openedx/core/djangoapps/course_groups/models.py @@ -12,6 +12,7 @@ from django.core.exceptions import ValidationError from django.db import models, transaction from django.db.models.signals import pre_delete from django.dispatch import receiver +from django.utils.encoding import python_2_unicode_compatible from opaque_keys.edx.django.models import CourseKeyField from openedx.core.djangolib.model_mixins import DeletableByUserValue @@ -19,6 +20,7 @@ from openedx.core.djangolib.model_mixins import DeletableByUserValue log = logging.getLogger(__name__) +@python_2_unicode_compatible class CourseUserGroup(models.Model): """ This model represents groups of users in a course. Groups may have different types, @@ -66,7 +68,7 @@ class CourseUserGroup(models.Model): name=name ) - def __unicode__(self): + def __str__(self): return self.name diff --git a/openedx/core/djangoapps/crawlers/models.py b/openedx/core/djangoapps/crawlers/models.py index 24263e5c045..e3c35b673d0 100644 --- a/openedx/core/djangoapps/crawlers/models.py +++ b/openedx/core/djangoapps/crawlers/models.py @@ -7,8 +7,10 @@ from __future__ import absolute_import import six from config_models.models import ConfigurationModel from django.db import models +from django.utils.encoding import python_2_unicode_compatible +@python_2_unicode_compatible class CrawlersConfig(ConfigurationModel): """ Configuration for the crawlers django app. @@ -24,7 +26,7 @@ class CrawlersConfig(ConfigurationModel): default='edX-downloader', ) - def __unicode__(self): + def __str__(self): return u'CrawlersConfig("{}")'.format(self.known_user_agents) @classmethod diff --git a/openedx/core/djangoapps/credentials/models.py b/openedx/core/djangoapps/credentials/models.py index ad39709f54d..af32e4c9b1c 100644 --- a/openedx/core/djangoapps/credentials/models.py +++ b/openedx/core/djangoapps/credentials/models.py @@ -8,6 +8,7 @@ import six from config_models.models import ConfigurationModel from django.conf import settings from django.db import models +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ from six.moves.urllib.parse import urljoin # pylint: disable=import-error @@ -16,6 +17,7 @@ from openedx.core.djangoapps.site_configuration import helpers API_VERSION = 'v2' +@python_2_unicode_compatible class CredentialsApiConfig(ConfigurationModel): """ Manages configuration for connecting to the Credential service and using its @@ -62,7 +64,7 @@ class CredentialsApiConfig(ConfigurationModel): ) ) - def __unicode__(self): + def __str__(self): return self.public_api_url @property @@ -114,6 +116,7 @@ class CredentialsApiConfig(ConfigurationModel): return self.cache_ttl > 0 +@python_2_unicode_compatible class NotifyCredentialsConfig(ConfigurationModel): """ Manages configuration for a run of the notify_credentials management command. @@ -131,5 +134,5 @@ class NotifyCredentialsConfig(ConfigurationModel): default='', ) - def __unicode__(self): + def __str__(self): return six.text_type(self.arguments) diff --git a/openedx/core/djangoapps/credit/models.py b/openedx/core/djangoapps/credit/models.py index 73c8c0bf549..dcd483ee23c 100644 --- a/openedx/core/djangoapps/credit/models.py +++ b/openedx/core/djangoapps/credit/models.py @@ -20,6 +20,7 @@ from django.core.cache import cache from django.core.validators import RegexValidator from django.db import IntegrityError, models, transaction from django.dispatch import receiver +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy from edx_django_utils.cache import RequestCache @@ -33,6 +34,7 @@ CREDIT_PROVIDER_ID_REGEX = r"[a-z,A-Z,0-9,\-]+" log = logging.getLogger(__name__) +@python_2_unicode_compatible class CreditProvider(TimeStampedModel): """ This model represents an institution that can grant credit for a course. @@ -203,7 +205,7 @@ class CreditProvider(TimeStampedModel): except cls.DoesNotExist: return None - def __unicode__(self): + def __str__(self): """Unicode representation of the credit provider. """ return self.provider_id @@ -215,6 +217,7 @@ def invalidate_provider_cache(sender, **kwargs): # pylint: disable=unused-argum cache.delete(CreditProvider.CREDIT_PROVIDERS_CACHE_KEY) +@python_2_unicode_compatible class CreditCourse(models.Model): """ Model for tracking a credit course. @@ -265,7 +268,7 @@ class CreditCourse(models.Model): """ return cls.objects.get(course_key=course_key, enabled=True) - def __unicode__(self): + def __str__(self): """Unicode representation of the credit course. """ return six.text_type(self.course_key) @@ -277,6 +280,7 @@ def invalidate_credit_courses_cache(sender, **kwargs): # pylint: disable=unuse cache.delete(CreditCourse.CREDIT_COURSES_CACHE_KEY) +@python_2_unicode_compatible class CreditRequirement(TimeStampedModel): """ This model represents a credit requirement. @@ -307,8 +311,8 @@ class CreditRequirement(TimeStampedModel): unique_together = ('namespace', 'name', 'course') ordering = ["order"] - def __unicode__(self): - return '{course_id} - {name}'.format(course_id=self.course.course_key, name=self.display_name) + def __str__(self): + return u'{course_id} - {name}'.format(course_id=self.course.course_key, name=self.display_name) @classmethod def add_or_update_course_requirement(cls, credit_course, requirement, order): @@ -545,6 +549,7 @@ def default_deadline_for_credit_eligibility(): ) +@python_2_unicode_compatible class CreditEligibility(TimeStampedModel): """ A record of a user's eligibility for credit for a specific course. @@ -643,7 +648,7 @@ class CreditEligibility(TimeStampedModel): deadline__gt=datetime.datetime.now(pytz.UTC), ).exists() - def __unicode__(self): + def __str__(self): """Unicode representation of the credit eligibility. """ return u"{user}, {course}".format( user=self.username, @@ -651,6 +656,7 @@ class CreditEligibility(TimeStampedModel): ) +@python_2_unicode_compatible class CreditRequest(TimeStampedModel): """ A request for credit from a particular credit provider. @@ -768,7 +774,7 @@ class CreditRequest(TimeStampedModel): except cls.DoesNotExist: return None - def __unicode__(self): + def __str__(self): """Unicode representation of a credit request.""" return u"{course}, {provider}, {status}".format( course=self.course.course_key, @@ -777,6 +783,7 @@ class CreditRequest(TimeStampedModel): ) +@python_2_unicode_compatible class CreditConfig(ConfigurationModel): """ Manage credit configuration @@ -798,6 +805,6 @@ class CreditConfig(ConfigurationModel): """Whether responses from the commerce API will be cached.""" return self.enabled and self.cache_ttl > 0 - def __unicode__(self): + def __str__(self): """Unicode representation of the config. """ return 'Credit Configuration' diff --git a/openedx/core/djangoapps/dark_lang/models.py b/openedx/core/djangoapps/dark_lang/models.py index 5a0a5e8606a..e67f03259d7 100644 --- a/openedx/core/djangoapps/dark_lang/models.py +++ b/openedx/core/djangoapps/dark_lang/models.py @@ -5,8 +5,10 @@ from __future__ import absolute_import from config_models.models import ConfigurationModel from django.db import models +from django.utils.encoding import python_2_unicode_compatible +@python_2_unicode_compatible class DarkLangConfig(ConfigurationModel): """ Configuration for the dark_lang django app. @@ -26,7 +28,7 @@ class DarkLangConfig(ConfigurationModel): help_text="A comma-separated list of language codes to release to the public as beta languages." ) - def __unicode__(self): + def __str__(self): return u"DarkLangConfig()" @property diff --git a/openedx/core/djangoapps/django_comment_common/models.py b/openedx/core/djangoapps/django_comment_common/models.py index e1925e15214..41ba5a4f7bc 100644 --- a/openedx/core/djangoapps/django_comment_common/models.py +++ b/openedx/core/djangoapps/django_comment_common/models.py @@ -68,6 +68,7 @@ def assign_role(course_id, user, rolename): user.roles.add(role) +@python_2_unicode_compatible class Role(models.Model): """ Maps users to django_comment_client roles for a given course @@ -85,7 +86,7 @@ class Role(models.Model): # use existing table that was originally created from lms.djangoapps.discussion.django_comment_client app db_table = 'django_comment_client_role' - def __unicode__(self): + def __str__(self): return self.name + " for " + (text_type(self.course_id) if self.course_id else "all courses") # TODO the name of this method is a little bit confusing, @@ -194,6 +195,7 @@ def all_permissions_for_user_in_course(user, course_id): return permission_names +@python_2_unicode_compatible class ForumsConfig(ConfigurationModel): """ Config for the connection to the cs_comments_service forums backend. @@ -215,7 +217,7 @@ class ForumsConfig(ConfigurationModel): """The API key used to authenticate to the comments service.""" return getattr(settings, "COMMENTS_SERVICE_KEY", None) - def __unicode__(self): + def __str__(self): """ Simple representation so the admin screen looks less ugly. """ diff --git a/openedx/core/djangoapps/embargo/models.py b/openedx/core/djangoapps/embargo/models.py index 3cbd93b255f..53b2c7d69b7 100644 --- a/openedx/core/djangoapps/embargo/models.py +++ b/openedx/core/djangoapps/embargo/models.py @@ -76,6 +76,7 @@ class EmbargoedCourse(models.Model): return u"Course '{}' is {}Embargoed".format(text_type(self.course_id), not_em) +@python_2_unicode_compatible class EmbargoedState(ConfigurationModel): """ Register countries to be embargoed. @@ -99,7 +100,7 @@ class EmbargoedState(ConfigurationModel): return [] return [country.strip().upper() for country in self.embargoed_countries.split(',')] - def __unicode__(self): + def __str__(self): return self.embargoed_countries @@ -684,6 +685,7 @@ post_delete.connect(CourseAccessRuleHistory.snapshot_post_delete_receiver, sende post_delete.connect(CourseAccessRuleHistory.snapshot_post_delete_receiver, sender=CountryAccessRule) +@python_2_unicode_compatible class IPFilter(ConfigurationModel): """ Register specific IP addresses to explicitly block or unblock. @@ -742,5 +744,5 @@ class IPFilter(ConfigurationModel): return [] return self.IPFilterList([addr.strip() for addr in self.blacklist.split(',')]) - def __unicode__(self): + def __str__(self): return "Whitelist: {} - Blacklist: {}".format(self.whitelist_ips, self.blacklist_ips) diff --git a/openedx/core/djangoapps/site_configuration/models.py b/openedx/core/djangoapps/site_configuration/models.py index 6af78a171ea..0be707f8641 100644 --- a/openedx/core/djangoapps/site_configuration/models.py +++ b/openedx/core/djangoapps/site_configuration/models.py @@ -10,12 +10,14 @@ from django.contrib.sites.models import Site from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver +from django.utils.encoding import python_2_unicode_compatible from jsonfield.fields import JSONField from model_utils.models import TimeStampedModel logger = getLogger(__name__) # pylint: disable=invalid-name +@python_2_unicode_compatible class SiteConfiguration(models.Model): """ Model for storing site configuration. These configuration override OpenEdx configurations and settings. @@ -35,11 +37,11 @@ class SiteConfiguration(models.Model): load_kwargs={'object_pairs_hook': collections.OrderedDict} ) - def __unicode__(self): + def __str__(self): return u"<SiteConfiguration: {site} >".format(site=self.site) # xss-lint: disable=python-wrap-html def __repr__(self): - return self.__unicode__() + return self.__str__() def get_value(self, name, default=None): """ @@ -136,6 +138,7 @@ class SiteConfiguration(models.Model): return org in cls.get_all_orgs() +@python_2_unicode_compatible class SiteConfigurationHistory(TimeStampedModel): """ This is an archive table for SiteConfiguration, so that we can maintain a history of @@ -159,7 +162,7 @@ class SiteConfigurationHistory(TimeStampedModel): get_latest_by = 'modified' ordering = ('-modified', '-created',) - def __unicode__(self): + def __str__(self): # pylint: disable=line-too-long return u"<SiteConfigurationHistory: {site}, Last Modified: {modified} >".format( # xss-lint: disable=python-wrap-html modified=self.modified, @@ -167,7 +170,7 @@ class SiteConfigurationHistory(TimeStampedModel): ) def __repr__(self): - return self.__unicode__() + return self.__str__() @receiver(post_save, sender=SiteConfiguration) diff --git a/openedx/core/djangoapps/theming/helpers_dirs.py b/openedx/core/djangoapps/theming/helpers_dirs.py index 73f8777bc13..ca849faa9a7 100644 --- a/openedx/core/djangoapps/theming/helpers_dirs.py +++ b/openedx/core/djangoapps/theming/helpers_dirs.py @@ -6,6 +6,7 @@ from __future__ import absolute_import import os +from django.utils.encoding import python_2_unicode_compatible from path import Path @@ -92,6 +93,7 @@ def get_project_root_name_from_settings(project_root): return root.name +@python_2_unicode_compatible class Theme(object): """ class to encapsulate theme related information. @@ -129,12 +131,12 @@ class Theme(object): def __hash__(self): return hash((self.theme_dir_name, self.path)) - def __unicode__(self): + def __str__(self): # pylint: disable=line-too-long return u"<Theme: {name} at '{path}'>".format(name=self.name, path=self.path) # xss-lint: disable=python-wrap-html def __repr__(self): - return self.__unicode__() + return self.__str__() @property def path(self): diff --git a/openedx/core/djangoapps/theming/models.py b/openedx/core/djangoapps/theming/models.py index 04e77f6ebf8..88afba3c62f 100644 --- a/openedx/core/djangoapps/theming/models.py +++ b/openedx/core/djangoapps/theming/models.py @@ -5,8 +5,10 @@ from __future__ import absolute_import from django.contrib.sites.models import Site from django.db import models +from django.utils.encoding import python_2_unicode_compatible +@python_2_unicode_compatible class SiteTheme(models.Model): """ This is where the information about the site's theme gets stored to the db. @@ -19,7 +21,7 @@ class SiteTheme(models.Model): site = models.ForeignKey(Site, related_name='themes', on_delete=models.CASCADE) theme_dir_name = models.CharField(max_length=255) - def __unicode__(self): + def __str__(self): return self.theme_dir_name @staticmethod diff --git a/openedx/core/djangoapps/user_api/models.py b/openedx/core/djangoapps/user_api/models.py index 0980da53175..256bda5b6b8 100644 --- a/openedx/core/djangoapps/user_api/models.py +++ b/openedx/core/djangoapps/user_api/models.py @@ -183,6 +183,7 @@ class RetirementState(models.Model): return cls.objects.all().values_list('state_name', flat=True) +@python_2_unicode_compatible class UserRetirementPartnerReportingStatus(TimeStampedModel): """ When a user has been retired from LMS it will still need to be reported out to @@ -205,13 +206,14 @@ class UserRetirementPartnerReportingStatus(TimeStampedModel): verbose_name = 'User Retirement Reporting Status' verbose_name_plural = 'User Retirement Reporting Statuses' - def __unicode__(self): + def __str__(self): return u'UserRetirementPartnerReportingStatus: {} is being processed: {}'.format( self.user, self.is_being_processed ) +@python_2_unicode_compatible class UserRetirementRequest(TimeStampedModel): """ Records and perists every user retirement request. @@ -242,10 +244,11 @@ class UserRetirementRequest(TimeStampedModel): """ return cls.objects.filter(user=user).exists() - def __unicode__(self): + def __str__(self): return u'User: {} Requested: {}'.format(self.user.id, self.created) +@python_2_unicode_compatible class UserRetirementStatus(TimeStampedModel): """ Tracks the progress of a user's retirement request @@ -385,7 +388,7 @@ class UserRetirementStatus(TimeStampedModel): return retirement - def __unicode__(self): + def __str__(self): return u'User: {} State: {} Last Updated: {}'.format(self.user.id, self.current_state, self.modified) diff --git a/openedx/core/djangoapps/video_config/models.py b/openedx/core/djangoapps/video_config/models.py index f04696c256c..6837b10141d 100644 --- a/openedx/core/djangoapps/video_config/models.py +++ b/openedx/core/djangoapps/video_config/models.py @@ -7,12 +7,14 @@ import six from config_models.models import ConfigurationModel from django.db import models from django.db.models import BooleanField, PositiveIntegerField, TextField +from django.utils.encoding import python_2_unicode_compatible from model_utils.models import TimeStampedModel from opaque_keys.edx.django.models import CourseKeyField URL_REGEX = r'^[a-zA-Z0-9\-_]*$' +@python_2_unicode_compatible class HLSPlaybackEnabledFlag(ConfigurationModel): """ Enables HLS Playback across the platform. @@ -49,13 +51,14 @@ class HLSPlaybackEnabledFlag(ConfigurationModel): return feature.enabled if feature else False return True - def __unicode__(self): + def __str__(self): current_model = HLSPlaybackEnabledFlag.current() return u"HLSPlaybackEnabledFlag: enabled {is_enabled}".format( is_enabled=current_model.is_enabled() ) +@python_2_unicode_compatible class CourseHLSPlaybackEnabledFlag(ConfigurationModel): """ Enables HLS Playback for a specific course. Global feature must be @@ -67,7 +70,7 @@ class CourseHLSPlaybackEnabledFlag(ConfigurationModel): course_id = CourseKeyField(max_length=255, db_index=True) - def __unicode__(self): + def __str__(self): not_en = "Not " if self.enabled: not_en = "" @@ -78,6 +81,7 @@ class CourseHLSPlaybackEnabledFlag(ConfigurationModel): ) +@python_2_unicode_compatible class CourseYoutubeBlockedFlag(ConfigurationModel): """ Disables the playback of youtube videos for a given course. @@ -102,7 +106,7 @@ class CourseYoutubeBlockedFlag(ConfigurationModel): .first()) return feature.enabled if feature else False - def __unicode__(self): + def __str__(self): not_en = "Not " if self.enabled: not_en = "" @@ -113,6 +117,7 @@ class CourseYoutubeBlockedFlag(ConfigurationModel): ) +@python_2_unicode_compatible class VideoTranscriptEnabledFlag(ConfigurationModel): """ Enables Video Transcript across the platform. @@ -151,13 +156,14 @@ class VideoTranscriptEnabledFlag(ConfigurationModel): return feature.enabled if feature else False return True - def __unicode__(self): + def __str__(self): current_model = VideoTranscriptEnabledFlag.current() return u"VideoTranscriptEnabledFlag: enabled {is_enabled}".format( is_enabled=current_model.is_enabled() ) +@python_2_unicode_compatible class CourseVideoTranscriptEnabledFlag(ConfigurationModel): """ Enables Video Transcript for a specific course. Global feature must be @@ -171,7 +177,7 @@ class CourseVideoTranscriptEnabledFlag(ConfigurationModel): course_id = CourseKeyField(max_length=255, db_index=True) - def __unicode__(self): + def __str__(self): not_en = "Not " if self.enabled: not_en = "" @@ -182,13 +188,14 @@ class CourseVideoTranscriptEnabledFlag(ConfigurationModel): ) +@python_2_unicode_compatible class TranscriptMigrationSetting(ConfigurationModel): """ Arguments for the Transcript Migration management command .. no_pii: """ - def __unicode__(self): + def __str__(self): return ( u"[TranscriptMigrationSetting] Courses {courses} with update if already present as {force}" u" and commit as {commit}" @@ -225,6 +232,7 @@ class TranscriptMigrationSetting(ConfigurationModel): return self.command_run +@python_2_unicode_compatible class MigrationEnqueuedCourse(TimeStampedModel): """ Temporary model to persist the course IDs who has been enqueued for transcripts migration to S3. @@ -234,12 +242,13 @@ class MigrationEnqueuedCourse(TimeStampedModel): course_id = CourseKeyField(db_index=True, primary_key=True, max_length=255) command_run = PositiveIntegerField(default=0) - def __unicode__(self): + def __str__(self): return u'MigrationEnqueuedCourse: ID={course_id}, Run={command_run}'.format( course_id=self.course_id, command_run=self.command_run ) +@python_2_unicode_compatible class VideoThumbnailSetting(ConfigurationModel): """ Arguments for the Video Thumbnail management command @@ -275,13 +284,14 @@ class VideoThumbnailSetting(ConfigurationModel): self.offset += self.batch_size self.save() - def __unicode__(self): + def __str__(self): return "[VideoThumbnailSetting] update for {courses} courses if commit as {commit}".format( courses='ALL' if self.all_course_videos else self.course_ids, commit=self.commit, ) +@python_2_unicode_compatible class UpdatedCourseVideos(TimeStampedModel): """ Temporary model to persist the course videos which have been enqueued to update video thumbnails. @@ -295,7 +305,7 @@ class UpdatedCourseVideos(TimeStampedModel): class Meta: unique_together = ('course_id', 'edx_video_id') - def __unicode__(self): + def __str__(self): return u'UpdatedCourseVideos: CourseID={course_id}, VideoID={video_id}, Run={command_run}'.format( course_id=self.course_id, video_id=self.edx_video_id, command_run=self.command_run ) diff --git a/openedx/core/djangoapps/video_pipeline/models.py b/openedx/core/djangoapps/video_pipeline/models.py index 25f57cff24e..87a2a10dfd6 100644 --- a/openedx/core/djangoapps/video_pipeline/models.py +++ b/openedx/core/djangoapps/video_pipeline/models.py @@ -5,6 +5,7 @@ from __future__ import absolute_import from config_models.models import ConfigurationModel from django.contrib.auth import get_user_model from django.db import models +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ from opaque_keys.edx.django.models import CourseKeyField import six @@ -44,6 +45,7 @@ class VideoPipelineIntegration(ConfigurationModel): return User.objects.get(username=self.service_username) +@python_2_unicode_compatible class VideoUploadsEnabledByDefault(ConfigurationModel): """ Enables video uploads enabled By default feature across the platform. @@ -78,13 +80,14 @@ class VideoUploadsEnabledByDefault(ConfigurationModel): return feature.enabled if feature else False return True - def __unicode__(self): + def __str__(self): current_model = VideoUploadsEnabledByDefault.current() return u"VideoUploadsEnabledByDefault: enabled {is_enabled}".format( is_enabled=current_model.is_enabled() ) +@python_2_unicode_compatible class CourseVideoUploadsEnabledByDefault(ConfigurationModel): """ Enables video uploads enabled by default feature for a specific course. Its global feature must be @@ -96,7 +99,7 @@ class CourseVideoUploadsEnabledByDefault(ConfigurationModel): course_id = CourseKeyField(max_length=255, db_index=True) - def __unicode__(self): + def __str__(self): not_en = "Not " if self.enabled: not_en = "" diff --git a/openedx/core/djangoapps/waffle_utils/models.py b/openedx/core/djangoapps/waffle_utils/models.py index 4f84b684f60..1083d719ced 100644 --- a/openedx/core/djangoapps/waffle_utils/models.py +++ b/openedx/core/djangoapps/waffle_utils/models.py @@ -3,6 +3,7 @@ Models for configuring waffle utils. """ from __future__ import absolute_import from django.db.models import CharField +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ from model_utils import Choices from opaque_keys.edx.django.models import CourseKeyField @@ -12,6 +13,7 @@ from config_models.models import ConfigurationModel from openedx.core.lib.cache_utils import request_cached +@python_2_unicode_compatible class WaffleFlagCourseOverrideModel(ConfigurationModel): """ Used to force a waffle flag on or off for a course. @@ -59,6 +61,6 @@ class WaffleFlagCourseOverrideModel(ConfigurationModel): verbose_name = 'Waffle flag course override' verbose_name_plural = 'Waffle flag course overrides' - def __unicode__(self): + def __str__(self): enabled_label = "Enabled" if self.enabled else "Not Enabled" return u"Course '{}': Persistent Grades {}".format(text_type(self.course_id), enabled_label) diff --git a/openedx/features/announcements/models.py b/openedx/features/announcements/models.py index 74ae3bc9322..295e1b10f22 100644 --- a/openedx/features/announcements/models.py +++ b/openedx/features/announcements/models.py @@ -5,8 +5,10 @@ Models for Announcements from __future__ import absolute_import from django.db import models +from django.utils.encoding import python_2_unicode_compatible +@python_2_unicode_compatible class Announcement(models.Model): """Site-wide announcements to be displayed on the dashboard""" class Meta(object): @@ -15,5 +17,5 @@ class Announcement(models.Model): content = models.CharField(max_length=1000, null=False, default="lorem ipsum") active = models.BooleanField(default=True) - def __unicode__(self): + def __str__(self): return self.content -- GitLab