Fix failures caused by removing lms/djangoapps from sys.path

This commit is contained in:
Calen Pennington
2020-09-22 11:38:54 -04:00
committed by Calen Pennington
parent 211bd3beb5
commit 4a120a9e26
51 changed files with 298 additions and 282 deletions

View File

@@ -20,6 +20,7 @@ from django.utils.translation import ugettext_lazy
from path import Path as path
from openedx.core.release import RELEASE_LINE
from xmodule.modulestore.modulestore_settings import update_module_store_settings
########################## Prod-like settings ###################################
# These should be as close as possible to the settings we use in production.
@@ -36,6 +37,7 @@ os.environ['REVISION_CFG'] = "{config_root}/revisions.yml".format(config_root=CO
from .production import * # pylint: disable=wildcard-import, unused-wildcard-import, wrong-import-position
######################### Testing overrides ####################################
# Redirect to the test_root folder within the repo

View File

@@ -48,7 +48,7 @@ from datetime import timedelta
import lms.envs.common
# Although this module itself may not use these imported variables, other dependent modules may.
from lms.envs.common import (
USE_TZ, ALL_LANGUAGES, update_module_store_settings, ASSET_IGNORE_REGEX,
USE_TZ, ALL_LANGUAGES, ASSET_IGNORE_REGEX,
PARENTAL_CONSENT_AGE_LIMIT, REGISTRATION_EMAIL_PATTERNS_ALLOWED,
# The following PROFILE_IMAGE_* settings are included as they are
# indirectly accessed through the email opt-in API, which is
@@ -1440,7 +1440,7 @@ INSTALLED_APPS = [
# by installed apps.
'openedx.core.djangoapps.oauth_dispatch.apps.OAuthDispatchAppConfig',
'lms.djangoapps.courseware',
'coursewarehistoryextended',
'lms.djangoapps.coursewarehistoryextended',
'survey.apps.SurveyConfig',
'lms.djangoapps.verify_student.apps.VerifyStudentConfig',
'completion',
@@ -1499,7 +1499,7 @@ INSTALLED_APPS = [
'openedx.features.course_duration_limits',
'openedx.features.content_type_gating',
'openedx.features.discounts',
'experiments',
'lms.djangoapps.experiments',
'openedx.core.djangoapps.external_user_ids',
# so sample_task is available to celery workers

View File

@@ -14,7 +14,6 @@ sessions. Assumes structure:
# pylint: disable=wildcard-import, unused-wildcard-import
from .common import *
import os
from uuid import uuid4
@@ -24,8 +23,12 @@ from path import Path as path
from openedx.core.lib.derived import derive_settings
from util.db import NoOpMigrationModules
from xmodule.modulestore.modulestore_settings import update_module_store_settings
from .common import *
# import settings from LMS for consistent behavior with CMS
from lms.envs.test import (
from lms.envs.test import ( # pylint: disable=wrong-import-order
COMPREHENSIVE_THEME_DIRS,
DEFAULT_FILE_STORAGE,
ECOMMERCE_API_URL,

View File

@@ -44,7 +44,7 @@ class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase):
None: None,
}
URLCONF_MODULES = ['verify_student.urls']
URLCONF_MODULES = ['lms.djangoapps.verify_student.urls']
def setUp(self):
# Invoke UrlResetMixin

View File

@@ -40,5 +40,5 @@ INSTALLED_APPS.extend([
'course_creators',
'xblock_config.apps.XBlockConfig',
'user_tasks',
'lti_provider'
'lms.djangoapps.lti_provider'
])

View File

@@ -254,15 +254,6 @@ for app in os.listdir(six.text_type(root / 'common' / 'djangoapps')):
if os.path.isdir(six.text_type(root / path)) and app != 'terrain':
modules[path] = path
# These Django apps under lms don't import correctly with the "lms.djangapps" prefix
# Others don't import correctly without it...INSTALLED_APPS entries are inconsistent
lms_djangoapps = ['badges', 'branding', 'bulk_email', 'courseware',
'coursewarehistoryextended', 'email_marketing', 'experiments', 'lti_provider',
'mobile_api', 'notes', 'rss_proxy', 'shoppingcart', 'survey']
for app in lms_djangoapps:
path = os.path.join('lms', 'djangoapps', app)
modules[path] = path
def update_settings_module(service='lms'):
"""

View File

@@ -12,7 +12,7 @@ class BadgesConfig(AppConfig):
"""
Application Configuration for Badges.
"""
name = u'badges'
name = u'lms.djangoapps.badges'
def ready(self):
"""

View File

@@ -8,7 +8,7 @@ from django.test import TestCase
from django.test.utils import override_settings
from django.urls import reverse
from branding.api import _footer_business_links, get_footer, get_home_url, get_logo_url
from ..api import _footer_business_links, get_footer, get_home_url, get_logo_url
from openedx.core.djangoapps.site_configuration.tests.test_util import with_site_configuration
test_config_disabled_contact_us = { # pylint: disable=invalid-name

View File

@@ -0,0 +1,8 @@
from django.apps import AppConfig
class BulkEmailConfig(AppConfig):
"""
Application Configuration for bulk_email.
"""
name = u'lms.djangoapps.bulk_email'

View File

@@ -26,7 +26,7 @@ from xmodule.modulestore.tests.factories import CourseFactory
from lms.djangoapps.bulk_email.api import get_unsubscribed_link
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
class TestOptoutCourseEmails(ModuleStoreTestCase):
"""
Test that optouts are referenced in sending course email.
@@ -144,7 +144,7 @@ class TestOptoutCourseEmails(ModuleStoreTestCase):
self.assertIn(self.instructor.email, sent_addresses)
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
class TestACEOptoutCourseEmails(ModuleStoreTestCase):
"""
Test that optouts are referenced in sending course email.

View File

@@ -21,8 +21,8 @@ from django.utils.translation import get_language
from markupsafe import escape
from mock import Mock, patch
from bulk_email.models import BulkEmailFlag, Optout
from bulk_email.tasks import _get_course_email_context, _get_source_address
from ..models import BulkEmailFlag, Optout
from ..tasks import _get_course_email_context, _get_source_address
from course_modes.models import CourseMode
from lms.djangoapps.courseware.tests.factories import InstructorFactory, StaffFactory
@@ -166,7 +166,7 @@ class SendEmailWithMockedUgettextMixin(object):
text=text,
)
with patch('bulk_email.tasks._', side_effect=mock_ugettext):
with patch('lms.djangoapps.bulk_email.tasks._', side_effect=mock_ugettext):
self.client.post(self.send_mail_url, test_email)
return mail.outbox[0]
@@ -229,7 +229,7 @@ class LocalizedFromAddressCourseLangTestCase(SendEmailWithMockedUgettextMixin, E
self.assertRegex(message.from_email, 'AR .* Course Staff')
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
class TestEmailSendFromDashboardMockedHtmlToText(EmailSendFromDashboardTestCase):
"""
Tests email sending with mocked html_to_text.
@@ -249,7 +249,7 @@ class TestEmailSendFromDashboardMockedHtmlToText(EmailSendFromDashboardTestCase)
# We should get back a HttpResponseForbidden (status code 403)
self.assertContains(response, "Email is not enabled for this course.", status_code=403)
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
def test_send_to_self(self):
"""
Make sure email send to myself goes to myself.
@@ -566,7 +566,7 @@ class TestEmailSendFromDashboardMockedHtmlToText(EmailSendFromDashboardTestCase)
self.assertEqual(len(from_email), 61)
@override_settings(BULK_EMAIL_EMAILS_PER_TASK=3)
@patch('bulk_email.tasks.update_subtask_status')
@patch('lms.djangoapps.bulk_email.tasks.update_subtask_status')
def test_chunked_queries_send_numerous_emails(self, email_mock):
"""
Test sending a large number of emails, to test the chunked querying

View File

@@ -41,7 +41,7 @@ class EmailTestException(Exception):
@ddt.ddt
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
class TestEmailErrors(ModuleStoreTestCase):
"""
Test that errors from sending email are handled properly.
@@ -75,8 +75,8 @@ class TestEmailErrors(ModuleStoreTestCase):
super(TestEmailErrors, cls).tearDownClass()
BulkEmailFlag.objects.all().delete()
@patch('bulk_email.tasks.get_connection', autospec=True)
@patch('bulk_email.tasks.send_course_email.retry')
@patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True)
@patch('lms.djangoapps.bulk_email.tasks.send_course_email.retry')
def test_data_err_retry(self, retry, get_conn):
"""
Test that celery handles transient SMTPDataErrors by retrying.
@@ -97,9 +97,9 @@ class TestEmailErrors(ModuleStoreTestCase):
exc = kwargs['exc']
self.assertIsInstance(exc, SMTPDataError)
@patch('bulk_email.tasks.get_connection', autospec=True)
@patch('bulk_email.tasks.update_subtask_status')
@patch('bulk_email.tasks.send_course_email.retry')
@patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True)
@patch('lms.djangoapps.bulk_email.tasks.update_subtask_status')
@patch('lms.djangoapps.bulk_email.tasks.send_course_email.retry')
def test_data_err_fail(self, retry, result, get_conn):
"""
Test that celery handles permanent SMTPDataErrors by failing and not retrying.
@@ -130,8 +130,8 @@ class TestEmailErrors(ModuleStoreTestCase):
self.assertEqual(subtask_status.failed, expected_fails)
self.assertEqual(subtask_status.succeeded, settings.BULK_EMAIL_EMAILS_PER_TASK - expected_fails)
@patch('bulk_email.tasks.get_connection', autospec=True)
@patch('bulk_email.tasks.send_course_email.retry')
@patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True)
@patch('lms.djangoapps.bulk_email.tasks.send_course_email.retry')
def test_disconn_err_retry(self, retry, get_conn):
"""
Test that celery handles SMTPServerDisconnected by retrying.
@@ -151,8 +151,8 @@ class TestEmailErrors(ModuleStoreTestCase):
exc = kwargs['exc']
self.assertIsInstance(exc, SMTPServerDisconnected)
@patch('bulk_email.tasks.get_connection', autospec=True)
@patch('bulk_email.tasks.send_course_email.retry')
@patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True)
@patch('lms.djangoapps.bulk_email.tasks.send_course_email.retry')
def test_conn_err_retry(self, retry, get_conn):
"""
Test that celery handles SMTPConnectError by retrying.
@@ -173,8 +173,8 @@ class TestEmailErrors(ModuleStoreTestCase):
exc = kwargs['exc']
self.assertIsInstance(exc, SMTPConnectError)
@patch('bulk_email.tasks.SubtaskStatus.increment')
@patch('bulk_email.tasks.log')
@patch('lms.djangoapps.bulk_email.tasks.SubtaskStatus.increment')
@patch('lms.djangoapps.bulk_email.tasks.log')
def test_nonexistent_email(self, mock_log, result):
"""
Tests retries when the email doesn't exist
@@ -368,5 +368,5 @@ class TestEmailErrors(ModuleStoreTestCase):
with self.assertRaises(CourseEmail.DoesNotExist):
# we skip the call that updates subtask status, since we've not set up the InstructorTask
# for the subtask, and it's not important to the test.
with patch('bulk_email.tasks.update_subtask_status'):
with patch('lms.djangoapps.bulk_email.tasks.update_subtask_status'):
send_course_email(entry_id, bogus_email_id, to_list, global_email_context, subtask_status.to_dict())

View File

@@ -31,7 +31,7 @@ from xmodule.modulestore.tests.factories import CourseFactory
@ddt.ddt
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
class CourseEmailTest(ModuleStoreTestCase):
"""Test the CourseEmail model."""

View File

@@ -18,7 +18,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
class TestOptoutCourseEmailsBySignal(ModuleStoreTestCase):
"""
Tests that the force_optout_all signal receiver opts the user out of course emails

View File

@@ -32,8 +32,8 @@ from mock import Mock, patch
from opaque_keys.edx.locator import CourseLocator
from six.moves import range
from bulk_email.models import SEND_TO_LEARNERS, SEND_TO_MYSELF, SEND_TO_STAFF, CourseEmail, Optout
from bulk_email.tasks import _get_course_email_context
from ..models import SEND_TO_LEARNERS, SEND_TO_MYSELF, SEND_TO_STAFF, CourseEmail, Optout
from ..tasks import _get_course_email_context
from lms.djangoapps.instructor_task.models import InstructorTask
from lms.djangoapps.instructor_task.subtasks import SubtaskStatus, update_subtask_status
from lms.djangoapps.instructor_task.tasks import send_bulk_course_email
@@ -75,7 +75,7 @@ def my_update_subtask_status(entry_id, current_task_id, new_subtask_status):
update_subtask_status(entry_id, current_task_id, new_subtask_status)
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
"""Tests instructor task that send bulk email."""
@@ -134,7 +134,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
update_subtask_status(entry_id, bogus_task_id, new_subtask_status)
with self.assertRaises(ValueError):
with patch('bulk_email.tasks.update_subtask_status', dummy_update_subtask_status):
with patch('lms.djangoapps.bulk_email.tasks.update_subtask_status', dummy_update_subtask_status):
send_bulk_course_email(task_entry.id, {})
def _create_students(self, num_students):
@@ -194,7 +194,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
num_emails = settings.BULK_EMAIL_EMAILS_PER_TASK
# We also send email to the instructor:
self._create_students(num_emails - 1)
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
get_conn.return_value.send_messages.side_effect = cycle([None])
self._test_run_with_task(send_bulk_course_email, 'emailed', num_emails, num_emails)
@@ -203,12 +203,12 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
num_emails = settings.BULK_EMAIL_EMAILS_PER_TASK
# We also send email to the instructor:
self._create_students(num_emails - 1)
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
get_conn.return_value.send_messages.side_effect = cycle([None])
task_entry = self._test_run_with_task(send_bulk_course_email, 'emailed', num_emails, num_emails)
# submit the same task a second time, and confirm that it is not run again.
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
get_conn.return_value.send_messages.side_effect = cycle([Exception("This should not happen!")])
parent_status = self._run_task_with_mock_celery(send_bulk_course_email, task_entry.id, task_entry.task_id)
self.assertEqual(parent_status.get('total'), num_emails)
@@ -224,7 +224,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
student = students[0]
student.is_active = False
student.save()
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
get_conn.return_value.send_messages.side_effect = cycle([None])
self._test_run_with_task(send_bulk_course_email, 'emailed', num_emails - 1, num_emails - 1)
@@ -239,7 +239,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
for index in range(0, num_emails, 4):
Optout.objects.create(user=students[index], course_id=self.course.id)
# mark some students as opting out
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
get_conn.return_value.send_messages.side_effect = cycle([None])
self._test_run_with_task(
send_bulk_course_email, 'emailed', num_emails, expected_succeeds, skipped=expected_skipped
@@ -253,7 +253,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
self._create_students(num_emails - 1)
expected_fails = int((num_emails + 3) / 4.0)
expected_succeeds = num_emails - expected_fails
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
# have every fourth email fail due to some address failure:
get_conn.return_value.send_messages.side_effect = cycle([exception, None, None, None])
self._test_run_with_task(
@@ -298,7 +298,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
expected_succeeds = num_emails - emails_with_non_ascii_chars + num_of_course_instructors
expected_fails = emails_with_non_ascii_chars
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
get_conn.return_value.send_messages.side_effect = cycle([None])
self._test_run_with_task(
task_class=send_bulk_course_email,
@@ -317,7 +317,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
self._create_students(num_emails - 1)
expected_fails = 0
expected_succeeds = num_emails
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
# Have every other mail attempt fail due to disconnection.
get_conn.return_value.send_messages.side_effect = cycle([exception, None])
self._test_run_with_task(
@@ -338,10 +338,10 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
self._create_students(num_emails - 1)
expected_fails = num_emails
expected_succeeds = 0
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
# always fail to connect, triggering repeated retries until limit is hit:
get_conn.return_value.send_messages.side_effect = cycle([exception])
with patch('bulk_email.tasks.update_subtask_status', my_update_subtask_status):
with patch('lms.djangoapps.bulk_email.tasks.update_subtask_status', my_update_subtask_status):
self._test_run_with_task(
send_bulk_course_email,
'emailed',
@@ -392,7 +392,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
# exceeded"). The maximum recursion depth is 90, so
# num_emails * expected_retries < 90.
expected_retries = 10
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
# Cycle through N throttling errors followed by a success.
get_conn.return_value.send_messages.side_effect = cycle(
chain(repeat(exception, expected_retries), [None])
@@ -423,7 +423,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
self._create_students(num_emails - 1)
expected_fails = num_emails
expected_succeeds = 0
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
# always fail to connect, triggering repeated retries until limit is hit:
get_conn.return_value.send_messages.side_effect = cycle([exception])
self._test_run_with_task(
@@ -458,7 +458,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
# We also send email to the instructor:
self._create_students(num_emails - 1)
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
get_conn.return_value.send_messages.side_effect = cycle([None])
self._test_run_with_task(send_bulk_course_email, 'emailed', num_emails, num_emails)

View File

@@ -5,7 +5,7 @@ URLs for bulk_email app
from django.conf.urls import url
from django.conf import settings
from bulk_email import views
from . import views
urlpatterns = [
url(

View File

@@ -5,7 +5,7 @@ URLs for the Bulk Enrollment API
from django.conf.urls import url
from bulk_enroll.views import BulkEnrollView
from .views import BulkEnrollView
urlpatterns = [
url(r'^bulk_enroll', BulkEnrollView.as_view(), name='bulk_enroll'),

View File

@@ -5,19 +5,19 @@ URLs for the CCX Feature.
from django.conf.urls import url
import ccx.views
from . import views
urlpatterns = [
url(r'^ccx_coach$', ccx.views.dashboard, name='ccx_coach_dashboard'),
url(r'^create_ccx$', ccx.views.create_ccx, name='create_ccx'),
url(r'^save_ccx$', ccx.views.save_ccx, name='save_ccx'),
url(r'^ccx_schedule$', ccx.views.ccx_schedule, name='ccx_schedule'),
url(r'^ccx-manage-students$', ccx.views.ccx_students_management, name='ccx-manage-students'),
url(r'^ccx_coach$', views.dashboard, name='ccx_coach_dashboard'),
url(r'^create_ccx$', views.create_ccx, name='create_ccx'),
url(r'^save_ccx$', views.save_ccx, name='save_ccx'),
url(r'^ccx_schedule$', views.ccx_schedule, name='ccx_schedule'),
url(r'^ccx-manage-students$', views.ccx_students_management, name='ccx-manage-students'),
# Grade book
url(r'^ccx_gradebook$', ccx.views.ccx_gradebook, name='ccx_gradebook'),
url(r'^ccx_gradebook/(?P<offset>[0-9]+)$', ccx.views.ccx_gradebook, name='ccx_gradebook'),
url(r'^ccx_gradebook$', views.ccx_gradebook, name='ccx_gradebook'),
url(r'^ccx_gradebook/(?P<offset>[0-9]+)$', views.ccx_gradebook, name='ccx_gradebook'),
url(r'^ccx_grades.csv$', ccx.views.ccx_grades_csv, name='ccx_grades_csv'),
url(r'^ccx_set_grading_policy$', ccx.views.set_grading_policy, name='ccx_set_grading_policy'),
url(r'^ccx_grades.csv$', views.ccx_grades_csv, name='ccx_grades_csv'),
url(r'^ccx_set_grading_policy$', views.set_grading_policy, name='ccx_set_grading_policy'),
]

View File

@@ -31,7 +31,6 @@ from lms.djangoapps.courseware.fields import UnsignedBigIntAutoField
from six import text_type
from six.moves import range
import coursewarehistoryextended
from openedx.core.djangolib.markup import HTML
log = logging.getLogger("edx.courseware")
@@ -217,7 +216,8 @@ class BaseStudentModuleHistory(models.Model):
history_entries = []
if settings.FEATURES.get('ENABLE_CSMH_EXTENDED'):
history_entries += coursewarehistoryextended.models.StudentModuleHistoryExtended.objects.filter(
from lms.djangoapps.coursewarehistoryextended.models import StudentModuleHistoryExtended
history_entries += StudentModuleHistoryExtended.objects.filter(
# Django will sometimes try to join to courseware_studentmodule
# so just do an in query
student_module__in=[module.id for module in student_modules]

View File

@@ -0,0 +1,5 @@
from django.apps import AppConfig
class CoursewareHistoryExtendedConfig(AppConfig):
name = u'lms.djangoapps.coursewarehistoryextended'

View File

@@ -5,7 +5,7 @@ Urls for sysadmin dashboard feature
from django.conf.urls import url
from dashboard import sysadmin
from . import sysadmin
urlpatterns = [
url(r'^$', sysadmin.Users.as_view(), name="sysadmin"),

View File

@@ -5,7 +5,7 @@ Forum urls for the django_comment_client.
from django.conf.urls import url
from discussion import views
from . import views
urlpatterns = [
url(r'users/(?P<user_id>\w+)/followed$', views.followed_threads, name='followed_threads'),

View File

@@ -22,7 +22,7 @@ def edxnotes(cls):
Returns raw html for the component.
"""
# Import is placed here to avoid model import at project startup.
from edxnotes.helpers import (
from .helpers import (
generate_uid, get_edxnotes_id_token, get_public_endpoint, get_token_url, is_feature_enabled
)

View File

@@ -26,10 +26,10 @@ from lms.djangoapps.courseware.model_data import FieldDataCache
from lms.djangoapps.courseware.module_render import get_module_for_descriptor
from lms.djangoapps.courseware.tabs import get_course_tab_list
from edxmako.shortcuts import render_to_string
from edxnotes import helpers
from edxnotes.decorators import edxnotes
from edxnotes.exceptions import EdxNotesParseError, EdxNotesServiceUnavailable
from edxnotes.plugins import EdxNotesTab
from . import helpers
from .decorators import edxnotes
from .exceptions import EdxNotesParseError, EdxNotesServiceUnavailable
from .plugins import EdxNotesTab
from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user
from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory
from openedx.core.djangoapps.user_api.models import RetirementState, UserRetirementStatus
@@ -111,10 +111,10 @@ class EdxNotesDecoratorTest(ModuleStoreTestCase):
self.problem = TestProblem(self.course, self.user)
@patch.dict("django.conf.settings.FEATURES", {'ENABLE_EDXNOTES': True})
@patch("edxnotes.helpers.get_public_endpoint", autospec=True)
@patch("edxnotes.helpers.get_token_url", autospec=True)
@patch("edxnotes.helpers.get_edxnotes_id_token", autospec=True)
@patch("edxnotes.helpers.generate_uid", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.get_public_endpoint", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.get_token_url", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.get_edxnotes_id_token", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.generate_uid", autospec=True)
def test_edxnotes_enabled(self, mock_generate_uid, mock_get_id_token, mock_get_token_url, mock_get_endpoint):
"""
Tests if get_html is wrapped when feature flag is on and edxnotes are
@@ -312,7 +312,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
with patch_edxnotes_api_settings(None):
self.assertRaises(ImproperlyConfigured, get_endpoint_function)
@patch("edxnotes.helpers.requests.get", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
def test_get_notes_correct_data(self, mock_get):
"""
Tests the result if correct data is received.
@@ -405,7 +405,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
helpers.get_notes(self.request, self.course)
)
@patch("edxnotes.helpers.requests.get", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
def test_get_notes_json_error(self, mock_get):
"""
Tests the result if incorrect json is received.
@@ -413,7 +413,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
mock_get.return_value.content = b"Error"
self.assertRaises(EdxNotesParseError, helpers.get_notes, self.request, self.course)
@patch("edxnotes.helpers.requests.get", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
def test_get_notes_empty_collection(self, mock_get):
"""
Tests the result if an empty response is received.
@@ -421,7 +421,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
mock_get.return_value.content = json.dumps({}).encode('utf-8')
self.assertRaises(EdxNotesParseError, helpers.get_notes, self.request, self.course)
@patch("edxnotes.helpers.requests.get", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
def test_search_correct_data(self, mock_get):
"""
Tests the result if correct data is received.
@@ -512,7 +512,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
helpers.get_notes(self.request, self.course)
)
@patch("edxnotes.helpers.requests.get", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
def test_search_json_error(self, mock_get):
"""
Tests the result if incorrect json is received.
@@ -520,7 +520,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
mock_get.return_value.content = b"Error"
self.assertRaises(EdxNotesParseError, helpers.get_notes, self.request, self.course)
@patch("edxnotes.helpers.requests.get", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
def test_search_wrong_data_format(self, mock_get):
"""
Tests the result if incorrect data structure is received.
@@ -528,7 +528,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
mock_get.return_value.content = json.dumps({"1": 2}).encode('utf-8')
self.assertRaises(EdxNotesParseError, helpers.get_notes, self.request, self.course)
@patch("edxnotes.helpers.requests.get", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
def test_search_empty_collection(self, mock_get):
"""
Tests no results.
@@ -542,9 +542,9 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
@override_settings(EDXNOTES_PUBLIC_API="http://example.com")
@override_settings(EDXNOTES_INTERNAL_API="http://example.com")
@patch("edxnotes.helpers.anonymous_id_for_user", autospec=True)
@patch("edxnotes.helpers.get_edxnotes_id_token", autospec=True)
@patch("edxnotes.helpers.requests.post")
@patch("lms.djangoapps.edxnotes.helpers.anonymous_id_for_user", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.get_edxnotes_id_token", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.requests.post")
def test_delete_all_notes_for_user(self, mock_post, mock_get_id_token, mock_anonymous_id_for_user):
"""
Test GDPR data deletion for Notes user_id
@@ -656,8 +656,8 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
helpers.preprocess_collection(self.user, self.course, initial_collection)
)
@patch("edxnotes.helpers.has_access", autospec=True)
@patch("edxnotes.helpers.modulestore", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.has_access", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.modulestore", autospec=True)
def test_preprocess_collection_no_unit(self, mock_modulestore, mock_has_access):
"""
Tests the result if the unit does not exist.
@@ -783,9 +783,9 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
@override_settings(EDXNOTES_PUBLIC_API="http://example.com")
@override_settings(EDXNOTES_INTERNAL_API="http://example.com")
@patch("edxnotes.helpers.anonymous_id_for_user", autospec=True)
@patch("edxnotes.helpers.get_edxnotes_id_token", autospec=True)
@patch("edxnotes.helpers.requests.get", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.anonymous_id_for_user", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.get_edxnotes_id_token", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
def test_send_request_with_text_param(self, mock_get, mock_get_id_token, mock_anonymous_id_for_user):
"""
Tests that requests are send with correct information.
@@ -818,9 +818,9 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
@override_settings(EDXNOTES_PUBLIC_API="http://example.com")
@override_settings(EDXNOTES_INTERNAL_API="http://example.com")
@patch("edxnotes.helpers.anonymous_id_for_user", autospec=True)
@patch("edxnotes.helpers.get_edxnotes_id_token", autospec=True)
@patch("edxnotes.helpers.requests.get", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.anonymous_id_for_user", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.get_edxnotes_id_token", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
def test_send_request_without_text_param(self, mock_get, mock_get_id_token, mock_anonymous_id_for_user):
"""
Tests that requests are send with correct information.
@@ -1018,7 +1018,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
# pylint: disable=unused-argument
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
@patch("edxnotes.views.get_notes", return_value={'results': []})
@patch("lms.djangoapps.edxnotes.views.get_notes", return_value={'results': []})
def test_edxnotes_view_is_enabled(self, mock_get_notes):
"""
Tests that appropriate view is received if EdxNotes feature is enabled.
@@ -1029,8 +1029,8 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
# pylint: disable=unused-argument
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
@patch("edxnotes.views.get_notes", return_value={'results': []})
@patch("edxnotes.views.get_course_position", return_value={'display_name': 'Section 1', 'url': 'test_url'})
@patch("lms.djangoapps.edxnotes.views.get_notes", return_value={'results': []})
@patch("lms.djangoapps.edxnotes.views.get_course_position", return_value={'display_name': 'Section 1', 'url': 'test_url'})
def test_edxnotes_html_tags_should_not_be_escaped(self, mock_get_notes, mock_position):
"""
Tests that explicit html tags rendered correctly.
@@ -1051,7 +1051,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
self.assertEqual(response.status_code, 404)
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
@patch("edxnotes.views.get_notes", autospec=True)
@patch("lms.djangoapps.edxnotes.views.get_notes", autospec=True)
def test_search_notes_successfully_respond(self, mock_search):
"""
Tests that search notes successfully respond if EdxNotes feature is enabled.
@@ -1071,7 +1071,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
self.assertEqual(response.status_code, 404)
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
@patch("edxnotes.views.get_notes", autospec=True)
@patch("lms.djangoapps.edxnotes.views.get_notes", autospec=True)
def test_search_500_service_unavailable(self, mock_search):
"""
Tests that 500 status code is received if EdxNotes service is unavailable.
@@ -1082,7 +1082,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
self.assertContains(response, "error", status_code=500)
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
@patch("edxnotes.views.get_notes", autospec=True)
@patch("lms.djangoapps.edxnotes.views.get_notes", autospec=True)
def test_search_notes_exception(self, mock_search):
"""
Tests that 500 status code is received if invalid data was received from
@@ -1199,7 +1199,7 @@ class EdxNotesRetireAPITest(ModuleStoreTestCase):
headers = {'HTTP_AUTHORIZATION': 'JWT ' + token}
return headers
@patch("edxnotes.helpers.requests.post", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.requests.post", autospec=True)
def test_retire_user_success(self, mock_post):
"""
Tests that 204 response is received on success.
@@ -1258,7 +1258,7 @@ class EdxNotesRetireAPITest(ModuleStoreTestCase):
)
self.assertEqual(response.status_code, 405)
@patch("edxnotes.helpers.delete_all_notes_for_user", autospec=True)
@patch("lms.djangoapps.edxnotes.helpers.delete_all_notes_for_user", autospec=True)
def test_retire_user_downstream_unavailable(self, mock_delete_all_notes_for_user):
"""
Tests that 500 response is received if the downstream (i.e. the EdxNotes IDA) is unavailable.

View File

@@ -5,7 +5,7 @@ URLs for EdxNotes.
from django.conf.urls import url
from edxnotes import views
from . import views
# Additionally, we include login URLs for the browseable API.
urlpatterns = [

View File

@@ -16,7 +16,7 @@ from six import text_type
import third_party_auth
from course_modes.models import CourseMode
from email_marketing.models import EmailMarketingConfiguration
from .models import EmailMarketingConfiguration
from lms.djangoapps.email_marketing.tasks import get_email_cookies_via_sailthru, update_user, update_user_email
from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
from openedx.core.djangoapps.user_authn.cookies import CREATE_LOGON_COOKIE

View File

@@ -20,14 +20,14 @@ from sailthru.sailthru_response import SailthruResponse
import six
from testfixtures import LogCapture
from email_marketing.models import EmailMarketingConfiguration
from email_marketing.signals import (
from ..models import EmailMarketingConfiguration
from ..signals import (
add_email_marketing_cookies,
email_marketing_register_user,
email_marketing_user_field_changed,
update_sailthru
)
from email_marketing.tasks import (
from ..tasks import (
_create_user_list,
_get_list_from_email_marketing_provider,
_get_or_create_user_list,
@@ -43,7 +43,7 @@ from util.json_request import JsonResponse
log = logging.getLogger(__name__)
LOGGER_NAME = "email_marketing.signals"
LOGGER_NAME = "lms.djangoapps.email_marketing.signals"
TEST_EMAIL = "test@edx.org"
@@ -94,7 +94,7 @@ class EmailMarketingTests(TestCase):
super(EmailMarketingTests, self).setUp()
@freeze_time(datetime.datetime.now())
@patch('email_marketing.signals.crum.get_current_request')
@patch('lms.djangoapps.email_marketing.signals.crum.get_current_request')
@patch('sailthru.sailthru_client.SailthruClient.api_post')
def test_drop_cookie(self, mock_sailthru, mock_get_current_request):
"""
@@ -176,9 +176,9 @@ class EmailMarketingTests(TestCase):
add_email_marketing_cookies(None, response=response, user=self.user)
self.assertFalse('sailthru_hid' in response.cookies)
@patch('email_marketing.tasks.log.error')
@patch('email_marketing.tasks.SailthruClient.api_post')
@patch('email_marketing.tasks.SailthruClient.api_get')
@patch('lms.djangoapps.email_marketing.tasks.log.error')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_get')
def test_add_user(self, mock_sailthru_get, mock_sailthru_post, mock_log_error):
"""
test async method in tasks that actually updates Sailthru
@@ -214,7 +214,7 @@ class EmailMarketingTests(TestCase):
)
))
@patch('email_marketing.tasks.SailthruClient.api_post')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
def test_email_not_sent_to_enterprise_learners(self, mock_sailthru_post):
"""
tests that welcome email is not sent to the enterprise learner
@@ -229,7 +229,7 @@ class EmailMarketingTests(TestCase):
)
self.assertNotEqual(mock_sailthru_post.call_args[0][0], "send")
@patch('email_marketing.tasks.SailthruClient.api_post')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
def test_add_user_list_not_called_on_white_label_domain(self, mock_sailthru_post):
"""
test user is not added to Sailthru user lists if registered from a whitel labe site
@@ -241,8 +241,8 @@ class EmailMarketingTests(TestCase):
)
self.assertFalse(mock_sailthru_post.called)
@patch('email_marketing.tasks.log.error')
@patch('email_marketing.tasks.SailthruClient.api_post')
@patch('lms.djangoapps.email_marketing.tasks.log.error')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
def test_update_user_error_logging(self, mock_sailthru, mock_log_error):
"""
Ensure that error returned from Sailthru api is logged
@@ -270,9 +270,9 @@ class EmailMarketingTests(TestCase):
update_user.delay({}, self.user.email, activation=True)
self.assertTrue(mock_log_error.called)
@patch('email_marketing.tasks.update_user.retry')
@patch('email_marketing.tasks.log.error')
@patch('email_marketing.tasks.SailthruClient.api_post')
@patch('lms.djangoapps.email_marketing.tasks.update_user.retry')
@patch('lms.djangoapps.email_marketing.tasks.log.error')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
def test_update_user_error_retryable(self, mock_sailthru, mock_log_error, mock_retry):
"""
Ensure that retryable error is retried
@@ -282,9 +282,9 @@ class EmailMarketingTests(TestCase):
self.assertTrue(mock_log_error.called)
self.assertTrue(mock_retry.called)
@patch('email_marketing.tasks.update_user.retry')
@patch('email_marketing.tasks.log.error')
@patch('email_marketing.tasks.SailthruClient.api_post')
@patch('lms.djangoapps.email_marketing.tasks.update_user.retry')
@patch('lms.djangoapps.email_marketing.tasks.log.error')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
def test_update_user_error_nonretryable(self, mock_sailthru, mock_log_error, mock_retry):
"""
Ensure that non-retryable error is not retried
@@ -294,8 +294,8 @@ class EmailMarketingTests(TestCase):
self.assertTrue(mock_log_error.called)
self.assertFalse(mock_retry.called)
@patch('email_marketing.tasks.log.error')
@patch('email_marketing.tasks.SailthruClient.api_post')
@patch('lms.djangoapps.email_marketing.tasks.log.error')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
def test_just_return_tasks(self, mock_sailthru, mock_log_error):
"""
Ensure that disabling Sailthru just returns
@@ -312,7 +312,7 @@ class EmailMarketingTests(TestCase):
update_email_marketing_config(enabled=True)
@patch('email_marketing.signals.log.error')
@patch('lms.djangoapps.email_marketing.signals.log.error')
def test_just_return_signals(self, mock_log_error):
"""
Ensure that disabling Sailthru just returns
@@ -335,7 +335,7 @@ class EmailMarketingTests(TestCase):
email_marketing_user_field_changed(None, user=anon)
self.assertFalse(mock_log_error.called)
@patch('email_marketing.tasks.SailthruClient.api_post')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
def test_change_email(self, mock_sailthru):
"""
test async method in task that changes email in Sailthru
@@ -348,7 +348,7 @@ class EmailMarketingTests(TestCase):
self.assertEqual(userparms['id'], "old@edx.org")
self.assertEqual(userparms['keys']['email'], TEST_EMAIL)
@patch('email_marketing.tasks.SailthruClient')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
def test_get_or_create_sailthru_list(self, mock_sailthru_client):
"""
Test the task the create sailthru lists.
@@ -382,14 +382,14 @@ class EmailMarketingTests(TestCase):
mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []}))
self.assertEqual(_get_or_create_user_list(mock_sailthru_client, 'test2_user_list'), None)
@patch('email_marketing.tasks.SailthruClient')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
def test_get_sailthru_list_map_no_list(self, mock_sailthru_client):
"""Test when no list returned from sailthru"""
mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []}))
self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {})
mock_sailthru_client.api_get.assert_called_with("list", {})
@patch('email_marketing.tasks.SailthruClient')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
def test_get_sailthru_list_map_error(self, mock_sailthru_client):
"""Test when error occurred while fetching data from sailthru"""
mock_sailthru_client.api_get.return_value = SailthruResponse(
@@ -397,13 +397,13 @@ class EmailMarketingTests(TestCase):
)
self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {})
@patch('email_marketing.tasks.SailthruClient')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
def test_get_sailthru_list_map_exception(self, mock_sailthru_client):
"""Test when exception raised while fetching data from sailthru"""
mock_sailthru_client.api_get.side_effect = SailthruClientError
self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {})
@patch('email_marketing.tasks.SailthruClient')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
def test_get_sailthru_list(self, mock_sailthru_client):
"""Test fetch list data from sailthru"""
mock_sailthru_client.api_get.return_value = \
@@ -414,7 +414,7 @@ class EmailMarketingTests(TestCase):
)
mock_sailthru_client.api_get.assert_called_with("list", {})
@patch('email_marketing.tasks.SailthruClient')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
def test_create_sailthru_list(self, mock_sailthru_client):
"""Test create list in sailthru"""
mock_sailthru_client.api_post.return_value = SailthruResponse(JsonResponse({'ok': True}))
@@ -425,7 +425,7 @@ class EmailMarketingTests(TestCase):
self.assertEqual(listparms['primary'], 0)
self.assertEqual(listparms['public_name'], 'test_list_name')
@patch('email_marketing.tasks.SailthruClient')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
def test_create_sailthru_list_error(self, mock_sailthru_client):
"""Test error occurrence while creating sailthru list"""
mock_sailthru_client.api_post.return_value = SailthruResponse(
@@ -433,14 +433,14 @@ class EmailMarketingTests(TestCase):
)
self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), False)
@patch('email_marketing.tasks.SailthruClient')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
def test_create_sailthru_list_exception(self, mock_sailthru_client):
"""Test exception raised while creating sailthru list"""
mock_sailthru_client.api_post.side_effect = SailthruClientError
self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), False)
@patch('email_marketing.tasks.log.error')
@patch('email_marketing.tasks.SailthruClient.api_post')
@patch('lms.djangoapps.email_marketing.tasks.log.error')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
def test_error_logging(self, mock_sailthru, mock_log_error):
"""
Ensure that error returned from Sailthru api is logged
@@ -453,7 +453,7 @@ class EmailMarketingTests(TestCase):
update_user_email.delay(self.user.username, "newemail2@test.com")
self.assertTrue(mock_log_error.called)
@patch('email_marketing.signals.crum.get_current_request')
@patch('lms.djangoapps.email_marketing.signals.crum.get_current_request')
@patch('lms.djangoapps.email_marketing.tasks.update_user.delay')
def test_register_user(self, mock_update_user, mock_get_current_request):
"""
@@ -490,7 +490,7 @@ class EmailMarketingTests(TestCase):
self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], 'es-419')
@patch.dict(settings.FEATURES, {"ENABLE_THIRD_PARTY_AUTH": False})
@patch('email_marketing.signals.crum.get_current_request')
@patch('lms.djangoapps.email_marketing.signals.crum.get_current_request')
@patch('lms.djangoapps.email_marketing.tasks.update_user.delay')
@ddt.data(('auth_userprofile', 'gender', 'f', True),
('auth_user', 'is_active', 1, True),
@@ -505,10 +505,10 @@ class EmailMarketingTests(TestCase):
email_marketing_user_field_changed(None, self.user, table=table, setting=setting, new_value=value)
self.assertEqual(mock_update_user.called, result)
@patch('email_marketing.tasks.SailthruClient.api_post')
@patch('email_marketing.signals.third_party_auth.provider.Registry.get_from_pipeline')
@patch('email_marketing.signals.third_party_auth.pipeline.get')
@patch('email_marketing.signals.crum.get_current_request')
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
@patch('lms.djangoapps.email_marketing.signals.third_party_auth.provider.Registry.get_from_pipeline')
@patch('lms.djangoapps.email_marketing.signals.third_party_auth.pipeline.get')
@patch('lms.djangoapps.email_marketing.signals.crum.get_current_request')
@ddt.data(True, False)
def test_modify_field_with_sso(self, send_welcome_email, mock_get_current_request,
mock_pipeline_get, mock_registry_get_from_pipeline, mock_sailthru_post):
@@ -632,7 +632,7 @@ class SailthruTests(TestCase):
switch.return_value = True
white_label_site = Site.objects.create(domain='testwhitelabel.com', name='White Label')
site_dict = {'id': white_label_site.id, 'domain': white_label_site.domain, 'name': white_label_site.name}
with patch('email_marketing.signals._get_current_site') as mock_site_info:
with patch('lms.djangoapps.email_marketing.signals._get_current_site') as mock_site_info:
mock_site_info.return_value = site_dict
update_sailthru(None, self.user, 'audit', str(self.course_id))
self.assertFalse(mock_sailthru_purchase.called)

View File

@@ -0,0 +1,8 @@
from django.apps import AppConfig
class ExperimentsConfig(AppConfig):
"""
Application Configuration for experiments.
"""
name = u'lms.djangoapps.experiments'

View File

@@ -40,7 +40,7 @@ class ExperimentWaffleFlagTests(SharedModuleStoreTestCase):
self.flag = ExperimentWaffleFlag('experiments', 'test', __name__, num_buckets=2, experiment_id=0)
self.key = CourseKey.from_string('a/b/c')
bucket_patch = patch('experiments.flags.stable_bucketing_hash_group', return_value=1)
bucket_patch = patch('lms.djangoapps.experiments.flags.stable_bucketing_hash_group', return_value=1)
self.addCleanup(bucket_patch.stop)
bucket_patch.start()
@@ -110,7 +110,7 @@ class ExperimentWaffleFlagTests(SharedModuleStoreTestCase):
def test_tracking(self):
# Run twice, with same request
with patch('experiments.flags.segment') as segment_mock:
with patch('lms.djangoapps.experiments.flags.segment') as segment_mock:
self.assertEqual(self.get_bucket(track=True), 1)
RequestCache.clear_all_namespaces() # we want to force get_bucket to check session, not early exit
self.assertEqual(self.get_bucket(track=True), 1)
@@ -136,10 +136,10 @@ class ExperimentWaffleFlagTests(SharedModuleStoreTestCase):
self.assertEqual(self.get_bucket(active=False), 1) # still returns 1!
def test_is_enabled(self):
with patch('experiments.flags.ExperimentWaffleFlag.get_bucket', return_value=1):
with patch('lms.djangoapps.experiments.flags.ExperimentWaffleFlag.get_bucket', return_value=1):
self.assertEqual(self.flag.is_enabled(self.key), True)
self.assertEqual(self.flag.is_enabled(), True)
with patch('experiments.flags.ExperimentWaffleFlag.get_bucket', return_value=0):
with patch('lms.djangoapps.experiments.flags.ExperimentWaffleFlag.get_bucket', return_value=0):
self.assertEqual(self.flag.is_enabled(self.key), False)
self.assertEqual(self.flag.is_enabled(), False)
@@ -207,7 +207,7 @@ class ExperimentWaffleFlagCourseAwarenessTest(SharedModuleStoreTestCase):
# Use our custom fake `stable_bucketing_hash_group` implementation.
stable_bucket_patcher = patch(
'experiments.flags.stable_bucketing_hash_group', self._mock_stable_bucket
'lms.djangoapps.experiments.flags.stable_bucketing_hash_group', self._mock_stable_bucket
)
stable_bucket_patcher.start()
self.addCleanup(stable_bucket_patcher.stop)

View File

@@ -5,7 +5,7 @@ Experimentation URLs
from django.conf.urls import include, url
from experiments import routers, views, views_custom
from . import routers, views, views_custom
router = routers.DefaultRouter()
router.register(r'data', views.ExperimentDataViewSet, basename='data')

View File

@@ -349,7 +349,7 @@ class TestEndpointHttpMethods(SharedModuleStoreTestCase, LoginEnrollmentTestCase
)
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
"""
Ensure that users cannot access endpoints they shouldn't be able to.
@@ -3378,7 +3378,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
self.assertContains(response, message)
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
class TestInstructorSendEmail(SiteMixin, SharedModuleStoreTestCase, LoginEnrollmentTestCase):
"""
Checks that only instructors have access to email endpoints, and that

View File

@@ -189,7 +189,7 @@ class InstructorTaskModuleSubmitTest(InstructorTaskModuleTestCase):
task_function(self.create_task_request(self.instructor), location, **params)
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
class InstructorTaskCourseSubmitTest(TestReportMixin, InstructorTaskCourseTestCase):
"""Tests API methods that involve the submission of course-based background tasks."""

View File

@@ -10,7 +10,7 @@ class LtiProviderConfig(AppConfig):
"""
Configuration class for the lti_provider Django application.
"""
name = 'lti_provider'
name = 'lms.djangoapps.lti_provider'
verbose_name = "LTI Provider"
def ready(self):

View File

@@ -12,8 +12,8 @@ from django.test.client import RequestFactory
from mock import MagicMock, PropertyMock, patch
from six.moves import range
import lti_provider.users as users
from lti_provider.models import LtiConsumer, LtiUser
from .. import users
from ..models import LtiConsumer, LtiUser
from student.tests.factories import UserFactory
@@ -45,9 +45,9 @@ class UserManagementHelperTest(TestCase):
with self.assertRaises(PermissionDenied):
users.switch_user(self.request, self.lti_user, self.lti_consumer)
@patch('lti_provider.users.login')
@patch('lms.djangoapps.lti_provider.users.login')
def test_authenticate_called(self, _login_mock):
with patch('lti_provider.users.authenticate', return_value=self.new_user) as authenticate:
with patch('lms.djangoapps.lti_provider.users.authenticate', return_value=self.new_user) as authenticate:
users.switch_user(self.request, self.lti_user, self.lti_consumer)
authenticate.assert_called_with(
username=self.new_user.username,
@@ -55,9 +55,9 @@ class UserManagementHelperTest(TestCase):
lti_consumer=self.lti_consumer
)
@patch('lti_provider.users.login')
@patch('lms.djangoapps.lti_provider.users.login')
def test_login_called(self, login_mock):
with patch('lti_provider.users.authenticate', return_value=self.new_user):
with patch('lms.djangoapps.lti_provider.users.authenticate', return_value=self.new_user):
users.switch_user(self.request, self.lti_user, self.lti_consumer)
login_mock.assert_called_with(self.request, self.new_user)
@@ -73,8 +73,8 @@ class UserManagementHelperTest(TestCase):
)
@patch('lti_provider.users.switch_user', autospec=True)
@patch('lti_provider.users.create_lti_user', autospec=True)
@patch('lms.djangoapps.lti_provider.users.switch_user', autospec=True)
@patch('lms.djangoapps.lti_provider.users.create_lti_user', autospec=True)
class AuthenticateLtiUserTest(TestCase):
"""
Tests for the authenticate_lti_user function in users.py
@@ -111,7 +111,7 @@ class AuthenticateLtiUserTest(TestCase):
def test_authentication_with_new_user(self, _create_user, switch_user):
lti_user = MagicMock()
lti_user.edx_user_id = self.edx_user_id
with patch('lti_provider.users.create_lti_user', return_value=lti_user) as create_user:
with patch('lms.djangoapps.lti_provider.users.create_lti_user', return_value=lti_user) as create_user:
users.authenticate_lti_user(self.request, self.lti_user_id, self.lti_consumer)
create_user.assert_called_with(self.lti_user_id, self.lti_consumer)
switch_user.assert_called_with(self.request, lti_user, self.lti_consumer)
@@ -161,7 +161,7 @@ class CreateLtiUserTest(TestCase):
self.assertEqual(User.objects.count(), 1)
@patch('uuid.uuid4', return_value='random_uuid')
@patch('lti_provider.users.generate_random_edx_username', return_value='edx_id')
@patch('lms.djangoapps.lti_provider.users.generate_random_edx_username', return_value='edx_id')
def test_create_lti_user_creates_correct_user(self, uuid_mock, _username_mock):
users.create_lti_user('lti_user_id', self.lti_consumer)
self.assertEqual(User.objects.count(), 1)
@@ -169,7 +169,7 @@ class CreateLtiUserTest(TestCase):
self.assertEqual(user.email, 'edx_id@lti.example.com')
uuid_mock.assert_called_with()
@patch('lti_provider.users.generate_random_edx_username', side_effect=['edx_id', 'new_edx_id'])
@patch('lms.djangoapps.lti_provider.users.generate_random_edx_username', side_effect=['edx_id', 'new_edx_id'])
def test_unique_username_created(self, username_mock):
User(username='edx_id').save()
users.create_lti_user('lti_user_id', self.lti_consumer)

View File

@@ -71,7 +71,7 @@ class LtiTestMixin(object):
super(LtiTestMixin, self).setUp()
# Always accept the OAuth signature
self.mock_verify = MagicMock(return_value=True)
patcher = patch('lti_provider.signature_validator.SignatureValidator.verify', self.mock_verify)
patcher = patch('lms.djangoapps.lti_provider.signature_validator.SignatureValidator.verify', self.mock_verify)
patcher.start()
self.addCleanup(patcher.stop)
@@ -87,8 +87,8 @@ class LtiLaunchTest(LtiTestMixin, TestCase):
"""
Tests for the lti_launch view
"""
@patch('lti_provider.views.render_courseware')
@patch('lti_provider.views.authenticate_lti_user')
@patch('lms.djangoapps.lti_provider.views.render_courseware')
@patch('lms.djangoapps.lti_provider.views.authenticate_lti_user')
def test_valid_launch(self, _authenticate, render):
"""
Verifies that the LTI launch succeeds when passed a valid request.
@@ -97,9 +97,9 @@ class LtiLaunchTest(LtiTestMixin, TestCase):
views.lti_launch(request, six.text_type(COURSE_KEY), six.text_type(USAGE_KEY))
render.assert_called_with(request, USAGE_KEY)
@patch('lti_provider.views.render_courseware')
@patch('lti_provider.views.store_outcome_parameters')
@patch('lti_provider.views.authenticate_lti_user')
@patch('lms.djangoapps.lti_provider.views.render_courseware')
@patch('lms.djangoapps.lti_provider.views.store_outcome_parameters')
@patch('lms.djangoapps.lti_provider.views.authenticate_lti_user')
def test_valid_launch_with_optional_params(self, _authenticate, store_params, _render):
"""
Verifies that the LTI launch succeeds when passed a valid request.
@@ -112,9 +112,9 @@ class LtiLaunchTest(LtiTestMixin, TestCase):
self.consumer
)
@patch('lti_provider.views.render_courseware')
@patch('lti_provider.views.store_outcome_parameters')
@patch('lti_provider.views.authenticate_lti_user')
@patch('lms.djangoapps.lti_provider.views.render_courseware')
@patch('lms.djangoapps.lti_provider.views.store_outcome_parameters')
@patch('lms.djangoapps.lti_provider.views.authenticate_lti_user')
def test_outcome_service_registered(self, _authenticate, store_params, _render):
"""
Verifies that the LTI launch succeeds when passed a valid request.
@@ -168,7 +168,7 @@ class LtiLaunchTest(LtiTestMixin, TestCase):
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 403)
@patch('lti_provider.views.render_courseware')
@patch('lms.djangoapps.lti_provider.views.render_courseware')
def test_lti_consumer_record_supplemented_with_guid(self, _render):
self.mock_verify.return_value = False

View File

@@ -5,7 +5,7 @@ URLs for the rss_proxy djangoapp.
from django.conf.urls import url
from rss_proxy.views import proxy
from .views import proxy
app_name = 'rss_proxy'
urlpatterns = [

View File

@@ -9,15 +9,15 @@ from django.conf import settings
from django.test import TestCase
from mock import patch
from shoppingcart.models import Order, OrderItem
from shoppingcart.processors.CyberSource2 import (
from ...models import Order, OrderItem
from ..CyberSource2 import (
_get_processor_exception_html,
get_signed_purchase_params,
process_postpay_callback,
processor_hash,
render_purchase_form_html
)
from shoppingcart.processors.exceptions import (
from ..exceptions import (
CCProcessorDataException,
CCProcessorSignatureException,
CCProcessorWrongAmountException

View File

@@ -84,7 +84,7 @@ class OrderTest(ModuleStoreTestCase):
self.cost = 40
# Add mock tracker for event testing.
patcher = patch('shoppingcart.models.segment')
patcher = patch('lms.djangoapps.shoppingcart.models.segment')
self.mock_tracker = patcher.start()
self.addCleanup(patcher.stop)
@@ -299,7 +299,7 @@ class OrderTest(ModuleStoreTestCase):
# CertificateItem
cart = Order.get_cart_for_user(user=self.user)
CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
with patch('shoppingcart.models.CertificateItem.save', side_effect=DatabaseError):
with patch('lms.djangoapps.shoppingcart.models.CertificateItem.save', side_effect=DatabaseError):
with self.assertRaises(DatabaseError):
cart.purchase()
# verify that we rolled back the entire transaction
@@ -315,15 +315,15 @@ class OrderTest(ModuleStoreTestCase):
cart.purchase()
self.assertEqual(len(mail.outbox), 1)
@patch('shoppingcart.models.log.error')
@patch('lms.djangoapps.shoppingcart.models.log.error')
def test_purchase_item_email_smtp_failure(self, error_logger):
cart = Order.get_cart_for_user(user=self.user)
CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
with patch('shoppingcart.models.EmailMessage.send', side_effect=smtplib.SMTPException):
with patch('lms.djangoapps.shoppingcart.models.EmailMessage.send', side_effect=smtplib.SMTPException):
cart.purchase()
self.assertTrue(error_logger.called)
@patch('shoppingcart.models.log.error')
@patch('lms.djangoapps.shoppingcart.models.log.error')
def test_purchase_item_email_boto_failure(self, error_logger):
cart = Order.get_cart_for_user(user=self.user)
CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
@@ -348,7 +348,7 @@ class OrderTest(ModuleStoreTestCase):
cardtype='001',
)
@patch('shoppingcart.models.render_to_string')
@patch('lms.djangoapps.shoppingcart.models.render_to_string')
@patch.dict(settings.FEATURES, {'STORE_BILLING_INFO': True})
def test_billing_info_storage_on(self, render):
cart = Order.get_cart_for_user(self.user)
@@ -366,7 +366,7 @@ class OrderTest(ModuleStoreTestCase):
((_, context), _) = render.call_args
self.assertTrue(context['has_billing_info'])
@patch('shoppingcart.models.render_to_string')
@patch('lms.djangoapps.shoppingcart.models.render_to_string')
@patch.dict(settings.FEATURES, {'STORE_BILLING_INFO': False})
def test_billing_info_storage_off(self, render):
cart = Order.get_cart_for_user(self.user)
@@ -517,7 +517,7 @@ class CertificateItemTest(ModuleStoreTestCase):
self.mock_tracker = patcher.start()
self.addCleanup(patcher.stop)
analytics_patcher = patch('shoppingcart.models.segment')
analytics_patcher = patch('lms.djangoapps.shoppingcart.models.segment')
self.mock_analytics_tracker = analytics_patcher.start()
self.addCleanup(analytics_patcher.stop)
@@ -657,7 +657,7 @@ class CertificateItemTest(ModuleStoreTestCase):
mail.outbox = []
cutoff_date.return_value = datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=1)
with patch('shoppingcart.models.log.error') as mock_error_logger:
with patch('lms.djangoapps.shoppingcart.models.log.error') as mock_error_logger:
CourseEnrollment.unenroll(self.user, course_key)
self.assertFalse(mock_error_logger.called)
self.assertEqual(len(mail.outbox), 1)
@@ -666,7 +666,7 @@ class CertificateItemTest(ModuleStoreTestCase):
self.assertIn('has requested a refund on Order', mail.outbox[0].body)
@patch('student.models.CourseEnrollment.refund_cutoff_date')
@patch('shoppingcart.models.log.error')
@patch('lms.djangoapps.shoppingcart.models.log.error')
def test_refund_cert_callback_before_expiration_email_error(self, error_logger, cutoff_date):
# If there's an error sending an email to billing, we need to log this error
many_days = datetime.timedelta(days=60)
@@ -687,7 +687,7 @@ class CertificateItemTest(ModuleStoreTestCase):
cart.purchase()
cutoff_date.return_value = datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=1)
with patch('shoppingcart.models.send_mail', side_effect=smtplib.SMTPException):
with patch('lms.djangoapps.shoppingcart.models.send_mail', side_effect=smtplib.SMTPException):
CourseEnrollment.unenroll(self.user, course_key)
self.assertTrue(error_logger.call_args[0][0].startswith('Failed sending email'))

View File

@@ -34,8 +34,8 @@ from course_modes.tests.factories import CourseModeFactory
from lms.djangoapps.courseware.tests.factories import InstructorFactory
from edxmako.shortcuts import render_to_response
from openedx.core.djangoapps.embargo.test_utils import restrict_course
from shoppingcart.admin import SoftDeleteCouponAdmin
from shoppingcart.models import (
from ..admin import SoftDeleteCouponAdmin
from ..models import (
CertificateItem,
Coupon,
CouponRedemption,
@@ -46,10 +46,10 @@ from shoppingcart.models import (
PaidCourseRegistration,
RegistrationCodeRedemption
)
from shoppingcart.processors import render_purchase_form_html
from shoppingcart.processors.CyberSource2 import sign
from shoppingcart.tests.payment_fake import PaymentFakeView
from shoppingcart.views import _can_download_report, _get_date_from_str, initialize_report
from ..processors import render_purchase_form_html
from ..processors.CyberSource2 import sign
from ..tests.payment_fake import PaymentFakeView
from ..views import _can_download_report, _get_date_from_str, initialize_report
from student.models import CourseEnrollment
from student.roles import CourseSalesAdminRole
from student.tests.factories import AdminFactory, UserFactory
@@ -204,7 +204,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
resp = self.client.post(reverse('add_course_to_cart', args=[text_type(self.course_key)]))
self.assertEqual(resp.status_code, 403)
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_billing_details(self):
billing_url = reverse('billing_details')
self.login_user()
@@ -235,7 +235,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
resp = self.client.post(billing_url, data)
self.assertEqual(resp.status_code, 200)
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
@override_settings(PAID_COURSE_REGISTRATION_CURRENCY=['PKR', 'Rs'])
def test_billing_details_with_override_currency_settings(self):
billing_url = reverse('billing_details')
@@ -668,7 +668,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
current_enrollment, __ = CourseEnrollment.enrollment_mode_for_user(self.user, self.course_key)
self.assertEqual('verified', current_enrollment)
@patch('shoppingcart.views.log.debug')
@patch('lms.djangoapps.shoppingcart.views.log.debug')
def test_non_existing_coupon_redemption_on_removing_item(self, debug_log):
reg_item = self.add_course_to_user_cart(self.course_key)
@@ -682,7 +682,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
self.assertEqual(resp.status_code, 200)
self.assertEqual(self.cart.orderitem_set.count(), 0)
@patch('shoppingcart.views.log.info')
@patch('lms.djangoapps.shoppingcart.views.log.info')
def test_existing_coupon_redemption_on_removing_item(self, info_log):
self.add_coupon(self.course_key, True, self.coupon_code)
@@ -703,7 +703,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
str(reg_item.id)
)
@patch('shoppingcart.views.log.info')
@patch('lms.djangoapps.shoppingcart.views.log.info')
def test_reset_redemption_for_coupon(self, info_log):
self.add_coupon(self.course_key, True, self.coupon_code)
@@ -721,7 +721,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
reg_item.id
)
@patch('shoppingcart.views.log.info')
@patch('lms.djangoapps.shoppingcart.views.log.info')
def test_coupon_discount_for_multiple_courses_in_cart(self, info_log):
reg_item = self.add_course_to_user_cart(self.course_key)
@@ -756,7 +756,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
str(reg_item.id)
)
@patch('shoppingcart.views.log.info')
@patch('lms.djangoapps.shoppingcart.views.log.info')
def test_delete_certificate_item(self, info_log):
self.add_course_to_user_cart(self.course_key)
@@ -772,7 +772,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
self.assertEqual(self.cart.orderitem_set.count(), 1)
info_log.assert_called_with(u"order item %s removed for user %s", str(cert_item.id), self.user)
@patch('shoppingcart.views.log.info')
@patch('lms.djangoapps.shoppingcart.views.log.info')
def test_remove_coupon_redemption_on_clear_cart(self, info_log):
reg_item = self.add_course_to_user_cart(self.course_key)
@@ -815,8 +815,8 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
self.assertEqual(resp.status_code, 200)
self.assertTrue(PaidCourseRegistration.contained_in_order(self.cart, self.course_key))
@patch('shoppingcart.views.render_purchase_form_html', form_mock)
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_purchase_form_html', form_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_show_cart(self):
self.login_user()
reg_item = PaidCourseRegistration.add_to_order(
@@ -848,8 +848,8 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
self.assertEqual(context['currency'], 'usd')
self.assertEqual(context['currency_symbol'], '$')
@patch('shoppingcart.views.render_purchase_form_html', form_mock)
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_purchase_form_html', form_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
@override_settings(PAID_COURSE_REGISTRATION_CURRENCY=['PKR', 'Rs'])
def test_show_cart_with_override_currency_settings(self):
self.login_user()
@@ -876,7 +876,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
self.assertEqual(resp.status_code, 200)
self.assertEqual(self.cart.orderitem_set.count(), 0)
@patch('shoppingcart.views.log.exception')
@patch('lms.djangoapps.shoppingcart.views.log.exception')
def test_remove_item(self, exception_log):
self.login_user()
reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_key)
@@ -906,7 +906,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
'-1'
)
@patch('shoppingcart.views.process_postpay_callback', postpay_mock)
@patch('lms.djangoapps.shoppingcart.views.process_postpay_callback', postpay_mock)
def test_postpay_callback_success(self):
postpay_mock.return_value = {'success': True, 'order': self.cart}
self.login_user()
@@ -915,8 +915,8 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
self.assertEqual(urlparse(resp.__getitem__('location')).path,
reverse('shoppingcart.views.show_receipt', args=[self.cart.id]))
@patch('shoppingcart.views.process_postpay_callback', postpay_mock)
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.process_postpay_callback', postpay_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_postpay_callback_failure(self):
postpay_mock.return_value = {'success': False, 'order': self.cart, 'error_html': 'ERROR_TEST!!!'}
self.login_user()
@@ -977,7 +977,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
resp = self.client.get(url)
self.assert_no_xss(resp, '<script>alert("XSS")</script>')
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_reg_code_xss(self):
self.add_reg_code(self.xss_course_key)
@@ -1099,7 +1099,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
total_amount = PaidCourseRegistration.get_total_amount_of_purchased_item(self.course_key)
self.assertEqual(total_amount, 76)
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_show_receipt_success_with_valid_coupon_code(self):
self.add_course_to_user_cart(self.course_key)
self.add_coupon(self.course_key, True, self.coupon_code)
@@ -1112,7 +1112,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
self.assertContains(resp, 'FirstNameTesting123')
self.assertContains(resp, str(self.get_discount(self.cost)))
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_reg_code_and_course_registration_scenario(self):
self.add_reg_code(self.course_key)
@@ -1133,7 +1133,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
response = self.client.post(redeem_url)
self.assertEqual(response.status_code, 200)
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_reg_code_with_multiple_courses_and_checkout_scenario(self):
self.add_reg_code(self.course_key)
@@ -1182,7 +1182,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
self.assertIsNotNone(item2.course_enrollment)
self.assertEqual(item2.course_enrollment.course_id, self.testing_course.id)
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_show_receipt_success_with_valid_reg_code(self):
self.add_course_to_user_cart(self.course_key)
self.add_reg_code(self.course_key)
@@ -1194,7 +1194,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
resp = self.client.get(reverse('shoppingcart.views.show_receipt', args=[self.cart.id]))
self.assertContains(resp, '0.00')
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_show_receipt_success(self):
reg_item = PaidCourseRegistration.add_to_order(
self.cart,
@@ -1220,7 +1220,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
self.assertEqual(context['currency'], 'usd')
@override_settings(PAID_COURSE_REGISTRATION_CURRENCY=['PKR', 'Rs'])
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_show_receipt_success_with_override_currency_settings(self):
reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_key)
cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor')
@@ -1239,7 +1239,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
self.assertEqual(context['currency_symbol'], 'Rs')
self.assertEqual(context['currency'], 'PKR')
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_show_receipt_success_with_upgrade(self):
reg_item = PaidCourseRegistration.add_to_order(
@@ -1268,7 +1268,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
self.assertIn(cert_item, context['shoppingcart_items'][1])
self.assertFalse(context['any_refunds'])
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_show_receipt_success_refund(self):
reg_item = PaidCourseRegistration.add_to_order(
self.cart,
@@ -1291,7 +1291,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
self.assertIn(cert_item, context['shoppingcart_items'][1])
self.assertTrue(context['any_refunds'])
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_show_receipt_success_custom_receipt_page(self):
cert_item = CertificateItem.add_to_order(self.cart, self.course_key, self.cost, 'honor')
self.cart.purchase()
@@ -1432,7 +1432,7 @@ class ReceiptRedirectTest(SharedModuleStoreTestCase):
self.cart.start_purchase()
# Simulate hitting the post-pay callback
with patch('shoppingcart.views.process_postpay_callback') as mock_process:
with patch('lms.djangoapps.shoppingcart.views.process_postpay_callback') as mock_process:
mock_process.return_value = {'success': True, 'order': self.cart}
url = reverse('shoppingcart.views.postpay_callback')
resp = self.client.post(url, follow=True)
@@ -1510,7 +1510,7 @@ class ShoppingcartViewsClosedEnrollment(ModuleStoreTestCase):
"""
self.client.login(username=self.user.username, password="password")
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_to_check_that_cart_item_enrollment_is_closed(self):
self.login_user()
reg_item1 = PaidCourseRegistration.add_to_order(self.cart, self.course_key)
@@ -1911,7 +1911,7 @@ class CSVReportViewsTest(SharedModuleStoreTestCase):
response = self.client.put(reverse('payment_csv_report'))
self.assertEqual(response.status_code, 400)
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_report_csv_get(self):
self.login_user()
self.add_to_download_group(self.user)
@@ -1923,7 +1923,7 @@ class CSVReportViewsTest(SharedModuleStoreTestCase):
self.assertFalse(context['date_fmt_error'])
self.assertContains(response, "Download CSV Reports")
@patch('shoppingcart.views.render_to_response', render_mock)
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
def test_report_csv_bad_date(self):
self.login_user()
self.add_to_download_group(self.user)

View File

@@ -6,7 +6,7 @@ Defines the shoppingcart URLs
from django.conf import settings
from django.conf.urls import url
from shoppingcart import views
from . import views
urlpatterns = [
# Both the ~accept and ~reject callback pages are handled here

View File

@@ -430,7 +430,7 @@ class SupportViewEnrollmentsTests(SharedModuleStoreTestCase, SupportViewTestCase
kwargs={'username_or_email': getattr(self.student, search_string_type)}
)
with patch('support.views.enrollments.get_credit_provider_attribute_values') as mock_method:
with patch('lms.djangoapps.support.views.enrollments.get_credit_provider_attribute_values') as mock_method:
credit_provider = (
[u'Arizona State University'], 'You are now eligible for credit from Arizona State University'
)
@@ -469,7 +469,7 @@ class SupportViewLinkProgramEnrollmentsTests(SupportViewTestCase):
Tests for the link_program_enrollments support view.
"""
patch_render = patch(
'support.views.program_enrollments.render_to_response',
'lms.djangoapps.support.views.program_enrollments.render_to_response',
return_value=HttpResponse(),
autospec=True,
)
@@ -537,7 +537,7 @@ class SupportViewLinkProgramEnrollmentsTests(SupportViewTestCase):
'0001,learner-01,apple,orange\n0002,learner-02,purple', # extra fields
'\t0001 , \t learner-01 \n 0002 , learner-02 ', # whitespace
)
@patch('support.views.program_enrollments.link_program_enrollments')
@patch('lms.djangoapps.support.views.program_enrollments.link_program_enrollments')
def test_text(self, text, mocked_link):
self.client.post(self.url, data={
'program_uuid': self.program_uuid,
@@ -638,7 +638,7 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase):
View tests for Program Enrollments Inspector
"""
patch_render = patch(
'support.views.program_enrollments.render_to_response',
'lms.djangoapps.support.views.program_enrollments.render_to_response',
return_value=HttpResponse(),
autospec=True,
)

View File

@@ -5,15 +5,15 @@ URLs for the student support app.
from django.conf.urls import url
from lms.djangoapps.support.views.contact_us import ContactUsView
from support.views.certificate import CertificatesSupportView
from support.views.course_entitlements import EntitlementSupportView
from support.views.enrollments import EnrollmentSupportListView, EnrollmentSupportView
from support.views.feature_based_enrollments import FeatureBasedEnrollmentsSupportView
from support.views.index import index
from support.views.manage_user import ManageUserDetailView, ManageUserSupportView
from support.views.program_enrollments import LinkProgramEnrollmentSupportView, ProgramEnrollmentsInspectorView
from support.views.sso_records import SsoView
from .views.contact_us import ContactUsView
from .views.certificate import CertificatesSupportView
from .views.course_entitlements import EntitlementSupportView
from .views.enrollments import EnrollmentSupportListView, EnrollmentSupportView
from .views.feature_based_enrollments import FeatureBasedEnrollmentsSupportView
from .views.index import index
from .views.manage_user import ManageUserDetailView, ManageUserSupportView
from .views.program_enrollments import LinkProgramEnrollmentSupportView, ProgramEnrollmentsInspectorView
from .views.sso_records import SsoView
COURSE_ENTITLEMENTS_VIEW = EntitlementSupportView.as_view()

View File

@@ -16,7 +16,7 @@ class SoftwareSecureFakeViewTest(UrlResetMixin, TestCase):
Base class to test the fake software secure view.
"""
URLCONF_MODULES = ['verify_student.urls']
URLCONF_MODULES = ['lms.djangoapps.verify_student.urls']
def setUp(self, **kwargs):
enable_software_secure_fake = kwargs.get('enable_software_secure_fake', False)

View File

@@ -21,6 +21,7 @@ from django.utils.translation import ugettext_lazy
from path import Path as path
from openedx.core.release import RELEASE_LINE
from xmodule.modulestore.modulestore_settings import update_module_store_settings
CONFIG_ROOT = path(__file__).abspath().dirname()
TEST_ROOT = CONFIG_ROOT.dirname().dirname() / "test_root"

View File

@@ -52,8 +52,6 @@ from openedx.core.djangoapps.theming.helpers_dirs import (
)
from openedx.core.lib.derived import derived, derived_collection_entry
from openedx.core.release import doc_version
from xmodule.modulestore.modulestore_settings import update_module_store_settings
from xmodule.modulestore.edit_info import EditInfoMixin
from lms.djangoapps.lms_xblock.mixin import LmsBlockMixin
################################### FEATURES ###################################
@@ -724,7 +722,7 @@ DATA_DIR = COURSES_ROOT
# TODO: Remove the rest of the sys.path modification here and in cms/envs/common.py
sys.path.append(REPO_ROOT)
sys.path.append(PROJECT_ROOT / 'djangoapps')
sys.path.append(REPO_ROOT / 'sys_path_hacks' / 'lms')
sys.path.append(COMMON_ROOT / 'djangoapps')
# For Node.js
@@ -1169,9 +1167,12 @@ COURSE_LISTINGS = {}
############# XBlock Configuration ##########
# Import after sys.path fixup
# pylint: disable=wrong-import-position
from xmodule.modulestore.edit_info import EditInfoMixin
from xmodule.modulestore.inheritance import InheritanceMixin
from xmodule.modulestore import prefer_xmodules
from xmodule.x_module import XModuleMixin
# pylint: enable=wrong-import-position
# These are the Mixins that should be added to every XBlock.
# This should be moved into an XBlock Runtime/Application object
@@ -2483,26 +2484,26 @@ INSTALLED_APPS = [
# Our courseware
'lms.djangoapps.courseware',
'coursewarehistoryextended',
'lms.djangoapps.coursewarehistoryextended',
'student.apps.StudentConfig',
'static_template_view',
'staticbook',
'lms.djangoapps.static_template_view',
'lms.djangoapps.staticbook',
'track',
'eventtracking.django.apps.EventTrackingConfig',
'util',
'lms.djangoapps.certificates.apps.CertificatesConfig',
'dashboard',
'lms.djangoapps.dashboard',
'lms.djangoapps.instructor_task',
'openedx.core.djangoapps.course_groups',
'bulk_email',
'branding',
'lms.djangoapps.bulk_email',
'lms.djangoapps.branding',
# New (Blockstore-based) XBlock runtime
'openedx.core.djangoapps.xblock.apps.LmsXBlockAppConfig',
# Student support tools
'support',
'lms.djangoapps.support',
# django-oauth-toolkit
'oauth2_provider',
@@ -2518,7 +2519,7 @@ INSTALLED_APPS = [
# For the wiki
'wiki', # The new django-wiki from benjaoming
'django_notify',
'course_wiki', # Our customizations
'lms.djangoapps.course_wiki', # Our customizations
'mptt',
'sekizai',
#'wiki.plugins.attachments',
@@ -2527,18 +2528,18 @@ INSTALLED_APPS = [
# got tangled up during the Django 1.8 migration, so we are disabling it.
# See TNL-3783 for details.
#'wiki.plugins.notifications',
'course_wiki.plugins.markdownedx',
'lms.djangoapps.course_wiki.plugins.markdownedx',
# For testing
'django.contrib.admin', # only used in DEBUG mode
'debug',
'lms.djangoapps.debug',
'openedx.core.djangoapps.util.apps.UtilConfig',
# Discussion forums
'openedx.core.djangoapps.django_comment_common',
# Notes
'edxnotes',
'lms.djangoapps.edxnotes',
# Splash screen
'splash',
@@ -2549,7 +2550,7 @@ INSTALLED_APPS = [
'openedx.core.djangoapps.user_api',
# Shopping cart
'shoppingcart',
'lms.djangoapps.shoppingcart',
# Different Course Modes
'course_modes.apps.CourseModesConfig',
@@ -2561,7 +2562,7 @@ INSTALLED_APPS = [
'entitlements.apps.EntitlementsConfig',
# Bulk Enrollment API
'bulk_enroll',
'lms.djangoapps.bulk_enroll',
# Student Identity Verification
'lms.djangoapps.verify_student.apps.VerifyStudentConfig',
@@ -2570,7 +2571,7 @@ INSTALLED_APPS = [
'openedx.core.djangoapps.dark_lang',
# RSS Proxy
'rss_proxy',
'lms.djangoapps.rss_proxy',
# Country embargo support
'openedx.core.djangoapps.embargo',
@@ -2649,7 +2650,7 @@ INSTALLED_APPS = [
'learner_dashboard',
# Needed whether or not enabled, due to migrations
'badges.apps.BadgesConfig',
'lms.djangoapps.badges.apps.BadgesConfig',
# Enables default site and redirects
'django_sites_extensions',
@@ -2690,7 +2691,7 @@ INSTALLED_APPS = [
'openedx.features.content_type_gating',
'openedx.features.discounts',
'experiments',
'lms.djangoapps.experiments',
# DRF filters
'django_filters',

View File

@@ -771,8 +771,8 @@ CREDIT_PROVIDER_SECRET_KEYS = AUTH_TOKENS.get("CREDIT_PROVIDER_SECRET_KEYS", {})
##################### LTI Provider #####################
if FEATURES.get('ENABLE_LTI_PROVIDER'):
INSTALLED_APPS.append('lti_provider.apps.LtiProviderConfig')
AUTHENTICATION_BACKENDS.append('lti_provider.users.LtiBackend')
INSTALLED_APPS.append('lms.djangoapps.lti_provider.apps.LtiProviderConfig')
AUTHENTICATION_BACKENDS.append('lms.djangoapps.lti_provider.users.LtiBackend')
LTI_USER_EMAIL_DOMAIN = ENV_TOKENS.get('LTI_USER_EMAIL_DOMAIN', 'lti.example.com')

View File

@@ -30,6 +30,7 @@ from six.moves import range
from openedx.core.djangoapps.plugins.constants import ProjectType, SettingsType
from openedx.core.lib.derived import derive_settings
from openedx.core.lib.tempdir import mkdtemp_clean
from xmodule.modulestore.modulestore_settings import update_module_store_settings
from .common import *

View File

@@ -13,8 +13,8 @@ from edx_api_doc_tools import make_docs_urls
from edx_django_utils.plugins import get_plugin_url_patterns
from ratelimitbackend import admin
from branding import views as branding_views
from debug import views as debug_views
from lms.djangoapps.branding import views as branding_views
from lms.djangoapps.debug import views as debug_views
from lms.djangoapps.certificates import views as certificates_views
from lms.djangoapps.courseware.masquerade import MasqueradeView
from lms.djangoapps.courseware.module_render import (
@@ -31,6 +31,8 @@ from lms.djangoapps.discussion.config.settings import is_forum_daily_digest_enab
from lms.djangoapps.discussion.notification_prefs import views as notification_prefs_views
from lms.djangoapps.instructor.views import instructor_dashboard as instructor_dashboard_views
from lms.djangoapps.instructor_task import views as instructor_task_views
from lms.djangoapps.staticbook import views as staticbook_views
from lms.djangoapps.static_template_view import views as static_template_view_views
from openedx.core.apidocs import api_info
from openedx.core.djangoapps.auth_exchange.views import LoginWithAccessTokenView
from openedx.core.djangoapps.catalog.models import CatalogIntegration
@@ -49,8 +51,6 @@ from openedx.core.djangoapps.site_configuration import helpers as configuration_
from openedx.core.djangoapps.user_authn.views.login import redirect_to_lms_login
from openedx.core.djangoapps.verified_track_content import views as verified_track_content_views
from openedx.features.enterprise_support.api import enterprise_enabled
from static_template_view import views as static_template_view_views
from staticbook import views as staticbook_views
from student import views as student_views
from util import views as util_views
@@ -159,7 +159,7 @@ urlpatterns = [
url(r'^api/course_modes/', include(('course_modes.rest_api.urls', 'common.djangoapps.course_mods'),
namespace='course_modes_api')),
url(r'^verify_student/', include('verify_student.urls')),
url(r'^verify_student/', include('lms.djangoapps.verify_student.urls')),
# URLs for managing dark launches of languages
url(r'^update_lang/', include(('openedx.core.djangoapps.dark_lang.urls', 'openedx.core.djangoapps.dark_lang'),
@@ -212,7 +212,7 @@ urlpatterns += [
# the custom tab catch-all)
if settings.WIKI_ENABLED:
from wiki.urls import get_pattern as wiki_pattern
from course_wiki import views as course_wiki_views
from lms.djangoapps.course_wiki import views as course_wiki_views
from django_notify.urls import get_pattern as notify_pattern
wiki_url_patterns, wiki_app_name = wiki_pattern()
@@ -854,7 +854,7 @@ if settings.FEATURES.get('ENABLE_OAUTH2_PROVIDER'):
# Certificates
urlpatterns += [
url(r'^certificates/', include('certificates.urls')),
url(r'^certificates/', include('lms.djangoapps.certificates.urls')),
# Backwards compatibility with XQueue, which uses URLs that are not prefixed with /certificates/
url(r'^update_certificate$', certificates_views.update_certificate, name='update_certificate'),
@@ -885,7 +885,7 @@ if settings.FEATURES.get('CUSTOM_COURSES_EDX'):
# Access to courseware as an LTI provider
if settings.FEATURES.get('ENABLE_LTI_PROVIDER'):
urlpatterns += [
url(r'^lti_provider/', include('lti_provider.urls')),
url(r'^lti_provider/', include('lms.djangoapps.lti_provider.urls')),
]
urlpatterns += [

View File

@@ -13,7 +13,7 @@ from path import Path
# TODO: Remove the rest of the sys.path modification here and in (cms|lms)/envs/common.py
REPO_ROOT = Path(__file__).abspath().dirname().dirname().dirname() # /edx-platform/
sys.path.append(REPO_ROOT / 'common' / 'djangoapps')
sys.path.append(REPO_ROOT / 'lms' / 'djangoapps')
sys.path.append(REPO_ROOT / 'sys_path_hacks' / 'lms')
ALL_LANGUAGES = []
@@ -90,7 +90,7 @@ INSTALLED_APPS = (
'openedx.core.djangoapps.external_user_ids',
'openedx.core.djangoapps.demographics',
'experiments',
'lms.djangoapps.experiments',
'openedx.features.content_type_gating',
'openedx.features.course_duration_limits',
'openedx.features.discounts',

View File

@@ -1,4 +0,0 @@
import warnings
warnings.warn("Importing courseware.management.commands.import instead of lms.djangoapps.courseware.management.commands.import is deprecated", stacklevel=2)
from lms.djangoapps.courseware.management.commands.import import *