refactor: pyupgrade in common/util + xblock_django (#26724)
This commit is contained in:
@@ -8,8 +8,8 @@ not migrating so as not to inconvenience users by logging them all out.
|
||||
|
||||
|
||||
from functools import wraps
|
||||
from urllib.parse import urlencode
|
||||
|
||||
import six
|
||||
from django.core import cache
|
||||
# If we can't find a 'general' CACHE defined in settings.py, we simply fall back
|
||||
# to returning the default cache. This will happen with dev machines.
|
||||
@@ -67,8 +67,8 @@ def cache_if_anonymous(*get_parameters):
|
||||
if parameter_value is not None:
|
||||
# urlencode expects data to be of type str, and doesn't deal well with Unicode data
|
||||
# since it doesn't provide a way to specify an encoding.
|
||||
cache_key = cache_key + '.' + six.moves.urllib.parse.urlencode({
|
||||
get_parameter: six.text_type(parameter_value).encode('utf-8')
|
||||
cache_key = cache_key + '.' + urlencode({
|
||||
get_parameter: str(parameter_value).encode('utf-8')
|
||||
})
|
||||
|
||||
response = cache.get(cache_key)
|
||||
|
||||
@@ -5,8 +5,6 @@ Helper functions for configuration parsing
|
||||
|
||||
import collections
|
||||
|
||||
import six
|
||||
|
||||
|
||||
def convert_tokens(tokens):
|
||||
"""
|
||||
@@ -19,7 +17,7 @@ def convert_tokens(tokens):
|
||||
|
||||
if tokens == 'None':
|
||||
return None
|
||||
elif isinstance(tokens, six.string_types) or (not isinstance(tokens, collections.Iterable)):
|
||||
elif isinstance(tokens, str) or (not isinstance(tokens, collections.Iterable)):
|
||||
return tokens
|
||||
elif isinstance(tokens, dict):
|
||||
return {
|
||||
|
||||
@@ -4,8 +4,8 @@ Utility methods related to course
|
||||
|
||||
|
||||
import logging
|
||||
from urllib.parse import urlencode
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.utils.timezone import now
|
||||
|
||||
@@ -32,8 +32,8 @@ def get_encoded_course_sharing_utm_params():
|
||||
Returns encoded Course Sharing UTM Parameters.
|
||||
"""
|
||||
return {
|
||||
utm_source: six.moves.urllib.parse.urlencode(utm_params)
|
||||
for utm_source, utm_params in six.iteritems(COURSE_SHARING_UTM_PARAMETERS)
|
||||
utm_source: urlencode(utm_params)
|
||||
for utm_source, utm_params in COURSE_SHARING_UTM_PARAMETERS.items()
|
||||
}
|
||||
|
||||
|
||||
@@ -54,9 +54,9 @@ def get_link_for_about_page(course):
|
||||
elif settings.FEATURES.get('ENABLE_MKTG_SITE') and getattr(course, 'marketing_url', None):
|
||||
course_about_url = course.marketing_url
|
||||
else:
|
||||
course_about_url = u'{about_base_url}/courses/{course_key}/about'.format(
|
||||
course_about_url = '{about_base_url}/courses/{course_key}/about'.format(
|
||||
about_base_url=configuration_helpers.get_value('LMS_ROOT_URL', settings.LMS_ROOT_URL),
|
||||
course_key=six.text_type(course.id),
|
||||
course_key=str(course.id),
|
||||
)
|
||||
|
||||
return course_about_url
|
||||
|
||||
@@ -26,14 +26,14 @@ def get_default_time_display(dtime):
|
||||
|
||||
"""
|
||||
if dtime is None:
|
||||
return u""
|
||||
return ""
|
||||
if dtime.tzinfo is not None:
|
||||
try:
|
||||
timezone = u" " + dtime.tzinfo.tzname(dtime) # lint-amnesty, pylint: disable=redefined-outer-name
|
||||
timezone = " " + dtime.tzinfo.tzname(dtime) # lint-amnesty, pylint: disable=redefined-outer-name
|
||||
except NotImplementedError:
|
||||
timezone = dtime.strftime('%z')
|
||||
else:
|
||||
timezone = u" UTC"
|
||||
timezone = " UTC"
|
||||
|
||||
localized = strftime_localized(dtime, "DATE_TIME")
|
||||
return (localized + timezone).strip()
|
||||
|
||||
@@ -55,7 +55,7 @@ class OuterAtomic(transaction.Atomic):
|
||||
def __init__(self, using, savepoint, read_committed=False, name=None):
|
||||
self.read_committed = read_committed
|
||||
self.name = name
|
||||
super(OuterAtomic, self).__init__(using, savepoint) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(using, savepoint)
|
||||
|
||||
def __enter__(self):
|
||||
|
||||
@@ -88,7 +88,7 @@ class OuterAtomic(transaction.Atomic):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("SET TRANSACTION ISOLATION LEVEL READ COMMITTED")
|
||||
|
||||
super(OuterAtomic, self).__enter__() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__enter__()
|
||||
|
||||
|
||||
def outer_atomic(using=None, savepoint=True, read_committed=False, name=None):
|
||||
|
||||
@@ -73,7 +73,7 @@ def can_disable_rate_limit(clz):
|
||||
# No-op if the class isn't a Django Rest Framework view.
|
||||
if not issubclass(clz, APIView):
|
||||
msg = (
|
||||
u"{clz} is not a Django Rest Framework APIView subclass."
|
||||
"{clz} is not a Django Rest Framework APIView subclass."
|
||||
).format(clz=clz)
|
||||
LOGGER.warning(msg)
|
||||
return clz
|
||||
|
||||
@@ -6,7 +6,6 @@ Utility methods related to file handling.
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
import six
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.files.storage import DefaultStorage, get_valid_filename
|
||||
from django.utils.translation import ugettext as _
|
||||
@@ -99,7 +98,7 @@ def course_filename_prefix_generator(course_id, separator='_'):
|
||||
str: A unicode string which can safely be inserted into a
|
||||
filename.
|
||||
"""
|
||||
return get_valid_filename(six.text_type(separator).join([course_id.org, course_id.course, course_id.run]))
|
||||
return get_valid_filename(str(separator).join([course_id.org, course_id.course, course_id.run]))
|
||||
|
||||
|
||||
def course_and_time_based_filename_generator(course_id, base_name):
|
||||
@@ -118,14 +117,14 @@ def course_and_time_based_filename_generator(course_id, base_name):
|
||||
and the current time. Note that there will be no extension.
|
||||
|
||||
"""
|
||||
return u"{course_prefix}_{base_name}_{timestamp_str}".format(
|
||||
return "{course_prefix}_{base_name}_{timestamp_str}".format(
|
||||
course_prefix=course_filename_prefix_generator(course_id),
|
||||
base_name=get_valid_filename(base_name),
|
||||
timestamp_str=datetime.now(UTC).strftime("%Y-%m-%d-%H%M%S")
|
||||
)
|
||||
|
||||
|
||||
class UniversalNewlineIterator(object):
|
||||
class UniversalNewlineIterator:
|
||||
"""
|
||||
This iterable class can be used as a wrapper around a file-like
|
||||
object which does not inherently support being read in
|
||||
@@ -143,8 +142,6 @@ class UniversalNewlineIterator(object):
|
||||
"""
|
||||
Replace CR and CRLF with LF within `string`.
|
||||
"""
|
||||
if six.PY2:
|
||||
return string.replace('\r\n', '\n').replace('\r', '\n')
|
||||
return string.replace('\r\n', '\n').replace('\r', '\n').encode('utf-8')
|
||||
|
||||
def generate_lines(self):
|
||||
@@ -165,7 +162,7 @@ class UniversalNewlineIterator(object):
|
||||
line = char
|
||||
yield self.sanitize(last_line)
|
||||
else:
|
||||
line += six.text_type(char) if isinstance(char, int) else char
|
||||
line += str(char) if isinstance(char, int) else char
|
||||
buf = self.original_file.read(self.buffer_size)
|
||||
if not buf and line:
|
||||
yield self.sanitize(line)
|
||||
|
||||
@@ -31,7 +31,7 @@ class EDXJSONEncoder(DjangoJSONEncoder):
|
||||
return int(o)
|
||||
return float(o)
|
||||
else:
|
||||
return super(EDXJSONEncoder, self).default(o) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
return super().default(o)
|
||||
|
||||
|
||||
def expect_json(view_function):
|
||||
@@ -73,7 +73,7 @@ class JsonResponse(HttpResponse):
|
||||
kwargs.setdefault("content_type", "application/json")
|
||||
if status:
|
||||
kwargs["status"] = status
|
||||
super(JsonResponse, self).__init__(content, *args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(content, *args, **kwargs)
|
||||
|
||||
|
||||
class JsonResponseBadRequest(HttpResponseBadRequest):
|
||||
@@ -93,4 +93,4 @@ class JsonResponseBadRequest(HttpResponseBadRequest):
|
||||
content = json.dumps(obj, cls=encoder, indent=2, ensure_ascii=False)
|
||||
kwargs.setdefault("content_type", "application/json")
|
||||
kwargs["status"] = status
|
||||
super(JsonResponseBadRequest, self).__init__(content, *args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(content, *args, **kwargs)
|
||||
|
||||
@@ -5,7 +5,8 @@ so that we can cache any keys, not just ones that memcache would ordinarily acce
|
||||
|
||||
|
||||
import hashlib
|
||||
import six.moves.urllib.parse
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
|
||||
@@ -23,7 +24,7 @@ def cleaned_string(val):
|
||||
Converts `val` to unicode and URL-encodes special characters
|
||||
(including quotes and spaces)
|
||||
"""
|
||||
return six.moves.urllib.parse.quote_plus(smart_str(val))
|
||||
return quote_plus(smart_str(val))
|
||||
|
||||
|
||||
def safe_key(key, key_prefix, version):
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
# Converted from the original South migration 0002_default_rate_limit_config.py
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
"""
|
||||
Utility library for working with the edx-milestones app
|
||||
"""
|
||||
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
from edx_toggles.toggles import SettingDictToggle
|
||||
@@ -63,12 +60,12 @@ def add_prerequisite_course(course_key, prerequisite_course_key):
|
||||
if not is_prerequisite_courses_enabled():
|
||||
return None
|
||||
milestone_name = _('Course {course_id} requires {prerequisite_course_id}').format(
|
||||
course_id=six.text_type(course_key),
|
||||
prerequisite_course_id=six.text_type(prerequisite_course_key)
|
||||
course_id=str(course_key),
|
||||
prerequisite_course_id=str(prerequisite_course_key)
|
||||
)
|
||||
milestone = milestones_api.add_milestone({
|
||||
'name': milestone_name,
|
||||
'namespace': six.text_type(prerequisite_course_key),
|
||||
'namespace': str(prerequisite_course_key),
|
||||
'description': _('System defined milestone'),
|
||||
})
|
||||
# add requirement course milestone
|
||||
@@ -222,7 +219,7 @@ def get_required_content(course_key, user):
|
||||
"""
|
||||
required_content = []
|
||||
if ENABLE_MILESTONES_APP.is_enabled():
|
||||
course_run_id = six.text_type(course_key)
|
||||
course_run_id = str(course_key)
|
||||
|
||||
if user.is_authenticated:
|
||||
# Get all of the outstanding milestones for this course, for this user
|
||||
@@ -287,7 +284,7 @@ def generate_milestone_namespace(namespace, course_key=None):
|
||||
"""
|
||||
if namespace in list(NAMESPACE_CHOICES.values()):
|
||||
if namespace == 'entrance_exams':
|
||||
return '{}.{}'.format(six.text_type(course_key), NAMESPACE_CHOICES['ENTRANCE_EXAM'])
|
||||
return '{}.{}'.format(str(course_key), NAMESPACE_CHOICES['ENTRANCE_EXAM'])
|
||||
|
||||
|
||||
def serialize_user(user):
|
||||
@@ -382,7 +379,7 @@ def get_course_content_milestones(course_id, content_id=None, relationship='requ
|
||||
if content_id is None:
|
||||
return request_cache_dict[user_id][relationship]
|
||||
|
||||
return [m for m in request_cache_dict[user_id][relationship] if m['content_id'] == six.text_type(content_id)]
|
||||
return [m for m in request_cache_dict[user_id][relationship] if m['content_id'] == str(content_id)]
|
||||
|
||||
|
||||
def remove_course_content_user_milestones(course_key, content_key, user, relationship):
|
||||
|
||||
@@ -4,14 +4,13 @@ Utilities for django models.
|
||||
|
||||
from typing import Dict, Any, Tuple
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.dispatch import Signal
|
||||
from django_countries.fields import Country
|
||||
from eventtracking import tracker
|
||||
|
||||
# The setting name used for events when "settings" (account settings, preferences, profile information) change.
|
||||
USER_SETTINGS_CHANGED_EVENT_NAME = u'edx.user.settings.changed'
|
||||
USER_SETTINGS_CHANGED_EVENT_NAME = 'edx.user.settings.changed'
|
||||
# Used to signal a field value change
|
||||
USER_FIELD_CHANGED = Signal(providing_args=["user", "table", "setting", "old_value", "new_value"])
|
||||
USER_FIELDS_CHANGED = Signal(providing_args=["user", "table", "changed_values"])
|
||||
@@ -170,7 +169,7 @@ def _get_truncated_setting_value(value, max_length=None):
|
||||
truncated_value (object): the possibly truncated version of the value.
|
||||
was_truncated (bool): returns true if the serialized value was truncated.
|
||||
"""
|
||||
if isinstance(value, six.string_types) and max_length is not None and len(value) > max_length:
|
||||
if isinstance(value, str) and max_length is not None and len(value) > max_length:
|
||||
return value[0:max_length], True
|
||||
else:
|
||||
return value, False
|
||||
|
||||
@@ -5,7 +5,6 @@ import gzip
|
||||
import logging
|
||||
from io import BytesIO
|
||||
|
||||
import six
|
||||
from config_models.models import ConfigurationModel
|
||||
from django.db import models
|
||||
from django.utils.text import compress_string
|
||||
@@ -58,7 +57,7 @@ class CompressedTextField(CreatorMixin, models.TextField):
|
||||
Compress the text data.
|
||||
"""
|
||||
if value is not None:
|
||||
if isinstance(value, six.text_type):
|
||||
if isinstance(value, str):
|
||||
value = value.encode('utf8')
|
||||
value = compress_string(value)
|
||||
value = value.encode('base64').decode('utf8')
|
||||
@@ -68,7 +67,7 @@ class CompressedTextField(CreatorMixin, models.TextField):
|
||||
"""
|
||||
Decompresses the value from the database.
|
||||
"""
|
||||
if isinstance(value, six.text_type):
|
||||
if isinstance(value, str):
|
||||
value = decompress_string(value)
|
||||
|
||||
return value
|
||||
|
||||
@@ -13,7 +13,6 @@ from django.contrib.auth.password_validation import validate_password as django_
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ungettext
|
||||
from six import text_type
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -71,7 +70,7 @@ def password_validators_instruction_texts():
|
||||
complexity_instructions=' & '.join(complexity_instructions)
|
||||
)
|
||||
else:
|
||||
return _('Your password must contain {length_instruction}.'.format(length_instruction=length_instruction)) # lint-amnesty, pylint: disable=translation-of-non-string
|
||||
return _(f'Your password must contain {length_instruction}.') # lint-amnesty, pylint: disable=translation-of-non-string
|
||||
|
||||
|
||||
def password_validators_restrictions():
|
||||
@@ -93,10 +92,10 @@ def normalize_password(password):
|
||||
Normalize all passwords to 'NFKC' across the platform to prevent mismatched hash strings when comparing entered
|
||||
passwords on login. See LEARNER-4283 for more context.
|
||||
"""
|
||||
if not isinstance(password, text_type):
|
||||
if not isinstance(password, str):
|
||||
try:
|
||||
# some checks rely on unicode semantics (e.g. length)
|
||||
password = text_type(password, encoding='utf8')
|
||||
password = str(password, encoding='utf8')
|
||||
except UnicodeDecodeError:
|
||||
# no reason to get into weeds
|
||||
raise ValidationError([_('Invalid password.')]) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
@@ -159,7 +158,7 @@ class MinimumLengthValidator(DjangoMinimumLengthValidator): # lint-amnesty, pyl
|
||||
return 'min_length', self.min_length
|
||||
|
||||
|
||||
class MaximumLengthValidator(object):
|
||||
class MaximumLengthValidator:
|
||||
"""
|
||||
Validate whether the password is shorter than a maximum length.
|
||||
|
||||
@@ -195,7 +194,7 @@ class MaximumLengthValidator(object):
|
||||
return 'max_length', self.max_length
|
||||
|
||||
|
||||
class AlphabeticValidator(object):
|
||||
class AlphabeticValidator:
|
||||
"""
|
||||
Validate whether the password contains at least min_alphabetic letters.
|
||||
|
||||
@@ -243,7 +242,7 @@ class AlphabeticValidator(object):
|
||||
return 'min_alphabetic', self.min_alphabetic
|
||||
|
||||
|
||||
class NumericValidator(object):
|
||||
class NumericValidator:
|
||||
"""
|
||||
Validate whether the password contains at least min_numeric numbers.
|
||||
|
||||
@@ -291,7 +290,7 @@ class NumericValidator(object):
|
||||
return 'min_numeric', self.min_numeric
|
||||
|
||||
|
||||
class UppercaseValidator(object):
|
||||
class UppercaseValidator:
|
||||
"""
|
||||
Validate whether the password contains at least min_upper uppercase letters.
|
||||
|
||||
@@ -339,7 +338,7 @@ class UppercaseValidator(object):
|
||||
return 'min_upper', self.min_upper
|
||||
|
||||
|
||||
class LowercaseValidator(object):
|
||||
class LowercaseValidator:
|
||||
"""
|
||||
Validate whether the password contains at least min_lower lowercase letters.
|
||||
|
||||
@@ -387,7 +386,7 @@ class LowercaseValidator(object):
|
||||
return 'min_lower', self.min_lower
|
||||
|
||||
|
||||
class PunctuationValidator(object):
|
||||
class PunctuationValidator:
|
||||
"""
|
||||
Validate whether the password contains at least min_punctuation punctuation marks
|
||||
as defined by unicode categories.
|
||||
@@ -436,7 +435,7 @@ class PunctuationValidator(object):
|
||||
return 'min_punctuation', self.min_punctuation
|
||||
|
||||
|
||||
class SymbolValidator(object):
|
||||
class SymbolValidator:
|
||||
"""
|
||||
Validate whether the password contains at least min_symbol symbols as defined by unicode categories.
|
||||
|
||||
|
||||
@@ -2,23 +2,19 @@
|
||||
Utility Mixins for unit tests
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
import sys
|
||||
from importlib import reload
|
||||
from unittest.mock import patch
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.test import TestCase
|
||||
from django.urls import clear_url_caches, resolve
|
||||
from mock import patch
|
||||
|
||||
from common.djangoapps.util.db import OuterAtomic
|
||||
|
||||
if six.PY3:
|
||||
from importlib import reload
|
||||
|
||||
|
||||
class UrlResetMixin(object):
|
||||
class UrlResetMixin:
|
||||
"""Mixin to reset urls.py before and after a test
|
||||
|
||||
Django memoizes the function that reads the urls module (whatever module
|
||||
@@ -69,18 +65,18 @@ class UrlResetMixin(object):
|
||||
URLCONF_MODULES = ['myapp.url', 'another_app.urls']
|
||||
|
||||
"""
|
||||
super(UrlResetMixin, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
self.reset_urls()
|
||||
self.addCleanup(self.reset_urls)
|
||||
|
||||
|
||||
class EventTestMixin(object):
|
||||
class EventTestMixin:
|
||||
"""
|
||||
Generic mixin for verifying that events were emitted during a test.
|
||||
"""
|
||||
def setUp(self, tracker):
|
||||
super(EventTestMixin, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
patcher = patch(tracker)
|
||||
self.mock_tracker = patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
@@ -124,7 +120,7 @@ class EventTestMixin(object):
|
||||
return self.mock_tracker.emit.call_args[0]
|
||||
|
||||
|
||||
class PatchMediaTypeMixin(object):
|
||||
class PatchMediaTypeMixin:
|
||||
"""
|
||||
Generic mixin for verifying unsupported media type in PATCH
|
||||
"""
|
||||
|
||||
@@ -10,7 +10,7 @@ from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
|
||||
|
||||
class CourseCatalogServiceMockMixin(object):
|
||||
class CourseCatalogServiceMockMixin:
|
||||
"""
|
||||
Mocks for the Open edX service 'Course Catalog Service' responses.
|
||||
"""
|
||||
@@ -19,7 +19,7 @@ class CourseCatalogServiceMockMixin(object):
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
super(CourseCatalogServiceMockMixin, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
cache.clear()
|
||||
|
||||
def mock_course_discovery_api_for_catalog_contains(self, catalog_id=1, course_run_ids=None):
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
"""
|
||||
Tests for course utils.
|
||||
"""
|
||||
|
||||
from unittest import mock
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
from django.conf import settings
|
||||
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
@@ -20,7 +19,7 @@ class TestCourseSharingLinks(ModuleStoreTestCase):
|
||||
Tests for course sharing links.
|
||||
"""
|
||||
def setUp(self):
|
||||
super(TestCourseSharingLinks, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
# create test mongo course
|
||||
self.course = CourseFactory.create(
|
||||
@@ -70,7 +69,7 @@ class TestCourseSharingLinks(ModuleStoreTestCase):
|
||||
(True, True, 'test_social_sharing_url'),
|
||||
(False, True, 'test_marketing_url'),
|
||||
(True, False, 'test_social_sharing_url'),
|
||||
(False, False, '{}/courses/course-v1:test_org+test_number+test_run/about'.format(settings.LMS_ROOT_URL)),
|
||||
(False, False, f'{settings.LMS_ROOT_URL}/courses/course-v1:test_org+test_number+test_run/about'),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_sharing_link_with_settings(self, enable_social_sharing, enable_mktg_site, expected_course_sharing_link):
|
||||
@@ -88,7 +87,7 @@ class TestCourseSharingLinks(ModuleStoreTestCase):
|
||||
(['marketing_url'], 'test_social_sharing_url'),
|
||||
(
|
||||
['social_sharing_url', 'marketing_url'],
|
||||
'{}/courses/course-v1:test_org+test_number+test_run/about'.format(settings.LMS_ROOT_URL)
|
||||
f'{settings.LMS_ROOT_URL}/courses/course-v1:test_org+test_number+test_run/about'
|
||||
),
|
||||
)
|
||||
@ddt.unpack
|
||||
@@ -112,7 +111,7 @@ class TestCourseSharingLinks(ModuleStoreTestCase):
|
||||
(True, 'test_social_sharing_url'),
|
||||
(
|
||||
False,
|
||||
'{}/courses/course-v1:test_org+test_number+test_run/about'.format(settings.LMS_ROOT_URL)
|
||||
f'{settings.LMS_ROOT_URL}/courses/course-v1:test_org+test_number+test_run/about'
|
||||
),
|
||||
)
|
||||
@ddt.unpack
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Tests for util.date_utils
|
||||
"""
|
||||
|
||||
|
||||
import unittest
|
||||
from datetime import datetime, timedelta, tzinfo
|
||||
import pytest
|
||||
from unittest.mock import patch
|
||||
|
||||
import ddt
|
||||
import pytest
|
||||
from markupsafe import Markup
|
||||
from mock import patch
|
||||
from pytz import utc
|
||||
|
||||
from common.djangoapps.util.date_utils import (
|
||||
@@ -127,7 +126,7 @@ class StrftimeLocalizedTest(unittest.TestCase):
|
||||
("%Y", "2013"),
|
||||
("%m/%d/%y", "02/14/13"),
|
||||
("hello", "hello"),
|
||||
(u'%Y년 %m월 %d일', u"2013년 02월 14일"),
|
||||
('%Y년 %m월 %d일', "2013년 02월 14일"),
|
||||
("%a, %b %d, %Y", "Thu, Feb 14, 2013"),
|
||||
("%I:%M:%S %p", "04:41:17 PM"),
|
||||
("%A at %-I%P", "Thursday at 4pm"),
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import threading
|
||||
import time
|
||||
import unittest
|
||||
from io import StringIO
|
||||
|
||||
import ddt
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
@@ -12,8 +13,6 @@ from django.db import IntegrityError, connection
|
||||
from django.db.transaction import TransactionManagementError, atomic
|
||||
from django.test import TestCase, TransactionTestCase
|
||||
from django.test.utils import override_settings
|
||||
from django.utils.six import StringIO
|
||||
from six.moves import range
|
||||
|
||||
from common.djangoapps.util.db import enable_named_outer_atomic, generate_int_id, outer_atomic
|
||||
|
||||
@@ -54,7 +53,7 @@ class TransactionManagersTestCase(TransactionTestCase):
|
||||
class RequestThread(threading.Thread):
|
||||
""" A thread which runs a dummy view."""
|
||||
def __init__(self, delay, **kwargs):
|
||||
super(RequestThread, self).__init__(**kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(**kwargs)
|
||||
self.delay = delay
|
||||
self.status = {}
|
||||
|
||||
@@ -189,7 +188,7 @@ class GenerateIntIdTestCase(TestCase):
|
||||
used_ids = {2, 4, 6, 8}
|
||||
for __ in range(times):
|
||||
int_id = generate_int_id(minimum, maximum, used_ids)
|
||||
assert int_id in list((set(range(minimum, (maximum + 1))) - used_ids))
|
||||
assert int_id in list(set(range(minimum, (maximum + 1))) - used_ids)
|
||||
|
||||
|
||||
class MigrationTests(TestCase):
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
import mock
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.test import TestCase
|
||||
@@ -33,7 +33,7 @@ class DisableRateLimitTest(TestCase):
|
||||
"""Check that we can disable rate limiting for perf testing. """
|
||||
|
||||
def setUp(self):
|
||||
super(DisableRateLimitTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
cache.clear()
|
||||
self.view = FakeApiView()
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ from django.core.cache import caches
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase
|
||||
|
||||
|
||||
class CacheCheckMixin(object):
|
||||
class CacheCheckMixin:
|
||||
"""Base mixin that does our cache check."""
|
||||
|
||||
def check_caches(self, key):
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Tests for file.py
|
||||
"""
|
||||
@@ -7,17 +6,17 @@ Tests for file.py
|
||||
import os
|
||||
from datetime import datetime
|
||||
from io import StringIO
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
import ddt
|
||||
from django.core import exceptions
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.http import HttpRequest
|
||||
from django.test import TestCase
|
||||
from mock import Mock, patch
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from opaque_keys.edx.locations import CourseLocator
|
||||
from pytz import UTC
|
||||
from six import text_type
|
||||
|
||||
import common.djangoapps.util.file
|
||||
from common.djangoapps.util.file import (
|
||||
@@ -36,11 +35,11 @@ class FilenamePrefixGeneratorTestCase(TestCase):
|
||||
"""
|
||||
@ddt.data(CourseLocator(org='foo', course='bar', run='baz'), CourseKey.from_string('foo/bar/baz'))
|
||||
def test_locators(self, course_key):
|
||||
assert course_filename_prefix_generator(course_key) == u'foo_bar_baz'
|
||||
assert course_filename_prefix_generator(course_key) == 'foo_bar_baz'
|
||||
|
||||
@ddt.data(CourseLocator(org='foo', course='bar', run='baz'), CourseKey.from_string('foo/bar/baz'))
|
||||
def test_custom_separator(self, course_key):
|
||||
assert course_filename_prefix_generator(course_key, separator='-') == u'foo-bar-baz'
|
||||
assert course_filename_prefix_generator(course_key, separator='-') == 'foo-bar-baz'
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -51,7 +50,7 @@ class FilenameGeneratorTestCase(TestCase):
|
||||
NOW = datetime.strptime('1974-06-22T01:02:03', '%Y-%m-%dT%H:%M:%S').replace(tzinfo=UTC)
|
||||
|
||||
def setUp(self):
|
||||
super(FilenameGeneratorTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
datetime_patcher = patch.object(
|
||||
common.djangoapps.util.file, 'datetime',
|
||||
Mock(wraps=datetime)
|
||||
@@ -65,9 +64,9 @@ class FilenameGeneratorTestCase(TestCase):
|
||||
"""
|
||||
Tests that the generator creates names based on course_id, base name, and date.
|
||||
"""
|
||||
assert u'foo_bar_baz_file_1974-06-22-010203' == course_and_time_based_filename_generator(course_key, 'file')
|
||||
assert 'foo_bar_baz_file_1974-06-22-010203' == course_and_time_based_filename_generator(course_key, 'file')
|
||||
|
||||
assert u'foo_bar_baz_base_name_ø_1974-06-22-010203' ==\
|
||||
assert 'foo_bar_baz_base_name_ø_1974-06-22-010203' ==\
|
||||
course_and_time_based_filename_generator(course_key, ' base` name ø ')
|
||||
|
||||
|
||||
@@ -77,7 +76,7 @@ class StoreUploadedFileTestCase(TestCase):
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(StoreUploadedFileTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.request = Mock(spec=HttpRequest)
|
||||
self.file_content = b"test file content"
|
||||
self.stored_file_name = None
|
||||
@@ -85,7 +84,7 @@ class StoreUploadedFileTestCase(TestCase):
|
||||
self.default_max_size = 2000000
|
||||
|
||||
def tearDown(self):
|
||||
super(StoreUploadedFileTestCase, self).tearDown() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().tearDown()
|
||||
if self.file_storage and self.stored_file_name:
|
||||
self.file_storage.delete(self.stored_file_name)
|
||||
|
||||
@@ -93,7 +92,7 @@ class StoreUploadedFileTestCase(TestCase):
|
||||
"""
|
||||
Helper method to verify exception text.
|
||||
"""
|
||||
assert expected_message == text_type(error.value)
|
||||
assert expected_message == str(error.value)
|
||||
|
||||
def test_error_conditions(self):
|
||||
"""
|
||||
@@ -226,39 +225,39 @@ class TestUniversalNewlineIterator(TestCase):
|
||||
@ddt.data(1, 2, 999)
|
||||
def test_line_feeds(self, buffer_size):
|
||||
assert [thing.decode('utf-8') for thing
|
||||
in UniversalNewlineIterator(StringIO(u'foo\nbar\n'), buffer_size=buffer_size)] == ['foo\n', 'bar\n']
|
||||
in UniversalNewlineIterator(StringIO('foo\nbar\n'), buffer_size=buffer_size)] == ['foo\n', 'bar\n']
|
||||
|
||||
@ddt.data(1, 2, 999)
|
||||
def test_carriage_returns(self, buffer_size):
|
||||
assert [thing.decode('utf-8') for thing in
|
||||
UniversalNewlineIterator(StringIO(u'foo\rbar\r'), buffer_size=buffer_size)] == ['foo\n', 'bar\n']
|
||||
UniversalNewlineIterator(StringIO('foo\rbar\r'), buffer_size=buffer_size)] == ['foo\n', 'bar\n']
|
||||
|
||||
@ddt.data(1, 2, 999)
|
||||
def test_carriage_returns_and_line_feeds(self, buffer_size):
|
||||
assert [thing.decode('utf-8') for thing in
|
||||
UniversalNewlineIterator(StringIO(u'foo\r\nbar\r\n'), buffer_size=buffer_size)] == ['foo\n', 'bar\n']
|
||||
UniversalNewlineIterator(StringIO('foo\r\nbar\r\n'), buffer_size=buffer_size)] == ['foo\n', 'bar\n']
|
||||
|
||||
@ddt.data(1, 2, 999)
|
||||
def test_no_trailing_newline(self, buffer_size):
|
||||
assert [thing.decode('utf-8') for thing in
|
||||
UniversalNewlineIterator(StringIO(u'foo\nbar'), buffer_size=buffer_size)] == ['foo\n', 'bar']
|
||||
UniversalNewlineIterator(StringIO('foo\nbar'), buffer_size=buffer_size)] == ['foo\n', 'bar']
|
||||
|
||||
@ddt.data(1, 2, 999)
|
||||
def test_only_one_line(self, buffer_size):
|
||||
assert [thing.decode('utf-8') for thing in
|
||||
UniversalNewlineIterator(StringIO(u'foo\n'), buffer_size=buffer_size)] == ['foo\n']
|
||||
UniversalNewlineIterator(StringIO('foo\n'), buffer_size=buffer_size)] == ['foo\n']
|
||||
|
||||
@ddt.data(1, 2, 999)
|
||||
def test_only_one_line_no_trailing_newline(self, buffer_size):
|
||||
assert [thing.decode('utf-8') for thing in
|
||||
UniversalNewlineIterator(StringIO(u'foo'), buffer_size=buffer_size)] == ['foo']
|
||||
UniversalNewlineIterator(StringIO('foo'), buffer_size=buffer_size)] == ['foo']
|
||||
|
||||
@ddt.data(1, 2, 999)
|
||||
def test_empty_file(self, buffer_size):
|
||||
assert [thing.decode('utf-8') for thing in
|
||||
UniversalNewlineIterator(StringIO(u''), buffer_size=buffer_size)] == []
|
||||
UniversalNewlineIterator(StringIO(''), buffer_size=buffer_size)] == []
|
||||
|
||||
@ddt.data(1, 2, 999)
|
||||
def test_unicode_data(self, buffer_size):
|
||||
assert [thing.decode('utf-8') for thing
|
||||
in UniversalNewlineIterator(StringIO(u'héllø wo®ld'), buffer_size=buffer_size)] == [u'héllø wo®ld']
|
||||
in UniversalNewlineIterator(StringIO('héllø wo®ld'), buffer_size=buffer_size)] == ['héllø wo®ld']
|
||||
|
||||
@@ -6,7 +6,7 @@ Test for JsonResponse and JsonResponseBadRequest util classes.
|
||||
import json
|
||||
import unittest
|
||||
|
||||
import mock
|
||||
from unittest import mock
|
||||
from django.http import HttpResponse, HttpResponseBadRequest
|
||||
|
||||
from common.djangoapps.util.json_request import JsonResponse, JsonResponseBadRequest
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
"""
|
||||
Tests for keyword_substitution.py
|
||||
"""
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
import six
|
||||
from ddt import ddt, file_data
|
||||
from mock import patch
|
||||
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from common.djangoapps.util import keyword_substitution as Ks
|
||||
@@ -21,7 +19,7 @@ class KeywordSubTest(ModuleStoreTestCase):
|
||||
CREATE_USER = False
|
||||
|
||||
def setUp(self):
|
||||
super(KeywordSubTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory.create(
|
||||
email="testuser@edx.org",
|
||||
username="testuser",
|
||||
@@ -115,14 +113,14 @@ class KeywordSubTest(ModuleStoreTestCase):
|
||||
"""
|
||||
test_string = 'This string should not be subbed here %%USER_ID%%'
|
||||
|
||||
no_course_context = dict(
|
||||
(key, value) for key, value in six.iteritems(self.context) if key != 'course_title'
|
||||
)
|
||||
no_course_context = {
|
||||
key: value for key, value in self.context.items() if key != 'course_title'
|
||||
}
|
||||
result = Ks.substitute_keywords_with_data(test_string, no_course_context)
|
||||
assert test_string == result
|
||||
|
||||
no_user_id_context = dict(
|
||||
(key, value) for key, value in six.iteritems(self.context) if key != 'user_id'
|
||||
)
|
||||
no_user_id_context = {
|
||||
key: value for key, value in self.context.items() if key != 'user_id'
|
||||
}
|
||||
result = Ks.substitute_keywords_with_data(test_string, no_user_id_context)
|
||||
assert test_string == result
|
||||
|
||||
@@ -5,8 +5,6 @@ Tests for memcache in util app
|
||||
|
||||
from django.core.cache import caches
|
||||
from django.test import TestCase
|
||||
from six import unichr
|
||||
from six.moves import range
|
||||
|
||||
from common.djangoapps.util.memcache import safe_key
|
||||
|
||||
@@ -21,7 +19,7 @@ class MemcacheTest(TestCase):
|
||||
[129, 500, 2 ** 8 - 1, 2 ** 8 + 1, 2 ** 16 - 1])
|
||||
|
||||
def setUp(self):
|
||||
super(MemcacheTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.cache = caches['default']
|
||||
|
||||
def test_safe_key(self):
|
||||
@@ -51,7 +49,7 @@ class MemcacheTest(TestCase):
|
||||
key = safe_key(key, '', '')
|
||||
|
||||
# The key should now be valid
|
||||
assert self._is_valid_key(key), 'Failed for key length {0}'.format(length)
|
||||
assert self._is_valid_key(key), f'Failed for key length {length}'
|
||||
|
||||
def test_long_key_prefix_version(self):
|
||||
|
||||
@@ -72,39 +70,39 @@ class MemcacheTest(TestCase):
|
||||
for unicode_char in self.UNICODE_CHAR_CODES:
|
||||
|
||||
# Generate a key with that character
|
||||
key = unichr(unicode_char)
|
||||
key = chr(unicode_char)
|
||||
|
||||
# Make the key safe
|
||||
key = safe_key(key, '', '')
|
||||
|
||||
# The key should now be valid
|
||||
assert self._is_valid_key(key), 'Failed for unicode character {0}'.format(unicode_char)
|
||||
assert self._is_valid_key(key), f'Failed for unicode character {unicode_char}'
|
||||
|
||||
def test_safe_key_prefix_unicode(self):
|
||||
|
||||
for unicode_char in self.UNICODE_CHAR_CODES:
|
||||
|
||||
# Generate a prefix with that character
|
||||
prefix = unichr(unicode_char)
|
||||
prefix = chr(unicode_char)
|
||||
|
||||
# Make the key safe
|
||||
key = safe_key('test', prefix, '')
|
||||
|
||||
# The key should now be valid
|
||||
assert self._is_valid_key(key), 'Failed for unicode character {0}'.format(unicode_char)
|
||||
assert self._is_valid_key(key), f'Failed for unicode character {unicode_char}'
|
||||
|
||||
def test_safe_key_version_unicode(self):
|
||||
|
||||
for unicode_char in self.UNICODE_CHAR_CODES:
|
||||
|
||||
# Generate a version with that character
|
||||
version = unichr(unicode_char)
|
||||
version = chr(unicode_char)
|
||||
|
||||
# Make the key safe
|
||||
key = safe_key('test', '', version)
|
||||
|
||||
# The key should now be valid
|
||||
assert self._is_valid_key(key), 'Failed for unicode character {0}'.format(unicode_char)
|
||||
assert self._is_valid_key(key), f'Failed for unicode character {unicode_char}'
|
||||
|
||||
def _is_valid_key(self, key):
|
||||
"""
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
"""
|
||||
Tests for the milestones helpers library, which is the integration point for the edx_milestones API
|
||||
"""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
import ddt
|
||||
import pytest
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from milestones import api as milestones_api
|
||||
from milestones.exceptions import InvalidCourseKeyException, InvalidUserException
|
||||
from milestones.models import MilestoneRelationshipType
|
||||
from mock import patch
|
||||
|
||||
from common.djangoapps.util import milestones_helpers
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
@@ -31,7 +29,7 @@ class MilestonesHelpersTestCase(ModuleStoreTestCase):
|
||||
"""
|
||||
Test case scaffolding
|
||||
"""
|
||||
super(MilestonesHelpersTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create(
|
||||
metadata={
|
||||
'entrance_exam_enabled': True,
|
||||
@@ -80,16 +78,16 @@ class MilestonesHelpersTestCase(ModuleStoreTestCase):
|
||||
assert len(response) == 0
|
||||
|
||||
def test_add_course_milestone_returns_none_when_app_disabled(self):
|
||||
response = milestones_helpers.add_course_milestone(six.text_type(self.course.id), 'requires', self.milestone)
|
||||
response = milestones_helpers.add_course_milestone(str(self.course.id), 'requires', self.milestone)
|
||||
assert response is None
|
||||
|
||||
def test_get_course_milestones_returns_none_when_app_disabled(self):
|
||||
response = milestones_helpers.get_course_milestones(six.text_type(self.course.id))
|
||||
response = milestones_helpers.get_course_milestones(str(self.course.id))
|
||||
assert len(response) == 0
|
||||
|
||||
def test_add_course_content_milestone_returns_none_when_app_disabled(self):
|
||||
response = milestones_helpers.add_course_content_milestone(
|
||||
six.text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
'i4x://any/content/id',
|
||||
'requires',
|
||||
self.milestone
|
||||
@@ -98,7 +96,7 @@ class MilestonesHelpersTestCase(ModuleStoreTestCase):
|
||||
|
||||
def test_get_course_content_milestones_returns_none_when_app_disabled(self):
|
||||
response = milestones_helpers.get_course_content_milestones(
|
||||
six.text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
'i4x://doesnt/matter/for/this/test',
|
||||
'requires'
|
||||
)
|
||||
@@ -113,7 +111,7 @@ class MilestonesHelpersTestCase(ModuleStoreTestCase):
|
||||
assert 'ENTRANCE_EXAM' in response
|
||||
|
||||
def test_get_course_milestones_fulfillment_paths_returns_none_when_app_disabled(self):
|
||||
response = milestones_helpers.get_course_milestones_fulfillment_paths(six.text_type(self.course.id), self.user)
|
||||
response = milestones_helpers.get_course_milestones_fulfillment_paths(str(self.course.id), self.user)
|
||||
assert response is None
|
||||
|
||||
def test_add_user_milestone_returns_none_when_app_disabled(self):
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tests for util.password_policy_validators module."""
|
||||
|
||||
|
||||
@@ -48,7 +47,7 @@ class PasswordPolicyValidatorsTestCase(unittest.TestCase):
|
||||
|
||||
def test_unicode_password(self):
|
||||
""" Tests that validate_password enforces unicode """
|
||||
unicode_str = u'𤭮'
|
||||
unicode_str = '𤭮'
|
||||
byte_str = unicode_str.encode('utf-8')
|
||||
|
||||
# Sanity checks and demonstration of why this test is useful
|
||||
@@ -65,7 +64,7 @@ class PasswordPolicyValidatorsTestCase(unittest.TestCase):
|
||||
def test_password_unicode_normalization(self):
|
||||
""" Tests that validate_password normalizes passwords """
|
||||
# s ̣ ̇ (s with combining dot below and combining dot above)
|
||||
not_normalized_password = u'\u0073\u0323\u0307'
|
||||
not_normalized_password = '\u0073\u0323\u0307'
|
||||
assert len(not_normalized_password) == 3
|
||||
|
||||
# When we normalize we expect the not_normalized password to fail
|
||||
@@ -102,10 +101,10 @@ class PasswordPolicyValidatorsTestCase(unittest.TestCase):
|
||||
assert msg in password_validators_instruction_texts()
|
||||
|
||||
@data(
|
||||
(u'userna', u'username', 'test@example.com', 'The password is too similar to the username.'),
|
||||
(u'password', u'username', 'password@example.com', 'The password is too similar to the email address.'),
|
||||
(u'password', u'username', 'test@password.com', 'The password is too similar to the email address.'),
|
||||
(u'password', u'username', 'test@example.com', None),
|
||||
('userna', 'username', 'test@example.com', 'The password is too similar to the username.'),
|
||||
('password', 'username', 'password@example.com', 'The password is too similar to the email address.'),
|
||||
('password', 'username', 'test@password.com', 'The password is too similar to the email address.'),
|
||||
('password', 'username', 'test@example.com', None),
|
||||
)
|
||||
@unpack
|
||||
@override_settings(AUTH_PASSWORD_VALIDATORS=[
|
||||
@@ -118,13 +117,13 @@ class PasswordPolicyValidatorsTestCase(unittest.TestCase):
|
||||
|
||||
@data(
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.MinimumLengthValidator', {'min_length': 1})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'', 'This password is too short. It must contain at least 1 character.'),
|
||||
'', 'This password is too short. It must contain at least 1 character.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.MinimumLengthValidator', {'min_length': 8})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'd', 'This password is too short. It must contain at least 8 characters.'),
|
||||
'd', 'This password is too short. It must contain at least 8 characters.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.MinimumLengthValidator', {'min_length': 8})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'longpassword', None),
|
||||
'longpassword', None),
|
||||
)
|
||||
@unpack
|
||||
def test_minimum_length_validation_errors(self, config, password, msg):
|
||||
@@ -134,13 +133,13 @@ class PasswordPolicyValidatorsTestCase(unittest.TestCase):
|
||||
|
||||
@data(
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.MaximumLengthValidator', {'max_length': 1})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'longpassword', 'This password is too long. It must contain no more than 1 character.'),
|
||||
'longpassword', 'This password is too long. It must contain no more than 1 character.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.MaximumLengthValidator', {'max_length': 10})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'longpassword', 'This password is too long. It must contain no more than 10 characters.'),
|
||||
'longpassword', 'This password is too long. It must contain no more than 10 characters.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.MaximumLengthValidator', {'max_length': 20})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'shortpassword', None),
|
||||
'shortpassword', None),
|
||||
)
|
||||
@unpack
|
||||
def test_maximum_length_validation_errors(self, config, password, msg):
|
||||
@@ -149,8 +148,8 @@ class PasswordPolicyValidatorsTestCase(unittest.TestCase):
|
||||
self.validation_errors_checker(password, msg)
|
||||
|
||||
@data(
|
||||
(u'password', 'This password is too common.'),
|
||||
(u'good_password', None),
|
||||
('password', 'This password is too common.'),
|
||||
('good_password', None),
|
||||
)
|
||||
@unpack
|
||||
@override_settings(AUTH_PASSWORD_VALIDATORS=[
|
||||
@@ -162,13 +161,13 @@ class PasswordPolicyValidatorsTestCase(unittest.TestCase):
|
||||
|
||||
@data(
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.AlphabeticValidator', {'min_alphabetic': 1})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'12345', 'This password must contain at least 1 letter.'),
|
||||
'12345', 'This password must contain at least 1 letter.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.AlphabeticValidator', {'min_alphabetic': 5})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'test123', 'This password must contain at least 5 letters.'),
|
||||
'test123', 'This password must contain at least 5 letters.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.AlphabeticValidator', {'min_alphabetic': 2})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'password', None),
|
||||
'password', None),
|
||||
)
|
||||
@unpack
|
||||
def test_alphabetic_validation_errors(self, config, password, msg):
|
||||
@@ -178,13 +177,13 @@ class PasswordPolicyValidatorsTestCase(unittest.TestCase):
|
||||
|
||||
@data(
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.NumericValidator', {'min_numeric': 1})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'test', 'This password must contain at least 1 number.'),
|
||||
'test', 'This password must contain at least 1 number.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.NumericValidator', {'min_numeric': 4})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'test123', 'This password must contain at least 4 numbers.'),
|
||||
'test123', 'This password must contain at least 4 numbers.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.NumericValidator', {'min_numeric': 2})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'password123', None),
|
||||
'password123', None),
|
||||
)
|
||||
@unpack
|
||||
def test_numeric_validation_errors(self, config, password, msg):
|
||||
@@ -194,13 +193,13 @@ class PasswordPolicyValidatorsTestCase(unittest.TestCase):
|
||||
|
||||
@data(
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.UppercaseValidator', {'min_upper': 1})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'lowercase', 'This password must contain at least 1 uppercase letter.'),
|
||||
'lowercase', 'This password must contain at least 1 uppercase letter.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.UppercaseValidator', {'min_upper': 6})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'NOTenough', 'This password must contain at least 6 uppercase letters.'),
|
||||
'NOTenough', 'This password must contain at least 6 uppercase letters.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.UppercaseValidator', {'min_upper': 1})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'camelCase', None),
|
||||
'camelCase', None),
|
||||
)
|
||||
@unpack
|
||||
def test_upper_case_validation_errors(self, config, password, msg):
|
||||
@@ -210,13 +209,13 @@ class PasswordPolicyValidatorsTestCase(unittest.TestCase):
|
||||
|
||||
@data(
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.LowercaseValidator', {'min_lower': 1})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'UPPERCASE', 'This password must contain at least 1 lowercase letter.'),
|
||||
'UPPERCASE', 'This password must contain at least 1 lowercase letter.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.LowercaseValidator', {'min_lower': 4})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'notENOUGH', 'This password must contain at least 4 lowercase letters.'),
|
||||
'notENOUGH', 'This password must contain at least 4 lowercase letters.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.LowercaseValidator', {'min_lower': 1})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'goodPassword', None),
|
||||
'goodPassword', None),
|
||||
)
|
||||
@unpack
|
||||
def test_lower_case_validation_errors(self, config, password, msg):
|
||||
@@ -226,13 +225,13 @@ class PasswordPolicyValidatorsTestCase(unittest.TestCase):
|
||||
|
||||
@data(
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.PunctuationValidator', {'min_punctuation': 1})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'no punctuation', 'This password must contain at least 1 punctuation mark.'),
|
||||
'no punctuation', 'This password must contain at least 1 punctuation mark.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.PunctuationValidator', {'min_punctuation': 7})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'p@$$w0rd$!', 'This password must contain at least 7 punctuation marks.'),
|
||||
'p@$$w0rd$!', 'This password must contain at least 7 punctuation marks.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.PunctuationValidator', {'min_punctuation': 3})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'excl@m@t!on', None),
|
||||
'excl@m@t!on', None),
|
||||
)
|
||||
@unpack
|
||||
def test_punctuation_validation_errors(self, config, password, msg):
|
||||
@@ -242,13 +241,13 @@ class PasswordPolicyValidatorsTestCase(unittest.TestCase):
|
||||
|
||||
@data(
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.SymbolValidator', {'min_symbol': 1})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'no symbol', 'This password must contain at least 1 symbol.'),
|
||||
'no symbol', 'This password must contain at least 1 symbol.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.SymbolValidator', {'min_symbol': 3})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'☹️boo☹️', 'This password must contain at least 3 symbols.'),
|
||||
'☹️boo☹️', 'This password must contain at least 3 symbols.'),
|
||||
|
||||
([create_validator_config('common.djangoapps.util.password_policy_validators.SymbolValidator', {'min_symbol': 2})], # lint-amnesty, pylint: disable=line-too-long
|
||||
u'☪symbols!☹️', None),
|
||||
'☪symbols!☹️', None),
|
||||
)
|
||||
@unpack
|
||||
def test_symbol_validation_errors(self, config, password, msg):
|
||||
|
||||
@@ -4,15 +4,11 @@ Utility functions related to urls.
|
||||
|
||||
|
||||
import sys
|
||||
from importlib import import_module
|
||||
from importlib import import_module, reload
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.urls import set_urlconf
|
||||
|
||||
if six.PY3:
|
||||
from importlib import reload
|
||||
|
||||
|
||||
def reload_django_url_config():
|
||||
"""
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
""" Utility mixin; forces models to validate *before* saving to db """
|
||||
|
||||
|
||||
class ValidateOnSaveMixin(object):
|
||||
class ValidateOnSaveMixin:
|
||||
"""
|
||||
Forces models to call their full_clean method prior to saving
|
||||
"""
|
||||
@@ -11,4 +11,4 @@ class ValidateOnSaveMixin(object):
|
||||
"""
|
||||
if not (force_insert or force_update):
|
||||
self.full_clean()
|
||||
super(ValidateOnSaveMixin, self).save(force_insert, force_update, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().save(force_insert, force_update, **kwargs)
|
||||
|
||||
@@ -14,7 +14,6 @@ from django.views.defaults import server_error
|
||||
from django.shortcuts import redirect
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import CourseKey, UsageKey
|
||||
from six.moves import map
|
||||
|
||||
from lms.djangoapps.courseware.access import has_access
|
||||
from lms.djangoapps.courseware.masquerade import setup_masquerade
|
||||
@@ -75,7 +74,7 @@ def require_global_staff(func):
|
||||
return func(request, *args, **kwargs)
|
||||
else:
|
||||
return HttpResponseForbidden(
|
||||
u"Must be {platform_name} staff to perform this action.".format(
|
||||
"Must be {platform_name} staff to perform this action.".format(
|
||||
platform_name=settings.PLATFORM_NAME
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
@@ -19,7 +16,7 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
|
||||
('disabled_blocks', models.TextField(default=u'', help_text='Space-separated list of XBlocks which should not render.', blank=True)),
|
||||
('disabled_blocks', models.TextField(default='', help_text='Space-separated list of XBlocks which should not render.', blank=True)),
|
||||
('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')),
|
||||
],
|
||||
options={
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
@@ -14,6 +11,6 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='xblockdisableconfig',
|
||||
name='disabled_create_blocks',
|
||||
field=models.TextField(default=u'', help_text='Space-separated list of XBlock types whose creation to disable in Studio.', blank=True),
|
||||
field=models.TextField(default='', help_text='Space-separated list of XBlock types whose creation to disable in Studio.', blank=True),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
@@ -36,8 +33,8 @@ class Migration(migrations.Migration):
|
||||
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
|
||||
('name', models.CharField(max_length=255, db_index=True)),
|
||||
('template', models.CharField(default=u'', max_length=255, blank=True)),
|
||||
('support_level', models.CharField(default=u'us', max_length=2, choices=[(u'fs', 'Fully Supported'), (u'ps', 'Provisionally Supported'), (u'us', 'Unsupported')])),
|
||||
('template', models.CharField(default='', max_length=255, blank=True)),
|
||||
('support_level', models.CharField(default='us', max_length=2, choices=[('fs', 'Fully Supported'), ('ps', 'Provisionally Supported'), ('us', 'Unsupported')])),
|
||||
('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
||||
@@ -40,13 +40,13 @@ class XBlockStudioConfigurationFlag(ConfigurationModel):
|
||||
.. no_pii:
|
||||
"""
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
app_label = "xblock_django"
|
||||
|
||||
# boolean field 'enabled' inherited from parent ConfigurationModel
|
||||
|
||||
def __str__(self):
|
||||
return "XBlockStudioConfigurationFlag(enabled={})".format(self.enabled)
|
||||
return f"XBlockStudioConfigurationFlag(enabled={self.enabled})"
|
||||
|
||||
|
||||
class XBlockStudioConfiguration(ConfigurationModel):
|
||||
@@ -57,9 +57,9 @@ class XBlockStudioConfiguration(ConfigurationModel):
|
||||
"""
|
||||
KEY_FIELDS = ('name', 'template') # xblock name/template combination is unique
|
||||
|
||||
FULL_SUPPORT = u'fs'
|
||||
PROVISIONAL_SUPPORT = u'ps'
|
||||
UNSUPPORTED = u'us'
|
||||
FULL_SUPPORT = 'fs'
|
||||
PROVISIONAL_SUPPORT = 'ps'
|
||||
UNSUPPORTED = 'us'
|
||||
|
||||
SUPPORT_CHOICES = (
|
||||
(FULL_SUPPORT, _('Fully Supported')),
|
||||
@@ -69,10 +69,10 @@ class XBlockStudioConfiguration(ConfigurationModel):
|
||||
|
||||
# boolean field 'enabled' inherited from parent ConfigurationModel
|
||||
name = models.CharField(max_length=255, null=False, db_index=True)
|
||||
template = models.CharField(max_length=255, blank=True, default=u'')
|
||||
template = models.CharField(max_length=255, blank=True, default='')
|
||||
support_level = models.CharField(max_length=2, choices=SUPPORT_CHOICES, default=UNSUPPORTED)
|
||||
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
app_label = "xblock_django"
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
"""
|
||||
Tests related to XBlock support API.
|
||||
"""
|
||||
|
||||
|
||||
import six
|
||||
|
||||
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
|
||||
from common.djangoapps.xblock_django.api import authorable_xblocks, deprecated_xblocks, disabled_xblocks
|
||||
from common.djangoapps.xblock_django.models import XBlockConfiguration, XBlockStudioConfiguration, XBlockStudioConfigurationFlag # lint-amnesty, pylint: disable=line-too-long
|
||||
@@ -15,7 +11,7 @@ class XBlockSupportTestCase(CacheIsolationTestCase):
|
||||
Tests for XBlock Support methods.
|
||||
"""
|
||||
def setUp(self):
|
||||
super(XBlockSupportTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
# Set up XBlockConfigurations for disabled and deprecated states
|
||||
block_config = [
|
||||
@@ -47,23 +43,23 @@ class XBlockSupportTestCase(CacheIsolationTestCase):
|
||||
""" Tests the deprecated_xblocks method """
|
||||
|
||||
deprecated_xblock_names = [block.name for block in deprecated_xblocks()]
|
||||
six.assertCountEqual(self, ["poll", "survey"], deprecated_xblock_names)
|
||||
self.assertCountEqual(["poll", "survey"], deprecated_xblock_names)
|
||||
|
||||
XBlockConfiguration(name="poll", enabled=True, deprecated=False).save()
|
||||
|
||||
deprecated_xblock_names = [block.name for block in deprecated_xblocks()]
|
||||
six.assertCountEqual(self, ["survey"], deprecated_xblock_names)
|
||||
self.assertCountEqual(["survey"], deprecated_xblock_names)
|
||||
|
||||
def test_disabled_blocks(self):
|
||||
""" Tests the disabled_xblocks method """
|
||||
|
||||
disabled_xblock_names = [block.name for block in disabled_xblocks()]
|
||||
six.assertCountEqual(self, ["survey"], disabled_xblock_names)
|
||||
self.assertCountEqual(["survey"], disabled_xblock_names)
|
||||
|
||||
XBlockConfiguration(name="poll", enabled=False, deprecated=True).save()
|
||||
|
||||
disabled_xblock_names = [block.name for block in disabled_xblocks()]
|
||||
six.assertCountEqual(self, ["survey", "poll"], disabled_xblock_names)
|
||||
self.assertCountEqual(["survey", "poll"], disabled_xblock_names)
|
||||
|
||||
def test_authorable_blocks_empty_model(self):
|
||||
"""
|
||||
@@ -81,7 +77,7 @@ class XBlockSupportTestCase(CacheIsolationTestCase):
|
||||
Tests authorable_xblocks when name is not specified.
|
||||
"""
|
||||
authorable_xblock_names = [block.name for block in authorable_xblocks()]
|
||||
six.assertCountEqual(self, ["done", "problem", "problem", "html"], authorable_xblock_names)
|
||||
self.assertCountEqual(["done", "problem", "problem", "html"], authorable_xblock_names)
|
||||
|
||||
# Note that "survey" is disabled in XBlockConfiguration, but it is still returned by
|
||||
# authorable_xblocks because it is marked as enabled and unsupported in XBlockStudioConfiguration.
|
||||
@@ -89,8 +85,7 @@ class XBlockSupportTestCase(CacheIsolationTestCase):
|
||||
# is a whitelist and uses a combination of xblock type and template (and in addition has a global feature flag),
|
||||
# it is expected that Studio code will need to filter by both disabled_xblocks and authorable_xblocks.
|
||||
authorable_xblock_names = [block.name for block in authorable_xblocks(allow_unsupported=True)]
|
||||
six.assertCountEqual(
|
||||
self,
|
||||
self.assertCountEqual(
|
||||
["survey", "done", "problem", "problem", "problem", "html", "split_module"],
|
||||
authorable_xblock_names
|
||||
)
|
||||
|
||||
@@ -26,7 +26,7 @@ class UserServiceTestCase(TestCase):
|
||||
Tests for the DjangoXBlockUserService.
|
||||
"""
|
||||
def setUp(self):
|
||||
super(UserServiceTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory(username="tester", email="test@tester.com")
|
||||
self.user.profile.name = "Test Tester"
|
||||
set_user_preference(self.user, 'pref-lang', 'en')
|
||||
@@ -52,7 +52,7 @@ class UserServiceTestCase(TestCase):
|
||||
assert xb_user.opt_attrs[ATTR_KEY_USERNAME] == dj_user.username
|
||||
assert xb_user.opt_attrs[ATTR_KEY_USER_ID] == dj_user.id
|
||||
assert not xb_user.opt_attrs[ATTR_KEY_USER_IS_STAFF]
|
||||
assert all(((pref in USER_PREFERENCES_WHITE_LIST) for pref in xb_user.opt_attrs[ATTR_KEY_USER_PREFERENCES]))
|
||||
assert all((pref in USER_PREFERENCES_WHITE_LIST) for pref in xb_user.opt_attrs[ATTR_KEY_USER_PREFERENCES])
|
||||
|
||||
def test_convert_anon_user(self):
|
||||
"""
|
||||
|
||||
@@ -24,7 +24,7 @@ class DjangoXBlockUserService(UserService):
|
||||
A user service that converts Django users to XBlockUser
|
||||
"""
|
||||
def __init__(self, django_user, **kwargs):
|
||||
super(DjangoXBlockUserService, self).__init__(**kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(**kwargs)
|
||||
self._django_user = django_user
|
||||
if self._django_user:
|
||||
self._django_user.user_is_staff = kwargs.get('user_is_staff', False)
|
||||
|
||||
Reference in New Issue
Block a user