From 6672f6418826fcac783c99ddd39f56b7a0d11d30 Mon Sep 17 00:00:00 2001 From: John Eskew Date: Fri, 3 Nov 2017 14:36:56 -0400 Subject: [PATCH 1/2] Add commerce AppConfig and use to register signals. Move imports. Add explicit 'lms.djangoapps' prefix to all commerce imports, as another commerce Django app exists at openedx.core.djangoapps.commerce --- .../djangoapps/student/tests/test_refunds.py | 2 +- common/djangoapps/student/tests/test_views.py | 2 +- lms/djangoapps/commerce/__init__.py | 3 -- lms/djangoapps/commerce/admin.py | 2 +- lms/djangoapps/commerce/api/urls.py | 4 +-- .../commerce/api/v0/tests/test_views.py | 11 +++--- lms/djangoapps/commerce/api/v0/urls.py | 2 +- lms/djangoapps/commerce/api/v0/views.py | 4 +-- lms/djangoapps/commerce/api/v1/permissions.py | 2 +- lms/djangoapps/commerce/api/v1/serializers.py | 2 +- .../commerce/api/v1/tests/test_models.py | 2 +- .../commerce/api/v1/tests/test_serializers.py | 2 +- .../commerce/api/v1/tests/test_views.py | 4 +-- lms/djangoapps/commerce/api/v1/urls.py | 3 +- lms/djangoapps/commerce/api/v1/views.py | 8 ++--- lms/djangoapps/commerce/apps.py | 17 +++++++++ .../management/commands/configure_commerce.py | 2 +- .../commands/tests/test_configure_commerce.py | 2 +- lms/djangoapps/commerce/signals.py | 11 ++---- lms/djangoapps/commerce/tests/mocks.py | 2 +- lms/djangoapps/commerce/tests/test_signals.py | 36 ++++++++++--------- lms/djangoapps/commerce/tests/test_utils.py | 4 +-- lms/djangoapps/commerce/tests/test_views.py | 2 +- lms/djangoapps/commerce/urls.py | 2 +- lms/djangoapps/commerce/utils.py | 2 +- lms/djangoapps/commerce/views.py | 2 +- .../courseware/tests/test_date_summary.py | 2 +- lms/djangoapps/courseware/tests/test_views.py | 2 +- lms/djangoapps/courseware/views/views.py | 2 +- lms/djangoapps/instructor/services.py | 2 +- lms/djangoapps/learner_dashboard/views.py | 2 +- .../student_account/test/test_views.py | 6 ++-- lms/djangoapps/student_account/views.py | 2 +- .../verify_student/tests/test_views.py | 6 ++-- lms/djangoapps/verify_student/views.py | 2 +- lms/envs/common.py | 2 +- lms/urls.py | 2 +- .../commands/tests/send_email_base.py | 2 +- .../tests/views/test_course_home.py | 4 +-- .../tests/views/test_course_sock.py | 2 +- .../course_experience/views/course_home.py | 2 +- 41 files changed, 94 insertions(+), 81 deletions(-) create mode 100644 lms/djangoapps/commerce/apps.py diff --git a/common/djangoapps/student/tests/test_refunds.py b/common/djangoapps/student/tests/test_refunds.py index 38d089bf93..79f31e3b95 100644 --- a/common/djangoapps/student/tests/test_refunds.py +++ b/common/djangoapps/student/tests/test_refunds.py @@ -203,7 +203,7 @@ class RefundableTest(SharedModuleStoreTestCase): raised while getting order detail for ecommerce. """ # importing this after overriding value of ECOMMERCE_API_URL - from commerce.tests.mocks import mock_order_endpoint + from lms.djangoapps.commerce.tests.mocks import mock_order_endpoint self.client.login(username=self.user.username, password=self.USER_PASSWORD) with mock_order_endpoint(order_number=self.ORDER_NUMBER, exception=exception, reset_on_exit=False): diff --git a/common/djangoapps/student/tests/test_views.py b/common/djangoapps/student/tests/test_views.py index 790cafd809..c4d70d6425 100644 --- a/common/djangoapps/student/tests/test_views.py +++ b/common/djangoapps/student/tests/test_views.py @@ -95,7 +95,7 @@ class TestStudentDashboardUnenrollments(SharedModuleStoreTestCase): self.cert_status = cert_status with patch('student.views.cert_info', side_effect=self.mock_cert): - with patch('commerce.signals.handle_refund_order') as mock_refund_handler: + with patch('lms.djangoapps.commerce.signals.handle_refund_order') as mock_refund_handler: REFUND_ORDER.connect(mock_refund_handler) response = self.client.post( reverse('change_enrollment'), diff --git a/lms/djangoapps/commerce/__init__.py b/lms/djangoapps/commerce/__init__.py index a02aabc656..e69de29bb2 100644 --- a/lms/djangoapps/commerce/__init__.py +++ b/lms/djangoapps/commerce/__init__.py @@ -1,3 +0,0 @@ -""" Commerce app. """ -# this is here to support registering the signals in signals.py -from commerce import signals diff --git a/lms/djangoapps/commerce/admin.py b/lms/djangoapps/commerce/admin.py index c5c178183a..420e174900 100644 --- a/lms/djangoapps/commerce/admin.py +++ b/lms/djangoapps/commerce/admin.py @@ -3,6 +3,6 @@ from config_models.admin import ConfigurationModelAdmin from django.contrib import admin -from commerce.models import CommerceConfiguration +from .models import CommerceConfiguration admin.site.register(CommerceConfiguration, ConfigurationModelAdmin) diff --git a/lms/djangoapps/commerce/api/urls.py b/lms/djangoapps/commerce/api/urls.py index a8715a738d..af1a1dde5b 100644 --- a/lms/djangoapps/commerce/api/urls.py +++ b/lms/djangoapps/commerce/api/urls.py @@ -4,6 +4,6 @@ API URLs. from django.conf.urls import include, url urlpatterns = [ - url(r'^v0/', include('commerce.api.v0.urls', namespace='v0')), - url(r'^v1/', include('commerce.api.v1.urls', namespace='v1')), + url(r'^v0/', include('lms.djangoapps.commerce.api.v0.urls', namespace='v0')), + url(r'^v1/', include('lms.djangoapps.commerce.api.v1.urls', namespace='v1')), ] diff --git a/lms/djangoapps/commerce/api/v0/tests/test_views.py b/lms/djangoapps/commerce/api/v0/tests/test_views.py index 2e2a864130..52aa0e3d5f 100644 --- a/lms/djangoapps/commerce/api/v0/tests/test_views.py +++ b/lms/djangoapps/commerce/api/v0/tests/test_views.py @@ -14,12 +14,13 @@ from django.test.utils import override_settings from edx_rest_api_client import exceptions from nose.plugins.attrib import attr -from commerce.api.v0.views import SAILTHRU_CAMPAIGN_COOKIE -from commerce.constants import Messages -from commerce.tests.mocks import mock_basket_order -from commerce.tests.test_views import UserMixin from course_modes.models import CourseMode +from course_modes.tests.factories import CourseModeFactory from enrollment.api import get_enrollment +from ..views import SAILTHRU_CAMPAIGN_COOKIE +from ....constants import Messages +from ....tests.mocks import mock_basket_order +from ....tests.test_views import UserMixin from openedx.core.djangoapps.embargo.test_utils import restrict_course from openedx.core.lib.django_test_client_utils import get_absolute_url from student.models import CourseEnrollment @@ -250,7 +251,7 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase) self.assertFalse(CourseEnrollment.is_enrolled(self.user, self.course.id)) self.assertIsNotNone(get_enrollment(self.user.username, unicode(self.course.id))) - @mock.patch('commerce.api.v0.views.update_email_opt_in') + @mock.patch('lms.djangoapps.commerce.api.v0.views.update_email_opt_in') @ddt.data(*itertools.product((False, True), (False, True), (False, True))) @ddt.unpack def test_marketing_email_opt_in(self, is_opt_in, has_sku, is_exception, mock_update): diff --git a/lms/djangoapps/commerce/api/v0/urls.py b/lms/djangoapps/commerce/api/v0/urls.py index 601df846e8..b6df78845c 100644 --- a/lms/djangoapps/commerce/api/v0/urls.py +++ b/lms/djangoapps/commerce/api/v0/urls.py @@ -3,7 +3,7 @@ API v0 URLs. """ from django.conf.urls import include, url -from commerce.api.v0 import views +from . import views BASKET_URLS = [ url(r'^$', views.BasketsView.as_view(), name='create'), diff --git a/lms/djangoapps/commerce/api/v0/views.py b/lms/djangoapps/commerce/api/v0/views.py index 181cf81ed4..ee91ac2cf5 100644 --- a/lms/djangoapps/commerce/api/v0/views.py +++ b/lms/djangoapps/commerce/api/v0/views.py @@ -9,12 +9,12 @@ from rest_framework.permissions import IsAuthenticated from rest_framework.status import HTTP_406_NOT_ACCEPTABLE, HTTP_409_CONFLICT from rest_framework.views import APIView -from commerce.constants import Messages -from commerce.http import DetailResponse from course_modes.models import CourseMode from courseware import courses from enrollment.api import add_enrollment from enrollment.views import EnrollmentCrossDomainSessionAuth +from ...constants import Messages +from ...http import DetailResponse from openedx.core.djangoapps.commerce.utils import ecommerce_api_client from openedx.core.djangoapps.embargo import api as embargo_api from openedx.core.djangoapps.user_api.preferences.api import update_email_opt_in diff --git a/lms/djangoapps/commerce/api/v1/permissions.py b/lms/djangoapps/commerce/api/v1/permissions.py index 629f5835dc..81298bbd8e 100644 --- a/lms/djangoapps/commerce/api/v1/permissions.py +++ b/lms/djangoapps/commerce/api/v1/permissions.py @@ -3,7 +3,7 @@ from django.conf import settings from django.contrib.auth.models import User from rest_framework.permissions import BasePermission, DjangoModelPermissions -from commerce.utils import is_account_activation_requirement_disabled +from ...utils import is_account_activation_requirement_disabled from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.lib.api.permissions import ApiKeyHeaderPermission diff --git a/lms/djangoapps/commerce/api/v1/serializers.py b/lms/djangoapps/commerce/api/v1/serializers.py index c1a4645c6c..6825b5a9b8 100644 --- a/lms/djangoapps/commerce/api/v1/serializers.py +++ b/lms/djangoapps/commerce/api/v1/serializers.py @@ -7,8 +7,8 @@ from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey from rest_framework import serializers -from commerce.api.v1.models import Course from course_modes.models import CourseMode +from .models import Course from xmodule.modulestore.django import modulestore diff --git a/lms/djangoapps/commerce/api/v1/tests/test_models.py b/lms/djangoapps/commerce/api/v1/tests/test_models.py index 16c40acaaf..575c773774 100644 --- a/lms/djangoapps/commerce/api/v1/tests/test_models.py +++ b/lms/djangoapps/commerce/api/v1/tests/test_models.py @@ -2,8 +2,8 @@ import ddt from django.test import TestCase -from commerce.api.v1.models import Course from course_modes.models import CourseMode +from ..models import Course @ddt.ddt diff --git a/lms/djangoapps/commerce/api/v1/tests/test_serializers.py b/lms/djangoapps/commerce/api/v1/tests/test_serializers.py index 93bcb9aee3..c17b069122 100644 --- a/lms/djangoapps/commerce/api/v1/tests/test_serializers.py +++ b/lms/djangoapps/commerce/api/v1/tests/test_serializers.py @@ -1,7 +1,7 @@ """ Commerce API v1 serializer tests. """ from django.test import TestCase -from commerce.api.v1.serializers import serializers, validate_course_id +from ..serializers import serializers, validate_course_id class CourseValidatorTests(TestCase): diff --git a/lms/djangoapps/commerce/api/v1/tests/test_views.py b/lms/djangoapps/commerce/api/v1/tests/test_views.py index 177d1ea9f3..1bc4e3e710 100644 --- a/lms/djangoapps/commerce/api/v1/tests/test_views.py +++ b/lms/djangoapps/commerce/api/v1/tests/test_views.py @@ -14,9 +14,9 @@ from edx_rest_api_client import exceptions from nose.plugins.attrib import attr from rest_framework.utils.encoders import JSONEncoder -from commerce.tests.mocks import mock_order_endpoint -from commerce.tests.test_views import UserMixin from course_modes.models import CourseMode +from ....tests.mocks import mock_order_endpoint +from ....tests.test_views import UserMixin from lms.djangoapps.verify_student.models import VerificationDeadline from student.tests.factories import UserFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase diff --git a/lms/djangoapps/commerce/api/v1/urls.py b/lms/djangoapps/commerce/api/v1/urls.py index e448701ea8..88a4de47b5 100644 --- a/lms/djangoapps/commerce/api/v1/urls.py +++ b/lms/djangoapps/commerce/api/v1/urls.py @@ -1,8 +1,7 @@ -""" API v1 URLs. """ from django.conf import settings from django.conf.urls import include, url -from commerce.api.v1 import views +from . import views COURSE_URLS = [ url(r'^$', views.CourseListView.as_view(), name='list'), diff --git a/lms/djangoapps/commerce/api/v1/views.py b/lms/djangoapps/commerce/api/v1/views.py index 5c25d991c4..39fae0b275 100644 --- a/lms/djangoapps/commerce/api/v1/views.py +++ b/lms/djangoapps/commerce/api/v1/views.py @@ -10,11 +10,11 @@ from rest_framework.permissions import IsAuthenticated from rest_framework.views import APIView from rest_framework_oauth.authentication import OAuth2Authentication -from commerce.api.v1.models import Course -from commerce.api.v1.permissions import ApiKeyOrModelPermission, IsAuthenticatedOrActivationOverridden -from commerce.api.v1.serializers import CourseSerializer -from commerce.utils import is_account_activation_requirement_disabled from course_modes.models import CourseMode +from .models import Course +from .permissions import ApiKeyOrModelPermission, IsAuthenticatedOrActivationOverridden +from .serializers import CourseSerializer +from ...utils import is_account_activation_requirement_disabled from openedx.core.djangoapps.commerce.utils import ecommerce_api_client from openedx.core.lib.api.mixins import PutAsCreateMixin from util.json_request import JsonResponse diff --git a/lms/djangoapps/commerce/apps.py b/lms/djangoapps/commerce/apps.py new file mode 100644 index 0000000000..d0bddaa323 --- /dev/null +++ b/lms/djangoapps/commerce/apps.py @@ -0,0 +1,17 @@ +""" +Commerce Application Configuration +""" +from django.apps import AppConfig + + +class CommerceConfig(AppConfig): + """ + Application Configuration for Commerce. + """ + name = 'lms.djangoapps.commerce' + + def ready(self): + """ + Connect handlers to signals. + """ + from . import signals # pylint: disable=unused-variable diff --git a/lms/djangoapps/commerce/management/commands/configure_commerce.py b/lms/djangoapps/commerce/management/commands/configure_commerce.py index 6b47a8814d..df27a5d3db 100644 --- a/lms/djangoapps/commerce/management/commands/configure_commerce.py +++ b/lms/djangoapps/commerce/management/commands/configure_commerce.py @@ -9,7 +9,7 @@ import logging from django.core.management import BaseCommand -from commerce.models import CommerceConfiguration +from ...models import CommerceConfiguration logger = logging.getLogger(__name__) # pylint: disable=invalid-name diff --git a/lms/djangoapps/commerce/management/commands/tests/test_configure_commerce.py b/lms/djangoapps/commerce/management/commands/tests/test_configure_commerce.py index 1e7791e5d6..a52e1d7d5e 100644 --- a/lms/djangoapps/commerce/management/commands/tests/test_configure_commerce.py +++ b/lms/djangoapps/commerce/management/commands/tests/test_configure_commerce.py @@ -4,7 +4,7 @@ Tests for management command for enabling commerce configuration. from django.core.management import call_command from django.test import TestCase -from commerce.models import CommerceConfiguration +from ....models import CommerceConfiguration class TestCommerceConfigurationCommand(TestCase): diff --git a/lms/djangoapps/commerce/signals.py b/lms/djangoapps/commerce/signals.py index 25cb10ebc1..46af858f23 100644 --- a/lms/djangoapps/commerce/signals.py +++ b/lms/djangoapps/commerce/signals.py @@ -10,9 +10,12 @@ from urlparse import urljoin import requests from django.conf import settings from django.contrib.auth import get_user_model +from django.contrib.auth.models import AnonymousUser from django.dispatch import receiver from django.utils.translation import ugettext as _ +from .models import CommerceConfiguration +from openedx.core.djangoapps.commerce.utils import ecommerce_api_client, is_commerce_service_configured from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.theming import helpers as theming_helpers from request_cache.middleware import RequestCache @@ -28,10 +31,6 @@ def handle_refund_order(sender, course_enrollment=None, **kwargs): Signal receiver for unenrollments, used to automatically initiate refunds when applicable. """ - # Import is placed here to avoid model import at project startup. - from django.contrib.auth.models import AnonymousUser - from openedx.core.djangoapps.commerce.utils import is_commerce_service_configured - if not is_commerce_service_configured(): return @@ -84,10 +83,6 @@ def refund_seat(course_enrollment): exceptions.SlumberBaseException: for any unhandled HTTP error during communication with the E-Commerce Service. exceptions.Timeout: if the attempt to reach the commerce service timed out. """ - # Import is placed here to avoid model import at project startup. - from commerce.models import CommerceConfiguration - from openedx.core.djangoapps.commerce.utils import ecommerce_api_client - User = get_user_model() # pylint:disable=invalid-name course_key_str = unicode(course_enrollment.course_id) enrollee = course_enrollment.user diff --git a/lms/djangoapps/commerce/tests/mocks.py b/lms/djangoapps/commerce/tests/mocks.py index 1ce677842a..a42be0021d 100644 --- a/lms/djangoapps/commerce/tests/mocks.py +++ b/lms/djangoapps/commerce/tests/mocks.py @@ -4,7 +4,7 @@ import json import httpretty from django.conf import settings -from commerce.tests import factories +from . import factories # pylint: disable=invalid-name diff --git a/lms/djangoapps/commerce/tests/test_signals.py b/lms/djangoapps/commerce/tests/test_signals.py index f74f1f2500..fb953edc82 100644 --- a/lms/djangoapps/commerce/tests/test_signals.py +++ b/lms/djangoapps/commerce/tests/test_signals.py @@ -18,11 +18,15 @@ from django.test.utils import override_settings from opaque_keys.edx.keys import CourseKey from requests import Timeout -from commerce.models import CommerceConfiguration -from commerce.signals import create_zendesk_ticket, generate_refund_notification_body, send_refund_notification -from commerce.tests import JSON -from commerce.tests.mocks import mock_create_refund, mock_process_refund from course_modes.models import CourseMode +from ..models import CommerceConfiguration +from ..signals import ( + create_zendesk_ticket, + generate_refund_notification_body, + send_refund_notification +) +from . import JSON +from .mocks import mock_create_refund, mock_process_refund from student.signals import REFUND_ORDER from student.tests.factories import CourseEnrollmentFactory, UserFactory @@ -76,11 +80,11 @@ class TestRefundSignal(TestCase): Ensure that the receiver quietly bypasses attempts to initiate refunds when there is no external service configured. """ - with mock.patch('commerce.signals.refund_seat') as mock_refund_seat: + with mock.patch('lms.djangoapps.commerce.signals.refund_seat') as mock_refund_seat: self.send_signal() self.assertFalse(mock_refund_seat.called) - @mock.patch('commerce.signals.refund_seat') + @mock.patch('lms.djangoapps.commerce.signals.refund_seat') def test_receiver(self, mock_refund_seat): """ Ensure that the REFUND_ORDER signal triggers correct calls to @@ -100,8 +104,8 @@ class TestRefundSignal(TestCase): self.send_signal() self.assertFalse(mock_refund_seat.called) - @mock.patch('commerce.signals.refund_seat') - @mock.patch('commerce.signals.get_request_user', return_value=None) + @mock.patch('lms.djangoapps.commerce.signals.refund_seat') + @mock.patch('lms.djangoapps.commerce.signals.get_request_user', return_value=None) def test_requester(self, mock_get_request_user, mock_refund_seat): """ Ensure the right requester is specified when initiating refunds. @@ -131,7 +135,7 @@ class TestRefundSignal(TestCase): self.send_signal() self.assertFalse(mock_refund_seat.called) - @mock.patch('commerce.signals.log.exception') + @mock.patch('lms.djangoapps.commerce.signals.log.exception') def test_error_logging(self, mock_log_exception): """ Ensure that unexpected Exceptions are logged as errors (but do not @@ -141,7 +145,7 @@ class TestRefundSignal(TestCase): self.send_signal() self.assertTrue(mock_log_exception.called) - @mock.patch('commerce.signals.send_refund_notification') + @mock.patch('lms.djangoapps.commerce.signals.send_refund_notification') def test_notification_when_approval_fails(self, mock_send_notification): """ Ensure the notification function is triggered when refunds are initiated, and cannot be automatically approved. @@ -156,7 +160,7 @@ class TestRefundSignal(TestCase): self.assertTrue(mock_send_notification.called) mock_send_notification.assert_called_with(self.course_enrollment, [failed_refund_id]) - @mock.patch('commerce.signals.send_refund_notification') + @mock.patch('lms.djangoapps.commerce.signals.send_refund_notification') def test_notification_if_automatic_approval_disabled(self, mock_send_notification): """ Ensure the notification is always sent if the automatic approval functionality is disabled. @@ -170,7 +174,7 @@ class TestRefundSignal(TestCase): self.assertTrue(mock_send_notification.called) mock_send_notification.assert_called_with(self.course_enrollment, [refund_id]) - @mock.patch('commerce.signals.send_refund_notification') + @mock.patch('lms.djangoapps.commerce.signals.send_refund_notification') def test_no_notification_after_approval(self, mock_send_notification): """ Ensure the notification function is triggered when refunds are initiated, and cannot be automatically approved. @@ -185,7 +189,7 @@ class TestRefundSignal(TestCase): last_request = httpretty.last_request() self.assertDictEqual(json.loads(last_request.body), {'action': 'approve_payment_only'}) - @mock.patch('commerce.signals.send_refund_notification') + @mock.patch('lms.djangoapps.commerce.signals.send_refund_notification') def test_notification_no_refund(self, mock_send_notification): """ Ensure the notification function is NOT triggered when no refunds are @@ -195,7 +199,7 @@ class TestRefundSignal(TestCase): self.send_signal() self.assertFalse(mock_send_notification.called) - @mock.patch('commerce.signals.send_refund_notification') + @mock.patch('lms.djangoapps.commerce.signals.send_refund_notification') @ddt.data( CourseMode.HONOR, CourseMode.PROFESSIONAL, @@ -216,8 +220,8 @@ class TestRefundSignal(TestCase): self.send_signal() self.assertFalse(mock_send_notification.called) - @mock.patch('commerce.signals.send_refund_notification', side_effect=Exception("Splat!")) - @mock.patch('commerce.signals.log.warning') + @mock.patch('lms.djangoapps.commerce.signals.send_refund_notification', side_effect=Exception("Splat!")) + @mock.patch('lms.djangoapps.commerce.signals.log.warning') def test_notification_error(self, mock_log_warning, mock_send_notification): """ Ensure an error occuring during notification does not break program diff --git a/lms/djangoapps/commerce/tests/test_utils.py b/lms/djangoapps/commerce/tests/test_utils.py index 145332fa80..c72fbe804a 100644 --- a/lms/djangoapps/commerce/tests/test_utils.py +++ b/lms/djangoapps/commerce/tests/test_utils.py @@ -9,8 +9,8 @@ from django.test.utils import override_settings from mock import patch from waffle.testutils import override_switch -from commerce.models import CommerceConfiguration -from commerce.utils import EcommerceService +from ..models import CommerceConfiguration +from ..utils import EcommerceService from openedx.core.lib.log_utils import audit_log from student.tests.factories import UserFactory diff --git a/lms/djangoapps/commerce/tests/test_views.py b/lms/djangoapps/commerce/tests/test_views.py index a2ec722840..601c13a743 100644 --- a/lms/djangoapps/commerce/tests/test_views.py +++ b/lms/djangoapps/commerce/tests/test_views.py @@ -109,7 +109,7 @@ class ReceiptViewTests(UserMixin, ModuleStoreTestCase): self.assertRegexpMatches(response.content, expected_pattern) @ddt.data(True, False) - @mock.patch('commerce.views.is_user_payment_error') + @mock.patch('lms.djangoapps.commerce.views.is_user_payment_error') def test_cybersource_message(self, is_user_message_expected, mock_is_user_payment_error): """ Ensure that the page displays the right message for the reason_code (it diff --git a/lms/djangoapps/commerce/urls.py b/lms/djangoapps/commerce/urls.py index b8c3774f82..eb0ded876a 100644 --- a/lms/djangoapps/commerce/urls.py +++ b/lms/djangoapps/commerce/urls.py @@ -3,7 +3,7 @@ Defines the URL routes for this app. """ from django.conf.urls import url -from commerce import views +from . import views urlpatterns = [ url(r'^checkout/cancel/$', views.checkout_cancel, name='checkout_cancel'), diff --git a/lms/djangoapps/commerce/utils.py b/lms/djangoapps/commerce/utils.py index daf83e4d0b..6a3419b626 100644 --- a/lms/djangoapps/commerce/utils.py +++ b/lms/djangoapps/commerce/utils.py @@ -7,7 +7,7 @@ from django.conf import settings from django.core.urlresolvers import reverse from student.models import CourseEnrollment -from commerce.models import CommerceConfiguration +from .models import CommerceConfiguration from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers diff --git a/lms/djangoapps/commerce/views.py b/lms/djangoapps/commerce/views.py index 5f41736f07..fd82a05fdd 100644 --- a/lms/djangoapps/commerce/views.py +++ b/lms/djangoapps/commerce/views.py @@ -10,9 +10,9 @@ from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_http_methods from opaque_keys.edx.locator import CourseLocator -from commerce.models import CommerceConfiguration from course_modes.models import CourseMode from edxmako.shortcuts import render_to_response +from .models import CommerceConfiguration from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.theming.helpers import is_request_in_themed_site diff --git a/lms/djangoapps/courseware/tests/test_date_summary.py b/lms/djangoapps/courseware/tests/test_date_summary.py index 052cea4f83..a02443ddb7 100644 --- a/lms/djangoapps/courseware/tests/test_date_summary.py +++ b/lms/djangoapps/courseware/tests/test_date_summary.py @@ -12,7 +12,7 @@ from mock import patch from nose.plugins.attrib import attr from pytz import utc -from commerce.models import CommerceConfiguration +from lms.djangoapps.commerce.models import CommerceConfiguration from course_modes.models import CourseMode from course_modes.tests.factories import CourseModeFactory from courseware.courses import get_course_date_blocks diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 0056b6cfc5..0ed7673d06 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -35,7 +35,7 @@ from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory from certificates import api as certs_api from certificates.models import CertificateGenerationConfiguration, CertificateStatuses from certificates.tests.factories import CertificateInvalidationFactory, GeneratedCertificateFactory -from commerce.models import CommerceConfiguration +from lms.djangoapps.commerce.models import CommerceConfiguration from course_modes.models import CourseMode from course_modes.tests.factories import CourseModeFactory from courseware.access_utils import check_course_open_for_learner diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 1c1ee58e75..32b704e6e0 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -12,7 +12,7 @@ import shoppingcart import survey.views from certificates import api as certs_api from certificates.models import CertificateStatuses -from commerce.utils import EcommerceService +from lms.djangoapps.commerce.utils import EcommerceService from course_modes.models import (CourseMode, get_course_prices) from courseware.access import has_access, has_ccx_coach_role from courseware.access_utils import check_course_open_for_learner diff --git a/lms/djangoapps/instructor/services.py b/lms/djangoapps/instructor/services.py index 5e7e4fadf6..91543d658e 100644 --- a/lms/djangoapps/instructor/services.py +++ b/lms/djangoapps/instructor/services.py @@ -10,7 +10,7 @@ from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey, UsageKey import lms.djangoapps.instructor.enrollment as enrollment -from commerce.signals import create_zendesk_ticket +from lms.djangoapps.commerce.signals import create_zendesk_ticket from courseware.models import StudentModule from lms.djangoapps.instructor.views.tools import get_student_from_identifier from student import auth diff --git a/lms/djangoapps/learner_dashboard/views.py b/lms/djangoapps/learner_dashboard/views.py index cb58623f9a..34065d2d52 100644 --- a/lms/djangoapps/learner_dashboard/views.py +++ b/lms/djangoapps/learner_dashboard/views.py @@ -5,7 +5,7 @@ from django.http import Http404 from django.views.decorators.http import require_GET from edxmako.shortcuts import render_to_response -from commerce.utils import EcommerceService +from lms.djangoapps.commerce.utils import EcommerceService from lms.djangoapps.learner_dashboard.programs import ProgramsFragmentView from lms.djangoapps.learner_dashboard.utils import FAKE_COURSE_KEY, strip_course_id diff --git a/lms/djangoapps/student_account/test/test_views.py b/lms/djangoapps/student_account/test/test_views.py index 767ec1242b..a98aa2e37f 100644 --- a/lms/djangoapps/student_account/test/test_views.py +++ b/lms/djangoapps/student_account/test/test_views.py @@ -27,9 +27,9 @@ from provider.oauth2.models import AccessToken as dop_access_token from provider.oauth2.models import RefreshToken as dop_refresh_token from testfixtures import LogCapture -from commerce.models import CommerceConfiguration -from commerce.tests import factories -from commerce.tests.mocks import mock_get_orders +from lms.djangoapps.commerce.models import CommerceConfiguration +from lms.djangoapps.commerce.tests import factories +from lms.djangoapps.commerce.tests.mocks import mock_get_orders from course_modes.models import CourseMode from http.cookies import SimpleCookie from openedx.core.djangoapps.oauth_dispatch.tests import factories as dot_factories diff --git a/lms/djangoapps/student_account/views.py b/lms/djangoapps/student_account/views.py index e454cc12df..a3eaa8d91e 100644 --- a/lms/djangoapps/student_account/views.py +++ b/lms/djangoapps/student_account/views.py @@ -18,7 +18,7 @@ from django.views.decorators.http import require_http_methods from django_countries import countries import third_party_auth -from commerce.models import CommerceConfiguration +from lms.djangoapps.commerce.models import CommerceConfiguration from edxmako.shortcuts import render_to_response from lms.djangoapps.commerce.utils import EcommerceService from openedx.core.djangoapps.commerce.utils import ecommerce_api_client diff --git a/lms/djangoapps/verify_student/tests/test_views.py b/lms/djangoapps/verify_student/tests/test_views.py index 3ff2b7b458..c06a05b1e7 100644 --- a/lms/djangoapps/verify_student/tests/test_views.py +++ b/lms/djangoapps/verify_student/tests/test_views.py @@ -28,14 +28,14 @@ from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.locator import CourseLocator from waffle.testutils import override_switch -from commerce.models import CommerceConfiguration -from commerce.tests import TEST_API_URL, TEST_PAYMENT_DATA, TEST_PUBLIC_URL_ROOT +from lms.djangoapps.commerce.models import CommerceConfiguration +from lms.djangoapps.commerce.tests import TEST_API_URL, TEST_PAYMENT_DATA, TEST_PUBLIC_URL_ROOT from common.test.utils import XssTestMixin from course_modes.models import CourseMode from course_modes.tests.factories import CourseModeFactory from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification, VerificationDeadline from lms.djangoapps.verify_student.views import PayAndVerifyView, checkout_with_ecommerce_service, render_to_response -from commerce.utils import EcommerceService +from lms.djangoapps.commerce.utils import EcommerceService from openedx.core.djangoapps.embargo.test_utils import restrict_course from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme from openedx.core.djangoapps.user_api.accounts.api import get_account_settings diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py index 5c305873b1..fe04488839 100644 --- a/lms/djangoapps/verify_student/views.py +++ b/lms/djangoapps/verify_student/views.py @@ -30,7 +30,7 @@ from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey from pytz import UTC -from commerce.utils import EcommerceService, is_account_activation_requirement_disabled +from lms.djangoapps.commerce.utils import EcommerceService, is_account_activation_requirement_disabled from course_modes.models import CourseMode from edxmako.shortcuts import render_to_response, render_to_string from eventtracking import tracker diff --git a/lms/envs/common.py b/lms/envs/common.py index a0eadeeb9d..5aa8f214b8 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -2243,7 +2243,7 @@ INSTALLED_APPS = [ 'corsheaders', 'openedx.core.djangoapps.cors_csrf', - 'commerce', + 'lms.djangoapps.commerce.apps.CommerceConfig', # Credit courses 'openedx.core.djangoapps.credit.apps.CreditConfig', diff --git a/lms/urls.py b/lms/urls.py index e501ef68a3..55c262eb77 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -847,7 +847,7 @@ if configuration_helpers.get_value('ENABLE_BULK_ENROLLMENT_VIEW', settings.FEATU # Shopping cart urlpatterns += [ url(r'^shoppingcart/', include('shoppingcart.urls')), - url(r'^commerce/', include('commerce.urls', namespace='commerce')), + url(r'^commerce/', include('lms.djangoapps.commerce.urls', namespace='commerce')), ] # Course goals diff --git a/openedx/core/djangoapps/schedules/management/commands/tests/send_email_base.py b/openedx/core/djangoapps/schedules/management/commands/tests/send_email_base.py index b98f65c7d6..5ec45fb11e 100644 --- a/openedx/core/djangoapps/schedules/management/commands/tests/send_email_base.py +++ b/openedx/core/djangoapps/schedules/management/commands/tests/send_email_base.py @@ -10,7 +10,7 @@ from freezegun import freeze_time from mock import Mock, patch import pytz -from commerce.models import CommerceConfiguration +from lms.djangoapps.commerce.models import CommerceConfiguration from course_modes.models import CourseMode from course_modes.tests.factories import CourseModeFactory from courseware.models import DynamicUpgradeDeadlineConfiguration diff --git a/openedx/features/course_experience/tests/views/test_course_home.py b/openedx/features/course_experience/tests/views/test_course_home.py index 87c62e1c86..60da457f7a 100644 --- a/openedx/features/course_experience/tests/views/test_course_home.py +++ b/openedx/features/course_experience/tests/views/test_course_home.py @@ -14,8 +14,8 @@ from pytz import UTC from waffle.models import Flag from waffle.testutils import override_flag -from commerce.models import CommerceConfiguration -from commerce.utils import EcommerceService +from lms.djangoapps.commerce.models import CommerceConfiguration +from lms.djangoapps.commerce.utils import EcommerceService from lms.djangoapps.course_goals.api import add_course_goal, remove_course_goal from course_modes.models import CourseMode from courseware.tests.factories import StaffFactory diff --git a/openedx/features/course_experience/tests/views/test_course_sock.py b/openedx/features/course_experience/tests/views/test_course_sock.py index cc31250d45..4d8b3c0bdc 100644 --- a/openedx/features/course_experience/tests/views/test_course_sock.py +++ b/openedx/features/course_experience/tests/views/test_course_sock.py @@ -4,7 +4,7 @@ Tests for course verification sock import ddt -from commerce.models import CommerceConfiguration +from lms.djangoapps.commerce.models import CommerceConfiguration from course_modes.models import CourseMode from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag from openedx.features.course_experience import DISPLAY_COURSE_SOCK_FLAG diff --git a/openedx/features/course_experience/views/course_home.py b/openedx/features/course_experience/views/course_home.py index dff93ed7f4..287863aa7e 100644 --- a/openedx/features/course_experience/views/course_home.py +++ b/openedx/features/course_experience/views/course_home.py @@ -9,7 +9,7 @@ from django.utils.decorators import method_decorator from django.views.decorators.cache import cache_control from django.views.decorators.csrf import ensure_csrf_cookie -from commerce.utils import EcommerceService +from lms.djangoapps.commerce.utils import EcommerceService from course_modes.models import get_cosmetic_verified_display_price from courseware.access import has_access from courseware.courses import ( From 80d70f6ecb80e7b8b9a8ba7394da826213476900 Mon Sep 17 00:00:00 2001 From: John Eskew Date: Wed, 8 Nov 2017 16:31:22 -0500 Subject: [PATCH 2/2] Run all touched files through isort. --- .../djangoapps/student/tests/test_refunds.py | 4 +- common/djangoapps/student/tests/test_views.py | 10 ++-- .../commerce/api/v0/tests/test_views.py | 10 ++-- lms/djangoapps/commerce/api/v0/views.py | 5 +- lms/djangoapps/commerce/api/v1/permissions.py | 3 +- lms/djangoapps/commerce/api/v1/serializers.py | 3 +- .../commerce/api/v1/tests/test_models.py | 1 + .../commerce/api/v1/tests/test_views.py | 5 +- lms/djangoapps/commerce/api/v1/views.py | 9 +-- lms/djangoapps/commerce/signals.py | 3 +- lms/djangoapps/commerce/tests/test_signals.py | 13 ++-- lms/djangoapps/commerce/tests/test_utils.py | 5 +- lms/djangoapps/commerce/utils.py | 3 +- lms/djangoapps/commerce/views.py | 3 +- .../courseware/tests/test_date_summary.py | 10 ++-- lms/djangoapps/courseware/tests/test_views.py | 2 +- lms/djangoapps/courseware/views/views.py | 59 ++++++++++--------- lms/djangoapps/instructor/services.py | 2 +- .../student_account/test/test_views.py | 4 +- lms/djangoapps/student_account/views.py | 2 +- .../verify_student/tests/test_views.py | 6 +- lms/djangoapps/verify_student/views.py | 4 +- .../commands/tests/send_email_base.py | 23 ++++---- .../tests/views/test_course_home.py | 9 +-- .../tests/views/test_course_sock.py | 4 +- .../course_experience/views/course_home.py | 19 +++--- 26 files changed, 115 insertions(+), 106 deletions(-) diff --git a/common/djangoapps/student/tests/test_refunds.py b/common/djangoapps/student/tests/test_refunds.py index 79f31e3b95..ae521f3fb4 100644 --- a/common/djangoapps/student/tests/test_refunds.py +++ b/common/djangoapps/student/tests/test_refunds.py @@ -18,11 +18,11 @@ from edx_rest_api_client.exceptions import SlumberBaseException from mock import patch from slumber.exceptions import HttpClientError, HttpServerError +from certificates.models import CertificateStatuses, GeneratedCertificate # pylint: disable=import-error +from certificates.tests.factories import GeneratedCertificateFactory # pylint: disable=import-error # These imports refer to lms djangoapps. # Their testcases are only run under lms. from course_modes.tests.factories import CourseModeFactory -from certificates.models import CertificateStatuses, GeneratedCertificate # pylint: disable=import-error -from certificates.tests.factories import GeneratedCertificateFactory # pylint: disable=import-error from openedx.core.djangoapps.commerce.utils import ECOMMERCE_DATE_FORMAT from student.models import CourseEnrollment, CourseEnrollmentAttribute from student.tests.factories import UserFactory diff --git a/common/djangoapps/student/tests/test_views.py b/common/djangoapps/student/tests/test_views.py index c4d70d6425..e74e58fa97 100644 --- a/common/djangoapps/student/tests/test_views.py +++ b/common/djangoapps/student/tests/test_views.py @@ -14,17 +14,17 @@ from django.core.urlresolvers import reverse from django.test import RequestFactory, TestCase from edx_oauth2_provider.constants import AUTHORIZED_CLIENTS_SESSION_KEY from edx_oauth2_provider.tests.factories import ClientFactory, TrustedClientFactory -from mock import patch -from pyquery import PyQuery as pq -from opaque_keys import InvalidKeyError - from milestones.tests.utils import MilestonesTestCaseMixin +from mock import patch +from opaque_keys import InvalidKeyError +from pyquery import PyQuery as pq + from student.cookies import get_user_info_cookie_data from student.helpers import DISABLE_UNENROLL_CERT_STATES from student.models import CourseEnrollment, UserProfile from student.signals import REFUND_ORDER from student.tests.factories import CourseEnrollmentFactory, UserFactory -from util.milestones_helpers import set_prerequisite_courses, remove_prerequisite_course, get_course_milestones +from util.milestones_helpers import get_course_milestones, remove_prerequisite_course, set_prerequisite_courses from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory diff --git a/lms/djangoapps/commerce/api/v0/tests/test_views.py b/lms/djangoapps/commerce/api/v0/tests/test_views.py index 52aa0e3d5f..558db9b500 100644 --- a/lms/djangoapps/commerce/api/v0/tests/test_views.py +++ b/lms/djangoapps/commerce/api/v0/tests/test_views.py @@ -17,19 +17,19 @@ from nose.plugins.attrib import attr from course_modes.models import CourseMode from course_modes.tests.factories import CourseModeFactory from enrollment.api import get_enrollment -from ..views import SAILTHRU_CAMPAIGN_COOKIE -from ....constants import Messages -from ....tests.mocks import mock_basket_order -from ....tests.test_views import UserMixin from openedx.core.djangoapps.embargo.test_utils import restrict_course from openedx.core.lib.django_test_client_utils import get_absolute_url from student.models import CourseEnrollment -from course_modes.tests.factories import CourseModeFactory from student.tests.tests import EnrollmentEventTestMixin from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory +from ....constants import Messages +from ....tests.mocks import mock_basket_order +from ....tests.test_views import UserMixin +from ..views import SAILTHRU_CAMPAIGN_COOKIE + UTM_COOKIE_NAME = 'edx.test.utm' UTM_COOKIE_CONTENTS = { 'utm_source': 'test-source' diff --git a/lms/djangoapps/commerce/api/v0/views.py b/lms/djangoapps/commerce/api/v0/views.py index ee91ac2cf5..1d2db22b2f 100644 --- a/lms/djangoapps/commerce/api/v0/views.py +++ b/lms/djangoapps/commerce/api/v0/views.py @@ -13,8 +13,6 @@ from course_modes.models import CourseMode from courseware import courses from enrollment.api import add_enrollment from enrollment.views import EnrollmentCrossDomainSessionAuth -from ...constants import Messages -from ...http import DetailResponse from openedx.core.djangoapps.commerce.utils import ecommerce_api_client from openedx.core.djangoapps.embargo import api as embargo_api from openedx.core.djangoapps.user_api.preferences.api import update_email_opt_in @@ -22,6 +20,9 @@ from openedx.core.lib.api.authentication import OAuth2AuthenticationAllowInactiv from student.models import CourseEnrollment from util.json_request import JsonResponse +from ...constants import Messages +from ...http import DetailResponse + log = logging.getLogger(__name__) SAILTHRU_CAMPAIGN_COOKIE = 'sailthru_bid' diff --git a/lms/djangoapps/commerce/api/v1/permissions.py b/lms/djangoapps/commerce/api/v1/permissions.py index 81298bbd8e..5ff2b9842d 100644 --- a/lms/djangoapps/commerce/api/v1/permissions.py +++ b/lms/djangoapps/commerce/api/v1/permissions.py @@ -3,10 +3,11 @@ from django.conf import settings from django.contrib.auth.models import User from rest_framework.permissions import BasePermission, DjangoModelPermissions -from ...utils import is_account_activation_requirement_disabled from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.lib.api.permissions import ApiKeyHeaderPermission +from ...utils import is_account_activation_requirement_disabled + class ApiKeyOrModelPermission(BasePermission): """ Access granted for requests with API key in header, diff --git a/lms/djangoapps/commerce/api/v1/serializers.py b/lms/djangoapps/commerce/api/v1/serializers.py index 6825b5a9b8..b0b526371e 100644 --- a/lms/djangoapps/commerce/api/v1/serializers.py +++ b/lms/djangoapps/commerce/api/v1/serializers.py @@ -8,9 +8,10 @@ from opaque_keys.edx.keys import CourseKey from rest_framework import serializers from course_modes.models import CourseMode -from .models import Course from xmodule.modulestore.django import modulestore +from .models import Course + class CourseModeSerializer(serializers.ModelSerializer): """ CourseMode serializer. """ diff --git a/lms/djangoapps/commerce/api/v1/tests/test_models.py b/lms/djangoapps/commerce/api/v1/tests/test_models.py index 575c773774..982c0ea481 100644 --- a/lms/djangoapps/commerce/api/v1/tests/test_models.py +++ b/lms/djangoapps/commerce/api/v1/tests/test_models.py @@ -3,6 +3,7 @@ import ddt from django.test import TestCase from course_modes.models import CourseMode + from ..models import Course diff --git a/lms/djangoapps/commerce/api/v1/tests/test_views.py b/lms/djangoapps/commerce/api/v1/tests/test_views.py index 1bc4e3e710..f8a32ce962 100644 --- a/lms/djangoapps/commerce/api/v1/tests/test_views.py +++ b/lms/djangoapps/commerce/api/v1/tests/test_views.py @@ -15,13 +15,14 @@ from nose.plugins.attrib import attr from rest_framework.utils.encoders import JSONEncoder from course_modes.models import CourseMode -from ....tests.mocks import mock_order_endpoint -from ....tests.test_views import UserMixin from lms.djangoapps.verify_student.models import VerificationDeadline from student.tests.factories import UserFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory +from ....tests.mocks import mock_order_endpoint +from ....tests.test_views import UserMixin + PASSWORD = 'test' JSON_CONTENT_TYPE = 'application/json' diff --git a/lms/djangoapps/commerce/api/v1/views.py b/lms/djangoapps/commerce/api/v1/views.py index 39fae0b275..5a0ee6d9a2 100644 --- a/lms/djangoapps/commerce/api/v1/views.py +++ b/lms/djangoapps/commerce/api/v1/views.py @@ -11,14 +11,15 @@ from rest_framework.views import APIView from rest_framework_oauth.authentication import OAuth2Authentication from course_modes.models import CourseMode -from .models import Course -from .permissions import ApiKeyOrModelPermission, IsAuthenticatedOrActivationOverridden -from .serializers import CourseSerializer -from ...utils import is_account_activation_requirement_disabled from openedx.core.djangoapps.commerce.utils import ecommerce_api_client from openedx.core.lib.api.mixins import PutAsCreateMixin from util.json_request import JsonResponse +from ...utils import is_account_activation_requirement_disabled +from .models import Course +from .permissions import ApiKeyOrModelPermission, IsAuthenticatedOrActivationOverridden +from .serializers import CourseSerializer + log = logging.getLogger(__name__) diff --git a/lms/djangoapps/commerce/signals.py b/lms/djangoapps/commerce/signals.py index 46af858f23..01b4e9146d 100644 --- a/lms/djangoapps/commerce/signals.py +++ b/lms/djangoapps/commerce/signals.py @@ -14,13 +14,14 @@ from django.contrib.auth.models import AnonymousUser from django.dispatch import receiver from django.utils.translation import ugettext as _ -from .models import CommerceConfiguration from openedx.core.djangoapps.commerce.utils import ecommerce_api_client, is_commerce_service_configured from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.theming import helpers as theming_helpers from request_cache.middleware import RequestCache from student.signals import REFUND_ORDER +from .models import CommerceConfiguration + log = logging.getLogger(__name__) diff --git a/lms/djangoapps/commerce/tests/test_signals.py b/lms/djangoapps/commerce/tests/test_signals.py index fb953edc82..55b1d15d53 100644 --- a/lms/djangoapps/commerce/tests/test_signals.py +++ b/lms/djangoapps/commerce/tests/test_signals.py @@ -19,17 +19,14 @@ from opaque_keys.edx.keys import CourseKey from requests import Timeout from course_modes.models import CourseMode -from ..models import CommerceConfiguration -from ..signals import ( - create_zendesk_ticket, - generate_refund_notification_body, - send_refund_notification -) -from . import JSON -from .mocks import mock_create_refund, mock_process_refund from student.signals import REFUND_ORDER from student.tests.factories import CourseEnrollmentFactory, UserFactory +from . import JSON +from ..models import CommerceConfiguration +from ..signals import create_zendesk_ticket, generate_refund_notification_body, send_refund_notification +from .mocks import mock_create_refund, mock_process_refund + ZENDESK_URL = 'http://zendesk.example.com/' ZENDESK_USER = 'test@example.com' ZENDESK_API_KEY = 'abc123' diff --git a/lms/djangoapps/commerce/tests/test_utils.py b/lms/djangoapps/commerce/tests/test_utils.py index c72fbe804a..fc2c08297b 100644 --- a/lms/djangoapps/commerce/tests/test_utils.py +++ b/lms/djangoapps/commerce/tests/test_utils.py @@ -9,11 +9,12 @@ from django.test.utils import override_settings from mock import patch from waffle.testutils import override_switch -from ..models import CommerceConfiguration -from ..utils import EcommerceService from openedx.core.lib.log_utils import audit_log from student.tests.factories import UserFactory +from ..models import CommerceConfiguration +from ..utils import EcommerceService + def update_commerce_config(enabled=False, checkout_page='/test_basket/'): """ Enable / Disable CommerceConfiguration model """ diff --git a/lms/djangoapps/commerce/utils.py b/lms/djangoapps/commerce/utils.py index 6a3419b626..30eb070fd5 100644 --- a/lms/djangoapps/commerce/utils.py +++ b/lms/djangoapps/commerce/utils.py @@ -5,10 +5,11 @@ from urlparse import urljoin import waffle from django.conf import settings from django.core.urlresolvers import reverse + +from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from student.models import CourseEnrollment from .models import CommerceConfiguration -from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers def is_account_activation_requirement_disabled(): diff --git a/lms/djangoapps/commerce/views.py b/lms/djangoapps/commerce/views.py index fd82a05fdd..a9047e6083 100644 --- a/lms/djangoapps/commerce/views.py +++ b/lms/djangoapps/commerce/views.py @@ -12,7 +12,6 @@ from opaque_keys.edx.locator import CourseLocator from course_modes.models import CourseMode from edxmako.shortcuts import render_to_response -from .models import CommerceConfiguration from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.theming.helpers import is_request_in_themed_site @@ -20,6 +19,8 @@ from shoppingcart.processors.CyberSource2 import is_user_payment_error from student.models import CourseEnrollment from util.json_request import JsonResponse +from .models import CommerceConfiguration + log = logging.getLogger(__name__) diff --git a/lms/djangoapps/courseware/tests/test_date_summary.py b/lms/djangoapps/courseware/tests/test_date_summary.py index a02443ddb7..ce6f575dd8 100644 --- a/lms/djangoapps/courseware/tests/test_date_summary.py +++ b/lms/djangoapps/courseware/tests/test_date_summary.py @@ -12,23 +12,23 @@ from mock import patch from nose.plugins.attrib import attr from pytz import utc -from lms.djangoapps.commerce.models import CommerceConfiguration from course_modes.models import CourseMode from course_modes.tests.factories import CourseModeFactory from courseware.courses import get_course_date_blocks from courseware.date_summary import ( + CertificateAvailableDate, CourseEndDate, CourseStartDate, TodaysDate, VerificationDeadlineDate, - VerifiedUpgradeDeadlineDate, - CertificateAvailableDate + VerifiedUpgradeDeadlineDate ) from courseware.models import ( CourseDynamicUpgradeDeadlineConfiguration, DynamicUpgradeDeadlineConfiguration, OrgDynamicUpgradeDeadlineConfiguration ) +from lms.djangoapps.commerce.models import CommerceConfiguration from lms.djangoapps.verify_student.models import VerificationDeadline from lms.djangoapps.verify_student.tests.factories import SoftwareSecurePhotoVerificationFactory from openedx.core.djangoapps.content.course_overviews.models import CourseOverview @@ -38,8 +38,8 @@ from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory from openedx.core.djangoapps.user_api.preferences.api import set_user_preference from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag -from openedx.features.course_experience import CourseHomeMessages, UNIFIED_COURSE_TAB_FLAG, UPGRADE_DEADLINE_MESSAGE -from student.tests.factories import CourseEnrollmentFactory, UserFactory, TEST_PASSWORD +from openedx.features.course_experience import UNIFIED_COURSE_TAB_FLAG, UPGRADE_DEADLINE_MESSAGE, CourseHomeMessages +from student.tests.factories import TEST_PASSWORD, CourseEnrollmentFactory, UserFactory from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 0ed7673d06..eca079f730 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -35,7 +35,6 @@ from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory from certificates import api as certs_api from certificates.models import CertificateGenerationConfiguration, CertificateStatuses from certificates.tests.factories import CertificateInvalidationFactory, GeneratedCertificateFactory -from lms.djangoapps.commerce.models import CommerceConfiguration from course_modes.models import CourseMode from course_modes.tests.factories import CourseModeFactory from courseware.access_utils import check_course_open_for_learner @@ -45,6 +44,7 @@ from courseware.tests.factories import GlobalStaffFactory, StudentModuleFactory from courseware.testutils import RenderXBlockTestMixin from courseware.url_helpers import get_redirect_url from courseware.user_state_client import DjangoXBlockUserStateClient +from lms.djangoapps.commerce.models import CommerceConfiguration from lms.djangoapps.commerce.utils import EcommerceService # pylint: disable=import-error from lms.djangoapps.grades.config.waffle import waffle as grades_waffle from lms.djangoapps.grades.config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 32b704e6e0..92587bf02d 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -8,12 +8,38 @@ from collections import OrderedDict, namedtuple from datetime import datetime import analytics +from django.conf import settings +from django.contrib.auth.decorators import login_required +from django.contrib.auth.models import AnonymousUser, User +from django.core.exceptions import PermissionDenied +from django.core.urlresolvers import reverse +from django.db import transaction +from django.db.models import Q +from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, QueryDict +from django.shortcuts import redirect +from django.template.context_processors import csrf +from django.utils.decorators import method_decorator +from django.utils.http import urlquote_plus +from django.utils.text import slugify +from django.utils.translation import ugettext as _ +from django.views.decorators.cache import cache_control +from django.views.decorators.csrf import ensure_csrf_cookie +from django.views.decorators.http import require_GET, require_http_methods, require_POST +from django.views.generic import View +from eventtracking import tracker +from ipware.ip import get_ip +from markupsafe import escape +from opaque_keys import InvalidKeyError +from opaque_keys.edx.keys import CourseKey, UsageKey +from pytz import UTC +from rest_framework import status +from web_fragments.fragment import Fragment + import shoppingcart import survey.views from certificates import api as certs_api from certificates.models import CertificateStatuses -from lms.djangoapps.commerce.utils import EcommerceService -from course_modes.models import (CourseMode, get_course_prices) +from course_modes.models import CourseMode, get_course_prices from courseware.access import has_access, has_ccx_coach_role from courseware.access_utils import check_course_open_for_learner from courseware.courses import ( @@ -34,47 +60,24 @@ from courseware.model_data import FieldDataCache from courseware.models import BaseStudentModuleHistory, StudentModule from courseware.url_helpers import get_redirect_url from courseware.user_state_client import DjangoXBlockUserStateClient -from django.conf import settings -from django.contrib.auth.decorators import login_required -from django.contrib.auth.models import AnonymousUser, User -from django.template.context_processors import csrf -from django.core.exceptions import PermissionDenied -from django.core.urlresolvers import reverse -from django.db import transaction -from django.db.models import Q -from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, QueryDict -from django.shortcuts import redirect -from django.utils.decorators import method_decorator -from django.utils.http import urlquote_plus -from django.utils.text import slugify -from pytz import UTC -from django.utils.translation import ugettext as _ -from django.views.decorators.cache import cache_control -from django.views.decorators.csrf import ensure_csrf_cookie -from django.views.decorators.http import require_GET, require_http_methods, require_POST -from django.views.generic import View from edxmako.shortcuts import marketing_link, render_to_response, render_to_string from enrollment.api import add_enrollment -from eventtracking import tracker -from ipware.ip import get_ip from lms.djangoapps.ccx.custom_exception import CCXLocatorValidationException +from lms.djangoapps.commerce.utils import EcommerceService from lms.djangoapps.courseware.exceptions import CourseAccessRedirect, Redirect from lms.djangoapps.experiments.utils import get_experiment_user_metadata_context from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory from lms.djangoapps.instructor.enrollment import uses_shib from lms.djangoapps.instructor.views.api import require_global_staff from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification -from markupsafe import escape -from opaque_keys import InvalidKeyError -from opaque_keys.edx.keys import CourseKey, UsageKey from openedx.core.djangoapps.catalog.utils import get_programs, get_programs_with_type +from openedx.core.djangoapps.certificates import api as auto_certs_api from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.credit.api import ( get_credit_requirement_status, is_credit_course, is_user_eligible_for_credit ) -from openedx.core.djangoapps.certificates import api as auto_certs_api from openedx.core.djangoapps.models.course_details import CourseDetails from openedx.core.djangoapps.monitoring_utils import set_custom_metrics_for_course_key from openedx.core.djangoapps.plugin_api.views import EdxFragmentView @@ -87,14 +90,12 @@ from openedx.features.course_experience import UNIFIED_COURSE_TAB_FLAG, course_h from openedx.features.course_experience.course_tools import CourseToolsPluginManager from openedx.features.course_experience.views.course_dates import CourseDatesFragmentView from openedx.features.enterprise_support.api import data_sharing_consent_required -from rest_framework import status from shoppingcart.utils import is_shopping_cart_enabled from student.models import CourseEnrollment, UserTestGroup from util.cache import cache, cache_if_anonymous from util.db import outer_atomic from util.milestones_helpers import get_prerequisite_courses_display from util.views import _record_feedback_in_zendesk, ensure_valid_course_key, ensure_valid_usage_key -from web_fragments.fragment import Fragment from xmodule.modulestore.django import modulestore from xmodule.modulestore.exceptions import ItemNotFoundError, NoPathToItem from xmodule.tabs import CourseTabList diff --git a/lms/djangoapps/instructor/services.py b/lms/djangoapps/instructor/services.py index 91543d658e..55442edf11 100644 --- a/lms/djangoapps/instructor/services.py +++ b/lms/djangoapps/instructor/services.py @@ -10,8 +10,8 @@ from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey, UsageKey import lms.djangoapps.instructor.enrollment as enrollment -from lms.djangoapps.commerce.signals import create_zendesk_ticket from courseware.models import StudentModule +from lms.djangoapps.commerce.signals import create_zendesk_ticket from lms.djangoapps.instructor.views.tools import get_student_from_identifier from student import auth from student.roles import CourseStaffRole diff --git a/lms/djangoapps/student_account/test/test_views.py b/lms/djangoapps/student_account/test/test_views.py index a98aa2e37f..c119475b5c 100644 --- a/lms/djangoapps/student_account/test/test_views.py +++ b/lms/djangoapps/student_account/test/test_views.py @@ -20,6 +20,7 @@ from django.test import TestCase from django.test.utils import override_settings from edx_oauth2_provider.tests.factories import AccessTokenFactory, ClientFactory, RefreshTokenFactory from edx_rest_api_client import exceptions +from http.cookies import SimpleCookie from nose.plugins.attrib import attr from oauth2_provider.models import AccessToken as dot_access_token from oauth2_provider.models import RefreshToken as dot_refresh_token @@ -27,11 +28,10 @@ from provider.oauth2.models import AccessToken as dop_access_token from provider.oauth2.models import RefreshToken as dop_refresh_token from testfixtures import LogCapture +from course_modes.models import CourseMode from lms.djangoapps.commerce.models import CommerceConfiguration from lms.djangoapps.commerce.tests import factories from lms.djangoapps.commerce.tests.mocks import mock_get_orders -from course_modes.models import CourseMode -from http.cookies import SimpleCookie from openedx.core.djangoapps.oauth_dispatch.tests import factories as dot_factories from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin diff --git a/lms/djangoapps/student_account/views.py b/lms/djangoapps/student_account/views.py index a3eaa8d91e..08d724e514 100644 --- a/lms/djangoapps/student_account/views.py +++ b/lms/djangoapps/student_account/views.py @@ -18,8 +18,8 @@ from django.views.decorators.http import require_http_methods from django_countries import countries import third_party_auth -from lms.djangoapps.commerce.models import CommerceConfiguration from edxmako.shortcuts import render_to_response +from lms.djangoapps.commerce.models import CommerceConfiguration from lms.djangoapps.commerce.utils import EcommerceService from openedx.core.djangoapps.commerce.utils import ecommerce_api_client from openedx.core.djangoapps.external_auth.login_and_register import login as external_auth_login diff --git a/lms/djangoapps/verify_student/tests/test_views.py b/lms/djangoapps/verify_student/tests/test_views.py index c06a05b1e7..6186a3bd87 100644 --- a/lms/djangoapps/verify_student/tests/test_views.py +++ b/lms/djangoapps/verify_student/tests/test_views.py @@ -28,14 +28,14 @@ from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.locator import CourseLocator from waffle.testutils import override_switch -from lms.djangoapps.commerce.models import CommerceConfiguration -from lms.djangoapps.commerce.tests import TEST_API_URL, TEST_PAYMENT_DATA, TEST_PUBLIC_URL_ROOT from common.test.utils import XssTestMixin from course_modes.models import CourseMode from course_modes.tests.factories import CourseModeFactory +from lms.djangoapps.commerce.models import CommerceConfiguration +from lms.djangoapps.commerce.tests import TEST_API_URL, TEST_PAYMENT_DATA, TEST_PUBLIC_URL_ROOT +from lms.djangoapps.commerce.utils import EcommerceService from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification, VerificationDeadline from lms.djangoapps.verify_student.views import PayAndVerifyView, checkout_with_ecommerce_service, render_to_response -from lms.djangoapps.commerce.utils import EcommerceService from openedx.core.djangoapps.embargo.test_utils import restrict_course from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme from openedx.core.djangoapps.user_api.accounts.api import get_account_settings diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py index fe04488839..6d3f5183c1 100644 --- a/lms/djangoapps/verify_student/views.py +++ b/lms/djangoapps/verify_student/views.py @@ -25,15 +25,15 @@ from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_POST from django.views.generic.base import View from edx_rest_api_client.exceptions import SlumberBaseException +from eventtracking import tracker from ipware.ip import get_ip from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey from pytz import UTC -from lms.djangoapps.commerce.utils import EcommerceService, is_account_activation_requirement_disabled from course_modes.models import CourseMode from edxmako.shortcuts import render_to_response, render_to_string -from eventtracking import tracker +from lms.djangoapps.commerce.utils import EcommerceService, is_account_activation_requirement_disabled from lms.djangoapps.verify_student.image import InvalidImageData, decode_image_data from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification, VerificationDeadline from lms.djangoapps.verify_student.ssencrypt import has_valid_signature diff --git a/openedx/core/djangoapps/schedules/management/commands/tests/send_email_base.py b/openedx/core/djangoapps/schedules/management/commands/tests/send_email_base.py index 5ec45fb11e..7ab9d5b405 100644 --- a/openedx/core/djangoapps/schedules/management/commands/tests/send_email_base.py +++ b/openedx/core/djangoapps/schedules/management/commands/tests/send_email_base.py @@ -1,33 +1,32 @@ -from collections import namedtuple, defaultdict -from copy import deepcopy import datetime -import ddt import logging +from collections import defaultdict, namedtuple +from copy import deepcopy import attr +import ddt +import pytz from django.conf import settings +from edx_ace.channel import ChannelType +from edx_ace.test_utils import StubPolicy, patch_channels, patch_policies +from edx_ace.utils.date import serialize from freezegun import freeze_time from mock import Mock, patch -import pytz +from opaque_keys.edx.keys import CourseKey -from lms.djangoapps.commerce.models import CommerceConfiguration from course_modes.models import CourseMode from course_modes.tests.factories import CourseModeFactory from courseware.models import DynamicUpgradeDeadlineConfiguration -from edx_ace.channel import ChannelType -from edx_ace.utils.date import serialize -from edx_ace.test_utils import StubPolicy, patch_channels, patch_policies -from opaque_keys.edx.keys import CourseKey -from openedx.core.djangoapps.site_configuration.tests.factories import SiteConfigurationFactory, SiteFactory +from lms.djangoapps.commerce.models import CommerceConfiguration from openedx.core.djangoapps.schedules import resolvers, tasks from openedx.core.djangoapps.schedules.resolvers import _get_datetime_beginning_of_day from openedx.core.djangoapps.schedules.tests.factories import ScheduleConfigFactory, ScheduleFactory +from openedx.core.djangoapps.site_configuration.tests.factories import SiteConfigurationFactory, SiteFactory from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES -from openedx.core.djangolib.testing.utils import FilteredQueryCountMixin, CacheIsolationTestCase +from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, FilteredQueryCountMixin from student.models import CourseEnrollment from student.tests.factories import UserFactory - SITE_QUERY = 1 # django_site SITE_CONFIG_QUERY = 1 # site_configuration_siteconfiguration diff --git a/openedx/features/course_experience/tests/views/test_course_home.py b/openedx/features/course_experience/tests/views/test_course_home.py index 60da457f7a..e1cc09caff 100644 --- a/openedx/features/course_experience/tests/views/test_course_home.py +++ b/openedx/features/course_experience/tests/views/test_course_home.py @@ -14,11 +14,11 @@ from pytz import UTC from waffle.models import Flag from waffle.testutils import override_flag +from course_modes.models import CourseMode +from courseware.tests.factories import StaffFactory from lms.djangoapps.commerce.models import CommerceConfiguration from lms.djangoapps.commerce.utils import EcommerceService from lms.djangoapps.course_goals.api import add_course_goal, remove_course_goal -from course_modes.models import CourseMode -from courseware.tests.factories import StaffFactory from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES, override_waffle_flag from openedx.features.course_experience import ( SHOW_REVIEWS_TOOL_FLAG, @@ -26,14 +26,15 @@ from openedx.features.course_experience import ( UNIFIED_COURSE_TAB_FLAG ) from student.models import CourseEnrollment -from student.tests.factories import UserFactory, CourseEnrollmentFactory +from student.tests.factories import CourseEnrollmentFactory, UserFactory from util.date_utils import strftime_localized from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.tests.django_utils import CourseUserType, ModuleStoreTestCase, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls + +from ... import COURSE_PRE_START_ACCESS_FLAG, ENABLE_COURSE_GOALS from .helpers import add_course_mode from .test_course_updates import create_course_update, remove_course_updates -from ... import COURSE_PRE_START_ACCESS_FLAG, ENABLE_COURSE_GOALS TEST_PASSWORD = 'test' TEST_CHAPTER_NAME = 'Test Chapter' diff --git a/openedx/features/course_experience/tests/views/test_course_sock.py b/openedx/features/course_experience/tests/views/test_course_sock.py index 4d8b3c0bdc..a2992cf638 100644 --- a/openedx/features/course_experience/tests/views/test_course_sock.py +++ b/openedx/features/course_experience/tests/views/test_course_sock.py @@ -4,11 +4,11 @@ Tests for course verification sock import ddt -from lms.djangoapps.commerce.models import CommerceConfiguration from course_modes.models import CourseMode +from lms.djangoapps.commerce.models import CommerceConfiguration from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag from openedx.features.course_experience import DISPLAY_COURSE_SOCK_FLAG -from student.tests.factories import UserFactory, CourseEnrollmentFactory +from student.tests.factories import CourseEnrollmentFactory, UserFactory from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory diff --git a/openedx/features/course_experience/views/course_home.py b/openedx/features/course_experience/views/course_home.py index 287863aa7e..b7c9232706 100644 --- a/openedx/features/course_experience/views/course_home.py +++ b/openedx/features/course_experience/views/course_home.py @@ -2,30 +2,31 @@ Views for the course home page. """ -from django.template.context_processors import csrf from django.core.urlresolvers import reverse +from django.template.context_processors import csrf from django.template.loader import render_to_string from django.utils.decorators import method_decorator from django.views.decorators.cache import cache_control from django.views.decorators.csrf import ensure_csrf_cookie +from opaque_keys.edx.keys import CourseKey +from web_fragments.fragment import Fragment -from lms.djangoapps.commerce.utils import EcommerceService from course_modes.models import get_cosmetic_verified_display_price from courseware.access import has_access -from courseware.courses import ( - can_self_enroll_in_course, - get_course_info_section, - get_course_with_access, +from courseware.courses import can_self_enroll_in_course, get_course_info_section, get_course_with_access +from lms.djangoapps.commerce.utils import EcommerceService +from lms.djangoapps.course_goals.api import ( + get_course_goal, + get_course_goal_options, + get_goal_api_url, + has_course_goal_permission ) -from lms.djangoapps.course_goals.api import get_course_goal, has_course_goal_permission, get_course_goal_options, get_goal_api_url from lms.djangoapps.courseware.exceptions import CourseAccessRedirect from lms.djangoapps.courseware.views.views import CourseTabView -from opaque_keys.edx.keys import CourseKey from openedx.core.djangoapps.plugin_api.views import EdxFragmentView from openedx.features.course_experience.course_tools import CourseToolsPluginManager from student.models import CourseEnrollment from util.views import ensure_valid_course_key -from web_fragments.fragment import Fragment from .. import LATEST_UPDATE_FLAG, SHOW_UPGRADE_MSG_ON_COURSE_HOME, USE_BOOTSTRAP_FLAG from ..utils import get_course_outline_block_tree