Merge pull request #20355 from edx/bom/discussions-colocation

Discussions consolidation
This commit is contained in:
Nimisha Asthagiri
2019-05-02 08:08:03 -04:00
committed by GitHub
160 changed files with 558 additions and 435 deletions

2
.github/CODEOWNERS vendored
View File

@@ -22,9 +22,7 @@ common/lib/xmodule/xmodule/capa_module.py @edx/platform-core-extensions
common/lib/xmodule/xmodule/html_module.py @edx/platform-core-extensions
common/lib/xmodule/xmodule/video_module @edx/platform-core-extensions
lms/djangoapps/discussion/ @edx/platform-core-extensions
lms/djangoapps/discussion_api/ @edx/platform-core-extensions
lms/djangoapps/edxnotes @edx/platform-core-extensions
lms/djangoapps/notifier_api/ @edx/platform-core-extensions
# Analytics
common/djangoapps/track/ @edx/edx-data-engineering

2
.gitignore vendored
View File

@@ -132,7 +132,7 @@ build
/src/
\#*\#
.env/
lms/lib/comment_client/python
openedx/core/djangoapps/discussion_common/comment_client/python
autodeploy.properties
.ws_migrations_complete
dist

View File

@@ -2,7 +2,7 @@
Script for importing courseware from XML format
"""
from django.core.management.base import BaseCommand
from django_comment_common.utils import are_permissions_roles_seeded, seed_permissions_roles
from openedx.core.djangoapps.discussion_common.utils import are_permissions_roles_seeded, seed_permissions_roles
from xmodule.contentstore.django import contentstore
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore

View File

@@ -9,7 +9,7 @@ import tempfile
from django.core.management import call_command
from path import Path as path
from django_comment_common.utils import are_permissions_roles_seeded
from openedx.core.djangoapps.discussion_common.utils import are_permissions_roles_seeded
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase

View File

@@ -35,7 +35,7 @@ from contentstore.views.component import ADVANCED_COMPONENT_TYPES
from contentstore.config import waffle
from course_action_state.managers import CourseActionStateItemNotFoundError
from course_action_state.models import CourseRerunState, CourseRerunUIStateManager
from django_comment_common.utils import are_permissions_roles_seeded
from openedx.core.djangoapps.discussion_common.utils import are_permissions_roles_seeded
from openedx.core.lib.tempdir import mkdtemp_clean
from student import auth
from student.models import CourseEnrollment

View File

@@ -15,8 +15,8 @@ from opaque_keys.edx.locator import LibraryLocator
from pytz import UTC
from six import text_type
from django_comment_common.models import assign_default_role
from django_comment_common.utils import seed_permissions_roles
from openedx.core.djangoapps.discussion_common.models import assign_default_role
from openedx.core.djangoapps.discussion_common.utils import seed_permissions_roles
from openedx.core.djangoapps.site_configuration.models import SiteConfiguration
from openedx.features.content_type_gating.models import ContentTypeGatingConfig
from openedx.features.content_type_gating.partitions import CONTENT_TYPE_GATING_SCHEME

View File

@@ -1055,8 +1055,8 @@ INSTALLED_APPS = [
# Ability to detect and special-case crawler behavior
'openedx.core.djangoapps.crawlers',
# comment common
'django_comment_common',
# Discussion
'openedx.core.djangoapps.discussion_common',
# for course creator table
'django.contrib.admin',

View File

@@ -51,9 +51,7 @@ from slumber.exceptions import HttpClientError, HttpServerError
from user_util import user_util
from edx_django_utils.cache import RequestCache
import lms.lib.comment_client as cc
from student.signals import UNENROLL_DONE, ENROLL_STATUS_CHANGE, ENROLLMENT_TRACK_UPDATED
from lms.djangoapps.certificates.models import GeneratedCertificate
from course_modes.models import CourseMode, get_cosmetic_verified_display_price
from courseware.models import (
CourseDynamicUpgradeDeadlineConfiguration,
@@ -62,7 +60,9 @@ from courseware.models import (
)
from enrollment.api import _default_course_mode
from lms.djangoapps.certificates.models import GeneratedCertificate
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
import openedx.core.djangoapps.discussion_common.comment_client as cc
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.djangoapps.xmodule_django.models import NoneToEmptyManager
from openedx.core.djangolib.model_mixins import DeletableByUserValue

View File

@@ -1,7 +1,7 @@
"""
Helpers for student roles
"""
from django_comment_common.models import (
from openedx.core.djangoapps.discussion_common.models import (
FORUM_ROLE_ADMINISTRATOR,
FORUM_ROLE_MODERATOR,
FORUM_ROLE_GROUP_MODERATOR,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -10,7 +10,6 @@ LMS and Studio.
common/djangoapps/course_action_state/modules
common/djangoapps/course_modes/modules
common/djangoapps/database_fixups/modules
common/djangoapps/django_comment_common/modules
common/djangoapps/edxmako/modules
common/djangoapps/enrollment/modules
common/djangoapps/entitlements/modules

View File

@@ -8,9 +8,9 @@ from courseware.courses import get_course_by_id
from django.db import migrations
from django.http import Http404
from django_comment_common.models import FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, \
from openedx.core.djangoapps.discussion_common.models import FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, \
FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_STUDENT
from django_comment_common.utils import STUDENT_ROLE_PERMISSIONS, MODERATOR_ROLE_PERMISSIONS, \
from openedx.core.djangoapps.discussion_common.utils import STUDENT_ROLE_PERMISSIONS, MODERATOR_ROLE_PERMISSIONS, \
ADMINISTRATOR_ROLE_PERMISSIONS
log = logging.getLogger("edx.ccx")
@@ -26,8 +26,8 @@ def seed_forum_roles_for_existing_ccx(apps, schema_editor):
"""
CustomCourseForEdX = apps.get_model("ccx", "CustomCourseForEdX")
Role = apps.get_model("django_comment_common", "Role")
Permission = apps.get_model("django_comment_common", "Permission")
Role = apps.get_model("discussion_common", "Role")
Permission = apps.get_model("discussion_common", "Permission")
db_alias = schema_editor.connection.alias
# This will need to be changed if ccx gets moved out of the default db for some reason.
if db_alias != 'default':
@@ -76,7 +76,7 @@ class Migration(migrations.Migration):
dependencies = [
('ccx', '0003_add_master_course_staff_in_ccx'),
('django_comment_common', '0002_forumsconfig'),
('discussion_common', '0002_forumsconfig'),
]
operations = [

View File

@@ -23,9 +23,6 @@ from courseware.tabs import get_course_tab_list
from courseware.tests.factories import StudentModuleFactory
from courseware.tests.helpers import LoginEnrollmentTestCase
from courseware.testutils import FieldOverrideTestMixin
from django_comment_client.utils import has_forum_access
from django_comment_common.models import FORUM_ROLE_ADMINISTRATOR
from django_comment_common.utils import are_permissions_roles_seeded
from edx_django_utils.cache import RequestCache
from edxmako.shortcuts import render_to_response
from lms.djangoapps.ccx.models import CustomCourseForEdX
@@ -34,9 +31,12 @@ from lms.djangoapps.ccx.tests.factories import CcxFactory
from lms.djangoapps.ccx.tests.utils import CcxTestCase, flatten
from lms.djangoapps.ccx.utils import ccx_course, is_email
from lms.djangoapps.ccx.views import get_date
from lms.djangoapps.discussion.django_comment_client.utils import has_forum_access
from lms.djangoapps.grades.tasks import compute_all_grades_for_course
from lms.djangoapps.instructor.access import allow_access, list_with_level
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.discussion_common.models import FORUM_ROLE_ADMINISTRATOR
from openedx.core.djangoapps.discussion_common.utils import are_permissions_roles_seeded
from student.models import CourseEnrollment, CourseEnrollmentAllowed
from student.roles import CourseCcxCoachRole, CourseInstructorRole, CourseStaffRole
from student.tests.factories import AdminFactory, CourseEnrollmentFactory, UserFactory

View File

@@ -25,9 +25,6 @@ from opaque_keys.edx.keys import CourseKey
from courseware.access import has_access
from courseware.courses import get_course_by_id
from lms.djangoapps.courseware.field_overrides import disable_overrides
from django_comment_common.models import FORUM_ROLE_ADMINISTRATOR, assign_role
from django_comment_common.utils import seed_permissions_roles
from edxmako.shortcuts import render_to_response
from lms.djangoapps.ccx.models import CustomCourseForEdX
from lms.djangoapps.ccx.overrides import (
@@ -48,9 +45,12 @@ from lms.djangoapps.ccx.utils import (
get_enrollment_action_and_identifiers,
parse_date,
)
from lms.djangoapps.courseware.field_overrides import disable_overrides
from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory
from lms.djangoapps.instructor.enrollment import enroll_email, get_email_params
from lms.djangoapps.instructor.views.gradebook_api import get_grade_book_page
from openedx.core.djangoapps.discussion_common.models import FORUM_ROLE_ADMINISTRATOR, assign_role
from openedx.core.djangoapps.discussion_common.utils import seed_permissions_roles
from student.models import CourseEnrollment
from student.roles import CourseCcxCoachRole
from xmodule.modulestore.django import SignalHandler

View File

@@ -213,7 +213,10 @@ class TestTemplates(TestDiscussionXBlock):
Test for has_permission method.
"""
permission_canary = object()
with mock.patch('django_comment_client.permissions.has_permission', return_value=permission_canary) as has_perm:
with mock.patch(
'lms.djangoapps.discussion.django_comment_client.permissions.has_permission',
return_value=permission_canary,
) as has_perm:
actual_permission = self.block.has_permission("test_permission")
self.assertEqual(actual_permission, permission_canary)
has_perm.assert_called_once_with(self.django_user_canary, 'test_permission', 'test_course')

View File

@@ -10,7 +10,7 @@ from courseware.access import has_access
from courseware.tests.factories import BetaTesterFactory
from lms.djangoapps.ccx.tests.test_overrides import inject_field_overrides
from lms.djangoapps.courseware.field_overrides import OverrideFieldData, OverrideModulestoreFieldData
from lms.djangoapps.django_comment_client.utils import get_accessible_discussion_xblocks
from lms.djangoapps.discussion.django_comment_client.utils import get_accessible_discussion_xblocks
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory

View File

@@ -8,13 +8,8 @@ Direction: Move and Extract
===========================
Discussions related functionality is scattered across a number of places and should be better consolidated. Today we have:
* ``common/djangoapps/django_comment_common``
* ``lms/djangoapps/discussion``
* ``lms/djangoapps/discussion_api``
* ``lms/djangoapps/django_comment_client``
* ``lms/djangoapps/notification_prefs``
* ``lms/djangoapps/notifier_api``
* ``lms/lib/comment_client``
* ``openedx/core/djangoapps/discussion_common``
* ``openedx/core/lib/xblock_builtin/xblock_discussion``
Ideally, what we want in the long term is for all of this extracted into a new repository that holds the code for both the inline discussion XBlock as well as all the Django apps. Use of the notifier API should be replaced with edx-ace.

View File

@@ -12,7 +12,7 @@ from openedx.core.djangoapps.plugins.constants import ProjectType, SettingsType,
class DiscussionConfig(AppConfig):
"""
Application Configuration for Grades.
Application Configuration for Discussion.
"""
name = u'lms.djangoapps.discussion'

View File

@@ -0,0 +1,3 @@
# pylint: disable=missing-docstring,relative-import
# This import registers the ForumThreadViewedEventTransformer
import event_transformers

View File

@@ -1,3 +1,4 @@
# pylint: skip-file
"""
Transformers for Discussion-related events.
"""
@@ -8,9 +9,9 @@ from eventtracking.processors.exceptions import EventEmissionExit
from opaque_keys import InvalidKeyError
from opaque_keys.edx.locator import CourseLocator
from django_comment_client.base.views import add_truncated_title_to_event_data
from django_comment_client.permissions import get_team
from django_comment_client.utils import get_cached_discussion_id_map_by_course_id
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 track.transformers import EventTransformer, EventTransformerRegistry
from track.views.segmentio import (
BI_SCREEN_VIEWED_EVENT_NAME,

View File

@@ -1,3 +1,4 @@
# pylint: skip-file
# -*- coding: utf-8 -*-
"""Tests for django comment client views."""
import json
@@ -18,25 +19,27 @@ from six import text_type
from common.test.utils import MockSignalHandlerMixin, disable_signal
from course_modes.models import CourseMode
from course_modes.tests.factories import CourseModeFactory
from django_comment_client.base import views
from django_comment_client.tests.group_id import (
from lms.djangoapps.discussion.django_comment_client.base import views
from lms.djangoapps.discussion.django_comment_client.tests.group_id import (
CohortedTopicGroupIdTestMixin,
GroupIdAssertionMixin,
NonCohortedTopicGroupIdTestMixin
)
from django_comment_client.tests.unicode import UnicodeTestMixin
from django_comment_client.tests.utils import CohortedTestCase, ForumsEnableMixin
from django_comment_common.models import (
from lms.djangoapps.discussion.django_comment_client.tests.unicode import UnicodeTestMixin
from lms.djangoapps.discussion.django_comment_client.tests.utils import CohortedTestCase, ForumsEnableMixin
from openedx.core.djangoapps.discussion_common.comment_client import Thread
from openedx.core.djangoapps.discussion_common.models import (
assign_role,
CourseDiscussionSettings,
FORUM_ROLE_STUDENT,
Role
)
from django_comment_common.utils import ThreadContext, seed_permissions_roles, set_course_discussion_settings
from lms.djangoapps.teams.tests.factories import CourseTeamFactory, CourseTeamMembershipFactory
from lms.lib.comment_client import Thread
from openedx.core.djangoapps.course_groups.cohorts import set_course_cohorted
from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory
from openedx.core.djangoapps.discussion_common.utils import (
ThreadContext, seed_permissions_roles, set_course_discussion_settings
)
from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES
from student.roles import CourseStaffRole, UserBasedRole
from student.tests.factories import CourseAccessRoleFactory, CourseEnrollmentFactory, UserFactory
@@ -72,7 +75,7 @@ class MockRequestSetupMixin(object):
mock_request.return_value = self._create_response_mock(data)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
class CreateThreadGroupIdTestCase(
MockRequestSetupMixin,
CohortedTestCase,
@@ -107,7 +110,7 @@ class CreateThreadGroupIdTestCase(
self._assert_json_response_contains_group_info(response)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
@disable_signal(views, 'thread_edited')
@disable_signal(views, 'thread_voted')
@disable_signal(views, 'thread_deleted')
@@ -365,7 +368,7 @@ class ViewsTestCaseMixin(object):
@ddt.ddt
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
@disable_signal(views, 'thread_created')
@disable_signal(views, 'thread_edited')
class ViewsQueryCountTestCase(
@@ -418,7 +421,7 @@ class ViewsQueryCountTestCase(
@ddt.ddt
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
class ViewsTestCase(
ForumsEnableMixin,
UrlResetMixin,
@@ -641,7 +644,10 @@ class ViewsTestCase(
with self.assert_discussion_signals('thread_edited'):
self.update_thread_helper(mock_request)
@patch('django_comment_client.utils.get_discussion_categories_ids', return_value=["test_commentable"])
@patch(
'lms.djangoapps.discussion.django_comment_client.utils.get_discussion_categories_ids',
return_value=["test_commentable"],
)
def test_update_thread_wrong_commentable_id(self, mock_get_discussion_id_map, mock_request):
self._test_request_error(
"update_thread",
@@ -1062,7 +1068,7 @@ class ViewsTestCase(
self.assertEqual(response.status_code, 200)
@patch("lms.lib.comment_client.utils.requests.request", autospec=True)
@patch("openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request", autospec=True)
@disable_signal(views, 'comment_endorsed')
class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStoreTestCase, MockRequestSetupMixin):
@@ -1191,7 +1197,7 @@ class CreateThreadUnicodeTestCase(
cls.student = UserFactory.create()
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request,):
"""
Test to make sure unicode data in a thread doesn't break it.
@@ -1233,8 +1239,11 @@ class UpdateThreadUnicodeTestCase(
cls.student = UserFactory.create()
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
@patch('django_comment_client.utils.get_discussion_categories_ids', return_value=["test_commentable"])
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch(
'lms.djangoapps.discussion.django_comment_client.utils.get_discussion_categories_ids',
return_value=["test_commentable"],
)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request, mock_get_discussion_id_map):
self._set_mock_request_data(mock_request, {
"user_id": str(self.student.id),
@@ -1275,7 +1284,7 @@ class CreateCommentUnicodeTestCase(
cls.student = UserFactory.create()
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request):
commentable_id = "non_team_dummy_id"
self._set_mock_request_data(mock_request, {
@@ -1322,7 +1331,7 @@ class UpdateCommentUnicodeTestCase(
cls.student = UserFactory.create()
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request):
self._set_mock_request_data(mock_request, {
"user_id": str(self.student.id),
@@ -1362,7 +1371,7 @@ class CreateSubCommentUnicodeTestCase(
cls.student = UserFactory.create()
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request):
"""
Create a comment with unicode in it.
@@ -1390,7 +1399,7 @@ class CreateSubCommentUnicodeTestCase(
@ddt.ddt
@patch("lms.lib.comment_client.utils.requests.request", autospec=True)
@patch("openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request", autospec=True)
@disable_signal(views, 'thread_voted')
@disable_signal(views, 'thread_edited')
@disable_signal(views, 'comment_created')
@@ -1757,7 +1766,7 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
CourseAccessRoleFactory(course_id=cls.course.id, user=cls.student, role='Wizard')
@patch('eventtracking.tracker.emit')
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def test_thread_created_event(self, __, mock_emit):
request = RequestFactory().post(
"dummy_url", {
@@ -1786,7 +1795,7 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
self.assertEquals(event['anonymous_to_peers'], False)
@patch('eventtracking.tracker.emit')
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def test_response_event(self, mock_request, mock_emit):
"""
Check to make sure an event is fired when a user responds to a thread.
@@ -1812,7 +1821,7 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
self.assertEqual(event['options']['followed'], True)
@patch('eventtracking.tracker.emit')
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def test_comment_event(self, mock_request, mock_emit):
"""
Ensure an event is fired when someone comments on a response.
@@ -1839,7 +1848,7 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
self.assertEqual(event['options']['followed'], False)
@patch('eventtracking.tracker.emit')
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
@ddt.data((
'create_thread',
'edx.forum.thread.created', {
@@ -1891,7 +1900,7 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
)
@ddt.unpack
@patch('eventtracking.tracker.emit')
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def test_thread_voted_event(self, view_name, obj_id_name, obj_type, mock_request, mock_emit):
undo = view_name.startswith('undo')
@@ -1953,7 +1962,7 @@ class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRe
request.view_name = "users"
return views.users(request, course_id=text_type(course_id))
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def test_finds_exact_match(self, mock_request):
self.set_post_counts(mock_request)
response = self.make_request(username="other")
@@ -1963,7 +1972,7 @@ class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRe
[{"id": self.other_user.id, "username": self.other_user.username}]
)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def test_finds_no_match(self, mock_request):
self.set_post_counts(mock_request)
response = self.make_request(username="othor")
@@ -2000,7 +2009,7 @@ class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRe
self.assertIn("errors", content)
self.assertNotIn("users", content)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def test_requires_matched_user_has_forum_content(self, mock_request):
self.set_post_counts(mock_request, 0, 0)
response = self.make_request(username="other")

View File

@@ -3,7 +3,7 @@ Base urls for the django_comment_client.
"""
from django.conf.urls import url
from django_comment_client.base import views
from lms.djangoapps.discussion.django_comment_client.base import views
urlpatterns = [
url(r'^upload$', views.upload, name='upload'),

View File

@@ -1,3 +1,4 @@
# pylint: disable=missing-docstring,unused-argument
"""Views for discussion forums."""
from __future__ import print_function
@@ -20,12 +21,14 @@ from django.views.decorators.http import require_GET, require_POST
from opaque_keys.edx.keys import CourseKey
from six import text_type
import django_comment_client.settings as cc_settings
import lms.lib.comment_client as cc
from courseware.access import has_access
from courseware.courses import get_course_by_id, get_course_overview_with_access, get_course_with_access
from django_comment_client.permissions import check_permissions_by_view, get_team, has_permission
from django_comment_client.utils import (
from lms.djangoapps.courseware.exceptions import CourseAccessRedirect
from lms.djangoapps.discussion.django_comment_client.permissions import (
check_permissions_by_view, get_team, has_permission,
)
import lms.djangoapps.discussion.django_comment_client.settings as cc_settings
from lms.djangoapps.discussion.django_comment_client.utils import (
JsonError,
JsonResponse,
add_courseware_context,
@@ -38,7 +41,8 @@ from django_comment_client.utils import (
is_comment_too_deep,
prepare_content
)
from django_comment_common.signals import (
import openedx.core.djangoapps.discussion_common.comment_client as cc
from openedx.core.djangoapps.discussion_common.signals import (
comment_created,
comment_deleted,
comment_edited,
@@ -51,9 +55,8 @@ from django_comment_common.signals import (
thread_followed,
thread_unfollowed,
)
from django_comment_common.utils import ThreadContext
from openedx.core.djangoapps.discussion_common.utils import ThreadContext
import eventtracking
from lms.djangoapps.courseware.exceptions import CourseAccessRedirect
from util.file import store_uploaded_file
log = logging.getLogger(__name__)
@@ -96,10 +99,7 @@ def track_created_event(request, event_name, course, obj, data):
"""
Send analytics event for a newly created thread, response or comment.
"""
if len(obj.body) > TRACKING_MAX_FORUM_BODY:
data['truncated'] = True
else:
data['truncated'] = False
data['truncated'] = len(obj.body) > TRACKING_MAX_FORUM_BODY
data['body'] = obj.body[:TRACKING_MAX_FORUM_BODY]
track_forum_event(request, event_name, course, obj, data)

View File

@@ -1,10 +1,11 @@
# pylint: disable=missing-docstring
import json
import logging
from six import text_type
from django_comment_client.utils import JsonError
from lms.lib.comment_client import CommentClientRequestError
from lms.djangoapps.discussion.django_comment_client.utils import JsonError
from openedx.core.djangoapps.discussion_common.comment_client import CommentClientRequestError
log = logging.getLogger(__name__)

View File

@@ -0,0 +1 @@
# This file is intentionally blank. It has been moved to openedx/core/djangoapps/discussion_common

View File

@@ -1,3 +1,4 @@
# pylint: disable=missing-docstring
"""
Module for checking permissions with the comment_client backend
"""
@@ -8,10 +9,12 @@ from types import NoneType
from edx_django_utils.cache import DEFAULT_REQUEST_CACHE
from opaque_keys.edx.keys import CourseKey
from django_comment_common.models import CourseDiscussionSettings, all_permissions_for_user_in_course
from django_comment_common.utils import get_course_discussion_settings
from lms.djangoapps.teams.models import CourseTeam
from lms.lib.comment_client import Thread
from openedx.core.djangoapps.discussion_common.comment_client import Thread
from openedx.core.djangoapps.discussion_common.models import (
CourseDiscussionSettings, all_permissions_for_user_in_course,
)
from openedx.core.djangoapps.discussion_common.utils import get_course_discussion_settings
from openedx.core.lib.cache_utils import request_cached

View File

@@ -1,3 +1,4 @@
# pylint: disable=missing-docstring
from django.conf import settings
MAX_COMMENT_DEPTH = None
@@ -7,4 +8,7 @@ ALLOWED_UPLOAD_FILE_TYPES = ('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.tiff')
if hasattr(settings, 'DISCUSSION_SETTINGS'):
MAX_COMMENT_DEPTH = settings.DISCUSSION_SETTINGS.get('MAX_COMMENT_DEPTH')
MAX_UPLOAD_FILE_SIZE = settings.DISCUSSION_SETTINGS.get('MAX_UPLOAD_FILE_SIZE') or MAX_UPLOAD_FILE_SIZE
ALLOWED_UPLOAD_FILE_TYPES = settings.DISCUSSION_SETTINGS.get('ALLOWED_UPLOAD_FILE_TYPES') or ALLOWED_UPLOAD_FILE_TYPES
ALLOWED_UPLOAD_FILE_TYPES = (
settings.DISCUSSION_SETTINGS.get('ALLOWED_UPLOAD_FILE_TYPES') or
ALLOWED_UPLOAD_FILE_TYPES
)

View File

@@ -1,6 +1,7 @@
# pylint: disable=missing-docstring
from factory.django import DjangoModelFactory
from django_comment_common.models import Permission, Role
from openedx.core.djangoapps.discussion_common.models import Permission, Role
class RoleFactory(DjangoModelFactory):

View File

@@ -1,11 +1,12 @@
# pylint: disable=missing-docstring
import json
import re
from course_modes.models import CourseMode
from course_modes.tests.factories import CourseModeFactory
from django_comment_common.models import CourseDiscussionSettings
from django_comment_common.utils import set_course_discussion_settings
from lms.djangoapps.teams.tests.factories import CourseTeamFactory
from openedx.core.djangoapps.discussion_common.models import CourseDiscussionSettings
from openedx.core.djangoapps.discussion_common.utils import set_course_discussion_settings
class GroupIdAssertionMixin(object):

View File

@@ -1,3 +1,4 @@
# pylint: skip-file
import json
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from logging import getLogger

View File

@@ -1,3 +1,4 @@
# pylint: disable=missing-docstring
import json
import threading
import unittest
@@ -5,7 +6,7 @@ import urllib2
import pytest
from django_comment_client.tests.mock_cs_server.mock_cs_server import MockCommentServiceServer
from lms.djangoapps.discussion.django_comment_client.tests.mock_cs_server.mock_cs_server import MockCommentServiceServer
class MockCommentServiceServerTest(unittest.TestCase):

View File

@@ -1,11 +1,12 @@
# pylint: disable=missing-docstring
import json
import django.http
from django.test import TestCase
from six import text_type
import django_comment_client.middleware as middleware
import lms.lib.comment_client
import lms.djangoapps.discussion.django_comment_client.middleware as middleware
import openedx.core.djangoapps.discussion_common.comment_client as comment_client
class AjaxExceptionTestCase(TestCase):
@@ -15,9 +16,9 @@ class AjaxExceptionTestCase(TestCase):
self.a = middleware.AjaxExceptionMiddleware()
self.request1 = django.http.HttpRequest()
self.request0 = django.http.HttpRequest()
self.exception1 = lms.lib.comment_client.CommentClientRequestError('{}', 401)
self.exception2 = lms.lib.comment_client.CommentClientRequestError('Foo!', 404)
self.exception0 = lms.lib.comment_client.CommentClient500Error("Holy crap the server broke!")
self.exception1 = comment_client.CommentClientRequestError('{}', 401)
self.exception2 = comment_client.CommentClientRequestError('Foo!', 404)
self.exception0 = comment_client.CommentClient500Error("Holy crap the server broke!")
self.request1.META['HTTP_X_REQUESTED_WITH'] = "XMLHttpRequest"
self.request0.META['HTTP_X_REQUESTED_WITH'] = "SHADOWFAX"

View File

@@ -4,7 +4,7 @@ Tests for the django comment client integration models
from django.test.testcases import TestCase
from opaque_keys.edx.keys import CourseKey
import django_comment_common.models as models
import openedx.core.djangoapps.discussion_common.models as models
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_MODULESTORE, ModuleStoreTestCase
from xmodule.modulestore.tests.factories import ToyCourseFactory

View File

@@ -1,3 +1,4 @@
# pylint: skip-file
# -*- coding: utf-8 -*-
import datetime
import json
@@ -12,31 +13,31 @@ from mock import Mock, patch
from pytz import UTC
from six import text_type
import django_comment_client.utils as utils
from course_modes.models import CourseMode
from course_modes.tests.factories import CourseModeFactory
from courseware.tabs import get_course_tab_list
from courseware.tests.factories import InstructorFactory
from django_comment_client.constants import TYPE_ENTRY, TYPE_SUBCATEGORY
from django_comment_client.tests.factories import RoleFactory
from django_comment_client.tests.unicode import UnicodeTestMixin
from django_comment_client.tests.utils import config_course_discussions, topic_name_to_id
from django_comment_common.models import (
from lms.djangoapps.discussion.django_comment_client.constants import TYPE_ENTRY, TYPE_SUBCATEGORY
from lms.djangoapps.discussion.django_comment_client.tests.factories import RoleFactory
from lms.djangoapps.discussion.django_comment_client.tests.unicode import UnicodeTestMixin
from lms.djangoapps.discussion.django_comment_client.tests.utils import config_course_discussions, topic_name_to_id
import lms.djangoapps.discussion.django_comment_client.utils as utils
from lms.djangoapps.teams.tests.factories import CourseTeamFactory
from openedx.core.djangoapps.course_groups import cohorts
from openedx.core.djangoapps.course_groups.cohorts import set_course_cohorted
from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory, config_course_cohorts
from openedx.core.djangoapps.discussion_common.comment_client.utils import CommentClientMaintenanceError, perform_request
from openedx.core.djangoapps.discussion_common.models import (
CourseDiscussionSettings,
ForumsConfig,
assign_role,
DiscussionsIdMapping,
)
from django_comment_common.utils import (
from openedx.core.djangoapps.discussion_common.utils import (
get_course_discussion_settings,
seed_permissions_roles,
set_course_discussion_settings
)
from lms.djangoapps.teams.tests.factories import CourseTeamFactory
from lms.lib.comment_client.utils import CommentClientMaintenanceError, perform_request
from openedx.core.djangoapps.course_groups import cohorts
from openedx.core.djangoapps.course_groups.cohorts import set_course_cohorted
from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory, config_course_cohorts
from openedx.core.djangoapps.util.testing import ContentGroupTestCase
from student.roles import CourseStaffRole
from student.tests.factories import AdminFactory, CourseEnrollmentFactory, UserFactory
@@ -1592,7 +1593,9 @@ class PermissionsTestCase(ModuleStoreTestCase):
user = mock.Mock()
user.id = 1
with mock.patch('django_comment_client.utils.check_permissions_by_view') as check_perm:
with mock.patch(
'lms.djangoapps.discussion.django_comment_client.utils.check_permissions_by_view'
) as check_perm:
check_perm.return_value = True
self.assertEqual(utils.get_ability(None, content, user), {
'editable': True,
@@ -1620,7 +1623,9 @@ class PermissionsTestCase(ModuleStoreTestCase):
"""
content = {'user_id': '1', 'type': 'thread'}
with mock.patch('django_comment_client.utils.check_permissions_by_view') as check_perm:
with mock.patch(
'lms.djangoapps.discussion.django_comment_client.utils.check_permissions_by_view'
) as check_perm:
# check_permissions_by_view returns false because user is not enrolled in the course.
check_perm.return_value = False
global_staff = UserFactory(username='global_staff', email='global_staff@edx.org', is_staff=True)
@@ -1721,7 +1726,10 @@ class GroupModeratorPermissionsTestCase(ModuleStoreTestCase):
# Give group moderator permissions to group_moderator
assign_role(self.course.id, self.group_moderator, 'Group Moderator')
@mock.patch('django_comment_client.permissions._check_condition', side_effect=_check_condition)
@mock.patch(
'lms.djangoapps.discussion.django_comment_client.permissions._check_condition',
side_effect=_check_condition,
)
def test_not_divided(self, check_condition_function):
"""
Group moderator should not have moderator permissions if the discussions are not divided.
@@ -1754,7 +1762,10 @@ class GroupModeratorPermissionsTestCase(ModuleStoreTestCase):
'can_report': True
})
@mock.patch('django_comment_client.permissions._check_condition', side_effect=_check_condition)
@mock.patch(
'lms.djangoapps.discussion.django_comment_client.permissions._check_condition',
side_effect=_check_condition,
)
def test_divided_within_group(self, check_condition_function):
"""
Group moderator should have moderator permissions within their group if the discussions are divided.
@@ -1783,7 +1794,10 @@ class GroupModeratorPermissionsTestCase(ModuleStoreTestCase):
'can_report': True
})
@mock.patch('django_comment_client.permissions._check_condition', side_effect=_check_condition)
@mock.patch(
'lms.djangoapps.discussion.django_comment_client.permissions._check_condition',
side_effect=_check_condition,
)
def test_divided_outside_group(self, check_condition_function):
"""
Group moderator should not have moderator permissions outside of their group.

View File

@@ -1,3 +1,4 @@
# pylint: disable=missing-docstring
# coding=utf-8
@@ -15,7 +16,9 @@ class UnicodeTestMixin(object):
self._test_unicode_data(u"𝕋𝕙𝕚𝕤 𝕡𝕠𝕤𝕥 𝕔𝕠𝕟𝕥𝕒𝕚𝕟𝕤 𝕔𝕙𝕒𝕣𝕒𝕔𝕥𝕖𝕣𝕤 𝕠𝕦𝕥𝕤𝕚𝕕𝕖 𝕥𝕙𝕖 𝔹𝕄")
def test_special_chars(self):
self._test_unicode_data(u"\" This , post > contains < delimiter ] and [ other } special { characters ; that & may ' break things")
self._test_unicode_data(
u"\" 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}")

View File

@@ -3,8 +3,10 @@ Utilities for tests within the django_comment_client module.
"""
from mock import patch
from django_comment_common.models import ForumsConfig, Role
from django_comment_common.utils import CourseDiscussionSettings, seed_permissions_roles, set_course_discussion_settings
from openedx.core.djangoapps.discussion_common.models import ForumsConfig, Role
from openedx.core.djangoapps.discussion_common.utils import (
CourseDiscussionSettings, seed_permissions_roles, set_course_discussion_settings,
)
from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory
from student.tests.factories import CourseEnrollmentFactory, UserFactory
from util.testing import UrlResetMixin

View File

@@ -4,5 +4,5 @@ Urls for the django_comment_client.
from django.conf.urls import include, url
urlpatterns = [
url(r'', include('django_comment_client.base.urls')),
url(r'', include('lms.djangoapps.discussion.django_comment_client.base.urls')),
]

View File

@@ -1,3 +1,4 @@
# pylint: skip-file
import json
import logging
from collections import defaultdict
@@ -15,17 +16,19 @@ from six import text_type
from courseware import courses
from courseware.access import has_access
from django_comment_client.constants import TYPE_ENTRY, TYPE_SUBCATEGORY
from django_comment_client.permissions import check_permissions_by_view, get_team, has_permission
from django_comment_client.settings import MAX_COMMENT_DEPTH
from django_comment_common.models import (
from lms.djangoapps.discussion.django_comment_client.constants import TYPE_ENTRY, TYPE_SUBCATEGORY
from lms.djangoapps.discussion.django_comment_client.permissions import (
check_permissions_by_view, get_team, has_permission,
)
from lms.djangoapps.discussion.django_comment_client.settings import MAX_COMMENT_DEPTH
from openedx.core.djangoapps.discussion_common.models import (
FORUM_ROLE_STUDENT,
FORUM_ROLE_COMMUNITY_TA,
CourseDiscussionSettings,
DiscussionsIdMapping,
Role
)
from django_comment_common.utils import get_course_discussion_settings
from openedx.core.djangoapps.discussion_common.utils import get_course_discussion_settings
from openedx.core.djangoapps.course_groups.cohorts import get_cohort_id, get_cohort_names, is_course_cohorted
from openedx.core.lib.cache_utils import request_cached
from student.models import get_user_by_username_or_email
@@ -271,7 +274,9 @@ def _filter_unstarted_categories(category_map, course):
if key != "start_date":
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"])
log.debug(
u"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:
filtered_map["children"].append((child, c_type))
@@ -568,7 +573,9 @@ def get_ability(course_id, content, user):
user_group_id,
content_user_group_id
),
'can_reply': check_permissions_by_view(user, course_id, content, "create_comment" if content['type'] == 'thread' else "create_sub_comment"),
'can_reply': check_permissions_by_view(
user, course_id, content, "create_comment" if content['type'] == 'thread' else "create_sub_comment",
),
'can_delete': check_permissions_by_view(
user,
course_id,

View File

@@ -1,8 +1,9 @@
# pylint: disable=missing-docstring
from __future__ import print_function
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from django_comment_common.models import Role
from openedx.core.djangoapps.discussion_common.models import Role
class Command(BaseCommand):

View File

@@ -1,3 +1,4 @@
# pylint: disable=missing-docstring
"""
This must be run only after seed_permissions_roles.py!
@@ -7,7 +8,7 @@ Enrollments.
from __future__ import print_function
from django.core.management.base import BaseCommand
from django_comment_common.models import assign_default_role_on_enrollment
from openedx.core.djangoapps.discussion_common.models import assign_default_role_on_enrollment
from student.models import CourseEnrollment

View File

@@ -7,7 +7,7 @@ Enrollments.
from __future__ import print_function
from django.core.management.base import BaseCommand
from django_comment_common.models import assign_default_role_on_enrollment
from openedx.core.djangoapps.discussion_common.models import assign_default_role_on_enrollment
from student.models import CourseEnrollment

View File

@@ -1,3 +1,4 @@
# pylint: disable=missing-docstring
from courseware.courses import get_course
from django.core.management.base import BaseCommand, CommandError
from opaque_keys.edx.keys import CourseKey

View File

@@ -1,11 +1,12 @@
# pylint: disable=missing-docstring,broad-except
"""
Reload forum (comment client) users from existing users.
"""
from __future__ import print_function
import lms.lib.comment_client as cc
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
import openedx.core.djangoapps.discussion_common.comment_client as cc
class Command(BaseCommand):

View File

@@ -1,9 +1,10 @@
# pylint: disable=missing-docstring
"""
Management command to seed default permissions and roles.
"""
from django.core.management.base import BaseCommand
from django_comment_common.utils import seed_permissions_roles
from opaque_keys.edx.keys import CourseKey
from openedx.core.djangoapps.discussion_common.utils import seed_permissions_roles
class Command(BaseCommand):

View File

@@ -1,3 +1,4 @@
# pylint: disable=missing-docstring,too-many-format-args
from __future__ import print_function
from django.contrib.auth.models import User

View File

@@ -3,9 +3,9 @@ One-off script to sync all user information to the
discussion service (later info will be synced automatically)
"""
import lms.lib.comment_client as cc
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
import openedx.core.djangoapps.discussion_common.comment_client as cc
class Command(BaseCommand):

View File

@@ -1 +1,2 @@
# pylint: disable=missing-docstring
NOTIFICATION_PREF_KEY = "notification_pref"

View File

@@ -1,7 +1,8 @@
# pylint: disable=missing-docstring,unused-argument,no-member
from django.contrib.auth.models import User
from lettuce import step, world
from notification_prefs import NOTIFICATION_PREF_KEY
from lms.djangoapps.discussion.notification_prefs import NOTIFICATION_PREF_KEY
from openedx.core.djangoapps.user_api.preferences.api import get_user_preference, set_user_preference
USERNAME = "robot"

View File

@@ -1,3 +1,4 @@
# pylint: disable=missing-docstring,consider-iterating-dictionary
import json
from django.contrib.auth.models import AnonymousUser
@@ -9,8 +10,10 @@ from django.test.client import RequestFactory
from django.test.utils import override_settings
from mock import patch
from notification_prefs import NOTIFICATION_PREF_KEY
from notification_prefs.views import UsernameCipher, ajax_disable, ajax_enable, ajax_status, set_subscription
from lms.djangoapps.discussion.notification_prefs import NOTIFICATION_PREF_KEY
from lms.djangoapps.discussion.notification_prefs.views import (
UsernameCipher, ajax_disable, ajax_enable, ajax_status, set_subscription,
)
from openedx.core.djangoapps.user_api.models import UserPreference
from student.tests.factories import UserFactory
from util.testing import UrlResetMixin

View File

@@ -1,3 +1,4 @@
# pylint: disable=missing-docstring
"""
Views to support notification preferences.
"""
@@ -22,7 +23,7 @@ from django.views.decorators.http import require_GET, require_POST
from six import text_type
from edxmako.shortcuts import render_to_response
from notification_prefs import NOTIFICATION_PREF_KEY
from lms.djangoapps.discussion.notification_prefs import NOTIFICATION_PREF_KEY
from openedx.core.djangoapps.user_api.models import UserPreference
from openedx.core.djangoapps.user_api.preferences.api import delete_user_preference
@@ -90,7 +91,7 @@ class UsernameCipher(object):
try:
unpadded = unpadder.update(decrypted) + unpadder.finalize()
if len(unpadded) == 0:
if len(unpadded) == 0: # pylint: disable=len-as-condition
raise UsernameDecryptionException("padding")
return unpadded
except ValueError:

View File

@@ -1,8 +1,9 @@
# pylint: disable=missing-docstring
from django.contrib.auth.models import User
from django.http import Http404
from rest_framework import serializers
from lms.djangoapps.notification_prefs import NOTIFICATION_PREF_KEY
from lms.djangoapps.discussion.notification_prefs import NOTIFICATION_PREF_KEY
from openedx.core.djangoapps.course_groups.cohorts import is_course_cohorted
from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY

View File

@@ -1,3 +1,4 @@
# pylint: disable=missing-docstring
from __future__ import absolute_import
import itertools
@@ -7,10 +8,10 @@ from django.test.client import RequestFactory
from django.test.utils import override_settings
from opaque_keys.edx.locator import CourseLocator
from django_comment_common.models import Permission, Role
from notification_prefs import NOTIFICATION_PREF_KEY
from notifier_api.views import NotifierUsersViewSet
from lms.djangoapps.discussion.notification_prefs import NOTIFICATION_PREF_KEY
from lms.djangoapps.discussion.notifier_api.views import NotifierUsersViewSet
from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory
from openedx.core.djangoapps.discussion_common.models import Permission, Role
from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
from openedx.core.djangoapps.user_api.models import UserPreference
from openedx.core.djangoapps.user_api.tests.factories import UserPreferenceFactory

View File

@@ -5,7 +5,7 @@ URLs for the notifier api app
from django.conf.urls import include, url
from rest_framework import routers
from notifier_api.views import NotifierUsersViewSet
from lms.djangoapps.discussion.notifier_api.views import NotifierUsersViewSet
notifier_api_router = routers.DefaultRouter()
notifier_api_router.register(r'users', NotifierUsersViewSet, base_name="notifier_users")

View File

@@ -1,10 +1,13 @@
"""
Django views for the Notifier.
"""
from django.contrib.auth.models import User
from rest_framework import pagination
from rest_framework.response import Response
from rest_framework.viewsets import ReadOnlyModelViewSet
from notification_prefs import NOTIFICATION_PREF_KEY
from notifier_api.serializers import NotifierUserSerializer
from lms.djangoapps.discussion.notification_prefs import NOTIFICATION_PREF_KEY
from lms.djangoapps.discussion.notifier_api.serializers import NotifierUserSerializer
from openedx.core.lib.api.permissions import ApiKeyHeaderPermission

View File

@@ -5,7 +5,7 @@ Views handling read (GET) requests for the Discussion tab and inline discussions
from django.conf import settings
from django.utils.translation import ugettext_noop
import django_comment_client.utils as utils
import lms.djangoapps.discussion.django_comment_client.utils as utils
from courseware.tabs import EnrolledTab
from xmodule.tabs import TabFragmentViewMixin

View File

@@ -3,30 +3,43 @@ Discussion API internal interface
"""
import itertools
from collections import defaultdict
from enum import Enum
from urllib import urlencode
from urlparse import urlunparse
from django.core.exceptions import ValidationError
from django.urls import reverse
from django.http import Http404
from enum import Enum
from opaque_keys import InvalidKeyError
from opaque_keys.edx.locator import CourseKey
from rest_framework.exceptions import PermissionDenied
from courseware.courses import get_course_with_access
from discussion_api.exceptions import CommentNotFoundError, DiscussionDisabledError, ThreadNotFoundError
from discussion_api.forms import CommentActionsForm, ThreadActionsForm
from discussion_api.permissions import (
from lms.djangoapps.courseware.courses import get_course_with_access
from lms.djangoapps.discussion.rest_api.exceptions import (
CommentNotFoundError, DiscussionDisabledError, ThreadNotFoundError,
)
from lms.djangoapps.discussion.rest_api.forms import CommentActionsForm, ThreadActionsForm
from lms.djangoapps.discussion.rest_api.permissions import (
can_delete,
get_editable_fields,
get_initializable_comment_fields,
get_initializable_thread_fields
)
from discussion_api.serializers import CommentSerializer, DiscussionTopicSerializer, ThreadSerializer, get_context
from django_comment_client.base.views import track_comment_created_event, track_thread_created_event, track_voted_event
from django_comment_client.utils import get_accessible_discussion_xblocks, get_group_id_for_user, is_commentable_divided
from django_comment_common.signals import (
from lms.djangoapps.discussion.rest_api.serializers import (
CommentSerializer, DiscussionTopicSerializer, ThreadSerializer, get_context,
)
from lms.djangoapps.discussion.django_comment_client.base.views import (
track_comment_created_event, track_thread_created_event, track_voted_event,
)
from lms.djangoapps.discussion.django_comment_client.utils import (
get_accessible_discussion_xblocks, get_group_id_for_user, is_commentable_divided,
)
from lms.djangoapps.courseware.exceptions import CourseAccessRedirect
from lms.djangoapps.discussion.rest_api.pagination import DiscussionAPIPagination
from openedx.core.djangoapps.discussion_common.comment_client.comment import Comment
from openedx.core.djangoapps.discussion_common.comment_client.thread import Thread
from openedx.core.djangoapps.discussion_common.comment_client.utils import CommentClientRequestError
from openedx.core.djangoapps.discussion_common.signals import (
comment_created,
comment_deleted,
comment_edited,
@@ -36,12 +49,7 @@ from django_comment_common.signals import (
thread_edited,
thread_voted
)
from django_comment_common.utils import get_course_discussion_settings
from lms.djangoapps.courseware.exceptions import CourseAccessRedirect
from lms.djangoapps.discussion_api.pagination import DiscussionAPIPagination
from lms.lib.comment_client.comment import Comment
from lms.lib.comment_client.thread import Thread
from lms.lib.comment_client.utils import CommentClientRequestError
from openedx.core.djangoapps.discussion_common.utils import get_course_discussion_settings
from openedx.core.djangoapps.user_api.accounts.views import AccountViewSet
from openedx.core.lib.exceptions import CourseNotFoundError, DiscussionNotFoundError, PageNotFoundError
@@ -175,7 +183,7 @@ def get_course(request, course_key):
Returns:
The course information; see discussion_api.views.CourseView for more
The course information; see discussion.rest_api.views.CourseView for more
detail.
Raises:
@@ -305,7 +313,7 @@ def get_course_topics(request, course_key, topic_ids=None):
Returns:
A course topic listing dictionary; see discussion_api.views.CourseTopicViews
A course topic listing dictionary; see discussion.rest_api.views.CourseTopicViews
for more detail.
Raises:
@@ -510,7 +518,7 @@ def get_thread_list(
Returns:
A paginated result containing a list of threads; see
discussion_api.views.ThreadViewSet for more detail.
discussion.rest_api.views.ThreadViewSet for more detail.
Raises:
@@ -612,7 +620,7 @@ def get_comment_list(request, thread_id, endorsed, page, page_size, requested_fi
Returns:
A paginated result containing a list of comments; see
discussion_api.views.CommentViewSet for more detail.
discussion.rest_api.views.CommentViewSet for more detail.
"""
response_skip = page_size * (page - 1)
cc_thread, context = _get_thread_and_context(
@@ -809,7 +817,7 @@ def create_thread(request, thread_data):
Returns:
The created thread; see discussion_api.views.ThreadViewSet for more
The created thread; see discussion.rest_api.views.ThreadViewSet for more
detail.
"""
course_id = thread_data.get("course_id")
@@ -859,7 +867,7 @@ def create_comment(request, comment_data):
Returns:
The created comment; see discussion_api.views.CommentViewSet for more
The created comment; see discussion.rest_api.views.CommentViewSet for more
detail.
"""
thread_id = comment_data.get("thread_id")
@@ -902,7 +910,7 @@ def update_thread(request, thread_id, update_data):
Returns:
The updated thread; see discussion_api.views.ThreadViewSet for more
The updated thread; see discussion.rest_api.views.ThreadViewSet for more
detail.
"""
cc_thread, context = _get_thread_and_context(request, thread_id, retrieve_kwargs={"with_responses": True})
@@ -941,7 +949,7 @@ def update_comment(request, comment_id, update_data):
Returns:
The updated comment; see discussion_api.views.CommentViewSet for more
The updated comment; see discussion.rest_api.views.CommentViewSet for more
detail.
Raises:
@@ -1042,7 +1050,7 @@ def get_response_comments(request, comment_id, page, page_size, requested_fields
response_skip = page_size * (page - 1)
paged_response_comments = response_comments[response_skip:(response_skip + page_size)]
if len(paged_response_comments) == 0 and page != 1:
if not paged_response_comments and page != 1:
raise PageNotFoundError("Page not found (No results on this page).")
results = _serialize_discussion_entities(

View File

@@ -11,7 +11,9 @@ from opaque_keys.edx.locator import CourseLocator
from six import text_type
from courseware.courses import get_course_with_access
from django_comment_common.models import Role, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_GROUP_MODERATOR
from openedx.core.djangoapps.discussion_common.models import (
Role, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_GROUP_MODERATOR,
)
from openedx.core.djangoapps.util.forms import ExtendedNullBooleanField, MultiValueField
@@ -146,7 +148,7 @@ class CourseDiscussionSettingsForm(Form):
self.cleaned_data['course_key'] = course_key
return course_id
except InvalidKeyError:
raise ValidationError("'{}' is not a valid course key".format(text_type(course_id)))
raise ValidationError(u"'{}' is not a valid course key".format(text_type(course_id)))
class CourseDiscussionRolesForm(CourseDiscussionSettingsForm):
@@ -160,7 +162,7 @@ class CourseDiscussionRolesForm(CourseDiscussionSettingsForm):
)
rolename = ChoiceField(
ROLE_CHOICES,
error_messages={"invalid_choice": "Role '%(value)s' does not exist"}
error_messages={u"invalid_choice": u"Role '%(value)s' does not exist"}
)
def clean_rolename(self):
@@ -171,7 +173,7 @@ class CourseDiscussionRolesForm(CourseDiscussionSettingsForm):
try:
role = Role.objects.get(name=rolename, course_id=course_id)
except Role.DoesNotExist:
raise ValidationError("Role '{}' does not exist".format(rolename))
raise ValidationError(u"Role '{}' does not exist".format(rolename))
self.cleaned_data['role'] = role
return rolename

View File

@@ -1,8 +1,8 @@
"""
Discussion API permission logic
"""
from lms.lib.comment_client.comment import Comment
from lms.lib.comment_client.thread import Thread
from openedx.core.djangoapps.discussion_common.comment_client.comment import Comment
from openedx.core.djangoapps.discussion_common.comment_client.thread import Thread
def _is_author(cc_content, context):

View File

@@ -9,22 +9,28 @@ from django.core.exceptions import ValidationError
from django.urls import reverse
from rest_framework import serializers
from discussion.views import get_divided_discussions
from discussion_api.permissions import NON_UPDATABLE_COMMENT_FIELDS, NON_UPDATABLE_THREAD_FIELDS, get_editable_fields
from discussion_api.render import render_body
from django_comment_client.utils import is_comment_too_deep, get_group_id_for_user, get_group_name
from django_comment_common.models import (
from openedx.core.djangoapps.discussion_common.models import (
FORUM_ROLE_ADMINISTRATOR,
FORUM_ROLE_COMMUNITY_TA,
FORUM_ROLE_MODERATOR,
Role,
)
from django_comment_common.utils import get_course_discussion_settings
from lms.djangoapps.django_comment_client.utils import course_discussion_division_enabled, get_group_names_by_id
from lms.lib.comment_client.comment import Comment
from lms.lib.comment_client.thread import Thread
from lms.lib.comment_client.user import User as CommentClientUser
from lms.lib.comment_client.utils import CommentClientRequestError
from openedx.core.djangoapps.discussion_common.comment_client.comment import Comment
from openedx.core.djangoapps.discussion_common.comment_client.thread import Thread
from openedx.core.djangoapps.discussion_common.comment_client.user import User as CommentClientUser
from openedx.core.djangoapps.discussion_common.comment_client.utils import CommentClientRequestError
from openedx.core.djangoapps.discussion_common.utils import get_course_discussion_settings
from lms.djangoapps.discussion.django_comment_client.utils import (
is_comment_too_deep, get_group_id_for_user, get_group_name,
)
from lms.djangoapps.discussion.rest_api.permissions import (
NON_UPDATABLE_COMMENT_FIELDS, NON_UPDATABLE_THREAD_FIELDS, get_editable_fields,
)
from lms.djangoapps.discussion.rest_api.render import render_body
from lms.djangoapps.discussion.views import get_divided_discussions
from lms.djangoapps.discussion.django_comment_client.utils import (
course_discussion_division_enabled, get_group_names_by_id,
)
from student.models import get_user_by_username_or_email
@@ -75,6 +81,7 @@ def validate_not_blank(value):
class _ContentSerializer(serializers.Serializer):
# pylint: disable=abstract-method
"""
A base class for thread and comment serializers.
"""
@@ -368,6 +375,7 @@ class CommentSerializer(_ContentSerializer):
]
def to_representation(self, data):
# pylint: disable=arguments-differ
data = super(CommentSerializer, self).to_representation(data)
# Django Rest Framework v3 no longer includes None values
@@ -529,7 +537,7 @@ class DiscussionRolesSerializer(serializers.Serializer):
self.user = get_user_by_username_or_email(user_id)
return user_id
except DjangoUser.DoesNotExist:
raise ValidationError("'{}' is not a valid student identifier".format(user_id))
raise ValidationError(u"'{}' is not a valid student identifier".format(user_id))
def validate(self, attrs):
"""Validate the data at an object level."""

View File

@@ -17,8 +17,8 @@ from rest_framework.exceptions import PermissionDenied
from common.test.utils import MockSignalHandlerMixin, disable_signal
from courseware.tests.factories import BetaTesterFactory, StaffFactory
from discussion_api import api
from discussion_api.api import (
from lms.djangoapps.discussion.rest_api import api
from lms.djangoapps.discussion.rest_api.api import (
create_comment,
create_thread,
delete_comment,
@@ -31,15 +31,17 @@ from discussion_api.api import (
update_comment,
update_thread
)
from discussion_api.exceptions import CommentNotFoundError, DiscussionDisabledError, ThreadNotFoundError
from discussion_api.tests.utils import (
from lms.djangoapps.discussion.rest_api.exceptions import (
CommentNotFoundError, DiscussionDisabledError, ThreadNotFoundError,
)
from lms.djangoapps.discussion.rest_api.tests.utils import (
CommentsServiceMockMixin,
make_minimal_cs_comment,
make_minimal_cs_thread,
make_paginated_api_response
)
from django_comment_client.tests.utils import ForumsEnableMixin
from django_comment_common.models import (
from lms.djangoapps.discussion.django_comment_client.tests.utils import ForumsEnableMixin
from openedx.core.djangoapps.discussion_common.models import (
FORUM_ROLE_ADMINISTRATOR,
FORUM_ROLE_COMMUNITY_TA,
FORUM_ROLE_MODERATOR,
@@ -1549,7 +1551,7 @@ class CreateThreadTest(
})
self.register_post_thread_response(cs_thread)
with self.assert_signal_sent(api, 'thread_created', sender=None, user=self.user, exclude_args=('post',)):
actual = create_thread(self.request, data)
create_thread(self.request, data)
event_name, event_data = mock_emit.call_args[0]
self.assertEqual(event_name, "edx.forum.thread.created")
self.assertEqual(

View File

@@ -9,7 +9,7 @@ import ddt
from django.http import QueryDict
from opaque_keys.edx.locator import CourseLocator
from discussion_api.forms import CommentListGetForm, ThreadListGetForm
from lms.djangoapps.discussion.rest_api.forms import CommentListGetForm, ThreadListGetForm
from openedx.core.djangoapps.util.test_forms import FormTestMixin

View File

@@ -5,8 +5,8 @@ from unittest import TestCase
from django.test import RequestFactory
from discussion_api.pagination import DiscussionAPIPagination
from discussion_api.tests.utils import make_paginated_api_response
from lms.djangoapps.discussion.rest_api.pagination import DiscussionAPIPagination
from lms.djangoapps.discussion.rest_api.tests.utils import make_paginated_api_response
class PaginationSerializerTest(TestCase):

View File

@@ -5,15 +5,15 @@ import itertools
import ddt
from discussion_api.permissions import (
from lms.djangoapps.discussion.rest_api.permissions import (
can_delete,
get_editable_fields,
get_initializable_comment_fields,
get_initializable_thread_fields
)
from lms.lib.comment_client.comment import Comment
from lms.lib.comment_client.thread import Thread
from lms.lib.comment_client.user import User
from openedx.core.djangoapps.discussion_common.comment_client.comment import Comment
from openedx.core.djangoapps.discussion_common.comment_client.thread import Thread
from openedx.core.djangoapps.discussion_common.comment_client.user import User
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory

View File

@@ -5,7 +5,7 @@ from unittest import TestCase
import ddt
from discussion_api.render import render_body
from lms.djangoapps.discussion.rest_api.render import render_body
def _add_p_tags(raw_body):

View File

@@ -9,18 +9,20 @@ import httpretty
import mock
from django.test.client import RequestFactory
from discussion_api.serializers import CommentSerializer, ThreadSerializer, get_context
from discussion_api.tests.utils import CommentsServiceMockMixin, make_minimal_cs_comment, make_minimal_cs_thread
from django_comment_client.tests.utils import ForumsEnableMixin
from django_comment_common.models import (
from lms.djangoapps.discussion.rest_api.serializers import CommentSerializer, ThreadSerializer, get_context
from lms.djangoapps.discussion.rest_api.tests.utils import (
CommentsServiceMockMixin, make_minimal_cs_comment, make_minimal_cs_thread,
)
from lms.djangoapps.discussion.django_comment_client.tests.utils import ForumsEnableMixin
from openedx.core.djangoapps.discussion_common.comment_client.comment import Comment
from openedx.core.djangoapps.discussion_common.comment_client.thread import Thread
from openedx.core.djangoapps.discussion_common.models import (
FORUM_ROLE_ADMINISTRATOR,
FORUM_ROLE_COMMUNITY_TA,
FORUM_ROLE_MODERATOR,
FORUM_ROLE_STUDENT,
Role
)
from lms.lib.comment_client.comment import Comment
from lms.lib.comment_client.thread import Thread
from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory
from student.tests.factories import UserFactory
from util.testing import UrlResetMixin
@@ -737,7 +739,7 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
@ddt.data(None, -1, 0, 2, 5)
def test_create_parent_id_too_deep(self, max_depth):
with mock.patch("django_comment_client.utils.MAX_COMMENT_DEPTH", max_depth):
with mock.patch("lms.djangoapps.discussion.django_comment_client.utils.MAX_COMMENT_DEPTH", max_depth):
data = self.minimal_data.copy()
context = get_context(self.course, self.request, make_minimal_cs_thread())
if max_depth is None or max_depth >= 0:

View File

@@ -21,17 +21,19 @@ from six import text_type
from common.test.utils import disable_signal
from course_modes.models import CourseMode
from course_modes.tests.factories import CourseModeFactory
from discussion_api import api
from discussion_api.tests.utils import (
from lms.djangoapps.discussion.rest_api import api
from lms.djangoapps.discussion.rest_api.tests.utils import (
CommentsServiceMockMixin,
ProfileImageTestMixin,
make_minimal_cs_comment,
make_minimal_cs_thread,
make_paginated_api_response
)
from django_comment_client.tests.utils import ForumsEnableMixin, config_course_discussions, topic_name_to_id
from django_comment_common.models import CourseDiscussionSettings, Role
from django_comment_common.utils import seed_permissions_roles
from lms.djangoapps.discussion.django_comment_client.tests.utils import (
ForumsEnableMixin, config_course_discussions, topic_name_to_id,
)
from openedx.core.djangoapps.discussion_common.models import CourseDiscussionSettings, Role
from openedx.core.djangoapps.discussion_common.utils import seed_permissions_roles
from openedx.core.djangoapps.course_groups.tests.helpers import config_course_cohorts
from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user
from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_image_storage

View File

@@ -521,7 +521,7 @@ class ProfileImageTestMixin(object):
self.assertTrue(storage.exists(name))
with closing(Image.open(storage.path(name))) as img:
self.assertEqual(img.size, (size, size))
self.assertEqual(img.format, 'JPEG')
self.assertEqual(img.format, 'JPEG') # pylint: disable=no-member
else:
self.assertFalse(storage.exists(name))

View File

@@ -1,3 +1,4 @@
# pylint: skip-file
"""
Discussion API URLs
"""
@@ -5,7 +6,7 @@ from django.conf import settings
from django.conf.urls import include, url
from rest_framework.routers import SimpleRouter
from discussion_api.views import (
from lms.djangoapps.discussion.rest_api.views import (
CommentViewSet,
CourseDiscussionSettingsAPIView,
CourseDiscussionRolesAPIView,
@@ -29,7 +30,7 @@ urlpatterns = [
name="discussion_course_settings",
),
url(
r'^v1/courses/{}/roles/(?P<rolename>[A-Za-z0-9+ _-]+)/?$'.format(
r"^v1/courses/{}/roles/(?P<rolename>[A-Za-z0-9+ _-]+)/?$".format(
settings.COURSE_ID_PATTERN
),
CourseDiscussionRolesAPIView.as_view(),

View File

@@ -17,14 +17,10 @@ from rest_framework.views import APIView
from rest_framework.viewsets import ViewSet
from six import text_type
from django_comment_client.utils import available_division_schemes
from django_comment_common.models import Role
from django_comment_common.utils import get_course_discussion_settings, set_course_discussion_settings
from instructor.access import update_forum_role
from lms.lib import comment_client
from discussion.views import get_divided_discussions
from discussion_api.api import (
from lms.djangoapps.discussion.django_comment_client.utils import available_division_schemes
from lms.djangoapps.discussion.rest_api.api import (
create_comment,
create_thread,
delete_comment,
@@ -38,13 +34,13 @@ from discussion_api.api import (
update_comment,
update_thread
)
from discussion_api.forms import (
from lms.djangoapps.discussion.rest_api.forms import (
CommentGetForm,
CommentListGetForm,
CourseDiscussionSettingsForm,
ThreadListGetForm,
CourseDiscussionRolesForm)
from discussion_api.serializers import (
from lms.djangoapps.discussion.rest_api.serializers import (
DiscussionRolesSerializer,
DiscussionRolesListSerializer,
DiscussionSettingsSerializer,
@@ -52,6 +48,11 @@ from discussion_api.serializers import (
from openedx.core.lib.api.authentication import OAuth2AuthenticationAllowInactiveUser
from openedx.core.lib.api.parsers import MergePatchParser
from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, view_auth_classes
from openedx.core.djangoapps.discussion_common import comment_client
from openedx.core.djangoapps.discussion_common.models import Role
from openedx.core.djangoapps.discussion_common.utils import (
get_course_discussion_settings, set_course_discussion_settings,
)
from openedx.core.djangoapps.user_api.accounts.permissions import CanReplaceUsername, CanRetireUser
from openedx.core.djangoapps.user_api.models import UserRetirementStatus
from util.json_request import JsonResponse
@@ -930,7 +931,7 @@ class CourseDiscussionRolesAPIView(DeveloperErrorViewMixin, APIView):
try:
update_forum_role(course_id, user, rolename, action)
except Role.DoesNotExist:
raise ValidationError("Role '{}' does not exist".format(rolename))
raise ValidationError(u"Role '{}' does not exist".format(rolename))
role = form.cleaned_data['role']
data = {'course_id': course_id, 'users': role.users.all()}

View File

@@ -6,8 +6,8 @@ import logging
from django.conf import settings
from django.dispatch import receiver
from django_comment_common import signals
from lms.djangoapps.discussion import tasks
from openedx.core.djangoapps.discussion_common import signals
from opaque_keys.edx.locator import LibraryLocator
from openedx.core.djangoapps.site_configuration.models import SiteConfiguration
from openedx.core.djangoapps.theming.helpers import get_current_site

View File

@@ -11,18 +11,20 @@ from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from celery_utils.logged_task import LoggedTask
from django_comment_common.models import DiscussionsIdMapping
from edx_ace import ace
from edx_ace.utils import date
from edx_ace.recipient import Recipient
from eventtracking import tracker
from lms.djangoapps.discussion.django_comment_client.utils import (
permalink, get_accessible_discussion_xblocks_by_course_id,
)
from opaque_keys.edx.keys import CourseKey
from lms.djangoapps.django_comment_client.utils import permalink, get_accessible_discussion_xblocks_by_course_id
import lms.lib.comment_client as cc
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.ace_common.template_context import get_base_template_context
from openedx.core.djangoapps.ace_common.message import BaseMessageType
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
import openedx.core.djangoapps.discussion_common.comment_client as cc
from openedx.core.djangoapps.discussion_common.models import DiscussionsIdMapping
from openedx.core.lib.celery.task_utils import emulate_http_request
from track import segment

View File

@@ -10,7 +10,7 @@ from django.utils.translation import ugettext as _
from django.template.defaultfilters import escapejs
from django.urls import reverse
from django_comment_client.permissions import has_permission
from lms.djangoapps.discussion.django_comment_client.permissions import has_permission
from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_string
from openedx.core.djangolib.markup import HTML
%>

View File

@@ -10,7 +10,7 @@ from django.utils.translation import ugettext as _, ungettext
from django.template.defaultfilters import escapejs
from django.urls import reverse
from django_comment_client.permissions import has_permission
from lms.djangoapps.discussion.django_comment_client.permissions import has_permission
from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_string
%>

View File

@@ -1,9 +1,9 @@
from django.test import TestCase
import mock
from django_comment_common import signals, models
from edx_django_utils.cache import RequestCache
from lms.djangoapps.discussion.signals.handlers import ENABLE_FORUM_NOTIFICATIONS_FOR_SITE_KEY
from openedx.core.djangoapps.discussion_common import signals, models
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory, SiteConfigurationFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory

View File

@@ -9,18 +9,17 @@ import ddt
from django.contrib.sites.models import Site
import mock
import lms.lib.comment_client as cc
from django_comment_common.models import ForumsConfig
from django_comment_common.signals import comment_created
from edx_ace.recipient import Recipient
from edx_ace.renderers import EmailRenderer
from edx_ace.channel import ChannelType, get_channel_for_message
from edx_ace.utils import date
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.content.course_overviews.tests.factories import CourseOverviewFactory
from openedx.core.djangoapps.ace_common.template_context import get_base_template_context
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
import openedx.core.djangoapps.discussion_common.comment_client as cc
from openedx.core.djangoapps.discussion_common.models import ForumsConfig
from openedx.core.djangoapps.discussion_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 student.tests.factories import CourseEnrollmentFactory, UserFactory

View File

@@ -14,36 +14,36 @@ from six import text_type
from course_modes.models import CourseMode
from course_modes.tests.factories import CourseModeFactory
from django_comment_client.constants import TYPE_ENTRY, TYPE_SUBCATEGORY
from django_comment_client.permissions import get_team
from django_comment_client.tests.group_id import (
from lms.djangoapps.discussion.django_comment_client.constants import TYPE_ENTRY, TYPE_SUBCATEGORY
from lms.djangoapps.discussion.django_comment_client.permissions import get_team
from lms.djangoapps.discussion.django_comment_client.tests.group_id import (
CohortedTopicGroupIdTestMixin,
GroupIdAssertionMixin,
NonCohortedTopicGroupIdTestMixin
)
from django_comment_client.tests.unicode import UnicodeTestMixin
from django_comment_client.tests.utils import (
from lms.djangoapps.discussion.django_comment_client.tests.unicode import UnicodeTestMixin
from lms.djangoapps.discussion.django_comment_client.tests.utils import (
CohortedTestCase,
ForumsEnableMixin,
config_course_discussions,
topic_name_to_id
)
from django_comment_client.utils import strip_none
from django_comment_common.models import (
CourseDiscussionSettings,
ForumsConfig,
FORUM_ROLE_STUDENT,
)
from django_comment_common.utils import ThreadContext, seed_permissions_roles
from lms.djangoapps.discussion.django_comment_client.utils import strip_none
from lms.djangoapps.courseware.exceptions import CourseAccessRedirect
from lms.djangoapps.discussion import views
from lms.djangoapps.discussion.views import _get_discussion_default_topic_id
from lms.djangoapps.discussion.views import course_discussions_settings_handler
from lms.djangoapps.teams.tests.factories import CourseTeamFactory, CourseTeamMembershipFactory
from lms.lib.comment_client.utils import CommentClientPaginatedResult
from openedx.core.djangoapps.course_groups.models import CourseUserGroup
from openedx.core.djangoapps.course_groups.tests.helpers import config_course_cohorts
from openedx.core.djangoapps.course_groups.tests.test_views import CohortViewsTestCase
from openedx.core.djangoapps.discussion_common.comment_client.utils import CommentClientPaginatedResult
from openedx.core.djangoapps.discussion_common.models import (
CourseDiscussionSettings,
ForumsConfig,
FORUM_ROLE_STUDENT,
)
from openedx.core.djangoapps.discussion_common.utils import ThreadContext, seed_permissions_roles
from openedx.core.djangoapps.util.testing import ContentGroupTestCase
from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES
from openedx.features.content_type_gating.models import ContentTypeGatingConfig
@@ -559,7 +559,7 @@ class SingleCohortedThreadTestCase(CohortedTestCase):
self.assertRegexpMatches(html, r'"group_name": "student_cohort"')
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
class SingleThreadAccessTestCase(CohortedTestCase):
def call_view(self, mock_request, commentable_id, user, group_id, thread_group_id=None, pass_group_id=True):
@@ -647,7 +647,7 @@ class SingleThreadAccessTestCase(CohortedTestCase):
self.assertEqual(resp.status_code, 200)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
class SingleThreadGroupIdTestCase(CohortedTestCase, GroupIdAssertionMixin):
cs_endpoint = "/threads/dummy_thread_id"
@@ -888,7 +888,7 @@ class SingleThreadContentGroupTestCase(ForumsEnableMixin, UrlResetMixin, Content
self.assert_can_access(self.beta_user, self.alpha_module.discussion_id, thread_id, True)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
class InlineDiscussionContextTestCase(ForumsEnableMixin, ModuleStoreTestCase):
def setUp(self):
@@ -925,7 +925,7 @@ class InlineDiscussionContextTestCase(ForumsEnableMixin, ModuleStoreTestCase):
self.assertEqual(json_response['discussion_data'][0]['context'], ThreadContext.STANDALONE)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
class InlineDiscussionGroupIdTestCase(
CohortedTestCase,
CohortedTopicGroupIdTestMixin,
@@ -976,7 +976,7 @@ class InlineDiscussionGroupIdTestCase(
)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
class ForumFormDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupIdTestMixin):
cs_endpoint = "/threads"
@@ -1022,7 +1022,7 @@ class ForumFormDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupIdT
)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupIdTestMixin):
cs_endpoint = "/active_threads"
@@ -1183,7 +1183,7 @@ class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupI
verify_group_id_not_present(profiled_user=self.moderator, pass_group_id=False)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
class FollowedThreadsDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupIdTestMixin):
cs_endpoint = "/subscribed_threads"
@@ -1220,7 +1220,7 @@ class FollowedThreadsDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGr
)
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
class InlineDiscussionTestCase(ForumsEnableMixin, ModuleStoreTestCase):
def setUp(self):
@@ -1480,7 +1480,7 @@ class InlineDiscussionUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCa
def setUp(self):
super(InlineDiscussionUnicodeTestCase, self).setUp()
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request):
mock_request.side_effect = make_mock_request_impl(course=self.course, text=text)
request = RequestFactory().get("dummy_url")
@@ -1513,7 +1513,7 @@ class ForumFormDiscussionUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTes
def setUp(self):
super(ForumFormDiscussionUnicodeTestCase, self).setUp()
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request):
mock_request.side_effect = make_mock_request_impl(course=self.course, text=text)
request = RequestFactory().get("dummy_url")
@@ -1528,7 +1528,7 @@ class ForumFormDiscussionUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTes
@ddt.ddt
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
class ForumDiscussionXSSTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase):
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
@@ -1601,7 +1601,7 @@ class ForumDiscussionSearchUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreT
def setUp(self):
super(ForumDiscussionSearchUnicodeTestCase, self).setUp()
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request):
mock_request.side_effect = make_mock_request_impl(course=self.course, text=text)
data = {
@@ -1637,7 +1637,7 @@ class SingleThreadUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase,
def setUp(self):
super(SingleThreadUnicodeTestCase, self).setUp()
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request):
thread_id = "test_thread_id"
mock_request.side_effect = make_mock_request_impl(course=self.course, text=text, thread_id=thread_id)
@@ -1670,7 +1670,7 @@ class UserProfileUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, U
def setUp(self):
super(UserProfileUnicodeTestCase, self).setUp()
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request):
mock_request.side_effect = make_mock_request_impl(course=self.course, text=text)
request = RequestFactory().get("dummy_url")
@@ -1702,7 +1702,7 @@ class FollowedThreadsUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCas
def setUp(self):
super(FollowedThreadsUnicodeTestCase, self).setUp()
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request):
mock_request.side_effect = make_mock_request_impl(course=self.course, text=text)
request = RequestFactory().get("dummy_url")
@@ -1729,7 +1729,7 @@ class EnrollmentTestCase(ForumsEnableMixin, ModuleStoreTestCase):
self.student = UserFactory.create()
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.requests.request', autospec=True)
def test_unenrolled(self, mock_request):
mock_request.side_effect = make_mock_request_impl(course=self.course, text='dummy')
request = RequestFactory().get('dummy_url')
@@ -2111,7 +2111,7 @@ class ThreadViewedEventTestCase(EventTestMixin, ForumsEnableMixin, UrlResetMixin
self.client.login(username=self.student.username, password=PASSWORD)
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
@patch('lms.lib.comment_client.utils.perform_request')
@patch('openedx.core.djangoapps.discussion_common.comment_client.utils.perform_request')
def test_thread_viewed_event(self, mock_perform_request):
mock_perform_request.side_effect = make_mock_perform_request_impl(
course=self.course,

View File

@@ -23,16 +23,14 @@ from opaque_keys.edx.keys import CourseKey
from rest_framework import status
from web_fragments.fragment import Fragment
import django_comment_client.utils as utils
from lms.djangoapps.experiments.utils import get_experiment_user_metadata_context
import lms.lib.comment_client as cc
from courseware.access import has_access
from courseware.courses import get_course_with_access
from courseware.views.views import CourseTabView
from django_comment_client.base.views import track_thread_viewed_event
from django_comment_client.constants import TYPE_ENTRY
from django_comment_client.permissions import get_team, has_permission
from django_comment_client.utils import (
import lms.djangoapps.discussion.django_comment_client.utils as utils
from lms.djangoapps.discussion.django_comment_client.base.views import track_thread_viewed_event
from lms.djangoapps.discussion.django_comment_client.constants import TYPE_ENTRY
from lms.djangoapps.discussion.django_comment_client.permissions import get_team, has_permission
from lms.djangoapps.discussion.django_comment_client.utils import (
add_courseware_context,
available_division_schemes,
course_discussion_division_enabled,
@@ -43,8 +41,12 @@ from django_comment_client.utils import (
is_commentable_divided,
strip_none
)
from django_comment_common.models import CourseDiscussionSettings
from django_comment_common.utils import ThreadContext, get_course_discussion_settings, set_course_discussion_settings
from lms.djangoapps.experiments.utils import get_experiment_user_metadata_context
import openedx.core.djangoapps.discussion_common.comment_client as cc
from openedx.core.djangoapps.discussion_common.models import CourseDiscussionSettings
from openedx.core.djangoapps.discussion_common.utils import (
ThreadContext, get_course_discussion_settings, set_course_discussion_settings,
)
from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
from openedx.features.course_duration_limits.access import generate_course_expired_fragment
from student.models import CourseEnrollment

View File

@@ -1,2 +0,0 @@
# This import registers the ForumThreadViewedEventTransformer
import event_transformers # pylint: disable=relative-import

View File

@@ -1 +0,0 @@
# This file is intentionally blank. It has been moved to common/djangoapps/django_comment_common

Some files were not shown because too many files have changed in this diff Show More