refactor: Ran pyupgrade on openedx/core/djangoapps/user_api
Co-authored-by: Muhammad Soban Javed <58461728+iamsobanjaved@users.noreply.github.com>
This commit is contained in:
@@ -40,58 +40,58 @@ VISIBILITY_PREFIX = 'visibility.'
|
||||
# It is shown to users who attempt to create a new account using invalid characters
|
||||
# in the username.
|
||||
USERNAME_INVALID_CHARS_ASCII = _(
|
||||
u"Usernames can only contain letters (A-Z, a-z), numerals (0-9), underscores (_), and hyphens (-)."
|
||||
"Usernames can only contain letters (A-Z, a-z), numerals (0-9), underscores (_), and hyphens (-)."
|
||||
)
|
||||
|
||||
# Translators: This message is shown only when the Unicode usernames are allowed.
|
||||
# It is shown to users who attempt to create a new account using invalid characters
|
||||
# in the username.
|
||||
USERNAME_INVALID_CHARS_UNICODE = _(
|
||||
u"Usernames can only contain letters, numerals, and @/./+/-/_ characters."
|
||||
"Usernames can only contain letters, numerals, and @/./+/-/_ characters."
|
||||
)
|
||||
|
||||
# Translators: This message is shown to users who attempt to create a new account using
|
||||
# an invalid email format.
|
||||
EMAIL_INVALID_MSG = _(u'"{email}" is not a valid email address.')
|
||||
EMAIL_INVALID_MSG = _('"{email}" is not a valid email address.')
|
||||
|
||||
# Translators: This message is shown to users who attempt to create a new
|
||||
# account using an username/email associated with an existing account.
|
||||
EMAIL_CONFLICT_MSG = _(
|
||||
u"It looks like {email_address} belongs to an existing account. "
|
||||
u"Try again with a different email address."
|
||||
"It looks like {email_address} belongs to an existing account. "
|
||||
"Try again with a different email address."
|
||||
)
|
||||
USERNAME_CONFLICT_MSG = _(
|
||||
u"It looks like {username} belongs to an existing account. "
|
||||
u"Try again with a different username."
|
||||
"It looks like {username} belongs to an existing account. "
|
||||
"Try again with a different username."
|
||||
)
|
||||
|
||||
# Translators: This message is shown to users who enter a username/email/password
|
||||
# with an inappropriate length (too short or too long).
|
||||
USERNAME_BAD_LENGTH_MSG = format_lazy(
|
||||
_(u"Username must be between {min} and {max} characters long."),
|
||||
_("Username must be between {min} and {max} characters long."),
|
||||
min=USERNAME_MIN_LENGTH,
|
||||
max=USERNAME_MAX_LENGTH,
|
||||
)
|
||||
EMAIL_BAD_LENGTH_MSG = format_lazy(
|
||||
_(u"Enter a valid email address that contains at least {min} characters."),
|
||||
_("Enter a valid email address that contains at least {min} characters."),
|
||||
min=EMAIL_MIN_LENGTH,
|
||||
)
|
||||
|
||||
# These strings are normally not user-facing.
|
||||
USERNAME_BAD_TYPE_MSG = u"Username must be a string."
|
||||
EMAIL_BAD_TYPE_MSG = u"Email must be a string."
|
||||
PASSWORD_BAD_TYPE_MSG = u"Password must be a string."
|
||||
USERNAME_BAD_TYPE_MSG = "Username must be a string."
|
||||
EMAIL_BAD_TYPE_MSG = "Email must be a string."
|
||||
PASSWORD_BAD_TYPE_MSG = "Password must be a string."
|
||||
|
||||
# Translators: These messages are shown to users who do not enter information
|
||||
# into the required field or enter it incorrectly.
|
||||
REQUIRED_FIELD_NAME_MSG = _(u"Enter your full name.")
|
||||
REQUIRED_FIELD_CONFIRM_EMAIL_MSG = _(u"The email addresses do not match.")
|
||||
REQUIRED_FIELD_COUNTRY_MSG = _(u"Select your country or region of residence.")
|
||||
REQUIRED_FIELD_PROFESSION_SELECT_MSG = _(u"Select your profession.")
|
||||
REQUIRED_FIELD_SPECIALTY_SELECT_MSG = _(u"Select your specialty.")
|
||||
REQUIRED_FIELD_PROFESSION_TEXT_MSG = _(u"Enter your profession.")
|
||||
REQUIRED_FIELD_SPECIALTY_TEXT_MSG = _(u"Enter your specialty.")
|
||||
REQUIRED_FIELD_CITY_MSG = _(u"Enter your city.")
|
||||
REQUIRED_FIELD_GOALS_MSG = _(u"Tell us your goals.")
|
||||
REQUIRED_FIELD_LEVEL_OF_EDUCATION_MSG = _(u"Select the highest level of education you have completed.")
|
||||
REQUIRED_FIELD_MAILING_ADDRESS_MSG = _(u"Enter your mailing address.")
|
||||
REQUIRED_FIELD_NAME_MSG = _("Enter your full name.")
|
||||
REQUIRED_FIELD_CONFIRM_EMAIL_MSG = _("The email addresses do not match.")
|
||||
REQUIRED_FIELD_COUNTRY_MSG = _("Select your country or region of residence.")
|
||||
REQUIRED_FIELD_PROFESSION_SELECT_MSG = _("Select your profession.")
|
||||
REQUIRED_FIELD_SPECIALTY_SELECT_MSG = _("Select your specialty.")
|
||||
REQUIRED_FIELD_PROFESSION_TEXT_MSG = _("Enter your profession.")
|
||||
REQUIRED_FIELD_SPECIALTY_TEXT_MSG = _("Enter your specialty.")
|
||||
REQUIRED_FIELD_CITY_MSG = _("Enter your city.")
|
||||
REQUIRED_FIELD_GOALS_MSG = _("Tell us your goals.")
|
||||
REQUIRED_FIELD_LEVEL_OF_EDUCATION_MSG = _("Select the highest level of education you have completed.")
|
||||
REQUIRED_FIELD_MAILING_ADDRESS_MSG = _("Enter your mailing address.")
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=missing-docstring
|
||||
"""
|
||||
Programmatic integration point for User API Accounts sub-application
|
||||
@@ -7,14 +6,12 @@ Programmatic integration point for User API Accounts sub-application
|
||||
|
||||
import datetime
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.core.validators import ValidationError, validate_email
|
||||
from django.utils.translation import override as override_language
|
||||
from django.utils.translation import ugettext as _
|
||||
from pytz import UTC
|
||||
from six import text_type # pylint: disable=ungrouped-imports
|
||||
from common.djangoapps.student import views as student_views
|
||||
from common.djangoapps.student.models import (
|
||||
AccountRecovery,
|
||||
@@ -166,7 +163,7 @@ def update_account_settings(requesting_user, update, username=None):
|
||||
raise err
|
||||
except Exception as err:
|
||||
raise AccountUpdateError( # lint-amnesty, pylint: disable=raise-missing-from
|
||||
u"Error thrown when saving account updates: '{}'".format(text_type(err))
|
||||
"Error thrown when saving account updates: '{}'".format(str(err))
|
||||
)
|
||||
|
||||
_send_email_change_requests_if_needed(update, user)
|
||||
@@ -176,15 +173,15 @@ def _validate_read_only_fields(user, data, field_errors):
|
||||
# Check for fields that are not editable. Marking them read-only causes them to be ignored, but we wish to 400.
|
||||
read_only_fields = set(data.keys()).intersection(
|
||||
# Remove email since it is handled separately below when checking for changing_email.
|
||||
(set(AccountUserSerializer.get_read_only_fields()) - set(["email"])) |
|
||||
(set(AccountUserSerializer.get_read_only_fields()) - {"email"}) |
|
||||
set(AccountLegacyProfileSerializer.get_read_only_fields() or set()) |
|
||||
get_enterprise_readonly_account_fields(user)
|
||||
)
|
||||
|
||||
for read_only_field in read_only_fields:
|
||||
field_errors[read_only_field] = {
|
||||
"developer_message": u"This field is not editable via this API",
|
||||
"user_message": _(u"The '{field_name}' field cannot be edited.").format(field_name=read_only_field)
|
||||
"developer_message": "This field is not editable via this API",
|
||||
"user_message": _("The '{field_name}' field cannot be edited.").format(field_name=read_only_field)
|
||||
}
|
||||
del data[read_only_field]
|
||||
|
||||
@@ -196,15 +193,15 @@ def _validate_email_change(user, data, field_errors):
|
||||
return
|
||||
|
||||
if not settings.FEATURES['ALLOW_EMAIL_ADDRESS_CHANGE']:
|
||||
raise AccountUpdateError(u"Email address changes have been disabled by the site operators.")
|
||||
raise AccountUpdateError("Email address changes have been disabled by the site operators.")
|
||||
|
||||
new_email = data["email"]
|
||||
try:
|
||||
student_views.validate_new_email(user, new_email)
|
||||
except ValueError as err:
|
||||
field_errors["email"] = {
|
||||
"developer_message": u"Error thrown from validate_new_email: '{}'".format(text_type(err)),
|
||||
"user_message": text_type(err)
|
||||
"developer_message": "Error thrown from validate_new_email: '{}'".format(str(err)),
|
||||
"user_message": str(err)
|
||||
}
|
||||
return
|
||||
|
||||
@@ -225,8 +222,8 @@ def _validate_secondary_email(user, data, field_errors):
|
||||
student_views.validate_secondary_email(user, secondary_email)
|
||||
except ValueError as err:
|
||||
field_errors["secondary_email"] = {
|
||||
"developer_message": u"Error thrown from validate_secondary_email: '{}'".format(text_type(err)),
|
||||
"user_message": text_type(err)
|
||||
"developer_message": "Error thrown from validate_secondary_email: '{}'".format(str(err)),
|
||||
"user_message": str(err)
|
||||
}
|
||||
else:
|
||||
# Don't process with sending email to given new email, if it is already associated with
|
||||
@@ -247,7 +244,7 @@ def _validate_name_change(user_profile, data, field_errors):
|
||||
validate_name(data['name'])
|
||||
except ValidationError as err:
|
||||
field_errors["name"] = {
|
||||
"developer_message": u"Error thrown from validate_name: '{}'".format(err.message),
|
||||
"developer_message": f"Error thrown from validate_name: '{err.message}'",
|
||||
"user_message": err.message
|
||||
}
|
||||
return None
|
||||
@@ -310,7 +307,7 @@ def _store_old_name_if_needed(old_name, user_profile, requesting_user):
|
||||
meta['old_names'] = []
|
||||
meta['old_names'].append([
|
||||
old_name,
|
||||
u"Name change requested through account API by {0}".format(requesting_user.username),
|
||||
f"Name change requested through account API by {requesting_user.username}",
|
||||
datetime.datetime.now(UTC).isoformat()
|
||||
])
|
||||
user_profile.set_meta(meta)
|
||||
@@ -324,8 +321,8 @@ def _send_email_change_requests_if_needed(data, user):
|
||||
student_views.do_email_change_request(user, new_email)
|
||||
except ValueError as err:
|
||||
raise AccountUpdateError( # lint-amnesty, pylint: disable=raise-missing-from
|
||||
u"Error thrown from do_email_change_request: '{}'".format(text_type(err)),
|
||||
user_message=text_type(err)
|
||||
"Error thrown from do_email_change_request: '{}'".format(str(err)),
|
||||
user_message=str(err)
|
||||
)
|
||||
|
||||
new_secondary_email = data.get("secondary_email")
|
||||
@@ -338,8 +335,8 @@ def _send_email_change_requests_if_needed(data, user):
|
||||
)
|
||||
except ValueError as err:
|
||||
raise AccountUpdateError( # lint-amnesty, pylint: disable=raise-missing-from
|
||||
u"Error thrown from do_email_change_request: '{}'".format(text_type(err)),
|
||||
user_message=text_type(err)
|
||||
"Error thrown from do_email_change_request: '{}'".format(str(err)),
|
||||
user_message=str(err)
|
||||
)
|
||||
|
||||
|
||||
@@ -480,7 +477,7 @@ def _validate(validation_func, err, *args):
|
||||
try:
|
||||
validation_func(*args)
|
||||
except err as validation_err:
|
||||
return text_type(validation_err)
|
||||
return str(validation_err)
|
||||
return ''
|
||||
|
||||
|
||||
@@ -499,7 +496,7 @@ def _validate_username(username):
|
||||
"""
|
||||
try:
|
||||
_validate_unicode(username)
|
||||
_validate_type(username, six.string_types, accounts.USERNAME_BAD_TYPE_MSG)
|
||||
_validate_type(username, str, accounts.USERNAME_BAD_TYPE_MSG)
|
||||
_validate_length(
|
||||
username,
|
||||
accounts.USERNAME_MIN_LENGTH,
|
||||
@@ -511,7 +508,7 @@ def _validate_username(username):
|
||||
# message by convention.
|
||||
validate_username(username)
|
||||
except (UnicodeError, errors.AccountDataBadType, errors.AccountDataBadLength) as username_err:
|
||||
raise errors.AccountUsernameInvalid(text_type(username_err))
|
||||
raise errors.AccountUsernameInvalid(str(username_err))
|
||||
except ValidationError as validation_err:
|
||||
raise errors.AccountUsernameInvalid(validation_err.message)
|
||||
|
||||
@@ -531,12 +528,12 @@ def _validate_email(email):
|
||||
"""
|
||||
try:
|
||||
_validate_unicode(email)
|
||||
_validate_type(email, six.string_types, accounts.EMAIL_BAD_TYPE_MSG)
|
||||
_validate_type(email, str, accounts.EMAIL_BAD_TYPE_MSG)
|
||||
_validate_length(email, accounts.EMAIL_MIN_LENGTH, accounts.EMAIL_MAX_LENGTH, accounts.EMAIL_BAD_LENGTH_MSG)
|
||||
validate_email.message = accounts.EMAIL_INVALID_MSG.format(email=email)
|
||||
validate_email(email)
|
||||
except (UnicodeError, errors.AccountDataBadType, errors.AccountDataBadLength) as invalid_email_err:
|
||||
raise errors.AccountEmailInvalid(text_type(invalid_email_err))
|
||||
raise errors.AccountEmailInvalid(str(invalid_email_err))
|
||||
except ValidationError as validation_err:
|
||||
raise errors.AccountEmailInvalid(validation_err.message)
|
||||
|
||||
@@ -573,11 +570,11 @@ def _validate_password(password, username=None, email=None):
|
||||
|
||||
"""
|
||||
try:
|
||||
_validate_type(password, six.string_types, accounts.PASSWORD_BAD_TYPE_MSG)
|
||||
_validate_type(password, str, accounts.PASSWORD_BAD_TYPE_MSG)
|
||||
temp_user = User(username=username, email=email) if username else None
|
||||
validate_password(password, user=temp_user)
|
||||
except errors.AccountDataBadType as invalid_password_err:
|
||||
raise errors.AccountPasswordInvalid(text_type(invalid_password_err))
|
||||
raise errors.AccountPasswordInvalid(str(invalid_password_err))
|
||||
except ValidationError as validation_err:
|
||||
raise errors.AccountPasswordInvalid(' '.join(validation_err.messages))
|
||||
|
||||
@@ -680,7 +677,7 @@ def _validate_length(data, min, max, err): # lint-amnesty, pylint: disable=rede
|
||||
raise errors.AccountDataBadLength(err)
|
||||
|
||||
|
||||
def _validate_unicode(data, err=u"Input not valid unicode"):
|
||||
def _validate_unicode(data, err="Input not valid unicode"):
|
||||
"""Checks whether the input data is valid unicode or not.
|
||||
|
||||
:param data: The data to check for unicode validity.
|
||||
@@ -690,9 +687,9 @@ def _validate_unicode(data, err=u"Input not valid unicode"):
|
||||
|
||||
"""
|
||||
try:
|
||||
if not isinstance(data, str) and not isinstance(data, six.text_type):
|
||||
if not isinstance(data, str) and not isinstance(data, str):
|
||||
raise UnicodeError(err)
|
||||
# In some cases we pass the above, but it's still inappropriate utf-8.
|
||||
six.text_type(data)
|
||||
str(data)
|
||||
except UnicodeError:
|
||||
raise UnicodeError(err) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
@@ -26,8 +26,8 @@ class RetirementQueueDeletionForm(forms.Form):
|
||||
None,
|
||||
# Translators: 'current_state' is a string from an enumerated list indicating the learner's retirement
|
||||
# state. Example: FORUMS_COMPLETE
|
||||
u"Retirement requests can only be cancelled for users in the PENDING state."
|
||||
u" Current request state for '{original_username}': {current_state}".format(
|
||||
"Retirement requests can only be cancelled for users in the PENDING state."
|
||||
" Current request state for '{original_username}': {current_state}".format(
|
||||
original_username=retirement.original_username,
|
||||
current_state=retirement.current_state.state_name
|
||||
)
|
||||
|
||||
@@ -43,7 +43,7 @@ def _get_profile_image_filename(name, size, file_extension=PROFILE_IMAGE_FILE_EX
|
||||
"""
|
||||
Returns the full filename for a profile image, given the name and size.
|
||||
"""
|
||||
return '{name}_{size}.{file_extension}'.format(name=name, size=size, file_extension=file_extension)
|
||||
return f'{name}_{size}.{file_extension}'
|
||||
|
||||
|
||||
def _get_profile_image_urls(name, storage, file_extension=PROFILE_IMAGE_FILE_EXTENSION, version=None):
|
||||
@@ -60,7 +60,7 @@ def _get_profile_image_urls(name, storage, file_extension=PROFILE_IMAGE_FILE_EXT
|
||||
# query string (such as signed S3 URLs), append to the query
|
||||
# string with "&v=" instead.
|
||||
separator = '&' if '?' in url else '?'
|
||||
return '{}{}v={}'.format(url, separator, version) if version is not None else url
|
||||
return f'{url}{separator}v={version}' if version is not None else url
|
||||
|
||||
return {size_display_name: _make_url(size) for size_display_name, size in settings.PROFILE_IMAGE_SIZES_MAP.items()}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imp
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.urls import reverse
|
||||
from rest_framework import serializers
|
||||
from six import text_type
|
||||
|
||||
from common.djangoapps.student.models import UserPasswordToggleHistory
|
||||
from lms.djangoapps.badges.utils import badges_enabled
|
||||
@@ -54,7 +53,7 @@ class LanguageProficiencySerializer(serializers.ModelSerializer):
|
||||
Class that serializes the LanguageProficiency model for account
|
||||
information.
|
||||
"""
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = LanguageProficiency
|
||||
fields = ("code",)
|
||||
|
||||
@@ -75,7 +74,7 @@ class SocialLinkSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
Class that serializes the SocialLink model for the UserProfile object.
|
||||
"""
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = SocialLink
|
||||
fields = ("platform", "social_link")
|
||||
|
||||
@@ -86,7 +85,7 @@ class SocialLinkSerializer(serializers.ModelSerializer):
|
||||
valid_platforms = ["facebook", "twitter", "linkedin"]
|
||||
if platform not in valid_platforms:
|
||||
raise serializers.ValidationError(
|
||||
u"The social platform must be facebook, twitter or linkedin"
|
||||
"The social platform must be facebook, twitter or linkedin"
|
||||
)
|
||||
return platform
|
||||
|
||||
@@ -105,7 +104,7 @@ class UserReadOnlySerializer(serializers.Serializer): # lint-amnesty, pylint: d
|
||||
# Don't pass the 'custom_fields' arg up to the superclass
|
||||
self.custom_fields = kwargs.pop('custom_fields', [])
|
||||
|
||||
super(UserReadOnlySerializer, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def to_representation(self, user): # lint-amnesty, pylint: disable=arguments-differ
|
||||
"""
|
||||
@@ -117,7 +116,7 @@ class UserReadOnlySerializer(serializers.Serializer): # lint-amnesty, pylint: d
|
||||
user_profile = user.profile
|
||||
except ObjectDoesNotExist:
|
||||
user_profile = None
|
||||
LOGGER.warning(u"user profile for the user [%s] does not exist", user.username)
|
||||
LOGGER.warning("user profile for the user [%s] does not exist", user.username)
|
||||
|
||||
try:
|
||||
account_recovery = user.account_recovery
|
||||
@@ -226,7 +225,7 @@ class UserAccountDisableHistorySerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
created_by = serializers.SerializerMethodField()
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = UserPasswordToggleHistory
|
||||
fields = ("created", "comment", "disabled", "created_by")
|
||||
|
||||
@@ -240,7 +239,7 @@ class AccountUserSerializer(serializers.HyperlinkedModelSerializer, ReadOnlyFiel
|
||||
"""
|
||||
password_toggle_history = UserAccountDisableHistorySerializer(many=True, required=False)
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ("username", "email", "date_joined", "is_active", "password_toggle_history")
|
||||
read_only_fields = fields
|
||||
@@ -257,7 +256,7 @@ class AccountLegacyProfileSerializer(serializers.HyperlinkedModelSerializer, Rea
|
||||
social_links = SocialLinkSerializer(many=True, required=False)
|
||||
phone_number = PhoneNumberSerializer(required=False)
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = UserProfile
|
||||
fields = (
|
||||
"name", "gender", "goals", "year_of_birth", "level_of_education", "country", "state", "social_links",
|
||||
@@ -272,7 +271,7 @@ class AccountLegacyProfileSerializer(serializers.HyperlinkedModelSerializer, Rea
|
||||
""" Enforce maximum length for bio. """
|
||||
if len(new_bio) > BIO_MAX_LENGTH:
|
||||
raise serializers.ValidationError(
|
||||
u"The about me field must be at most {} characters long.".format(BIO_MAX_LENGTH)
|
||||
f"The about me field must be at most {BIO_MAX_LENGTH} characters long."
|
||||
)
|
||||
return new_bio
|
||||
|
||||
@@ -280,7 +279,7 @@ class AccountLegacyProfileSerializer(serializers.HyperlinkedModelSerializer, Rea
|
||||
""" Enforce minimum length for name. """
|
||||
if len(new_name) < NAME_MIN_LENGTH:
|
||||
raise serializers.ValidationError(
|
||||
u"The name field must be at least {} character long.".format(NAME_MIN_LENGTH)
|
||||
f"The name field must be at least {NAME_MIN_LENGTH} character long."
|
||||
)
|
||||
return new_name
|
||||
|
||||
@@ -289,7 +288,7 @@ class AccountLegacyProfileSerializer(serializers.HyperlinkedModelSerializer, Rea
|
||||
Enforce all languages are unique.
|
||||
"""
|
||||
language_proficiencies = [language for language in value] # lint-amnesty, pylint: disable=unnecessary-comprehension
|
||||
unique_language_proficiencies = set(language["code"] for language in language_proficiencies)
|
||||
unique_language_proficiencies = {language["code"] for language in language_proficiencies}
|
||||
if len(language_proficiencies) != len(unique_language_proficiencies):
|
||||
raise serializers.ValidationError("The language_proficiencies field must consist of unique languages.")
|
||||
return value
|
||||
@@ -299,7 +298,7 @@ class AccountLegacyProfileSerializer(serializers.HyperlinkedModelSerializer, Rea
|
||||
Enforce only one entry for a particular social platform.
|
||||
"""
|
||||
social_links = [social_link for social_link in value] # lint-amnesty, pylint: disable=unnecessary-comprehension
|
||||
unique_social_links = set(social_link["platform"] for social_link in social_links)
|
||||
unique_social_links = {social_link["platform"] for social_link in social_links}
|
||||
if len(social_links) != len(unique_social_links):
|
||||
raise serializers.ValidationError("The social_links field must consist of unique social platforms.")
|
||||
return value
|
||||
@@ -349,7 +348,7 @@ class AccountLegacyProfileSerializer(serializers.HyperlinkedModelSerializer, Rea
|
||||
data = {'has_image': user_profile.has_profile_image}
|
||||
urls = get_profile_image_urls_for_user(user, request)
|
||||
data.update({
|
||||
'{image_key_prefix}_{size}'.format(image_key_prefix=PROFILE_IMAGE_KEY_PREFIX, size=size_display_name): url
|
||||
f'{PROFILE_IMAGE_KEY_PREFIX}_{size_display_name}': url
|
||||
for size_display_name, url in urls.items()
|
||||
})
|
||||
return data
|
||||
@@ -408,8 +407,8 @@ class AccountLegacyProfileSerializer(serializers.HyperlinkedModelSerializer, Rea
|
||||
# If we have encountered any validation errors, return them to the user.
|
||||
raise errors.AccountValidationError({
|
||||
'social_links': {
|
||||
"developer_message": u"Error when adding new social link: '{}'".format(text_type(err)),
|
||||
"user_message": text_type(err)
|
||||
"developer_message": "Error when adding new social link: '{}'".format(str(err)),
|
||||
"user_message": str(err)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -425,7 +424,7 @@ class AccountLegacyProfileSerializer(serializers.HyperlinkedModelSerializer, Rea
|
||||
|
||||
# Update all fields on the user profile that are writeable,
|
||||
# except for "language_proficiencies" and "social_links", which we'll update separately
|
||||
update_fields = set(self.get_writeable_fields()) - set(["language_proficiencies"]) - set(["social_links"])
|
||||
update_fields = set(self.get_writeable_fields()) - {"language_proficiencies"} - {"social_links"}
|
||||
for field_name in update_fields:
|
||||
default = getattr(instance, field_name)
|
||||
field_value = validated_data.get(field_name, default)
|
||||
@@ -452,7 +451,7 @@ class RetirementUserProfileSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
Serialize a small subset of UserProfile data for use in RetirementStatus APIs
|
||||
"""
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = UserProfile
|
||||
fields = ('id', 'name')
|
||||
|
||||
@@ -463,7 +462,7 @@ class RetirementUserSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
profile = RetirementUserProfileSerializer(read_only=True)
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ('id', 'username', 'email', 'profile')
|
||||
|
||||
@@ -472,7 +471,7 @@ class RetirementStateSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
Serialize a small subset of RetirementState data for use in RetirementStatus APIs
|
||||
"""
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = RetirementState
|
||||
fields = ('id', 'state_name', 'state_execution_order')
|
||||
|
||||
@@ -485,7 +484,7 @@ class UserRetirementStatusSerializer(serializers.ModelSerializer):
|
||||
current_state = RetirementStateSerializer(read_only=True)
|
||||
last_state = RetirementStateSerializer(read_only=True)
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = UserRetirementStatus
|
||||
exclude = ['responses', ]
|
||||
|
||||
@@ -580,6 +579,6 @@ def _visible_fields_from_custom_preferences(user, configuration):
|
||||
preferences = UserPreference.get_all_preferences(user)
|
||||
fields_shared_with_all_users = [
|
||||
field_name for field_name in configuration.get('custom_shareable_fields')
|
||||
if preferences.get('{}{}'.format(VISIBILITY_PREFIX, field_name)) == 'all_users'
|
||||
if preferences.get(f'{VISIBILITY_PREFIX}{field_name}') == 'all_users'
|
||||
]
|
||||
return set(fields_shared_with_all_users + configuration.get('public_fields'))
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
|
||||
import logging
|
||||
import urllib
|
||||
from datetime import datetime
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
@@ -64,7 +64,7 @@ def account_settings(request):
|
||||
if duplicate_provider:
|
||||
url = '{url}?{params}'.format(
|
||||
url=url,
|
||||
params=six.moves.urllib.parse.urlencode({
|
||||
params=urllib.parse.urlencode({
|
||||
'duplicate_provider': duplicate_provider,
|
||||
}),
|
||||
)
|
||||
@@ -87,7 +87,7 @@ def account_settings_context(request):
|
||||
"""
|
||||
user = request.user
|
||||
|
||||
year_of_birth_options = [(six.text_type(year), six.text_type(year)) for year in UserProfile.VALID_YEARS]
|
||||
year_of_birth_options = [(str(year), str(year)) for year in UserProfile.VALID_YEARS]
|
||||
try:
|
||||
user_orders = get_user_orders(user)
|
||||
except: # pylint: disable=bare-except
|
||||
@@ -231,19 +231,19 @@ def _get_extended_profile_fields():
|
||||
'gender', 'year_of_birth', 'language_proficiencies', 'social_links']
|
||||
|
||||
field_labels_map = {
|
||||
"first_name": _(u"First Name"),
|
||||
"last_name": _(u"Last Name"),
|
||||
"city": _(u"City"),
|
||||
"state": _(u"State/Province/Region"),
|
||||
"company": _(u"Company"),
|
||||
"title": _(u"Title"),
|
||||
"job_title": _(u"Job Title"),
|
||||
"mailing_address": _(u"Mailing address"),
|
||||
"goals": _(u"Tell us why you're interested in {platform_name}").format(
|
||||
"first_name": _("First Name"),
|
||||
"last_name": _("Last Name"),
|
||||
"city": _("City"),
|
||||
"state": _("State/Province/Region"),
|
||||
"company": _("Company"),
|
||||
"title": _("Title"),
|
||||
"job_title": _("Job Title"),
|
||||
"mailing_address": _("Mailing address"),
|
||||
"goals": _("Tell us why you're interested in {platform_name}").format(
|
||||
platform_name=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME)
|
||||
),
|
||||
"profession": _(u"Profession"),
|
||||
"specialty": _(u"Specialty")
|
||||
"profession": _("Profession"),
|
||||
"specialty": _("Specialty")
|
||||
}
|
||||
|
||||
extended_profile_field_names = configuration_helpers.get_value('extended_profile_fields', [])
|
||||
|
||||
@@ -4,15 +4,13 @@ Utility methods for the account settings.
|
||||
|
||||
|
||||
import re
|
||||
from urllib.parse import urlparse # pylint: disable=import-error
|
||||
|
||||
import waffle
|
||||
from completion.waffle import ENABLE_COMPLETION_TRACKING_SWITCH
|
||||
from completion.models import BlockCompletion
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
from six import text_type
|
||||
from six.moves import range # lint-amnesty, pylint: disable=unused-import
|
||||
from six.moves.urllib.parse import urlparse # pylint: disable=import-error
|
||||
|
||||
from common.djangoapps.third_party_auth.config.waffle import ENABLE_MULTIPLE_SSO_ACCOUNTS_ASSOCIATION_TO_SAML_USER
|
||||
from openedx.core.djangoapps.site_configuration.models import SiteConfiguration
|
||||
@@ -63,7 +61,7 @@ def format_social_link(platform_name, new_social_link):
|
||||
return None
|
||||
|
||||
# For security purposes, always build up the url rather than using input from user.
|
||||
return 'https://www.{}{}'.format(url_stub, username)
|
||||
return f'https://www.{url_stub}{username}'
|
||||
|
||||
|
||||
def _get_username_from_social_link(platform_name, new_social_link):
|
||||
@@ -173,10 +171,10 @@ def retrieve_last_sitewide_block_completed(user):
|
||||
if not (lms_root and item):
|
||||
return
|
||||
|
||||
return u"{lms_root}/courses/{course_key}/jump_to/{location}".format(
|
||||
return "{lms_root}/courses/{course_key}/jump_to/{location}".format(
|
||||
lms_root=lms_root,
|
||||
course_key=text_type(item.location.course_key),
|
||||
location=text_type(item.location),
|
||||
course_key=str(item.location.course_key),
|
||||
location=str(item.location),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ from rest_framework.response import Response
|
||||
from rest_framework.serializers import ValidationError
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.viewsets import ViewSet
|
||||
from six import iteritems, text_type
|
||||
from social_django.models import UserSocialAuth
|
||||
from wiki.models import ArticleRevision
|
||||
from wiki.models.pluginbase import RevisionPluginRevision
|
||||
@@ -115,7 +114,7 @@ def request_requires_username(function):
|
||||
if not username:
|
||||
return Response(
|
||||
status=status.HTTP_404_NOT_FOUND,
|
||||
data={'message': text_type('The user was not specified.')}
|
||||
data={'message': 'The user was not specified.'}
|
||||
)
|
||||
return function(self, request)
|
||||
return wrapper
|
||||
@@ -469,16 +468,16 @@ class DeactivateLogoutView(APIView):
|
||||
logout(request)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
except KeyError:
|
||||
log.exception('Username not specified {}'.format(request.user))
|
||||
return Response(u'Username not specified.', status=status.HTTP_404_NOT_FOUND)
|
||||
log.exception(f'Username not specified {request.user}')
|
||||
return Response('Username not specified.', status=status.HTTP_404_NOT_FOUND)
|
||||
except user_model.DoesNotExist:
|
||||
log.exception('The user "{}" does not exist.'.format(request.user.username))
|
||||
log.exception(f'The user "{request.user.username}" does not exist.')
|
||||
return Response(
|
||||
u'The user "{}" does not exist.'.format(request.user.username), status=status.HTTP_404_NOT_FOUND
|
||||
f'The user "{request.user.username}" does not exist.', status=status.HTTP_404_NOT_FOUND
|
||||
)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
log.exception('500 error deactivating account {}'.format(exc))
|
||||
return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
log.exception(f'500 error deactivating account {exc}')
|
||||
return Response(str(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
def _verify_user_password(self, request):
|
||||
"""
|
||||
@@ -499,11 +498,11 @@ class DeactivateLogoutView(APIView):
|
||||
self._handle_failed_authentication(request.user)
|
||||
except AuthFailedError as err:
|
||||
log.exception(
|
||||
"The user password to deactivate was incorrect. {}".format(request.user.username)
|
||||
f"The user password to deactivate was incorrect. {request.user.username}"
|
||||
)
|
||||
return Response(text_type(err), status=status.HTTP_403_FORBIDDEN)
|
||||
return Response(str(err), status=status.HTTP_403_FORBIDDEN)
|
||||
except Exception as err: # pylint: disable=broad-except
|
||||
return Response(u"Could not verify user password: {}".format(err), status=status.HTTP_400_BAD_REQUEST)
|
||||
return Response(f"Could not verify user password: {err}", status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def _check_excessive_login_attempts(self, user):
|
||||
"""
|
||||
@@ -713,9 +712,9 @@ class AccountRetirementPartnerReportView(ViewSet):
|
||||
# to disambiguate them in Python, which will respect case in the comparison.
|
||||
if len(usernames) != len(retirement_statuses_clean):
|
||||
return Response(
|
||||
u'{} original_usernames given, {} found!\n'
|
||||
u'Given usernames:\n{}\n'
|
||||
u'Found UserRetirementReportingStatuses:\n{}'.format(
|
||||
'{} original_usernames given, {} found!\n'
|
||||
'Given usernames:\n{}\n'
|
||||
'Found UserRetirementReportingStatuses:\n{}'.format(
|
||||
len(usernames),
|
||||
len(retirement_statuses_clean),
|
||||
usernames,
|
||||
@@ -758,7 +757,7 @@ class AccountRetirementStatusView(ViewSet):
|
||||
state_objs = RetirementState.objects.filter(state_name__in=states)
|
||||
if state_objs.count() != len(states):
|
||||
found = [s.state_name for s in state_objs]
|
||||
raise RetirementStateError(u'Unknown state. Requested: {} Found: {}'.format(states, found))
|
||||
raise RetirementStateError(f'Unknown state. Requested: {states} Found: {found}')
|
||||
|
||||
earliest_datetime = datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=cool_off_days)
|
||||
|
||||
@@ -775,10 +774,10 @@ class AccountRetirementStatusView(ViewSet):
|
||||
except ValueError:
|
||||
return Response('Invalid cool_off_days, should be integer.', status=status.HTTP_400_BAD_REQUEST)
|
||||
except KeyError as exc:
|
||||
return Response(u'Missing required parameter: {}'.format(text_type(exc)),
|
||||
return Response('Missing required parameter: {}'.format(str(exc)),
|
||||
status=status.HTTP_400_BAD_REQUEST)
|
||||
except RetirementStateError as exc:
|
||||
return Response(text_type(exc), status=status.HTTP_400_BAD_REQUEST)
|
||||
return Response(str(exc), status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def retirements_by_status_and_date(self, request):
|
||||
"""
|
||||
@@ -815,14 +814,14 @@ class AccountRetirementStatusView(ViewSet):
|
||||
return Response(serializer.data)
|
||||
# This should only occur on the datetime conversion of the start / end dates.
|
||||
except ValueError as exc:
|
||||
return Response(u'Invalid start or end date: {}'.format(text_type(exc)), status=status.HTTP_400_BAD_REQUEST)
|
||||
return Response('Invalid start or end date: {}'.format(str(exc)), status=status.HTTP_400_BAD_REQUEST)
|
||||
except KeyError as exc:
|
||||
return Response(u'Missing required parameter: {}'.format(text_type(exc)),
|
||||
return Response('Missing required parameter: {}'.format(str(exc)),
|
||||
status=status.HTTP_400_BAD_REQUEST)
|
||||
except RetirementState.DoesNotExist:
|
||||
return Response('Unknown retirement state.', status=status.HTTP_400_BAD_REQUEST)
|
||||
except RetirementStateError as exc:
|
||||
return Response(text_type(exc), status=status.HTTP_400_BAD_REQUEST)
|
||||
return Response(str(exc), status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def retrieve(self, request, username): # pylint: disable=unused-argument
|
||||
"""
|
||||
@@ -886,9 +885,9 @@ class AccountRetirementStatusView(ViewSet):
|
||||
except UserRetirementStatus.DoesNotExist:
|
||||
return Response(status=status.HTTP_404_NOT_FOUND)
|
||||
except RetirementStateError as exc:
|
||||
return Response(text_type(exc), status=status.HTTP_400_BAD_REQUEST)
|
||||
return Response(str(exc), status=status.HTTP_400_BAD_REQUEST)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
return Response(str(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
def cleanup(self, request):
|
||||
"""
|
||||
@@ -921,9 +920,9 @@ class AccountRetirementStatusView(ViewSet):
|
||||
retirements.delete()
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
except (RetirementStateError, UserRetirementStatus.DoesNotExist, TypeError) as exc:
|
||||
return Response(text_type(exc), status=status.HTTP_400_BAD_REQUEST)
|
||||
return Response(str(exc), status=status.HTTP_400_BAD_REQUEST)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
return Response(str(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
|
||||
class LMSAccountRetirementView(ViewSet):
|
||||
@@ -975,9 +974,9 @@ class LMSAccountRetirementView(ViewSet):
|
||||
except UserRetirementStatus.DoesNotExist:
|
||||
return Response(status=status.HTTP_404_NOT_FOUND)
|
||||
except RetirementStateError as exc:
|
||||
return Response(text_type(exc), status=status.HTTP_400_BAD_REQUEST)
|
||||
return Response(str(exc), status=status.HTTP_400_BAD_REQUEST)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
return Response(str(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@@ -1045,9 +1044,9 @@ class AccountRetirementView(ViewSet):
|
||||
except UserRetirementStatus.DoesNotExist:
|
||||
return Response(status=status.HTTP_404_NOT_FOUND)
|
||||
except RetirementStateError as exc:
|
||||
return Response(text_type(exc), status=status.HTTP_400_BAD_REQUEST)
|
||||
return Response(str(exc), status=status.HTTP_400_BAD_REQUEST)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
return Response(str(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@@ -1057,7 +1056,7 @@ class AccountRetirementView(ViewSet):
|
||||
For the given user, sets all of the user's profile fields to some retired value.
|
||||
This also deletes all ``SocialLink`` objects associated with this user's profile.
|
||||
"""
|
||||
for model_field, value_to_assign in iteritems(USER_PROFILE_PII):
|
||||
for model_field, value_to_assign in USER_PROFILE_PII.items():
|
||||
setattr(user.profile, model_field, value_to_assign)
|
||||
|
||||
user.profile.save()
|
||||
@@ -1260,7 +1259,7 @@ class UsernameReplacementView(APIView):
|
||||
)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
log.exception(
|
||||
u"Unable to change username from %s to %s. Failed on table %s because %s",
|
||||
"Unable to change username from %s to %s. Failed on table %s because %s",
|
||||
current_username,
|
||||
new_username,
|
||||
model.__class__.__name__, # Retrieves the model name that it failed on
|
||||
@@ -1269,14 +1268,14 @@ class UsernameReplacementView(APIView):
|
||||
return False
|
||||
if num_rows_changed == 0:
|
||||
log.info(
|
||||
u"Unable to change username from %s to %s because %s doesn't exist.",
|
||||
"Unable to change username from %s to %s because %s doesn't exist.",
|
||||
current_username,
|
||||
new_username,
|
||||
current_username,
|
||||
)
|
||||
else:
|
||||
log.info(
|
||||
u"Successfully changed username from %s to %s.",
|
||||
"Successfully changed username from %s to %s.",
|
||||
current_username,
|
||||
new_username,
|
||||
)
|
||||
|
||||
@@ -26,7 +26,7 @@ class RetirementStateAdmin(admin.ModelAdmin):
|
||||
list_filter = ('is_dead_end_state', 'required',)
|
||||
search_fields = ('state_name',)
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = RetirementState
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ class UserRetirementStatusAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
Adds our custom URL to the admin
|
||||
"""
|
||||
urls = super(UserRetirementStatusAdmin, self).get_urls() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
urls = super().get_urls()
|
||||
custom_urls = [
|
||||
url(
|
||||
r'^(?P<retirement_id>.+)/cancel_retirement/$',
|
||||
@@ -105,7 +105,7 @@ class UserRetirementStatusAdmin(admin.ModelAdmin):
|
||||
try:
|
||||
if obj.current_state.state_name == 'PENDING':
|
||||
return format_html(
|
||||
u'<a class="button" href="{}">{}</a> ',
|
||||
'<a class="button" href="{}">{}</a> ',
|
||||
reverse('admin:cancel-retirement', args=[obj.pk]),
|
||||
_('Cancel')
|
||||
)
|
||||
@@ -121,7 +121,7 @@ class UserRetirementStatusAdmin(admin.ModelAdmin):
|
||||
Removes the default bulk delete option provided by Django,
|
||||
it doesn't do what we need for this model.
|
||||
"""
|
||||
actions = super(UserRetirementStatusAdmin, self).get_actions(request) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
actions = super().get_actions(request)
|
||||
if 'delete_selected' in actions:
|
||||
del actions['delete_selected']
|
||||
return actions
|
||||
@@ -138,7 +138,7 @@ class UserRetirementStatusAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
return False
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = UserRetirementStatus
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ class UserRetirementRequestAdmin(admin.ModelAdmin):
|
||||
list_display = ('user', 'created')
|
||||
raw_id_fields = ('user',)
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = UserRetirementRequest
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ class UserRetirementPartnerReportingStatusAdmin(admin.ModelAdmin):
|
||||
'reset_state', # See reset_state() below.
|
||||
]
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = UserRetirementPartnerReportingStatus
|
||||
|
||||
def user_id(self, obj):
|
||||
@@ -192,7 +192,7 @@ class UserRetirementPartnerReportingStatusAdmin(admin.ModelAdmin):
|
||||
if rows_updated == 1:
|
||||
message_bit = "one user was"
|
||||
else:
|
||||
message_bit = u"%s users were" % rows_updated
|
||||
self.message_user(request, u"%s successfully reset." % message_bit)
|
||||
message_bit = "%s users were" % rows_updated
|
||||
self.message_user(request, "%s successfully reset." % message_bit)
|
||||
|
||||
reset_state.short_description = 'Reset is_being_processed to False'
|
||||
|
||||
@@ -7,7 +7,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from edx_toggles.toggles import WaffleSwitch
|
||||
|
||||
SYSTEM_MAINTENANCE_MSG = _(u'System maintenance in progress. Please try again later.')
|
||||
SYSTEM_MAINTENANCE_MSG = _('System maintenance in progress. Please try again later.')
|
||||
|
||||
# .. toggle_name: user_api.enable_multiple_user_enterprises_feature
|
||||
# .. toggle_implementation: WaffleSwitch
|
||||
|
||||
@@ -20,8 +20,8 @@ from ..models import UserCourseTag
|
||||
COURSE_SCOPE = 'course'
|
||||
|
||||
|
||||
class BulkCourseTags(object): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
CACHE_NAMESPACE = u'user_api.course_tag.api'
|
||||
class BulkCourseTags: # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
CACHE_NAMESPACE = 'user_api.course_tag.api'
|
||||
|
||||
@classmethod
|
||||
def prefetch(cls, course_id, users):
|
||||
@@ -53,7 +53,7 @@ class BulkCourseTags(object): # lint-amnesty, pylint: disable=missing-class-doc
|
||||
|
||||
@classmethod
|
||||
def _cache_key(cls, course_id):
|
||||
return u'course_tag.{}'.format(course_id)
|
||||
return f'course_tag.{course_id}'
|
||||
|
||||
|
||||
def get_course_tag(user, course_id, key):
|
||||
|
||||
@@ -108,7 +108,7 @@ class PreferenceValidationError(PreferenceRequestError):
|
||||
"""
|
||||
def __init__(self, preference_errors):
|
||||
self.preference_errors = preference_errors
|
||||
super(PreferenceValidationError, self).__init__(preference_errors) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(preference_errors)
|
||||
|
||||
|
||||
class PreferenceUpdateError(PreferenceRequestError):
|
||||
@@ -119,7 +119,7 @@ class PreferenceUpdateError(PreferenceRequestError):
|
||||
def __init__(self, developer_message, user_message=None):
|
||||
self.developer_message = developer_message
|
||||
self.user_message = user_message
|
||||
super(PreferenceUpdateError, self).__init__(developer_message) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(developer_message)
|
||||
|
||||
|
||||
class CountryCodeError(ValueError):
|
||||
|
||||
@@ -10,7 +10,6 @@ import traceback
|
||||
from collections import defaultdict
|
||||
from functools import wraps
|
||||
|
||||
import six
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.serializers.json import DjangoJSONEncoder
|
||||
@@ -57,9 +56,9 @@ def intercept_errors(api_error, ignore_errors=None):
|
||||
for ignored in ignore_errors or []:
|
||||
if isinstance(ex, ignored):
|
||||
msg = (
|
||||
u"A handled error occurred when calling '{func_name}' "
|
||||
u"with arguments '{args}' and keyword arguments '{kwargs}': "
|
||||
u"{exception}"
|
||||
"A handled error occurred when calling '{func_name}' "
|
||||
"with arguments '{args}' and keyword arguments '{kwargs}': "
|
||||
"{exception}"
|
||||
).format(
|
||||
func_name=func.__name__,
|
||||
args=args,
|
||||
@@ -73,9 +72,9 @@ def intercept_errors(api_error, ignore_errors=None):
|
||||
|
||||
# Otherwise, log the error and raise the API-specific error
|
||||
msg = (
|
||||
u"An unexpected error occurred when calling '{func_name}' "
|
||||
u"with arguments '{args}' and keyword arguments '{kwargs}' from {caller}: "
|
||||
u"{exception}"
|
||||
"An unexpected error occurred when calling '{func_name}' "
|
||||
"with arguments '{args}' and keyword arguments '{kwargs}' from {caller}: "
|
||||
"{exception}"
|
||||
).format(
|
||||
func_name=func.__name__,
|
||||
args=args,
|
||||
@@ -93,7 +92,7 @@ class InvalidFieldError(Exception):
|
||||
"""The provided field definition is not valid. """
|
||||
|
||||
|
||||
class FormDescription(object):
|
||||
class FormDescription:
|
||||
"""Generate a JSON representation of a form. """
|
||||
|
||||
ALLOWED_TYPES = ["text", "email", "select", "textarea", "checkbox", "plaintext", "password", "hidden"]
|
||||
@@ -135,10 +134,10 @@ class FormDescription(object):
|
||||
self._field_overrides = defaultdict(dict)
|
||||
|
||||
def add_field(
|
||||
self, name, label=u"", field_type=u"text", default=u"",
|
||||
placeholder=u"", instructions=u"", required=True, restrictions=None,
|
||||
self, name, label="", field_type="text", default="",
|
||||
placeholder="", instructions="", required=True, restrictions=None,
|
||||
options=None, include_default_option=False, error_messages=None,
|
||||
supplementalLink=u"", supplementalText=u""
|
||||
supplementalLink="", supplementalText=""
|
||||
):
|
||||
"""Add a field to the form description.
|
||||
|
||||
@@ -190,7 +189,7 @@ class FormDescription(object):
|
||||
|
||||
"""
|
||||
if field_type not in self.ALLOWED_TYPES:
|
||||
msg = u"Field type '{field_type}' is not a valid type. Allowed types are: {allowed}.".format(
|
||||
msg = "Field type '{field_type}' is not a valid type. Allowed types are: {allowed}.".format(
|
||||
field_type=field_type,
|
||||
allowed=", ".join(self.ALLOWED_TYPES)
|
||||
)
|
||||
@@ -240,14 +239,11 @@ class FormDescription(object):
|
||||
|
||||
if restrictions is not None:
|
||||
allowed_restrictions = self.ALLOWED_RESTRICTIONS.get(field_type, [])
|
||||
for key, val in six.iteritems(restrictions):
|
||||
for key, val in restrictions.items():
|
||||
if key in allowed_restrictions:
|
||||
field_dict["restrictions"][key] = val
|
||||
else:
|
||||
msg = u"Restriction '{restriction}' is not allowed for field type '{field_type}'".format(
|
||||
restriction=key,
|
||||
field_type=field_type
|
||||
)
|
||||
msg = f"Restriction '{key}' is not allowed for field type '{field_type}'"
|
||||
raise InvalidFieldError(msg)
|
||||
|
||||
if error_messages is not None:
|
||||
@@ -337,7 +333,7 @@ class FormDescription(object):
|
||||
|
||||
self._field_overrides[field_name].update({
|
||||
property_name: property_value
|
||||
for property_name, property_value in six.iteritems(kwargs)
|
||||
for property_name, property_value in kwargs.items()
|
||||
if property_name in self.OVERRIDE_FIELD_PROPERTIES
|
||||
})
|
||||
|
||||
@@ -353,7 +349,7 @@ class LocalizedJSONEncoder(DjangoJSONEncoder):
|
||||
"""
|
||||
if isinstance(obj, Promise):
|
||||
return force_text(obj)
|
||||
super(LocalizedJSONEncoder, self).default(obj) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().default(obj)
|
||||
|
||||
|
||||
def serializer_is_dirty(preference_serializer):
|
||||
|
||||
@@ -19,7 +19,7 @@ urlpatterns = [
|
||||
url(r'^account/settings$', account_settings, name='account_settings'),
|
||||
url(r'^user_api/v1/', include(USER_API_ROUTER.urls)),
|
||||
url(
|
||||
r'^user_api/v1/preferences/(?P<pref_key>{})/users/$'.format(UserPreference.KEY_REGEX),
|
||||
fr'^user_api/v1/preferences/(?P<pref_key>{UserPreference.KEY_REGEX})/users/$',
|
||||
user_api_views.PreferenceUsersListView.as_view()
|
||||
),
|
||||
url(
|
||||
|
||||
@@ -14,7 +14,7 @@ class DeletionNotificationMessage(BaseMessageType):
|
||||
Message to notify learners that their account is queued for deletion.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DeletionNotificationMessage, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation
|
||||
self.options['from_address'] = helpers.get_value( # pylint: disable=unsupported-assignment-operation
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
import django.core.validators
|
||||
import django.utils.timezone
|
||||
import model_utils.fields
|
||||
@@ -42,21 +39,21 @@ class Migration(migrations.Migration):
|
||||
name='UserPreference',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('key', models.CharField(db_index=True, max_length=255, validators=[django.core.validators.RegexValidator(u'[-_a-zA-Z0-9]+')])),
|
||||
('key', models.CharField(db_index=True, max_length=255, validators=[django.core.validators.RegexValidator('[-_a-zA-Z0-9]+')])),
|
||||
('value', models.TextField()),
|
||||
('user', models.ForeignKey(related_name='preferences', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
|
||||
],
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='userpreference',
|
||||
unique_together=set([('user', 'key')]),
|
||||
unique_together={('user', 'key')},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='userorgtag',
|
||||
unique_together=set([('user', 'org', 'key')]),
|
||||
unique_together={('user', 'org', 'key')},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='usercoursetag',
|
||||
unique_together=set([('user', 'course_id', 'key')]),
|
||||
unique_together={('user', 'course_id', 'key')},
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.12 on 2018-04-19 17:55
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.13 on 2018-05-14 20:37
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.13 on 2018-06-13 20:54
|
||||
|
||||
|
||||
|
||||
@@ -45,12 +45,12 @@ class UserPreference(models.Model):
|
||||
|
||||
.. no_pii: Stores arbitrary key/value pairs, currently none are PII. If that changes, update this annotation.
|
||||
"""
|
||||
KEY_REGEX = u"[-_a-zA-Z0-9]+"
|
||||
KEY_REGEX = "[-_a-zA-Z0-9]+"
|
||||
user = models.ForeignKey(User, db_index=True, related_name="preferences", on_delete=models.CASCADE)
|
||||
key = models.CharField(max_length=255, db_index=True, validators=[RegexValidator(KEY_REGEX)])
|
||||
value = models.TextField()
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
unique_together = ("user", "key")
|
||||
|
||||
@staticmethod
|
||||
@@ -61,7 +61,7 @@ class UserPreference(models.Model):
|
||||
|
||||
Returns: Set of (preference type, value) pairs for each of the user's preferences
|
||||
"""
|
||||
return dict([(pref.key, pref.value) for pref in user.preferences.all()]) # lint-amnesty, pylint: disable=consider-using-dict-comprehension
|
||||
return {pref.key: pref.value for pref in user.preferences.all()}
|
||||
|
||||
@classmethod
|
||||
def get_value(cls, user, preference_key, default=None):
|
||||
@@ -158,7 +158,7 @@ class UserCourseTag(models.Model):
|
||||
course_id = CourseKeyField(max_length=255, db_index=True)
|
||||
value = models.TextField()
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
unique_together = ("user", "course_id", "key")
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ class UserOrgTag(TimeStampedModel, DeletableByUserValue):
|
||||
org = models.CharField(max_length=255, db_index=True)
|
||||
value = models.TextField()
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
unique_together = ("user", "org", "key")
|
||||
|
||||
|
||||
@@ -195,9 +195,9 @@ class RetirementState(models.Model):
|
||||
required = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return '{} (step {})'.format(self.state_name, self.state_execution_order)
|
||||
return f'{self.state_name} (step {self.state_execution_order})'
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
ordering = ('state_execution_order',)
|
||||
|
||||
@classmethod
|
||||
@@ -232,12 +232,12 @@ class UserRetirementPartnerReportingStatus(TimeStampedModel):
|
||||
original_name = models.CharField(max_length=255, blank=True, db_index=True)
|
||||
is_being_processed = models.BooleanField(default=False)
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
verbose_name = 'User Retirement Reporting Status'
|
||||
verbose_name_plural = 'User Retirement Reporting Statuses'
|
||||
|
||||
def __str__(self):
|
||||
return u'UserRetirementPartnerReportingStatus: {} is being processed: {}'.format(
|
||||
return 'UserRetirementPartnerReportingStatus: {} is being processed: {}'.format(
|
||||
self.user,
|
||||
self.is_being_processed
|
||||
)
|
||||
@@ -254,7 +254,7 @@ class UserRetirementRequest(TimeStampedModel):
|
||||
"""
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
verbose_name = 'User Retirement Request'
|
||||
verbose_name_plural = 'User Retirement Requests'
|
||||
|
||||
@@ -264,7 +264,7 @@ class UserRetirementRequest(TimeStampedModel):
|
||||
Creates a UserRetirementRequest for the specified user.
|
||||
"""
|
||||
if cls.has_user_requested_retirement(user):
|
||||
raise RetirementStateError(u'User {} already has a retirement request row!'.format(user))
|
||||
raise RetirementStateError(f'User {user} already has a retirement request row!')
|
||||
return cls.objects.create(user=user)
|
||||
|
||||
@classmethod
|
||||
@@ -275,10 +275,9 @@ class UserRetirementRequest(TimeStampedModel):
|
||||
return cls.objects.filter(user=user).exists()
|
||||
|
||||
def __str__(self):
|
||||
return u'User: {} Requested: {}'.format(self.user.id, self.created)
|
||||
return f'User: {self.user.id} Requested: {self.created}'
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class UserRetirementStatus(TimeStampedModel):
|
||||
"""
|
||||
Tracks the progress of a user's retirement request
|
||||
@@ -297,7 +296,7 @@ class UserRetirementStatus(TimeStampedModel):
|
||||
last_state = models.ForeignKey(RetirementState, blank=True, related_name='last_state', on_delete=models.CASCADE)
|
||||
responses = models.TextField()
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
verbose_name = 'User Retirement Status'
|
||||
verbose_name_plural = 'User Retirement Statuses'
|
||||
|
||||
@@ -308,16 +307,14 @@ class UserRetirementStatus(TimeStampedModel):
|
||||
dead_end_states = list(RetirementState.get_dead_end_state_names_list())
|
||||
states = list(RetirementState.get_state_names_list())
|
||||
if self.current_state in dead_end_states:
|
||||
raise RetirementStateError(u'RetirementStatus: Unable to move user from {}'.format(self.current_state))
|
||||
raise RetirementStateError(f'RetirementStatus: Unable to move user from {self.current_state}')
|
||||
|
||||
try:
|
||||
new_state_index = states.index(new_state)
|
||||
if new_state_index <= states.index(self.current_state.state_name):
|
||||
raise ValueError()
|
||||
except ValueError:
|
||||
err = u'{} does not exist or is an eariler state than current state {}'.format(
|
||||
new_state, self.current_state
|
||||
)
|
||||
err = f'{new_state} does not exist or is an eariler state than current state {self.current_state}'
|
||||
raise RetirementStateError(err) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
def _validate_update_data(self, data):
|
||||
@@ -330,13 +327,11 @@ class UserRetirementStatus(TimeStampedModel):
|
||||
|
||||
for required_key in required_keys:
|
||||
if required_key not in data:
|
||||
raise RetirementStateError(u'RetirementStatus: Required key {} missing from update'.format(
|
||||
required_key
|
||||
))
|
||||
raise RetirementStateError(f'RetirementStatus: Required key {required_key} missing from update')
|
||||
|
||||
for key in data:
|
||||
if key not in known_keys:
|
||||
raise RetirementStateError(u'RetirementStatus: Unknown key {} in update'.format(key))
|
||||
raise RetirementStateError(f'RetirementStatus: Unknown key {key} in update')
|
||||
|
||||
@classmethod
|
||||
def create_retirement(cls, user):
|
||||
@@ -350,7 +345,7 @@ class UserRetirementStatus(TimeStampedModel):
|
||||
raise RetirementStateError('Default state does not exist! Populate retirement states to retire users.') # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
if cls.objects.filter(user=user).exists():
|
||||
raise RetirementStateError(u'User {} already has a retirement status row!'.format(user))
|
||||
raise RetirementStateError(f'User {user} already has a retirement status row!')
|
||||
|
||||
retired_username = get_retired_username_by_username(user.username)
|
||||
retired_email = get_retired_email_by_email(user.email)
|
||||
@@ -366,7 +361,7 @@ class UserRetirementStatus(TimeStampedModel):
|
||||
retired_email=retired_email,
|
||||
current_state=pending,
|
||||
last_state=pending,
|
||||
responses=u'Created in state {} by create_retirement'.format(pending)
|
||||
responses=f'Created in state {pending} by create_retirement'
|
||||
)
|
||||
|
||||
def update_state(self, update):
|
||||
@@ -383,7 +378,7 @@ class UserRetirementStatus(TimeStampedModel):
|
||||
old_state = self.current_state
|
||||
self.current_state = RetirementState.objects.get(state_name=update['new_state'])
|
||||
self.last_state = old_state
|
||||
self.responses += u"\n Moved from {} to {}:\n{}\n".format(old_state, self.current_state, update['response'])
|
||||
self.responses += "\n Moved from {} to {}:\n{}\n".format(old_state, self.current_state, update['response'])
|
||||
self.save()
|
||||
|
||||
@classmethod
|
||||
@@ -411,19 +406,19 @@ class UserRetirementStatus(TimeStampedModel):
|
||||
break
|
||||
|
||||
if retirement is None:
|
||||
raise UserRetirementStatus.DoesNotExist(u'{} does not have an exact match in UserRetirementStatus. '
|
||||
u'{} similar rows found.'.format(username, len(retirements)))
|
||||
raise UserRetirementStatus.DoesNotExist('{} does not have an exact match in UserRetirementStatus. '
|
||||
'{} similar rows found.'.format(username, len(retirements)))
|
||||
|
||||
state = retirement.current_state
|
||||
|
||||
if state.required or state.state_name.endswith('_COMPLETE'):
|
||||
raise RetirementStateError(u'{} is in {}, not a valid state to perform retirement '
|
||||
u'actions on.'.format(retirement, state.state_name))
|
||||
raise RetirementStateError('{} is in {}, not a valid state to perform retirement '
|
||||
'actions on.'.format(retirement, state.state_name))
|
||||
|
||||
return retirement
|
||||
|
||||
def __str__(self):
|
||||
return u'User: {} State: {} Last Updated: {}'.format(self.user.id, self.current_state, self.modified)
|
||||
return f'User: {self.user.id} State: {self.current_state} Last Updated: {self.modified}'
|
||||
|
||||
|
||||
@receiver(models.signals.post_delete, sender=UserRetirementStatus)
|
||||
|
||||
@@ -14,7 +14,7 @@ from xmodule.partitions.partitions import NoSuchUserPartitionGroupError, UserPar
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NotImplementedPartitionScheme(object):
|
||||
class NotImplementedPartitionScheme:
|
||||
"""
|
||||
This "scheme" allows previously-defined schemes to be purged, while giving existing
|
||||
course data definitions a safe entry point to load.
|
||||
@@ -30,7 +30,7 @@ class NotImplementedPartitionScheme(object):
|
||||
return None
|
||||
|
||||
|
||||
class ReturnGroup1PartitionScheme(object):
|
||||
class ReturnGroup1PartitionScheme:
|
||||
"""
|
||||
This scheme is needed to allow verification partitions to be killed, see EDUCATOR-199
|
||||
"""
|
||||
@@ -43,7 +43,7 @@ class ReturnGroup1PartitionScheme(object):
|
||||
return user_partition.get_group(1)
|
||||
|
||||
|
||||
class RandomUserPartitionScheme(object):
|
||||
class RandomUserPartitionScheme:
|
||||
"""
|
||||
This scheme randomly assigns users into the partition's groups.
|
||||
"""
|
||||
@@ -66,7 +66,7 @@ class RandomUserPartitionScheme(object):
|
||||
except NoSuchUserPartitionGroupError:
|
||||
# jsa: we can turn off warnings here if this is an expected case.
|
||||
log.warning(
|
||||
u"group not found in RandomUserPartitionScheme: %r",
|
||||
"group not found in RandomUserPartitionScheme: %r",
|
||||
{
|
||||
"requested_partition_id": user_partition.id,
|
||||
"requested_group_id": group_id,
|
||||
@@ -74,7 +74,7 @@ class RandomUserPartitionScheme(object):
|
||||
exc_info=True
|
||||
)
|
||||
except ValueError:
|
||||
log.error(u"Bad group_id %r for user: %r", group_id, user)
|
||||
log.error("Bad group_id %r for user: %r", group_id, user)
|
||||
|
||||
if group is None and assign and not course_tag_api.BulkCourseTags.is_prefetched(course_key):
|
||||
if not user_partition.groups:
|
||||
@@ -115,4 +115,4 @@ class RandomUserPartitionScheme(object):
|
||||
"""
|
||||
Returns the key to use to look up and save the user's group for a given user partition.
|
||||
"""
|
||||
return 'xblock.partition_service.partition_{0}'.format(user_partition.id)
|
||||
return f'xblock.partition_service.partition_{user_partition.id}'
|
||||
|
||||
@@ -5,7 +5,6 @@ API for managing user preferences.
|
||||
|
||||
import logging
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db import IntegrityError
|
||||
@@ -134,7 +133,7 @@ def update_user_preferences(requesting_user, update, user=None):
|
||||
PreferenceUpdateError: the operation failed when performing the update.
|
||||
UserAPIInternalError: the operation failed due to an unexpected error.
|
||||
"""
|
||||
if not user or isinstance(user, six.string_types):
|
||||
if not user or isinstance(user, str):
|
||||
user = _get_authorized_user(requesting_user, user)
|
||||
else:
|
||||
_check_authorized(requesting_user, user.username)
|
||||
@@ -145,7 +144,7 @@ def update_user_preferences(requesting_user, update, user=None):
|
||||
for preference_key in update.keys():
|
||||
preference_value = update[preference_key]
|
||||
if preference_value is not None:
|
||||
preference_value = six.text_type(preference_value)
|
||||
preference_value = str(preference_value)
|
||||
try:
|
||||
serializer = create_user_preference_serializer(user, preference_key, preference_value)
|
||||
validate_user_preference_serializer(serializer, preference_key, preference_value)
|
||||
@@ -162,7 +161,7 @@ def update_user_preferences(requesting_user, update, user=None):
|
||||
for preference_key in update.keys():
|
||||
preference_value = update[preference_key]
|
||||
if preference_value is not None:
|
||||
preference_value = six.text_type(preference_value)
|
||||
preference_value = str(preference_value)
|
||||
try:
|
||||
serializer = serializers[preference_key]
|
||||
|
||||
@@ -201,7 +200,7 @@ def set_user_preference(requesting_user, preference_key, preference_value, usern
|
||||
"""
|
||||
existing_user = _get_authorized_user(requesting_user, username)
|
||||
if preference_value is not None:
|
||||
preference_value = six.text_type(preference_value)
|
||||
preference_value = str(preference_value)
|
||||
serializer = create_user_preference_serializer(existing_user, preference_key, preference_value)
|
||||
validate_user_preference_serializer(serializer, preference_key, preference_value)
|
||||
|
||||
@@ -248,10 +247,10 @@ def delete_user_preference(requesting_user, preference_key, username=None):
|
||||
user_preference.delete()
|
||||
except Exception as error:
|
||||
raise PreferenceUpdateError( # lint-amnesty, pylint: disable=raise-missing-from
|
||||
developer_message=u"Delete failed for user preference '{preference_key}': {error}".format(
|
||||
developer_message="Delete failed for user preference '{preference_key}': {error}".format(
|
||||
preference_key=preference_key, error=error
|
||||
),
|
||||
user_message=_(u"Delete failed for user preference '{preference_key}'.").format(
|
||||
user_message=_("Delete failed for user preference '{preference_key}'.").format(
|
||||
preference_key=preference_key
|
||||
),
|
||||
)
|
||||
@@ -300,7 +299,7 @@ def update_email_opt_in(user, org, opt_in):
|
||||
_track_update_email_opt_in(user.id, org, opt_in)
|
||||
except IntegrityError as err:
|
||||
log.warning(
|
||||
u"Could not update organization wide preference due to IntegrityError: {}".format(six.text_type(err))
|
||||
"Could not update organization wide preference due to IntegrityError: {}".format(str(err))
|
||||
)
|
||||
|
||||
|
||||
@@ -399,8 +398,8 @@ def validate_user_preference_serializer(serializer, preference_key, preference_v
|
||||
Raises:
|
||||
PreferenceValidationError: the supplied key and/or value for a user preference are invalid.
|
||||
"""
|
||||
if preference_value is None or six.text_type(preference_value).strip() == '':
|
||||
format_string = ugettext_noop(u"Preference '{preference_key}' cannot be set to an empty value.")
|
||||
if preference_value is None or str(preference_value).strip() == '':
|
||||
format_string = ugettext_noop("Preference '{preference_key}' cannot be set to an empty value.")
|
||||
raise PreferenceValidationError({
|
||||
preference_key: {
|
||||
"developer_message": format_string.format(preference_key=preference_key),
|
||||
@@ -412,16 +411,16 @@ def validate_user_preference_serializer(serializer, preference_key, preference_v
|
||||
# DRF error messages are of type ErrorDetail and serialize out as such. We want to coerce those
|
||||
# messages into the strings only.
|
||||
for key in errors:
|
||||
errors[key] = [six.text_type(el) for el in errors[key]]
|
||||
developer_message = u"Value '{preference_value}' not valid for preference '{preference_key}': {error}".format(
|
||||
errors[key] = [str(el) for el in errors[key]]
|
||||
developer_message = "Value '{preference_value}' not valid for preference '{preference_key}': {error}".format(
|
||||
preference_key=preference_key, preference_value=preference_value, error=errors
|
||||
)
|
||||
if "key" in serializer.errors:
|
||||
user_message = _(u"Invalid user preference key '{preference_key}'.").format(
|
||||
user_message = _("Invalid user preference key '{preference_key}'.").format(
|
||||
preference_key=preference_key
|
||||
)
|
||||
else:
|
||||
user_message = _(u"Value '{preference_value}' is not valid for user preference '{preference_key}'.").format(
|
||||
user_message = _("Value '{preference_value}' is not valid for user preference '{preference_key}'.").format(
|
||||
preference_key=preference_key, preference_value=preference_value
|
||||
)
|
||||
raise PreferenceValidationError({
|
||||
@@ -431,8 +430,8 @@ def validate_user_preference_serializer(serializer, preference_key, preference_v
|
||||
}
|
||||
})
|
||||
if preference_key == "time_zone" and preference_value not in common_timezones_set:
|
||||
developer_message = ugettext_noop(u"Value '{preference_value}' not valid for preference '{preference_key}': Not in timezone set.") # pylint: disable=line-too-long
|
||||
user_message = ugettext_noop(u"Value '{preference_value}' is not a valid time zone selection.")
|
||||
developer_message = ugettext_noop("Value '{preference_value}' not valid for preference '{preference_key}': Not in timezone set.") # pylint: disable=line-too-long
|
||||
user_message = ugettext_noop("Value '{preference_value}' is not a valid time zone selection.")
|
||||
raise PreferenceValidationError({
|
||||
preference_key: {
|
||||
"developer_message": developer_message.format(
|
||||
@@ -446,10 +445,10 @@ def validate_user_preference_serializer(serializer, preference_key, preference_v
|
||||
def _create_preference_update_error(preference_key, preference_value, error):
|
||||
""" Creates a PreferenceUpdateError with developer_message and user_message. """
|
||||
return PreferenceUpdateError(
|
||||
developer_message=u"Save failed for user preference '{key}' with value '{value}': {error}".format(
|
||||
developer_message="Save failed for user preference '{key}' with value '{value}': {error}".format(
|
||||
key=preference_key, value=preference_value, error=error
|
||||
),
|
||||
user_message=_(u"Save failed for user preference '{key}' with value '{value}'.").format(
|
||||
user_message=_("Save failed for user preference '{key}' with value '{value}'.").format(
|
||||
key=preference_key, value=preference_value
|
||||
),
|
||||
)
|
||||
|
||||
@@ -34,7 +34,7 @@ class UserSerializer(serializers.HyperlinkedModelSerializer):
|
||||
"""
|
||||
return UserPreference.get_all_preferences(user)
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = User
|
||||
# This list is the minimal set required by the notification service
|
||||
fields = ("id", "url", "email", "name", "username", "preferences")
|
||||
@@ -49,7 +49,7 @@ class UserPreferenceSerializer(serializers.HyperlinkedModelSerializer):
|
||||
"""
|
||||
user = UserSerializer()
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = UserPreference
|
||||
depth = 1
|
||||
fields = ('user', 'key', 'value', 'url')
|
||||
@@ -61,13 +61,13 @@ class RawUserPreferenceSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
user = serializers.PrimaryKeyRelatedField(queryset=User.objects.all())
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = UserPreference
|
||||
depth = 1
|
||||
fields = ('user', 'key', 'value', 'url')
|
||||
|
||||
|
||||
class ReadOnlyFieldsSerializerMixin(object):
|
||||
class ReadOnlyFieldsSerializerMixin:
|
||||
"""
|
||||
Mixin for use with Serializers that provides a method
|
||||
`get_read_only_fields`, which returns a tuple of all read-only
|
||||
|
||||
@@ -13,7 +13,7 @@ from ..models import UserCourseTag, UserOrgTag, UserPreference
|
||||
# Factories are self documenting
|
||||
# pylint: disable=missing-docstring
|
||||
class UserPreferenceFactory(DjangoModelFactory):
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = UserPreference
|
||||
|
||||
user = None
|
||||
@@ -22,7 +22,7 @@ class UserPreferenceFactory(DjangoModelFactory):
|
||||
|
||||
|
||||
class UserCourseTagFactory(DjangoModelFactory):
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = UserCourseTag
|
||||
|
||||
user = SubFactory(UserFactory)
|
||||
@@ -33,7 +33,7 @@ class UserCourseTagFactory(DjangoModelFactory):
|
||||
|
||||
class UserOrgTagFactory(DjangoModelFactory):
|
||||
""" Simple factory class for generating UserOrgTags """
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = UserOrgTag
|
||||
|
||||
user = SubFactory(UserFactory)
|
||||
|
||||
@@ -1,254 +1,253 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Constants used in the test suite. """
|
||||
SORTED_COUNTRIES = [
|
||||
(u"AF", u"Afghanistan"),
|
||||
(u"AX", u"\xc5land Islands"),
|
||||
(u"AL", u"Albania"),
|
||||
(u"DZ", u"Algeria"),
|
||||
(u"AS", u"American Samoa"),
|
||||
(u"AD", u"Andorra"),
|
||||
(u"AO", u"Angola"),
|
||||
(u"AI", u"Anguilla"),
|
||||
(u"AQ", u"Antarctica"),
|
||||
(u"AG", u"Antigua and Barbuda"),
|
||||
(u"AR", u"Argentina"),
|
||||
(u"AM", u"Armenia"),
|
||||
(u"AW", u"Aruba"),
|
||||
(u"AU", u"Australia"),
|
||||
(u"AT", u"Austria"),
|
||||
(u"AZ", u"Azerbaijan"),
|
||||
(u"BS", u"Bahamas"),
|
||||
(u"BH", u"Bahrain"),
|
||||
(u"BD", u"Bangladesh"),
|
||||
(u"BB", u"Barbados"),
|
||||
(u"BY", u"Belarus"),
|
||||
(u"BE", u"Belgium"),
|
||||
(u"BZ", u"Belize"),
|
||||
(u"BJ", u"Benin"),
|
||||
(u"BM", u"Bermuda"),
|
||||
(u"BT", u"Bhutan"),
|
||||
(u"BO", u"Bolivia"),
|
||||
(u"BQ", u"Bonaire, Sint Eustatius and Saba"),
|
||||
(u"BA", u"Bosnia and Herzegovina"),
|
||||
(u"BW", u"Botswana"),
|
||||
(u"BV", u"Bouvet Island"),
|
||||
(u"BR", u"Brazil"),
|
||||
(u"IO", u"British Indian Ocean Territory"),
|
||||
(u"BN", u"Brunei"),
|
||||
(u"BG", u"Bulgaria"),
|
||||
(u"BF", u"Burkina Faso"),
|
||||
(u"BI", u"Burundi"),
|
||||
(u"CV", u"Cabo Verde"),
|
||||
(u"KH", u"Cambodia"),
|
||||
(u"CM", u"Cameroon"),
|
||||
(u"CA", u"Canada"),
|
||||
(u"KY", u"Cayman Islands"),
|
||||
(u"CF", u"Central African Republic"),
|
||||
(u"TD", u"Chad"),
|
||||
(u"CL", u"Chile"),
|
||||
(u"CN", u"China"),
|
||||
(u"CX", u"Christmas Island"),
|
||||
(u"CC", u"Cocos (Keeling) Islands"),
|
||||
(u"CO", u"Colombia"),
|
||||
(u"KM", u"Comoros"),
|
||||
(u"CG", u"Congo"),
|
||||
(u"CD", u"Congo (the Democratic Republic of the)"),
|
||||
(u"CK", u"Cook Islands"),
|
||||
(u"CR", u"Costa Rica"),
|
||||
(u"CI", u"C\xf4te d'Ivoire"),
|
||||
(u"HR", u"Croatia"),
|
||||
(u"CU", u"Cuba"),
|
||||
(u"CW", u"Cura\xe7ao"),
|
||||
(u"CY", u"Cyprus"),
|
||||
(u"CZ", u"Czechia"),
|
||||
(u"DK", u"Denmark"),
|
||||
(u"DJ", u"Djibouti"),
|
||||
(u"DM", u"Dominica"),
|
||||
(u"DO", u"Dominican Republic"),
|
||||
(u"EC", u"Ecuador"),
|
||||
(u"EG", u"Egypt"),
|
||||
(u"SV", u"El Salvador"),
|
||||
(u"GQ", u"Equatorial Guinea"),
|
||||
(u"ER", u"Eritrea"),
|
||||
(u"EE", u"Estonia"),
|
||||
(u"SZ", u"Eswatini"),
|
||||
(u"ET", u"Ethiopia"),
|
||||
(u"FK", u"Falkland Islands [Malvinas]"),
|
||||
(u"FO", u"Faroe Islands"),
|
||||
(u"FJ", u"Fiji"),
|
||||
(u"FI", u"Finland"),
|
||||
(u"FR", u"France"),
|
||||
(u"GF", u"French Guiana"),
|
||||
(u"PF", u"French Polynesia"),
|
||||
(u"TF", u"French Southern Territories"),
|
||||
(u"GA", u"Gabon"),
|
||||
(u"GM", u"Gambia"),
|
||||
(u"GE", u"Georgia"),
|
||||
(u"DE", u"Germany"),
|
||||
(u"GH", u"Ghana"),
|
||||
(u"GI", u"Gibraltar"),
|
||||
(u"GR", u"Greece"),
|
||||
(u"GL", u"Greenland"),
|
||||
(u"GD", u"Grenada"),
|
||||
(u"GP", u"Guadeloupe"),
|
||||
(u"GU", u"Guam"),
|
||||
(u"GT", u"Guatemala"),
|
||||
(u"GG", u"Guernsey"),
|
||||
(u"GN", u"Guinea"),
|
||||
(u"GW", u"Guinea-Bissau"),
|
||||
(u"GY", u"Guyana"),
|
||||
(u"HT", u"Haiti"),
|
||||
(u"HM", u"Heard Island and McDonald Islands"),
|
||||
(u"VA", u"Holy See"),
|
||||
(u"HN", u"Honduras"),
|
||||
(u"HK", u"Hong Kong"),
|
||||
(u"HU", u"Hungary"),
|
||||
(u"IS", u"Iceland"),
|
||||
(u"IN", u"India"),
|
||||
(u"ID", u"Indonesia"),
|
||||
(u"IR", u"Iran"),
|
||||
(u"IQ", u"Iraq"),
|
||||
(u"IE", u"Ireland"),
|
||||
(u"IM", u"Isle of Man"),
|
||||
(u"IL", u"Israel"),
|
||||
(u"IT", u"Italy"),
|
||||
(u"JM", u"Jamaica"),
|
||||
(u"JP", u"Japan"),
|
||||
(u"JE", u"Jersey"),
|
||||
(u"JO", u"Jordan"),
|
||||
(u"KZ", u"Kazakhstan"),
|
||||
(u"KE", u"Kenya"),
|
||||
(u"KI", u"Kiribati"),
|
||||
(u"XK", u"Kosovo"),
|
||||
(u"KW", u"Kuwait"),
|
||||
(u"KG", u"Kyrgyzstan"),
|
||||
(u"LA", u"Laos"),
|
||||
(u"LV", u"Latvia"),
|
||||
(u"LB", u"Lebanon"),
|
||||
(u"LS", u"Lesotho"),
|
||||
(u"LR", u"Liberia"),
|
||||
(u"LY", u"Libya"),
|
||||
(u"LI", u"Liechtenstein"),
|
||||
(u"LT", u"Lithuania"),
|
||||
(u"LU", u"Luxembourg"),
|
||||
(u"MO", u"Macao"),
|
||||
(u"MG", u"Madagascar"),
|
||||
(u"MW", u"Malawi"),
|
||||
(u"MY", u"Malaysia"),
|
||||
(u"MV", u"Maldives"),
|
||||
(u"ML", u"Mali"),
|
||||
(u"MT", u"Malta"),
|
||||
(u"MH", u"Marshall Islands"),
|
||||
(u"MQ", u"Martinique"),
|
||||
(u"MR", u"Mauritania"),
|
||||
(u"MU", u"Mauritius"),
|
||||
(u"YT", u"Mayotte"),
|
||||
(u"MX", u"Mexico"),
|
||||
(u"FM", u"Micronesia (Federated States of)"),
|
||||
(u"MD", u"Moldova"),
|
||||
(u"MC", u"Monaco"),
|
||||
(u"MN", u"Mongolia"),
|
||||
(u"ME", u"Montenegro"),
|
||||
(u"MS", u"Montserrat"),
|
||||
(u"MA", u"Morocco"),
|
||||
(u"MZ", u"Mozambique"),
|
||||
(u"MM", u"Myanmar"),
|
||||
(u"NA", u"Namibia"),
|
||||
(u"NR", u"Nauru"),
|
||||
(u"NP", u"Nepal"),
|
||||
(u"NL", u"Netherlands"),
|
||||
(u"NC", u"New Caledonia"),
|
||||
(u"NZ", u"New Zealand"),
|
||||
(u"NI", u"Nicaragua"),
|
||||
(u"NE", u"Niger"),
|
||||
(u"NG", u"Nigeria"),
|
||||
(u"NU", u"Niue"),
|
||||
(u"NF", u"Norfolk Island"),
|
||||
(u"KP", u"North Korea"),
|
||||
(u"MK", u"North Macedonia"),
|
||||
(u"MP", u"Northern Mariana Islands"),
|
||||
(u"NO", u"Norway"),
|
||||
(u"OM", u"Oman"),
|
||||
(u"PK", u"Pakistan"),
|
||||
(u"PW", u"Palau"),
|
||||
(u"PS", u"Palestine, State of"),
|
||||
(u"PA", u"Panama"),
|
||||
(u"PG", u"Papua New Guinea"),
|
||||
(u"PY", u"Paraguay"),
|
||||
(u"PE", u"Peru"),
|
||||
(u"PH", u"Philippines"),
|
||||
(u"PN", u"Pitcairn"),
|
||||
(u"PL", u"Poland"),
|
||||
(u"PT", u"Portugal"),
|
||||
(u"PR", u"Puerto Rico"),
|
||||
(u"QA", u"Qatar"),
|
||||
(u"RE", u"R\xe9union"),
|
||||
(u"RO", u"Romania"),
|
||||
(u"RU", u"Russia"),
|
||||
(u"RW", u"Rwanda"),
|
||||
(u"BL", u"Saint Barth\xe9lemy"),
|
||||
(u"SH", u"Saint Helena, Ascension and Tristan da Cunha"),
|
||||
(u"KN", u"Saint Kitts and Nevis"),
|
||||
(u"LC", u"Saint Lucia"),
|
||||
(u"MF", u"Saint Martin (French part)"),
|
||||
(u"PM", u"Saint Pierre and Miquelon"),
|
||||
(u"VC", u"Saint Vincent and the Grenadines"),
|
||||
(u"WS", u"Samoa"),
|
||||
(u"SM", u"San Marino"),
|
||||
(u"ST", u"Sao Tome and Principe"),
|
||||
(u"SA", u"Saudi Arabia"),
|
||||
(u"SN", u"Senegal"),
|
||||
(u"RS", u"Serbia"),
|
||||
(u"SC", u"Seychelles"),
|
||||
(u"SL", u"Sierra Leone"),
|
||||
(u"SG", u"Singapore"),
|
||||
(u"SX", u"Sint Maarten (Dutch part)"),
|
||||
(u"SK", u"Slovakia"),
|
||||
(u"SI", u"Slovenia"),
|
||||
(u"SB", u"Solomon Islands"),
|
||||
(u"SO", u"Somalia"),
|
||||
(u"ZA", u"South Africa"),
|
||||
(u"GS", u"South Georgia and the South Sandwich Islands"),
|
||||
(u"KR", u"South Korea"),
|
||||
(u"SS", u"South Sudan"),
|
||||
(u"ES", u"Spain"),
|
||||
(u"LK", u"Sri Lanka"),
|
||||
(u"SD", u"Sudan"),
|
||||
(u"SR", u"Suriname"),
|
||||
(u"SJ", u"Svalbard and Jan Mayen"),
|
||||
(u"SE", u"Sweden"),
|
||||
(u"CH", u"Switzerland"),
|
||||
(u"SY", u"Syria"),
|
||||
(u"TW", u"Taiwan"),
|
||||
(u"TJ", u"Tajikistan"),
|
||||
(u"TZ", u"Tanzania"),
|
||||
(u"TH", u"Thailand"),
|
||||
(u"TL", u"Timor-Leste"),
|
||||
(u"TG", u"Togo"),
|
||||
(u"TK", u"Tokelau"),
|
||||
(u"TO", u"Tonga"),
|
||||
(u"TT", u"Trinidad and Tobago"),
|
||||
(u"TN", u"Tunisia"),
|
||||
(u"TR", u"Turkey"),
|
||||
(u"TM", u"Turkmenistan"),
|
||||
(u"TC", u"Turks and Caicos Islands"),
|
||||
(u"TV", u"Tuvalu"),
|
||||
(u"UG", u"Uganda"),
|
||||
(u"UA", u"Ukraine"),
|
||||
(u"AE", u"United Arab Emirates"),
|
||||
(u"GB", u"United Kingdom"),
|
||||
(u"UM", u"United States Minor Outlying Islands"),
|
||||
(u"US", u"United States of America"),
|
||||
(u"UY", u"Uruguay"),
|
||||
(u"UZ", u"Uzbekistan"),
|
||||
(u"VU", u"Vanuatu"),
|
||||
(u"VE", u"Venezuela"),
|
||||
(u"VN", u"Vietnam"),
|
||||
(u"VG", u"Virgin Islands (British)"),
|
||||
(u"VI", u"Virgin Islands (U.S.)"),
|
||||
(u"WF", u"Wallis and Futuna"),
|
||||
(u"EH", u"Western Sahara"),
|
||||
(u"YE", u"Yemen"),
|
||||
(u"ZM", u"Zambia"),
|
||||
(u"ZW", u"Zimbabwe")
|
||||
("AF", "Afghanistan"),
|
||||
("AX", "\xc5land Islands"),
|
||||
("AL", "Albania"),
|
||||
("DZ", "Algeria"),
|
||||
("AS", "American Samoa"),
|
||||
("AD", "Andorra"),
|
||||
("AO", "Angola"),
|
||||
("AI", "Anguilla"),
|
||||
("AQ", "Antarctica"),
|
||||
("AG", "Antigua and Barbuda"),
|
||||
("AR", "Argentina"),
|
||||
("AM", "Armenia"),
|
||||
("AW", "Aruba"),
|
||||
("AU", "Australia"),
|
||||
("AT", "Austria"),
|
||||
("AZ", "Azerbaijan"),
|
||||
("BS", "Bahamas"),
|
||||
("BH", "Bahrain"),
|
||||
("BD", "Bangladesh"),
|
||||
("BB", "Barbados"),
|
||||
("BY", "Belarus"),
|
||||
("BE", "Belgium"),
|
||||
("BZ", "Belize"),
|
||||
("BJ", "Benin"),
|
||||
("BM", "Bermuda"),
|
||||
("BT", "Bhutan"),
|
||||
("BO", "Bolivia"),
|
||||
("BQ", "Bonaire, Sint Eustatius and Saba"),
|
||||
("BA", "Bosnia and Herzegovina"),
|
||||
("BW", "Botswana"),
|
||||
("BV", "Bouvet Island"),
|
||||
("BR", "Brazil"),
|
||||
("IO", "British Indian Ocean Territory"),
|
||||
("BN", "Brunei"),
|
||||
("BG", "Bulgaria"),
|
||||
("BF", "Burkina Faso"),
|
||||
("BI", "Burundi"),
|
||||
("CV", "Cabo Verde"),
|
||||
("KH", "Cambodia"),
|
||||
("CM", "Cameroon"),
|
||||
("CA", "Canada"),
|
||||
("KY", "Cayman Islands"),
|
||||
("CF", "Central African Republic"),
|
||||
("TD", "Chad"),
|
||||
("CL", "Chile"),
|
||||
("CN", "China"),
|
||||
("CX", "Christmas Island"),
|
||||
("CC", "Cocos (Keeling) Islands"),
|
||||
("CO", "Colombia"),
|
||||
("KM", "Comoros"),
|
||||
("CG", "Congo"),
|
||||
("CD", "Congo (the Democratic Republic of the)"),
|
||||
("CK", "Cook Islands"),
|
||||
("CR", "Costa Rica"),
|
||||
("CI", "C\xf4te d'Ivoire"),
|
||||
("HR", "Croatia"),
|
||||
("CU", "Cuba"),
|
||||
("CW", "Cura\xe7ao"),
|
||||
("CY", "Cyprus"),
|
||||
("CZ", "Czechia"),
|
||||
("DK", "Denmark"),
|
||||
("DJ", "Djibouti"),
|
||||
("DM", "Dominica"),
|
||||
("DO", "Dominican Republic"),
|
||||
("EC", "Ecuador"),
|
||||
("EG", "Egypt"),
|
||||
("SV", "El Salvador"),
|
||||
("GQ", "Equatorial Guinea"),
|
||||
("ER", "Eritrea"),
|
||||
("EE", "Estonia"),
|
||||
("SZ", "Eswatini"),
|
||||
("ET", "Ethiopia"),
|
||||
("FK", "Falkland Islands [Malvinas]"),
|
||||
("FO", "Faroe Islands"),
|
||||
("FJ", "Fiji"),
|
||||
("FI", "Finland"),
|
||||
("FR", "France"),
|
||||
("GF", "French Guiana"),
|
||||
("PF", "French Polynesia"),
|
||||
("TF", "French Southern Territories"),
|
||||
("GA", "Gabon"),
|
||||
("GM", "Gambia"),
|
||||
("GE", "Georgia"),
|
||||
("DE", "Germany"),
|
||||
("GH", "Ghana"),
|
||||
("GI", "Gibraltar"),
|
||||
("GR", "Greece"),
|
||||
("GL", "Greenland"),
|
||||
("GD", "Grenada"),
|
||||
("GP", "Guadeloupe"),
|
||||
("GU", "Guam"),
|
||||
("GT", "Guatemala"),
|
||||
("GG", "Guernsey"),
|
||||
("GN", "Guinea"),
|
||||
("GW", "Guinea-Bissau"),
|
||||
("GY", "Guyana"),
|
||||
("HT", "Haiti"),
|
||||
("HM", "Heard Island and McDonald Islands"),
|
||||
("VA", "Holy See"),
|
||||
("HN", "Honduras"),
|
||||
("HK", "Hong Kong"),
|
||||
("HU", "Hungary"),
|
||||
("IS", "Iceland"),
|
||||
("IN", "India"),
|
||||
("ID", "Indonesia"),
|
||||
("IR", "Iran"),
|
||||
("IQ", "Iraq"),
|
||||
("IE", "Ireland"),
|
||||
("IM", "Isle of Man"),
|
||||
("IL", "Israel"),
|
||||
("IT", "Italy"),
|
||||
("JM", "Jamaica"),
|
||||
("JP", "Japan"),
|
||||
("JE", "Jersey"),
|
||||
("JO", "Jordan"),
|
||||
("KZ", "Kazakhstan"),
|
||||
("KE", "Kenya"),
|
||||
("KI", "Kiribati"),
|
||||
("XK", "Kosovo"),
|
||||
("KW", "Kuwait"),
|
||||
("KG", "Kyrgyzstan"),
|
||||
("LA", "Laos"),
|
||||
("LV", "Latvia"),
|
||||
("LB", "Lebanon"),
|
||||
("LS", "Lesotho"),
|
||||
("LR", "Liberia"),
|
||||
("LY", "Libya"),
|
||||
("LI", "Liechtenstein"),
|
||||
("LT", "Lithuania"),
|
||||
("LU", "Luxembourg"),
|
||||
("MO", "Macao"),
|
||||
("MG", "Madagascar"),
|
||||
("MW", "Malawi"),
|
||||
("MY", "Malaysia"),
|
||||
("MV", "Maldives"),
|
||||
("ML", "Mali"),
|
||||
("MT", "Malta"),
|
||||
("MH", "Marshall Islands"),
|
||||
("MQ", "Martinique"),
|
||||
("MR", "Mauritania"),
|
||||
("MU", "Mauritius"),
|
||||
("YT", "Mayotte"),
|
||||
("MX", "Mexico"),
|
||||
("FM", "Micronesia (Federated States of)"),
|
||||
("MD", "Moldova"),
|
||||
("MC", "Monaco"),
|
||||
("MN", "Mongolia"),
|
||||
("ME", "Montenegro"),
|
||||
("MS", "Montserrat"),
|
||||
("MA", "Morocco"),
|
||||
("MZ", "Mozambique"),
|
||||
("MM", "Myanmar"),
|
||||
("NA", "Namibia"),
|
||||
("NR", "Nauru"),
|
||||
("NP", "Nepal"),
|
||||
("NL", "Netherlands"),
|
||||
("NC", "New Caledonia"),
|
||||
("NZ", "New Zealand"),
|
||||
("NI", "Nicaragua"),
|
||||
("NE", "Niger"),
|
||||
("NG", "Nigeria"),
|
||||
("NU", "Niue"),
|
||||
("NF", "Norfolk Island"),
|
||||
("KP", "North Korea"),
|
||||
("MK", "North Macedonia"),
|
||||
("MP", "Northern Mariana Islands"),
|
||||
("NO", "Norway"),
|
||||
("OM", "Oman"),
|
||||
("PK", "Pakistan"),
|
||||
("PW", "Palau"),
|
||||
("PS", "Palestine, State of"),
|
||||
("PA", "Panama"),
|
||||
("PG", "Papua New Guinea"),
|
||||
("PY", "Paraguay"),
|
||||
("PE", "Peru"),
|
||||
("PH", "Philippines"),
|
||||
("PN", "Pitcairn"),
|
||||
("PL", "Poland"),
|
||||
("PT", "Portugal"),
|
||||
("PR", "Puerto Rico"),
|
||||
("QA", "Qatar"),
|
||||
("RE", "R\xe9union"),
|
||||
("RO", "Romania"),
|
||||
("RU", "Russia"),
|
||||
("RW", "Rwanda"),
|
||||
("BL", "Saint Barth\xe9lemy"),
|
||||
("SH", "Saint Helena, Ascension and Tristan da Cunha"),
|
||||
("KN", "Saint Kitts and Nevis"),
|
||||
("LC", "Saint Lucia"),
|
||||
("MF", "Saint Martin (French part)"),
|
||||
("PM", "Saint Pierre and Miquelon"),
|
||||
("VC", "Saint Vincent and the Grenadines"),
|
||||
("WS", "Samoa"),
|
||||
("SM", "San Marino"),
|
||||
("ST", "Sao Tome and Principe"),
|
||||
("SA", "Saudi Arabia"),
|
||||
("SN", "Senegal"),
|
||||
("RS", "Serbia"),
|
||||
("SC", "Seychelles"),
|
||||
("SL", "Sierra Leone"),
|
||||
("SG", "Singapore"),
|
||||
("SX", "Sint Maarten (Dutch part)"),
|
||||
("SK", "Slovakia"),
|
||||
("SI", "Slovenia"),
|
||||
("SB", "Solomon Islands"),
|
||||
("SO", "Somalia"),
|
||||
("ZA", "South Africa"),
|
||||
("GS", "South Georgia and the South Sandwich Islands"),
|
||||
("KR", "South Korea"),
|
||||
("SS", "South Sudan"),
|
||||
("ES", "Spain"),
|
||||
("LK", "Sri Lanka"),
|
||||
("SD", "Sudan"),
|
||||
("SR", "Suriname"),
|
||||
("SJ", "Svalbard and Jan Mayen"),
|
||||
("SE", "Sweden"),
|
||||
("CH", "Switzerland"),
|
||||
("SY", "Syria"),
|
||||
("TW", "Taiwan"),
|
||||
("TJ", "Tajikistan"),
|
||||
("TZ", "Tanzania"),
|
||||
("TH", "Thailand"),
|
||||
("TL", "Timor-Leste"),
|
||||
("TG", "Togo"),
|
||||
("TK", "Tokelau"),
|
||||
("TO", "Tonga"),
|
||||
("TT", "Trinidad and Tobago"),
|
||||
("TN", "Tunisia"),
|
||||
("TR", "Turkey"),
|
||||
("TM", "Turkmenistan"),
|
||||
("TC", "Turks and Caicos Islands"),
|
||||
("TV", "Tuvalu"),
|
||||
("UG", "Uganda"),
|
||||
("UA", "Ukraine"),
|
||||
("AE", "United Arab Emirates"),
|
||||
("GB", "United Kingdom"),
|
||||
("UM", "United States Minor Outlying Islands"),
|
||||
("US", "United States of America"),
|
||||
("UY", "Uruguay"),
|
||||
("UZ", "Uzbekistan"),
|
||||
("VU", "Vanuatu"),
|
||||
("VE", "Venezuela"),
|
||||
("VN", "Vietnam"),
|
||||
("VG", "Virgin Islands (British)"),
|
||||
("VI", "Virgin Islands (U.S.)"),
|
||||
("WF", "Wallis and Futuna"),
|
||||
("EH", "Western Sahara"),
|
||||
("YE", "Yemen"),
|
||||
("ZM", "Zambia"),
|
||||
("ZW", "Zimbabwe")
|
||||
]
|
||||
|
||||
@@ -5,13 +5,12 @@ Tests for helper functions.
|
||||
|
||||
import json
|
||||
import re
|
||||
from unittest import mock
|
||||
|
||||
import ddt # lint-amnesty, pylint: disable=unused-import
|
||||
import mock
|
||||
import pytest
|
||||
from django import forms
|
||||
from django.test import TestCase
|
||||
from six import text_type
|
||||
|
||||
from ..helpers import FormDescription, InvalidFieldError, intercept_errors
|
||||
|
||||
@@ -57,17 +56,17 @@ class InterceptErrorsTest(TestCase):
|
||||
self.maxDiff = None
|
||||
exception = 'openedx.core.djangoapps.user_api.tests.test_helpers.FakeInputException'
|
||||
expected_log_msg = (
|
||||
u"An unexpected error occurred when calling 'intercepted_function' with arguments '()' and "
|
||||
u"keyword arguments '{{'raise_error': <class '{}'>}}' "
|
||||
u"from File \"{}\", line XXX, in test_logs_errors\n"
|
||||
u" intercepted_function(raise_error=FakeInputException): FakeInputException()"
|
||||
"An unexpected error occurred when calling 'intercepted_function' with arguments '()' and "
|
||||
"keyword arguments '{{'raise_error': <class '{}'>}}' "
|
||||
"from File \"{}\", line XXX, in test_logs_errors\n"
|
||||
" intercepted_function(raise_error=FakeInputException): FakeInputException()"
|
||||
).format(exception, __file__.rstrip('c'))
|
||||
|
||||
# Verify that the raised exception has the error message
|
||||
try:
|
||||
intercepted_function(raise_error=FakeInputException)
|
||||
except FakeOutputException as ex:
|
||||
actual_message = re.sub(r'line \d+', 'line XXX', text_type(ex), flags=re.MULTILINE)
|
||||
actual_message = re.sub(r'line \d+', 'line XXX', str(ex), flags=re.MULTILINE)
|
||||
assert actual_message == expected_log_msg
|
||||
|
||||
# Verify that the error logger is called
|
||||
@@ -159,7 +158,7 @@ class FormDescriptionTest(TestCase):
|
||||
{'default': True, 'name': 'Pakistan', 'value': 'PK'}]
|
||||
|
||||
|
||||
class DummyRegistrationExtensionModel(object):
|
||||
class DummyRegistrationExtensionModel:
|
||||
"""
|
||||
Dummy registration object
|
||||
"""
|
||||
@@ -190,8 +189,8 @@ class TestCaseForm(forms.Form):
|
||||
|
||||
favorite_movie = forms.CharField(
|
||||
label="Fav Flick", min_length=MOVIE_MIN_LEN, max_length=MOVIE_MAX_LEN, error_messages={
|
||||
"required": u"Please tell us your favorite movie.",
|
||||
"invalid": u"We're pretty sure you made that movie up."
|
||||
"required": "Please tell us your favorite movie.",
|
||||
"invalid": "We're pretty sure you made that movie up."
|
||||
}
|
||||
)
|
||||
favorite_editor = forms.ChoiceField(label="Favorite Editor", choices=FAVORITE_EDITOR, required=False, initial='cat')
|
||||
@@ -207,7 +206,7 @@ class TestCaseForm(forms.Form):
|
||||
dummy_model = DummyRegistrationExtensionModel()
|
||||
return dummy_model
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
"""
|
||||
Set options for fields which can't be conveyed in their definition.
|
||||
"""
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"""Tests for user API middleware"""
|
||||
|
||||
|
||||
from unittest.mock import Mock, patch
|
||||
from django.http import HttpResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from mock import Mock, patch
|
||||
|
||||
from common.djangoapps.student.tests.factories import AnonymousUserFactory, UserFactory
|
||||
|
||||
@@ -17,7 +17,7 @@ class TagsMiddlewareTest(TestCase):
|
||||
Test the UserTagsEventContextMiddleware
|
||||
"""
|
||||
def setUp(self):
|
||||
super(TagsMiddlewareTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.middleware = UserTagsEventContextMiddleware()
|
||||
self.user = UserFactory.create()
|
||||
self.other_user = UserFactory.create()
|
||||
@@ -27,7 +27,7 @@ class TagsMiddlewareTest(TestCase):
|
||||
|
||||
# TODO: Make it so we can use reverse. Appears to fail depending on the order in which tests are run
|
||||
#self.request = RequestFactory().get(reverse('courseware', kwargs={'course_id': self.course_id}))
|
||||
self.request = RequestFactory().get('/courses/{}/courseware'.format(self.course_id))
|
||||
self.request = RequestFactory().get(f'/courses/{self.course_id}/courseware')
|
||||
self.request.user = self.user
|
||||
|
||||
self.response = Mock(spec=HttpResponse)
|
||||
|
||||
@@ -123,7 +123,7 @@ class TestUserPreferenceEvents(UserSettingsEventTestMixin, TestCase):
|
||||
Mixin for verifying that user preference events are fired correctly.
|
||||
"""
|
||||
def setUp(self):
|
||||
super(TestUserPreferenceEvents, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.table = "user_api_userpreference"
|
||||
self.user = UserFactory.create()
|
||||
self.TEST_KEY = "test key"
|
||||
|
||||
@@ -4,11 +4,10 @@ Test the user api's partition extensions.
|
||||
|
||||
|
||||
from collections import defaultdict
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from django.test import TestCase
|
||||
from mock import patch
|
||||
from six.moves import range
|
||||
|
||||
from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme, UserPartitionError
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
@@ -16,7 +15,7 @@ from xmodule.partitions.partitions import Group, UserPartition
|
||||
from xmodule.partitions.tests.test_partitions import PartitionTestCase
|
||||
|
||||
|
||||
class MemoryCourseTagAPI(object):
|
||||
class MemoryCourseTagAPI:
|
||||
"""
|
||||
An implementation of a user service that uses an in-memory dictionary for storage
|
||||
"""
|
||||
@@ -31,7 +30,7 @@ class MemoryCourseTagAPI(object):
|
||||
"""Gets the value of ``key``"""
|
||||
self._tags[course_id][key] = value
|
||||
|
||||
class BulkCourseTags(object):
|
||||
class BulkCourseTags:
|
||||
@classmethod
|
||||
def is_prefetched(self, course_id): # lint-amnesty, pylint: disable=bad-classmethod-argument, unused-argument
|
||||
return False
|
||||
@@ -46,7 +45,7 @@ class TestRandomUserPartitionScheme(PartitionTestCase):
|
||||
MOCK_COURSE_ID = "mock-course-id"
|
||||
|
||||
def setUp(self):
|
||||
super(TestRandomUserPartitionScheme, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
# Patch in a memory-based user service instead of using the persistent version
|
||||
course_tag_api = MemoryCourseTagAPI()
|
||||
self.user_service_patcher = patch(
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
|
||||
import json # lint-amnesty, pylint: disable=unused-import
|
||||
from unittest import skipUnless # lint-amnesty, pylint: disable=unused-import
|
||||
from unittest import mock # lint-amnesty, pylint: disable=unused-import
|
||||
import pytest
|
||||
import ddt
|
||||
import httpretty # lint-amnesty, pylint: disable=unused-import
|
||||
import mock # lint-amnesty, pylint: disable=unused-import
|
||||
import six
|
||||
from django.conf import settings # lint-amnesty, pylint: disable=unused-import
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user, unused-import
|
||||
from django.core import mail # lint-amnesty, pylint: disable=unused-import
|
||||
@@ -17,8 +16,6 @@ from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from pytz import UTC, common_timezones_set # lint-amnesty, pylint: disable=unused-import
|
||||
from six import text_type
|
||||
from six.moves import range
|
||||
from social_django.models import Partial, UserSocialAuth # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
from openedx.core.djangoapps.django_comment_common import models
|
||||
@@ -90,9 +87,8 @@ class UserAPITestCase(ApiTestCase):
|
||||
|
||||
def assertUserIsValid(self, user):
|
||||
"""Assert that the given user result is valid"""
|
||||
six.assertCountEqual(self, list(user.keys()), ["email", "id", "name", "username", "preferences", "url"])
|
||||
six.assertCountEqual(
|
||||
self,
|
||||
self.assertCountEqual(list(user.keys()), ["email", "id", "name", "username", "preferences", "url"])
|
||||
self.assertCountEqual(
|
||||
list(user["preferences"].items()),
|
||||
[(pref.key, pref.value) for pref in self.prefs if pref.user.id == user["id"]] # lint-amnesty, pylint: disable=no-member
|
||||
)
|
||||
@@ -102,7 +98,7 @@ class UserAPITestCase(ApiTestCase):
|
||||
"""
|
||||
Assert that the given preference is acknowledged by the system
|
||||
"""
|
||||
six.assertCountEqual(self, list(pref.keys()), ["user", "key", "value", "url"])
|
||||
self.assertCountEqual(list(pref.keys()), ["user", "key", "value", "url"])
|
||||
self.assertSelfReferential(pref)
|
||||
self.assertUserIsValid(pref["user"])
|
||||
|
||||
@@ -124,7 +120,7 @@ class EmptyUserTestCase(UserAPITestCase):
|
||||
class EmptyRoleTestCase(UserAPITestCase):
|
||||
"""Test that the endpoint supports empty result sets"""
|
||||
course_id = CourseKey.from_string("org/course/run")
|
||||
LIST_URI = ROLE_LIST_URI + "?course_id=" + six.text_type(course_id)
|
||||
LIST_URI = ROLE_LIST_URI + "?course_id=" + str(course_id)
|
||||
|
||||
def test_get_list_empty(self):
|
||||
"""Test that the endpoint properly returns empty result sets"""
|
||||
@@ -140,11 +136,11 @@ class UserApiTestCase(UserAPITestCase):
|
||||
Generalized test case class for specific implementations below
|
||||
"""
|
||||
def setUp(self):
|
||||
super(UserApiTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.users = [
|
||||
UserFactory.create(
|
||||
email="test{0}@test.org".format(i),
|
||||
profile__name=u"Test {0}".format(i)
|
||||
email=f"test{i}@test.org",
|
||||
profile__name=f"Test {i}"
|
||||
)
|
||||
for i in range(5)
|
||||
]
|
||||
@@ -161,10 +157,10 @@ class RoleTestCase(UserApiTestCase):
|
||||
Test cases covering Role-related views and their behaviors
|
||||
"""
|
||||
course_id = CourseKey.from_string("org/course/run")
|
||||
LIST_URI = ROLE_LIST_URI + "?course_id=" + six.text_type(course_id)
|
||||
LIST_URI = ROLE_LIST_URI + "?course_id=" + str(course_id)
|
||||
|
||||
def setUp(self):
|
||||
super(RoleTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
(role, _) = models.Role.objects.get_or_create(
|
||||
name=models.FORUM_ROLE_MODERATOR,
|
||||
course_id=self.course_id
|
||||
@@ -222,7 +218,7 @@ class RoleTestCase(UserApiTestCase):
|
||||
def test_get_list_pagination(self):
|
||||
first_page = self.get_json(self.LIST_URI, data={
|
||||
"page_size": 3,
|
||||
"course_id": text_type(self.course_id),
|
||||
"course_id": str(self.course_id),
|
||||
})
|
||||
assert first_page['count'] == 5
|
||||
first_page_next_uri = first_page["next"]
|
||||
@@ -253,7 +249,7 @@ class UserViewSetTest(UserApiTestCase):
|
||||
LIST_URI = USER_LIST_URI
|
||||
|
||||
def setUp(self):
|
||||
super(UserViewSetTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.detail_uri = self.get_uri_for_user(self.users[0])
|
||||
|
||||
# List view tests
|
||||
@@ -362,7 +358,7 @@ class UserPreferenceViewSetTest(CacheIsolationTestCase, UserApiTestCase):
|
||||
ENABLED_CACHES = ['default']
|
||||
|
||||
def setUp(self):
|
||||
super(UserPreferenceViewSetTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.detail_uri = self.get_uri_for_pref(self.prefs[0])
|
||||
|
||||
# List view tests
|
||||
@@ -555,30 +551,30 @@ class UpdateEmailOptInTestCase(UserAPITestCase, SharedModuleStoreTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(UpdateEmailOptInTestCase, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create()
|
||||
cls.url = reverse("preferences_email_opt_in")
|
||||
|
||||
def setUp(self):
|
||||
""" Create a course and user, then log in. """
|
||||
super(UpdateEmailOptInTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory.create(username=self.USERNAME, email=self.EMAIL, password=self.PASSWORD)
|
||||
self.client.login(username=self.USERNAME, password=self.PASSWORD)
|
||||
|
||||
@ddt.data(
|
||||
(u"True", u"True"),
|
||||
(u"true", u"True"),
|
||||
(u"TrUe", u"True"),
|
||||
(u"Banana", u"False"),
|
||||
(u"strawberries", u"False"),
|
||||
(u"False", u"False"),
|
||||
("True", "True"),
|
||||
("true", "True"),
|
||||
("TrUe", "True"),
|
||||
("Banana", "False"),
|
||||
("strawberries", "False"),
|
||||
("False", "False"),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_update_email_opt_in(self, opt, result):
|
||||
"""Tests the email opt in preference"""
|
||||
# Register, which should trigger an activation email
|
||||
response = self.client.post(self.url, {
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"email_opt_in": opt
|
||||
})
|
||||
self.assertHttpOK(response)
|
||||
@@ -597,9 +593,9 @@ class UpdateEmailOptInTestCase(UserAPITestCase, SharedModuleStoreTestCase):
|
||||
"""Tests the email opt in preference"""
|
||||
params = {}
|
||||
if use_course_id:
|
||||
params["course_id"] = six.text_type(self.course.id)
|
||||
params["course_id"] = str(self.course.id)
|
||||
if use_opt_in:
|
||||
params["email_opt_in"] = u"True"
|
||||
params["email_opt_in"] = "True"
|
||||
|
||||
response = self.client.post(self.url, params)
|
||||
self.assertHttpBadRequest(response)
|
||||
@@ -610,14 +606,14 @@ class UpdateEmailOptInTestCase(UserAPITestCase, SharedModuleStoreTestCase):
|
||||
self.user.save()
|
||||
# Register, which should trigger an activation email
|
||||
response = self.client.post(self.url, {
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"email_opt_in": u"True"
|
||||
"course_id": str(self.course.id),
|
||||
"email_opt_in": "True"
|
||||
})
|
||||
self.assertHttpOK(response)
|
||||
preference = UserOrgTag.objects.get(
|
||||
user=self.user, org=self.course.id.org, key="email-optin"
|
||||
)
|
||||
assert preference.value == u'True'
|
||||
assert preference.value == 'True'
|
||||
|
||||
def test_update_email_opt_in_anonymous_user(self):
|
||||
"""
|
||||
@@ -626,8 +622,8 @@ class UpdateEmailOptInTestCase(UserAPITestCase, SharedModuleStoreTestCase):
|
||||
"""
|
||||
self.client.logout()
|
||||
response = self.client.post(self.url, {
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"email_opt_in": u"True"
|
||||
"course_id": str(self.course.id),
|
||||
"email_opt_in": "True"
|
||||
})
|
||||
assert response.status_code == 403
|
||||
|
||||
@@ -638,7 +634,7 @@ class UpdateEmailOptInTestCase(UserAPITestCase, SharedModuleStoreTestCase):
|
||||
"""
|
||||
response = self.client.post(self.url, {
|
||||
"course_id": 'invalid',
|
||||
"email_opt_in": u"True"
|
||||
"email_opt_in": "True"
|
||||
})
|
||||
self.assertHttpBadRequest(response)
|
||||
with pytest.raises(UserOrgTag.DoesNotExist):
|
||||
|
||||
@@ -89,17 +89,17 @@ urlpatterns = [
|
||||
name='accounts_detail_api'
|
||||
),
|
||||
url(
|
||||
r'^v1/accounts/{}$'.format(settings.USERNAME_PATTERN),
|
||||
fr'^v1/accounts/{settings.USERNAME_PATTERN}$',
|
||||
ACCOUNT_DETAIL,
|
||||
name='accounts_api'
|
||||
),
|
||||
url(
|
||||
r'^v1/accounts/{}/image$'.format(settings.USERNAME_PATTERN),
|
||||
fr'^v1/accounts/{settings.USERNAME_PATTERN}/image$',
|
||||
ProfileImageView.as_view(),
|
||||
name='accounts_profile_image_api'
|
||||
),
|
||||
url(
|
||||
r'^v1/accounts/{}/deactivate/$'.format(settings.USERNAME_PATTERN),
|
||||
fr'^v1/accounts/{settings.USERNAME_PATTERN}/deactivate/$',
|
||||
AccountDeactivationView.as_view(),
|
||||
name='accounts_deactivation'
|
||||
),
|
||||
@@ -109,17 +109,17 @@ urlpatterns = [
|
||||
name='deactivate_logout'
|
||||
),
|
||||
url(
|
||||
r'^v1/accounts/{}/verification_status/$'.format(settings.USERNAME_PATTERN),
|
||||
fr'^v1/accounts/{settings.USERNAME_PATTERN}/verification_status/$',
|
||||
IDVerificationStatusView.as_view(),
|
||||
name='verification_status'
|
||||
),
|
||||
url(
|
||||
r'^v1/accounts/{}/verifications/$'.format(settings.USERNAME_PATTERN),
|
||||
fr'^v1/accounts/{settings.USERNAME_PATTERN}/verifications/$',
|
||||
IDVerificationStatusDetailsView.as_view(),
|
||||
name='verification_details'
|
||||
),
|
||||
url(
|
||||
r'^v1/accounts/{}/retirement_status/$'.format(settings.USERNAME_PATTERN),
|
||||
fr'^v1/accounts/{settings.USERNAME_PATTERN}/retirement_status/$',
|
||||
RETIREMENT_RETRIEVE,
|
||||
name='accounts_retirement_retrieve'
|
||||
),
|
||||
@@ -169,12 +169,12 @@ urlpatterns = [
|
||||
name='username_replacement'
|
||||
),
|
||||
url(
|
||||
r'^v1/preferences/{}$'.format(settings.USERNAME_PATTERN),
|
||||
fr'^v1/preferences/{settings.USERNAME_PATTERN}$',
|
||||
PreferencesView.as_view(),
|
||||
name='preferences_api'
|
||||
),
|
||||
url(
|
||||
r'^v1/preferences/{}/(?P<preference_key>[a-zA-Z0-9_]+)$'.format(settings.USERNAME_PATTERN),
|
||||
fr'^v1/preferences/{settings.USERNAME_PATTERN}/(?P<preference_key>[a-zA-Z0-9_]+)$',
|
||||
PreferencesDetailView.as_view(),
|
||||
name='preferences_detail_api'
|
||||
),
|
||||
@@ -183,7 +183,7 @@ urlpatterns = [
|
||||
|
||||
# Moved from user_api/legacy_urls.py
|
||||
url(
|
||||
r'^v1/preferences/(?P<pref_key>{})/users/$'.format(UserPreference.KEY_REGEX),
|
||||
fr'^v1/preferences/(?P<pref_key>{UserPreference.KEY_REGEX})/users/$',
|
||||
user_api_views.PreferenceUsersListView.as_view()
|
||||
),
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ from rest_framework import authentication, generics, status, viewsets
|
||||
from rest_framework.exceptions import ParseError
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.views import APIView
|
||||
from six import text_type # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
from openedx.core.djangoapps.django_comment_common.models import Role
|
||||
from openedx.core.djangoapps.user_api import accounts # lint-amnesty, pylint: disable=unused-import
|
||||
@@ -128,7 +127,7 @@ class UpdateEmailOptInPreference(APIView):
|
||||
except InvalidKeyError:
|
||||
return HttpResponse(
|
||||
status=400,
|
||||
content=u"No course '{course_id}' found".format(course_id=course_id),
|
||||
content=f"No course '{course_id}' found",
|
||||
content_type="text/plain"
|
||||
)
|
||||
# Only check for true. All other values are False.
|
||||
|
||||
Reference in New Issue
Block a user