BOM-2358 : Pyupgrade in dashboard, debug, discussion apps (#26529)
* Python code cleanup by the cleanup-python-code Jenkins job. This pull request was generated by the cleanup-python-code Jenkins job, which ran ``` cd lms/djangoapps/dashboard; find . -type f -name '*.py' | while read fname; do sed -i 's/ # lint-amnesty, pylint: disable=super-with-arguments//; s/ # lint-amnesty, pylint: disable=import-error, wrong-import-order//; s/ # lint-amnesty, pylint: disable=wrong-import-order//' "$fname"; done; find . -type f -name '*.py' | while read fname; do pyupgrade --exit-zero-even-if-changed --py3-plus --py36-plus --py38-plus "$fname"; done; isort --recursive . ``` The following packages were installed: `pyupgrade,isort` * feedback done Co-authored-by: Zulqarnain <muhammad.zulqarnain@arbisoft.com>
This commit is contained in:
committed by
GitHub
parent
e505d99237
commit
f33f12bbea
@@ -17,9 +17,9 @@ from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from six import StringIO
|
||||
from xmodule.util.sandboxing import DEFAULT_PYTHON_LIB_FILENAME
|
||||
|
||||
from lms.djangoapps.dashboard.models import CourseImportLog
|
||||
from xmodule.util.sandboxing import DEFAULT_PYTHON_LIB_FILENAME
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -35,7 +35,7 @@ class GitImportError(Exception):
|
||||
def __init__(self, message=None):
|
||||
if message is None:
|
||||
message = self.MESSAGE
|
||||
super(GitImportError, self).__init__(message) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(message)
|
||||
|
||||
|
||||
class GitImportErrorNoDir(GitImportError):
|
||||
@@ -43,11 +43,11 @@ class GitImportErrorNoDir(GitImportError):
|
||||
GitImportError when no directory exists at the specified path.
|
||||
"""
|
||||
def __init__(self, repo_dir):
|
||||
super(GitImportErrorNoDir, self).__init__( # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(
|
||||
_(
|
||||
u"Path {0} doesn't exist, please create it, "
|
||||
u"or configure a different path with "
|
||||
u"GIT_REPO_DIR"
|
||||
"Path {0} doesn't exist, please create it, "
|
||||
"or configure a different path with "
|
||||
"GIT_REPO_DIR"
|
||||
).format(repo_dir)
|
||||
)
|
||||
|
||||
@@ -118,8 +118,8 @@ def cmd_log(cmd, cwd):
|
||||
"""
|
||||
output = subprocess.check_output(cmd, cwd=cwd, stderr=subprocess.STDOUT).decode('utf-8')
|
||||
|
||||
log.debug(u'Command was: %r. Working directory was: %r', ' '.join(cmd), cwd)
|
||||
log.debug(u'Command output was: %r', output)
|
||||
log.debug('Command was: %r. Working directory was: %r', ' '.join(cmd), cwd)
|
||||
log.debug('Command output was: %r', output)
|
||||
return output
|
||||
|
||||
|
||||
@@ -135,15 +135,15 @@ def switch_branch(branch, rdir):
|
||||
try:
|
||||
cmd_log(['git', 'fetch', ], rdir)
|
||||
except subprocess.CalledProcessError as ex:
|
||||
log.exception(u'Unable to fetch remote: %r', ex.output)
|
||||
log.exception('Unable to fetch remote: %r', ex.output)
|
||||
raise GitImportErrorCannotBranch() # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
# Check if the branch is available from the remote.
|
||||
cmd = ['git', 'ls-remote', 'origin', '-h', 'refs/heads/{0}'.format(branch), ]
|
||||
cmd = ['git', 'ls-remote', 'origin', '-h', f'refs/heads/{branch}', ]
|
||||
try:
|
||||
output = cmd_log(cmd, rdir)
|
||||
except subprocess.CalledProcessError as ex:
|
||||
log.exception(u'Getting a list of remote branches failed: %r', ex.output)
|
||||
log.exception('Getting a list of remote branches failed: %r', ex.output)
|
||||
raise GitImportErrorCannotBranch() # lint-amnesty, pylint: disable=raise-missing-from
|
||||
if branch not in output:
|
||||
raise GitImportErrorRemoteBranchMissing()
|
||||
@@ -152,7 +152,7 @@ def switch_branch(branch, rdir):
|
||||
try:
|
||||
output = cmd_log(cmd, rdir)
|
||||
except subprocess.CalledProcessError as ex:
|
||||
log.exception(u'Getting a list of local branches failed: %r', ex.output)
|
||||
log.exception('Getting a list of local branches failed: %r', ex.output)
|
||||
raise GitImportErrorCannotBranch() # lint-amnesty, pylint: disable=raise-missing-from
|
||||
branches = []
|
||||
for line in output.split('\n'):
|
||||
@@ -161,18 +161,18 @@ def switch_branch(branch, rdir):
|
||||
if branch not in branches:
|
||||
# Checkout with -b since it is remote only
|
||||
cmd = ['git', 'checkout', '--force', '--track',
|
||||
'-b', branch, 'origin/{0}'.format(branch), ]
|
||||
'-b', branch, f'origin/{branch}', ]
|
||||
try:
|
||||
cmd_log(cmd, rdir)
|
||||
except subprocess.CalledProcessError as ex:
|
||||
log.exception(u'Unable to checkout remote branch: %r', ex.output)
|
||||
log.exception('Unable to checkout remote branch: %r', ex.output)
|
||||
raise GitImportErrorCannotBranch() # lint-amnesty, pylint: disable=raise-missing-from
|
||||
# Go ahead and reset hard to the newest version of the branch now that we know
|
||||
# it is local.
|
||||
try:
|
||||
cmd_log(['git', 'reset', '--hard', 'origin/{0}'.format(branch), ], rdir)
|
||||
cmd_log(['git', 'reset', '--hard', f'origin/{branch}', ], rdir)
|
||||
except subprocess.CalledProcessError as ex:
|
||||
log.exception(u'Unable to reset to branch: %r', ex.output)
|
||||
log.exception('Unable to reset to branch: %r', ex.output)
|
||||
raise GitImportErrorCannotBranch() # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
|
||||
@@ -215,9 +215,9 @@ def add_repo(repo, rdir_in, branch=None):
|
||||
rdir = os.path.basename(rdir_in)
|
||||
else:
|
||||
rdir = repo.rsplit('/', 1)[-1].rsplit('.git', 1)[0]
|
||||
log.debug(u'rdir = %s', rdir)
|
||||
log.debug('rdir = %s', rdir)
|
||||
|
||||
rdirp = '{0}/{1}'.format(git_repo_dir, rdir)
|
||||
rdirp = f'{git_repo_dir}/{rdir}'
|
||||
if os.path.exists(rdirp):
|
||||
log.info('directory already exists, doing a git pull instead '
|
||||
'of git clone')
|
||||
@@ -231,7 +231,7 @@ def add_repo(repo, rdir_in, branch=None):
|
||||
try:
|
||||
ret_git = cmd_log(cmd, cwd=cwd)
|
||||
except subprocess.CalledProcessError as ex:
|
||||
log.exception(u'Error running git pull: %r', ex.output)
|
||||
log.exception('Error running git pull: %r', ex.output)
|
||||
raise GitImportErrorCannotPull() # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
if branch:
|
||||
@@ -242,10 +242,10 @@ def add_repo(repo, rdir_in, branch=None):
|
||||
try:
|
||||
commit_id = cmd_log(cmd, cwd=rdirp)
|
||||
except subprocess.CalledProcessError as ex:
|
||||
log.exception(u'Unable to get git log: %r', ex.output)
|
||||
log.exception('Unable to get git log: %r', ex.output)
|
||||
raise GitImportErrorBadRepo() # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
ret_git += u'\nCommit ID: {0}'.format(commit_id)
|
||||
ret_git += f'\nCommit ID: {commit_id}'
|
||||
|
||||
# get branch
|
||||
cmd = ['git', 'symbolic-ref', '--short', 'HEAD', ]
|
||||
@@ -254,10 +254,10 @@ def add_repo(repo, rdir_in, branch=None):
|
||||
except subprocess.CalledProcessError as ex:
|
||||
# I can't discover a way to excercise this, but git is complex
|
||||
# so still logging and raising here in case.
|
||||
log.exception(u'Unable to determine branch: %r', ex.output)
|
||||
log.exception('Unable to determine branch: %r', ex.output)
|
||||
raise GitImportErrorBadRepo() # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
ret_git += u'{0}Branch: {1}'.format(' \n', branch)
|
||||
ret_git += '{}Branch: {}'.format(' \n', branch)
|
||||
|
||||
# Get XML logging logger and capture debug to parse results
|
||||
output = StringIO()
|
||||
@@ -306,8 +306,8 @@ def add_repo(repo, rdir_in, branch=None):
|
||||
# We want set course id in CourseImportLog as CourseLocator. So that in split module
|
||||
# environment course id remain consistent as CourseLocator instance.
|
||||
course_key = CourseLocator(*course_id)
|
||||
cdir = '{0}/{1}'.format(git_repo_dir, course_key.course)
|
||||
log.debug(u'Studio course dir = %s', cdir)
|
||||
cdir = f'{git_repo_dir}/{course_key.course}'
|
||||
log.debug('Studio course dir = %s', cdir)
|
||||
|
||||
if os.path.exists(cdir) and not os.path.islink(cdir):
|
||||
log.debug(' -> exists, but is not symlink')
|
||||
@@ -319,7 +319,7 @@ def add_repo(repo, rdir_in, branch=None):
|
||||
log.exception('Failed to remove course directory')
|
||||
|
||||
if not os.path.exists(cdir):
|
||||
log.debug(u' -> creating symlink between %s and %s', rdirp, cdir)
|
||||
log.debug(' -> creating symlink between %s and %s', rdirp, cdir)
|
||||
try:
|
||||
os.symlink(os.path.abspath(rdirp), os.path.abspath(cdir))
|
||||
except OSError:
|
||||
@@ -348,5 +348,5 @@ def add_repo(repo, rdir_in, branch=None):
|
||||
)
|
||||
cil.save()
|
||||
|
||||
log.debug(u'saved CourseImportLog for %s', cil.course_id)
|
||||
log.debug('saved CourseImportLog for %s', cil.course_id)
|
||||
mdb.close()
|
||||
|
||||
@@ -7,11 +7,11 @@ import logging
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from lms.djangoapps.dashboard import git_import
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.xml import XMLModuleStore
|
||||
|
||||
from lms.djangoapps.dashboard import git_import
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ class Command(BaseCommand):
|
||||
# to store the courses for use on the Web site.
|
||||
help = ('Usage: '
|
||||
'git_add_course repository_url [directory to check out into] [repository_branch] '
|
||||
'\n{0}'.format(_('Import the specified git repository and optional branch into the '
|
||||
'modulestore and optionally specified directory.')))
|
||||
'\n{}'.format(_('Import the specified git repository and optional branch into the '
|
||||
'modulestore and optionally specified directory.')))
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# Positional arguments
|
||||
|
||||
@@ -16,6 +16,10 @@ from django.core.management.base import CommandError
|
||||
from django.test.utils import override_settings
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from six import StringIO
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.mongo_connection import MONGO_HOST, MONGO_PORT_NUM
|
||||
|
||||
import lms.djangoapps.dashboard.git_import as git_import
|
||||
from lms.djangoapps.dashboard.git_import import (
|
||||
@@ -26,10 +30,6 @@ from lms.djangoapps.dashboard.git_import import (
|
||||
GitImportErrorRemoteBranchMissing,
|
||||
GitImportErrorUrlBad
|
||||
)
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.mongo_connection import MONGO_HOST, MONGO_PORT_NUM
|
||||
TEST_MONGODB_LOG = {
|
||||
'host': MONGO_HOST,
|
||||
'port': MONGO_PORT_NUM,
|
||||
@@ -41,7 +41,7 @@ TEST_MONGODB_LOG = {
|
||||
|
||||
@override_settings(
|
||||
MONGODB_LOG=TEST_MONGODB_LOG,
|
||||
GIT_REPO_DIR=settings.TEST_ROOT / "course_repos_{}".format(uuid4().hex)
|
||||
GIT_REPO_DIR=settings.TEST_ROOT / f"course_repos_{uuid4().hex}"
|
||||
)
|
||||
@unittest.skipUnless(settings.FEATURES.get('ENABLE_SYSADMIN_DASHBOARD'),
|
||||
"ENABLE_SYSADMIN_DASHBOARD not set")
|
||||
@@ -57,7 +57,7 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
|
||||
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
|
||||
|
||||
def setUp(self):
|
||||
super(TestGitAddCourse, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.git_repo_dir = settings.GIT_REPO_DIR
|
||||
|
||||
def assertCommandFailureRegexp(self, regex, *args):
|
||||
@@ -72,17 +72,14 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
|
||||
Validate argument checking
|
||||
"""
|
||||
# No argument given.
|
||||
if six.PY2:
|
||||
self.assertCommandFailureRegexp('Error: too few arguments')
|
||||
else:
|
||||
self.assertCommandFailureRegexp('Error: the following arguments are required: repository_url')
|
||||
self.assertCommandFailureRegexp('Error: the following arguments are required: repository_url')
|
||||
# Extra/Un-named arguments given.
|
||||
self.assertCommandFailureRegexp(
|
||||
'Error: unrecognized arguments: blah blah blah',
|
||||
'blah', 'blah', 'blah', 'blah')
|
||||
# Not a valid path.
|
||||
self.assertCommandFailureRegexp(
|
||||
u'Path {0} doesn\'t exist, please create it,'.format(self.git_repo_dir),
|
||||
f'Path {self.git_repo_dir} doesn\'t exist, please create it,',
|
||||
'blah')
|
||||
# Test successful import from command
|
||||
if not os.path.isdir(self.git_repo_dir):
|
||||
@@ -119,14 +116,14 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
|
||||
git_import.add_repo('file:///foobar.git', None, None)
|
||||
|
||||
# Test git repo that exists, but is "broken"
|
||||
bare_repo = os.path.abspath('{0}/{1}'.format(settings.TEST_ROOT, 'bare.git'))
|
||||
bare_repo = os.path.abspath('{}/{}'.format(settings.TEST_ROOT, 'bare.git'))
|
||||
os.mkdir(bare_repo)
|
||||
self.addCleanup(shutil.rmtree, bare_repo)
|
||||
subprocess.check_output(['git', '--bare', 'init', ], stderr=subprocess.STDOUT,
|
||||
cwd=bare_repo)
|
||||
|
||||
with pytest.raises(GitImportErrorBadRepo):
|
||||
git_import.add_repo('file://{0}'.format(bare_repo), None, None)
|
||||
git_import.add_repo(f'file://{bare_repo}', None, None)
|
||||
|
||||
def test_detached_repo(self):
|
||||
"""
|
||||
@@ -188,7 +185,7 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
|
||||
This wil create conditions to exercise bad paths in the switch_branch function.
|
||||
"""
|
||||
# create bare repo that we can mess with and attempt an import
|
||||
bare_repo = os.path.abspath('{0}/{1}'.format(settings.TEST_ROOT, 'bare.git'))
|
||||
bare_repo = os.path.abspath('{}/{}'.format(settings.TEST_ROOT, 'bare.git'))
|
||||
os.mkdir(bare_repo)
|
||||
self.addCleanup(shutil.rmtree, bare_repo)
|
||||
subprocess.check_output(['git', '--bare', 'init', ], stderr=subprocess.STDOUT,
|
||||
@@ -202,7 +199,7 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
|
||||
|
||||
rdir = '{0}/bare'.format(repo_dir)
|
||||
with pytest.raises(GitImportErrorBadRepo):
|
||||
git_import.add_repo('file://{0}'.format(bare_repo), None, None)
|
||||
git_import.add_repo(f'file://{bare_repo}', None, None)
|
||||
|
||||
# Get logger for checking strings in logs
|
||||
output = StringIO()
|
||||
@@ -212,12 +209,12 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
|
||||
glog.addHandler(test_log_handler)
|
||||
|
||||
# Move remote so fetch fails
|
||||
shutil.move(bare_repo, '{0}/not_bare.git'.format(settings.TEST_ROOT))
|
||||
shutil.move(bare_repo, f'{settings.TEST_ROOT}/not_bare.git')
|
||||
try:
|
||||
git_import.switch_branch('master', rdir)
|
||||
except GitImportError:
|
||||
assert 'Unable to fetch remote' in output.getvalue()
|
||||
shutil.move('{0}/not_bare.git'.format(settings.TEST_ROOT), bare_repo)
|
||||
shutil.move(f'{settings.TEST_ROOT}/not_bare.git', bare_repo)
|
||||
output.truncate(0)
|
||||
|
||||
# Replace origin with a different remote
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
|
||||
import mongoengine
|
||||
|
||||
from xmodule.modulestore.mongoengine_fields import CourseKeyField
|
||||
|
||||
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
This module creates a sysadmin dashboard for managing and viewing
|
||||
courses.
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import warnings
|
||||
from io import StringIO
|
||||
|
||||
import mongoengine
|
||||
from django.conf import settings
|
||||
@@ -26,18 +25,17 @@ from django.views.decorators.http import condition
|
||||
from django.views.generic.base import TemplateView
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from path import Path as path
|
||||
from six import StringIO, text_type
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
import lms.djangoapps.dashboard.git_import as git_import
|
||||
from common.djangoapps.track import views as track_views
|
||||
from lms.djangoapps.dashboard.git_import import GitImportError
|
||||
from lms.djangoapps.dashboard.models import CourseImportLog
|
||||
from common.djangoapps.edxmako.shortcuts import render_to_response
|
||||
from lms.djangoapps.courseware.courses import get_course_by_id
|
||||
from openedx.core.djangolib.markup import HTML
|
||||
from common.djangoapps.student.models import CourseEnrollment, Registration, UserProfile
|
||||
from common.djangoapps.student.roles import CourseInstructorRole, CourseStaffRole
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from common.djangoapps.track import views as track_views
|
||||
from lms.djangoapps.courseware.courses import get_course_by_id
|
||||
from lms.djangoapps.dashboard.git_import import GitImportError
|
||||
from lms.djangoapps.dashboard.models import CourseImportLog
|
||||
from openedx.core.djangolib.markup import HTML
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -56,9 +54,9 @@ class SysadminDashboardView(TemplateView):
|
||||
warnings.warn("Sysadmin Dashboard is deprecated. See DEPR-118.", DeprecationWarning)
|
||||
|
||||
self.def_ms = modulestore()
|
||||
self.msg = u''
|
||||
self.msg = ''
|
||||
self.datatable = []
|
||||
super(SysadminDashboardView, self).__init__(**kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(**kwargs)
|
||||
|
||||
@method_decorator(ensure_csrf_cookie)
|
||||
@method_decorator(login_required)
|
||||
@@ -66,7 +64,7 @@ class SysadminDashboardView(TemplateView):
|
||||
must_revalidate=True))
|
||||
@method_decorator(condition(etag_func=None))
|
||||
def dispatch(self, *args, **kwargs):
|
||||
return super(SysadminDashboardView, self).dispatch(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
return super().dispatch(*args, **kwargs)
|
||||
|
||||
def get_courses(self):
|
||||
""" Get an iterable list of courses."""
|
||||
@@ -88,7 +86,7 @@ class Users(SysadminDashboardView):
|
||||
if not name:
|
||||
return _('Must provide full name')
|
||||
|
||||
msg = u''
|
||||
msg = ''
|
||||
if not password:
|
||||
return _('Password must be supplied')
|
||||
|
||||
@@ -104,7 +102,7 @@ class Users(SysadminDashboardView):
|
||||
try:
|
||||
user.save()
|
||||
except IntegrityError:
|
||||
msg += _(u'Oops, failed to create user {user}, {error}').format(
|
||||
msg += _('Oops, failed to create user {user}, {error}').format(
|
||||
user=user,
|
||||
error="IntegrityError"
|
||||
)
|
||||
@@ -117,7 +115,7 @@ class Users(SysadminDashboardView):
|
||||
profile.name = name
|
||||
profile.save()
|
||||
|
||||
msg += _(u'User {user} created successfully!').format(user=user)
|
||||
msg += _('User {user} created successfully!').format(user=user)
|
||||
return msg
|
||||
|
||||
def delete_user(self, uname):
|
||||
@@ -129,19 +127,19 @@ class Users(SysadminDashboardView):
|
||||
try:
|
||||
user = User.objects.get(email=uname)
|
||||
except User.DoesNotExist as err:
|
||||
msg = _(u'Cannot find user with email address {email_addr}').format(email_addr=uname)
|
||||
msg = _('Cannot find user with email address {email_addr}').format(email_addr=uname)
|
||||
return msg
|
||||
else:
|
||||
try:
|
||||
user = User.objects.get(username=uname)
|
||||
except User.DoesNotExist as err:
|
||||
msg = _(u'Cannot find user with username {username} - {error}').format(
|
||||
msg = _('Cannot find user with username {username} - {error}').format(
|
||||
username=uname,
|
||||
error=str(err)
|
||||
)
|
||||
return msg
|
||||
user.delete()
|
||||
return _(u'Deleted user {username}').format(username=uname)
|
||||
return _('Deleted user {username}').format(username=uname)
|
||||
|
||||
def make_datatable(self):
|
||||
"""
|
||||
@@ -185,12 +183,12 @@ class Users(SysadminDashboardView):
|
||||
uname = request.POST.get('student_uname', '').strip()
|
||||
name = request.POST.get('student_fullname', '').strip()
|
||||
password = request.POST.get('student_password', '').strip()
|
||||
self.msg = HTML(u'<h4>{0}</h4><p>{1}</p><hr />{2}').format(
|
||||
self.msg = HTML('<h4>{0}</h4><p>{1}</p><hr />{2}').format(
|
||||
_('Create User Results'),
|
||||
self.create_user(uname, name, password), self.msg)
|
||||
elif action == 'del_user':
|
||||
uname = request.POST.get('student_uname', '').strip()
|
||||
self.msg = HTML(u'<h4>{0}</h4><p>{1}</p><hr />{2}').format(
|
||||
self.msg = HTML('<h4>{0}</h4><p>{1}</p><hr />{2}').format(
|
||||
_('Delete User Results'), self.delete_user(uname), self.msg)
|
||||
context = {
|
||||
'datatable': self.make_datatable(),
|
||||
@@ -222,14 +220,14 @@ class Courses(SysadminDashboardView):
|
||||
return info
|
||||
|
||||
cmd = ['git', 'log', '-1',
|
||||
u'--format=format:{ "commit": "%H", "author": "%an %ae", "date": "%ad"}', ]
|
||||
'--format=format:{ "commit": "%H", "author": "%an %ae", "date": "%ad"}', ]
|
||||
try:
|
||||
output_json = json.loads(subprocess.check_output(cmd, cwd=gdir).decode('utf-8'))
|
||||
info = [output_json['commit'],
|
||||
output_json['date'],
|
||||
output_json['author'], ]
|
||||
except OSError as error:
|
||||
log.warning(text_type(u"Error fetching git data: %s - %s"), text_type(cdir), text_type(error))
|
||||
log.warning("Error fetching git data: %s - %s", str(cdir), str(error))
|
||||
except (ValueError, subprocess.CalledProcessError):
|
||||
pass
|
||||
|
||||
@@ -251,9 +249,9 @@ class Courses(SysadminDashboardView):
|
||||
at debug level for display in template
|
||||
"""
|
||||
|
||||
msg = u''
|
||||
msg = ''
|
||||
|
||||
log.debug(u'Adding course using git repo %s', gitloc)
|
||||
log.debug('Adding course using git repo %s', gitloc)
|
||||
|
||||
# Grab logging output for debugging imports
|
||||
output = StringIO()
|
||||
@@ -291,8 +289,8 @@ class Courses(SysadminDashboardView):
|
||||
msg_header = _('Added Course')
|
||||
color = 'blue'
|
||||
|
||||
msg = HTML(u"<h4 style='color:{0}'>{1}</h4>").format(color, msg_header)
|
||||
msg += HTML(u"<pre>{0}</pre>").format(escape(ret))
|
||||
msg = HTML("<h4 style='color:{0}'>{1}</h4>").format(color, msg_header)
|
||||
msg += HTML("<pre>{0}</pre>").format(escape(ret))
|
||||
return msg
|
||||
|
||||
def make_datatable(self, courses=None):
|
||||
@@ -302,7 +300,7 @@ class Courses(SysadminDashboardView):
|
||||
courses = courses or self.get_courses()
|
||||
for course in courses:
|
||||
gdir = course.id.course
|
||||
data.append([course.display_name, text_type(course.id)]
|
||||
data.append([course.display_name, str(course.id)]
|
||||
+ self.git_info_for_course(gdir))
|
||||
|
||||
return dict(header=[_('Course Name'),
|
||||
@@ -357,7 +355,7 @@ class Courses(SysadminDashboardView):
|
||||
course_found = True
|
||||
except Exception as err: # pylint: disable=broad-except
|
||||
self.msg += _( # lint-amnesty, pylint: disable=translation-of-non-string
|
||||
HTML(u'Error - cannot get course with ID {0}<br/><pre>{1}</pre>')
|
||||
HTML('Error - cannot get course with ID {0}<br/><pre>{1}</pre>')
|
||||
).format(
|
||||
course_key,
|
||||
escape(str(err))
|
||||
@@ -368,8 +366,8 @@ class Courses(SysadminDashboardView):
|
||||
self.def_ms.delete_course(course.id, request.user.id)
|
||||
# don't delete user permission groups, though
|
||||
self.msg += \
|
||||
HTML(u"<font color='red'>{0} {1} = {2} ({3})</font>").format(
|
||||
_('Deleted'), text_type(course.location), text_type(course.id), course.display_name)
|
||||
HTML("<font color='red'>{0} {1} = {2} ({3})</font>").format(
|
||||
_('Deleted'), str(course.location), str(course.id), course.display_name)
|
||||
|
||||
context = {
|
||||
'datatable': self.make_datatable(list(courses.values())),
|
||||
@@ -477,7 +475,7 @@ class GitLogs(TemplateView):
|
||||
cilset = CourseImportLog.objects.filter(
|
||||
course_id=course_id
|
||||
).order_by('-created')
|
||||
log.debug(u'cilset length=%s', len(cilset))
|
||||
log.debug('cilset length=%s', len(cilset))
|
||||
|
||||
# Paginate the query set
|
||||
paginator = Paginator(cilset, page_size)
|
||||
@@ -494,7 +492,7 @@ class GitLogs(TemplateView):
|
||||
mdb.close()
|
||||
context = {
|
||||
'logs': logs,
|
||||
'course_id': text_type(course_id) if course_id else None,
|
||||
'course_id': str(course_id) if course_id else None,
|
||||
'error_msg': error_msg,
|
||||
'page_size': page_size
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"""
|
||||
Provide tests for sysadmin dashboard feature in sysadmin.py
|
||||
"""
|
||||
|
||||
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
@@ -18,19 +16,17 @@ from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from pytz import UTC
|
||||
from six import text_type
|
||||
from six.moves import range
|
||||
|
||||
from lms.djangoapps.dashboard.git_import import GitImportErrorNoDir
|
||||
from lms.djangoapps.dashboard.models import CourseImportLog
|
||||
from openedx.core.djangolib.markup import Text
|
||||
from common.djangoapps.student.roles import CourseStaffRole, GlobalStaff
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from common.djangoapps.util.date_utils import DEFAULT_DATE_TIME_FORMAT, get_time_display
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.mongo_connection import MONGO_HOST, MONGO_PORT_NUM
|
||||
|
||||
from common.djangoapps.student.roles import CourseStaffRole, GlobalStaff
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from common.djangoapps.util.date_utils import DEFAULT_DATE_TIME_FORMAT, get_time_display
|
||||
from lms.djangoapps.dashboard.git_import import GitImportErrorNoDir
|
||||
from lms.djangoapps.dashboard.models import CourseImportLog
|
||||
from openedx.core.djangolib.markup import Text
|
||||
|
||||
TEST_MONGODB_LOG = {
|
||||
'host': MONGO_HOST,
|
||||
'port': MONGO_PORT_NUM,
|
||||
@@ -52,7 +48,7 @@ class SysadminBaseTestCase(SharedModuleStoreTestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""Setup test case by adding primary user."""
|
||||
super(SysadminBaseTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory.create(username='test_user',
|
||||
email='test_user+sysadmin@edx.org',
|
||||
password='foo')
|
||||
@@ -73,7 +69,7 @@ class SysadminBaseTestCase(SharedModuleStoreTestCase):
|
||||
def _rm_edx4edx(self):
|
||||
"""Deletes the sample course from the XML store"""
|
||||
def_ms = modulestore()
|
||||
course_path = '{0}/edx4edx_lite'.format(
|
||||
course_path = '{}/edx4edx_lite'.format(
|
||||
os.path.abspath(settings.DATA_DIR))
|
||||
try:
|
||||
# using XML store
|
||||
@@ -86,11 +82,11 @@ class SysadminBaseTestCase(SharedModuleStoreTestCase):
|
||||
response = self.client.post(
|
||||
reverse('sysadmin_courses'),
|
||||
{
|
||||
'course_id': text_type(course.id),
|
||||
'course_id': str(course.id),
|
||||
'action': 'del_course',
|
||||
}
|
||||
)
|
||||
self.addCleanup(self._rm_glob, '{0}_deleted_*'.format(course_path))
|
||||
self.addCleanup(self._rm_glob, f'{course_path}_deleted_*')
|
||||
|
||||
return response
|
||||
|
||||
@@ -112,7 +108,7 @@ class SysadminBaseTestCase(SharedModuleStoreTestCase):
|
||||
|
||||
@override_settings(
|
||||
MONGODB_LOG=TEST_MONGODB_LOG,
|
||||
GIT_REPO_DIR=settings.TEST_ROOT / "course_repos_{}".format(uuid4().hex)
|
||||
GIT_REPO_DIR=settings.TEST_ROOT / f"course_repos_{uuid4().hex}"
|
||||
)
|
||||
@unittest.skipUnless(settings.FEATURES.get('ENABLE_SYSADMIN_DASHBOARD'),
|
||||
"ENABLE_SYSADMIN_DASHBOARD not set")
|
||||
@@ -124,7 +120,7 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase):
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
"""Delete mongo log entries after test."""
|
||||
super(TestSysAdminMongoCourseImport, cls).tearDownClass()
|
||||
super().tearDownClass()
|
||||
try:
|
||||
mongoengine.connect(TEST_MONGODB_LOG['db'])
|
||||
CourseImportLog.objects.all().delete()
|
||||
@@ -153,7 +149,7 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase):
|
||||
|
||||
# Create git loaded course
|
||||
response = self._add_edx4edx()
|
||||
self.assertContains(response, Text(text_type(GitImportErrorNoDir(settings.GIT_REPO_DIR))))
|
||||
self.assertContains(response, Text(str(GitImportErrorNoDir(settings.GIT_REPO_DIR))))
|
||||
|
||||
def test_mongo_course_add_delete(self):
|
||||
"""
|
||||
@@ -182,7 +178,7 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase):
|
||||
# Regex of first 3 columns of course information table row for
|
||||
# test course loaded from git. Would not have sha1 if
|
||||
# git_info_for_course failed.
|
||||
table_re = re.compile(u"""
|
||||
table_re = re.compile("""
|
||||
<tr>\\s+
|
||||
<td>edX\\sAuthor\\sCourse</td>\\s+ # expected test git course name
|
||||
<td>course-v1:MITx\\+edx4edx\\+edx4edx</td>\\s+ # expected test git course_id
|
||||
@@ -314,7 +310,7 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase):
|
||||
page
|
||||
)
|
||||
)
|
||||
self.assertContains(response, u'Page {} of 2'.format(expected))
|
||||
self.assertContains(response, f'Page {expected} of 2')
|
||||
|
||||
CourseImportLog.objects.delete()
|
||||
|
||||
|
||||
@@ -6,15 +6,11 @@ For each of the courses, it loops through all of the modules, and dumps
|
||||
each as a separate output file containing the json representation
|
||||
of each of its fields (including those fields that are set as default values).
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from path import Path as path
|
||||
from six import text_type
|
||||
|
||||
from xmodule.modulestore.xml import XMLModuleStore
|
||||
|
||||
@@ -28,7 +24,7 @@ class Command(BaseCommand):
|
||||
|
||||
def handle(self, *args, **options):
|
||||
if len(args) != 1:
|
||||
raise CommandError(u'Must called with arguments: {}'.format(self.args))
|
||||
raise CommandError(f'Must called with arguments: {self.args}')
|
||||
|
||||
xml_module_store = XMLModuleStore(
|
||||
data_dir=settings.DATA_DIR,
|
||||
@@ -40,12 +36,12 @@ class Command(BaseCommand):
|
||||
|
||||
export_dir = path(args[0])
|
||||
|
||||
for course_id, course_modules in six.iteritems(xml_module_store.modules):
|
||||
for course_id, course_modules in xml_module_store.modules.items():
|
||||
course_path = course_id.replace('/', '_')
|
||||
for location, descriptor in six.iteritems(course_modules):
|
||||
location_path = text_type(location).replace('/', '_')
|
||||
for location, descriptor in course_modules.items():
|
||||
location_path = str(location).replace('/', '_')
|
||||
data = {}
|
||||
for field_name, field in six.iteritems(descriptor.fields):
|
||||
for field_name, field in descriptor.fields.items():
|
||||
try:
|
||||
data[field_name] = field.read_json(descriptor)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
import pprint
|
||||
import traceback
|
||||
|
||||
from codejail.safe_exec import safe_exec
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.utils.html import escape
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
|
||||
from codejail.safe_exec import safe_exec
|
||||
from common.djangoapps.edxmako.shortcuts import render_to_response
|
||||
from openedx.core.djangolib.markup import HTML
|
||||
|
||||
@@ -52,7 +52,7 @@ def show_parameters(request):
|
||||
"""A page that shows what parameters were on the URL and post."""
|
||||
html_list = []
|
||||
for name, value in sorted(request.GET.items()):
|
||||
html_list.append(escape(u"GET {}: {!r}".format(name, value)))
|
||||
html_list.append(escape(f"GET {name}: {value!r}"))
|
||||
for name, value in sorted(request.POST.items()):
|
||||
html_list.append(escape(u"POST {}: {!r}".format(name, value)))
|
||||
html_list.append(escape(f"POST {name}: {value!r}"))
|
||||
return HttpResponse("\n".join(HTML("<p>{}</p>").format(h) for h in html_list))
|
||||
|
||||
@@ -17,21 +17,21 @@ class DiscussionConfig(AppConfig):
|
||||
Application Configuration for Discussion.
|
||||
"""
|
||||
|
||||
name = u'lms.djangoapps.discussion'
|
||||
name = 'lms.djangoapps.discussion'
|
||||
plugin_app = {
|
||||
PluginURLs.CONFIG: {
|
||||
ProjectType.LMS: {
|
||||
PluginURLs.NAMESPACE: u'',
|
||||
PluginURLs.REGEX: r'^courses/{}/discussion/forum/'.format(COURSE_ID_PATTERN),
|
||||
PluginURLs.RELATIVE_PATH: u'urls',
|
||||
PluginURLs.NAMESPACE: '',
|
||||
PluginURLs.REGEX: fr'^courses/{COURSE_ID_PATTERN}/discussion/forum/',
|
||||
PluginURLs.RELATIVE_PATH: 'urls',
|
||||
}
|
||||
},
|
||||
PluginSettings.CONFIG: {
|
||||
ProjectType.CMS: {
|
||||
SettingsType.COMMON: {PluginSettings.RELATIVE_PATH: u'settings.common'},
|
||||
SettingsType.COMMON: {PluginSettings.RELATIVE_PATH: 'settings.common'},
|
||||
},
|
||||
ProjectType.LMS: {
|
||||
SettingsType.COMMON: {PluginSettings.RELATIVE_PATH: u'settings.common'},
|
||||
SettingsType.COMMON: {PluginSettings.RELATIVE_PATH: 'settings.common'},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,20 +2,17 @@
|
||||
"""
|
||||
Transformers for Discussion-related events.
|
||||
"""
|
||||
|
||||
|
||||
import six
|
||||
from django.contrib.auth.models import User
|
||||
from django.urls import NoReverseMatch, reverse
|
||||
from eventtracking.processors.exceptions import EventEmissionExit
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
|
||||
from common.djangoapps.track.transformers import EventTransformer, EventTransformerRegistry
|
||||
from common.djangoapps.track.views.segmentio import BI_SCREEN_VIEWED_EVENT_NAME, FORUM_THREAD_VIEWED_EVENT_LABEL
|
||||
from lms.djangoapps.discussion.django_comment_client.base.views import add_truncated_title_to_event_data
|
||||
from lms.djangoapps.discussion.django_comment_client.permissions import get_team
|
||||
from lms.djangoapps.discussion.django_comment_client.utils import get_cached_discussion_id_map_by_course_id
|
||||
from common.djangoapps.track.transformers import EventTransformer, EventTransformerRegistry
|
||||
from common.djangoapps.track.views.segmentio import BI_SCREEN_VIEWED_EVENT_NAME, FORUM_THREAD_VIEWED_EVENT_LABEL
|
||||
|
||||
|
||||
def _get_string(dictionary, key, del_if_bad=True):
|
||||
@@ -28,7 +25,7 @@ def _get_string(dictionary, key, del_if_bad=True):
|
||||
"""
|
||||
if key in dictionary:
|
||||
value = dictionary[key]
|
||||
if isinstance(value, six.string_types):
|
||||
if isinstance(value, str):
|
||||
return value
|
||||
else:
|
||||
if del_if_bad:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import pytest
|
||||
# pylint: skip-file
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tests for django comment client views."""
|
||||
|
||||
|
||||
@@ -10,7 +9,6 @@ from contextlib import contextmanager
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
import six
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.management import call_command
|
||||
from django.test.client import RequestFactory
|
||||
@@ -18,12 +16,16 @@ from django.urls import reverse
|
||||
from eventtracking.processors.exceptions import EventEmissionExit
|
||||
from mock import ANY, Mock, patch
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from six import text_type
|
||||
from six.moves import range
|
||||
|
||||
from common.test.utils import MockSignalHandlerMixin, disable_signal
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
|
||||
from common.djangoapps.student.roles import CourseStaffRole, UserBasedRole
|
||||
from common.djangoapps.student.tests.factories import CourseAccessRoleFactory, CourseEnrollmentFactory, UserFactory
|
||||
from common.djangoapps.track.middleware import TrackMiddleware
|
||||
from common.djangoapps.track.views import segmentio
|
||||
from common.djangoapps.track.views.tests.base import SEGMENTIO_TEST_USER_ID, SegmentIOTrackingTestCaseBase
|
||||
from common.djangoapps.util.testing import UrlResetMixin
|
||||
from common.test.utils import MockSignalHandlerMixin, disable_signal
|
||||
from lms.djangoapps.discussion.django_comment_client.base import views
|
||||
from lms.djangoapps.discussion.django_comment_client.tests.group_id import (
|
||||
CohortedTopicGroupIdTestMixin,
|
||||
@@ -49,12 +51,6 @@ from openedx.core.djangoapps.django_comment_common.utils import (
|
||||
)
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES
|
||||
from openedx.core.lib.teams_config import TeamsConfig
|
||||
from common.djangoapps.student.roles import CourseStaffRole, UserBasedRole
|
||||
from common.djangoapps.student.tests.factories import CourseAccessRoleFactory, CourseEnrollmentFactory, UserFactory
|
||||
from common.djangoapps.track.middleware import TrackMiddleware
|
||||
from common.djangoapps.track.views import segmentio
|
||||
from common.djangoapps.track.views.tests.base import SEGMENTIO_TEST_USER_ID, SegmentIOTrackingTestCaseBase
|
||||
from common.djangoapps.util.testing import UrlResetMixin
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase
|
||||
@@ -71,7 +67,7 @@ QUERY_COUNT_TABLE_BLACKLIST = WAFFLE_TABLES
|
||||
# pylint: disable=missing-docstring
|
||||
|
||||
|
||||
class MockRequestSetupMixin(object):
|
||||
class MockRequestSetupMixin:
|
||||
def _create_response_mock(self, data):
|
||||
return Mock(
|
||||
text=json.dumps(data),
|
||||
@@ -103,7 +99,7 @@ class CreateThreadGroupIdTestCase(
|
||||
|
||||
return views.create_thread(
|
||||
request,
|
||||
course_id=six.text_type(self.course.id),
|
||||
course_id=str(self.course.id),
|
||||
commentable_id=commentable_id
|
||||
)
|
||||
|
||||
@@ -150,7 +146,7 @@ class ThreadActionGroupIdTestCase(
|
||||
|
||||
return getattr(views, view_name)(
|
||||
request,
|
||||
course_id=six.text_type(self.course.id),
|
||||
course_id=str(self.course.id),
|
||||
thread_id="dummy",
|
||||
**(view_args or {})
|
||||
)
|
||||
@@ -209,7 +205,7 @@ class ThreadActionGroupIdTestCase(
|
||||
)
|
||||
|
||||
|
||||
class ViewsTestCaseMixin(object):
|
||||
class ViewsTestCaseMixin:
|
||||
|
||||
def set_up_course(self, module_count=0):
|
||||
"""
|
||||
@@ -230,13 +226,13 @@ class ViewsTestCaseMixin(object):
|
||||
ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
category='discussion',
|
||||
discussion_id='id_module_{}'.format(i),
|
||||
discussion_category=u'Category {}'.format(i),
|
||||
discussion_target=u'Discussion {}'.format(i)
|
||||
discussion_id=f'id_module_{i}',
|
||||
discussion_category=f'Category {i}',
|
||||
discussion_target=f'Discussion {i}'
|
||||
)
|
||||
|
||||
# seed the forums permissions and roles
|
||||
call_command('seed_permissions_roles', six.text_type(self.course_id))
|
||||
call_command('seed_permissions_roles', str(self.course_id))
|
||||
|
||||
# Patch the comment client user save method so it does not try
|
||||
# to create a new cc user when creating a django user
|
||||
@@ -322,24 +318,24 @@ class ViewsTestCaseMixin(object):
|
||||
if extra_request_data:
|
||||
thread.update(extra_request_data)
|
||||
url = reverse('create_thread', kwargs={'commentable_id': 'i4x-MITx-999-course-Robot_Super_Course',
|
||||
'course_id': six.text_type(self.course_id)})
|
||||
'course_id': str(self.course_id)})
|
||||
response = self.client.post(url, data=thread)
|
||||
assert mock_request.called
|
||||
expected_data = {
|
||||
'thread_type': 'discussion',
|
||||
'body': u'this is a post',
|
||||
'body': 'this is a post',
|
||||
'context': ThreadContext.COURSE,
|
||||
'anonymous_to_peers': False, 'user_id': 1,
|
||||
'title': u'Hello',
|
||||
'commentable_id': u'i4x-MITx-999-course-Robot_Super_Course',
|
||||
'title': 'Hello',
|
||||
'commentable_id': 'i4x-MITx-999-course-Robot_Super_Course',
|
||||
'anonymous': False,
|
||||
'course_id': six.text_type(self.course_id),
|
||||
'course_id': str(self.course_id),
|
||||
}
|
||||
if extra_response_data:
|
||||
expected_data.update(extra_response_data)
|
||||
mock_request.assert_called_with(
|
||||
'post',
|
||||
'{prefix}/i4x-MITx-999-course-Robot_Super_Course/threads'.format(prefix=CS_PREFIX),
|
||||
f'{CS_PREFIX}/i4x-MITx-999-course-Robot_Super_Course/threads',
|
||||
data=expected_data,
|
||||
params={'request_id': ANY},
|
||||
headers=ANY,
|
||||
@@ -360,7 +356,7 @@ class ViewsTestCaseMixin(object):
|
||||
response = self.client.post(
|
||||
reverse("update_thread", kwargs={
|
||||
"thread_id": "dummy",
|
||||
"course_id": six.text_type(self.course_id)
|
||||
"course_id": str(self.course_id)
|
||||
}),
|
||||
data={"body": "foo", "title": "foo", "commentable_id": "some_topic"}
|
||||
)
|
||||
@@ -389,7 +385,7 @@ class ViewsQueryCountTestCase(
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(ViewsQueryCountTestCase, self).setUp()
|
||||
super().setUp()
|
||||
|
||||
def count_queries(func): # pylint: disable=no-self-argument
|
||||
"""
|
||||
@@ -438,7 +434,7 @@ class ViewsTestCase(
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(ViewsTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create(
|
||||
org='MITx', course='999',
|
||||
discussion_topics={"Some Topic": {"id": "some_topic"}},
|
||||
@@ -447,19 +443,19 @@ class ViewsTestCase(
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(ViewsTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
cls.course_id = cls.course.id
|
||||
|
||||
# seed the forums permissions and roles
|
||||
call_command('seed_permissions_roles', six.text_type(cls.course_id))
|
||||
call_command('seed_permissions_roles', str(cls.course_id))
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
# Patching the ENABLE_DISCUSSION_SERVICE value affects the contents of urls.py,
|
||||
# so we need to call super.setUp() which reloads urls.py (because
|
||||
# of the UrlResetMixin)
|
||||
super(ViewsTestCase, self).setUp()
|
||||
super().setUp()
|
||||
|
||||
# Patch the comment client user save method so it does not try
|
||||
# to create a new cc user when creating a django user
|
||||
@@ -523,7 +519,7 @@ class ViewsTestCase(
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
view_name,
|
||||
kwargs={"course_id": six.text_type(self.course_id), "thread_id": 'i4x-MITx-999-course-Robot_Super_Course'}
|
||||
kwargs={"course_id": str(self.course_id), "thread_id": 'i4x-MITx-999-course-Robot_Super_Course'}
|
||||
)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
@@ -540,7 +536,7 @@ class ViewsTestCase(
|
||||
with self.assert_discussion_signals('thread_deleted'):
|
||||
response = views.delete_thread(
|
||||
request,
|
||||
course_id=six.text_type(self.course.id),
|
||||
course_id=str(self.course.id),
|
||||
thread_id=test_thread_id
|
||||
)
|
||||
assert response.status_code == 200
|
||||
@@ -558,14 +554,14 @@ class ViewsTestCase(
|
||||
with self.assert_discussion_signals('comment_deleted'):
|
||||
response = views.delete_comment(
|
||||
request,
|
||||
course_id=six.text_type(self.course.id),
|
||||
course_id=str(self.course.id),
|
||||
comment_id=test_comment_id
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert mock_request.called
|
||||
args = mock_request.call_args[0]
|
||||
assert args[0] == 'delete'
|
||||
assert args[1].endswith('/{}'.format(test_comment_id))
|
||||
assert args[1].endswith(f"/{test_comment_id}")
|
||||
|
||||
def _test_request_error(self, view_name, view_kwargs, data, mock_request):
|
||||
"""
|
||||
@@ -583,7 +579,7 @@ class ViewsTestCase(
|
||||
def test_create_thread_no_title(self, mock_request):
|
||||
self._test_request_error(
|
||||
"create_thread",
|
||||
{"commentable_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"commentable_id": "dummy", "course_id": str(self.course_id)},
|
||||
{"body": "foo"},
|
||||
mock_request
|
||||
)
|
||||
@@ -591,7 +587,7 @@ class ViewsTestCase(
|
||||
def test_create_thread_empty_title(self, mock_request):
|
||||
self._test_request_error(
|
||||
"create_thread",
|
||||
{"commentable_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"commentable_id": "dummy", "course_id": str(self.course_id)},
|
||||
{"body": "foo", "title": " "},
|
||||
mock_request
|
||||
)
|
||||
@@ -599,7 +595,7 @@ class ViewsTestCase(
|
||||
def test_create_thread_no_body(self, mock_request):
|
||||
self._test_request_error(
|
||||
"create_thread",
|
||||
{"commentable_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"commentable_id": "dummy", "course_id": str(self.course_id)},
|
||||
{"title": "foo"},
|
||||
mock_request
|
||||
)
|
||||
@@ -607,7 +603,7 @@ class ViewsTestCase(
|
||||
def test_create_thread_empty_body(self, mock_request):
|
||||
self._test_request_error(
|
||||
"create_thread",
|
||||
{"commentable_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"commentable_id": "dummy", "course_id": str(self.course_id)},
|
||||
{"body": " ", "title": "foo"},
|
||||
mock_request
|
||||
)
|
||||
@@ -615,7 +611,7 @@ class ViewsTestCase(
|
||||
def test_update_thread_no_title(self, mock_request):
|
||||
self._test_request_error(
|
||||
"update_thread",
|
||||
{"thread_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"thread_id": "dummy", "course_id": str(self.course_id)},
|
||||
{"body": "foo"},
|
||||
mock_request
|
||||
)
|
||||
@@ -623,7 +619,7 @@ class ViewsTestCase(
|
||||
def test_update_thread_empty_title(self, mock_request):
|
||||
self._test_request_error(
|
||||
"update_thread",
|
||||
{"thread_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"thread_id": "dummy", "course_id": str(self.course_id)},
|
||||
{"body": "foo", "title": " "},
|
||||
mock_request
|
||||
)
|
||||
@@ -631,7 +627,7 @@ class ViewsTestCase(
|
||||
def test_update_thread_no_body(self, mock_request):
|
||||
self._test_request_error(
|
||||
"update_thread",
|
||||
{"thread_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"thread_id": "dummy", "course_id": str(self.course_id)},
|
||||
{"title": "foo"},
|
||||
mock_request
|
||||
)
|
||||
@@ -639,7 +635,7 @@ class ViewsTestCase(
|
||||
def test_update_thread_empty_body(self, mock_request):
|
||||
self._test_request_error(
|
||||
"update_thread",
|
||||
{"thread_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"thread_id": "dummy", "course_id": str(self.course_id)},
|
||||
{"body": " ", "title": "foo"},
|
||||
mock_request
|
||||
)
|
||||
@@ -655,7 +651,7 @@ class ViewsTestCase(
|
||||
def test_update_thread_wrong_commentable_id(self, mock_get_discussion_id_map, mock_request):
|
||||
self._test_request_error(
|
||||
"update_thread",
|
||||
{"thread_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"thread_id": "dummy", "course_id": str(self.course_id)},
|
||||
{"body": "foo", "title": "foo", "commentable_id": "wrong_commentable"},
|
||||
mock_request
|
||||
)
|
||||
@@ -666,7 +662,7 @@ class ViewsTestCase(
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"create_comment",
|
||||
kwargs={"course_id": six.text_type(self.course_id), "thread_id": "dummy"}
|
||||
kwargs={"course_id": str(self.course_id), "thread_id": "dummy"}
|
||||
),
|
||||
data={"body": "body"}
|
||||
)
|
||||
@@ -675,7 +671,7 @@ class ViewsTestCase(
|
||||
def test_create_comment_no_body(self, mock_request):
|
||||
self._test_request_error(
|
||||
"create_comment",
|
||||
{"thread_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"thread_id": "dummy", "course_id": str(self.course_id)},
|
||||
{},
|
||||
mock_request
|
||||
)
|
||||
@@ -683,7 +679,7 @@ class ViewsTestCase(
|
||||
def test_create_comment_empty_body(self, mock_request):
|
||||
self._test_request_error(
|
||||
"create_comment",
|
||||
{"thread_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"thread_id": "dummy", "course_id": str(self.course_id)},
|
||||
{"body": " "},
|
||||
mock_request
|
||||
)
|
||||
@@ -691,7 +687,7 @@ class ViewsTestCase(
|
||||
def test_create_sub_comment_no_body(self, mock_request):
|
||||
self._test_request_error(
|
||||
"create_sub_comment",
|
||||
{"comment_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"comment_id": "dummy", "course_id": str(self.course_id)},
|
||||
{},
|
||||
mock_request
|
||||
)
|
||||
@@ -699,7 +695,7 @@ class ViewsTestCase(
|
||||
def test_create_sub_comment_empty_body(self, mock_request):
|
||||
self._test_request_error(
|
||||
"create_sub_comment",
|
||||
{"comment_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"comment_id": "dummy", "course_id": str(self.course_id)},
|
||||
{"body": " "},
|
||||
mock_request
|
||||
)
|
||||
@@ -707,7 +703,7 @@ class ViewsTestCase(
|
||||
def test_update_comment_no_body(self, mock_request):
|
||||
self._test_request_error(
|
||||
"update_comment",
|
||||
{"comment_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"comment_id": "dummy", "course_id": str(self.course_id)},
|
||||
{},
|
||||
mock_request
|
||||
)
|
||||
@@ -715,7 +711,7 @@ class ViewsTestCase(
|
||||
def test_update_comment_empty_body(self, mock_request):
|
||||
self._test_request_error(
|
||||
"update_comment",
|
||||
{"comment_id": "dummy", "course_id": six.text_type(self.course_id)},
|
||||
{"comment_id": "dummy", "course_id": str(self.course_id)},
|
||||
{"body": " "},
|
||||
mock_request
|
||||
)
|
||||
@@ -728,14 +724,14 @@ class ViewsTestCase(
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"update_comment",
|
||||
kwargs={"course_id": six.text_type(self.course_id), "comment_id": comment_id}
|
||||
kwargs={"course_id": str(self.course_id), "comment_id": comment_id}
|
||||
),
|
||||
data={"body": updated_body}
|
||||
)
|
||||
assert response.status_code == 200
|
||||
mock_request.assert_called_with(
|
||||
"put",
|
||||
"{prefix}/comments/{comment_id}".format(prefix=CS_PREFIX, comment_id=comment_id),
|
||||
f"{CS_PREFIX}/comments/{comment_id}",
|
||||
headers=ANY,
|
||||
params=ANY,
|
||||
timeout=ANY,
|
||||
@@ -779,14 +775,14 @@ class ViewsTestCase(
|
||||
})
|
||||
url = reverse('flag_abuse_for_thread', kwargs={
|
||||
'thread_id': '518d4237b023791dca00000d',
|
||||
'course_id': six.text_type(self.course_id)
|
||||
'course_id': str(self.course_id)
|
||||
})
|
||||
response = self.client.post(url)
|
||||
assert mock_request.called
|
||||
|
||||
call_list = [
|
||||
(
|
||||
('get', '{prefix}/threads/518d4237b023791dca00000d'.format(prefix=CS_PREFIX)),
|
||||
('get', f'{CS_PREFIX}/threads/518d4237b023791dca00000d'),
|
||||
{
|
||||
'data': None,
|
||||
'params': {'mark_as_read': True, 'request_id': ANY, 'with_responses': False},
|
||||
@@ -795,7 +791,7 @@ class ViewsTestCase(
|
||||
}
|
||||
),
|
||||
(
|
||||
('put', '{prefix}/threads/518d4237b023791dca00000d/abuse_flag'.format(prefix=CS_PREFIX)),
|
||||
('put', f'{CS_PREFIX}/threads/518d4237b023791dca00000d/abuse_flag'),
|
||||
{
|
||||
'data': {'user_id': '1'},
|
||||
'params': {'request_id': ANY},
|
||||
@@ -804,7 +800,7 @@ class ViewsTestCase(
|
||||
}
|
||||
),
|
||||
(
|
||||
('get', '{prefix}/threads/518d4237b023791dca00000d'.format(prefix=CS_PREFIX)),
|
||||
('get', f'{CS_PREFIX}/threads/518d4237b023791dca00000d'),
|
||||
{
|
||||
'data': None,
|
||||
'params': {'mark_as_read': True, 'request_id': ANY, 'with_responses': False},
|
||||
@@ -856,14 +852,14 @@ class ViewsTestCase(
|
||||
})
|
||||
url = reverse('un_flag_abuse_for_thread', kwargs={
|
||||
'thread_id': '518d4237b023791dca00000d',
|
||||
'course_id': six.text_type(self.course_id)
|
||||
'course_id': str(self.course_id)
|
||||
})
|
||||
response = self.client.post(url)
|
||||
assert mock_request.called
|
||||
|
||||
call_list = [
|
||||
(
|
||||
('get', '{prefix}/threads/518d4237b023791dca00000d'.format(prefix=CS_PREFIX)),
|
||||
('get', f'{CS_PREFIX}/threads/518d4237b023791dca00000d'),
|
||||
{
|
||||
'data': None,
|
||||
'params': {'mark_as_read': True, 'request_id': ANY, 'with_responses': False},
|
||||
@@ -872,7 +868,7 @@ class ViewsTestCase(
|
||||
}
|
||||
),
|
||||
(
|
||||
('put', '{prefix}/threads/518d4237b023791dca00000d/abuse_unflag'.format(prefix=CS_PREFIX)),
|
||||
('put', f'{CS_PREFIX}/threads/518d4237b023791dca00000d/abuse_unflag'),
|
||||
{
|
||||
'data': {'user_id': '1'},
|
||||
'params': {'request_id': ANY},
|
||||
@@ -881,7 +877,7 @@ class ViewsTestCase(
|
||||
}
|
||||
),
|
||||
(
|
||||
('get', '{prefix}/threads/518d4237b023791dca00000d'.format(prefix=CS_PREFIX)),
|
||||
('get', f'{CS_PREFIX}/threads/518d4237b023791dca00000d'),
|
||||
{
|
||||
'data': None,
|
||||
'params': {'mark_as_read': True, 'request_id': ANY, 'with_responses': False},
|
||||
@@ -927,14 +923,14 @@ class ViewsTestCase(
|
||||
})
|
||||
url = reverse('flag_abuse_for_comment', kwargs={
|
||||
'comment_id': '518d4237b023791dca00000d',
|
||||
'course_id': six.text_type(self.course_id)
|
||||
'course_id': str(self.course_id)
|
||||
})
|
||||
response = self.client.post(url)
|
||||
assert mock_request.called
|
||||
|
||||
call_list = [
|
||||
(
|
||||
('get', '{prefix}/comments/518d4237b023791dca00000d'.format(prefix=CS_PREFIX)),
|
||||
('get', f'{CS_PREFIX}/comments/518d4237b023791dca00000d'),
|
||||
{
|
||||
'data': None,
|
||||
'params': {'request_id': ANY},
|
||||
@@ -943,7 +939,7 @@ class ViewsTestCase(
|
||||
}
|
||||
),
|
||||
(
|
||||
('put', '{prefix}/comments/518d4237b023791dca00000d/abuse_flag'.format(prefix=CS_PREFIX)),
|
||||
('put', f'{CS_PREFIX}/comments/518d4237b023791dca00000d/abuse_flag'),
|
||||
{
|
||||
'data': {'user_id': '1'},
|
||||
'params': {'request_id': ANY},
|
||||
@@ -952,7 +948,7 @@ class ViewsTestCase(
|
||||
}
|
||||
),
|
||||
(
|
||||
('get', '{prefix}/comments/518d4237b023791dca00000d'.format(prefix=CS_PREFIX)),
|
||||
('get', f'{CS_PREFIX}/comments/518d4237b023791dca00000d'),
|
||||
{
|
||||
'data': None,
|
||||
'params': {'request_id': ANY},
|
||||
@@ -998,14 +994,14 @@ class ViewsTestCase(
|
||||
})
|
||||
url = reverse('un_flag_abuse_for_comment', kwargs={
|
||||
'comment_id': '518d4237b023791dca00000d',
|
||||
'course_id': six.text_type(self.course_id)
|
||||
'course_id': str(self.course_id)
|
||||
})
|
||||
response = self.client.post(url)
|
||||
assert mock_request.called
|
||||
|
||||
call_list = [
|
||||
(
|
||||
('get', '{prefix}/comments/518d4237b023791dca00000d'.format(prefix=CS_PREFIX)),
|
||||
('get', f'{CS_PREFIX}/comments/518d4237b023791dca00000d'),
|
||||
{
|
||||
'data': None,
|
||||
'params': {'request_id': ANY},
|
||||
@@ -1014,7 +1010,7 @@ class ViewsTestCase(
|
||||
}
|
||||
),
|
||||
(
|
||||
('put', '{prefix}/comments/518d4237b023791dca00000d/abuse_unflag'.format(prefix=CS_PREFIX)),
|
||||
('put', f'{CS_PREFIX}/comments/518d4237b023791dca00000d/abuse_unflag'),
|
||||
{
|
||||
'data': {'user_id': '1'},
|
||||
'params': {'request_id': ANY},
|
||||
@@ -1023,7 +1019,7 @@ class ViewsTestCase(
|
||||
}
|
||||
),
|
||||
(
|
||||
('get', '{prefix}/comments/518d4237b023791dca00000d'.format(prefix=CS_PREFIX)),
|
||||
('get', f'{CS_PREFIX}/comments/518d4237b023791dca00000d'),
|
||||
{
|
||||
'data': None,
|
||||
'params': {'request_id': ANY},
|
||||
@@ -1050,7 +1046,7 @@ class ViewsTestCase(
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
view_name,
|
||||
kwargs={item_id: 'dummy', 'course_id': six.text_type(self.course_id)}
|
||||
kwargs={item_id: 'dummy', 'course_id': str(self.course_id)}
|
||||
)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
@@ -1062,7 +1058,7 @@ class ViewsTestCase(
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
'endorse_comment',
|
||||
kwargs={'comment_id': 'dummy', 'course_id': six.text_type(self.course_id)}
|
||||
kwargs={'comment_id': 'dummy', 'course_id': str(self.course_id)}
|
||||
)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
@@ -1075,12 +1071,12 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(ViewPermissionsTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(ViewPermissionsTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
seed_permissions_roles(cls.course.id)
|
||||
|
||||
@@ -1095,13 +1091,13 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(ViewPermissionsTestCase, self).setUp()
|
||||
super().setUp()
|
||||
|
||||
def test_pin_thread_as_student(self, mock_request):
|
||||
self._set_mock_request_data(mock_request, {})
|
||||
self.client.login(username=self.student.username, password=self.password)
|
||||
response = self.client.post(
|
||||
reverse("pin_thread", kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy"})
|
||||
reverse("pin_thread", kwargs={"course_id": str(self.course.id), "thread_id": "dummy"})
|
||||
)
|
||||
assert response.status_code == 401
|
||||
|
||||
@@ -1109,7 +1105,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
|
||||
self._set_mock_request_data(mock_request, {})
|
||||
self.client.login(username=self.moderator.username, password=self.password)
|
||||
response = self.client.post(
|
||||
reverse("pin_thread", kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy"})
|
||||
reverse("pin_thread", kwargs={"course_id": str(self.course.id), "thread_id": "dummy"})
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
@@ -1117,7 +1113,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
|
||||
self._set_mock_request_data(mock_request, {})
|
||||
self.client.login(username=self.student.username, password=self.password)
|
||||
response = self.client.post(
|
||||
reverse("un_pin_thread", kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy"})
|
||||
reverse("un_pin_thread", kwargs={"course_id": str(self.course.id), "thread_id": "dummy"})
|
||||
)
|
||||
assert response.status_code == 401
|
||||
|
||||
@@ -1125,7 +1121,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
|
||||
self._set_mock_request_data(mock_request, {})
|
||||
self.client.login(username=self.moderator.username, password=self.password)
|
||||
response = self.client.post(
|
||||
reverse("un_pin_thread", kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy"})
|
||||
reverse("un_pin_thread", kwargs={"course_id": str(self.course.id), "thread_id": "dummy"})
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
@@ -1148,7 +1144,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
|
||||
)
|
||||
self.client.login(username=self.moderator.username, password=self.password)
|
||||
response = self.client.post(
|
||||
reverse("endorse_comment", kwargs={"course_id": six.text_type(self.course.id), "comment_id": "dummy"})
|
||||
reverse("endorse_comment", kwargs={"course_id": str(self.course.id), "comment_id": "dummy"})
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
@@ -1160,7 +1156,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
|
||||
)
|
||||
self.client.login(username=self.student.username, password=self.password)
|
||||
response = self.client.post(
|
||||
reverse("endorse_comment", kwargs={"course_id": six.text_type(self.course.id), "comment_id": "dummy"})
|
||||
reverse("endorse_comment", kwargs={"course_id": str(self.course.id), "comment_id": "dummy"})
|
||||
)
|
||||
assert response.status_code == 401
|
||||
|
||||
@@ -1172,7 +1168,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
|
||||
)
|
||||
self.client.login(username=self.student.username, password=self.password)
|
||||
response = self.client.post(
|
||||
reverse("endorse_comment", kwargs={"course_id": six.text_type(self.course.id), "comment_id": "dummy"})
|
||||
reverse("endorse_comment", kwargs={"course_id": str(self.course.id), "comment_id": "dummy"})
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
@@ -1186,12 +1182,12 @@ class CreateThreadUnicodeTestCase(
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(CreateThreadUnicodeTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(CreateThreadUnicodeTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
seed_permissions_roles(cls.course.id)
|
||||
cls.student = UserFactory.create()
|
||||
@@ -1208,7 +1204,7 @@ class CreateThreadUnicodeTestCase(
|
||||
request.view_name = "create_thread"
|
||||
response = views.create_thread(
|
||||
# The commentable ID contains a username, the Unicode char below ensures it works fine
|
||||
request, course_id=six.text_type(self.course.id), commentable_id=u"non_tåem_dummy_id"
|
||||
request, course_id=str(self.course.id), commentable_id="non_tåem_dummy_id"
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
@@ -1228,12 +1224,12 @@ class UpdateThreadUnicodeTestCase(
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(UpdateThreadUnicodeTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(UpdateThreadUnicodeTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
seed_permissions_roles(cls.course.id)
|
||||
cls.student = UserFactory.create()
|
||||
@@ -1252,7 +1248,7 @@ class UpdateThreadUnicodeTestCase(
|
||||
request = RequestFactory().post("dummy_url", {"body": text, "title": text, "thread_type": "question", "commentable_id": "test_commentable"})
|
||||
request.user = self.student
|
||||
request.view_name = "update_thread"
|
||||
response = views.update_thread(request, course_id=six.text_type(self.course.id), thread_id="dummy_thread_id")
|
||||
response = views.update_thread(request, course_id=str(self.course.id), thread_id="dummy_thread_id")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert mock_request.called
|
||||
@@ -1273,12 +1269,12 @@ class CreateCommentUnicodeTestCase(
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(CreateCommentUnicodeTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(CreateCommentUnicodeTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
seed_permissions_roles(cls.course.id)
|
||||
cls.student = UserFactory.create()
|
||||
@@ -1299,7 +1295,7 @@ class CreateCommentUnicodeTestCase(
|
||||
request.user = self.student
|
||||
request.view_name = "create_comment"
|
||||
response = views.create_comment(
|
||||
request, course_id=six.text_type(self.course.id), thread_id="dummy_thread_id"
|
||||
request, course_id=str(self.course.id), thread_id="dummy_thread_id"
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
@@ -1320,12 +1316,12 @@ class UpdateCommentUnicodeTestCase(
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(UpdateCommentUnicodeTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(UpdateCommentUnicodeTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
seed_permissions_roles(cls.course.id)
|
||||
cls.student = UserFactory.create()
|
||||
@@ -1340,7 +1336,7 @@ class UpdateCommentUnicodeTestCase(
|
||||
request = RequestFactory().post("dummy_url", {"body": text})
|
||||
request.user = self.student
|
||||
request.view_name = "update_comment"
|
||||
response = views.update_comment(request, course_id=six.text_type(self.course.id), comment_id="dummy_comment_id")
|
||||
response = views.update_comment(request, course_id=str(self.course.id), comment_id="dummy_comment_id")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert mock_request.called
|
||||
@@ -1360,12 +1356,12 @@ class CreateSubCommentUnicodeTestCase(
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(CreateSubCommentUnicodeTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(CreateSubCommentUnicodeTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
seed_permissions_roles(cls.course.id)
|
||||
cls.student = UserFactory.create()
|
||||
@@ -1388,7 +1384,7 @@ class CreateSubCommentUnicodeTestCase(
|
||||
Thread.commentable_id = "test_commentable"
|
||||
try:
|
||||
response = views.create_sub_comment(
|
||||
request, course_id=six.text_type(self.course.id), comment_id="dummy_comment_id"
|
||||
request, course_id=str(self.course.id), comment_id="dummy_comment_id"
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
@@ -1441,7 +1437,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(TeamsPermissionsTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
teams_config_data = {
|
||||
'topics': [{'id': "topic_id", 'name': 'Solar Power', 'description': 'Solar power is hot'}]
|
||||
}
|
||||
@@ -1449,7 +1445,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(TeamsPermissionsTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.course = CourseFactory.create()
|
||||
cls.password = "test password"
|
||||
seed_permissions_roles(cls.course.id)
|
||||
@@ -1491,7 +1487,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
|
||||
# Create a team
|
||||
cls.team_commentable_id = "team_discussion_id"
|
||||
cls.team = CourseTeamFactory.create(
|
||||
name=u'The Only Team',
|
||||
name='The Only Team',
|
||||
course_id=cls.course.id,
|
||||
topic_id='topic_id',
|
||||
discussion_topic_id=cls.team_commentable_id
|
||||
@@ -1510,7 +1506,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(TeamsPermissionsTestCase, self).setUp()
|
||||
super().setUp()
|
||||
|
||||
def _setup_mock(self, user, mock_request, data):
|
||||
user = getattr(self, user)
|
||||
@@ -1555,14 +1551,14 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
|
||||
"closed": False, "commentable_id": commentable_id,
|
||||
"context": "standalone",
|
||||
"username": thread_author.username,
|
||||
"course_id": six.text_type(self.course.id)
|
||||
"course_id": str(self.course.id)
|
||||
}
|
||||
)
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"update_thread",
|
||||
kwargs={
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"thread_id": "dummy"
|
||||
}
|
||||
),
|
||||
@@ -1599,14 +1595,14 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
|
||||
"commentable_id": commentable_id,
|
||||
"user_id": str(comment_author.id),
|
||||
"username": comment_author.username,
|
||||
"course_id": six.text_type(self.course.id)
|
||||
"course_id": str(self.course.id)
|
||||
})
|
||||
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"delete_comment",
|
||||
kwargs={
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"comment_id": "dummy"
|
||||
}
|
||||
),
|
||||
@@ -1627,7 +1623,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
|
||||
reverse(
|
||||
"create_comment",
|
||||
kwargs={
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"thread_id": "dummy"
|
||||
}
|
||||
),
|
||||
@@ -1650,7 +1646,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
|
||||
reverse(
|
||||
"create_sub_comment",
|
||||
kwargs={
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"comment_id": "dummy_comment"
|
||||
}
|
||||
),
|
||||
@@ -1674,7 +1670,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
action,
|
||||
kwargs={"course_id": six.text_type(self.course.id), "comment_id": "dummy_comment"}
|
||||
kwargs={"course_id": str(self.course.id), "comment_id": "dummy_comment"}
|
||||
)
|
||||
)
|
||||
assert response.status_code == status_code
|
||||
@@ -1696,7 +1692,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
action,
|
||||
kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy_thread"}
|
||||
kwargs={"course_id": str(self.course.id), "thread_id": "dummy_thread"}
|
||||
)
|
||||
)
|
||||
assert response.status_code == status_code
|
||||
@@ -1714,12 +1710,12 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(ForumEventTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(ForumEventTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
seed_permissions_roles(cls.course.id)
|
||||
|
||||
@@ -1742,7 +1738,7 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
|
||||
request = RequestFactory().post("dummy_url", {"body": "Test comment", 'auto_subscribe': True})
|
||||
request.user = self.student
|
||||
request.view_name = "create_comment"
|
||||
views.create_comment(request, course_id=six.text_type(self.course.id), thread_id='test_thread_id')
|
||||
views.create_comment(request, course_id=str(self.course.id), thread_id='test_thread_id')
|
||||
|
||||
event_name, event = mock_emit.call_args[0]
|
||||
assert event_name == 'edx.forum.response.created'
|
||||
@@ -1769,7 +1765,7 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
|
||||
request = RequestFactory().post("dummy_url", {"body": "Another comment"})
|
||||
request.user = self.student
|
||||
request.view_name = "create_sub_comment"
|
||||
views.create_sub_comment(request, course_id=six.text_type(self.course.id), comment_id="dummy_comment_id")
|
||||
views.create_sub_comment(request, course_id=str(self.course.id), comment_id="dummy_comment_id")
|
||||
|
||||
event_name, event = mock_emit.call_args[0]
|
||||
assert event_name == 'edx.forum.comment.created'
|
||||
@@ -1818,7 +1814,7 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
|
||||
request.user = user
|
||||
request.view_name = view_name
|
||||
|
||||
getattr(views, view_name)(request, course_id=six.text_type(self.course.id), **view_kwargs)
|
||||
getattr(views, view_name)(request, course_id=str(self.course.id), **view_kwargs)
|
||||
|
||||
name, event = mock_emit.call_args[0]
|
||||
assert name == event_name
|
||||
@@ -1845,7 +1841,7 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
|
||||
request.user = self.student
|
||||
request.view_name = view_name
|
||||
view_function = getattr(views, view_name)
|
||||
kwargs = dict(course_id=six.text_type(self.course.id))
|
||||
kwargs = dict(course_id=str(self.course.id))
|
||||
kwargs[obj_id_name] = obj_id_name
|
||||
if not undo:
|
||||
kwargs.update(value='up')
|
||||
@@ -1853,7 +1849,7 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
|
||||
|
||||
assert mock_emit.called
|
||||
event_name, event = mock_emit.call_args[0]
|
||||
assert event_name == 'edx.forum.{}.voted'.format(obj_type)
|
||||
assert event_name == f'edx.forum.{obj_type}.voted'
|
||||
assert event['target_username'] == 'gumprecht'
|
||||
assert event['undo_vote'] == undo
|
||||
assert event['vote_value'] == 'up'
|
||||
@@ -1864,12 +1860,12 @@ class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRe
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(UsersEndpointTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(UsersEndpointTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
seed_permissions_roles(cls.course.id)
|
||||
|
||||
@@ -1892,7 +1888,7 @@ class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRe
|
||||
request = getattr(RequestFactory(), method)("dummy_url", kwargs)
|
||||
request.user = self.student
|
||||
request.view_name = "users"
|
||||
return views.users(request, course_id=text_type(course_id))
|
||||
return views.users(request, course_id=str(course_id))
|
||||
|
||||
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
|
||||
def test_finds_exact_match(self, mock_request):
|
||||
@@ -2050,7 +2046,7 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
|
||||
|
||||
@mock.patch.dict("common.djangoapps.student.models.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(ForumThreadViewedEventTransformerTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.courses_by_store = {
|
||||
ModuleStoreEnum.Type.mongo: CourseFactory.create(
|
||||
org='TestX',
|
||||
@@ -2198,7 +2194,7 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
|
||||
topic_id=commentable_id,
|
||||
thread_id=thread_id,
|
||||
)
|
||||
expected_path = '/courses/{0}/discussion/forum/{1}/threads/{2}'.format(
|
||||
expected_path = '/courses/{}/discussion/forum/{}/threads/{}'.format(
|
||||
course.id, commentable_id, thread_id
|
||||
)
|
||||
assert event_trans['event'].get('url').endswith(expected_path)
|
||||
@@ -2221,7 +2217,7 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
|
||||
topic_id=self.category.discussion_id,
|
||||
)
|
||||
assert event_trans_2['event'].get('category_id') == self.category.discussion_id
|
||||
full_category_name = u'{0} / {1}'.format(self.category.discussion_category, self.category.discussion_target)
|
||||
full_category_name = f'{self.category.discussion_category} / {self.category.discussion_target}'
|
||||
assert event_trans_2['event'].get('category_name') == full_category_name
|
||||
|
||||
def test_roles(self):
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
"""Views for discussion forums."""
|
||||
|
||||
|
||||
import functools
|
||||
import json
|
||||
import logging
|
||||
@@ -18,10 +16,10 @@ from django.views.decorators import csrf
|
||||
from django.views.decorators.clickjacking import xframe_options_exempt
|
||||
from django.views.decorators.http import require_GET, require_POST
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from six import text_type
|
||||
|
||||
import lms.djangoapps.discussion.django_comment_client.settings as cc_settings
|
||||
import openedx.core.djangoapps.django_comment_common.comment_client as cc
|
||||
from common.djangoapps.util.file import store_uploaded_file
|
||||
from lms.djangoapps.courseware.access import has_access
|
||||
from lms.djangoapps.courseware.courses import get_course_by_id, get_course_overview_with_access, get_course_with_access
|
||||
from lms.djangoapps.courseware.exceptions import CourseAccessRedirect
|
||||
@@ -57,7 +55,6 @@ from openedx.core.djangoapps.django_comment_common.signals import (
|
||||
thread_voted
|
||||
)
|
||||
from openedx.core.djangoapps.django_comment_common.utils import ThreadContext
|
||||
from common.djangoapps.util.file import store_uploaded_file
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -237,7 +234,7 @@ def create_thread(request, course_id, commentable_id):
|
||||
Given a course and commentable ID, create the thread
|
||||
"""
|
||||
|
||||
log.debug(u"Creating new thread in %r, id %r", course_id, commentable_id)
|
||||
log.debug("Creating new thread in %r, id %r", course_id, commentable_id)
|
||||
course_key = CourseKey.from_string(course_id)
|
||||
course = get_course_with_access(request.user, 'load', course_key)
|
||||
post = request.POST
|
||||
@@ -262,7 +259,7 @@ def create_thread(request, course_id, commentable_id):
|
||||
'anonymous': anonymous,
|
||||
'anonymous_to_peers': anonymous_to_peers,
|
||||
'commentable_id': commentable_id,
|
||||
'course_id': text_type(course_key),
|
||||
'course_id': str(course_key),
|
||||
'user_id': user.id,
|
||||
'thread_type': post["thread_type"],
|
||||
'body': post["body"],
|
||||
@@ -380,7 +377,7 @@ def _create_comment(request, course_key, thread_id=None, parent_id=None):
|
||||
anonymous=anonymous,
|
||||
anonymous_to_peers=anonymous_to_peers,
|
||||
user_id=user.id,
|
||||
course_id=text_type(course_key),
|
||||
course_id=str(course_key),
|
||||
thread_id=thread_id,
|
||||
parent_id=parent_id,
|
||||
body=post["body"]
|
||||
@@ -771,10 +768,10 @@ def upload(request, course_id): # ajax upload file to a question or answer # l
|
||||
)
|
||||
|
||||
except exceptions.PermissionDenied as err:
|
||||
error = six.text_type(err)
|
||||
error = str(err)
|
||||
except Exception as err: # pylint: disable=broad-except
|
||||
print(err)
|
||||
logging.critical(six.text_type(err))
|
||||
logging.critical(str(err))
|
||||
error = _('Error uploading file. Please contact the site administrator. Thank you.')
|
||||
|
||||
if error == '':
|
||||
|
||||
@@ -3,7 +3,6 @@ import json
|
||||
import logging
|
||||
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
from six import text_type
|
||||
|
||||
from lms.djangoapps.discussion.django_comment_client.utils import JsonError
|
||||
from openedx.core.djangoapps.django_comment_common.comment_client import CommentClientRequestError
|
||||
@@ -23,7 +22,7 @@ class AjaxExceptionMiddleware(MiddlewareMixin):
|
||||
"""
|
||||
if isinstance(exception, CommentClientRequestError) and request.is_ajax():
|
||||
try:
|
||||
return JsonError(json.loads(text_type(exception)), exception.status_code)
|
||||
return JsonError(json.loads(str(exception)), exception.status_code)
|
||||
except ValueError:
|
||||
return JsonError(text_type(exception), exception.status_code)
|
||||
return JsonError(str(exception), exception.status_code)
|
||||
return None
|
||||
|
||||
@@ -5,7 +5,6 @@ Module for checking permissions with the comment_client backend
|
||||
|
||||
import logging
|
||||
|
||||
import six
|
||||
from edx_django_utils.cache import DEFAULT_REQUEST_CACHE
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
@@ -104,7 +103,7 @@ def _check_condition(user, condition, content):
|
||||
try:
|
||||
commentable_id = content['commentable_id']
|
||||
request_cache_dict = DEFAULT_REQUEST_CACHE.data
|
||||
cache_key = u"django_comment_client.check_team_member.{}.{}".format(user.id, commentable_id)
|
||||
cache_key = f"django_comment_client.check_team_member.{user.id}.{commentable_id}"
|
||||
if cache_key in request_cache_dict:
|
||||
return request_cache_dict[cache_key]
|
||||
team = get_team(commentable_id)
|
||||
@@ -138,7 +137,7 @@ def _check_conditions_permissions(user, permissions, course_id, content, user_gr
|
||||
"""
|
||||
|
||||
def test(user, per, operator="or"):
|
||||
if isinstance(per, six.string_types):
|
||||
if isinstance(per, str):
|
||||
if per in CONDITIONS:
|
||||
return _check_condition(user, per, content)
|
||||
if 'group_' in per:
|
||||
|
||||
@@ -5,7 +5,7 @@ from openedx.core.djangoapps.django_comment_common.models import Permission, Rol
|
||||
|
||||
|
||||
class RoleFactory(DjangoModelFactory): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = Role
|
||||
|
||||
name = 'Student'
|
||||
@@ -13,7 +13,7 @@ class RoleFactory(DjangoModelFactory): # lint-amnesty, pylint: disable=missing-
|
||||
|
||||
|
||||
class PermissionFactory(DjangoModelFactory):
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = Permission
|
||||
|
||||
name = 'create_comment'
|
||||
|
||||
@@ -11,7 +11,7 @@ from openedx.core.djangoapps.django_comment_common.models import CourseDiscussio
|
||||
from openedx.core.djangoapps.django_comment_common.utils import set_course_discussion_settings
|
||||
|
||||
|
||||
class GroupIdAssertionMixin(object):
|
||||
class GroupIdAssertionMixin:
|
||||
def _data_or_params_cs_request(self, mock_request):
|
||||
"""
|
||||
Returns the data or params dict that `mock_request` was called with.
|
||||
|
||||
@@ -30,7 +30,7 @@ class MockCommentServiceRequestHandler(BaseHTTPRequestHandler):
|
||||
# Log the request
|
||||
# pylint: disable=logging-format-interpolation
|
||||
logger.debug(
|
||||
u"Comment Service received POST request {0} to path {1}"
|
||||
"Comment Service received POST request {} to path {}"
|
||||
.format(json.dumps(post_dict), self.path)
|
||||
)
|
||||
|
||||
@@ -38,7 +38,7 @@ class MockCommentServiceRequestHandler(BaseHTTPRequestHandler):
|
||||
if 'X-Edx-Api-Key' in self.headers:
|
||||
response = self.server._response_str
|
||||
# Log the response
|
||||
logger.debug(u"Comment Service: sending response %s", json.dumps(response))
|
||||
logger.debug("Comment Service: sending response %s", json.dumps(response))
|
||||
|
||||
# Send a response back to the client
|
||||
self.send_response(200)
|
||||
@@ -68,7 +68,7 @@ class MockCommentServiceRequestHandler(BaseHTTPRequestHandler):
|
||||
# Log the request
|
||||
# pylint: disable=logging-format-interpolation
|
||||
logger.debug(
|
||||
u"Comment Service received PUT request {0} to path {1}"
|
||||
"Comment Service received PUT request {} to path {}"
|
||||
.format(json.dumps(post_dict), self.path)
|
||||
)
|
||||
|
||||
@@ -76,7 +76,7 @@ class MockCommentServiceRequestHandler(BaseHTTPRequestHandler):
|
||||
if 'X-Edx-Api-Key' in self.headers:
|
||||
response = self.server._response_str
|
||||
# Log the response
|
||||
logger.debug(u"Comment Service: sending response %s", json.dumps(response))
|
||||
logger.debug("Comment Service: sending response %s", json.dumps(response))
|
||||
|
||||
# Send a response back to the client
|
||||
self.send_response(200)
|
||||
|
||||
@@ -15,7 +15,7 @@ class MockCommentServiceServerTest(unittest.TestCase):
|
||||
'''
|
||||
|
||||
def setUp(self):
|
||||
super(MockCommentServiceServerTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
# This is a test of the test setup,
|
||||
# so it does not need to run as part of the unit test suite
|
||||
@@ -44,8 +44,8 @@ class MockCommentServiceServerTest(unittest.TestCase):
|
||||
of how you would create a new user
|
||||
"""
|
||||
# Send a request
|
||||
values = {'username': u'user100',
|
||||
'external_id': '4', 'email': u'user100@edx.org'}
|
||||
values = {'username': 'user100',
|
||||
'external_id': '4', 'email': 'user100@edx.org'}
|
||||
data = json.dumps(values)
|
||||
headers = {'Content-Type': 'application/json', 'Content-Length': len(data), 'X-Edx-Api-Key': 'TEST_API_KEY'}
|
||||
req = six.moves.urllib.request.Request(self.server_url + '/api/v1/users/4', data, headers) # lint-amnesty, pylint: disable=undefined-variable
|
||||
|
||||
@@ -3,7 +3,6 @@ import json
|
||||
|
||||
import django.http
|
||||
from django.test import TestCase
|
||||
from six import text_type
|
||||
|
||||
import lms.djangoapps.discussion.django_comment_client.middleware as middleware
|
||||
import openedx.core.djangoapps.django_comment_common.comment_client as comment_client
|
||||
@@ -12,7 +11,7 @@ import openedx.core.djangoapps.django_comment_common.comment_client as comment_c
|
||||
class AjaxExceptionTestCase(TestCase): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
|
||||
def setUp(self):
|
||||
super(AjaxExceptionTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.a = middleware.AjaxExceptionMiddleware()
|
||||
self.request1 = django.http.HttpRequest()
|
||||
self.request0 = django.http.HttpRequest()
|
||||
@@ -26,12 +25,12 @@ class AjaxExceptionTestCase(TestCase): # lint-amnesty, pylint: disable=missing-
|
||||
response1 = self.a.process_exception(self.request1, self.exception1)
|
||||
assert isinstance(response1, middleware.JsonError)
|
||||
assert self.exception1.status_code == response1.status_code
|
||||
assert {'errors': json.loads(text_type(self.exception1))} == json.loads(response1.content.decode('utf-8'))
|
||||
assert {'errors': json.loads(str(self.exception1))} == json.loads(response1.content.decode('utf-8'))
|
||||
|
||||
response2 = self.a.process_exception(self.request1, self.exception2)
|
||||
assert isinstance(response2, middleware.JsonError)
|
||||
assert self.exception2.status_code == response2.status_code
|
||||
assert {'errors': [text_type(self.exception2)]} == json.loads(response2.content.decode('utf-8'))
|
||||
assert {'errors': [str(self.exception2)]} == json.loads(response2.content.decode('utf-8'))
|
||||
|
||||
assert self.a.process_exception(self.request1, self.exception0) is None
|
||||
assert self.a.process_exception(self.request0, self.exception1) is None
|
||||
|
||||
@@ -18,7 +18,7 @@ class RoleClassTestCase(ModuleStoreTestCase):
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
super(RoleClassTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
# For course ID, syntax edx/classname/classdate is important
|
||||
# because xmodel.course_module.id_to_location looks for a string to split
|
||||
@@ -58,7 +58,7 @@ class PermissionClassTestCase(TestCase):
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(PermissionClassTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.permission = models.Permission.objects.get_or_create(name="test")[0]
|
||||
|
||||
def test_unicode(self):
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
# pylint: skip-file
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import sys
|
||||
from unittest import mock
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
import pytest
|
||||
import six
|
||||
from django.test import RequestFactory, TestCase
|
||||
from django.urls import reverse
|
||||
from edx_django_utils.cache import RequestCache
|
||||
from mock import Mock, patch
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from pytz import UTC
|
||||
from six import text_type
|
||||
|
||||
import lms.djangoapps.discussion.django_comment_client.utils as utils
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
|
||||
from common.djangoapps.student.roles import CourseStaffRole
|
||||
from common.djangoapps.student.tests.factories import AdminFactory, CourseEnrollmentFactory, UserFactory
|
||||
from lms.djangoapps.courseware.tabs import get_course_tab_list
|
||||
from lms.djangoapps.courseware.tests.factories import InstructorFactory
|
||||
from lms.djangoapps.discussion.django_comment_client.constants import TYPE_ENTRY, TYPE_SUBCATEGORY
|
||||
@@ -47,8 +46,6 @@ from openedx.core.djangoapps.django_comment_common.utils import (
|
||||
set_course_discussion_settings
|
||||
)
|
||||
from openedx.core.djangoapps.util.testing import ContentGroupTestCase
|
||||
from common.djangoapps.student.roles import CourseStaffRole
|
||||
from common.djangoapps.student.tests.factories import AdminFactory, CourseEnrollmentFactory, UserFactory
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_MODULESTORE, ModuleStoreTestCase
|
||||
@@ -81,7 +78,7 @@ class AccessUtilsTestCase(ModuleStoreTestCase):
|
||||
CREATE_USER = False
|
||||
|
||||
def setUp(self):
|
||||
super(AccessUtilsTestCase, self).setUp()
|
||||
super().setUp()
|
||||
|
||||
self.course = CourseFactory.create()
|
||||
self.course_id = self.course.id
|
||||
@@ -105,7 +102,7 @@ class AccessUtilsTestCase(ModuleStoreTestCase):
|
||||
|
||||
def test_get_role_ids(self):
|
||||
ret = utils.get_role_ids(self.course_id)
|
||||
expected = {u'Moderator': [3], u'Community TA': [4, 5]}
|
||||
expected = {'Moderator': [3], 'Community TA': [4, 5]}
|
||||
assert ret == expected
|
||||
|
||||
def test_has_discussion_privileges(self):
|
||||
@@ -134,7 +131,7 @@ class CoursewareContextTestCase(ModuleStoreTestCase):
|
||||
comment client service integration
|
||||
"""
|
||||
def setUp(self):
|
||||
super(CoursewareContextTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create(org="TestX", number="101", display_name="Test Course")
|
||||
self.discussion1 = ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
@@ -170,7 +167,7 @@ class CoursewareContextTestCase(ModuleStoreTestCase):
|
||||
def assertThreadCorrect(thread, discussion, expected_title): # pylint: disable=invalid-name
|
||||
"""Asserts that the given thread has the expected set of properties"""
|
||||
assert set(thread.keys()) == set(['commentable_id', 'courseware_url', 'courseware_title'])
|
||||
assert thread.get('courseware_url') == reverse('jump_to', kwargs={'course_id': text_type(self.course.id), 'location': text_type(discussion.location)})
|
||||
assert thread.get('courseware_url') == reverse('jump_to', kwargs={'course_id': str(self.course.id), 'location': str(discussion.location)})
|
||||
assert thread.get('courseware_title') == expected_title
|
||||
|
||||
assertThreadCorrect(threads[0], self.discussion1, "Chapter / Discussion 1")
|
||||
@@ -228,7 +225,7 @@ class CachedDiscussionIdMapTestCase(ModuleStoreTestCase):
|
||||
ENABLED_SIGNALS = ['course_published']
|
||||
|
||||
def setUp(self):
|
||||
super(CachedDiscussionIdMapTestCase, self).setUp()
|
||||
super().setUp()
|
||||
|
||||
self.course = CourseFactory.create(org='TestX', number='101', display_name='Test Course')
|
||||
self.discussion = ItemFactory.create(
|
||||
@@ -340,7 +337,7 @@ class CachedDiscussionIdMapTestCase(ModuleStoreTestCase):
|
||||
assert not utils.discussion_category_id_access(self.course, user, 'private_discussion_id')
|
||||
|
||||
|
||||
class CategoryMapTestMixin(object):
|
||||
class CategoryMapTestMixin:
|
||||
"""
|
||||
Provides functionality for classes that test
|
||||
`get_discussion_category_map`.
|
||||
@@ -361,7 +358,7 @@ class CategoryMapTestCase(CategoryMapTestMixin, ModuleStoreTestCase):
|
||||
comment client service integration
|
||||
"""
|
||||
def setUp(self):
|
||||
super(CategoryMapTestCase, self).setUp()
|
||||
super().setUp()
|
||||
|
||||
self.course = CourseFactory.create(
|
||||
org="TestX", number="101", display_name="Test Course",
|
||||
@@ -382,7 +379,7 @@ class CategoryMapTestCase(CategoryMapTestMixin, ModuleStoreTestCase):
|
||||
return ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
category="discussion",
|
||||
discussion_id="discussion{}".format(self.discussion_num),
|
||||
discussion_id=f"discussion{self.discussion_num}",
|
||||
discussion_category=discussion_category,
|
||||
discussion_target=discussion_target,
|
||||
**kwargs
|
||||
@@ -676,7 +673,7 @@ class CategoryMapTestCase(CategoryMapTestMixin, ModuleStoreTestCase):
|
||||
def test_start_date_filter(self):
|
||||
now = datetime.datetime.now()
|
||||
self.create_discussion("Chapter 1", "Discussion 1", start=now)
|
||||
self.create_discussion("Chapter 1", u"Discussion 2 обсуждение", start=self.later)
|
||||
self.create_discussion("Chapter 1", "Discussion 2 обсуждение", start=self.later)
|
||||
self.create_discussion("Chapter 2", "Discussion", start=now)
|
||||
self.create_discussion("Chapter 2 / Section 1 / Subsection 1", "Discussion", start=self.later)
|
||||
self.create_discussion("Chapter 2 / Section 1 / Subsection 2", "Discussion", start=self.later)
|
||||
@@ -1003,11 +1000,8 @@ class CategoryMapTestCase(CategoryMapTestMixin, ModuleStoreTestCase):
|
||||
"Topic B": {"id": "Topic_B"},
|
||||
"Topic C": {"id": "Topic_C"}
|
||||
}
|
||||
six.assertCountEqual(
|
||||
self,
|
||||
utils.get_discussion_categories_ids(self.course, self.user),
|
||||
["Topic_A", "Topic_B", "Topic_C"]
|
||||
)
|
||||
assert len(utils.get_discussion_categories_ids(self.course, self.user)) ==\
|
||||
len(["Topic_A", "Topic_B", "Topic_C"])
|
||||
|
||||
def test_ids_inline(self):
|
||||
self.create_discussion("Chapter 1", "Discussion 1")
|
||||
@@ -1016,11 +1010,8 @@ class CategoryMapTestCase(CategoryMapTestMixin, ModuleStoreTestCase):
|
||||
self.create_discussion("Chapter 2 / Section 1 / Subsection 1", "Discussion")
|
||||
self.create_discussion("Chapter 2 / Section 1 / Subsection 2", "Discussion")
|
||||
self.create_discussion("Chapter 3 / Section 1", "Discussion")
|
||||
six.assertCountEqual(
|
||||
self,
|
||||
utils.get_discussion_categories_ids(self.course, self.user),
|
||||
["discussion1", "discussion2", "discussion3", "discussion4", "discussion5", "discussion6"]
|
||||
)
|
||||
assert len(utils.get_discussion_categories_ids(self.course, self.user)) ==\
|
||||
len(["discussion1", "discussion2", "discussion3", "discussion4", "discussion5", "discussion6"])
|
||||
|
||||
def test_ids_mixed(self):
|
||||
self.course.discussion_topics = {
|
||||
@@ -1031,11 +1022,8 @@ class CategoryMapTestCase(CategoryMapTestMixin, ModuleStoreTestCase):
|
||||
self.create_discussion("Chapter 1", "Discussion 1")
|
||||
self.create_discussion("Chapter 2", "Discussion")
|
||||
self.create_discussion("Chapter 2 / Section 1 / Subsection 1", "Discussion")
|
||||
six.assertCountEqual(
|
||||
self,
|
||||
utils.get_discussion_categories_ids(self.course, self.user),
|
||||
["Topic_A", "Topic_B", "Topic_C", "discussion1", "discussion2", "discussion3"]
|
||||
)
|
||||
assert len(utils.get_discussion_categories_ids(self.course, self.user)) ==\
|
||||
len(["Topic_A", "Topic_B", "Topic_C", "discussion1", "discussion2", "discussion3"])
|
||||
|
||||
|
||||
class ContentGroupCategoryMapTestCase(CategoryMapTestMixin, ContentGroupTestCase):
|
||||
@@ -1212,7 +1200,7 @@ class DiscussionTabTestCase(ModuleStoreTestCase):
|
||||
""" Test visibility of the discussion tab. """
|
||||
|
||||
def setUp(self):
|
||||
super(DiscussionTabTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create()
|
||||
self.enrolled_user = UserFactory.create()
|
||||
self.staff_user = AdminFactory.create()
|
||||
@@ -1252,7 +1240,7 @@ class IsCommentableDividedTestCase(ModuleStoreTestCase):
|
||||
"""
|
||||
Make sure that course is reloaded every time--clear out the modulestore.
|
||||
"""
|
||||
super(IsCommentableDividedTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.toy_course_key = ToyCourseFactory.create().id
|
||||
|
||||
def test_is_commentable_divided(self):
|
||||
@@ -1385,7 +1373,7 @@ class GroupIdForUserTestCase(ModuleStoreTestCase):
|
||||
""" Test the get_group_id_for_user method. """
|
||||
|
||||
def setUp(self):
|
||||
super(GroupIdForUserTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create()
|
||||
CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.AUDIT)
|
||||
CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.VERIFIED)
|
||||
@@ -1425,7 +1413,7 @@ class CourseDiscussionDivisionEnabledTestCase(ModuleStoreTestCase):
|
||||
""" Test the course_discussion_division_enabled and available_division_schemes methods. """
|
||||
|
||||
def setUp(self):
|
||||
super(CourseDiscussionDivisionEnabledTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create()
|
||||
CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.AUDIT)
|
||||
self.test_cohort = CohortFactory(
|
||||
@@ -1471,7 +1459,7 @@ class GroupNameTestCase(ModuleStoreTestCase):
|
||||
""" Test the get_group_name and get_group_names_by_id methods. """
|
||||
|
||||
def setUp(self):
|
||||
super(GroupNameTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create()
|
||||
CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.AUDIT)
|
||||
CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.VERIFIED)
|
||||
@@ -1585,7 +1573,7 @@ class GroupModeratorPermissionsTestCase(ModuleStoreTestCase):
|
||||
return True if condition == 'is_open' or condition == 'is_team_member_if_applicable' else False
|
||||
|
||||
def setUp(self):
|
||||
super(GroupModeratorPermissionsTestCase, self).setUp()
|
||||
super().setUp()
|
||||
|
||||
# Create course, seed permissions roles, and create team
|
||||
self.course = CourseFactory.create()
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
# lint-amnesty, pylint: disable=missing-module-docstring
|
||||
|
||||
|
||||
class UnicodeTestMixin(object): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
class UnicodeTestMixin: # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
def test_ascii(self):
|
||||
self._test_unicode_data(u"This post contains ASCII.")
|
||||
self._test_unicode_data("This post contains ASCII.")
|
||||
|
||||
def test_latin_1(self):
|
||||
self._test_unicode_data(u"Thís pøst çòñtáins Lätin-1 tæxt")
|
||||
self._test_unicode_data("Thís pøst çòñtáins Lätin-1 tæxt")
|
||||
|
||||
def test_CJK(self):
|
||||
self._test_unicode_data(u"イんノ丂 アo丂イ co刀イムノ刀丂 cフズ")
|
||||
self._test_unicode_data("イんノ丂 アo丂イ co刀イムノ刀丂 cフズ")
|
||||
|
||||
def test_non_BMP(self):
|
||||
self._test_unicode_data(u"𝕋𝕙𝕚𝕤 𝕡𝕠𝕤𝕥 𝕔𝕠𝕟𝕥𝕒𝕚𝕟𝕤 𝕔𝕙𝕒𝕣𝕒𝕔𝕥𝕖𝕣𝕤 𝕠𝕦𝕥𝕤𝕚𝕕𝕖 𝕥𝕙𝕖 𝔹𝕄ℙ")
|
||||
self._test_unicode_data("𝕋𝕙𝕚𝕤 𝕡𝕠𝕤𝕥 𝕔𝕠𝕟𝕥𝕒𝕚𝕟𝕤 𝕔𝕙𝕒𝕣𝕒𝕔𝕥𝕖𝕣𝕤 𝕠𝕦𝕥𝕤𝕚𝕕𝕖 𝕥𝕙𝕖 𝔹𝕄ℙ")
|
||||
|
||||
def test_special_chars(self):
|
||||
self._test_unicode_data(
|
||||
u"\" This , post > contains < delimiter ] and [ other } special { characters ; that & may ' break things"
|
||||
"\" This , post > contains < delimiter ] and [ other } special { characters ; that & may ' break things"
|
||||
)
|
||||
|
||||
def test_string_interp(self):
|
||||
self._test_unicode_data(u"This post contains %s string interpolation #{syntax}")
|
||||
self._test_unicode_data("This post contains %s string interpolation #{syntax}")
|
||||
|
||||
@@ -3,8 +3,10 @@ Utilities for tests within the django_comment_client module.
|
||||
"""
|
||||
|
||||
|
||||
from mock import patch
|
||||
from unittest.mock import patch
|
||||
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from common.djangoapps.util.testing import UrlResetMixin
|
||||
from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory
|
||||
from openedx.core.djangoapps.django_comment_common.models import ForumsConfig, Role
|
||||
from openedx.core.djangoapps.django_comment_common.utils import (
|
||||
@@ -13,20 +15,18 @@ from openedx.core.djangoapps.django_comment_common.utils import (
|
||||
set_course_discussion_settings
|
||||
)
|
||||
from openedx.core.lib.teams_config import TeamsConfig
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from common.djangoapps.util.testing import UrlResetMixin
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
|
||||
class ForumsEnableMixin(object):
|
||||
class ForumsEnableMixin:
|
||||
"""
|
||||
Ensures that the forums are enabled for a given test class.
|
||||
"""
|
||||
def setUp(self):
|
||||
super(ForumsEnableMixin, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
config = ForumsConfig.current()
|
||||
config.enabled = True
|
||||
@@ -40,7 +40,7 @@ class CohortedTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStoreTestCa
|
||||
@classmethod
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUpClass(cls):
|
||||
super(CohortedTestCase, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create(
|
||||
cohort_config={
|
||||
"cohorted": True,
|
||||
@@ -61,7 +61,7 @@ class CohortedTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStoreTestCa
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(CohortedTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
seed_permissions_roles(self.course.id)
|
||||
self.student = UserFactory.create()
|
||||
@@ -115,8 +115,8 @@ def config_course_discussions(
|
||||
division_scheme=CourseDiscussionSettings.COHORT,
|
||||
)
|
||||
|
||||
course.discussion_topics = dict((name, {"sort_key": "A", "id": to_id(name)})
|
||||
for name in discussion_topics)
|
||||
course.discussion_topics = {name: {"sort_key": "A", "id": to_id(name)}
|
||||
for name in discussion_topics}
|
||||
try:
|
||||
# Not implemented for XMLModulestore, which is used by test_cohorts.
|
||||
modulestore().update_item(course, ModuleStoreEnum.UserID.test)
|
||||
|
||||
@@ -6,18 +6,17 @@ import logging
|
||||
from collections import defaultdict
|
||||
from datetime import datetime
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import connection
|
||||
from django.http import HttpResponse
|
||||
from django.urls import reverse
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
from opaque_keys.edx.keys import CourseKey, i4xEncoder, UsageKey
|
||||
from opaque_keys.edx.keys import CourseKey, UsageKey, i4xEncoder
|
||||
from pytz import UTC
|
||||
from six import text_type
|
||||
from six.moves import map
|
||||
|
||||
from common.djangoapps.student.models import get_user_by_username_or_email
|
||||
from common.djangoapps.student.roles import GlobalStaff
|
||||
from lms.djangoapps.courseware import courses
|
||||
from lms.djangoapps.courseware.access import has_access
|
||||
from lms.djangoapps.discussion.django_comment_client.constants import TYPE_ENTRY, TYPE_SUBCATEGORY
|
||||
@@ -37,8 +36,6 @@ from openedx.core.djangoapps.django_comment_common.models import (
|
||||
)
|
||||
from openedx.core.djangoapps.django_comment_common.utils import get_course_discussion_settings
|
||||
from openedx.core.lib.cache_utils import request_cached
|
||||
from common.djangoapps.student.models import get_user_by_username_or_email
|
||||
from common.djangoapps.student.roles import GlobalStaff
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.partitions.partitions import ENROLLMENT_TRACK_PARTITION_ID
|
||||
from xmodule.partitions.partitions_service import PartitionService
|
||||
@@ -57,7 +54,7 @@ def strip_none(dic):
|
||||
"""
|
||||
Returns a dictionary stripped of any keys having values of None
|
||||
"""
|
||||
return dict([(k, v) for k, v in six.iteritems(dic) if v is not None])
|
||||
return {k: v for k, v in dic.items() if v is not None}
|
||||
|
||||
|
||||
def strip_blank(dic):
|
||||
@@ -69,7 +66,7 @@ def strip_blank(dic):
|
||||
Determines if the provided value contains no information
|
||||
"""
|
||||
return isinstance(v, str) and len(v.strip()) == 0
|
||||
return dict([(k, v) for k, v in six.iteritems(dic) if not _is_blank(v)])
|
||||
return {k: v for k, v in dic.items() if not _is_blank(v)}
|
||||
|
||||
# TODO should we be checking if d1 and d2 have the same keys with different values?
|
||||
|
||||
@@ -79,7 +76,7 @@ def get_role_ids(course_id):
|
||||
Returns a dictionary having role names as keys and a list of users as values
|
||||
"""
|
||||
roles = Role.objects.filter(course_id=course_id).exclude(name=FORUM_ROLE_STUDENT)
|
||||
return dict([(role.name, list(role.users.values_list('id', flat=True))) for role in roles])
|
||||
return {role.name: list(role.users.values_list('id', flat=True)) for role in roles}
|
||||
|
||||
|
||||
def has_discussion_privileges(user, course_id):
|
||||
@@ -129,7 +126,7 @@ def has_required_keys(xblock):
|
||||
for key in ('discussion_id', 'discussion_category', 'discussion_target'):
|
||||
if getattr(xblock, key, None) is None:
|
||||
log.debug(
|
||||
u"Required key '%s' not in discussion %s, leaving out of category map",
|
||||
"Required key '%s' not in discussion %s, leaving out of category map",
|
||||
key,
|
||||
xblock.location
|
||||
)
|
||||
@@ -281,7 +278,7 @@ def _filter_unstarted_categories(category_map, course):
|
||||
filtered_map["entries"][child][key] = unfiltered_map["entries"][child][key]
|
||||
else:
|
||||
log.debug(
|
||||
u"Filtering out:%s with start_date: %s", child, unfiltered_map["entries"][child]["start_date"]
|
||||
"Filtering out:%s with start_date: %s", child, unfiltered_map["entries"][child]["start_date"]
|
||||
)
|
||||
else:
|
||||
if course.self_paced or unfiltered_map["subcategories"][child]["start_date"] < now:
|
||||
@@ -425,7 +422,7 @@ def get_discussion_category_map(course, user, divided_only_if_explicit=False, ex
|
||||
# If we've already seen this title, append an incrementing number to disambiguate
|
||||
# the category from other categores sharing the same title in the course discussion UI.
|
||||
dupe_counters[title] += 1
|
||||
title = u"{title} ({counter})".format(title=title, counter=dupe_counters[title])
|
||||
title = "{title} ({counter})".format(title=title, counter=dupe_counters[title])
|
||||
node[level]["entries"][title] = {"id": entry["id"],
|
||||
"sort_key": entry["sort_key"],
|
||||
"start_date": entry["start_date"],
|
||||
@@ -496,8 +493,7 @@ class JsonResponse(HttpResponse):
|
||||
Object constructor, converts data (if provided) to JSON
|
||||
"""
|
||||
content = json.dumps(data, cls=i4xEncoder)
|
||||
super(JsonResponse, self).__init__(content,
|
||||
content_type='application/json; charset=utf-8')
|
||||
super().__init__(content, content_type='application/json; charset=utf-8')
|
||||
|
||||
|
||||
class JsonError(HttpResponse):
|
||||
@@ -508,11 +504,10 @@ class JsonError(HttpResponse):
|
||||
"""
|
||||
Object constructor, returns an error response containing the provided exception messages
|
||||
"""
|
||||
if isinstance(error_messages, six.string_types):
|
||||
if isinstance(error_messages, str):
|
||||
error_messages = [error_messages]
|
||||
content = json.dumps({'errors': error_messages}, indent=2, ensure_ascii=False)
|
||||
super(JsonError, self).__init__(content,
|
||||
content_type='application/json; charset=utf-8', status=status)
|
||||
super().__init__(content, content_type='application/json; charset=utf-8', status=status)
|
||||
|
||||
|
||||
class HtmlResponse(HttpResponse):
|
||||
@@ -523,7 +518,7 @@ class HtmlResponse(HttpResponse):
|
||||
"""
|
||||
Object constructor, brokers provided HTML to caller
|
||||
"""
|
||||
super(HtmlResponse, self).__init__(html, content_type='text/plain')
|
||||
super().__init__(html, content_type='text/plain')
|
||||
|
||||
|
||||
class ViewNameMiddleware(MiddlewareMixin):
|
||||
@@ -562,7 +557,7 @@ class QueryCountDebugMiddleware(MiddlewareMixin):
|
||||
query_time = query.get('duration', 0) / 1000
|
||||
total_time += float(query_time)
|
||||
|
||||
log.info(u'%s queries run, total %s seconds', len(connection.queries), total_time)
|
||||
log.info('%s queries run, total %s seconds', len(connection.queries), total_time)
|
||||
return response
|
||||
|
||||
|
||||
@@ -687,7 +682,7 @@ def get_metadata_for_threads(course_id, threads, user, user_info):
|
||||
|
||||
def permalink(content):
|
||||
if isinstance(content['course_id'], CourseKey):
|
||||
course_id = text_type(content['course_id'])
|
||||
course_id = str(content['course_id'])
|
||||
else:
|
||||
course_id = content['course_id']
|
||||
if content['type'] == 'thread':
|
||||
@@ -702,10 +697,10 @@ def extend_content(content):
|
||||
if content.get('user_id'):
|
||||
try:
|
||||
user = User.objects.get(pk=content['user_id'])
|
||||
roles = dict(('name', role.name.lower()) for role in user.roles.filter(course_id=content['course_id']))
|
||||
roles = {'name': role.name.lower() for role in user.roles.filter(course_id=content['course_id'])}
|
||||
except User.DoesNotExist:
|
||||
log.error(
|
||||
u'User ID %s in comment content %s but not in our DB.',
|
||||
'User ID %s in comment content %s but not in our DB.',
|
||||
content.get('user_id'),
|
||||
content.get('id')
|
||||
)
|
||||
@@ -735,10 +730,10 @@ def add_courseware_context(content_list, course, user, id_map=None):
|
||||
for content in content_list:
|
||||
commentable_id = content['commentable_id']
|
||||
if commentable_id in id_map:
|
||||
location = text_type(id_map[commentable_id]["location"])
|
||||
location = str(id_map[commentable_id]["location"])
|
||||
title = id_map[commentable_id]["title"]
|
||||
|
||||
url = reverse('jump_to', kwargs={"course_id": text_type(course.id),
|
||||
url = reverse('jump_to', kwargs={"course_id": str(course.id),
|
||||
"location": location})
|
||||
|
||||
content.update({"courseware_url": url, "courseware_title": title})
|
||||
@@ -787,7 +782,7 @@ def prepare_content(content, course_key, is_staff=False, discussion_division_ena
|
||||
endorser = User.objects.get(pk=endorsement["user_id"])
|
||||
except User.DoesNotExist:
|
||||
log.error(
|
||||
u"User ID %s in endorsement for comment %s but not in our DB.",
|
||||
"User ID %s in endorsement for comment %s but not in our DB.",
|
||||
content.get('user_id'),
|
||||
content.get('id')
|
||||
)
|
||||
@@ -946,7 +941,7 @@ def is_commentable_divided(course_key, commentable_id, course_discussion_setting
|
||||
# inline discussions are divided by default
|
||||
ans = True
|
||||
|
||||
log.debug(u"is_commentable_divided(%s, %s) = {%s}", course_key, commentable_id, ans)
|
||||
log.debug("is_commentable_divided(%s, %s) = {%s}", course_key, commentable_id, ans)
|
||||
return ans
|
||||
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ Enrollments.
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from openedx.core.djangoapps.django_comment_common.models import assign_default_role_on_enrollment
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from openedx.core.djangoapps.django_comment_common.models import assign_default_role_on_enrollment
|
||||
|
||||
|
||||
class Command(BaseCommand): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
@@ -26,5 +26,5 @@ class Command(BaseCommand): # lint-amnesty, pylint: disable=missing-class-docst
|
||||
for i, enrollment in enumerate(CourseEnrollment.objects.filter(course_id=course_id, is_active=1), start=1):
|
||||
assign_default_role_on_enrollment(None, enrollment)
|
||||
if i % 1000 == 0:
|
||||
print('{0}...'.format(i), end=' ')
|
||||
print(f'{i}...', end=' ')
|
||||
print()
|
||||
|
||||
@@ -8,8 +8,8 @@ Enrollments.
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from openedx.core.djangoapps.django_comment_common.models import assign_default_role_on_enrollment
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from openedx.core.djangoapps.django_comment_common.models import assign_default_role_on_enrollment
|
||||
|
||||
|
||||
class Command(BaseCommand): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
@@ -20,5 +20,5 @@ class Command(BaseCommand): # lint-amnesty, pylint: disable=missing-class-docst
|
||||
for i, enrollment in enumerate(CourseEnrollment.objects.filter(is_active=1), start=1):
|
||||
assign_default_role_on_enrollment(None, enrollment)
|
||||
if i % 1000 == 0:
|
||||
print('{0}...'.format(i), end=' ')
|
||||
print(f'{i}...', end=' ')
|
||||
print()
|
||||
|
||||
@@ -19,7 +19,7 @@ class Command(BaseCommand): # lint-amnesty, pylint: disable=missing-class-docst
|
||||
|
||||
course = get_course(course_key)
|
||||
if not course:
|
||||
raise CommandError(u'Invalid course id: {}'.format(course_id))
|
||||
raise CommandError(f'Invalid course id: {course_id}')
|
||||
|
||||
if course.discussion_link:
|
||||
self.stdout.write(course.discussion_link)
|
||||
|
||||
@@ -24,7 +24,7 @@ class Command(BaseCommand): # lint-amnesty, pylint: disable=missing-class-docst
|
||||
cc_user = cc.User.from_django_user(user)
|
||||
cc_user.save()
|
||||
except Exception as err: # lint-amnesty, pylint: disable=broad-except
|
||||
print(u'update user info to discussion failed for user with id: {}, error={}'.format(user, str(err)))
|
||||
print('update user info to discussion failed for user with id: {}, error={}'.format(user, str(err)))
|
||||
|
||||
def handle(self, *args, **options):
|
||||
if len(options['usernames']) >= 1:
|
||||
|
||||
@@ -20,16 +20,16 @@ class Command(BaseCommand): # lint-amnesty, pylint: disable=missing-class-docst
|
||||
else:
|
||||
user = User.objects.get(username=email_or_username)
|
||||
except User.DoesNotExist:
|
||||
print(u'User {} does not exist. '.format(email_or_username))
|
||||
print(f'User {email_or_username} does not exist. ')
|
||||
print('Available users: ')
|
||||
print(User.objects.all())
|
||||
return
|
||||
|
||||
roles = user.roles.all()
|
||||
print(u'{} has %d roles:'.format(user, len(roles)))
|
||||
print('{} has %d roles:'.format(user, len(roles)))
|
||||
for role in roles:
|
||||
print(u'\t{}'.format(role))
|
||||
print(f'\t{role}')
|
||||
|
||||
for role in roles:
|
||||
print(u'{} has permissions: '.format(role))
|
||||
print(f'{role} has permissions: ')
|
||||
print(role.permissions.all())
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
# pylint: disable=consider-iterating-dictionary, missing-module-docstring
|
||||
|
||||
|
||||
import json
|
||||
|
||||
import six
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import Http404
|
||||
@@ -13,6 +10,8 @@ from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from mock import patch
|
||||
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from common.djangoapps.util.testing import UrlResetMixin
|
||||
from lms.djangoapps.discussion.notification_prefs import NOTIFICATION_PREF_KEY
|
||||
from lms.djangoapps.discussion.notification_prefs.views import (
|
||||
UsernameCipher,
|
||||
@@ -22,8 +21,6 @@ from lms.djangoapps.discussion.notification_prefs.views import (
|
||||
set_subscription
|
||||
)
|
||||
from openedx.core.djangoapps.user_api.models import UserPreference
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from common.djangoapps.util.testing import UrlResetMixin
|
||||
|
||||
|
||||
@override_settings(SECRET_KEY="test secret key")
|
||||
@@ -32,7 +29,7 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(NotificationPrefViewTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory.create(username="testuser")
|
||||
# Tokens are intentionally hard-coded instead of computed to help us
|
||||
# avoid breaking existing links.
|
||||
@@ -45,7 +42,7 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
|
||||
UserFactory.create(username="thisusernameissoveryverylong"):
|
||||
"AAAAAAAAAAAAAAAAAAAAAPECbYqPI7_W4mRF8LbTaHuHt3tNXPggZ1Bke-zDyEiZ",
|
||||
# Non-ASCII username
|
||||
UserFactory.create(username=u"\u4e2d\u56fd"):
|
||||
UserFactory.create(username="\u4e2d\u56fd"):
|
||||
"AAAAAAAAAAAAAAAAAAAAAMjfGAhZKIZsI3L-Z7nflTA="
|
||||
}
|
||||
self.request_factory = RequestFactory()
|
||||
@@ -63,7 +60,7 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
|
||||
# now coerce username to utf-8 encoded str, since we test with non-ascii unicdoe above and
|
||||
# the unittest framework has hard time coercing to unicode.
|
||||
# decrypt also can't take a unicode input, so coerce its input to str
|
||||
assert six.binary_type(user.username.encode('utf-8')) == UsernameCipher().decrypt(str(pref.value))
|
||||
assert bytes(user.username.encode('utf-8')) == UsernameCipher().decrypt(str(pref.value))
|
||||
|
||||
def assertNotPrefExists(self, user):
|
||||
"""Ensure that the user does not have a persisted preference"""
|
||||
@@ -189,7 +186,7 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
|
||||
def test_unsubscribe_invalid_token(self):
|
||||
def test_invalid_token(token, message):
|
||||
request = self.request_factory.get("dummy")
|
||||
self.assertRaisesRegex(Http404, "^{}$".format(message), set_subscription, request, token, False)
|
||||
self.assertRaisesRegex(Http404, f"^{message}$", set_subscription, request, token, False)
|
||||
|
||||
# Invalid base64 encoding
|
||||
test_invalid_token("ZOMG INVALID BASE64 CHARS!!!", "base64url")
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
"""
|
||||
Views to support notification preferences.
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
import os
|
||||
from base64 import urlsafe_b64decode, urlsafe_b64encode
|
||||
from binascii import Error
|
||||
from hashlib import sha256
|
||||
|
||||
import six
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives.ciphers import Cipher
|
||||
from cryptography.hazmat.primitives.ciphers.algorithms import AES
|
||||
@@ -19,8 +18,6 @@ from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imp
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.views.decorators.http import require_GET, require_POST
|
||||
import six
|
||||
from six import text_type
|
||||
|
||||
from common.djangoapps.edxmako.shortcuts import render_to_response
|
||||
from lms.djangoapps.discussion.notification_prefs import NOTIFICATION_PREF_KEY
|
||||
@@ -34,7 +31,7 @@ class UsernameDecryptionException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class UsernameCipher(object):
|
||||
class UsernameCipher:
|
||||
"""
|
||||
A transformation of a username to/from an opaque token
|
||||
|
||||
@@ -191,7 +188,7 @@ def set_subscription(request, token, subscribe):
|
||||
except UnicodeDecodeError:
|
||||
raise Http404("base64url") # lint-amnesty, pylint: disable=raise-missing-from
|
||||
except UsernameDecryptionException as exn:
|
||||
raise Http404(text_type(exn)) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
raise Http404(str(exn)) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
except User.DoesNotExist:
|
||||
raise Http404("username") # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class DiscussionTab(TabFragmentViewMixin, EnrolledTab):
|
||||
|
||||
@classmethod
|
||||
def is_enabled(cls, course, user=None):
|
||||
if not super(DiscussionTab, cls).is_enabled(course, user):
|
||||
if not super().is_enabled(course, user):
|
||||
return False
|
||||
# Disable the regular discussion tab if LTI-based external Discussion forum is enabled
|
||||
if DiscussionLtiCourseTab.is_enabled(course, user):
|
||||
|
||||
@@ -7,7 +7,6 @@ import itertools
|
||||
from collections import defaultdict
|
||||
from enum import Enum
|
||||
|
||||
import six
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.http import Http404
|
||||
from django.urls import reverse
|
||||
@@ -64,11 +63,12 @@ from openedx.core.djangoapps.django_comment_common.signals import (
|
||||
)
|
||||
from openedx.core.djangoapps.django_comment_common.utils import get_course_discussion_settings
|
||||
from openedx.core.djangoapps.user_api.accounts.api import get_account_settings
|
||||
from openedx.core.djangoapps.user_api.accounts.views import AccountViewSet # lint-amnesty, pylint: disable=unused-import
|
||||
from openedx.core.djangoapps.user_api.accounts.views import \
|
||||
AccountViewSet # lint-amnesty, pylint: disable=unused-import
|
||||
from openedx.core.lib.exceptions import CourseNotFoundError, DiscussionNotFoundError, PageNotFoundError
|
||||
|
||||
|
||||
class DiscussionTopic(object):
|
||||
class DiscussionTopic:
|
||||
"""
|
||||
Class for discussion topic structure
|
||||
"""
|
||||
@@ -177,7 +177,7 @@ def get_thread_list_url(request, course_key, topic_id_list=None, following=False
|
||||
"""
|
||||
path = reverse("thread-list")
|
||||
query_list = (
|
||||
[("course_id", six.text_type(course_key))] +
|
||||
[("course_id", str(course_key))] +
|
||||
[("topic_id", topic_id) for topic_id in topic_id_list or []] +
|
||||
([("following", following)] if following else [])
|
||||
)
|
||||
@@ -228,7 +228,7 @@ def get_course(request, course_key):
|
||||
|
||||
course = _get_course(course_key, request.user)
|
||||
return {
|
||||
"id": six.text_type(course_key),
|
||||
"id": str(course_key),
|
||||
"blackouts": [
|
||||
{
|
||||
"start": _format_datetime(blackout["start"]),
|
||||
@@ -369,7 +369,7 @@ def get_course_topics(request, course_key, topic_ids=None):
|
||||
not_found_topic_ids = topic_ids - (existing_courseware_topic_ids | existing_non_courseware_topic_ids)
|
||||
if not_found_topic_ids:
|
||||
raise DiscussionNotFoundError(
|
||||
u"Discussion not found for '{}'.".format(", ".join(str(id) for id in not_found_topic_ids))
|
||||
"Discussion not found for '{}'.".format(", ".join(str(id) for id in not_found_topic_ids))
|
||||
)
|
||||
|
||||
return {
|
||||
@@ -576,18 +576,18 @@ def get_thread_list(
|
||||
if order_by not in cc_map:
|
||||
raise ValidationError({
|
||||
"order_by":
|
||||
[u"Invalid value. '{}' must be 'last_activity_at', 'comment_count', or 'vote_count'".format(order_by)]
|
||||
[f"Invalid value. '{order_by}' must be 'last_activity_at', 'comment_count', or 'vote_count'"]
|
||||
})
|
||||
if order_direction != "desc":
|
||||
raise ValidationError({
|
||||
"order_direction": [u"Invalid value. '{}' must be 'desc'".format(order_direction)]
|
||||
"order_direction": [f"Invalid value. '{order_direction}' must be 'desc'"]
|
||||
})
|
||||
|
||||
course = _get_course(course_key, request.user)
|
||||
context = get_context(course, request)
|
||||
|
||||
query_params = {
|
||||
"user_id": six.text_type(request.user.id),
|
||||
"user_id": str(request.user.id),
|
||||
"group_id": (
|
||||
None if context["is_requester_privileged"] else
|
||||
get_group_id_for_user(request.user, get_course_discussion_settings(course.id))
|
||||
@@ -603,13 +603,13 @@ def get_thread_list(
|
||||
query_params[view] = "true"
|
||||
else:
|
||||
ValidationError({
|
||||
"view": [u"Invalid value. '{}' must be 'unread' or 'unanswered'".format(view)]
|
||||
"view": [f"Invalid value. '{view}' must be 'unread' or 'unanswered'"]
|
||||
})
|
||||
|
||||
if following:
|
||||
paginated_results = context["cc_requester"].subscribed_threads(query_params)
|
||||
else:
|
||||
query_params["course_id"] = six.text_type(course.id)
|
||||
query_params["course_id"] = str(course.id)
|
||||
query_params["commentable_ids"] = ",".join(topic_id_list) if topic_id_list else None
|
||||
query_params["text"] = text_search
|
||||
paginated_results = Thread.search(query_params)
|
||||
@@ -1046,7 +1046,7 @@ def get_thread(request, thread_id, requested_fields=None):
|
||||
thread_id,
|
||||
retrieve_kwargs={
|
||||
"with_responses": True,
|
||||
"user_id": six.text_type(request.user.id),
|
||||
"user_id": str(request.user.id),
|
||||
}
|
||||
)
|
||||
return _serialize_discussion_entities(request, context, [cc_thread], requested_fields, DiscussionEntity.thread)[0]
|
||||
|
||||
@@ -11,7 +11,6 @@ from django.forms import BooleanField, CharField, ChoiceField, Form, IntegerFiel
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from six import text_type
|
||||
|
||||
from lms.djangoapps.courseware.courses import get_course_with_access
|
||||
from openedx.core.djangoapps.django_comment_common.models import (
|
||||
@@ -75,7 +74,7 @@ class ThreadListGetForm(_PaginationForm):
|
||||
try:
|
||||
return CourseLocator.from_string(value)
|
||||
except InvalidKeyError:
|
||||
raise ValidationError(u"'{}' is not a valid course id".format(value)) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
raise ValidationError(f"'{value}' is not a valid course id") # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
def clean_following(self):
|
||||
"""Validate following"""
|
||||
@@ -86,13 +85,13 @@ class ThreadListGetForm(_PaginationForm):
|
||||
return value
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super(ThreadListGetForm, self).clean() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
cleaned_data = super().clean()
|
||||
exclusive_params_count = sum(
|
||||
1 for param in self.EXCLUSIVE_PARAMS if cleaned_data.get(param)
|
||||
)
|
||||
if exclusive_params_count > 1:
|
||||
raise ValidationError(
|
||||
u"The following query parameters are mutually exclusive: {}".format(
|
||||
"The following query parameters are mutually exclusive: {}".format(
|
||||
", ".join(self.EXCLUSIVE_PARAMS)
|
||||
)
|
||||
)
|
||||
@@ -143,7 +142,7 @@ class CourseDiscussionSettingsForm(Form):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.request_user = kwargs.pop('request_user')
|
||||
super(CourseDiscussionSettingsForm, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def clean_course_id(self):
|
||||
"""Validate the 'course_id' value"""
|
||||
@@ -154,7 +153,7 @@ class CourseDiscussionSettingsForm(Form):
|
||||
self.cleaned_data['course_key'] = course_key
|
||||
return course_id
|
||||
except InvalidKeyError:
|
||||
raise ValidationError(u"'{}' is not a valid course key".format(text_type(course_id))) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
raise ValidationError("'{}' is not a valid course key".format(str(course_id))) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
|
||||
class CourseDiscussionRolesForm(CourseDiscussionSettingsForm):
|
||||
@@ -168,7 +167,7 @@ class CourseDiscussionRolesForm(CourseDiscussionSettingsForm):
|
||||
)
|
||||
rolename = ChoiceField(
|
||||
choices=ROLE_CHOICES,
|
||||
error_messages={u"invalid_choice": u"Role '%(value)s' does not exist"}
|
||||
error_messages={"invalid_choice": "Role '%(value)s' does not exist"}
|
||||
)
|
||||
|
||||
def clean_rolename(self):
|
||||
@@ -179,7 +178,7 @@ class CourseDiscussionRolesForm(CourseDiscussionSettingsForm):
|
||||
try:
|
||||
role = Role.objects.get(name=rolename, course_id=course_id)
|
||||
except Role.DoesNotExist:
|
||||
raise ValidationError(u"Role '{}' does not exist".format(rolename)) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
raise ValidationError(f"Role '{rolename}' does not exist") # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
self.cleaned_data['role'] = role
|
||||
return rolename
|
||||
|
||||
@@ -7,7 +7,7 @@ from edx_rest_framework_extensions.paginators import NamespacedPageNumberPaginat
|
||||
from rest_framework.utils.urls import replace_query_param
|
||||
|
||||
|
||||
class _Page(object):
|
||||
class _Page:
|
||||
"""
|
||||
Implements just enough of the django.core.paginator.Page interface to allow
|
||||
PaginationSerializer to work.
|
||||
@@ -51,7 +51,7 @@ class DiscussionAPIPagination(NamespacedPageNumberPagination):
|
||||
self.base_url = request.build_absolute_uri()
|
||||
self.count = result_count
|
||||
|
||||
super(DiscussionAPIPagination, self).__init__() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__()
|
||||
|
||||
def get_result_count(self):
|
||||
"""
|
||||
|
||||
@@ -9,6 +9,7 @@ from django.urls import reverse
|
||||
from rest_framework import serializers
|
||||
from six.moves.urllib.parse import urlencode, urlunparse
|
||||
|
||||
from common.djangoapps.student.models import get_user_by_username_or_email
|
||||
from lms.djangoapps.discussion.django_comment_client.utils import (
|
||||
course_discussion_division_enabled,
|
||||
get_group_id_for_user,
|
||||
@@ -34,7 +35,6 @@ from openedx.core.djangoapps.django_comment_common.models import (
|
||||
Role
|
||||
)
|
||||
from openedx.core.djangoapps.django_comment_common.utils import get_course_discussion_settings
|
||||
from common.djangoapps.student.models import get_user_by_username_or_email
|
||||
|
||||
|
||||
def get_context(course, request, thread=None):
|
||||
@@ -103,10 +103,10 @@ class _ContentSerializer(serializers.Serializer):
|
||||
non_updatable_fields = set()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(_ContentSerializer, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
for field in self.non_updatable_fields:
|
||||
setattr(self, "validate_{}".format(field), self._validate_non_updatable)
|
||||
setattr(self, f"validate_{field}", self._validate_non_updatable)
|
||||
|
||||
def _validate_non_updatable(self, value):
|
||||
"""Ensure that a field is not edited in an update operation."""
|
||||
@@ -223,7 +223,7 @@ class ThreadSerializer(_ContentSerializer):
|
||||
non_updatable_fields = NON_UPDATABLE_THREAD_FIELDS
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ThreadSerializer, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(*args, **kwargs)
|
||||
# Compensate for the fact that some threads in the comments service do
|
||||
# not have the pinned field set
|
||||
if self.instance and self.instance.get("pinned") is None:
|
||||
@@ -329,7 +329,7 @@ class CommentSerializer(_ContentSerializer):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
remove_fields = kwargs.pop('remove_fields', None)
|
||||
super(CommentSerializer, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if remove_fields:
|
||||
# for multiple fields in a list
|
||||
@@ -379,7 +379,7 @@ class CommentSerializer(_ContentSerializer):
|
||||
|
||||
def to_representation(self, data):
|
||||
# pylint: disable=arguments-differ
|
||||
data = super(CommentSerializer, self).to_representation(data) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
data = super().to_representation(data)
|
||||
|
||||
# Django Rest Framework v3 no longer includes None values
|
||||
# in the representation. To maintain the previous behavior,
|
||||
@@ -478,7 +478,7 @@ class DiscussionSettingsSerializer(serializers.Serializer):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.course = kwargs.pop('course')
|
||||
self.discussion_settings = kwargs.pop('discussion_settings')
|
||||
super(DiscussionSettingsSerializer, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def validate(self, attrs):
|
||||
"""
|
||||
@@ -532,7 +532,7 @@ class DiscussionRolesSerializer(serializers.Serializer):
|
||||
user_id = serializers.CharField()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DiscussionRolesSerializer, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(*args, **kwargs)
|
||||
self.user = None
|
||||
|
||||
def validate_user_id(self, user_id): # lint-amnesty, pylint: disable=missing-function-docstring
|
||||
@@ -540,7 +540,7 @@ class DiscussionRolesSerializer(serializers.Serializer):
|
||||
self.user = get_user_by_username_or_email(user_id)
|
||||
return user_id
|
||||
except DjangoUser.DoesNotExist:
|
||||
raise ValidationError(u"'{}' is not a valid student identifier".format(user_id)) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
raise ValidationError(f"'{user_id}' is not a valid student identifier") # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
def validate(self, attrs):
|
||||
"""Validate the data at an object level."""
|
||||
@@ -574,7 +574,7 @@ class DiscussionRolesMemberSerializer(serializers.Serializer):
|
||||
group_name = serializers.SerializerMethodField()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DiscussionRolesMemberSerializer, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(*args, **kwargs)
|
||||
self.course_discussion_settings = self.context['course_discussion_settings']
|
||||
|
||||
def get_group_name(self, instance):
|
||||
|
||||
@@ -5,19 +5,20 @@ Tests for Discussion API internal interface
|
||||
|
||||
import itertools
|
||||
from datetime import datetime, timedelta
|
||||
import pytest
|
||||
from unittest import mock
|
||||
|
||||
import ddt
|
||||
import httpretty
|
||||
import mock
|
||||
import six
|
||||
import pytest
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.test.client import RequestFactory
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from pytz import UTC
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
from six.moves import range
|
||||
from six.moves.urllib.parse import parse_qs, urlencode, urlparse, urlunparse
|
||||
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from common.djangoapps.util.testing import UrlResetMixin
|
||||
from common.test.utils import MockSignalHandlerMixin, disable_signal
|
||||
from lms.djangoapps.courseware.tests.factories import BetaTesterFactory, StaffFactory
|
||||
from lms.djangoapps.discussion.django_comment_client.tests.utils import ForumsEnableMixin
|
||||
@@ -57,8 +58,6 @@ from openedx.core.djangoapps.django_comment_common.models import (
|
||||
Role
|
||||
)
|
||||
from openedx.core.lib.exceptions import CourseNotFoundError, PageNotFoundError
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from common.djangoapps.util.testing import UrlResetMixin
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase
|
||||
@@ -141,12 +140,12 @@ class GetCourseTest(ForumsEnableMixin, UrlResetMixin, SharedModuleStoreTestCase)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(GetCourseTest, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create(org="x", course="y", run="z")
|
||||
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(GetCourseTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory.create()
|
||||
CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id)
|
||||
self.request = RequestFactory().get("/dummy")
|
||||
@@ -168,7 +167,7 @@ class GetCourseTest(ForumsEnableMixin, UrlResetMixin, SharedModuleStoreTestCase)
|
||||
|
||||
def test_basic(self):
|
||||
assert get_course(self.request, self.course.id) == {
|
||||
'id': six.text_type(self.course.id),
|
||||
'id': str(self.course.id),
|
||||
'blackouts': [],
|
||||
'thread_list_url': 'http://testserver/api/discussion/v1/threads/?course_id=x%2Fy%2Fz',
|
||||
'following_thread_list_url':
|
||||
@@ -186,7 +185,7 @@ class GetCourseTestBlackouts(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCa
|
||||
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(GetCourseTestBlackouts, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create(org="x", course="y", run="z")
|
||||
self.user = UserFactory.create()
|
||||
CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id)
|
||||
@@ -223,7 +222,7 @@ class GetCourseTopicsTest(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
|
||||
"""Test for get_course_topics"""
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(GetCourseTopicsTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.maxDiff = None # pylint: disable=invalid-name
|
||||
self.partition = UserPartition(
|
||||
0,
|
||||
@@ -266,7 +265,7 @@ class GetCourseTopicsTest(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
|
||||
"""
|
||||
path = "http://testserver/api/discussion/v1/threads/"
|
||||
topic_ids_to_query = [("topic_id", topic_id) for topic_id in topic_id_list]
|
||||
query_list = [("course_id", six.text_type(self.course.id))] + topic_ids_to_query
|
||||
query_list = [("course_id", str(self.course.id))] + topic_ids_to_query
|
||||
return urlunparse(("", "", path, "", urlencode(query_list), ""))
|
||||
|
||||
def get_course_topics(self):
|
||||
@@ -592,12 +591,12 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(GetThreadListTest, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(GetThreadListTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
httpretty.reset()
|
||||
httpretty.enable()
|
||||
self.addCleanup(httpretty.reset)
|
||||
@@ -662,8 +661,8 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
|
||||
self.get_thread_list([], topic_id_list=["topic_x", "topic_meow"])
|
||||
assert urlparse(httpretty.last_request().path).path == '/api/v1/threads' # lint-amnesty, pylint: disable=no-member
|
||||
self.assert_last_query_params({
|
||||
"user_id": [six.text_type(self.user.id)],
|
||||
"course_id": [six.text_type(self.course.id)],
|
||||
"user_id": [str(self.user.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"sort_key": ["activity"],
|
||||
"page": ["1"],
|
||||
"per_page": ["1"],
|
||||
@@ -673,8 +672,8 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
|
||||
def test_basic_query_params(self):
|
||||
self.get_thread_list([], page=6, page_size=14)
|
||||
self.assert_last_query_params({
|
||||
"user_id": [six.text_type(self.user.id)],
|
||||
"course_id": [six.text_type(self.course.id)],
|
||||
"user_id": [str(self.user.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"sort_key": ["activity"],
|
||||
"page": ["6"],
|
||||
"per_page": ["14"],
|
||||
@@ -686,7 +685,7 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
|
||||
source_threads = [
|
||||
make_minimal_cs_thread({
|
||||
"id": "test_thread_id_0",
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"commentable_id": "topic_x",
|
||||
"username": self.author.username,
|
||||
"user_id": str(self.author.id),
|
||||
@@ -702,7 +701,7 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
|
||||
}),
|
||||
make_minimal_cs_thread({
|
||||
"id": "test_thread_id_1",
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"commentable_id": "topic_y",
|
||||
"group_id": self.cohort.id,
|
||||
"username": self.author.username,
|
||||
@@ -828,8 +827,8 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
|
||||
text_search='test search string'
|
||||
).data == expected_result
|
||||
self.assert_last_query_params({
|
||||
"user_id": [six.text_type(self.user.id)],
|
||||
"course_id": [six.text_type(self.course.id)],
|
||||
"user_id": [str(self.user.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"sort_key": ["activity"],
|
||||
"page": ["1"],
|
||||
"per_page": ["10"],
|
||||
@@ -853,10 +852,10 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
|
||||
assert result == expected_result
|
||||
assert urlparse(
|
||||
httpretty.last_request().path # lint-amnesty, pylint: disable=no-member
|
||||
).path == '/api/v1/users/{}/subscribed_threads'.format(self.user.id)
|
||||
).path == f"/api/v1/users/{self.user.id}/subscribed_threads"
|
||||
self.assert_last_query_params({
|
||||
"user_id": [six.text_type(self.user.id)],
|
||||
"course_id": [six.text_type(self.course.id)],
|
||||
"user_id": [str(self.user.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"sort_key": ["activity"],
|
||||
"page": ["1"],
|
||||
"per_page": ["11"],
|
||||
@@ -880,8 +879,8 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
|
||||
assert result == expected_result
|
||||
assert urlparse(httpretty.last_request().path).path == '/api/v1/threads' # lint-amnesty, pylint: disable=no-member
|
||||
self.assert_last_query_params({
|
||||
"user_id": [six.text_type(self.user.id)],
|
||||
"course_id": [six.text_type(self.course.id)],
|
||||
"user_id": [str(self.user.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"sort_key": ["activity"],
|
||||
"page": ["1"],
|
||||
"per_page": ["11"],
|
||||
@@ -918,8 +917,8 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
|
||||
assert result == expected_result
|
||||
assert urlparse(httpretty.last_request().path).path == '/api/v1/threads' # lint-amnesty, pylint: disable=no-member
|
||||
self.assert_last_query_params({
|
||||
"user_id": [six.text_type(self.user.id)],
|
||||
"course_id": [six.text_type(self.course.id)],
|
||||
"user_id": [str(self.user.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"sort_key": [cc_query],
|
||||
"page": ["1"],
|
||||
"per_page": ["11"],
|
||||
@@ -946,8 +945,8 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
|
||||
assert result == expected_result
|
||||
assert urlparse(httpretty.last_request().path).path == '/api/v1/threads' # lint-amnesty, pylint: disable=no-member
|
||||
self.assert_last_query_params({
|
||||
"user_id": [six.text_type(self.user.id)],
|
||||
"course_id": [six.text_type(self.course.id)],
|
||||
"user_id": [str(self.user.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"sort_key": ["activity"],
|
||||
"page": ["1"],
|
||||
"per_page": ["11"],
|
||||
@@ -976,12 +975,12 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(GetCommentListTest, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(GetCommentListTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
httpretty.reset()
|
||||
httpretty.enable()
|
||||
self.addCleanup(httpretty.reset)
|
||||
@@ -1000,7 +999,7 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
|
||||
already in overrides.
|
||||
"""
|
||||
overrides = overrides.copy() if overrides else {}
|
||||
overrides.setdefault("course_id", six.text_type(self.course.id))
|
||||
overrides.setdefault("course_id", str(self.course.id))
|
||||
return make_minimal_cs_thread(overrides)
|
||||
|
||||
def get_comment_list(self, thread, endorsed=None, page=1, page_size=1):
|
||||
@@ -1031,7 +1030,7 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
|
||||
with pytest.raises(DiscussionDisabledError):
|
||||
self.get_comment_list(
|
||||
self.make_minimal_cs_thread(
|
||||
overrides={"course_id": six.text_type(disabled_course.id)}
|
||||
overrides={"course_id": str(disabled_course.id)}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1067,7 +1066,7 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
|
||||
cohort = CohortFactory.create(course_id=cohort_course.id, users=[self.user])
|
||||
_assign_role_to_user(user=self.user, course_id=cohort_course.id, role=role_name)
|
||||
thread = self.make_minimal_cs_thread({
|
||||
"course_id": six.text_type(cohort_course.id),
|
||||
"course_id": str(cohort_course.id),
|
||||
"commentable_id": "test_topic",
|
||||
"group_id": (
|
||||
None if thread_group_state == "no_group" else
|
||||
@@ -1319,7 +1318,7 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
|
||||
thread = self.make_minimal_cs_thread({
|
||||
"thread_type": "question",
|
||||
"endorsed_responses": [make_minimal_cs_comment({
|
||||
"id": "comment_{}".format(i),
|
||||
"id": f"comment_{i}",
|
||||
"username": self.user.username
|
||||
}) for i in range(10)]
|
||||
})
|
||||
@@ -1331,12 +1330,12 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
|
||||
"""
|
||||
actual = self.get_comment_list(thread, endorsed=True, page=page, page_size=page_size).data
|
||||
result_ids = [result["id"] for result in actual["results"]]
|
||||
assert result_ids == ['comment_{}'.format(i) for i in range(expected_start, expected_stop)]
|
||||
assert result_ids == [f"comment_{i}" for i in range(expected_start, expected_stop)]
|
||||
assert actual['pagination']['next'] == (
|
||||
'http://testserver/test_path?page={}'.format(expected_next) if expected_next else None
|
||||
f"http://testserver/test_path?page={expected_next}" if expected_next else None
|
||||
)
|
||||
assert actual['pagination']['previous'] == (
|
||||
'http://testserver/test_path?page={}'.format(expected_prev) if expected_prev else None
|
||||
f"http://testserver/test_path?page={expected_prev}" if expected_prev else None
|
||||
)
|
||||
|
||||
# Only page
|
||||
@@ -1437,7 +1436,7 @@ class CreateThreadTest(
|
||||
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(CreateThreadTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create()
|
||||
httpretty.reset()
|
||||
httpretty.enable()
|
||||
@@ -1449,7 +1448,7 @@ class CreateThreadTest(
|
||||
self.request.user = self.user
|
||||
CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id)
|
||||
self.minimal_data = {
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"topic_id": "test_topic",
|
||||
"type": "discussion",
|
||||
"title": "Test Title",
|
||||
@@ -1468,13 +1467,13 @@ class CreateThreadTest(
|
||||
actual = create_thread(self.request, self.minimal_data)
|
||||
expected = self.expected_thread_data({
|
||||
"id": "test_id",
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_id",
|
||||
"read": True,
|
||||
})
|
||||
assert actual == expected
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'course_id': [six.text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'commentable_id': ['test_topic'],
|
||||
'thread_type': ['discussion'],
|
||||
'title': ['Test Title'],
|
||||
@@ -1532,7 +1531,7 @@ class CreateThreadTest(
|
||||
expected = self.expected_thread_data({
|
||||
"author_label": "Staff",
|
||||
"id": "test_id",
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_id",
|
||||
"read": True,
|
||||
})
|
||||
@@ -1540,7 +1539,7 @@ class CreateThreadTest(
|
||||
self.assertEqual(
|
||||
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member
|
||||
{
|
||||
"course_id": [six.text_type(self.course.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"commentable_id": ["test_topic"],
|
||||
"thread_type": ["discussion"],
|
||||
"title": ["Test Title"],
|
||||
@@ -1639,7 +1638,7 @@ class CreateThreadTest(
|
||||
_assign_role_to_user(user=self.user, course_id=cohort_course.id, role=role_name)
|
||||
self.register_post_thread_response({"username": self.user.username})
|
||||
data = self.minimal_data.copy()
|
||||
data["course_id"] = six.text_type(cohort_course.id)
|
||||
data["course_id"] = str(cohort_course.id)
|
||||
if data_group_state == "group_is_none":
|
||||
data["group_id"] = None
|
||||
elif data_group_state == "group_is_set":
|
||||
@@ -1663,7 +1662,7 @@ class CreateThreadTest(
|
||||
assert 'group_id' not in actual_post_data
|
||||
except ValidationError as ex:
|
||||
if not expected_error:
|
||||
self.fail(u"Unexpected validation error: {}".format(ex))
|
||||
self.fail(f"Unexpected validation error: {ex}")
|
||||
|
||||
def test_following(self):
|
||||
self.register_post_thread_response({"id": "test_id", "username": self.user.username})
|
||||
@@ -1673,7 +1672,7 @@ class CreateThreadTest(
|
||||
result = create_thread(self.request, data)
|
||||
assert result['following'] is True
|
||||
cs_request = httpretty.last_request()
|
||||
assert urlparse(cs_request.path).path == '/api/v1/users/{}/subscriptions'.format(self.user.id) # lint-amnesty, pylint: disable=no-member
|
||||
assert urlparse(cs_request.path).path == f"/api/v1/users/{self.user.id}/subscriptions" # lint-amnesty, pylint: disable=no-member
|
||||
assert cs_request.method == 'POST'
|
||||
assert cs_request.parsed_body == {'source_type': ['thread'], 'source_id': ['test_id']} # lint-amnesty, pylint: disable=no-member
|
||||
|
||||
@@ -1723,7 +1722,7 @@ class CreateThreadTest(
|
||||
|
||||
def test_discussions_disabled(self):
|
||||
disabled_course = _discussion_disabled_course_for(self.user)
|
||||
self.minimal_data["course_id"] = six.text_type(disabled_course.id)
|
||||
self.minimal_data["course_id"] = str(disabled_course.id)
|
||||
with pytest.raises(DiscussionDisabledError):
|
||||
create_thread(self.request, self.minimal_data)
|
||||
|
||||
@@ -1746,10 +1745,14 @@ class CreateCommentTest(
|
||||
MockSignalHandlerMixin
|
||||
):
|
||||
"""Tests for create_comment"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(CreateCommentTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
httpretty.reset()
|
||||
httpretty.enable()
|
||||
self.course = CourseFactory.create()
|
||||
@@ -1763,7 +1766,7 @@ class CreateCommentTest(
|
||||
self.register_get_thread_response(
|
||||
make_minimal_cs_thread({
|
||||
"id": "test_thread",
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"commentable_id": "test_topic",
|
||||
})
|
||||
)
|
||||
@@ -1815,12 +1818,12 @@ class CreateCommentTest(
|
||||
}
|
||||
assert actual == expected
|
||||
expected_url = (
|
||||
"/api/v1/comments/{}".format(parent_id) if parent_id else
|
||||
f"/api/v1/comments/{parent_id}" if parent_id else
|
||||
"/api/v1/threads/test_thread/comments"
|
||||
)
|
||||
assert urlparse(httpretty.last_request().path).path == expected_url # lint-amnesty, pylint: disable=no-member
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'course_id': [six.text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'body': ['Test body'],
|
||||
'user_id': [str(self.user.id)]
|
||||
}
|
||||
@@ -1905,7 +1908,7 @@ class CreateCommentTest(
|
||||
self.assertEqual(
|
||||
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member
|
||||
{
|
||||
"course_id": [six.text_type(self.course.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"body": ["Test body"],
|
||||
"user_id": [str(self.user.id)]
|
||||
}
|
||||
@@ -1960,7 +1963,7 @@ class CreateCommentTest(
|
||||
self.register_get_thread_response(
|
||||
make_minimal_cs_thread({
|
||||
"id": "test_thread",
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"thread_type": thread_type,
|
||||
"user_id": str(self.user.id) if is_thread_author else str(self.user.id + 1),
|
||||
})
|
||||
@@ -2031,7 +2034,7 @@ class CreateCommentTest(
|
||||
self.register_get_thread_response(
|
||||
make_minimal_cs_thread({
|
||||
"id": "test_thread",
|
||||
"course_id": six.text_type(disabled_course.id),
|
||||
"course_id": str(disabled_course.id),
|
||||
"commentable_id": "test_topic",
|
||||
})
|
||||
)
|
||||
@@ -2055,7 +2058,7 @@ class CreateCommentTest(
|
||||
cohort_course, cohort = _create_course_and_cohort_with_user_role(course_is_cohorted, self.user, role_name)
|
||||
self.register_get_thread_response(make_minimal_cs_thread({
|
||||
"id": "cohort_thread",
|
||||
"course_id": six.text_type(cohort_course.id),
|
||||
"course_id": str(cohort_course.id),
|
||||
"group_id": (
|
||||
None if thread_group_state == "no_group" else
|
||||
cohort.id if thread_group_state == "match_group" else
|
||||
@@ -2097,12 +2100,12 @@ class UpdateThreadTest(
|
||||
"""Tests for update_thread"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(UpdateThreadTest, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(UpdateThreadTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
httpretty.reset()
|
||||
httpretty.enable()
|
||||
self.addCleanup(httpretty.reset)
|
||||
@@ -2122,7 +2125,7 @@ class UpdateThreadTest(
|
||||
"""
|
||||
cs_data = make_minimal_cs_thread({
|
||||
"id": "test_thread",
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"commentable_id": "original_topic",
|
||||
"username": self.user.username,
|
||||
"user_id": str(self.user.id),
|
||||
@@ -2156,7 +2159,7 @@ class UpdateThreadTest(
|
||||
'title': 'Original Title'
|
||||
})
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'course_id': [six.text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'commentable_id': ['original_topic'],
|
||||
'thread_type': ['discussion'],
|
||||
'title': ['Original Title'],
|
||||
@@ -2187,7 +2190,7 @@ class UpdateThreadTest(
|
||||
|
||||
def test_discussions_disabled(self):
|
||||
disabled_course = _discussion_disabled_course_for(self.user)
|
||||
self.register_thread(overrides={"course_id": six.text_type(disabled_course.id)})
|
||||
self.register_thread(overrides={"course_id": str(disabled_course.id)})
|
||||
with pytest.raises(DiscussionDisabledError):
|
||||
update_thread(self.request, "test_thread", {})
|
||||
|
||||
@@ -2207,7 +2210,7 @@ class UpdateThreadTest(
|
||||
def test_group_access(self, role_name, course_is_cohorted, thread_group_state):
|
||||
cohort_course, cohort = _create_course_and_cohort_with_user_role(course_is_cohorted, self.user, role_name)
|
||||
self.register_thread({
|
||||
"course_id": six.text_type(cohort_course.id),
|
||||
"course_id": str(cohort_course.id),
|
||||
"group_id": (
|
||||
None if thread_group_state == "no_group" else
|
||||
cohort.id if thread_group_state == "match_group" else
|
||||
@@ -2264,7 +2267,7 @@ class UpdateThreadTest(
|
||||
result = update_thread(self.request, "test_thread", data)
|
||||
assert result['following'] == new_following
|
||||
last_request_path = urlparse(httpretty.last_request().path).path # lint-amnesty, pylint: disable=no-member
|
||||
subscription_url = "/api/v1/users/{}/subscriptions".format(self.user.id)
|
||||
subscription_url = f"/api/v1/users/{self.user.id}/subscriptions"
|
||||
if old_following == new_following:
|
||||
assert last_request_path != subscription_url
|
||||
else:
|
||||
@@ -2450,12 +2453,12 @@ class UpdateCommentTest(
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(UpdateCommentTest, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(UpdateCommentTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
httpretty.reset()
|
||||
httpretty.enable()
|
||||
@@ -2479,7 +2482,7 @@ class UpdateCommentTest(
|
||||
|
||||
cs_thread_data = make_minimal_cs_thread({
|
||||
"id": "test_thread",
|
||||
"course_id": six.text_type(course.id)
|
||||
"course_id": str(course.id)
|
||||
})
|
||||
cs_thread_data.update(thread_overrides or {})
|
||||
self.register_get_thread_response(cs_thread_data)
|
||||
@@ -2533,7 +2536,7 @@ class UpdateCommentTest(
|
||||
assert actual == expected
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'body': ['Edited body'],
|
||||
'course_id': [six.text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'user_id': [str(self.user.id)],
|
||||
'anonymous': ['False'],
|
||||
'anonymous_to_peers': ['False'],
|
||||
@@ -2581,7 +2584,7 @@ class UpdateCommentTest(
|
||||
{"thread_id": "test_thread"},
|
||||
thread_overrides={
|
||||
"id": "test_thread",
|
||||
"course_id": six.text_type(cohort_course.id),
|
||||
"course_id": str(cohort_course.id),
|
||||
"group_id": (
|
||||
None if thread_group_state == "no_group" else
|
||||
cohort.id if thread_group_state == "match_group" else
|
||||
@@ -2827,12 +2830,12 @@ class DeleteThreadTest(
|
||||
"""Tests for delete_thread"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(DeleteThreadTest, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(DeleteThreadTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
httpretty.reset()
|
||||
httpretty.enable()
|
||||
self.addCleanup(httpretty.reset)
|
||||
@@ -2852,7 +2855,7 @@ class DeleteThreadTest(
|
||||
"""
|
||||
cs_data = make_minimal_cs_thread({
|
||||
"id": self.thread_id,
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"user_id": str(self.user.id),
|
||||
})
|
||||
cs_data.update(overrides or {})
|
||||
@@ -2863,7 +2866,7 @@ class DeleteThreadTest(
|
||||
self.register_thread()
|
||||
with self.assert_signal_sent(api, 'thread_deleted', sender=None, user=self.user, exclude_args=('post',)):
|
||||
assert delete_thread(self.request, self.thread_id) is None
|
||||
assert urlparse(httpretty.last_request().path).path == '/api/v1/threads/{}'.format(self.thread_id) # lint-amnesty, pylint: disable=no-member
|
||||
assert urlparse(httpretty.last_request().path).path == f"/api/v1/threads/{self.thread_id}" # lint-amnesty, pylint: disable=no-member
|
||||
assert httpretty.last_request().method == 'DELETE'
|
||||
|
||||
def test_thread_id_not_found(self):
|
||||
@@ -2884,7 +2887,7 @@ class DeleteThreadTest(
|
||||
|
||||
def test_discussions_disabled(self):
|
||||
disabled_course = _discussion_disabled_course_for(self.user)
|
||||
self.register_thread(overrides={"course_id": six.text_type(disabled_course.id)})
|
||||
self.register_thread(overrides={"course_id": str(disabled_course.id)})
|
||||
with pytest.raises(DiscussionDisabledError):
|
||||
delete_thread(self.request, self.thread_id)
|
||||
|
||||
@@ -2928,7 +2931,7 @@ class DeleteThreadTest(
|
||||
"""
|
||||
cohort_course, cohort = _create_course_and_cohort_with_user_role(course_is_cohorted, self.user, role_name)
|
||||
self.register_thread({
|
||||
"course_id": six.text_type(cohort_course.id),
|
||||
"course_id": str(cohort_course.id),
|
||||
"group_id": (
|
||||
None if thread_group_state == "no_group" else
|
||||
cohort.id if thread_group_state == "match_group" else
|
||||
@@ -2960,12 +2963,12 @@ class DeleteCommentTest(
|
||||
"""Tests for delete_comment"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(DeleteCommentTest, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(DeleteCommentTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
httpretty.reset()
|
||||
httpretty.enable()
|
||||
self.addCleanup(httpretty.reset)
|
||||
@@ -2986,7 +2989,7 @@ class DeleteCommentTest(
|
||||
"""
|
||||
cs_thread_data = make_minimal_cs_thread({
|
||||
"id": self.thread_id,
|
||||
"course_id": six.text_type(self.course.id)
|
||||
"course_id": str(self.course.id)
|
||||
})
|
||||
cs_thread_data.update(thread_overrides or {})
|
||||
self.register_get_thread_response(cs_thread_data)
|
||||
@@ -3005,7 +3008,7 @@ class DeleteCommentTest(
|
||||
self.register_comment_and_thread()
|
||||
with self.assert_signal_sent(api, 'comment_deleted', sender=None, user=self.user, exclude_args=('post',)):
|
||||
assert delete_comment(self.request, self.comment_id) is None
|
||||
assert urlparse(httpretty.last_request().path).path == '/api/v1/comments/{}'.format(self.comment_id) # lint-amnesty, pylint: disable=no-member
|
||||
assert urlparse(httpretty.last_request().path).path == f"/api/v1/comments/{self.comment_id}" # lint-amnesty, pylint: disable=no-member
|
||||
assert httpretty.last_request().method == 'DELETE'
|
||||
|
||||
def test_comment_id_not_found(self):
|
||||
@@ -3029,8 +3032,8 @@ class DeleteCommentTest(
|
||||
def test_discussions_disabled(self):
|
||||
disabled_course = _discussion_disabled_course_for(self.user)
|
||||
self.register_comment_and_thread(
|
||||
thread_overrides={"course_id": six.text_type(disabled_course.id)},
|
||||
overrides={"course_id": six.text_type(disabled_course.id)}
|
||||
thread_overrides={"course_id": str(disabled_course.id)},
|
||||
overrides={"course_id": str(disabled_course.id)}
|
||||
)
|
||||
with pytest.raises(DiscussionDisabledError):
|
||||
delete_comment(self.request, self.comment_id)
|
||||
@@ -3079,7 +3082,7 @@ class DeleteCommentTest(
|
||||
self.register_comment_and_thread(
|
||||
overrides={"thread_id": "test_thread"},
|
||||
thread_overrides={
|
||||
"course_id": six.text_type(cohort_course.id),
|
||||
"course_id": str(cohort_course.id),
|
||||
"group_id": (
|
||||
None if thread_group_state == "no_group" else
|
||||
cohort.id if thread_group_state == "match_group" else
|
||||
@@ -3110,12 +3113,12 @@ class RetrieveThreadTest(
|
||||
"""Tests for get_thread"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(RetrieveThreadTest, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(RetrieveThreadTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
httpretty.reset()
|
||||
httpretty.enable()
|
||||
self.addCleanup(httpretty.reset)
|
||||
@@ -3135,7 +3138,7 @@ class RetrieveThreadTest(
|
||||
"""
|
||||
cs_data = make_minimal_cs_thread({
|
||||
"id": self.thread_id,
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"commentable_id": "test_topic",
|
||||
"username": self.user.username,
|
||||
"user_id": str(self.user.id),
|
||||
@@ -3202,7 +3205,7 @@ class RetrieveThreadTest(
|
||||
"""
|
||||
cohort_course, cohort = _create_course_and_cohort_with_user_role(course_is_cohorted, self.user, role_name)
|
||||
self.register_thread({
|
||||
"course_id": six.text_type(cohort_course.id),
|
||||
"course_id": str(cohort_course.id),
|
||||
"group_id": (
|
||||
None if thread_group_state == "no_group" else
|
||||
cohort.id if thread_group_state == "match_group" else
|
||||
|
||||
@@ -15,7 +15,7 @@ from lms.djangoapps.discussion.rest_api.forms import CommentListGetForm, ThreadL
|
||||
from openedx.core.djangoapps.util.test_forms import FormTestMixin
|
||||
|
||||
|
||||
class PaginationTestMixin(object):
|
||||
class PaginationTestMixin:
|
||||
"""A mixin for testing forms with pagination fields"""
|
||||
|
||||
def test_missing_page(self):
|
||||
@@ -45,7 +45,7 @@ class ThreadListGetFormTest(FormTestMixin, PaginationTestMixin, TestCase):
|
||||
FORM_CLASS = ThreadListGetForm
|
||||
|
||||
def setUp(self):
|
||||
super(ThreadListGetFormTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.form_data = QueryDict(
|
||||
urlencode(
|
||||
{
|
||||
@@ -159,7 +159,7 @@ class CommentListGetFormTest(FormTestMixin, PaginationTestMixin, TestCase):
|
||||
FORM_CLASS = CommentListGetForm
|
||||
|
||||
def setUp(self):
|
||||
super(CommentListGetFormTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.form_data = {
|
||||
"thread_id": "deadbeef",
|
||||
"endorsed": "False",
|
||||
|
||||
@@ -12,7 +12,7 @@ from lms.djangoapps.discussion.rest_api.render import render_body
|
||||
|
||||
def _add_p_tags(raw_body):
|
||||
"""Return raw_body surrounded by p tags"""
|
||||
return "<p>{raw_body}</p>".format(raw_body=raw_body)
|
||||
return f"<p>{raw_body}</p>"
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -29,8 +29,8 @@ class RenderBodyTest(TestCase):
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_markdown_inline(self, delimiter, tag):
|
||||
assert render_body(u'{delimiter}some text{delimiter}'.format(delimiter=delimiter)) == \
|
||||
u'<p><{tag}>some text</{tag}></p>'.format(tag=tag)
|
||||
assert render_body('{delimiter}some text{delimiter}'.format(delimiter=delimiter)) == \
|
||||
'<p><{tag}>some text</{tag}></p>'.format(tag=tag)
|
||||
|
||||
@ddt.data(
|
||||
"b", "blockquote", "code", "del", "dd", "dl", "dt", "em", "h1", "h2", "h3", "i", "kbd",
|
||||
@@ -44,14 +44,14 @@ class RenderBodyTest(TestCase):
|
||||
|
||||
@ddt.data("br", "hr")
|
||||
def test_selfclosing_tag(self, tag):
|
||||
raw_body = "<{tag}>".format(tag=tag)
|
||||
raw_body = f"<{tag}>"
|
||||
is_inline_tag = tag == "br"
|
||||
rendered_body = _add_p_tags(raw_body) if is_inline_tag else raw_body
|
||||
assert render_body(raw_body) == rendered_body
|
||||
|
||||
@ddt.data("http", "https", "ftp")
|
||||
def test_allowed_a_tag(self, protocol):
|
||||
raw_body = '<a href="{protocol}://foo" title="bar">baz</a>'.format(protocol=protocol)
|
||||
raw_body = f'<a href="{protocol}://foo" title="bar">baz</a>'
|
||||
assert render_body(raw_body) == _add_p_tags(raw_body)
|
||||
|
||||
def test_disallowed_a_tag(self):
|
||||
@@ -75,7 +75,7 @@ class RenderBodyTest(TestCase):
|
||||
|
||||
@ddt.data("p", "br", "li", "hr") # img is tested above
|
||||
def test_allowed_unpaired_tags(self, tag):
|
||||
raw_body = "foo<{tag}>bar".format(tag=tag)
|
||||
raw_body = f"foo<{tag}>bar"
|
||||
assert render_body(raw_body) == _add_p_tags(raw_body)
|
||||
|
||||
def test_unpaired_start_tag(self):
|
||||
|
||||
@@ -4,14 +4,15 @@ Tests for Discussion API serializers
|
||||
|
||||
|
||||
import itertools
|
||||
from unittest import mock
|
||||
|
||||
import ddt
|
||||
import httpretty
|
||||
import mock
|
||||
import six
|
||||
from django.test.client import RequestFactory
|
||||
from six.moves.urllib.parse import urlparse
|
||||
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from common.djangoapps.util.testing import UrlResetMixin
|
||||
from lms.djangoapps.discussion.django_comment_client.tests.utils import ForumsEnableMixin
|
||||
from lms.djangoapps.discussion.rest_api.serializers import CommentSerializer, ThreadSerializer, get_context
|
||||
from lms.djangoapps.discussion.rest_api.tests.utils import (
|
||||
@@ -29,8 +30,6 @@ from openedx.core.djangoapps.django_comment_common.models import (
|
||||
FORUM_ROLE_STUDENT,
|
||||
Role
|
||||
)
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from common.djangoapps.util.testing import UrlResetMixin
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
@@ -45,12 +44,12 @@ class SerializerTestMixin(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetM
|
||||
@classmethod
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUpClass(cls):
|
||||
super(SerializerTestMixin, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(SerializerTestMixin, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
httpretty.reset()
|
||||
httpretty.enable()
|
||||
self.addCleanup(httpretty.reset)
|
||||
@@ -149,7 +148,7 @@ class ThreadSerializerSerializationTest(SerializerTestMixin, SharedModuleStoreTe
|
||||
Create a thread with the given overrides, plus some useful test data.
|
||||
"""
|
||||
merged_overrides = {
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"user_id": str(self.author.id),
|
||||
"username": self.author.username,
|
||||
"read": True,
|
||||
@@ -169,7 +168,7 @@ class ThreadSerializerSerializationTest(SerializerTestMixin, SharedModuleStoreTe
|
||||
def test_basic(self):
|
||||
thread = make_minimal_cs_thread({
|
||||
"id": "test_thread",
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"commentable_id": "test_topic",
|
||||
"user_id": str(self.author.id),
|
||||
"username": self.author.username,
|
||||
@@ -246,7 +245,7 @@ class ThreadSerializerSerializationTest(SerializerTestMixin, SharedModuleStoreTe
|
||||
class CommentSerializerTest(SerializerTestMixin, SharedModuleStoreTestCase):
|
||||
"""Tests for CommentSerializer."""
|
||||
def setUp(self):
|
||||
super(CommentSerializerTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.endorser = UserFactory.create()
|
||||
self.endorsed_at = "2015-05-18T12:34:56Z"
|
||||
|
||||
@@ -412,12 +411,12 @@ class ThreadSerializerDeserializationTest(
|
||||
@classmethod
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUpClass(cls):
|
||||
super(ThreadSerializerDeserializationTest, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(ThreadSerializerDeserializationTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
httpretty.reset()
|
||||
httpretty.enable()
|
||||
self.addCleanup(httpretty.reset)
|
||||
@@ -427,7 +426,7 @@ class ThreadSerializerDeserializationTest(
|
||||
self.request = RequestFactory().get("/dummy")
|
||||
self.request.user = self.user
|
||||
self.minimal_data = {
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"topic_id": "test_topic",
|
||||
"type": "discussion",
|
||||
"title": "Test Title",
|
||||
@@ -435,7 +434,7 @@ class ThreadSerializerDeserializationTest(
|
||||
}
|
||||
self.existing_thread = Thread(**make_minimal_cs_thread({
|
||||
"id": "existing_thread",
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"commentable_id": "original_topic",
|
||||
"thread_type": "discussion",
|
||||
"title": "Original Title",
|
||||
@@ -468,7 +467,7 @@ class ThreadSerializerDeserializationTest(
|
||||
assert urlparse(httpretty.last_request().path).path ==\
|
||||
'/api/v1/test_topic/threads' # lint-amnesty, pylint: disable=no-member
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'course_id': [six.text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'commentable_id': ['test_topic'],
|
||||
'thread_type': ['discussion'],
|
||||
'title': ['Test Title'],
|
||||
@@ -483,7 +482,7 @@ class ThreadSerializerDeserializationTest(
|
||||
data["group_id"] = 42
|
||||
self.save_and_reserialize(data)
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'course_id': [six.text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'commentable_id': ['test_topic'],
|
||||
'thread_type': ['discussion'],
|
||||
'title': ['Test Title'],
|
||||
@@ -524,7 +523,7 @@ class ThreadSerializerDeserializationTest(
|
||||
self.register_put_thread_response(self.existing_thread.attributes)
|
||||
self.save_and_reserialize({}, self.existing_thread)
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'course_id': [six.text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'commentable_id': ['original_topic'],
|
||||
'thread_type': ['discussion'],
|
||||
'title': ['Original Title'],
|
||||
@@ -549,7 +548,7 @@ class ThreadSerializerDeserializationTest(
|
||||
}
|
||||
saved = self.save_and_reserialize(data, self.existing_thread)
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'course_id': [six.text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'commentable_id': ['edited_topic'],
|
||||
'thread_type': ['question'],
|
||||
'title': ['Edited Title'],
|
||||
@@ -593,11 +592,11 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
|
||||
"""Tests for ThreadSerializer deserialization."""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(CommentSerializerDeserializationTest, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
def setUp(self):
|
||||
super(CommentSerializerDeserializationTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
httpretty.reset()
|
||||
httpretty.enable()
|
||||
self.addCleanup(httpretty.reset)
|
||||
@@ -616,7 +615,7 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
|
||||
"body": "Original body",
|
||||
"user_id": str(self.user.id),
|
||||
"username": self.user.username,
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
}))
|
||||
|
||||
def save_and_reserialize(self, data, instance=None):
|
||||
@@ -627,7 +626,7 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
|
||||
context = get_context(
|
||||
self.course,
|
||||
self.request,
|
||||
make_minimal_cs_thread({"course_id": six.text_type(self.course.id)})
|
||||
make_minimal_cs_thread({"course_id": str(self.course.id)})
|
||||
)
|
||||
serializer = CommentSerializer(
|
||||
instance,
|
||||
@@ -652,12 +651,12 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
|
||||
)
|
||||
saved = self.save_and_reserialize(data)
|
||||
expected_url = (
|
||||
"/api/v1/comments/{}".format(parent_id) if parent_id else
|
||||
f"/api/v1/comments/{parent_id}" if parent_id else
|
||||
"/api/v1/threads/test_thread/comments"
|
||||
)
|
||||
assert urlparse(httpretty.last_request().path).path == expected_url # lint-amnesty, pylint: disable=no-member
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'course_id': [six.text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'body': ['Test body'],
|
||||
'user_id': [str(self.user.id)]
|
||||
}
|
||||
@@ -676,7 +675,7 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
|
||||
)
|
||||
self.save_and_reserialize(data)
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'course_id': [six.text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'body': ['Test body'],
|
||||
'user_id': [str(self.user.id)],
|
||||
'endorsed': ['True']
|
||||
@@ -754,7 +753,7 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
|
||||
data["endorsed"] = True
|
||||
saved = self.save_and_reserialize(data)
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'course_id': [six.text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'body': ['Test body'],
|
||||
'user_id': [str(self.user.id)],
|
||||
'endorsed': ['True']
|
||||
@@ -769,7 +768,7 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
|
||||
self.save_and_reserialize({}, instance=self.existing_comment)
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'body': ['Original body'],
|
||||
'course_id': [six.text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'user_id': [str(self.user.id)],
|
||||
'anonymous': ['False'],
|
||||
'anonymous_to_peers': ['False'],
|
||||
@@ -787,7 +786,7 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
|
||||
saved = self.save_and_reserialize(data, instance=self.existing_comment)
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'body': ['Edited body'],
|
||||
'course_id': [six.text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'user_id': [str(self.user.id)],
|
||||
'anonymous': ['False'],
|
||||
'anonymous_to_peers': ['False'],
|
||||
|
||||
@@ -5,22 +5,23 @@ Tests for Discussion API views
|
||||
|
||||
import json
|
||||
from datetime import datetime
|
||||
from unittest import mock
|
||||
|
||||
import ddt
|
||||
import httpretty
|
||||
import mock
|
||||
from django.urls import reverse
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from pytz import UTC
|
||||
from rest_framework.parsers import JSONParser
|
||||
from rest_framework.test import APIClient, APITestCase
|
||||
from six import text_type
|
||||
from six.moves import range
|
||||
from six.moves.urllib.parse import urlparse
|
||||
|
||||
from common.test.utils import disable_signal
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
|
||||
from common.djangoapps.student.models import get_retired_username_by_username
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, SuperuserFactory, UserFactory
|
||||
from common.djangoapps.util.testing import PatchMediaTypeMixin, UrlResetMixin
|
||||
from common.test.utils import disable_signal
|
||||
from lms.djangoapps.discussion.django_comment_client.tests.utils import (
|
||||
ForumsEnableMixin,
|
||||
config_course_discussions,
|
||||
@@ -38,12 +39,9 @@ from openedx.core.djangoapps.course_groups.tests.helpers import config_course_co
|
||||
from openedx.core.djangoapps.django_comment_common.models import CourseDiscussionSettings, Role
|
||||
from openedx.core.djangoapps.django_comment_common.utils import seed_permissions_roles
|
||||
from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user
|
||||
from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory, AccessTokenFactory
|
||||
from openedx.core.djangoapps.oauth_dispatch.tests.factories import AccessTokenFactory, ApplicationFactory
|
||||
from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_image_storage
|
||||
from openedx.core.djangoapps.user_api.models import RetirementState, UserRetirementStatus
|
||||
from common.djangoapps.student.models import get_retired_username_by_username
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, SuperuserFactory, UserFactory
|
||||
from common.djangoapps.util.testing import PatchMediaTypeMixin, UrlResetMixin
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
@@ -61,7 +59,7 @@ class DiscussionAPIViewTestMixin(ForumsEnableMixin, CommentsServiceMockMixin, Ur
|
||||
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(DiscussionAPIViewTestMixin, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.maxDiff = None # pylint: disable=invalid-name
|
||||
self.course = CourseFactory.create(
|
||||
org="x",
|
||||
@@ -92,7 +90,7 @@ class DiscussionAPIViewTestMixin(ForumsEnableMixin, CommentsServiceMockMixin, Ur
|
||||
"""
|
||||
cs_thread = make_minimal_cs_thread({
|
||||
"id": "test_thread",
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"commentable_id": "test_topic",
|
||||
"username": self.user.username,
|
||||
"user_id": str(self.user.id),
|
||||
@@ -110,7 +108,7 @@ class DiscussionAPIViewTestMixin(ForumsEnableMixin, CommentsServiceMockMixin, Ur
|
||||
"""
|
||||
cs_comment = make_minimal_cs_comment({
|
||||
"id": "test_comment",
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"thread_id": "test_thread",
|
||||
"username": self.user.username,
|
||||
"user_id": str(self.user.id),
|
||||
@@ -139,8 +137,8 @@ class DiscussionAPIViewTestMixin(ForumsEnableMixin, CommentsServiceMockMixin, Ur
|
||||
class CourseViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
"""Tests for CourseView"""
|
||||
def setUp(self):
|
||||
super(CourseViewTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
self.url = reverse("discussion_course", kwargs={"course_id": text_type(self.course.id)})
|
||||
super().setUp()
|
||||
self.url = reverse("discussion_course", kwargs={"course_id": str(self.course.id)})
|
||||
|
||||
def test_404(self):
|
||||
response = self.client.get(
|
||||
@@ -158,7 +156,7 @@ class CourseViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
response,
|
||||
200,
|
||||
{
|
||||
"id": text_type(self.course.id),
|
||||
"id": str(self.course.id),
|
||||
"blackouts": [],
|
||||
"thread_list_url": "http://testserver/api/discussion/v1/threads/?course_id=x%2Fy%2Fz",
|
||||
"following_thread_list_url": (
|
||||
@@ -174,7 +172,7 @@ class CourseViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
class RetireViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
"""Tests for CourseView"""
|
||||
def setUp(self):
|
||||
super(RetireViewTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
RetirementState.objects.create(state_name='PENDING', state_execution_order=1)
|
||||
self.retire_forums_state = RetirementState.objects.create(state_name='RETIRE_FORUMS', state_execution_order=11)
|
||||
|
||||
@@ -248,7 +246,7 @@ class RetireViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
class ReplaceUsernamesViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
"""Tests for ReplaceUsernamesView"""
|
||||
def setUp(self):
|
||||
super(ReplaceUsernamesViewTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.client_user = UserFactory()
|
||||
self.client_user.username = "test_replace_username_service_worker"
|
||||
self.new_username = "test_username_replacement"
|
||||
@@ -261,7 +259,7 @@ class ReplaceUsernamesViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
assert response.status_code == expected_status
|
||||
|
||||
if expected_content:
|
||||
assert text_type(response.content) == expected_content
|
||||
assert str(response.content) == expected_content
|
||||
|
||||
def build_jwt_headers(self, user):
|
||||
"""
|
||||
@@ -342,8 +340,8 @@ class CourseTopicsViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
Tests for CourseTopicsView
|
||||
"""
|
||||
def setUp(self):
|
||||
super(CourseTopicsViewTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
self.url = reverse("course_topics", kwargs={"course_id": text_type(self.course.id)})
|
||||
super().setUp()
|
||||
self.url = reverse("course_topics", kwargs={"course_id": str(self.course.id)})
|
||||
|
||||
def create_course(self, modules_count, module_store, topics):
|
||||
"""
|
||||
@@ -358,15 +356,15 @@ class CourseTopicsViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
discussion_topics=topics
|
||||
)
|
||||
CourseEnrollmentFactory.create(user=self.user, course_id=course.id)
|
||||
course_url = reverse("course_topics", kwargs={"course_id": text_type(course.id)})
|
||||
course_url = reverse("course_topics", kwargs={"course_id": str(course.id)})
|
||||
# add some discussion xblocks
|
||||
for i in range(modules_count):
|
||||
ItemFactory.create(
|
||||
parent_location=course.location,
|
||||
category='discussion',
|
||||
discussion_id='id_module_{}'.format(i),
|
||||
discussion_category='Category {}'.format(i),
|
||||
discussion_target='Discussion {}'.format(i),
|
||||
discussion_id=f'id_module_{i}',
|
||||
discussion_category=f'Category {i}',
|
||||
discussion_target=f'Discussion {i}',
|
||||
publish_item=False,
|
||||
)
|
||||
return course_url
|
||||
@@ -433,7 +431,7 @@ class CourseTopicsViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
"""
|
||||
topic_id = "courseware-topic-id"
|
||||
self.make_discussion_xblock(topic_id, "test_category", "test_target")
|
||||
url = "{}?topic_id=invalid_topic_id".format(self.url)
|
||||
url = f"{self.url}?topic_id=invalid_topic_id"
|
||||
response = self.client.get(url)
|
||||
self.assert_response_correct(
|
||||
response,
|
||||
@@ -449,7 +447,7 @@ class CourseTopicsViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
topic_id_2 = "topic_id_2"
|
||||
self.make_discussion_xblock(topic_id_1, "test_category_1", "test_target_1")
|
||||
self.make_discussion_xblock(topic_id_2, "test_category_2", "test_target_2")
|
||||
url = "{}?topic_id=topic_id_1,topic_id_2".format(self.url)
|
||||
url = f"{self.url}?topic_id=topic_id_1,topic_id_2"
|
||||
response = self.client.get(url)
|
||||
self.assert_response_correct(
|
||||
response,
|
||||
@@ -495,7 +493,7 @@ class CourseTopicsViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, ProfileImageTestMixin):
|
||||
"""Tests for ThreadViewSet list"""
|
||||
def setUp(self):
|
||||
super(ThreadViewSetListTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.author = UserFactory.create()
|
||||
self.url = reverse("thread-list")
|
||||
|
||||
@@ -505,7 +503,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
"""
|
||||
thread = make_minimal_cs_thread({
|
||||
"id": "test_thread",
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"commentable_id": "test_topic",
|
||||
"user_id": str(self.user.id),
|
||||
"username": self.user.username,
|
||||
@@ -530,7 +528,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
)
|
||||
|
||||
def test_404(self):
|
||||
response = self.client.get(self.url, {"course_id": text_type("non/existent/course")})
|
||||
response = self.client.get(self.url, {"course_id": "non/existent/course"})
|
||||
self.assert_response_correct(
|
||||
response,
|
||||
404,
|
||||
@@ -553,7 +551,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
"editable_fields": ["abuse_flagged", "following", "read", "voted"],
|
||||
})]
|
||||
self.register_get_threads_response(source_threads, page=1, num_pages=2)
|
||||
response = self.client.get(self.url, {"course_id": text_type(self.course.id), "following": ""})
|
||||
response = self.client.get(self.url, {"course_id": str(self.course.id), "following": ""})
|
||||
expected_response = make_paginated_api_response(
|
||||
results=expected_threads,
|
||||
count=1,
|
||||
@@ -568,8 +566,8 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
expected_response
|
||||
)
|
||||
self.assert_last_query_params({
|
||||
"user_id": [text_type(self.user.id)],
|
||||
"course_id": [text_type(self.course.id)],
|
||||
"user_id": [str(self.user.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"sort_key": ["activity"],
|
||||
"page": ["1"],
|
||||
"per_page": ["10"],
|
||||
@@ -583,13 +581,13 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
self.client.get(
|
||||
self.url,
|
||||
{
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"view": query,
|
||||
}
|
||||
)
|
||||
self.assert_last_query_params({
|
||||
"user_id": [text_type(self.user.id)],
|
||||
"course_id": [text_type(self.course.id)],
|
||||
"user_id": [str(self.user.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"sort_key": ["activity"],
|
||||
"page": ["1"],
|
||||
"per_page": ["10"],
|
||||
@@ -601,7 +599,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
self.register_get_threads_response([], page=1, num_pages=1)
|
||||
response = self.client.get(
|
||||
self.url,
|
||||
{"course_id": text_type(self.course.id), "page": "18", "page_size": "4"}
|
||||
{"course_id": str(self.course.id), "page": "18", "page_size": "4"}
|
||||
)
|
||||
self.assert_response_correct(
|
||||
response,
|
||||
@@ -609,8 +607,8 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
{"developer_message": "Page not found (No results on this page)."}
|
||||
)
|
||||
self.assert_last_query_params({
|
||||
"user_id": [text_type(self.user.id)],
|
||||
"course_id": [text_type(self.course.id)],
|
||||
"user_id": [str(self.user.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"sort_key": ["activity"],
|
||||
"page": ["18"],
|
||||
"per_page": ["4"],
|
||||
@@ -621,7 +619,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
self.register_get_threads_search_response([], None, num_pages=0)
|
||||
response = self.client.get(
|
||||
self.url,
|
||||
{"course_id": text_type(self.course.id), "text_search": "test search string"}
|
||||
{"course_id": str(self.course.id), "text_search": "test search string"}
|
||||
)
|
||||
|
||||
expected_response = make_paginated_api_response(
|
||||
@@ -634,8 +632,8 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
expected_response
|
||||
)
|
||||
self.assert_last_query_params({
|
||||
"user_id": [text_type(self.user.id)],
|
||||
"course_id": [text_type(self.course.id)],
|
||||
"user_id": [str(self.user.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"sort_key": ["activity"],
|
||||
"page": ["1"],
|
||||
"per_page": ["10"],
|
||||
@@ -649,7 +647,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
response = self.client.get(
|
||||
self.url,
|
||||
{
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"following": following,
|
||||
}
|
||||
)
|
||||
@@ -665,14 +663,14 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
)
|
||||
assert urlparse(
|
||||
httpretty.last_request().path # lint-amnesty, pylint: disable=no-member
|
||||
).path == '/api/v1/users/{}/subscribed_threads'.format(self.user.id)
|
||||
).path == f"/api/v1/users/{self.user.id}/subscribed_threads"
|
||||
|
||||
@ddt.data(False, "false", "0")
|
||||
def test_following_false(self, following):
|
||||
response = self.client.get(
|
||||
self.url,
|
||||
{
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"following": following,
|
||||
}
|
||||
)
|
||||
@@ -688,7 +686,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
response = self.client.get(
|
||||
self.url,
|
||||
{
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"following": "invalid-boolean",
|
||||
}
|
||||
)
|
||||
@@ -720,13 +718,13 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
self.client.get(
|
||||
self.url,
|
||||
{
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"order_by": http_query,
|
||||
}
|
||||
)
|
||||
self.assert_last_query_params({
|
||||
"user_id": [text_type(self.user.id)],
|
||||
"course_id": [text_type(self.course.id)],
|
||||
"user_id": [str(self.user.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"page": ["1"],
|
||||
"per_page": ["10"],
|
||||
"sort_key": [cc_query],
|
||||
@@ -743,13 +741,13 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
self.client.get(
|
||||
self.url,
|
||||
{
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"order_direction": "desc",
|
||||
}
|
||||
)
|
||||
self.assert_last_query_params({
|
||||
"user_id": [text_type(self.user.id)],
|
||||
"course_id": [text_type(self.course.id)],
|
||||
"user_id": [str(self.user.id)],
|
||||
"course_id": [str(self.course.id)],
|
||||
"sort_key": ["activity"],
|
||||
"page": ["1"],
|
||||
"per_page": ["10"],
|
||||
@@ -762,7 +760,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
self.register_get_user_response(self.user)
|
||||
self.register_get_threads_search_response([], None, num_pages=0)
|
||||
response = self.client.get(self.url, {
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"text_search": "test search string",
|
||||
"topic_id": "topic1, topic2",
|
||||
})
|
||||
@@ -795,7 +793,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
|
||||
response = self.client.get(
|
||||
self.url,
|
||||
{"course_id": text_type(self.course.id), "requested_fields": "profile_image"},
|
||||
{"course_id": str(self.course.id), "requested_fields": "profile_image"},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
response_threads = json.loads(response.content.decode('utf-8'))['results']
|
||||
@@ -820,7 +818,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
|
||||
response = self.client.get(
|
||||
self.url,
|
||||
{"course_id": text_type(self.course.id), "requested_fields": "profile_image"},
|
||||
{"course_id": str(self.course.id), "requested_fields": "profile_image"},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
response_thread = json.loads(response.content.decode('utf-8'))['results'][0]
|
||||
@@ -834,7 +832,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
|
||||
class ThreadViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
"""Tests for ThreadViewSet create"""
|
||||
def setUp(self):
|
||||
super(ThreadViewSetCreateTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = reverse("thread-list")
|
||||
|
||||
def test_basic(self):
|
||||
@@ -846,7 +844,7 @@ class ThreadViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
})
|
||||
self.register_post_thread_response(cs_thread)
|
||||
request_data = {
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"topic_id": "test_topic",
|
||||
"type": "discussion",
|
||||
"title": "Test Title",
|
||||
@@ -861,7 +859,7 @@ class ThreadViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
response_data = json.loads(response.content.decode('utf-8'))
|
||||
assert response_data == self.expected_thread_data({'read': True})
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'course_id': [text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'commentable_id': ['test_topic'],
|
||||
'thread_type': ['discussion'],
|
||||
'title': ['Test Title'],
|
||||
@@ -897,7 +895,7 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest
|
||||
"""Tests for ThreadViewSet partial_update"""
|
||||
def setUp(self):
|
||||
self.unsupported_media_type = JSONParser.media_type
|
||||
super(ThreadViewSetPartialUpdateTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = reverse("thread-detail", kwargs={"thread_id": "test_thread"})
|
||||
|
||||
def test_basic(self):
|
||||
@@ -923,7 +921,7 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest
|
||||
'response_count': 2
|
||||
})
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'course_id': [text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'commentable_id': ['test_topic'],
|
||||
'thread_type': ['discussion'],
|
||||
'title': ['Test Title'],
|
||||
@@ -1030,7 +1028,7 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest
|
||||
class ThreadViewSetDeleteTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
"""Tests for ThreadViewSet delete"""
|
||||
def setUp(self):
|
||||
super(ThreadViewSetDeleteTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = reverse("thread-detail", kwargs={"thread_id": "test_thread"})
|
||||
self.thread_id = "test_thread"
|
||||
|
||||
@@ -1038,7 +1036,7 @@ class ThreadViewSetDeleteTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
self.register_get_user_response(self.user)
|
||||
cs_thread = make_minimal_cs_thread({
|
||||
"id": self.thread_id,
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"username": self.user.username,
|
||||
"user_id": str(self.user.id),
|
||||
})
|
||||
@@ -1047,7 +1045,7 @@ class ThreadViewSetDeleteTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
response = self.client.delete(self.url)
|
||||
assert response.status_code == 204
|
||||
assert response.content == b''
|
||||
assert urlparse(httpretty.last_request().path).path == '/api/v1/threads/{}'.format(self.thread_id) # lint-amnesty, pylint: disable=no-member
|
||||
assert urlparse(httpretty.last_request().path).path == f"/api/v1/threads/{self.thread_id}" # lint-amnesty, pylint: disable=no-member
|
||||
assert httpretty.last_request().method == 'DELETE'
|
||||
|
||||
def test_delete_nonexistent_thread(self):
|
||||
@@ -1062,7 +1060,7 @@ class ThreadViewSetDeleteTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, ProfileImageTestMixin):
|
||||
"""Tests for CommentViewSet list"""
|
||||
def setUp(self):
|
||||
super(CommentViewSetListTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.author = UserFactory.create()
|
||||
self.url = reverse("comment-list")
|
||||
self.thread_id = "test_thread"
|
||||
@@ -1092,7 +1090,7 @@ class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pr
|
||||
already in overrides.
|
||||
"""
|
||||
overrides = overrides.copy() if overrides else {}
|
||||
overrides.setdefault("course_id", text_type(self.course.id))
|
||||
overrides.setdefault("course_id", str(self.course.id))
|
||||
return make_minimal_cs_thread(overrides)
|
||||
|
||||
def expected_response_comment(self, overrides=None):
|
||||
@@ -1155,7 +1153,7 @@ class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pr
|
||||
})]
|
||||
self.register_get_thread_response({
|
||||
"id": self.thread_id,
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"thread_type": "discussion",
|
||||
"children": source_comments,
|
||||
"resp_total": 100,
|
||||
@@ -1192,7 +1190,7 @@ class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pr
|
||||
self.register_get_user_response(self.user)
|
||||
self.register_get_thread_response(make_minimal_cs_thread({
|
||||
"id": self.thread_id,
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"thread_type": "discussion",
|
||||
"resp_total": 10,
|
||||
}))
|
||||
@@ -1301,7 +1299,7 @@ class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pr
|
||||
})
|
||||
thread = self.make_minimal_cs_thread({
|
||||
"id": self.thread_id,
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"thread_type": "discussion",
|
||||
"children": [response_1, response_2],
|
||||
"resp_total": 2,
|
||||
@@ -1336,7 +1334,7 @@ class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pr
|
||||
source_comments = [self.create_source_comment()]
|
||||
self.register_get_thread_response({
|
||||
"id": self.thread_id,
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"thread_type": "discussion",
|
||||
"children": source_comments,
|
||||
"resp_total": 100,
|
||||
@@ -1437,7 +1435,7 @@ class CommentViewSetDeleteTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
"""Tests for ThreadViewSet delete"""
|
||||
|
||||
def setUp(self):
|
||||
super(CommentViewSetDeleteTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = reverse("comment-detail", kwargs={"comment_id": "test_comment"})
|
||||
self.comment_id = "test_comment"
|
||||
|
||||
@@ -1445,7 +1443,7 @@ class CommentViewSetDeleteTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
self.register_get_user_response(self.user)
|
||||
cs_thread = make_minimal_cs_thread({
|
||||
"id": "test_thread",
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
})
|
||||
self.register_get_thread_response(cs_thread)
|
||||
cs_comment = make_minimal_cs_comment({
|
||||
@@ -1460,7 +1458,7 @@ class CommentViewSetDeleteTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
response = self.client.delete(self.url)
|
||||
assert response.status_code == 204
|
||||
assert response.content == b''
|
||||
assert urlparse(httpretty.last_request().path).path == '/api/v1/comments/{}'.format(self.comment_id) # lint-amnesty, pylint: disable=no-member
|
||||
assert urlparse(httpretty.last_request().path).path == f"/api/v1/comments/{self.comment_id}" # lint-amnesty, pylint: disable=no-member
|
||||
assert httpretty.last_request().method == 'DELETE'
|
||||
|
||||
def test_delete_nonexistent_comment(self):
|
||||
@@ -1475,7 +1473,7 @@ class CommentViewSetDeleteTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
class CommentViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
"""Tests for CommentViewSet create"""
|
||||
def setUp(self):
|
||||
super(CommentViewSetCreateTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = reverse("comment-list")
|
||||
|
||||
def test_basic(self):
|
||||
@@ -1517,7 +1515,7 @@ class CommentViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
assert response_data == expected_response_data
|
||||
assert urlparse(httpretty.last_request().path).path == '/api/v1/threads/test_thread/comments' # lint-amnesty, pylint: disable=no-member
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'course_id': [text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'body': ['Test body'],
|
||||
'user_id': [str(self.user.id)]
|
||||
}
|
||||
@@ -1558,7 +1556,7 @@ class CommentViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTes
|
||||
"""Tests for CommentViewSet partial_update"""
|
||||
def setUp(self):
|
||||
self.unsupported_media_type = JSONParser.media_type
|
||||
super(CommentViewSetPartialUpdateTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
httpretty.reset()
|
||||
httpretty.enable()
|
||||
self.addCleanup(httpretty.reset)
|
||||
@@ -1610,7 +1608,7 @@ class CommentViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTes
|
||||
})
|
||||
assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
|
||||
'body': ['Edited body'],
|
||||
'course_id': [text_type(self.course.id)],
|
||||
'course_id': [str(self.course.id)],
|
||||
'user_id': [str(self.user.id)],
|
||||
'anonymous': ['False'],
|
||||
'anonymous_to_peers': ['False'],
|
||||
@@ -1666,7 +1664,7 @@ class CommentViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTes
|
||||
class ThreadViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, ProfileImageTestMixin):
|
||||
"""Tests for ThreadViewSet Retrieve"""
|
||||
def setUp(self):
|
||||
super(ThreadViewSetRetrieveTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = reverse("thread-detail", kwargs={"thread_id": "test_thread"})
|
||||
self.thread_id = "test_thread"
|
||||
|
||||
@@ -1674,7 +1672,7 @@ class ThreadViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase,
|
||||
self.register_get_user_response(self.user)
|
||||
cs_thread = make_minimal_cs_thread({
|
||||
"id": self.thread_id,
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"commentable_id": "test_topic",
|
||||
"username": self.user.username,
|
||||
"user_id": str(self.user.id),
|
||||
@@ -1699,7 +1697,7 @@ class ThreadViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase,
|
||||
self.register_get_user_response(self.user)
|
||||
cs_thread = make_minimal_cs_thread({
|
||||
"id": self.thread_id,
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"username": self.user.username,
|
||||
"user_id": str(self.user.id),
|
||||
})
|
||||
@@ -1717,7 +1715,7 @@ class ThreadViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase,
|
||||
class CommentViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, ProfileImageTestMixin):
|
||||
"""Tests for CommentViewSet Retrieve"""
|
||||
def setUp(self):
|
||||
super(CommentViewSetRetrieveTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = reverse("comment-detail", kwargs={"comment_id": "test_comment"})
|
||||
self.thread_id = "test_thread"
|
||||
self.comment_id = "test_comment"
|
||||
@@ -1729,7 +1727,7 @@ class CommentViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase
|
||||
return make_minimal_cs_comment({
|
||||
"id": comment_id,
|
||||
"parent_id": parent_id,
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"thread_id": self.thread_id,
|
||||
"thread_type": "discussion",
|
||||
"username": self.user.username,
|
||||
@@ -1746,7 +1744,7 @@ class CommentViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase
|
||||
cs_comment = self.make_comment_data(self.comment_id, None, [cs_comment_child])
|
||||
cs_thread = make_minimal_cs_thread({
|
||||
"id": self.thread_id,
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"children": [cs_comment],
|
||||
})
|
||||
self.register_get_thread_response(cs_thread)
|
||||
@@ -1794,7 +1792,7 @@ class CommentViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase
|
||||
cs_comment = self.make_comment_data(self.comment_id, None, [cs_comment_child])
|
||||
cs_thread = make_minimal_cs_thread({
|
||||
"id": self.thread_id,
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"children": [cs_comment],
|
||||
})
|
||||
self.register_get_thread_response(cs_thread)
|
||||
@@ -1818,7 +1816,7 @@ class CommentViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase
|
||||
cs_comment = self.make_comment_data(self.comment_id, None, [cs_comment_child])
|
||||
cs_thread = make_minimal_cs_thread({
|
||||
'id': self.thread_id,
|
||||
'course_id': text_type(self.course.id),
|
||||
'course_id': str(self.course.id),
|
||||
'children': [cs_comment],
|
||||
})
|
||||
self.register_get_thread_response(cs_thread)
|
||||
@@ -1842,7 +1840,7 @@ class CourseDiscussionSettingsAPIViewTest(APITestCase, UrlResetMixin, ModuleStor
|
||||
"""
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(CourseDiscussionSettingsAPIViewTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create(
|
||||
org="x",
|
||||
course="y",
|
||||
@@ -1850,7 +1848,7 @@ class CourseDiscussionSettingsAPIViewTest(APITestCase, UrlResetMixin, ModuleStor
|
||||
start=datetime.now(UTC),
|
||||
discussion_topics={"Test Topic": {"id": "test_topic"}}
|
||||
)
|
||||
self.path = reverse('discussion_course_settings', kwargs={'course_id': text_type(self.course.id)})
|
||||
self.path = reverse('discussion_course_settings', kwargs={'course_id': str(self.course.id)})
|
||||
self.password = 'edx'
|
||||
self.user = UserFactory(username='staff', password=self.password, is_staff=True)
|
||||
|
||||
@@ -1894,12 +1892,12 @@ class CourseDiscussionSettingsAPIViewTest(APITestCase, UrlResetMixin, ModuleStor
|
||||
def _get_expected_response(self):
|
||||
"""Return the default expected response before any changes to the discussion settings."""
|
||||
return {
|
||||
u'always_divide_inline_discussions': False,
|
||||
u'divided_inline_discussions': [],
|
||||
u'divided_course_wide_discussions': [],
|
||||
u'id': 1,
|
||||
u'division_scheme': u'cohort',
|
||||
u'available_division_schemes': [u'cohort']
|
||||
'always_divide_inline_discussions': False,
|
||||
'divided_inline_discussions': [],
|
||||
'divided_course_wide_discussions': [],
|
||||
'id': 1,
|
||||
'division_scheme': 'cohort',
|
||||
'available_division_schemes': ['cohort']
|
||||
}
|
||||
|
||||
def patch_request(self, data, headers=None):
|
||||
@@ -2085,7 +2083,7 @@ class CourseDiscussionRolesAPIViewTest(APITestCase, UrlResetMixin, ModuleStoreTe
|
||||
"""
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(CourseDiscussionRolesAPIViewTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create(
|
||||
org="x",
|
||||
course="y",
|
||||
@@ -2100,7 +2098,7 @@ class CourseDiscussionRolesAPIViewTest(APITestCase, UrlResetMixin, ModuleStoreTe
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def path(self, course_id=None, role=None):
|
||||
"""Return the URL path to the endpoint based on the provided arguments."""
|
||||
course_id = text_type(self.course.id) if course_id is None else course_id
|
||||
course_id = str(self.course.id) if course_id is None else course_id
|
||||
role = 'Moderator' if role is None else role
|
||||
return reverse(
|
||||
'discussion_course_roles',
|
||||
|
||||
@@ -10,7 +10,6 @@ from contextlib import closing
|
||||
from datetime import datetime
|
||||
|
||||
import httpretty
|
||||
import six
|
||||
from PIL import Image
|
||||
from pytz import UTC
|
||||
|
||||
@@ -68,7 +67,7 @@ def _get_comment_callback(comment_data, thread_id, parent_id):
|
||||
return callback
|
||||
|
||||
|
||||
class CommentsServiceMockMixin(object):
|
||||
class CommentsServiceMockMixin:
|
||||
"""Mixin with utility methods for mocking the comments service"""
|
||||
def register_get_threads_response(self, threads, page, num_pages):
|
||||
"""Register a mock response for GET on the CS thread list endpoint"""
|
||||
@@ -128,7 +127,7 @@ class CommentsServiceMockMixin(object):
|
||||
assert httpretty.is_enabled(), 'httpretty must be enabled to mock calls.'
|
||||
httpretty.register_uri(
|
||||
httpretty.GET,
|
||||
"http://localhost:4567/api/v1/threads/{id}".format(id=thread_id),
|
||||
f"http://localhost:4567/api/v1/threads/{thread_id}",
|
||||
body="",
|
||||
status=status_code
|
||||
)
|
||||
@@ -152,9 +151,9 @@ class CommentsServiceMockMixin(object):
|
||||
specified.
|
||||
"""
|
||||
if parent_id:
|
||||
url = "http://localhost:4567/api/v1/comments/{}".format(parent_id)
|
||||
url = f"http://localhost:4567/api/v1/comments/{parent_id}"
|
||||
else:
|
||||
url = "http://localhost:4567/api/v1/threads/{}/comments".format(thread_id)
|
||||
url = f"http://localhost:4567/api/v1/threads/{thread_id}/comments"
|
||||
|
||||
assert httpretty.is_enabled(), 'httpretty must be enabled to mock calls.'
|
||||
httpretty.register_uri(
|
||||
@@ -185,7 +184,7 @@ class CommentsServiceMockMixin(object):
|
||||
assert httpretty.is_enabled(), 'httpretty must be enabled to mock calls.'
|
||||
httpretty.register_uri(
|
||||
httpretty.GET,
|
||||
"http://localhost:4567/api/v1/comments/{id}".format(id=comment_id),
|
||||
f"http://localhost:4567/api/v1/comments/{comment_id}",
|
||||
body="",
|
||||
status=status_code
|
||||
)
|
||||
@@ -208,7 +207,7 @@ class CommentsServiceMockMixin(object):
|
||||
assert httpretty.is_enabled(), 'httpretty must be enabled to mock calls.'
|
||||
httpretty.register_uri(
|
||||
httpretty.GET,
|
||||
"http://localhost:4567/api/v1/users/{id}".format(id=user.id),
|
||||
f"http://localhost:4567/api/v1/users/{user.id}",
|
||||
body=json.dumps({
|
||||
"id": str(user.id),
|
||||
"subscribed_thread_ids": subscribed_thread_ids or [],
|
||||
@@ -222,7 +221,7 @@ class CommentsServiceMockMixin(object):
|
||||
assert httpretty.is_enabled(), 'httpretty must be enabled to mock calls.'
|
||||
httpretty.register_uri(
|
||||
httpretty.POST,
|
||||
"http://localhost:4567/api/v1/users/{id}/retire".format(id=user.id),
|
||||
f"http://localhost:4567/api/v1/users/{user.id}/retire",
|
||||
body=body,
|
||||
status=status
|
||||
)
|
||||
@@ -231,7 +230,7 @@ class CommentsServiceMockMixin(object):
|
||||
assert httpretty.is_enabled(), 'httpretty must be enabled to mock calls.'
|
||||
httpretty.register_uri(
|
||||
httpretty.POST,
|
||||
"http://localhost:4567/api/v1/users/{id}/replace_username".format(id=user.id),
|
||||
f"http://localhost:4567/api/v1/users/{user.id}/replace_username",
|
||||
body=body,
|
||||
status=status
|
||||
)
|
||||
@@ -241,7 +240,7 @@ class CommentsServiceMockMixin(object):
|
||||
assert httpretty.is_enabled(), 'httpretty must be enabled to mock calls.'
|
||||
httpretty.register_uri(
|
||||
httpretty.GET,
|
||||
"http://localhost:4567/api/v1/users/{}/subscribed_threads".format(user.id),
|
||||
f"http://localhost:4567/api/v1/users/{user.id}/subscribed_threads",
|
||||
body=json.dumps({
|
||||
"collection": threads,
|
||||
"page": page,
|
||||
@@ -260,7 +259,7 @@ class CommentsServiceMockMixin(object):
|
||||
for method in [httpretty.POST, httpretty.DELETE]:
|
||||
httpretty.register_uri(
|
||||
method,
|
||||
"http://localhost:4567/api/v1/users/{id}/subscriptions".format(id=user.id),
|
||||
f"http://localhost:4567/api/v1/users/{user.id}/subscriptions",
|
||||
body=json.dumps({}), # body is unused
|
||||
status=200
|
||||
)
|
||||
@@ -274,7 +273,7 @@ class CommentsServiceMockMixin(object):
|
||||
for method in [httpretty.PUT, httpretty.DELETE]:
|
||||
httpretty.register_uri(
|
||||
method,
|
||||
"http://localhost:4567/api/v1/threads/{}/votes".format(thread_id),
|
||||
f"http://localhost:4567/api/v1/threads/{thread_id}/votes",
|
||||
body=json.dumps({}), # body is unused
|
||||
status=200
|
||||
)
|
||||
@@ -288,7 +287,7 @@ class CommentsServiceMockMixin(object):
|
||||
for method in [httpretty.PUT, httpretty.DELETE]:
|
||||
httpretty.register_uri(
|
||||
method,
|
||||
"http://localhost:4567/api/v1/comments/{}/votes".format(comment_id),
|
||||
f"http://localhost:4567/api/v1/comments/{comment_id}/votes",
|
||||
body=json.dumps({}), # body is unused
|
||||
status=200
|
||||
)
|
||||
@@ -315,7 +314,7 @@ class CommentsServiceMockMixin(object):
|
||||
assert httpretty.is_enabled(), 'httpretty must be enabled to mock calls.'
|
||||
httpretty.register_uri(
|
||||
httpretty.POST,
|
||||
"http://localhost:4567/api/v1/users/{id}/read".format(id=user.id),
|
||||
f"http://localhost:4567/api/v1/users/{user.id}/read",
|
||||
params={'source_type': content_type, 'source_id': content_id},
|
||||
body=json.dumps({}), # body is unused
|
||||
status=200
|
||||
@@ -336,7 +335,7 @@ class CommentsServiceMockMixin(object):
|
||||
assert httpretty.is_enabled(), 'httpretty must be enabled to mock calls.'
|
||||
httpretty.register_uri(
|
||||
httpretty.DELETE,
|
||||
"http://localhost:4567/api/v1/threads/{id}".format(id=thread_id),
|
||||
f"http://localhost:4567/api/v1/threads/{thread_id}",
|
||||
body=json.dumps({}), # body is unused
|
||||
status=200
|
||||
)
|
||||
@@ -348,7 +347,7 @@ class CommentsServiceMockMixin(object):
|
||||
assert httpretty.is_enabled(), 'httpretty must be enabled to mock calls.'
|
||||
httpretty.register_uri(
|
||||
httpretty.DELETE,
|
||||
"http://localhost:4567/api/v1/comments/{id}".format(id=comment_id),
|
||||
f"http://localhost:4567/api/v1/comments/{comment_id}",
|
||||
body=json.dumps({}), # body is unused
|
||||
status=200
|
||||
)
|
||||
@@ -392,7 +391,7 @@ class CommentsServiceMockMixin(object):
|
||||
"voted": False,
|
||||
"vote_count": 0,
|
||||
"editable_fields": ["abuse_flagged", "following", "raw_body", "read", "title", "topic_id", "type", "voted"],
|
||||
"course_id": six.text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"topic_id": "test_topic",
|
||||
"group_id": None,
|
||||
"group_name": None,
|
||||
@@ -494,7 +493,7 @@ def make_paginated_api_response(results=None, count=0, num_pages=0, next_link=No
|
||||
}
|
||||
|
||||
|
||||
class ProfileImageTestMixin(object):
|
||||
class ProfileImageTestMixin:
|
||||
"""
|
||||
Mixin with utility methods for user profile image
|
||||
"""
|
||||
|
||||
@@ -39,14 +39,14 @@ urlpatterns = [
|
||||
name="discussion_course_roles",
|
||||
),
|
||||
url(
|
||||
r"^v1/courses/{}".format(settings.COURSE_ID_PATTERN),
|
||||
fr"^v1/courses/{settings.COURSE_ID_PATTERN}",
|
||||
CourseView.as_view(),
|
||||
name="discussion_course"
|
||||
),
|
||||
url(r"^v1/accounts/retire_forum", RetireUserView.as_view(), name="retire_discussion_user"),
|
||||
url(r"^v1/accounts/replace_username", ReplaceUsernamesView.as_view(), name="replace_discussion_username"),
|
||||
url(
|
||||
r"^v1/course_topics/{}".format(settings.COURSE_ID_PATTERN),
|
||||
fr"^v1/course_topics/{settings.COURSE_ID_PATTERN}",
|
||||
CourseTopicsView.as_view(),
|
||||
name="course_topics"
|
||||
),
|
||||
|
||||
@@ -17,10 +17,8 @@ from rest_framework.parsers import JSONParser
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.viewsets import ViewSet
|
||||
from six import text_type
|
||||
|
||||
from lms.djangoapps.discussion.views import get_divided_discussions
|
||||
from lms.djangoapps.instructor.access import update_forum_role
|
||||
from common.djangoapps.util.json_request import JsonResponse
|
||||
from lms.djangoapps.discussion.django_comment_client.utils import available_division_schemes
|
||||
from lms.djangoapps.discussion.rest_api.api import (
|
||||
create_comment,
|
||||
@@ -48,6 +46,8 @@ from lms.djangoapps.discussion.rest_api.serializers import (
|
||||
DiscussionRolesSerializer,
|
||||
DiscussionSettingsSerializer
|
||||
)
|
||||
from lms.djangoapps.discussion.views import get_divided_discussions
|
||||
from lms.djangoapps.instructor.access import update_forum_role
|
||||
from openedx.core.djangoapps.django_comment_common import comment_client
|
||||
from openedx.core.djangoapps.django_comment_common.models import Role
|
||||
from openedx.core.djangoapps.django_comment_common.utils import (
|
||||
@@ -57,10 +57,8 @@ from openedx.core.djangoapps.django_comment_common.utils import (
|
||||
from openedx.core.djangoapps.user_api.accounts.permissions import CanReplaceUsername, CanRetireUser
|
||||
from openedx.core.djangoapps.user_api.models import UserRetirementStatus
|
||||
from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser
|
||||
|
||||
from openedx.core.lib.api.parsers import MergePatchParser
|
||||
from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, view_auth_classes
|
||||
from common.djangoapps.util.json_request import JsonResponse
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -594,7 +592,7 @@ class RetireUserView(APIView):
|
||||
return Response(status=status.HTTP_404_NOT_FOUND)
|
||||
raise
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
return Response(str(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@@ -661,7 +659,7 @@ class ReplaceUsernamesView(APIView):
|
||||
cc_user.replace_username(new_username)
|
||||
except User.DoesNotExist:
|
||||
log.warning(
|
||||
u"Unable to change username from %s to %s in forums because %s doesn't exist in LMS DB.",
|
||||
"Unable to change username from %s to %s in forums because %s doesn't exist in LMS DB.",
|
||||
current_username,
|
||||
new_username,
|
||||
new_username,
|
||||
@@ -670,14 +668,14 @@ class ReplaceUsernamesView(APIView):
|
||||
except comment_client.CommentClientRequestError as exc:
|
||||
if exc.status_code == 404:
|
||||
log.info(
|
||||
u"Unable to change username from %s to %s in forums because user doesn't exist in forums",
|
||||
"Unable to change username from %s to %s in forums because user doesn't exist in forums",
|
||||
current_username,
|
||||
new_username,
|
||||
)
|
||||
return True
|
||||
else:
|
||||
log.exception(
|
||||
u"Unable to change username from %s to %s in forums because forums API call failed with: %s.",
|
||||
"Unable to change username from %s to %s in forums because forums API call failed with: %s.",
|
||||
current_username,
|
||||
new_username,
|
||||
exc,
|
||||
@@ -685,7 +683,7 @@ class ReplaceUsernamesView(APIView):
|
||||
return False
|
||||
|
||||
log.info(
|
||||
u"Successfully changed username from %s to %s in forums.",
|
||||
"Successfully changed username from %s to %s in forums.",
|
||||
current_username,
|
||||
new_username,
|
||||
)
|
||||
@@ -824,7 +822,7 @@ class CourseDiscussionSettingsAPIView(DeveloperErrorViewMixin, APIView):
|
||||
try:
|
||||
discussion_settings = set_course_discussion_settings(course_key, **settings_to_change)
|
||||
except ValueError as e:
|
||||
raise ValidationError(text_type(e)) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
raise ValidationError(str(e)) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@@ -937,7 +935,7 @@ class CourseDiscussionRolesAPIView(DeveloperErrorViewMixin, APIView):
|
||||
try:
|
||||
update_forum_role(course_id, user, rolename, action)
|
||||
except Role.DoesNotExist:
|
||||
raise ValidationError(u"Role '{}' does not exist".format(rolename)) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
raise ValidationError(f"Role '{rolename}' does not exist") # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
role = form.cleaned_data['role']
|
||||
data = {'course_id': course_id, 'users': role.users.all()}
|
||||
|
||||
@@ -5,7 +5,6 @@ Signal handlers related to discussions.
|
||||
|
||||
import logging
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.dispatch import receiver
|
||||
from opaque_keys.edx.locator import LibraryLocator
|
||||
@@ -33,7 +32,7 @@ def update_discussions_on_course_publish(sender, course_key, **kwargs): # pylin
|
||||
return
|
||||
|
||||
context = {
|
||||
'course_id': six.text_type(course_key),
|
||||
'course_id': str(course_key),
|
||||
}
|
||||
tasks.update_discussions_map.apply_async(
|
||||
args=[context],
|
||||
@@ -45,16 +44,16 @@ def update_discussions_on_course_publish(sender, course_key, **kwargs): # pylin
|
||||
def send_discussion_email_notification(sender, user, post, **kwargs): # lint-amnesty, pylint: disable=missing-function-docstring, unused-argument
|
||||
current_site = get_current_site()
|
||||
if current_site is None:
|
||||
log.info(u'Discussion: No current site, not sending notification about post: %s.', post.id)
|
||||
log.info('Discussion: No current site, not sending notification about post: %s.', post.id)
|
||||
return
|
||||
|
||||
try:
|
||||
if not current_site.configuration.get_value(ENABLE_FORUM_NOTIFICATIONS_FOR_SITE_KEY, False):
|
||||
log_message = u'Discussion: notifications not enabled for site: %s. Not sending message about post: %s.'
|
||||
log_message = 'Discussion: notifications not enabled for site: %s. Not sending message about post: %s.'
|
||||
log.info(log_message, current_site, post.id)
|
||||
return
|
||||
except SiteConfiguration.DoesNotExist:
|
||||
log_message = u'Discussion: No SiteConfiguration for site %s. Not sending message about post: %s.'
|
||||
log_message = 'Discussion: No SiteConfiguration for site %s. Not sending message about post: %s.'
|
||||
log.info(log_message, current_site, post.id)
|
||||
return
|
||||
|
||||
@@ -64,7 +63,7 @@ def send_discussion_email_notification(sender, user, post, **kwargs): # lint-am
|
||||
def send_message(comment, site): # lint-amnesty, pylint: disable=missing-function-docstring
|
||||
thread = comment.thread
|
||||
context = {
|
||||
'course_id': six.text_type(thread.course_id),
|
||||
'course_id': str(thread.course_id),
|
||||
'comment_id': comment.id,
|
||||
'comment_body': comment.body,
|
||||
'comment_author_id': comment.user_id,
|
||||
|
||||
@@ -6,7 +6,6 @@ pertaining to new discussion forum comments.
|
||||
|
||||
import logging
|
||||
|
||||
import six
|
||||
from celery import shared_task
|
||||
from celery_utils.logged_task import LoggedTask
|
||||
from django.conf import settings # lint-amnesty, pylint: disable=unused-import
|
||||
@@ -21,6 +20,7 @@ from opaque_keys.edx.keys import CourseKey
|
||||
from six.moves.urllib.parse import urljoin
|
||||
|
||||
import openedx.core.djangoapps.django_comment_common.comment_client as cc
|
||||
from common.djangoapps.track import segment
|
||||
from lms.djangoapps.discussion.django_comment_client.utils import (
|
||||
get_accessible_discussion_xblocks_by_course_id,
|
||||
permalink
|
||||
@@ -30,7 +30,6 @@ from openedx.core.djangoapps.ace_common.template_context import get_base_templat
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from openedx.core.djangoapps.django_comment_common.models import DiscussionsIdMapping
|
||||
from openedx.core.lib.celery.task_utils import emulate_http_request
|
||||
from common.djangoapps.track import segment
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -51,7 +50,7 @@ def update_discussions_map(context):
|
||||
course_key = CourseKey.from_string(context['course_id'])
|
||||
discussion_blocks = get_accessible_discussion_xblocks_by_course_id(course_key, include_all=True)
|
||||
discussions_id_map = {
|
||||
discussion_block.discussion_id: six.text_type(discussion_block.location)
|
||||
discussion_block.discussion_id: str(discussion_block.location)
|
||||
for discussion_block in discussion_blocks
|
||||
}
|
||||
DiscussionsIdMapping.update_mapping(course_key, discussions_id_map)
|
||||
@@ -76,7 +75,7 @@ def send_ace_message(context): # lint-amnesty, pylint: disable=missing-function
|
||||
_get_course_language(context['course_id']),
|
||||
message_context
|
||||
)
|
||||
log.info(u'Sending forum comment email notification with context %s', message_context)
|
||||
log.info('Sending forum comment email notification with context %s', message_context)
|
||||
ace.send(message)
|
||||
_track_notification_sent(message, context)
|
||||
|
||||
@@ -89,10 +88,10 @@ def _track_notification_sent(message, context):
|
||||
'app_label': 'discussion',
|
||||
'name': 'responsenotification', # This is 'Campaign' in GA
|
||||
'language': message.language,
|
||||
'uuid': six.text_type(message.uuid),
|
||||
'send_uuid': six.text_type(message.send_uuid),
|
||||
'uuid': str(message.uuid),
|
||||
'send_uuid': str(message.send_uuid),
|
||||
'thread_id': context['thread_id'],
|
||||
'course_id': six.text_type(context['course_id']),
|
||||
'course_id': str(context['course_id']),
|
||||
'thread_created_at': date.deserialize(context['thread_created_at']),
|
||||
'nonInteraction': 1,
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
## mako
|
||||
|
||||
<%!
|
||||
import six
|
||||
|
||||
from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_string
|
||||
%>
|
||||
@@ -48,7 +47,7 @@ from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_str
|
||||
$(function() {
|
||||
require(['discussion/js/discussion_board_factory'], function (DiscussionBoardFactory) {
|
||||
DiscussionBoardFactory({
|
||||
courseId: '${six.text_type(course.id) | n, js_escaped_string}',
|
||||
courseId: '${str(course.id) | n, js_escaped_string}',
|
||||
$el: $(".discussion-board"),
|
||||
rootUrl: '${root_url | n, js_escaped_string}',
|
||||
userInfo: ${user_info | n, dump_js_escaped_json},
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
<%!
|
||||
import json
|
||||
import six
|
||||
|
||||
from django.utils.translation import ugettext as _, ungettext
|
||||
from django.template.defaultfilters import escapejs
|
||||
@@ -21,7 +20,7 @@ from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_str
|
||||
<%static:require_module module_name="discussion/js/discussion_profile_page_factory" class_name="DiscussionProfilePageFactory">
|
||||
profile_page_context = {
|
||||
'courseSettings': ${course_settings | n, dump_js_escaped_json},
|
||||
'courseId': '${six.text_type(course.id) | n, js_escaped_string}',
|
||||
'courseId': '${str(course.id) | n, js_escaped_string}',
|
||||
'courseName': '${course.display_name_with_default | n, js_escaped_string}',
|
||||
'contentInfo': ${annotated_content_info | n, dump_js_escaped_json},
|
||||
'userInfo': ${user_info | n, dump_js_escaped_json},
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"""
|
||||
Tests the forum notification signals.
|
||||
"""
|
||||
|
||||
|
||||
import mock
|
||||
from django.test import TestCase
|
||||
from edx_django_utils.cache import RequestCache
|
||||
|
||||
@@ -6,10 +6,9 @@ Tests the execution of forum notification tasks.
|
||||
import json
|
||||
import math
|
||||
from datetime import datetime, timedelta
|
||||
from unittest import mock
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
import six
|
||||
from django.contrib.sites.models import Site
|
||||
from edx_ace.channel import ChannelType, get_channel_for_message
|
||||
from edx_ace.recipient import Recipient
|
||||
@@ -17,6 +16,7 @@ from edx_ace.renderers import EmailRenderer
|
||||
from edx_ace.utils import date
|
||||
|
||||
import openedx.core.djangoapps.django_comment_common.comment_client as cc
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from lms.djangoapps.discussion.signals.handlers import ENABLE_FORUM_NOTIFICATIONS_FOR_SITE_KEY
|
||||
from lms.djangoapps.discussion.tasks import _should_send_message, _track_notification_sent
|
||||
from openedx.core.djangoapps.ace_common.template_context import get_base_template_context
|
||||
@@ -25,7 +25,6 @@ from openedx.core.djangoapps.django_comment_common.models import ForumsConfig
|
||||
from openedx.core.djangoapps.django_comment_common.signals import comment_created
|
||||
from openedx.core.djangoapps.site_configuration.tests.factories import SiteConfigurationFactory
|
||||
from openedx.core.lib.celery.task_utils import emulate_http_request
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
|
||||
NOW = datetime.utcnow()
|
||||
@@ -72,7 +71,7 @@ class TaskTestCase(ModuleStoreTestCase): # lint-amnesty, pylint: disable=missin
|
||||
@classmethod
|
||||
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUpClass(cls):
|
||||
super(TaskTestCase, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.discussion_id = 'dummy_discussion_id'
|
||||
cls.course = CourseOverviewFactory.create(language='fr')
|
||||
|
||||
@@ -109,7 +108,7 @@ class TaskTestCase(ModuleStoreTestCase): # lint-amnesty, pylint: disable=missin
|
||||
def create_thread_and_comments(cls): # lint-amnesty, pylint: disable=missing-function-docstring
|
||||
cls.thread = {
|
||||
'id': cls.discussion_id,
|
||||
'course_id': six.text_type(cls.course.id),
|
||||
'course_id': str(cls.course.id),
|
||||
'created_at': date.serialize(TWO_HOURS_AGO),
|
||||
'title': 'thread-title',
|
||||
'user_id': cls.thread_author.id,
|
||||
@@ -147,7 +146,7 @@ class TaskTestCase(ModuleStoreTestCase): # lint-amnesty, pylint: disable=missin
|
||||
cls.comment['child_count'] = 1
|
||||
cls.thread2 = {
|
||||
'id': cls.discussion_id,
|
||||
'course_id': six.text_type(cls.course.id),
|
||||
'course_id': str(cls.course.id),
|
||||
'created_at': date.serialize(TWO_HOURS_AGO),
|
||||
'title': 'thread-title',
|
||||
'user_id': cls.thread_author.id,
|
||||
@@ -156,7 +155,7 @@ class TaskTestCase(ModuleStoreTestCase): # lint-amnesty, pylint: disable=missin
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
super(TaskTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.request_patcher = mock.patch('requests.request')
|
||||
self.mock_request = self.request_patcher.start()
|
||||
|
||||
@@ -168,7 +167,7 @@ class TaskTestCase(ModuleStoreTestCase): # lint-amnesty, pylint: disable=missin
|
||||
self.mock_permalink = self.permalink_patcher.start()
|
||||
|
||||
def tearDown(self):
|
||||
super(TaskTestCase, self).tearDown() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().tearDown()
|
||||
self.request_patcher.stop()
|
||||
self.ace_send_patcher.stop()
|
||||
self.permalink_patcher.stop()
|
||||
|
||||
@@ -6,22 +6,22 @@ Tests the forum notification views.
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from unittest.mock import ANY, Mock, call, patch
|
||||
|
||||
import ddt
|
||||
import pytest
|
||||
import six
|
||||
from django.http import Http404
|
||||
from django.test.client import Client, RequestFactory
|
||||
from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from django.utils import translation
|
||||
from edx_django_utils.cache import RequestCache
|
||||
from mock import ANY, Mock, call, patch
|
||||
from six import text_type
|
||||
from six.moves import range
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
|
||||
from common.djangoapps.student.roles import CourseStaffRole, UserBasedRole
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from common.djangoapps.util.testing import EventTestMixin, UrlResetMixin
|
||||
from lms.djangoapps.courseware.exceptions import CourseAccessRedirect
|
||||
from lms.djangoapps.discussion import views
|
||||
from lms.djangoapps.discussion.django_comment_client.constants import TYPE_ENTRY, TYPE_SUBCATEGORY
|
||||
@@ -56,9 +56,6 @@ from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES
|
||||
from openedx.core.lib.teams_config import TeamsConfig
|
||||
from openedx.features.content_type_gating.models import ContentTypeGatingConfig
|
||||
from openedx.features.enterprise_support.tests.mixins.enterprise import EnterpriseTestConsentRequired
|
||||
from common.djangoapps.student.roles import CourseStaffRole, UserBasedRole
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from common.djangoapps.util.testing import EventTestMixin, UrlResetMixin
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import (
|
||||
@@ -81,7 +78,7 @@ class ViewsExceptionTestCase(UrlResetMixin, ModuleStoreTestCase): # lint-amnest
|
||||
# Patching the ENABLE_DISCUSSION_SERVICE value affects the contents of urls.py,
|
||||
# so we need to call super.setUp() which reloads urls.py (because
|
||||
# of the UrlResetMixin)
|
||||
super(ViewsExceptionTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
# create a course
|
||||
self.course = CourseFactory.create(org='MITx', course='999',
|
||||
@@ -121,7 +118,7 @@ class ViewsExceptionTestCase(UrlResetMixin, ModuleStoreTestCase): # lint-amnest
|
||||
mock_from_django_user.return_value = Mock()
|
||||
|
||||
url = reverse('user_profile',
|
||||
kwargs={'course_id': text_type(self.course.id), 'user_id': '12345'}) # There is no user 12345
|
||||
kwargs={'course_id': str(self.course.id), 'user_id': '12345'}) # There is no user 12345
|
||||
response = self.client.get(url)
|
||||
assert response.status_code == 404
|
||||
|
||||
@@ -138,7 +135,7 @@ class ViewsExceptionTestCase(UrlResetMixin, ModuleStoreTestCase): # lint-amnest
|
||||
mock_from_django_user.return_value = Mock()
|
||||
|
||||
url = reverse('followed_threads',
|
||||
kwargs={'course_id': text_type(self.course.id), 'user_id': '12345'}) # There is no user 12345
|
||||
kwargs={'course_id': str(self.course.id), 'user_id': '12345'}) # There is no user 12345
|
||||
response = self.client.get(url)
|
||||
assert response.status_code == 404
|
||||
|
||||
@@ -176,7 +173,7 @@ def make_mock_thread_data( # lint-amnesty, pylint: disable=missing-function-doc
|
||||
thread_data['is_commentable_divided'] = is_commentable_divided
|
||||
if num_children is not None:
|
||||
thread_data["children"] = [{
|
||||
"id": "dummy_comment_id_{}".format(i),
|
||||
"id": f"dummy_comment_id_{i}",
|
||||
"type": "comment",
|
||||
"body": text,
|
||||
} for i in range(num_children)]
|
||||
@@ -283,7 +280,7 @@ def make_mock_request_impl( # lint-amnesty, pylint: disable=missing-function-do
|
||||
return mock_request_impl
|
||||
|
||||
|
||||
class StringEndsWithMatcher(object): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
class StringEndsWithMatcher: # lint-amnesty, pylint: disable=missing-class-docstring,eq-without-hash
|
||||
def __init__(self, suffix):
|
||||
self.suffix = suffix
|
||||
|
||||
@@ -291,14 +288,14 @@ class StringEndsWithMatcher(object): # lint-amnesty, pylint: disable=missing-cl
|
||||
return other.endswith(self.suffix)
|
||||
|
||||
|
||||
class PartialDictMatcher(object): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
class PartialDictMatcher: # lint-amnesty, pylint: disable=missing-class-docstring,eq-without-hash
|
||||
def __init__(self, expected_values):
|
||||
self.expected_values = expected_values
|
||||
|
||||
def __eq__(self, other):
|
||||
return all([
|
||||
key in other and other[key] == value
|
||||
for key, value in six.iteritems(self.expected_values)
|
||||
for key, value in self.expected_values.items()
|
||||
])
|
||||
|
||||
|
||||
@@ -308,7 +305,7 @@ class SingleThreadTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-amne
|
||||
CREATE_USER = False
|
||||
|
||||
def setUp(self):
|
||||
super(SingleThreadTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
self.course = CourseFactory.create(discussion_topics={'dummy discussion': {'id': 'dummy_discussion_id'}})
|
||||
self.student = UserFactory.create()
|
||||
@@ -326,7 +323,7 @@ class SingleThreadTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-amne
|
||||
request.user = self.student
|
||||
response = views.single_thread(
|
||||
request,
|
||||
text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
"dummy_discussion_id",
|
||||
"test_thread_id"
|
||||
)
|
||||
@@ -365,7 +362,7 @@ class SingleThreadTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-amne
|
||||
request.user = self.student
|
||||
response = views.single_thread(
|
||||
request,
|
||||
text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
"dummy_discussion_id",
|
||||
"test_thread_id"
|
||||
)
|
||||
@@ -398,7 +395,7 @@ class SingleThreadTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-amne
|
||||
request = RequestFactory().post("dummy_url")
|
||||
response = views.single_thread(
|
||||
request,
|
||||
text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
"dummy_discussion_id",
|
||||
"dummy_thread_id"
|
||||
)
|
||||
@@ -413,7 +410,7 @@ class SingleThreadTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-amne
|
||||
Http404,
|
||||
views.single_thread,
|
||||
request,
|
||||
text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
"test_discussion_id",
|
||||
"test_thread_id"
|
||||
)
|
||||
@@ -436,7 +433,7 @@ class SingleThreadTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-amne
|
||||
mocked.return_value = True
|
||||
response = self.client.get(
|
||||
reverse('single_thread', kwargs={
|
||||
'course_id': six.text_type(self.course.id),
|
||||
'course_id': str(self.course.id),
|
||||
'discussion_id': discussion_topic_id,
|
||||
'thread_id': thread_id,
|
||||
})
|
||||
@@ -464,7 +461,7 @@ class AllowPlusOrMinusOneInt(int): # pylint: disable=eq-without-hash
|
||||
return other in self.values
|
||||
|
||||
def __repr__(self):
|
||||
return "({} +/- 1)".format(self.value)
|
||||
return f"({self.value} +/- 1)"
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -532,7 +529,7 @@ class SingleThreadQueryCountTestCase(ForumsEnableMixin, ModuleStoreTestCase):
|
||||
with patch.dict("django.conf.settings.FEATURES", dict(ENABLE_ENTERPRISE_INTEGRATION=enterprise_enabled)):
|
||||
response = views.single_thread(
|
||||
request,
|
||||
text_type(course.id),
|
||||
str(course.id),
|
||||
"dummy_discussion_id",
|
||||
test_thread_id
|
||||
)
|
||||
@@ -577,7 +574,7 @@ class SingleCohortedThreadTestCase(CohortedTestCase): # lint-amnesty, pylint: d
|
||||
request.user = self.student
|
||||
response = views.single_thread(
|
||||
request,
|
||||
text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
"cohorted_topic",
|
||||
mock_thread_id
|
||||
)
|
||||
@@ -601,7 +598,7 @@ class SingleCohortedThreadTestCase(CohortedTestCase): # lint-amnesty, pylint: d
|
||||
self.client.login(username=self.student.username, password='test')
|
||||
response = self.client.get(
|
||||
reverse('single_thread', kwargs={
|
||||
'course_id': six.text_type(self.course.id),
|
||||
'course_id': str(self.course.id),
|
||||
'discussion_id': "cohorted_topic",
|
||||
'thread_id': mock_thread_id,
|
||||
})
|
||||
@@ -635,7 +632,7 @@ class SingleThreadAccessTestCase(CohortedTestCase): # lint-amnesty, pylint: dis
|
||||
request.user = user
|
||||
return views.single_thread(
|
||||
request,
|
||||
text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
commentable_id,
|
||||
thread_id
|
||||
)
|
||||
@@ -735,7 +732,7 @@ class SingleThreadGroupIdTestCase(CohortedTestCase, GroupIdAssertionMixin): # l
|
||||
self.client.login(username=user.username, password='test')
|
||||
|
||||
return self.client.get(
|
||||
reverse('single_thread', args=[six.text_type(self.course.id), commentable_id, "dummy_thread_id"]),
|
||||
reverse('single_thread', args=[str(self.course.id), commentable_id, "dummy_thread_id"]),
|
||||
data=request_data,
|
||||
**headers
|
||||
)
|
||||
@@ -774,7 +771,7 @@ class ForumFormDiscussionContentGroupTestCase(ForumsEnableMixin, ContentGroupTes
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(ForumFormDiscussionContentGroupTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.thread_list = [
|
||||
{"thread_id": "test_general_thread_id"},
|
||||
{"thread_id": "test_global_group_thread_id", "commentable_id": self.global_module.discussion_id},
|
||||
@@ -800,7 +797,7 @@ class ForumFormDiscussionContentGroupTestCase(ForumsEnableMixin, ContentGroupTes
|
||||
)
|
||||
self.client.login(username=user.username, password='test')
|
||||
return self.client.get(
|
||||
reverse("forum_form_discussion", args=[six.text_type(self.course.id)]),
|
||||
reverse("forum_form_discussion", args=[str(self.course.id)]),
|
||||
HTTP_X_REQUESTED_WITH="XMLHttpRequest"
|
||||
)
|
||||
|
||||
@@ -854,7 +851,7 @@ class SingleThreadContentGroupTestCase(ForumsEnableMixin, UrlResetMixin, Content
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(SingleThreadContentGroupTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
def assert_can_access(self, user, discussion_id, thread_id, should_have_access):
|
||||
"""
|
||||
@@ -865,7 +862,7 @@ class SingleThreadContentGroupTestCase(ForumsEnableMixin, UrlResetMixin, Content
|
||||
def call_single_thread():
|
||||
self.client.login(username=user.username, password='test')
|
||||
return self.client.get(
|
||||
reverse('single_thread', args=[six.text_type(self.course.id), discussion_id, thread_id])
|
||||
reverse('single_thread', args=[str(self.course.id), discussion_id, thread_id])
|
||||
)
|
||||
|
||||
if should_have_access:
|
||||
@@ -963,7 +960,7 @@ class SingleThreadContentGroupTestCase(ForumsEnableMixin, UrlResetMixin, Content
|
||||
class InlineDiscussionContextTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
|
||||
def setUp(self):
|
||||
super(InlineDiscussionContextTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create()
|
||||
CourseEnrollmentFactory(user=self.user, course_id=self.course.id)
|
||||
self.discussion_topic_id = "dummy_topic"
|
||||
@@ -989,7 +986,7 @@ class InlineDiscussionContextTestCase(ForumsEnableMixin, ModuleStoreTestCase):
|
||||
|
||||
response = views.inline_discussion(
|
||||
request,
|
||||
six.text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
self.discussion_topic_id,
|
||||
)
|
||||
|
||||
@@ -1012,7 +1009,7 @@ class InlineDiscussionContextTestCase(ForumsEnableMixin, ModuleStoreTestCase):
|
||||
mocked.return_value = True
|
||||
response = views.inline_discussion(
|
||||
request,
|
||||
six.text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
self.discussion_topic_id,
|
||||
)
|
||||
assert response.status_code == 403
|
||||
@@ -1028,7 +1025,7 @@ class InlineDiscussionGroupIdTestCase( # lint-amnesty, pylint: disable=missing-
|
||||
cs_endpoint = "/threads"
|
||||
|
||||
def setUp(self):
|
||||
super(InlineDiscussionGroupIdTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.cohorted_commentable_id = 'cohorted_topic'
|
||||
|
||||
def call_view(self, mock_request, commentable_id, user, group_id, pass_group_id=True):
|
||||
@@ -1054,7 +1051,7 @@ class InlineDiscussionGroupIdTestCase( # lint-amnesty, pylint: disable=missing-
|
||||
request.user = user
|
||||
return views.inline_discussion(
|
||||
request,
|
||||
text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
commentable_id
|
||||
)
|
||||
|
||||
@@ -1089,7 +1086,7 @@ class ForumFormDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupIdT
|
||||
|
||||
self.client.login(username=user.username, password='test')
|
||||
return self.client.get(
|
||||
reverse("forum_form_discussion", args=[six.text_type(self.course.id)]),
|
||||
reverse("forum_form_discussion", args=[str(self.course.id)]),
|
||||
data=request_data,
|
||||
**headers
|
||||
)
|
||||
@@ -1141,7 +1138,7 @@ class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupI
|
||||
|
||||
self.client.login(username=requesting_user.username, password='test')
|
||||
return self.client.get(
|
||||
reverse('user_profile', args=[six.text_type(self.course.id), profiled_user.id]),
|
||||
reverse('user_profile', args=[str(self.course.id), profiled_user.id]),
|
||||
data=request_data,
|
||||
**headers
|
||||
)
|
||||
@@ -1295,7 +1292,7 @@ class FollowedThreadsDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGr
|
||||
request.user = user
|
||||
return views.followed_threads(
|
||||
request,
|
||||
text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
user.id
|
||||
)
|
||||
|
||||
@@ -1315,7 +1312,7 @@ class FollowedThreadsDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGr
|
||||
class InlineDiscussionTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
|
||||
def setUp(self):
|
||||
super(InlineDiscussionTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
self.course = CourseFactory.create(
|
||||
org="TestX",
|
||||
@@ -1351,7 +1348,7 @@ class InlineDiscussionTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-
|
||||
course=self.course, text="dummy content", commentable_id=self.discussion1.discussion_id
|
||||
)
|
||||
return views.inline_discussion(
|
||||
request, text_type(self.course.id), self.discussion1.discussion_id
|
||||
request, str(self.course.id), self.discussion1.discussion_id
|
||||
)
|
||||
|
||||
def test_context(self, mock_request):
|
||||
@@ -1376,7 +1373,7 @@ class UserProfileTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(UserProfileTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
self.course = CourseFactory.create()
|
||||
self.student = UserFactory.create()
|
||||
@@ -1392,7 +1389,7 @@ class UserProfileTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
|
||||
|
||||
response = self.client.get(
|
||||
reverse('user_profile', kwargs={
|
||||
'course_id': six.text_type(self.course.id),
|
||||
'course_id': str(self.course.id),
|
||||
'user_id': self.profiled_user.id,
|
||||
}),
|
||||
data=params,
|
||||
@@ -1400,10 +1397,10 @@ class UserProfileTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
|
||||
)
|
||||
mock_request.assert_any_call(
|
||||
"get",
|
||||
StringEndsWithMatcher('/users/{}/active_threads'.format(self.profiled_user.id)),
|
||||
StringEndsWithMatcher(f'/users/{self.profiled_user.id}/active_threads'),
|
||||
data=None,
|
||||
params=PartialDictMatcher({
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"page": params.get("page", 1),
|
||||
"per_page": views.THREADS_PER_PAGE
|
||||
}),
|
||||
@@ -1421,13 +1418,10 @@ class UserProfileTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
|
||||
self.assertRegex(html, r'data-num-pages="1"')
|
||||
self.assertRegex(html, r'<span class="discussion-count">1</span> discussion started')
|
||||
self.assertRegex(html, r'<span class="discussion-count">2</span> comments')
|
||||
self.assertRegex(html, u''id': '{}''.format(self.TEST_THREAD_ID))
|
||||
self.assertRegex(html, u''title': '{}''.format(self.TEST_THREAD_TEXT))
|
||||
self.assertRegex(html, u''body': '{}''.format(self.TEST_THREAD_TEXT))
|
||||
if six.PY2:
|
||||
self.assertRegex(html, u''username': u'{}''.format(self.student.username))
|
||||
else:
|
||||
self.assertRegex(html, u''username': '{}''.format(self.student.username))
|
||||
self.assertRegex(html, f''id': '{self.TEST_THREAD_ID}'')
|
||||
self.assertRegex(html, f''title': '{self.TEST_THREAD_TEXT}'')
|
||||
self.assertRegex(html, f''body': '{self.TEST_THREAD_TEXT}'')
|
||||
self.assertRegex(html, f''username': '{self.student.username}'')
|
||||
|
||||
def check_ajax(self, mock_request, **params): # lint-amnesty, pylint: disable=missing-function-docstring
|
||||
response = self.get_response(mock_request, params, HTTP_X_REQUESTED_WITH="XMLHttpRequest")
|
||||
@@ -1459,7 +1453,7 @@ class UserProfileTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
|
||||
with pytest.raises(Http404):
|
||||
views.user_profile(
|
||||
request,
|
||||
text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
unenrolled_user.id
|
||||
)
|
||||
|
||||
@@ -1469,7 +1463,7 @@ class UserProfileTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
|
||||
with pytest.raises(Http404):
|
||||
views.user_profile(
|
||||
request,
|
||||
text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
-999
|
||||
)
|
||||
|
||||
@@ -1491,7 +1485,7 @@ class UserProfileTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
|
||||
request.user = self.student
|
||||
response = views.user_profile(
|
||||
request,
|
||||
text_type(self.course.id),
|
||||
str(self.course.id),
|
||||
self.profiled_user.id
|
||||
)
|
||||
assert response.status_code == 405
|
||||
@@ -1504,13 +1498,13 @@ class CommentsServiceRequestHeadersTestCase(ForumsEnableMixin, UrlResetMixin, Mo
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(CommentsServiceRequestHeadersTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
username = "foo"
|
||||
password = "bar"
|
||||
|
||||
# Invoke UrlResetMixin
|
||||
super(CommentsServiceRequestHeadersTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create(discussion_topics={'dummy discussion': {'id': 'dummy_discussion_id'}})
|
||||
self.student = UserFactory.create(username=username, password=password)
|
||||
CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id)
|
||||
@@ -1540,7 +1534,7 @@ class CommentsServiceRequestHeadersTestCase(ForumsEnableMixin, UrlResetMixin, Mo
|
||||
reverse(
|
||||
"single_thread",
|
||||
kwargs={
|
||||
"course_id": text_type(self.course.id),
|
||||
"course_id": str(self.course.id),
|
||||
"discussion_id": "dummy_discussion_id",
|
||||
"thread_id": thread_id,
|
||||
}
|
||||
@@ -1556,7 +1550,7 @@ class CommentsServiceRequestHeadersTestCase(ForumsEnableMixin, UrlResetMixin, Mo
|
||||
self.client.get(
|
||||
reverse(
|
||||
"forum_form_discussion",
|
||||
kwargs={"course_id": text_type(self.course.id)}
|
||||
kwargs={"course_id": str(self.course.id)}
|
||||
),
|
||||
)
|
||||
self.assert_all_calls_have_header(mock_request, "X-Edx-Api-Key", "test_api_key")
|
||||
@@ -1567,12 +1561,12 @@ class InlineDiscussionUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCa
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(InlineDiscussionUnicodeTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(InlineDiscussionUnicodeTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
cls.student = UserFactory.create()
|
||||
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
|
||||
@@ -1584,7 +1578,7 @@ class InlineDiscussionUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCa
|
||||
request.user = self.student
|
||||
|
||||
response = views.inline_discussion(
|
||||
request, text_type(self.course.id), self.course.discussion_topics['General']['id']
|
||||
request, str(self.course.id), self.course.discussion_topics['General']['id']
|
||||
)
|
||||
assert response.status_code == 200
|
||||
response_data = json.loads(response.content.decode('utf-8'))
|
||||
@@ -1597,12 +1591,12 @@ class ForumFormDiscussionUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTes
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(ForumFormDiscussionUnicodeTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(ForumFormDiscussionUnicodeTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
cls.student = UserFactory.create()
|
||||
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
|
||||
@@ -1614,7 +1608,7 @@ class ForumFormDiscussionUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTes
|
||||
request.user = self.student
|
||||
request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True
|
||||
|
||||
response = views.forum_form_discussion(request, text_type(self.course.id))
|
||||
response = views.forum_form_discussion(request, str(self.course.id))
|
||||
assert response.status_code == 200
|
||||
response_data = json.loads(response.content.decode('utf-8'))
|
||||
assert response_data['discussion_data'][0]['title'] == text
|
||||
@@ -1627,7 +1621,7 @@ class ForumDiscussionXSSTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTe
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(ForumDiscussionXSSTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
username = "foo"
|
||||
password = "bar"
|
||||
@@ -1645,11 +1639,11 @@ class ForumDiscussionXSSTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTe
|
||||
"""
|
||||
mock_user.return_value.to_dict.return_value = {}
|
||||
mock_req.return_value.status_code = 200
|
||||
reverse_url = "%s%s" % (reverse(
|
||||
reverse_url = "{}{}".format(reverse(
|
||||
"forum_form_discussion",
|
||||
kwargs={"course_id": six.text_type(self.course.id)}), '/forum_form_discussion')
|
||||
kwargs={"course_id": str(self.course.id)}), '/forum_form_discussion')
|
||||
# Test that malicious code does not appear in html
|
||||
url = "%s?%s=%s" % (reverse_url, 'sort_key', malicious_code)
|
||||
url = "{}?{}={}".format(reverse_url, 'sort_key', malicious_code)
|
||||
resp = self.client.get(url)
|
||||
self.assertNotContains(resp, malicious_code)
|
||||
|
||||
@@ -1669,9 +1663,9 @@ class ForumDiscussionXSSTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTe
|
||||
mock_request.side_effect = make_mock_request_impl(course=self.course, text='dummy')
|
||||
|
||||
url = reverse('user_profile',
|
||||
kwargs={'course_id': six.text_type(self.course.id), 'user_id': str(self.student.id)})
|
||||
kwargs={'course_id': str(self.course.id), 'user_id': str(self.student.id)})
|
||||
# Test that malicious code does not appear in html
|
||||
url_string = "%s?%s=%s" % (url, 'page', malicious_code)
|
||||
url_string = "{}?{}={}".format(url, 'page', malicious_code)
|
||||
resp = self.client.get(url_string)
|
||||
self.assertNotContains(resp, malicious_code)
|
||||
|
||||
@@ -1681,12 +1675,12 @@ class ForumDiscussionSearchUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreT
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(ForumDiscussionSearchUnicodeTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(ForumDiscussionSearchUnicodeTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
cls.student = UserFactory.create()
|
||||
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
|
||||
@@ -1702,7 +1696,7 @@ class ForumDiscussionSearchUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreT
|
||||
request.user = self.student
|
||||
request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True
|
||||
|
||||
response = views.forum_form_discussion(request, text_type(self.course.id))
|
||||
response = views.forum_form_discussion(request, str(self.course.id))
|
||||
assert response.status_code == 200
|
||||
response_data = json.loads(response.content.decode('utf-8'))
|
||||
assert response_data['discussion_data'][0]['title'] == text
|
||||
@@ -1714,12 +1708,12 @@ class SingleThreadUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase,
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(SingleThreadUnicodeTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create(discussion_topics={'dummy_discussion_id': {'id': 'dummy_discussion_id'}})
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(SingleThreadUnicodeTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
cls.student = UserFactory.create()
|
||||
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
|
||||
@@ -1732,7 +1726,7 @@ class SingleThreadUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase,
|
||||
request.user = self.student
|
||||
request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True
|
||||
|
||||
response = views.single_thread(request, text_type(self.course.id), "dummy_discussion_id", thread_id)
|
||||
response = views.single_thread(request, str(self.course.id), "dummy_discussion_id", thread_id)
|
||||
assert response.status_code == 200
|
||||
response_data = json.loads(response.content.decode('utf-8'))
|
||||
assert response_data['content']['title'] == text
|
||||
@@ -1744,12 +1738,12 @@ class UserProfileUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, U
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(UserProfileUnicodeTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(UserProfileUnicodeTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
cls.student = UserFactory.create()
|
||||
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
|
||||
@@ -1761,7 +1755,7 @@ class UserProfileUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, U
|
||||
request.user = self.student
|
||||
request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True
|
||||
|
||||
response = views.user_profile(request, text_type(self.course.id), str(self.student.id))
|
||||
response = views.user_profile(request, str(self.course.id), str(self.student.id))
|
||||
assert response.status_code == 200
|
||||
response_data = json.loads(response.content.decode('utf-8'))
|
||||
assert response_data['discussion_data'][0]['title'] == text
|
||||
@@ -1773,12 +1767,12 @@ class FollowedThreadsUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCas
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(FollowedThreadsUnicodeTestCase, cls).setUpClassAndTestData():
|
||||
with super().setUpClassAndTestData():
|
||||
cls.course = CourseFactory.create()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(FollowedThreadsUnicodeTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
cls.student = UserFactory.create()
|
||||
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
|
||||
@@ -1790,7 +1784,7 @@ class FollowedThreadsUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCas
|
||||
request.user = self.student
|
||||
request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True
|
||||
|
||||
response = views.followed_threads(request, text_type(self.course.id), str(self.student.id))
|
||||
response = views.followed_threads(request, str(self.course.id), str(self.student.id))
|
||||
assert response.status_code == 200
|
||||
response_data = json.loads(response.content.decode('utf-8'))
|
||||
assert response_data['discussion_data'][0]['title'] == text
|
||||
@@ -1805,7 +1799,7 @@ class EnrollmentTestCase(ForumsEnableMixin, ModuleStoreTestCase):
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super(EnrollmentTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create()
|
||||
self.student = UserFactory.create()
|
||||
|
||||
@@ -1816,7 +1810,7 @@ class EnrollmentTestCase(ForumsEnableMixin, ModuleStoreTestCase):
|
||||
request = RequestFactory().get('dummy_url')
|
||||
request.user = self.student
|
||||
with pytest.raises(CourseAccessRedirect):
|
||||
views.forum_form_discussion(request, course_id=text_type(self.course.id)) # pylint: disable=no-value-for-parameter, unexpected-keyword-arg
|
||||
views.forum_form_discussion(request, course_id=str(self.course.id)) # pylint: disable=no-value-for-parameter, unexpected-keyword-arg
|
||||
|
||||
|
||||
@patch('requests.request', autospec=True)
|
||||
@@ -1829,7 +1823,7 @@ class EnterpriseConsentTestCase(EnterpriseTestConsentRequired, ForumsEnableMixin
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
# Invoke UrlResetMixin setUp
|
||||
super(EnterpriseConsentTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
username = "foo"
|
||||
password = "bar"
|
||||
@@ -1851,7 +1845,7 @@ class EnterpriseConsentTestCase(EnterpriseTestConsentRequired, ForumsEnableMixin
|
||||
mock_enterprise_customer_for_request.return_value = None
|
||||
|
||||
thread_id = 'dummy'
|
||||
course_id = six.text_type(self.course.id)
|
||||
course_id = str(self.course.id)
|
||||
mock_request.side_effect = make_mock_request_impl(course=self.course, text='dummy', thread_id=thread_id)
|
||||
|
||||
for url in (
|
||||
@@ -1909,7 +1903,7 @@ class CourseDiscussionTopicsTestCase(DividedDiscussionsTestCase):
|
||||
"""
|
||||
Verify that we cannot access divide_discussion_topics if we're a non-staff user.
|
||||
"""
|
||||
self._verify_non_staff_cannot_access(views.discussion_topics, "GET", [six.text_type(self.course.id)])
|
||||
self._verify_non_staff_cannot_access(views.discussion_topics, "GET", [str(self.course.id)])
|
||||
|
||||
def test_get_discussion_topics(self):
|
||||
"""
|
||||
@@ -1965,12 +1959,12 @@ class CourseDiscussionsHandlerTestCase(DividedDiscussionsTestCase):
|
||||
Returns the static response dict.
|
||||
"""
|
||||
return {
|
||||
u'always_divide_inline_discussions': False,
|
||||
u'divided_inline_discussions': [],
|
||||
u'divided_course_wide_discussions': [],
|
||||
u'id': 1,
|
||||
u'division_scheme': u'cohort',
|
||||
u'available_division_schemes': [u'cohort']
|
||||
'always_divide_inline_discussions': False,
|
||||
'divided_inline_discussions': [],
|
||||
'divided_course_wide_discussions': [],
|
||||
'id': 1,
|
||||
'division_scheme': 'cohort',
|
||||
'available_division_schemes': ['cohort']
|
||||
}
|
||||
|
||||
def test_non_staff(self):
|
||||
@@ -1978,10 +1972,10 @@ class CourseDiscussionsHandlerTestCase(DividedDiscussionsTestCase):
|
||||
Verify that we cannot access course_discussions_settings_handler if we're a non-staff user.
|
||||
"""
|
||||
self._verify_non_staff_cannot_access(
|
||||
course_discussions_settings_handler, "GET", [six.text_type(self.course.id)]
|
||||
course_discussions_settings_handler, "GET", [str(self.course.id)]
|
||||
)
|
||||
self._verify_non_staff_cannot_access(
|
||||
course_discussions_settings_handler, "PATCH", [six.text_type(self.course.id)]
|
||||
course_discussions_settings_handler, "PATCH", [str(self.course.id)]
|
||||
)
|
||||
|
||||
def test_update_always_divide_inline_discussion_settings(self):
|
||||
@@ -2161,7 +2155,7 @@ class ThreadViewedEventTestCase(EventTestMixin, ForumsEnableMixin, UrlResetMixin
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self): # pylint: disable=arguments-differ
|
||||
super(ThreadViewedEventTestCase, self).setUp('eventtracking.tracker') # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp('eventtracking.tracker')
|
||||
|
||||
self.course = CourseFactory.create(
|
||||
teams_configuration=TeamsConfig({
|
||||
@@ -2206,8 +2200,8 @@ class ThreadViewedEventTestCase(EventTestMixin, ForumsEnableMixin, UrlResetMixin
|
||||
thread_id=self.DUMMY_THREAD_ID,
|
||||
commentable_id=self.category.discussion_id,
|
||||
)
|
||||
url = '/courses/{0}/discussion/forum/{1}/threads/{2}'.format(
|
||||
six.text_type(self.course.id),
|
||||
url = '/courses/{}/discussion/forum/{}/threads/{}'.format(
|
||||
str(self.course.id),
|
||||
self.category.discussion_id,
|
||||
self.DUMMY_THREAD_ID
|
||||
)
|
||||
|
||||
@@ -6,7 +6,6 @@ Views handling read (GET) requests for the Discussion tab and inline discussions
|
||||
import logging
|
||||
from functools import wraps
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
@@ -28,6 +27,8 @@ from web_fragments.fragment import Fragment
|
||||
|
||||
import lms.djangoapps.discussion.django_comment_client.utils as utils
|
||||
import openedx.core.djangoapps.django_comment_common.comment_client as cc
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.util.json_request import JsonResponse, expect_json
|
||||
from lms.djangoapps.courseware.access import has_access
|
||||
from lms.djangoapps.courseware.courses import get_course_with_access
|
||||
from lms.djangoapps.courseware.views.views import CourseTabView
|
||||
@@ -57,8 +58,6 @@ from openedx.core.djangoapps.django_comment_common.utils import (
|
||||
)
|
||||
from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
|
||||
from openedx.features.course_duration_limits.access import generate_course_expired_fragment
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.util.json_request import JsonResponse, expect_json
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
log = logging.getLogger("edx.discussions")
|
||||
@@ -84,7 +83,7 @@ def make_course_settings(course, user, include_category_map=True):
|
||||
'allow_anonymous': course.allow_anonymous,
|
||||
'allow_anonymous_to_peers': course.allow_anonymous_to_peers,
|
||||
'groups': [
|
||||
{"id": str(group_id), "name": group_name} for group_id, group_name in six.iteritems(group_names_by_id)
|
||||
{"id": str(group_id), "name": group_name} for group_id, group_name in group_names_by_id.items()
|
||||
]
|
||||
}
|
||||
if include_category_map:
|
||||
@@ -115,7 +114,7 @@ def get_threads(request, course, user_info, discussion_id=None, per_page=THREADS
|
||||
'per_page': per_page,
|
||||
'sort_key': 'activity',
|
||||
'text': '',
|
||||
'course_id': six.text_type(course.id),
|
||||
'course_id': str(course.id),
|
||||
'user_id': request.user.id,
|
||||
'context': ThreadContext.COURSE,
|
||||
'group_id': get_group_id_for_comments_service(request, course.id, discussion_id), # may raise ValueError
|
||||
@@ -290,7 +289,7 @@ def forum_form_discussion(request, course_key):
|
||||
'corrected_text': query_params['corrected_text'],
|
||||
})
|
||||
else:
|
||||
course_id = six.text_type(course.id)
|
||||
course_id = str(course.id)
|
||||
tab_view = CourseTabView()
|
||||
return tab_view.get(request, course_id, 'discussion')
|
||||
|
||||
@@ -344,7 +343,7 @@ def single_thread(request, course_key, discussion_id, thread_id):
|
||||
'annotated_content_info': annotated_content_info,
|
||||
})
|
||||
else:
|
||||
course_id = six.text_type(course.id)
|
||||
course_id = str(course.id)
|
||||
tab_view = CourseTabView()
|
||||
return tab_view.get(request, course_id, 'discussion', discussion_id=discussion_id, thread_id=thread_id)
|
||||
|
||||
@@ -475,7 +474,7 @@ def _create_discussion_board_context(request, base_context, thread=None):
|
||||
if "pinned" not in thread:
|
||||
thread["pinned"] = False
|
||||
thread_pages = 1
|
||||
root_url = reverse('forum_form_discussion', args=[six.text_type(course.id)])
|
||||
root_url = reverse('forum_form_discussion', args=[str(course.id)])
|
||||
else:
|
||||
threads, query_params = get_threads(request, course, user_info) # This might process a search query
|
||||
thread_pages = query_params['num_pages']
|
||||
@@ -608,7 +607,7 @@ def user_profile(request, course_key, user_id):
|
||||
# 'user_profile' page
|
||||
context['load_mathjax'] = False
|
||||
|
||||
return tab_view.get(request, six.text_type(course_key), 'discussion', profile_page_context=context)
|
||||
return tab_view.get(request, str(course_key), 'discussion', profile_page_context=context)
|
||||
except User.DoesNotExist:
|
||||
raise Http404 # lint-amnesty, pylint: disable=raise-missing-from
|
||||
except ValueError:
|
||||
@@ -768,7 +767,7 @@ class DiscussionBoardFragmentView(EdxFragmentView):
|
||||
return fragment
|
||||
except TeamDiscussionHiddenFromUserException:
|
||||
log.warning(
|
||||
u'User with id={user_id} tried to view private discussion with id={discussion_id}'.format(
|
||||
'User with id={user_id} tried to view private discussion with id={discussion_id}'.format(
|
||||
user_id=request.user.id,
|
||||
discussion_id=discussion_id
|
||||
)
|
||||
@@ -938,7 +937,7 @@ def course_discussions_settings_handler(request, course_key_string):
|
||||
)
|
||||
|
||||
if not settings_to_change:
|
||||
return JsonResponse({"error": six.text_type("Bad Request")}, 400)
|
||||
return JsonResponse({"error": "Bad Request"}, 400)
|
||||
|
||||
try:
|
||||
if settings_to_change:
|
||||
@@ -946,7 +945,7 @@ def course_discussions_settings_handler(request, course_key_string):
|
||||
|
||||
except ValueError as err:
|
||||
# Note: error message not translated because it is not exposed to the user (UI prevents this state).
|
||||
return JsonResponse({"error": six.text_type(err)}, 400)
|
||||
return JsonResponse({"error": str(err)}, 400)
|
||||
|
||||
divided_course_wide_discussions, divided_inline_discussions = get_divided_discussions(
|
||||
course, discussion_settings
|
||||
|
||||
Reference in New Issue
Block a user