diff --git a/openedx/core/djangoapps/user_api/accounts/__init__.py b/openedx/core/djangoapps/user_api/accounts/__init__.py index 15cf2eebeb..54ee6c2c65 100644 --- a/openedx/core/djangoapps/user_api/accounts/__init__.py +++ b/openedx/core/djangoapps/user_api/accounts/__init__.py @@ -2,10 +2,11 @@ Account constants """ +from __future__ import absolute_import + from django.utils.text import format_lazy from django.utils.translation import ugettext_lazy as _ - # The maximum length for the bio ("about me") account field BIO_MAX_LENGTH = 300 diff --git a/openedx/core/djangoapps/user_api/accounts/api.py b/openedx/core/djangoapps/user_api/accounts/api.py index dcb38f1ba5..7b60511233 100644 --- a/openedx/core/djangoapps/user_api/accounts/api.py +++ b/openedx/core/djangoapps/user_api/accounts/api.py @@ -3,50 +3,51 @@ """ Programmatic integration point for User API Accounts sub-application """ +from __future__ import absolute_import + import datetime -from pytz import UTC -from django.utils.translation import override as override_language, ugettext as _ -from django.db import transaction, IntegrityError -from django.core.exceptions import ObjectDoesNotExist +import six from django.conf import settings -from django.core.validators import validate_email, ValidationError +from django.core.exceptions import ObjectDoesNotExist +from django.core.validators import ValidationError, validate_email +from django.db import IntegrityError, transaction from django.http import HttpResponseForbidden -from openedx.core.djangoapps.theming.helpers import get_current_request -from six import text_type - -from student.models import ( - AccountRecovery, - User, - UserProfile, - Registration, - email_exists_or_retired, - username_exists_or_retired -) -from student import forms as student_forms -from student import views as student_views -from util.model_utils import emit_setting_changed_event -from util.password_policy_validators import validate_password, normalize_password +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 openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from openedx.core.djangoapps.user_api import errors, accounts, forms, helpers -from openedx.core.djangoapps.user_api.config.waffle import ( - PREVENT_AUTH_USER_WRITES, - SYSTEM_MAINTENANCE_MSG, - waffle, -) +from openedx.core.djangoapps.theming.helpers import get_current_request +from openedx.core.djangoapps.user_api import accounts, errors, forms, helpers +from openedx.core.djangoapps.user_api.config.waffle import PREVENT_AUTH_USER_WRITES, SYSTEM_MAINTENANCE_MSG, waffle from openedx.core.djangoapps.user_api.errors import ( AccountUpdateError, AccountValidationError, - PreferenceValidationError, + PreferenceValidationError ) from openedx.core.djangoapps.user_api.preferences.api import update_user_preferences from openedx.core.lib.api.view_utils import add_serializer_errors from openedx.features.enterprise_support.utils import get_enterprise_readonly_account_fields +from student import forms as student_forms +from student import views as student_views +from student.models import ( + AccountRecovery, + Registration, + User, + UserProfile, + email_exists_or_retired, + username_exists_or_retired +) +from util.model_utils import emit_setting_changed_event +from util.password_policy_validators import normalize_password, validate_password from .serializers import ( - AccountLegacyProfileSerializer, AccountUserSerializer, - UserReadOnlySerializer, _visible_fields # pylint: disable=invalid-name + AccountLegacyProfileSerializer, + AccountUserSerializer, + UserReadOnlySerializer, + _visible_fields ) # Public access point for this function. @@ -679,7 +680,7 @@ def _validate_username(username): """ try: _validate_unicode(username) - _validate_type(username, basestring, accounts.USERNAME_BAD_TYPE_MSG) + _validate_type(username, six.string_types, accounts.USERNAME_BAD_TYPE_MSG) _validate_length( username, accounts.USERNAME_MIN_LENGTH, @@ -711,7 +712,7 @@ def _validate_email(email): """ try: _validate_unicode(email) - _validate_type(email, basestring, accounts.EMAIL_BAD_TYPE_MSG) + _validate_type(email, six.string_types, 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) @@ -753,7 +754,7 @@ def _validate_password(password, username=None, email=None): """ try: - _validate_type(password, basestring, accounts.PASSWORD_BAD_TYPE_MSG) + _validate_type(password, six.string_types, 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: @@ -870,9 +871,9 @@ def _validate_unicode(data, err=u"Input not valid unicode"): """ try: - if not isinstance(data, str) and not isinstance(data, unicode): + if not isinstance(data, str) and not isinstance(data, six.text_type): raise UnicodeError(err) # In some cases we pass the above, but it's still inappropriate utf-8. - unicode(data) + six.text_type(data) except UnicodeError: raise UnicodeError(err) diff --git a/openedx/core/djangoapps/user_api/accounts/forms.py b/openedx/core/djangoapps/user_api/accounts/forms.py index 418b98a291..ee0b908cf2 100644 --- a/openedx/core/djangoapps/user_api/accounts/forms.py +++ b/openedx/core/djangoapps/user_api/accounts/forms.py @@ -2,8 +2,11 @@ Django forms for accounts """ +from __future__ import absolute_import + from django import forms from django.core.exceptions import ValidationError + from openedx.core.djangoapps.user_api.accounts.utils import generate_password diff --git a/openedx/core/djangoapps/user_api/accounts/image_helpers.py b/openedx/core/djangoapps/user_api/accounts/image_helpers.py index a1c46c46e5..cc56435ba9 100644 --- a/openedx/core/djangoapps/user_api/accounts/image_helpers.py +++ b/openedx/core/djangoapps/user_api/accounts/image_helpers.py @@ -1,21 +1,23 @@ """ Helper functions for the accounts API. """ +from __future__ import absolute_import + import hashlib from django.conf import settings +from django.contrib.staticfiles.storage import staticfiles_storage from django.core.exceptions import ObjectDoesNotExist from django.core.files.storage import get_storage_class -from django.contrib.staticfiles.storage import staticfiles_storage -from student.models import UserProfile -from ..errors import UserNotFound from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers +from student.models import UserProfile +from ..errors import UserNotFound PROFILE_IMAGE_FILE_EXTENSION = 'jpg' # All processed profile images are converted to JPEGs -_PROFILE_IMAGE_SIZES = settings.PROFILE_IMAGE_SIZES_MAP.values() +_PROFILE_IMAGE_SIZES = list(settings.PROFILE_IMAGE_SIZES_MAP.values()) def get_profile_image_storage(): diff --git a/openedx/core/djangoapps/user_api/accounts/permissions.py b/openedx/core/djangoapps/user_api/accounts/permissions.py index 7b14ce00c6..5604b93b1f 100644 --- a/openedx/core/djangoapps/user_api/accounts/permissions.py +++ b/openedx/core/djangoapps/user_api/accounts/permissions.py @@ -1,7 +1,7 @@ """ Permissions classes for User accounts API views. """ -from __future__ import unicode_literals +from __future__ import absolute_import, unicode_literals from django.conf import settings from rest_framework import permissions diff --git a/openedx/core/djangoapps/user_api/accounts/serializers.py b/openedx/core/djangoapps/user_api/accounts/serializers.py index 37e0321459..8e7f7e8099 100644 --- a/openedx/core/djangoapps/user_api/accounts/serializers.py +++ b/openedx/core/djangoapps/user_api/accounts/serializers.py @@ -1,34 +1,37 @@ """ Django REST Framework serializers for the User API Accounts sub-application """ +from __future__ import absolute_import + import json import logging -from rest_framework import serializers -from django.contrib.auth.models import User from django.conf import settings +from django.contrib.auth.models import User from django.core.exceptions import ObjectDoesNotExist from django.urls import reverse +from rest_framework import serializers from six import text_type from lms.djangoapps.badges.utils import badges_enabled from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.user_api import errors from openedx.core.djangoapps.user_api.accounts.utils import is_secondary_email_feature_enabled_for_user -from openedx.core.djangoapps.user_api.models import ( - RetirementState, - UserPreference, - UserRetirementStatus -) +from openedx.core.djangoapps.user_api.models import RetirementState, UserPreference, UserRetirementStatus from openedx.core.djangoapps.user_api.serializers import ReadOnlyFieldsSerializerMixin -from student.models import UserProfile, LanguageProficiency, SocialLink +from student.models import LanguageProficiency, SocialLink, UserProfile from . import ( - BIO_MAX_LENGTH, NAME_MIN_LENGTH, ACCOUNT_VISIBILITY_PREF_KEY, PRIVATE_VISIBILITY, CUSTOM_VISIBILITY, - ALL_USERS_VISIBILITY, VISIBILITY_PREFIX + ACCOUNT_VISIBILITY_PREF_KEY, + ALL_USERS_VISIBILITY, + BIO_MAX_LENGTH, + CUSTOM_VISIBILITY, + NAME_MIN_LENGTH, + PRIVATE_VISIBILITY, + VISIBILITY_PREFIX ) from .image_helpers import get_profile_image_urls_for_user -from .utils import validate_social_link, format_social_link +from .utils import format_social_link, validate_social_link PROFILE_IMAGE_KEY_PREFIX = 'image_url' LOGGER = logging.getLogger(__name__) diff --git a/openedx/core/djangoapps/user_api/accounts/settings_views.py b/openedx/core/djangoapps/user_api/accounts/settings_views.py index 6bfae46d69..b3d94c8554 100644 --- a/openedx/core/djangoapps/user_api/accounts/settings_views.py +++ b/openedx/core/djangoapps/user_api/accounts/settings_views.py @@ -1,18 +1,22 @@ """ Views related to Account Settings. """ -from datetime import datetime +from __future__ import absolute_import + import logging +from datetime import datetime + +import six from django.conf import settings from django.contrib import messages from django.contrib.auth.decorators import login_required from django.shortcuts import redirect -from django.utils.translation import ugettext as _ from django.urls import reverse +from django.utils.translation import ugettext as _ from django.views.decorators.http import require_http_methods from django_countries import countries +import third_party_auth from edxmako.shortcuts import render_to_response - from lms.djangoapps.commerce.models import CommerceConfiguration from lms.djangoapps.commerce.utils import EcommerceService from openedx.core.djangoapps.commerce.utils import ecommerce_api_client @@ -21,8 +25,8 @@ from openedx.core.djangoapps.lang_pref.api import all_languages, released_langua from openedx.core.djangoapps.programs.models import ProgramsApiConfig from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.user_api.accounts.toggles import ( - should_redirect_to_order_history_microfrontend, should_redirect_to_account_microfrontend, + should_redirect_to_order_history_microfrontend ) from openedx.core.djangoapps.user_api.preferences.api import get_user_preferences from openedx.core.lib.edx_api_utils import get_edx_api_data @@ -30,11 +34,9 @@ from openedx.core.lib.time_zone_utils import TIME_ZONE_CHOICES from openedx.features.enterprise_support.api import get_enterprise_customer_for_learner from openedx.features.enterprise_support.utils import update_account_settings_context_for_enterprise from student.models import UserProfile -import third_party_auth from third_party_auth import pipeline from util.date_utils import strftime_localized - log = logging.getLogger(__name__) @@ -75,7 +77,7 @@ def account_settings_context(request): """ user = request.user - year_of_birth_options = [(unicode(year), unicode(year)) for year in UserProfile.VALID_YEARS] + year_of_birth_options = [(six.text_type(year), six.text_type(year)) for year in UserProfile.VALID_YEARS] try: user_orders = get_user_orders(user) except: # pylint: disable=bare-except diff --git a/openedx/core/djangoapps/user_api/accounts/signals.py b/openedx/core/djangoapps/user_api/accounts/signals.py index 752f3dc00b..4c88b95069 100644 --- a/openedx/core/djangoapps/user_api/accounts/signals.py +++ b/openedx/core/djangoapps/user_api/accounts/signals.py @@ -2,6 +2,8 @@ Django Signal related functionality for user_api accounts """ +from __future__ import absolute_import + from django.dispatch import Signal # Signal to retire a user from LMS-initiated mailings (course mailings, etc) diff --git a/openedx/core/djangoapps/user_api/accounts/tests/retirement_helpers.py b/openedx/core/djangoapps/user_api/accounts/tests/retirement_helpers.py index 15d607df42..d54d3ec081 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/retirement_helpers.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/retirement_helpers.py @@ -1,6 +1,8 @@ """ Helpers for testing retirement functionality """ +from __future__ import absolute_import + import datetime import pytest @@ -9,14 +11,8 @@ from django.test import TestCase from social_django.models import UserSocialAuth from enrollment import api -from openedx.core.djangoapps.user_api.models import ( - RetirementState, - UserRetirementStatus -) -from student.models import ( - get_retired_username_by_username, - get_retired_email_by_email, -) +from openedx.core.djangoapps.user_api.models import RetirementState, UserRetirementStatus +from student.models import get_retired_email_by_email, get_retired_username_by_username from student.tests.factories import UserFactory from ..views import AccountRetirementView diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_api.py b/openedx/core/djangoapps/user_api/accounts/tests/test_api.py index 9ea3f2e136..f52f5a1113 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_api.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_api.py @@ -4,6 +4,8 @@ Unit tests for behavior that is specific to the api methods (vs. the view method Most of the functionality is covered in test_views.py. """ +from __future__ import absolute_import + import itertools import re import unicodedata @@ -41,11 +43,7 @@ from openedx.core.djangoapps.user_api.accounts.tests.testutils import ( INVALID_USERNAMES, VALID_USERNAMES_UNICODE ) -from openedx.core.djangoapps.user_api.config.waffle import ( - PREVENT_AUTH_USER_WRITES, - SYSTEM_MAINTENANCE_MSG, - waffle -) +from openedx.core.djangoapps.user_api.config.waffle import PREVENT_AUTH_USER_WRITES, SYSTEM_MAINTENANCE_MSG, waffle from openedx.core.djangoapps.user_api.errors import ( AccountEmailInvalid, AccountPasswordInvalid, diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_image_helpers.py b/openedx/core/djangoapps/user_api/accounts/tests/test_image_helpers.py index c7a35da947..b2e04e16f1 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_image_helpers.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_image_helpers.py @@ -1,15 +1,18 @@ """ Tests for helpers.py """ +from __future__ import absolute_import + import datetime import hashlib + +from django.test import TestCase from mock import patch from pytz import UTC -from django.test import TestCase - from openedx.core.djangolib.testing.utils import skip_unless_lms from student.tests.factories import UserFactory + from ..image_helpers import get_profile_image_urls_for_user TEST_SIZES = {'full': 50, 'small': 10} diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_models.py b/openedx/core/djangoapps/user_api/accounts/tests/test_models.py index e903ed0bd6..d7f4e29064 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_models.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_models.py @@ -1,6 +1,8 @@ """ Model specific tests for user_api """ +from __future__ import absolute_import + import pytest from openedx.core.djangoapps.user_api.models import ( @@ -11,8 +13,8 @@ from openedx.core.djangoapps.user_api.models import ( ) from student.models import get_retired_email_by_email, get_retired_username_by_username from student.tests.factories import UserFactory -from .retirement_helpers import setup_retirement_states # pylint: disable=unused-import +from .retirement_helpers import setup_retirement_states # pylint: disable=unused-import # Tell pytest it's ok to use the database pytestmark = pytest.mark.django_db diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_permissions.py b/openedx/core/djangoapps/user_api/accounts/tests/test_permissions.py index 94d46e9728..20bfd21a7f 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_permissions.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_permissions.py @@ -1,7 +1,9 @@ """ Tests for User deactivation API permissions """ -from django.test import TestCase, RequestFactory +from __future__ import absolute_import + +from django.test import RequestFactory, TestCase from openedx.core.djangoapps.user_api.accounts.permissions import CanDeactivateUser, CanRetireUser from student.tests.factories import ContentTypeFactory, PermissionFactory, SuperuserFactory, UserFactory diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py b/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py index 11525d4589..0d3bfb6075 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py @@ -2,15 +2,15 @@ """ Test cases to cover account retirement views """ -from __future__ import print_function +from __future__ import absolute_import, print_function import datetime import json import unittest import ddt -import pytz import mock +import pytz from consent.models import DataSharingConsent from django.conf import settings from django.contrib.auth.models import User @@ -20,40 +20,42 @@ from django.core.cache import cache from django.core.urlresolvers import reverse from django.test import TestCase from enterprise.models import ( + EnterpriseCourseEnrollment, EnterpriseCustomer, EnterpriseCustomerUser, - EnterpriseCourseEnrollment, - PendingEnterpriseCustomerUser, -) -from integrated_channels.sap_success_factors.models import ( - SapSuccessFactorsLearnerDataTransmissionAudit + PendingEnterpriseCustomerUser ) +from integrated_channels.sap_success_factors.models import SapSuccessFactorsLearnerDataTransmissionAudit from opaque_keys.edx.keys import CourseKey from rest_framework import status from six import iteritems, text_type +from six.moves import range from social_django.models import UserSocialAuth -from wiki.models import ArticleRevision, Article -from wiki.models.pluginbase import RevisionPluginRevision, RevisionPlugin -from xmodule.modulestore.tests.factories import CourseFactory -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from wiki.models import Article, ArticleRevision +from wiki.models.pluginbase import RevisionPlugin, RevisionPluginRevision from entitlements.models import CourseEntitlementSupportDetail from entitlements.tests.factories import CourseEntitlementFactory from openedx.core.djangoapps.api_admin.models import ApiAccessRequest -from openedx.core.djangoapps.credit.models import ( - CreditRequirementStatus, CreditRequest, CreditCourse, CreditProvider, CreditRequirement -) from openedx.core.djangoapps.course_groups.models import CourseUserGroup, UnregisteredLearnerCohortAssignments +from openedx.core.djangoapps.credit.models import ( + CreditCourse, + CreditProvider, + CreditRequest, + CreditRequirement, + CreditRequirementStatus +) from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory +from openedx.core.djangoapps.user_api.accounts.views import AccountRetirementPartnerReportView from openedx.core.djangoapps.user_api.models import ( RetirementState, - UserRetirementStatus, + UserOrgTag, UserRetirementPartnerReportingStatus, - UserOrgTag + UserRetirementStatus ) -from openedx.core.djangoapps.user_api.accounts.views import AccountRetirementPartnerReportView from student.models import ( + AccountRecovery, CourseEnrollment, CourseEnrollmentAllowed, ManualEnrollmentAudit, @@ -62,26 +64,27 @@ from student.models import ( Registration, SocialLink, UserProfile, - get_retired_username_by_username, get_retired_email_by_email, - AccountRecovery, + get_retired_username_by_username ) from student.tests.factories import ( + AccountRecoveryFactory, ContentTypeFactory, CourseEnrollmentAllowedFactory, PendingEmailChangeFactory, PermissionFactory, SuperuserFactory, - UserFactory, - AccountRecoveryFactory, + UserFactory ) +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.factories import CourseFactory -from ..views import AccountRetirementView, USER_PROFILE_PII from ...tests.factories import UserOrgTagFactory +from ..views import USER_PROFILE_PII, AccountRetirementView from .retirement_helpers import ( # pylint: disable=unused-import RetirementTestCase, - fake_completed_retirement, create_retirement_status, + fake_completed_retirement, setup_retirement_states ) diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_serializers.py b/openedx/core/djangoapps/user_api/accounts/tests/test_serializers.py index 2f6f0755a8..6fd32565fc 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_serializers.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_serializers.py @@ -1,16 +1,17 @@ """ Test cases to cover Accounts-related serializers of the User API application """ +from __future__ import absolute_import + import logging from django.test import TestCase from django.test.client import RequestFactory from testfixtures import LogCapture +from openedx.core.djangoapps.user_api.accounts.serializers import UserReadOnlySerializer from student.models import UserProfile from student.tests.factories import UserFactory -from openedx.core.djangoapps.user_api.accounts.serializers import UserReadOnlySerializer - LOGGER_NAME = "openedx.core.djangoapps.user_api.accounts.serializers" diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_settings_views.py b/openedx/core/djangoapps/user_api/accounts/tests/test_settings_views.py index ce10563a56..6ff1edf5a8 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_settings_views.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_settings_views.py @@ -1,28 +1,30 @@ """ Tests for views related to account settings. """ # -*- coding: utf-8 -*- +from __future__ import absolute_import + import mock from django.conf import settings from django.contrib import messages from django.contrib.messages.middleware import MessageMiddleware -from django.urls import reverse from django.http import HttpRequest from django.test import TestCase from django.test.utils import override_settings +from django.urls import reverse from edx_rest_api_client import exceptions from lms.djangoapps.commerce.models import CommerceConfiguration from lms.djangoapps.commerce.tests import factories from lms.djangoapps.commerce.tests.mocks import mock_get_orders -from openedx.core.djangoapps.user_api.accounts.toggles import REDIRECT_TO_ACCOUNT_MICROFRONTEND from openedx.core.djangoapps.dark_lang.models import DarkLangConfig from openedx.core.djangoapps.lang_pref.tests.test_api import EN, LT_LT from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin -from openedx.core.djangoapps.user_api.tests.factories import UserPreferenceFactory -from openedx.core.djangolib.testing.utils import skip_unless_lms from openedx.core.djangoapps.user_api.accounts.settings_views import account_settings_context, get_user_orders +from openedx.core.djangoapps.user_api.accounts.toggles import REDIRECT_TO_ACCOUNT_MICROFRONTEND +from openedx.core.djangoapps.user_api.tests.factories import UserPreferenceFactory from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag +from openedx.core.djangolib.testing.utils import skip_unless_lms from student.tests.factories import UserFactory from third_party_auth.tests.testutil import ThirdPartyAuthTestMixin diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_utils.py b/openedx/core/djangoapps/user_api/accounts/tests/test_utils.py index 6c2e66c047..b492c015b1 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_utils.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_utils.py @@ -3,11 +3,11 @@ from __future__ import absolute_import, division, print_function, unicode_literals import ddt +from completion import models +from completion.test_utils import CompletionWaffleTestMixin from django.test import TestCase from django.test.utils import override_settings -from completion import models -from completion.test_utils import CompletionWaffleTestMixin from openedx.core.djangoapps.user_api.accounts.utils import retrieve_last_sitewide_block_completed from openedx.core.djangolib.testing.utils import skip_unless_lms from student.models import CourseEnrollment @@ -15,7 +15,7 @@ from student.tests.factories import UserFactory from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory -from ..utils import format_social_link, validate_social_link, generate_password +from ..utils import format_social_link, generate_password, validate_social_link @ddt.ddt diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_views.py b/openedx/core/djangoapps/user_api/accounts/tests/test_views.py index f74cf3e427..11ed483431 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_views.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_views.py @@ -2,20 +2,22 @@ """ Test cases to cover Accounts-related behaviors of the User API application """ -from copy import deepcopy +from __future__ import absolute_import + import datetime import hashlib import json +from copy import deepcopy import ddt +import mock +import pytz from django.conf import settings from django.core.urlresolvers import reverse from django.test.testcases import TransactionTestCase from django.test.utils import override_settings - -import mock -import pytz from rest_framework.test import APIClient, APITestCase +from six.moves import range from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user from openedx.core.djangoapps.user_api.accounts import ACCOUNT_VISIBILITY_PREF_KEY @@ -25,8 +27,7 @@ from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_un from student.models import PendingEmailChange, UserProfile from student.tests.factories import TEST_PASSWORD, UserFactory -from .. import ALL_USERS_VISIBILITY, PRIVATE_VISIBILITY, CUSTOM_VISIBILITY - +from .. import ALL_USERS_VISIBILITY, CUSTOM_VISIBILITY, PRIVATE_VISIBILITY TEST_PROFILE_IMAGE_UPLOADED_AT = datetime.datetime(2002, 1, 9, 15, 43, 1, tzinfo=pytz.UTC) @@ -622,7 +623,8 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase): "This field is not editable via this API", data["field_errors"][field_name]["developer_message"] ) self.assertEqual( - u"The '{0}' field cannot be edited.".format(field_name), data["field_errors"][field_name]["user_message"] + u"The '{0}' field cannot be edited.".format(field_name), + data["field_errors"][field_name]["user_message"] ) for field_name in ["username", "date_joined", "is_active", "profile_image", "requires_parental_consent"]: diff --git a/openedx/core/djangoapps/user_api/accounts/tests/testutils.py b/openedx/core/djangoapps/user_api/accounts/tests/testutils.py index 37d1c47efc..07250584c1 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/testutils.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/testutils.py @@ -3,12 +3,10 @@ Utility functions, constants, etc. for testing. """ -from openedx.core.djangoapps.user_api.accounts import ( - USERNAME_MIN_LENGTH, USERNAME_MAX_LENGTH, - EMAIL_MAX_LENGTH, -) -from util.password_policy_validators import DEFAULT_MAX_PASSWORD_LENGTH +from __future__ import absolute_import +from openedx.core.djangoapps.user_api.accounts import EMAIL_MAX_LENGTH, USERNAME_MAX_LENGTH, USERNAME_MIN_LENGTH +from util.password_policy_validators import DEFAULT_MAX_PASSWORD_LENGTH INVALID_NAMES = [ None, diff --git a/openedx/core/djangoapps/user_api/accounts/toggles.py b/openedx/core/djangoapps/user_api/accounts/toggles.py index 32f7b453b5..6d2d7a3120 100644 --- a/openedx/core/djangoapps/user_api/accounts/toggles.py +++ b/openedx/core/djangoapps/user_api/accounts/toggles.py @@ -1,10 +1,11 @@ """ Toggles for accounts related code. """ +from __future__ import absolute_import + from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.waffle_utils import WaffleFlag - # .. toggle_name: REDIRECT_TO_ORDER_HISTORY_MICROFRONTEND # .. toggle_type: waffle_flag # .. toggle_default: False diff --git a/openedx/core/djangoapps/user_api/accounts/utils.py b/openedx/core/djangoapps/user_api/accounts/utils.py index a2e18f0aef..314896f840 100644 --- a/openedx/core/djangoapps/user_api/accounts/utils.py +++ b/openedx/core/djangoapps/user_api/accounts/utils.py @@ -1,20 +1,21 @@ """ Utility methods for the account settings. """ -from __future__ import unicode_literals +from __future__ import absolute_import, unicode_literals import random import re import string -from urlparse import urlparse import waffle +from completion import waffle as completion_waffle +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 +from six.moves.urllib.parse import urlparse # pylint: disable=import-error -from completion import waffle as completion_waffle -from completion.models import BlockCompletion from openedx.core.djangoapps.site_configuration.models import SiteConfiguration from openedx.core.djangoapps.theming.helpers import get_config_value_from_site_or_settings, get_current_site from xmodule.modulestore.django import modulestore @@ -37,10 +38,9 @@ def validate_social_link(platform_name, new_social_link): # Ensure that the new link is valid. if formatted_social_link is None: required_url_stub = settings.SOCIAL_PLATFORMS[platform_name]['url_stub'] - raise ValueError(_( - ' Make sure that you are providing a valid username or a URL that contains "' + - required_url_stub + '". To remove the link from your edX profile, leave this field blank.' - )) + raise ValueError(_('Make sure that you are providing a valid username or a URL that contains "{url_stub}". ' + 'To remove the link from your edX profile, ' + 'leave this field blank.').format(url_stub=required_url_stub)) def format_social_link(platform_name, new_social_link): @@ -190,7 +190,7 @@ def generate_password(length=12, chars=string.letters + string.digits): password = '' password += choice(string.digits) password += choice(string.letters) - password += ''.join([choice(chars) for _i in xrange(length - 2)]) + password += ''.join([choice(chars) for _i in range(length - 2)]) return password diff --git a/openedx/core/djangoapps/user_api/accounts/views.py b/openedx/core/djangoapps/user_api/accounts/views.py index d0b547ccf5..ee76f70cbd 100644 --- a/openedx/core/djangoapps/user_api/accounts/views.py +++ b/openedx/core/djangoapps/user_api/accounts/views.py @@ -4,10 +4,12 @@ An API for retrieving user account information. For additional information and historical context, see: https://openedx.atlassian.net/wiki/display/TNL/User+API """ +from __future__ import absolute_import + import datetime import logging -from functools import wraps import uuid +from functools import wraps import pytz from consent.models import DataSharingConsent @@ -38,25 +40,25 @@ from wiki.models import ArticleRevision from wiki.models.pluginbase import RevisionPluginRevision from entitlements.models import CourseEntitlement -from openedx.core.djangoapps.user_authn.exceptions import AuthFailedError from openedx.core.djangoapps.ace_common.template_context import get_base_template_context from openedx.core.djangoapps.api_admin.models import ApiAccessRequest -from openedx.core.djangoapps.credit.models import CreditRequirementStatus, CreditRequest from openedx.core.djangoapps.course_groups.models import UnregisteredLearnerCohortAssignments +from openedx.core.djangoapps.credit.models import CreditRequest, CreditRequirementStatus from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY from openedx.core.djangoapps.profile_images.images import remove_profile_images from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_image_names, set_has_profile_image -from openedx.core.djangolib.oauth2_retirement_utils import retire_dot_oauth2_models, retire_dop_oauth2_models +from openedx.core.djangoapps.user_authn.exceptions import AuthFailedError +from openedx.core.djangolib.oauth2_retirement_utils import retire_dop_oauth2_models, retire_dot_oauth2_models from openedx.core.lib.api.authentication import OAuth2AuthenticationAllowInactiveUser from openedx.core.lib.api.parsers import MergePatchParser from student.models import ( AccountRecovery, CourseEnrollment, - ManualEnrollmentAudit, - PendingNameChange, CourseEnrollmentAllowed, LoginFailures, + ManualEnrollmentAudit, PendingEmailChange, + PendingNameChange, Registration, User, UserProfile, @@ -65,7 +67,9 @@ from student.models import ( get_retired_username_by_username, is_username_retired ) + from ..errors import AccountUpdateError, AccountValidationError, UserNotAuthorized, UserNotFound +from ..message_types import DeletionNotificationMessage from ..models import ( RetirementState, RetirementStateError, @@ -76,12 +80,7 @@ from ..models import ( from .api import get_account_settings, update_account_settings from .permissions import CanDeactivateUser, CanReplaceUsername, CanRetireUser from .serializers import UserRetirementPartnerReportSerializer, UserRetirementStatusSerializer -from .signals import ( - USER_RETIRE_LMS_CRITICAL, - USER_RETIRE_LMS_MISC, - USER_RETIRE_MAILINGS, -) -from ..message_types import DeletionNotificationMessage +from .signals import USER_RETIRE_LMS_CRITICAL, USER_RETIRE_LMS_MISC, USER_RETIRE_MAILINGS log = logging.getLogger(__name__) @@ -681,7 +680,8 @@ 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)), status=status.HTTP_400_BAD_REQUEST) + return Response(u'Missing required parameter: {}'.format(text_type(exc)), + status=status.HTTP_400_BAD_REQUEST) except RetirementStateError as exc: return Response(text_type(exc), status=status.HTTP_400_BAD_REQUEST) @@ -722,7 +722,8 @@ class AccountRetirementStatusView(ViewSet): except ValueError as exc: return Response(u'Invalid start or end date: {}'.format(text_type(exc)), status=status.HTTP_400_BAD_REQUEST) except KeyError as exc: - return Response(u'Missing required parameter: {}'.format(text_type(exc)), status=status.HTTP_400_BAD_REQUEST) + return Response(u'Missing required parameter: {}'.format(text_type(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: